From 840ead36459a10281c6d0bc2eaa8813470cf2f75 Mon Sep 17 00:00:00 2001 From: DanS Date: Sat, 4 Jul 2026 21:11:02 -0500 Subject: [PATCH] refactor(ui): add material::LabeledInput helper + adopt at 8 form fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UI-standardization audit: the labeled single-line form field (a plain ImGui::Text label above a fixed-width InputText/InputTextWithHint) was open-coded across dialogs. Add material::LabeledInput(label, id, buf, size, width=-1, hint=nullptr, flags=0) mirroring that idiom exactly — pixel-identical, but a single chokepoint so input styling (label typography, frame, spacing) can later evolve in one place. Returns the input's edited bool. Adopt at the clean vertical (label-above) single-line sites: address-book add/edit (label + address), shield from-address, export-all-keys + export- transactions filename, validate-address input, request-payment label + URI. Left as-is: horizontal label-beside-input rows (settings RPC host/port/user/ pass use Text + SameLine), multiline (InputTextMultiline), numeric (InputDouble), combos, and hint-only inputs — none match the vertical single-line idiom. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/ui/material/draw_helpers.h | 16 ++++++++++++++++ src/ui/windows/address_book_dialog.cpp | 10 ++++------ src/ui/windows/export_all_keys_dialog.cpp | 4 +--- src/ui/windows/export_transactions_dialog.cpp | 4 +--- src/ui/windows/request_payment_dialog.cpp | 10 +++------- src/ui/windows/shield_dialog.cpp | 4 +--- src/ui/windows/validate_address_dialog.cpp | 7 +++---- 7 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/ui/material/draw_helpers.h b/src/ui/material/draw_helpers.h index d3fc7c1..26cf397 100644 --- a/src/ui/material/draw_helpers.h +++ b/src/ui/material/draw_helpers.h @@ -354,6 +354,22 @@ inline ImVec2 DrawPill(ImDrawList* dl, const ImVec2& pos, const char* text, ImFo return sz; } +// ── Labeled form input ─────────────────────────────────────────────────── +// The app's common form-field idiom: a plain label above a fixed-width single-line input +// (ImGui::Text label + SetNextItemWidth + InputText / InputTextWithHint). Mirrors the existing +// pattern exactly (no visual change) so input styling can later evolve in ONE place. `width` < 0 +// means full width (-1). Pass a non-null `hint` to use InputTextWithHint. Returns the input's +// edited bool. The label is drawn via "%s" so a stray '%' in the text is safe. +inline bool LabeledInput(const char* label, const char* id, char* buf, size_t bufSize, + float width = -1.0f, const char* hint = nullptr, + ImGuiInputTextFlags flags = 0) +{ + ImGui::Text("%s", label); + ImGui::SetNextItemWidth(width); + if (hint && hint[0]) return ImGui::InputTextWithHint(id, hint, buf, bufSize, flags); + return ImGui::InputText(id, buf, bufSize, flags); +} + // ── Frameless icon button ──────────────────────────────────────────────── // Style for IconButton. All colors default to 0 (= unset): color falls back to OnSurfaceMedium(); // hoverColor==0 means "no hover recolor"; hoverBg/restBg==0 mean "no background". diff --git a/src/ui/windows/address_book_dialog.cpp b/src/ui/windows/address_book_dialog.cpp index 6924456..7d271c9 100644 --- a/src/ui/windows/address_book_dialog.cpp +++ b/src/ui/windows/address_book_dialog.cpp @@ -101,15 +101,13 @@ void AddressBookDialog::render(App* app) if (material::BeginOverlayDialog(title, open, dialogW, 0.94f, Layout::kDialogCompactBottomRatio(), id)) { - ImGui::Text("%s", TR("label")); - ImGui::SetNextItemWidth(formW); - ImGui::InputText(isEdit ? "##EditLabel" : "##AddLabel", s_edit_label, sizeof(s_edit_label)); + material::LabeledInput(TR("label"), isEdit ? "##EditLabel" : "##AddLabel", + s_edit_label, sizeof(s_edit_label), formW); ImGui::Spacing(); - ImGui::Text("%s", TR("address_label")); - ImGui::SetNextItemWidth(formW); - ImGui::InputText(isEdit ? "##EditAddress" : "##AddAddress", s_edit_address, sizeof(s_edit_address)); + material::LabeledInput(TR("address_label"), isEdit ? "##EditAddress" : "##AddAddress", + s_edit_address, sizeof(s_edit_address), formW); if (!isEdit) { ImGui::SameLine(); if (material::StyledButton(TR("paste"), ImVec2(0,0), S.resolveFont(actionBtn.font))) { diff --git a/src/ui/windows/export_all_keys_dialog.cpp b/src/ui/windows/export_all_keys_dialog.cpp index bc10a32..fee1919 100644 --- a/src/ui/windows/export_all_keys_dialog.cpp +++ b/src/ui/windows/export_all_keys_dialog.cpp @@ -99,9 +99,7 @@ void ExportAllKeysDialog::render(App* app) ImGui::Spacing(); // Filename - ImGui::Text("%s", TR("output_filename")); - ImGui::SetNextItemWidth(-1); - ImGui::InputText("##Filename", s_filename, sizeof(s_filename)); + material::LabeledInput(TR("output_filename"), "##Filename", s_filename, sizeof(s_filename)); ImGui::Spacing(); ImGui::TextDisabled("%s", TR("file_save_location")); diff --git a/src/ui/windows/export_transactions_dialog.cpp b/src/ui/windows/export_transactions_dialog.cpp index e1b8b1e..81874f0 100644 --- a/src/ui/windows/export_transactions_dialog.cpp +++ b/src/ui/windows/export_transactions_dialog.cpp @@ -82,9 +82,7 @@ void ExportTransactionsDialog::render(App* app) ImGui::Spacing(); // Filename - ImGui::Text("%s", TR("output_filename")); - ImGui::SetNextItemWidth(-1); - ImGui::InputText("##Filename", s_filename, sizeof(s_filename)); + material::LabeledInput(TR("output_filename"), "##Filename", s_filename, sizeof(s_filename)); ImGui::Spacing(); ImGui::TextDisabled("%s", TR("file_save_location")); diff --git a/src/ui/windows/request_payment_dialog.cpp b/src/ui/windows/request_payment_dialog.cpp index 3c1a010..a76b668 100644 --- a/src/ui/windows/request_payment_dialog.cpp +++ b/src/ui/windows/request_payment_dialog.cpp @@ -197,9 +197,7 @@ void RequestPaymentDialog::render(App* app) ImGui::Spacing(); // Label (optional) - ImGui::Text("%s", TR("request_label")); - ImGui::SetNextItemWidth(-1); - if (ImGui::InputText("##Label", s_label, sizeof(s_label))) { + if (material::LabeledInput(TR("request_label"), "##Label", s_label, sizeof(s_label))) { s_uri_dirty = true; } @@ -242,13 +240,11 @@ void RequestPaymentDialog::render(App* app) // Payment URI display if (!s_payment_uri.empty()) { - ImGui::Text("%s", TR("request_payment_uri")); - ImGui::SetNextItemWidth(-1); - // Use a selectable text area for the URI char uri_buf[1024]; strncpy(uri_buf, s_payment_uri.c_str(), sizeof(uri_buf) - 1); - ImGui::InputText("##URI", uri_buf, sizeof(uri_buf), ImGuiInputTextFlags_ReadOnly); + material::LabeledInput(TR("request_payment_uri"), "##URI", uri_buf, sizeof(uri_buf), + -1.0f, nullptr, ImGuiInputTextFlags_ReadOnly); ImGui::Spacing(); diff --git a/src/ui/windows/shield_dialog.cpp b/src/ui/windows/shield_dialog.cpp index 5b18f17..d351a18 100644 --- a/src/ui/windows/shield_dialog.cpp +++ b/src/ui/windows/shield_dialog.cpp @@ -95,9 +95,7 @@ void ShieldDialog::render(App* app) // From address (for shield coinbase) if (s_mode == Mode::ShieldCoinbase) { - ImGui::Text("%s", TR("shield_from_address")); - ImGui::SetNextItemWidth(-1); - ImGui::InputText("##FromAddr", s_from_address, sizeof(s_from_address)); + material::LabeledInput(TR("shield_from_address"), "##FromAddr", s_from_address, sizeof(s_from_address)); ImGui::TextDisabled("%s", TR("shield_wildcard_hint")); ImGui::Spacing(); } diff --git a/src/ui/windows/validate_address_dialog.cpp b/src/ui/windows/validate_address_dialog.cpp index 65f4eaf..09b5cfe 100644 --- a/src/ui/windows/validate_address_dialog.cpp +++ b/src/ui/windows/validate_address_dialog.cpp @@ -61,10 +61,9 @@ void ValidateAddressDialog::render(App* app) ImGui::Spacing(); // Address input - ImGui::Text("%s", TR("address_label")); - ImGui::SetNextItemWidth(-1); - bool enter_pressed = ImGui::InputText("##ValidateAddr", s_address_input, sizeof(s_address_input), - ImGuiInputTextFlags_EnterReturnsTrue); + bool enter_pressed = material::LabeledInput(TR("address_label"), "##ValidateAddr", s_address_input, + sizeof(s_address_input), -1.0f, nullptr, + ImGuiInputTextFlags_EnterReturnsTrue); ImGui::Spacing();