diff options
| author | Aldrik Ramaekers <aldrikboy@gmail.com> | 2025-10-26 17:23:28 +0100 |
|---|---|---|
| committer | Aldrik Ramaekers <aldrikboy@gmail.com> | 2025-10-26 17:23:28 +0100 |
| commit | 60488d722bf29f3ff0ce3e08b90f30523a8d7b6d (patch) | |
| tree | c2e01243d8a0d970c35e250b66a66a226ab230dc /src | |
| parent | 5e06ad208e32330b662af90ce41613f5421095cb (diff) | |
loading animations and block navigation while writing to disk
Diffstat (limited to 'src')
| -rw-r--r-- | src/administration.cpp | 23 | ||||
| -rw-r--r-- | src/administration_writer.cpp | 174 | ||||
| -rw-r--r-- | src/ui/helpers.cpp | 100 | ||||
| -rw-r--r-- | src/ui/imgui_extensions.cpp | 95 | ||||
| -rw-r--r-- | src/ui/ui_contacts.cpp | 25 | ||||
| -rw-r--r-- | src/ui/ui_expenses.cpp | 36 | ||||
| -rw-r--r-- | src/ui/ui_invoices.cpp | 34 | ||||
| -rw-r--r-- | src/ui/ui_main.cpp | 1 | ||||
| -rw-r--r-- | src/ui/ui_projects.cpp | 23 | ||||
| -rw-r--r-- | src/ui/ui_settings.cpp | 85 |
10 files changed, 362 insertions, 234 deletions
diff --git a/src/administration.cpp b/src/administration.cpp index 9fdfe7e..cb158e2 100644 --- a/src/administration.cpp +++ b/src/administration.cpp @@ -26,7 +26,7 @@ static ledger g_administration; -static data_changed_event data_changed_event_callback = 0; +static data_changed_event administration_data_changed_event_callback = 0; static data_deleted_event data_deleted_event_callback = 0; static invoice_changed_event invoice_changed_event_callback = 0; static contact_changed_event contact_changed_event_callback = 0; @@ -58,7 +58,6 @@ static void create_default_cost_centers() list_append(&g_administration.cost_centers, tb);\ g_administration.next_id++;\ if (costcenter_changed_event_callback) costcenter_changed_event_callback(tb);\ - if (data_changed_event_callback) data_changed_event_callback();\ } ADD_COSTCENTER("costcenter.general_expenses", "GENE"); @@ -81,9 +80,9 @@ static s32 create_sequence_number() // Callback functions. // ======================= -void administration::set_data_changed_event_callback(data_changed_event ev) +void administration::set_administration_data_changed_event_callback(data_changed_event ev) { - data_changed_event_callback = ev; + administration_data_changed_event_callback = ev; } void administration::set_data_deleted_event_callback(data_deleted_event ev) @@ -227,7 +226,7 @@ ai_service administration::get_ai_service() void administration::set_ai_service(ai_service provider) { g_administration.ai_service = provider; - if (data_changed_event_callback) data_changed_event_callback(); + if (administration_data_changed_event_callback) administration_data_changed_event_callback(); } void administration::set_next_id(s32 nr) @@ -650,7 +649,6 @@ void administration::company_info_set(contact data) strops::copy(g_administration.default_currency, get_default_currency_for_country(g_administration.company_info.address.country_code), MAX_LEN_CURRENCY); if (contact_changed_event_callback) contact_changed_event_callback(&data); - if (data_changed_event_callback) data_changed_event_callback(); } // Contact functions. @@ -690,7 +688,6 @@ a_err administration::contact_add(contact data) g_administration.next_id++; if (contact_changed_event_callback) contact_changed_event_callback(new_contact); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -708,7 +705,6 @@ a_err administration::contact_update(contact data) memops::copy(c, &data, sizeof(data)); if (contact_changed_event_callback) contact_changed_event_callback(c); - if (data_changed_event_callback) data_changed_event_callback(); list_iterator_stop(&g_administration.contacts); return A_ERR_SUCCESS; @@ -1001,7 +997,6 @@ a_err administration::project_add(project data) g_administration.next_id++; if (project_changed_event_callback) project_changed_event_callback(new_project); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -1020,7 +1015,6 @@ a_err administration::project_update(project data) list_iterator_stop(&g_administration.projects); if (project_changed_event_callback) project_changed_event_callback(c); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -1163,7 +1157,6 @@ a_err administration::tax_rate_enable(tax_rate data) g_administration.next_id++; if (taxrate_changed_event_callback) taxrate_changed_event_callback(&data); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -1291,7 +1284,6 @@ a_err administration::cost_center_add(cost_center data) g_administration.next_id++; if (costcenter_changed_event_callback) costcenter_changed_event_callback(tb); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -1310,7 +1302,6 @@ a_err administration::cost_center_update(cost_center data) list_iterator_stop(&g_administration.cost_centers); if (costcenter_changed_event_callback) costcenter_changed_event_callback(c); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -1502,7 +1493,6 @@ a_err administration::invoice_update(invoice* inv) list_iterator_stop(&g_administration.invoices); if (invoice_changed_event_callback) invoice_changed_event_callback(c); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -1568,7 +1558,6 @@ a_err administration::invoice_add(invoice* inv) else g_administration.expense_count++; if (invoice_changed_event_callback) invoice_changed_event_callback(new_inv); - if (data_changed_event_callback) data_changed_event_callback(); return A_ERR_SUCCESS; } @@ -1784,10 +1773,6 @@ static void administration_recalculate_billing_item_totals(billing_item* item) { item->tax = item->net * (rate.rate/100.0f); } - else - { - assert(0); - } item->total = item->net + item->tax; } diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp index 77b1445..c45ec6e 100644 --- a/src/administration_writer.cpp +++ b/src/administration_writer.cpp @@ -18,6 +18,7 @@ #include <xml.h> #include <threads.h> +#include "config.hpp" #include "memops.hpp" #include "logger.hpp" #include "ui.hpp" @@ -28,51 +29,164 @@ #include "tinyfiledialogs.h" #include "file_templates.hpp" -mtx_t _save_file_mutex; +static mtx_t _save_file_mutex; +static bool _is_writing = false; +static write_completed_event _write_completed_ev = 0; + +bool administration_writer::is_writing() +{ + return _is_writing; +} + +void administration_writer::set_write_completed_event_callback(write_completed_event ev) +{ + _write_completed_ev = ev; +} static void on_administration_data_changed() { - if (administration_writer::save_all_administration_info_blocking()) { - ui::set_status(locale::get("status.saved")); - } - else { - ui::set_status(locale::get("status.saveFailed")); - } + _is_writing = true; + + auto* func = new auto([]() { + administration_writer::save_administration_info_blocking(); + + _is_writing = false; + if (_write_completed_ev) _write_completed_ev(); + }); + + auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(); delete f; return 0; }; + thrd_t thr; thrd_create(&thr, trampoline, 0); } static void on_administration_data_deleted(char id[MAX_LEN_ID]) { - administration_writer::delete_entry(id); + _is_writing = true; + + char* id_copy = (char*)memops::alloc(MAX_LEN_ID); + strops::copy(id_copy, id, MAX_LEN_ID); + + auto* func = new auto([](void* arg) { + char* id = (char*)arg; + administration_writer::delete_entry(id); + administration_writer::save_administration_info_blocking(); + memops::unalloc(arg); + + _is_writing = false; + if (_write_completed_ev) _write_completed_ev(); + }); + + auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; }; + thrd_t thr; thrd_create(&thr, trampoline, (void*)id_copy); } -static void on_invoice_changed(invoice* invoice) +static void on_invoice_changed(invoice* inv) { - administration_writer::save_invoice_blocking(*invoice); + _is_writing = true; + + invoice inv_copy = administration::invoice_create_copy(inv); + invoice* inv_copy2 = (invoice*)memops::alloc(sizeof(invoice)); + memops::copy(inv_copy2, &inv_copy, sizeof(invoice)); + + auto* func = new auto([](void* arg) { + invoice* inv = (invoice*)arg; + administration_writer::save_invoice_blocking(*inv); + administration_writer::save_administration_info_blocking(); + administration::invoice_destroy(inv); + + _is_writing = false; + if (_write_completed_ev) _write_completed_ev(); + }); + + auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; }; + thrd_t thr; thrd_create(&thr, trampoline, (void*)inv_copy2); } -static void on_contact_changed_changed(contact* contact) +static void on_contact_changed_changed(contact* cc) { - administration_writer::save_contact_blocking(*contact); + _is_writing = true; + + contact* cc_copy = (contact*)memops::alloc(sizeof(contact)); + memops::copy(cc_copy, cc, sizeof(contact)); + + auto* func = new auto([](void* arg) { + contact* cc = (contact*)arg; + administration_writer::save_contact_blocking(*cc); + administration_writer::save_administration_info_blocking(); + memops::unalloc(arg); + + _is_writing = false; + if (_write_completed_ev) _write_completed_ev(); + }); + + auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; }; + thrd_t thr; thrd_create(&thr, trampoline, (void*)cc_copy); } static void on_taxrate_changed_changed(tax_rate* rate) { - administration_writer::save_tax_rate_blocking(*rate); + _is_writing = true; + + tax_rate* rate_copy = (tax_rate*)memops::alloc(sizeof(tax_rate)); + memops::copy(rate_copy, rate, sizeof(tax_rate)); + + auto* func = new auto([](void* arg) { + tax_rate* rate = (tax_rate*)arg; + administration_writer::save_tax_rate_blocking(*rate); + administration_writer::save_administration_info_blocking(); + memops::unalloc(arg); + + _is_writing = false; + if (_write_completed_ev) _write_completed_ev(); + }); + + auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; }; + thrd_t thr; thrd_create(&thr, trampoline, (void*)rate_copy); } -static void on_costcenter_changed_changed(cost_center* cost_center) +static void on_costcenter_changed_changed(cost_center* cc) { - administration_writer::save_cost_center_blocking(*cost_center); + _is_writing = true; + + cost_center* cc_copy = (cost_center*)memops::alloc(sizeof(cost_center)); + memops::copy(cc_copy, cc, sizeof(cost_center)); + + auto* func = new auto([](void* arg) { + cost_center* cc = (cost_center*)arg; + administration_writer::save_cost_center_blocking(*cc); + memops::unalloc(arg); + + _is_writing = false; + if (_write_completed_ev) _write_completed_ev(); + }); + + auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; }; + thrd_t thr; thrd_create(&thr, trampoline, (void*)cc_copy); } -static void on_project_changed_changed(project* project) +static void on_project_changed_changed(project* pp) { - administration_writer::save_project_blocking(*project); + _is_writing = true; + + project* pp_copy = (project*)memops::alloc(sizeof(project)); + memops::copy(pp_copy, pp, sizeof(project)); + + auto* func = new auto([](void* arg) { + project* pp = (project*)arg; + administration_writer::save_project_blocking(*pp); + administration_writer::save_administration_info_blocking(); + memops::unalloc(arg); + + _is_writing = false; + if (_write_completed_ev) _write_completed_ev(); + }); + + auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; }; + thrd_t thr; thrd_create(&thr, trampoline, (void*)pp_copy); } bool administration_writer::create() { - administration::set_data_changed_event_callback(on_administration_data_changed); + administration::set_administration_data_changed_event_callback(on_administration_data_changed); administration::set_data_deleted_event_callback(on_administration_data_deleted); administration::set_invoice_changed_event_callback(on_invoice_changed); administration::set_contact_changed_event_callback(on_contact_changed_changed); @@ -80,7 +194,7 @@ bool administration_writer::create() administration::set_costcenter_changed_event_callback(on_costcenter_changed_changed); administration::set_project_changed_event_callback(on_project_changed_changed); - return mtx_init(&_save_file_mutex, mtx_plain) == thrd_success; + return mtx_init(&_save_file_mutex, mtx_plain|mtx_recursive) == thrd_success; } void administration_writer::destroy() @@ -101,17 +215,23 @@ static char* copy_template(const char* template_str, int* buf_size) static bool zip_entry_exists(char* entry) { + mtx_lock(&_save_file_mutex); + struct zip_t *zip_read = zip_open(administration::get_file_path(), 0, 'r'); int result = zip_entry_open(zip_read, entry); zip_entry_close(zip_read); zip_close(zip_read); + mtx_unlock(&_save_file_mutex); + return result == 0; } static bool delete_entry_by_name(char* entry) { STOPWATCH_START; + + mtx_lock(&_save_file_mutex); bool result = 1; struct zip_t *zip_write = zip_open(administration::get_file_path(), 0, 'a'); @@ -124,6 +244,8 @@ static bool delete_entry_by_name(char* entry) if (result) logger::info("Deleted entry '%s' in %.3fms.", entry, STOPWATCH_TIME); else logger::error("Failed to delete entry '%s'.", entry); + mtx_unlock(&_save_file_mutex); + return result; } @@ -137,6 +259,8 @@ bool administration_writer::delete_entry(char* id) static bool write_to_zip(char* entry_to_replace, char* orig_content, int final_length) { + mtx_lock(&_save_file_mutex); + bool result = 1; bool entry_exists = zip_entry_exists(entry_to_replace); if (entry_exists) delete_entry_by_name(entry_to_replace); @@ -149,6 +273,16 @@ static bool write_to_zip(char* entry_to_replace, char* orig_content, int final_l zip_entry_close(zip_write); zip_close(zip_write); + + #if WRITE_DELAY_SEC != 0 + struct timespec time; + time.tv_sec = WRITE_DELAY_SEC; + time.tv_nsec = 0; + thrd_sleep(&time, NULL); + #endif + + mtx_unlock(&_save_file_mutex); + return result; } @@ -705,7 +839,7 @@ bool administration_writer::save_contact_blocking(contact c) ///////////////////////////// //// Administration info ///////////////////////////// -bool administration_writer::save_all_administration_info_blocking() +bool administration_writer::save_administration_info_blocking() { STOPWATCH_START; diff --git a/src/ui/helpers.cpp b/src/ui/helpers.cpp deleted file mode 100644 index 476e780..0000000 --- a/src/ui/helpers.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -* Copyright (c) 2025 Aldrik Ramaekers <aldrik.ramaekers@gmail.com> -* -* Permission to use, copy, modify, and/or distribute this software for any -* purpose with or without fee is hereby granted, provided that the above -* copyright notice and this permission notice appear in all copies. -* -* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "ui.hpp" -#include "imgui.h" -#include "strops.hpp" - -#define STATUS_DURATION 4.0f -#define STATUS_FLASH_INTERVAL 0.1f -#define STATUS_MAX_FLASHES 2 - -namespace ui { - - ImFont* fontBold; - ImFont* fontBig; - - static status current_status; - - void ui::draw_status() - { - float region_width = ImGui::GetContentRegionAvail().x; - float text_width = ImGui::CalcTextSize(current_status.text).x; - - if (current_status.loading) - { - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + region_width - text_width - 20.0f); - ImGui::Text("%c", "|/-\\"[(int)(ImGui::GetTime() / 0.1f) & 3]); - return; - } - - if (current_status.visible) - { - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + region_width - text_width); - ImGui::PushStyleColor(ImGuiCol_Text, current_status.color); - ImGui::TextUnformatted(current_status.text); - ImGui::PopStyleColor(); - } - - ImGuiIO& io = ImGui::GetIO(); - current_status.time += io.DeltaTime; - - if (current_status.time >= STATUS_FLASH_INTERVAL && current_status.flash_count < STATUS_MAX_FLASHES) - { - current_status.visible = !current_status.visible; - if (current_status.visible) current_status.flash_count++; - current_status.time = 0.0f; - } - - if (current_status.time >= STATUS_DURATION) - { - current_status.text[0] = 0; - } - } - - static void set_status_ex(const char* txt, int color) - { - current_status.flash_count = 0; - current_status.visible = true; - current_status.time = 0.0f; - current_status.color = color; - current_status.loading = false; - strops::copy(current_status.text, txt, STATUS_TEXT_LEN); - } - - void ui::set_status_error(const char* txt) - { - set_status_ex(txt, config::colors::COLOR_ERROR); - } - - void ui::set_status(const char* txt) - { - set_status_ex(txt, config::colors::COLOR_DEFAULT); - } - - void ui::set_status_loading(bool loading) - { - current_status.visible = true; - current_status.time = 0.0f; - current_status.loading = loading; - } - - status ui::get_status() - { - return current_status; - } - -}
\ No newline at end of file diff --git a/src/ui/imgui_extensions.cpp b/src/ui/imgui_extensions.cpp index d1abc58..359fc17 100644 --- a/src/ui/imgui_extensions.cpp +++ b/src/ui/imgui_extensions.cpp @@ -4,11 +4,104 @@ #include "config.hpp" #include "locales.hpp" #include "countries.hpp" -#include "administration.hpp" #include "tinyfiledialogs.h" +#include "administration.hpp" +#include "administration_writer.hpp" + +namespace ui { + ImFont* fontBold; + ImFont* fontBig; +} namespace ImGui { + bool CheckboxX(const char* label, bool* v, bool disabled, bool show_loading_indicator_while_disabled) + { + bool result = false; + if (disabled) ImGui::BeginDisabled(); + if (!disabled || !show_loading_indicator_while_disabled) + { + result = ImGui::Checkbox(label, v); + } + else + { + bool tmp = false; + result = ImGui::Checkbox(label, &tmp); + if (result) *v = !(*v); + + float radius = 10.0f; + ImVec2 p_min = ImGui::GetItemRectMin(); + ImVec2 p_max = ImGui::GetItemRectMax(); + ImVec2 center = ImVec2((p_min.x + p_max.x) * 0.5f - radius, (p_min.y + p_max.y) * 0.5f - radius); + + ImGui::SetCursorScreenPos(ImVec2(center.x, center.y)); + + const ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + const ImVec4 bg = ImGui::GetStyleColorVec4(ImGuiCol_Button); + ImGui::LoadingIndicatorCircle("##loadingAnim", radius, bg, col, 6, 4.0f); + } + + if (disabled) ImGui::EndDisabled(); + return result; + } + + static ImVec2 CalcButtonSize(const char* label) + { + ImGuiStyle& style = ImGui::GetStyle(); + ImVec2 text_size = ImGui::CalcTextSize(label, nullptr, true); + ImVec2 button_size = ImVec2( + text_size.x + style.FramePadding.x * 2.0f, + text_size.y + style.FramePadding.y * 2.0f + ); + return button_size; + } + + bool Button(const char* label, bool block_while_writing_to_disk, bool show_loading_indicator_while_blocked) + { + if (block_while_writing_to_disk) + { + if (administration_writer::is_writing()) + { + if (show_loading_indicator_while_blocked) { + ImGui::PushID(label); + ImGui::BeginDisabled(); + bool result = ImGui::Button("", CalcButtonSize(label)); + + float radius = 10.0f; + ImVec2 p_min = ImGui::GetItemRectMin(); + ImVec2 p_max = ImGui::GetItemRectMax(); + ImVec2 center = ImVec2((p_min.x + p_max.x) * 0.5f - radius, (p_min.y + p_max.y) * 0.5f - radius); + + ImGui::SetCursorScreenPos(ImVec2(center.x, center.y)); + + const ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + const ImVec4 bg = ImGui::GetStyleColorVec4(ImGuiCol_Button); + ImGui::LoadingIndicatorCircle("##loadingAnim", radius, bg, col, 6, 4.0f); + + ImGui::EndDisabled(); + ImGui::PopID(); + + return result; + } + else + { + ImGui::BeginDisabled(); + bool result = ImGui::Button(label); + ImGui::EndDisabled(); + return result; + } + } + else + { + return ImGui::Button(label); + } + } + else + { + return ImGui::Button(label); + } + } + void InputTextWithError(const char* text, char* buffer, size_t buf_size, bool has_error) { if (has_error) { diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp index 0f1716f..5d92f8a 100644 --- a/src/ui/ui_contacts.cpp +++ b/src/ui/ui_contacts.cpp @@ -154,10 +154,15 @@ static void draw_contact_list() } } +static void _reset_to_default_view() +{ + current_view_state = ui::view_state::LIST_ALL; +} + static void draw_contacts_create() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } ImGui::ContactForm(&active_contact, false, false); @@ -167,17 +172,17 @@ static void draw_contacts_create() if (!can_save) ImGui::BeginDisabled(); // Save button ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_default_view); administration::contact_add(active_contact); - current_view_state = ui::view_state::LIST_ALL; } if (!can_save) ImGui::EndDisabled(); } static void draw_contacts_update() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } ImGui::ContactForm(&active_contact, false, false); @@ -187,9 +192,9 @@ static void draw_contacts_update() if (!can_save) ImGui::BeginDisabled(); // Save button ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_default_view); administration::contact_update(active_contact); - current_view_state = ui::view_state::LIST_ALL; } if (!can_save) ImGui::EndDisabled(); } @@ -203,8 +208,8 @@ void ui::draw_contacts() case ui::view_state::EDIT_EXISTING: draw_contacts_update(); break; case ui::view_state::VIEW_EXISTING: - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } ImGui::ContactForm(&active_contact, true, false); diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp index d1121b1..8635273 100644 --- a/src/ui/ui_expenses.cpp +++ b/src/ui/ui_expenses.cpp @@ -294,11 +294,17 @@ static void draw_expenses_list() } } +static void _reset_to_default_view() +{ + current_view_state = ui::view_state::LIST_ALL; + ui::destroy_expenses(); + ui::setup_expenses(); +} static void draw_expense_update() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } draw_expense_form(&active_invoice); @@ -307,13 +313,9 @@ static void draw_expense_update() if (!can_save) ImGui::BeginDisabled(); ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_default_view); administration::invoice_update(&active_invoice); - - current_view_state = ui::view_state::LIST_ALL; - - ui::destroy_expenses(); - ui::setup_expenses(); } if (!can_save) ImGui::EndDisabled(); @@ -321,8 +323,8 @@ static void draw_expense_update() static void draw_expense_create() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } draw_expense_form(&active_invoice); @@ -331,13 +333,9 @@ static void draw_expense_create() if (!can_save) ImGui::BeginDisabled(); ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_default_view); administration::invoice_add(&active_invoice); - - current_view_state = ui::view_state::LIST_ALL; - - ui::destroy_expenses(); - ui::setup_expenses(); } if (!can_save) ImGui::EndDisabled(); @@ -345,8 +343,8 @@ static void draw_expense_create() static void draw_expense_view() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } draw_expense_form(&active_invoice, true); @@ -365,7 +363,7 @@ static void draw_import_request() } else { if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + _reset_to_default_view(); active_import_request = 0; return; } diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp index 8741965..3987b72 100644 --- a/src/ui/ui_invoices.cpp +++ b/src/ui/ui_invoices.cpp @@ -388,11 +388,17 @@ static void draw_invoices_list() } } +static void _reset_to_default_view() +{ + current_view_state = ui::view_state::LIST_ALL; + ui::destroy_invoices(); + ui::setup_invoices(); +} static void draw_invoice_update() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } draw_invoice_form(&active_invoice); @@ -401,13 +407,9 @@ static void draw_invoice_update() if (!can_save) ImGui::BeginDisabled(); ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_default_view); administration::invoice_update(&active_invoice); - - current_view_state = ui::view_state::LIST_ALL; - - ui::destroy_invoices(); - ui::setup_invoices(); } if (!can_save) ImGui::EndDisabled(); @@ -415,8 +417,8 @@ static void draw_invoice_update() static void draw_invoice_create() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } draw_invoice_form(&active_invoice); @@ -425,13 +427,9 @@ static void draw_invoice_create() if (!can_save) ImGui::BeginDisabled(); ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_reset_to_default_view); administration::invoice_add(&active_invoice); - - current_view_state = ui::view_state::LIST_ALL; - - ui::destroy_invoices(); - ui::setup_invoices(); } if (!can_save) ImGui::EndDisabled(); @@ -439,8 +437,8 @@ static void draw_invoice_create() static void draw_invoice_view() { - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); } draw_invoice_form(&active_invoice, true); diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp index 48b1364..d4b9c58 100644 --- a/src/ui/ui_main.cpp +++ b/src/ui/ui_main.cpp @@ -160,7 +160,6 @@ void ui::draw_main() } ImGui::SameLine(); - ui::draw_status(); ImGui::End(); ImGui::PopStyleVar(); diff --git a/src/ui/ui_projects.cpp b/src/ui/ui_projects.cpp index 82597b4..94f2be6 100644 --- a/src/ui/ui_projects.cpp +++ b/src/ui/ui_projects.cpp @@ -26,22 +26,24 @@ static project selected_for_cancellation; static project active_project; -void ui::setup_projects() +static void _reset_to_default_view() { current_view_state = ui::view_state::LIST_ALL; active_project = administration::project_create_empty(); } +void ui::setup_projects() +{ + _reset_to_default_view(); +} + static void draw_project_form() { float widthAvailable = ImGui::GetContentRegionAvail().x; bool viewing_only = (current_view_state == ui::view_state::VIEW_EXISTING); - static const char* selected_country = NULL; - if (ImGui::Button(locale::get("form.back"))) { - current_view_state = ui::view_state::LIST_ALL; - active_project = administration::project_create_empty(); - selected_country = 0; + if (ImGui::Button(locale::get("form.back"), true, false)) { + _reset_to_default_view(); return; } ImGui::Spacing(); @@ -63,7 +65,10 @@ static void draw_project_form() if (!can_save) ImGui::BeginDisabled(); // Save button ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + + administration_writer::set_write_completed_event_callback(_reset_to_default_view); + if (current_view_state == ui::view_state::CREATE) { administration::project_add(active_project); } @@ -71,10 +76,6 @@ static void draw_project_form() else if (current_view_state == ui::view_state::EDIT_EXISTING) { administration::project_update(active_project); } - - current_view_state = ui::view_state::LIST_ALL; - selected_country = 0; - active_project = administration::project_create_empty(); } if (!can_save) ImGui::EndDisabled(); } diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp index e15bde0..1c8f92b 100644 --- a/src/ui/ui_settings.cpp +++ b/src/ui/ui_settings.cpp @@ -58,6 +58,13 @@ void ui::setup_settings() } } +static bool is_writing_vat_rate = false; +static u32 writing_vat_rate_index = 0; +static void _vat_rate_write_complete_callback() +{ + is_writing_vat_rate = false; +} + static void draw_vat_rates() { tax_rate_type type_iter = tax_rate_type::TAX_RATE_OUTGOING_INVOICE; @@ -84,7 +91,10 @@ static void draw_vat_rates() ImGui::TableSetColumnIndex(0); bool toggle = administration::tax_rate_is_enabled(c) == A_ERR_SUCCESS; - if (ImGui::Checkbox("##toggle", &toggle)) { + if (ImGui::CheckboxX("##toggle", &toggle, is_writing_vat_rate, i == writing_vat_rate_index)) { + writing_vat_rate_index = i; + is_writing_vat_rate = true; + administration_writer::set_write_completed_event_callback(_vat_rate_write_complete_callback); if (toggle) administration::tax_rate_enable(c); else administration::tax_rate_disable(c); } @@ -113,12 +123,26 @@ static void draw_vat_rates() if (type_iter < TAX_RATE_TYPE_END) goto go_again; } -static void draw_cost_centers() +static bool is_adding_cost_center = false; +static bool is_editing_cost_center = false; +static cost_center new_cost_center; + +static void _cost_center_update_callback() { - static bool is_adding_item = false; - static cost_center new_cost_center; + 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(); + ui::setup_settings(); + select_company_tab = 0; +} - static bool is_editing_item = false; +static void draw_cost_centers() +{ static u32 editing_item_index = 0; if (ImGui::BeginTable("TableCostCenters", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { @@ -137,7 +161,7 @@ static void draw_cost_centers() // Column 2: When editing, show inputs for new description. Else show stored description and check for modify request. ImGui::TableSetColumnIndex(1); - if (is_editing_item && editing_item_index == i) + if (is_editing_cost_center && editing_item_index == i) { bool is_desc_valid = !(administration::cost_center_is_valid(new_cost_center) & A_ERR_MISSING_DESCRIPTION); if (!is_desc_valid) ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(105, 43, 43, 255)); @@ -146,23 +170,16 @@ static void draw_cost_centers() if (!is_desc_valid) ImGui::BeginDisabled(); ImGui::SameLine(); - if (ImGui::Button(locale::get("form.save"))) { - is_editing_item = false; - is_adding_item = false; - + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(_cost_center_update_callback); administration::cost_center_update(new_cost_center); - - memops::zero(&new_cost_center, sizeof(new_cost_center)); - - ui::destroy_settings(); - ui::setup_settings(); } if (!is_desc_valid) ImGui::EndDisabled(); ImGui::SameLine(); - if (ImGui::Button(locale::get("form.cancel"))) { - is_editing_item = false; - is_adding_item = false; + if (ImGui::Button(locale::get("form.cancel"), true, false)) { + is_editing_cost_center = false; + is_adding_cost_center = false; memops::zero(&new_cost_center, sizeof(new_cost_center)); } } @@ -172,8 +189,8 @@ static void draw_cost_centers() if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { - is_editing_item = true; - is_adding_item = false; + is_editing_cost_center = true; + is_adding_cost_center = false; editing_item_index = i; new_cost_center = c; } @@ -182,7 +199,7 @@ static void draw_cost_centers() // When adding a new item. Show inputs for code and description, check validity, and handle save/cancel. // Form for new entry is displayed at bottom of list. - if (is_adding_item) + if (is_adding_cost_center) { ImGui::TableNextRow(); @@ -201,21 +218,17 @@ static void draw_cost_centers() if (!can_save) ImGui::BeginDisabled(); ImGui::SameLine(); - if (ImGui::Button(locale::get("form.create"))) + if (ImGui::Button(locale::get("form.create"), true)) { - is_adding_item = false; - is_editing_item = false; + administration_writer::set_write_completed_event_callback(_cost_center_update_callback); administration::cost_center_add(new_cost_center); - - ui::destroy_settings(); - ui::setup_settings(); } if (!can_save) ImGui::EndDisabled(); ImGui::SameLine(); - if (ImGui::Button(locale::get("form.cancel"))) { - is_adding_item = false; - is_editing_item = false; + if (ImGui::Button(locale::get("form.cancel"), true)) { + is_adding_cost_center = false; + is_editing_cost_center = false; memops::zero(&new_cost_center, sizeof(new_cost_center)); } } @@ -224,11 +237,11 @@ static void draw_cost_centers() } // If not adding a new item already, show create button at bottom of list. - if (!is_adding_item && ImGui::Button(locale::get("form.create"))) + if (!is_adding_cost_center && ImGui::Button(locale::get("form.create"))) { new_cost_center = administration::cost_center_create_empty(); - is_adding_item = true; - is_editing_item = false; + is_adding_cost_center = true; + is_editing_cost_center = false; } } @@ -317,7 +330,8 @@ static void draw_services() ImGui::EndDisabled(); } - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(0); administration::set_ai_service(new_service); } } @@ -336,7 +350,8 @@ void ui::draw_settings() bool can_save = administration::contact_is_valid(company_info) == A_ERR_SUCCESS; if (!can_save) ImGui::BeginDisabled(); ImGui::Spacing(); - if (ImGui::Button(locale::get("form.save"))) { + if (ImGui::Button(locale::get("form.save"), true)) { + administration_writer::set_write_completed_event_callback(0); administration::company_info_set(company_info); } if (!can_save) ImGui::EndDisabled(); |
