From c3d707901c94e4ba6584a0605bfdcb9752dd7f63 Mon Sep 17 00:00:00 2001 From: scawful Date: Thu, 17 Apr 2025 21:33:20 -0400 Subject: [PATCH] Refactor MessageEditor to utilize gfx::SnesColor for font preview colors and replace custom TextBox implementation with gui::TextBox for improved functionality; adjust child window dimensions dynamically based on current font bitmap size. --- src/app/editor/message/message_editor.cc | 12 +- src/app/editor/message/message_editor.h | 60 +-------- src/app/gui/style.h | 161 ++++++++++++++++++----- 3 files changed, 138 insertions(+), 95 deletions(-) diff --git a/src/app/editor/message/message_editor.cc b/src/app/editor/message/message_editor.cc index c8c019a6..b62cd7b8 100644 --- a/src/app/editor/message/message_editor.cc +++ b/src/app/editor/message/message_editor.cc @@ -50,10 +50,10 @@ void MessageEditor::Initialize() { all_dictionaries_ = BuildDictionaryEntries(rom()); ReadAllTextData(rom(), list_of_texts_); - font_preview_colors_.AddColor(0x7FFF); // White - font_preview_colors_.AddColor(0x7C00); // Red - font_preview_colors_.AddColor(0x03E0); // Green - font_preview_colors_.AddColor(0x001F); // Blue + font_preview_colors_.AddColor(gfx::SnesColor(0x7FFF)); // White + font_preview_colors_.AddColor(gfx::SnesColor(0x7C00)); // Red + font_preview_colors_.AddColor(gfx::SnesColor(0x03E0)); // Green + font_preview_colors_.AddColor(gfx::SnesColor(0x001F)); // Blue std::vector data(0x4000, 0); for (int i = 0; i < 0x4000; i++) { @@ -190,8 +190,8 @@ void MessageEditor::DrawCurrentMessage() { ImGui::EndPopup(); } gui::BeginPadding(1); - BeginChild("CurrentGfxFont", ImVec2(200, 0), true, - ImGuiWindowFlags_AlwaysVerticalScrollbar); + BeginChild("CurrentGfxFont", ImVec2(current_font_gfx16_bitmap_.width(), 0), + true, ImGuiWindowFlags_AlwaysVerticalScrollbar); current_font_gfx16_canvas_.DrawBackground(); gui::EndPadding(); current_font_gfx16_canvas_.DrawContextMenu(); diff --git a/src/app/editor/message/message_editor.h b/src/app/editor/message/message_editor.h index b9ae5694..c772d4a3 100644 --- a/src/app/editor/message/message_editor.h +++ b/src/app/editor/message/message_editor.h @@ -2,9 +2,7 @@ #define YAZE_APP_EDITOR_MESSAGE_EDITOR_H #include -#include #include -#include #include #include "absl/status/status.h" @@ -12,6 +10,7 @@ #include "app/editor/message/message_data.h" #include "app/gfx/bitmap.h" #include "app/gui/canvas.h" +#include "app/gui/style.h" #include "app/rom.h" namespace yaze { @@ -113,62 +112,7 @@ class MessageEditor : public Editor { gui::Canvas tile_editor_canvas_{"##TileEditorCanvas", ImVec2(256, 256)}; gui::Canvas tile_preview_canvas_{"##TilePreviewCanvas", ImVec2(64, 64)}; - struct TextBox { - std::string text; - std::string buffer; - int cursor_pos = 0; - int selection_start = 0; - int selection_end = 0; - int selection_length = 0; - bool has_selection = false; - bool has_focus = false; - bool changed = false; - bool can_undo = false; - - void Undo() { - text = buffer; - cursor_pos = selection_start; - has_selection = false; - } - void clearUndo() { can_undo = false; } - void Copy() { ImGui::SetClipboardText(text.c_str()); } - void Cut() { - Copy(); - text.erase(selection_start, selection_end - selection_start); - cursor_pos = selection_start; - has_selection = false; - changed = true; - } - void Paste() { - text.erase(selection_start, selection_end - selection_start); - text.insert(selection_start, ImGui::GetClipboardText()); - std::string str = ImGui::GetClipboardText(); - cursor_pos = selection_start + str.size(); - has_selection = false; - changed = true; - } - void clear() { - text.clear(); - buffer.clear(); - cursor_pos = 0; - selection_start = 0; - selection_end = 0; - selection_length = 0; - has_selection = false; - has_focus = false; - changed = false; - can_undo = false; - } - void SelectAll() { - selection_start = 0; - selection_end = text.size(); - selection_length = text.size(); - has_selection = true; - } - void Focus() { has_focus = true; } - }; - - TextBox message_text_box_; + gui::TextBox message_text_box_; absl::Status status_; }; diff --git a/src/app/gui/style.h b/src/app/gui/style.h index e5998ea1..afdc72b7 100644 --- a/src/app/gui/style.h +++ b/src/app/gui/style.h @@ -1,6 +1,7 @@ #ifndef YAZE_APP_CORE_STYLE_H #define YAZE_APP_CORE_STYLE_H +#include #include #include @@ -71,54 +72,152 @@ void TextWithSeparators(const absl::string_view &text); void DrawFontManager(); -static const char *ExampleNames[] = { - "Artichoke", "Arugula", "Asparagus", "Avocado", - "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", - "Belgian Endive", "Bell Pepper", "Bitter Gourd", "Bok Choy", - "Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", - "Calabash", "Capers", "Carrot", "Cassava", - "Cauliflower", "Celery", "Celery Root", "Celcuce", - "Chayote", "Chinese Broccoli", "Corn", "Cucumber"}; +struct TextBox { + std::string text; + std::string buffer; + int cursor_pos = 0; + int selection_start = 0; + int selection_end = 0; + int selection_length = 0; + bool has_selection = false; + bool has_focus = false; + bool changed = false; + bool can_undo = false; -struct MultiSelectWithClipper { - const int ITEMS_COUNT = 10000; - void Update() { - // Use default selection.Adapter: Pass index to - // SetNextItemSelectionUserData(), store index in Selection - static ImGuiSelectionBasicStorage selection; + void Undo() { + text = buffer; + cursor_pos = selection_start; + has_selection = false; + } + void clearUndo() { can_undo = false; } + void Copy() { ImGui::SetClipboardText(text.c_str()); } + void Cut() { + Copy(); + text.erase(selection_start, selection_end - selection_start); + cursor_pos = selection_start; + has_selection = false; + changed = true; + } + void Paste() { + text.erase(selection_start, selection_end - selection_start); + text.insert(selection_start, ImGui::GetClipboardText()); + std::string str = ImGui::GetClipboardText(); + cursor_pos = selection_start + str.size(); + has_selection = false; + changed = true; + } + void clear() { + text.clear(); + buffer.clear(); + cursor_pos = 0; + selection_start = 0; + selection_end = 0; + selection_length = 0; + has_selection = false; + has_focus = false; + changed = false; + can_undo = false; + } + void SelectAll() { + selection_start = 0; + selection_end = text.size(); + selection_length = text.size(); + has_selection = true; + } + void Focus() { has_focus = true; } +}; - ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT); - if (ImGui::BeginChild( - "##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), - ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) { +// Generic multi-select component that can be used with different types of data +template +class MultiSelect { + public: + // Callback function type for rendering an item + using ItemRenderer = + std::function; + + // Constructor with optional title and default flags + MultiSelect( + const char *title = "Selection", ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | - ImGuiMultiSelectFlags_BoxSelect1d; + ImGuiMultiSelectFlags_BoxSelect1d) + : title_(title), flags_(flags), selection_() {} + + // Set the items to display + void SetItems(const std::vector &items) { items_ = items; } + + // Set the renderer function for items + void SetItemRenderer(ItemRenderer renderer) { item_renderer_ = renderer; } + + // Set the height of the selection area (in font size units) + void SetHeight(float height_in_font_units = 20.0f) { + height_in_font_units_ = height_in_font_units; + } + + // Set the child window flags + void SetChildFlags(ImGuiChildFlags flags) { child_flags_ = flags; } + + // Update and render the multi-select component + void Update() { + ImGui::Text("%s: %d/%d", title_, selection_.Size, items_.size()); + + if (ImGui::BeginChild( + "##MultiSelectChild", + ImVec2(-FLT_MIN, ImGui::GetFontSize() * height_in_font_units_), + child_flags_)) { ImGuiMultiSelectIO *ms_io = - ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT); - selection.ApplyRequests(ms_io); + ImGui::BeginMultiSelect(flags_, selection_.Size, items_.size()); + selection_.ApplyRequests(ms_io); ImGuiListClipper clipper; - clipper.Begin(ITEMS_COUNT); + clipper.Begin(items_.size()); if (ms_io->RangeSrcItem != -1) - clipper.IncludeItemByIndex( - (int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped. + clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); + while (clipper.Step()) { for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++) { - char label[64]; - // sprintf(label, "Object %05d: %s", n, - // ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]); - bool item_is_selected = selection.Contains((ImGuiID)n); + bool item_is_selected = selection_.Contains((ImGuiID)n); ImGui::SetNextItemSelectionUserData(n); - ImGui::Selectable(label, item_is_selected); + + if (item_renderer_) { + item_renderer_(n, items_[n], item_is_selected); + } else { + // Default rendering if no custom renderer is provided + char label[64]; + snprintf(label, sizeof(label), "Item %d", n); + ImGui::Selectable(label, item_is_selected); + } } } ms_io = ImGui::EndMultiSelect(); - selection.ApplyRequests(ms_io); + selection_.ApplyRequests(ms_io); } ImGui::EndChild(); - ImGui::TreePop(); } + + // Get the selected indices + std::vector GetSelectedIndices() const { + std::vector indices; + for (int i = 0; i < items_.size(); i++) { + if (selection_.Contains((ImGuiID)i)) { + indices.push_back(i); + } + } + return indices; + } + + // Clear the selection + void ClearSelection() { selection_.Clear(); } + + private: + const char *title_; + ImGuiMultiSelectFlags flags_; + ImGuiSelectionBasicStorage selection_; + std::vector items_; + ItemRenderer item_renderer_; + float height_in_font_units_ = 20.0f; + ImGuiChildFlags child_flags_ = + ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY; }; } // namespace gui