From 887d5f9f8d1309134c72b1f35afc7d007a5c64aa Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Sat, 1 Nov 2025 16:29:25 +0100 Subject: refactor invoice views --- TODO | 1 + libs/imgui-1.92.1/imgui.h | 2 + src/main.cpp | 8 +++ src/ui/imgui_extensions.cpp | 7 ++- src/ui/ui_invoices.cpp | 143 ++++++++++++++++++++++---------------------- src/ui/ui_main.cpp | 2 +- src/ui/ui_settings.cpp | 3 - 7 files changed, 91 insertions(+), 75 deletions(-) diff --git a/TODO b/TODO index 8a68caa..723dbf3 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,7 @@ TODO: Fix: +- When reloading view, lock main thread as the freeing might cause a crash Refactor: - Refactor zip writing to be faster diff --git a/libs/imgui-1.92.1/imgui.h b/libs/imgui-1.92.1/imgui.h index 7a3c8cd..3b48ad8 100644 --- a/libs/imgui-1.92.1/imgui.h +++ b/libs/imgui-1.92.1/imgui.h @@ -570,6 +570,8 @@ namespace ImGui IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window-local coordinates. Call GetCursorScreenPos() after Begin() to get the absolute coordinates version. // Other layout functions + typedef int ImGuiSeparatorFlags; + IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness); IMGUI_API void Separator(float thickness = 1.0f); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. IMGUI_API void SameLine(float offset_from_start_x=0.0f, float spacing=-1.0f); // call between widgets or groups to layout them horizontally. X position given in window coordinates. IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in a horizontal-layout context. diff --git a/src/main.cpp b/src/main.cpp index 948678c..ffdeb03 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -289,6 +289,14 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) switch (msg) { + case WM_GETMINMAXINFO: + { + MINMAXINFO* minMaxInfo = (MINMAXINFO*)lParam; + minMaxInfo->ptMinTrackSize.x = 1400; // Minimum width + minMaxInfo->ptMinTrackSize.y = 900; // Minimum height + return 0; + } + case WM_SIZE: if (wParam == SIZE_MINIMIZED) return 0; diff --git a/src/ui/imgui_extensions.cpp b/src/ui/imgui_extensions.cpp index f3b9ff8..a90549f 100644 --- a/src/ui/imgui_extensions.cpp +++ b/src/ui/imgui_extensions.cpp @@ -67,6 +67,8 @@ namespace ImGui ImGui::BeginDisabled(); bool result = ImGui::Button("", CalcButtonSize(label)); + ImVec2 oldPos = ImGui::GetCursorScreenPos(); + float radius = 10.0f; ImVec2 p_min = ImGui::GetItemRectMin(); ImVec2 p_max = ImGui::GetItemRectMax(); @@ -77,9 +79,12 @@ namespace ImGui const ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); const ImVec4 bg = ImGui::GetStyleColorVec4(ImGuiCol_Button); ImGui::LoadingIndicatorCircle(radius, bg, col, 6, 4.0f); - ImGui::EndDisabled(); ImGui::PopID(); + + ImGui::SetCursorScreenPos(oldPos); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(0, 0)); return result; } diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp index ebf84d4..0e81259 100644 --- a/src/ui/ui_invoices.cpp +++ b/src/ui/ui_invoices.cpp @@ -29,6 +29,7 @@ static ui::view_state current_view_state = ui::view_state::LIST_ALL; static invoice active_invoice = {0}; static invoice selected_for_removal = {0}; +static const float sidepanel_width = 200.0f; static billing_item* invoice_items_buffer = 0; @@ -306,22 +307,35 @@ static void draw_invoices_list() ImGui::Spacing(); - if (ImGui::BeginTable("TableInvoices", 7, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (ImGui::BeginTable("TableInvoices", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { ImGui::TableSetupColumn(locale::get("invoice.table.invoicenumber"), ImGuiTableColumnFlags_WidthFixed, 130); ImGui::TableSetupColumn(locale::get("invoice.table.customer")); ImGui::TableSetupColumn(locale::get("invoice.table.addressee")); - ImGui::TableSetupColumn(locale::get("invoice.table.issuedat")); - ImGui::TableSetupColumn(locale::get("invoice.table.total")); - ImGui::TableSetupColumn(locale::get("invoice.table.status")); - ImGui::TableSetupColumn(""); - ImGui::TableHeadersRow(); + ImGui::TableSetupColumn(locale::get("invoice.table.issuedat"), ImGuiTableColumnFlags_WidthFixed, 90); + ImGui::TableSetupColumn(locale::get("invoice.table.total"), ImGuiTableColumnFlags_WidthFixed, 90); + ImGui::TableSetupColumn(locale::get("invoice.table.status"), ImGuiTableColumnFlags_WidthFixed, 90); + ImGui::TableHeadersRow(); for (u32 i = 0; i < invoice_count; i++) { invoice c = invoice_list[i]; ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); ImGui::Text(c.sequential_number); + ImGui::TableSetColumnIndex(0); + + ImGui::PushID(i); + ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap; + bool selected = false; + if (ImGui::Selectable("##invisible_selectable", selected, selectable_flags, ImVec2(0, ImGui::GetFrameHeight()-4.0f))) + { + active_invoice = c; + current_view_state = ui::view_state::VIEW_EXISTING; + } + ImGui::SetItemAllowOverlap(); + ImGui::SameLine(); + ImGui::PopID(); + + ImGui::Text(c.sequential_number); if (administration::invoice_is_valid(&c) != A_ERR_SUCCESS) { @@ -340,54 +354,19 @@ static void draw_invoices_list() ImGui::TableSetColumnIndex(3); ImGui::Text(buf); ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f %s", c.total, c.currency); ImGui::TableSetColumnIndex(5); ImGui::Text("%s", locale::get(administration::invoice_get_status_string(&c))); - ImGui::TableSetColumnIndex(6); - - char btn_name[20]; - strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.view"), i); - if (ImGui::Button(btn_name)) { - active_invoice = c; - current_view_state = ui::view_state::VIEW_EXISTING; - } ImGui::SameLine(); - - if (c.status == invoice_status::INVOICE_CONCEPT) - { - strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.change"), i); - if (ImGui::Button(btn_name)) { - active_invoice = administration::invoice_create_copy(&c); // We create a copy because of billing item list pointers. - current_view_state = ui::view_state::EDIT_EXISTING; - } - - ImGui::SameLine(); - strops::format(btn_name, sizeof(btn_name), "%s##%d", locale::get("form.delete"), i); - if (ImGui::Button(btn_name)) { - selected_for_removal = c; - ImGui::OpenPopup("ConfirmDeletePopup"); - } - } - } - - // Confirmation popup before contact is deleted definitively. - if (ImGui::BeginPopupModal("ConfirmDeletePopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar)) { - ImGui::Text(locale::get("form.confirmDelete")); - ImGui::Separator(); - - if (ImGui::Button(locale::get("form.yes"), ImVec2(120, 0))) { - administration::invoice_remove(&selected_for_removal); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button(locale::get("form.no"), ImVec2(120, 0))) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); } ImGui::EndTable(); } } +static void _reset_to_invoice_view() +{ + current_view_state = ui::view_state::VIEW_EXISTING; +} + static void _reset_to_default_view() { current_view_state = ui::view_state::LIST_ALL; @@ -398,25 +377,28 @@ static void _reset_to_default_view() static void draw_invoice_update() { if (ImGui::Button(locale::get("form.back"), true, false)) { - _reset_to_default_view(); + current_view_state = ui::view_state::VIEW_EXISTING; + } + + { // Save button + bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; + if (!can_save) ImGui::BeginDisabled(); + ImGui::SameLine(); + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_invoice_view); + administration::invoice_update(&active_invoice); + } + if (!can_save) ImGui::EndDisabled(); } ImGui::Spacing(); ImGui::Separator(3.0f); ImGui::Spacing(); + float availableWidth = ImGui::GetContentRegionAvail().x; + ImGui::BeginChild("##invoicePanel", ImVec2(availableWidth - sidepanel_width, 0), ImGuiChildFlags_None); draw_invoice_form(&active_invoice); - - bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; - if (!can_save) ImGui::BeginDisabled(); - - ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"), true)) { - administration_writer::set_write_completed_event_callback(_reset_to_default_view); - administration::invoice_update(&active_invoice); - } - - if (!can_save) ImGui::EndDisabled(); + ImGui::EndChild(); } static void draw_invoice_create() @@ -425,22 +407,25 @@ static void draw_invoice_create() _reset_to_default_view(); } + { // Save button + bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; + if (!can_save) ImGui::BeginDisabled(); + ImGui::SameLine(); + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_invoice_view); + administration::invoice_add(&active_invoice); + } + if (!can_save) ImGui::EndDisabled(); + } + ImGui::Spacing(); ImGui::Separator(3.0f); ImGui::Spacing(); + float availableWidth = ImGui::GetContentRegionAvail().x; + ImGui::BeginChild("##invoicePanel", ImVec2(availableWidth - sidepanel_width, 0), ImGuiChildFlags_None); draw_invoice_form(&active_invoice); - - bool can_save = administration::invoice_is_valid(&active_invoice) == A_ERR_SUCCESS; - if (!can_save) ImGui::BeginDisabled(); - - ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"), true)) { - administration_writer::set_write_completed_event_callback(_reset_to_default_view); - administration::invoice_add(&active_invoice); - } - - if (!can_save) ImGui::EndDisabled(); + ImGui::EndChild(); } static void draw_invoice_view() @@ -451,6 +436,13 @@ static void draw_invoice_view() ImGui::SameLine(); + if (ImGui::Button(locale::get("form.change"))) { + active_invoice = administration::invoice_create_copy(&active_invoice); // We create a copy because of billing item list pointers. + current_view_state = ui::view_state::EDIT_EXISTING; + } + + ImGui::SameLine(); + ImGui::PushItemWidth(100.0f); if (ImGui::BeginCombo("##Send", locale::get("ui.sendAs"))) { @@ -483,7 +475,18 @@ static void draw_invoice_view() ImGui::Separator(3.0f); ImGui::Spacing(); + float availableWidth = ImGui::GetContentRegionAvail().x; + ImGui::BeginChild("##invoicePanel", ImVec2(availableWidth - sidepanel_width, 0), ImGuiChildFlags_None); draw_invoice_form(&active_invoice, true); + ImGui::EndChild(); + + ImGui::SameLine(); + ImGui::SeparatorEx(1 << 1, 3.0f); + ImGui::SameLine(); + + ImGui::BeginChild("##historyPanel", ImVec2(sidepanel_width, 0), ImGuiChildFlags_None); + // Sidepanel + ImGui::EndChild(); } void ui::draw_invoices() diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp index 6d55177..67d678f 100644 --- a/src/ui/ui_main.cpp +++ b/src/ui/ui_main.cpp @@ -92,7 +92,7 @@ void ui::draw_main() float sidePanelWidth = 120.0f; ImGui::SetNextWindowPos(ImVec2(0, menuBarHeight)); ImGui::SetNextWindowSize(ImVec2(sidePanelWidth, io.DisplaySize.y - menuBarHeight - statusBarHeight)); - + // Side panel ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::Begin("SidePanel", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse); diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp index 076f231..c458260 100644 --- a/src/ui/ui_settings.cpp +++ b/src/ui/ui_settings.cpp @@ -131,9 +131,6 @@ static void _cost_center_update_callback() { is_editing_cost_center = false; is_adding_cost_center = false; - - administration::cost_center_update(new_cost_center); - memops::zero(&new_cost_center, sizeof(new_cost_center)); ui::destroy_settings(); -- cgit v1.2.3-70-g09d2