Fix selection reset on background refresh, support per-repo table column widths, fix minimap drag scrolling & colors, indent details panels
This commit is contained in:
@@ -206,10 +206,33 @@ void UserData::load()
|
||||
if (const ikv_node_t *widths = object_value(settings, "commit_table_columns", IKV_ARRAY))
|
||||
{
|
||||
const uint32_t count = std::min<uint32_t>(
|
||||
ikv_array_size(widths), static_cast<uint32_t>(commit_table_column_widths_.size()));
|
||||
ikv_array_size(widths), 4);
|
||||
for (uint32_t index = 0; index < count; ++index)
|
||||
commit_table_column_widths_[index] = static_cast<float>(ikv_as_float(ikv_array_get(widths, index)));
|
||||
}
|
||||
if (const ikv_node_t *repos = object_value(settings, "repository_settings", IKV_ARRAY))
|
||||
{
|
||||
for (uint32_t index = 0; index < ikv_array_size(repos); ++index)
|
||||
{
|
||||
const ikv_node_t *repo_entry = ikv_array_get(repos, index);
|
||||
if (ikv_node_type(repo_entry) != IKV_OBJECT)
|
||||
continue;
|
||||
const ikv_node_t *path_node = object_value(repo_entry, "path", IKV_STRING);
|
||||
const ikv_node_t *widths_node = object_value(repo_entry, "commit_table_columns", IKV_ARRAY);
|
||||
if (!path_node || !widths_node)
|
||||
continue;
|
||||
const char *path_str = ikv_as_string(path_node);
|
||||
if (path_str && *path_str)
|
||||
{
|
||||
std::string normalized_path = normalizePath(path_str);
|
||||
std::array<float, 4> &arr = repo_column_widths_[normalized_path];
|
||||
arr = commit_table_column_widths_;
|
||||
const uint32_t count = std::min<uint32_t>(ikv_array_size(widths_node), 4);
|
||||
for (uint32_t c = 0; c < count; ++c)
|
||||
arr[c] = static_cast<float>(ikv_as_float(ikv_array_get(widths_node, c)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (const ikv_node_t *history = object_value(root, "recently_closed", IKV_ARRAY))
|
||||
{
|
||||
@@ -279,6 +302,11 @@ void UserData::load()
|
||||
height = std::clamp(height, 42.0f, 500.0f);
|
||||
for (float &width : commit_table_column_widths_)
|
||||
width = std::clamp(width, 0.0f, 1200.0f);
|
||||
for (auto &[repo, widths_arr] : repo_column_widths_)
|
||||
{
|
||||
for (float &width : widths_arr)
|
||||
width = std::clamp(width, 0.0f, 1200.0f);
|
||||
}
|
||||
if (open_repositories_.empty())
|
||||
active_repository_ = 0;
|
||||
else
|
||||
@@ -570,6 +598,16 @@ void UserData::save() const
|
||||
for (const float width : commit_table_column_widths_)
|
||||
ikv_array_add_float(widths, width);
|
||||
|
||||
ikv_node_t *repos = ikv_object_add_array(settings, "repository_settings", IKV_OBJECT);
|
||||
for (const auto &[repo_path, col_widths] : repo_column_widths_)
|
||||
{
|
||||
ikv_node_t *repo_entry = ikv_array_add_object(repos);
|
||||
ikv_object_set_string(repo_entry, "path", repo_path.c_str());
|
||||
ikv_node_t *repo_widths = ikv_object_add_array(repo_entry, "commit_table_columns", IKV_FLOAT);
|
||||
for (const float w : col_widths)
|
||||
ikv_array_add_float(repo_widths, w);
|
||||
}
|
||||
|
||||
ikv_node_t *history = ikv_object_add_array(root, "recently_closed", IKV_STRING);
|
||||
for (const auto &path : recently_closed_)
|
||||
ikv_array_add_string(history, path.c_str());
|
||||
@@ -596,3 +634,32 @@ void UserData::save() const
|
||||
ikv_free(root);
|
||||
removeLegacyFiles();
|
||||
}
|
||||
|
||||
float UserData::commitTableColumnWidth(const std::string &repo_path, size_t index) const
|
||||
{
|
||||
if (index >= 4)
|
||||
return 0.0f;
|
||||
std::string normalized = normalizePath(repo_path);
|
||||
auto it = repo_column_widths_.find(normalized);
|
||||
if (it != repo_column_widths_.end())
|
||||
return it->second[index];
|
||||
return commit_table_column_widths_[index];
|
||||
}
|
||||
|
||||
void UserData::setCommitTableColumnWidth(const std::string &repo_path, size_t index, float width)
|
||||
{
|
||||
if (index >= 4)
|
||||
return;
|
||||
std::string normalized = normalizePath(repo_path);
|
||||
std::array<float, 4> &widths = repo_column_widths_[normalized];
|
||||
|
||||
// If this is a new entry, initialize with default global widths first
|
||||
auto it = repo_column_widths_.find(normalized);
|
||||
if (it->second[0] == 0.0f && it->second[1] == 0.0f && it->second[2] == 0.0f && it->second[3] == 0.0f)
|
||||
{
|
||||
widths = commit_table_column_widths_;
|
||||
}
|
||||
|
||||
widths[index] = width;
|
||||
save();
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
[[nodiscard]] float sidebarSectionHeight(size_t index) const { return sidebar_section_heights_.at(index); }
|
||||
[[nodiscard]] bool sidebarCollapsed() const { return sidebar_collapsed_; }
|
||||
[[nodiscard]] bool sidebarSectionOpen(size_t index) const { return sidebar_section_open_.at(index); }
|
||||
[[nodiscard]] float commitTableColumnWidth(size_t index) const { return commit_table_column_widths_.at(index); }
|
||||
[[nodiscard]] float commitTableColumnWidth(const std::string &repo_path, size_t index) const;
|
||||
[[nodiscard]] int pullMode() const { return pull_mode_; }
|
||||
[[nodiscard]] int zoomPercent() const { return zoom_percent_; }
|
||||
[[nodiscard]] std::optional<SavedGitCredential> remoteCredential(const std::string &remote_url) const;
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
void setSidebarSectionHeight(size_t index, float height) { sidebar_section_heights_.at(index) = height; }
|
||||
void setSidebarCollapsed(bool collapsed) { sidebar_collapsed_ = collapsed; }
|
||||
void setSidebarSectionOpen(size_t index, bool open) { sidebar_section_open_.at(index) = open; }
|
||||
void setCommitTableColumnWidth(size_t index, float width) { commit_table_column_widths_.at(index) = width; }
|
||||
void setCommitTableColumnWidth(const std::string &repo_path, size_t index, float width);
|
||||
void setPullMode(int mode)
|
||||
{
|
||||
pull_mode_ = mode;
|
||||
@@ -76,6 +76,7 @@ private:
|
||||
std::array<float, 4> sidebar_section_heights_ = {110.0f, 220.0f, 90.0f, 150.0f};
|
||||
bool sidebar_collapsed_ = false;
|
||||
std::array<bool, 4> sidebar_section_open_ = {true, true, true, true};
|
||||
std::unordered_map<std::string, std::array<float, 4>> repo_column_widths_;
|
||||
std::array<float, 4> commit_table_column_widths_ = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
int pull_mode_ = 1;
|
||||
int zoom_percent_ = 100;
|
||||
|
||||
@@ -439,7 +439,7 @@ std::vector<MinimapSegment> buildMinimapSegments(const std::string& text, Syntax
|
||||
if (std::isspace(value)) {
|
||||
size_t end = cursor + 1;
|
||||
while (end < text.size() && std::isspace(static_cast<unsigned char>(text[end]))) ++end;
|
||||
addMinimapSegment(segments, std::max(0.04f, static_cast<float>(end - cursor) * 0.18f), IM_COL32(0, 0, 0, 0));
|
||||
addMinimapSegment(segments, static_cast<float>(end - cursor) * 0.22f, IM_COL32(0, 0, 0, 0));
|
||||
cursor = end;
|
||||
continue;
|
||||
}
|
||||
@@ -588,7 +588,9 @@ void drawMinimap(const std::vector<MinimapEntry>& entries, const ImVec2& viewpor
|
||||
if ((hovered || active) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
|
||||
const float mouse_ratio = std::clamp((ImGui::GetIO().MousePos.y - minimum.y) / std::max(1.0f, content_size.y), 0.0f, 1.0f);
|
||||
const float target = std::clamp(mouse_ratio * rendered_height - clamped_visible_height * 0.5f, 0.0f, max_scroll_y);
|
||||
ImGui::BeginChild("diff_content_main");
|
||||
ImGui::SetScrollY(target);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
draw->AddRectFilled({minimum.x + scaled(1.0f, scale), viewport_y},
|
||||
{minimum.x + viewport_size.x - scaled(1.0f, scale), viewport_y + viewport_height},
|
||||
|
||||
@@ -368,8 +368,9 @@ void transfer_repository_state(RepositoryView& source, RepositoryView& target) {
|
||||
target.undo_action = std::move(source.undo_action);
|
||||
target.redo_action = std::move(source.redo_action);
|
||||
}
|
||||
|
||||
std::string selected_commit_hash(const RepositoryView& repository) {
|
||||
if (repository.selected_commit == -1)
|
||||
return "working_tree";
|
||||
if (repository.selected_commit < 0 || repository.selected_commit >= static_cast<int>(repository.commits.size()))
|
||||
return {};
|
||||
return oid_string(repository.commits[static_cast<size_t>(repository.selected_commit)].oid);
|
||||
@@ -377,6 +378,10 @@ std::string selected_commit_hash(const RepositoryView& repository) {
|
||||
|
||||
void restore_selected_commit(RepositoryView& repository, const std::string& hash) {
|
||||
if (hash.empty()) return;
|
||||
if (hash == "working_tree") {
|
||||
repository.selected_commit = -1;
|
||||
return;
|
||||
}
|
||||
git_oid target{};
|
||||
if (git_oid_fromstr(&target, hash.c_str()) != 0) return;
|
||||
for (size_t index = 0; index < repository.commits.size(); ++index) {
|
||||
@@ -1954,15 +1959,15 @@ void draw_commit_table() {
|
||||
float graph_width = default_graph_width;
|
||||
float date_width = default_date_width;
|
||||
if (g_user_data) {
|
||||
reference_width = std::clamp(ui(g_user_data->commitTableColumnWidth(0)),
|
||||
reference_width = std::clamp(ui(g_user_data->commitTableColumnWidth(repo().path, 0)),
|
||||
ui(120.0f), std::max(ui(120.0f), available_table_width * 0.45f));
|
||||
graph_width = std::clamp(ui(g_user_data->commitTableColumnWidth(1)),
|
||||
graph_width = std::clamp(ui(g_user_data->commitTableColumnWidth(repo().path, 1)),
|
||||
ui(90.0f), std::max(ui(90.0f), available_table_width * 0.35f));
|
||||
date_width = std::clamp(ui(g_user_data->commitTableColumnWidth(3)),
|
||||
date_width = std::clamp(ui(g_user_data->commitTableColumnWidth(repo().path, 3)),
|
||||
ui(130.0f), std::max(ui(130.0f), available_table_width * 0.30f));
|
||||
if (g_user_data->commitTableColumnWidth(0) <= 0.0f) reference_width = default_reference_width;
|
||||
if (g_user_data->commitTableColumnWidth(1) <= 0.0f) graph_width = default_graph_width;
|
||||
if (g_user_data->commitTableColumnWidth(3) <= 0.0f) date_width = default_date_width;
|
||||
if (g_user_data->commitTableColumnWidth(repo().path, 0) <= 0.0f) reference_width = default_reference_width;
|
||||
if (g_user_data->commitTableColumnWidth(repo().path, 1) <= 0.0f) graph_width = default_graph_width;
|
||||
if (g_user_data->commitTableColumnWidth(repo().path, 3) <= 0.0f) date_width = default_date_width;
|
||||
}
|
||||
if (reference_width + graph_width + date_width > available_table_width - ui(120.0f)) {
|
||||
const float scale = std::max(0.5f, (available_table_width - ui(120.0f)) /
|
||||
@@ -2020,7 +2025,7 @@ void draw_commit_table() {
|
||||
ImGui::TableHeadersRow();
|
||||
if (g_user_data) {
|
||||
for (int column = 0; column < 4; ++column)
|
||||
g_user_data->setCommitTableColumnWidth(static_cast<size_t>(column),
|
||||
g_user_data->setCommitTableColumnWidth(repo().path, static_cast<size_t>(column),
|
||||
ImGui::GetColumnWidth(column) / g_ui_scale);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
@@ -2033,8 +2038,9 @@ void draw_commit_table() {
|
||||
const float row_left = cursor.x - ImGui::GetStyle().CellPadding.x;
|
||||
const float row_top = cursor.y - ImGui::GetStyle().CellPadding.y;
|
||||
const float message_left = row_left + reference_width + graph_width;
|
||||
const float scrollbar_size = ImGui::GetWindowWidth() - ImGui::GetWindowContentRegionMax().x > 0.0f ? ImGui::GetStyle().ScrollbarSize : 0.0f;
|
||||
const float row_right = message_left + message_width + date_width +
|
||||
ImGui::GetStyle().CellPadding.x * 2.0f;
|
||||
ImGui::GetStyle().CellPadding.x * 2.0f - scrollbar_size;
|
||||
const ImVec2 mouse = ImGui::GetIO().MousePos;
|
||||
hovered = ImGui::IsWindowHovered() && mouse.x >= row_left && mouse.x < row_right &&
|
||||
mouse.y >= row_top && mouse.y < row_top + row_height;
|
||||
@@ -2594,6 +2600,7 @@ void draw_files(const std::vector<File>& files, bool staged_filter = false,
|
||||
}
|
||||
|
||||
void draw_working_details() {
|
||||
ImGui::Indent(ui(10.0f));
|
||||
int staged = 0;
|
||||
for (const auto& file : repo().working_files) if (file.staged) ++staged;
|
||||
const int unstaged = static_cast<int>(repo().working_files.size()) - staged;
|
||||
@@ -2804,9 +2811,11 @@ void draw_working_details() {
|
||||
ImGui::EndDisabled();
|
||||
ImGui::Unindent(ui(8.0f));
|
||||
ImGui::EndChild();
|
||||
ImGui::Unindent(ui(10.0f));
|
||||
}
|
||||
|
||||
void draw_commit_details() {
|
||||
ImGui::Indent(ui(10.0f));
|
||||
const int selected = std::clamp(repo().selected_commit, 0, static_cast<int>(repo().commits.size() - 1));
|
||||
g_git_manager->loadCommitChanges(repo(), selected, g_notice);
|
||||
auto& commit = repo().commits[selected];
|
||||
@@ -2918,6 +2927,7 @@ void draw_commit_details() {
|
||||
? commit.all_files : commit.changed_files;
|
||||
draw_files(displayed_files, false, false, oid_string(commit.oid));
|
||||
ImGui::EndChild();
|
||||
ImGui::Unindent(ui(10.0f));
|
||||
}
|
||||
|
||||
void draw_details(float width) {
|
||||
|
||||
Reference in New Issue
Block a user