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.

This commit is contained in:
scawful
2025-04-17 21:33:20 -04:00
parent a267e18f46
commit c3d707901c
3 changed files with 138 additions and 95 deletions

View File

@@ -50,10 +50,10 @@ void MessageEditor::Initialize() {
all_dictionaries_ = BuildDictionaryEntries(rom()); all_dictionaries_ = BuildDictionaryEntries(rom());
ReadAllTextData(rom(), list_of_texts_); ReadAllTextData(rom(), list_of_texts_);
font_preview_colors_.AddColor(0x7FFF); // White font_preview_colors_.AddColor(gfx::SnesColor(0x7FFF)); // White
font_preview_colors_.AddColor(0x7C00); // Red font_preview_colors_.AddColor(gfx::SnesColor(0x7C00)); // Red
font_preview_colors_.AddColor(0x03E0); // Green font_preview_colors_.AddColor(gfx::SnesColor(0x03E0)); // Green
font_preview_colors_.AddColor(0x001F); // Blue font_preview_colors_.AddColor(gfx::SnesColor(0x001F)); // Blue
std::vector<uint8_t> data(0x4000, 0); std::vector<uint8_t> data(0x4000, 0);
for (int i = 0; i < 0x4000; i++) { for (int i = 0; i < 0x4000; i++) {
@@ -190,8 +190,8 @@ void MessageEditor::DrawCurrentMessage() {
ImGui::EndPopup(); ImGui::EndPopup();
} }
gui::BeginPadding(1); gui::BeginPadding(1);
BeginChild("CurrentGfxFont", ImVec2(200, 0), true, BeginChild("CurrentGfxFont", ImVec2(current_font_gfx16_bitmap_.width(), 0),
ImGuiWindowFlags_AlwaysVerticalScrollbar); true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
current_font_gfx16_canvas_.DrawBackground(); current_font_gfx16_canvas_.DrawBackground();
gui::EndPadding(); gui::EndPadding();
current_font_gfx16_canvas_.DrawContextMenu(); current_font_gfx16_canvas_.DrawContextMenu();

View File

@@ -2,9 +2,7 @@
#define YAZE_APP_EDITOR_MESSAGE_EDITOR_H #define YAZE_APP_EDITOR_MESSAGE_EDITOR_H
#include <array> #include <array>
#include <memory>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#include "absl/status/status.h" #include "absl/status/status.h"
@@ -12,6 +10,7 @@
#include "app/editor/message/message_data.h" #include "app/editor/message/message_data.h"
#include "app/gfx/bitmap.h" #include "app/gfx/bitmap.h"
#include "app/gui/canvas.h" #include "app/gui/canvas.h"
#include "app/gui/style.h"
#include "app/rom.h" #include "app/rom.h"
namespace yaze { namespace yaze {
@@ -113,62 +112,7 @@ class MessageEditor : public Editor {
gui::Canvas tile_editor_canvas_{"##TileEditorCanvas", ImVec2(256, 256)}; gui::Canvas tile_editor_canvas_{"##TileEditorCanvas", ImVec2(256, 256)};
gui::Canvas tile_preview_canvas_{"##TilePreviewCanvas", ImVec2(64, 64)}; gui::Canvas tile_preview_canvas_{"##TilePreviewCanvas", ImVec2(64, 64)};
struct TextBox { gui::TextBox message_text_box_;
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_;
absl::Status status_; absl::Status status_;
}; };

View File

@@ -1,6 +1,7 @@
#ifndef YAZE_APP_CORE_STYLE_H #ifndef YAZE_APP_CORE_STYLE_H
#define YAZE_APP_CORE_STYLE_H #define YAZE_APP_CORE_STYLE_H
#include <functional>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -71,54 +72,152 @@ void TextWithSeparators(const absl::string_view &text);
void DrawFontManager(); void DrawFontManager();
static const char *ExampleNames[] = { struct TextBox {
"Artichoke", "Arugula", "Asparagus", "Avocado", std::string text;
"Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", std::string buffer;
"Belgian Endive", "Bell Pepper", "Bitter Gourd", "Bok Choy", int cursor_pos = 0;
"Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", int selection_start = 0;
"Calabash", "Capers", "Carrot", "Cassava", int selection_end = 0;
"Cauliflower", "Celery", "Celery Root", "Celcuce", int selection_length = 0;
"Chayote", "Chinese Broccoli", "Corn", "Cucumber"}; bool has_selection = false;
bool has_focus = false;
bool changed = false;
bool can_undo = false;
struct MultiSelectWithClipper { void Undo() {
const int ITEMS_COUNT = 10000; text = buffer;
void Update() { cursor_pos = selection_start;
// Use default selection.Adapter: Pass index to has_selection = false;
// SetNextItemSelectionUserData(), store index in Selection }
static ImGuiSelectionBasicStorage selection; 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); // Generic multi-select component that can be used with different types of data
if (ImGui::BeginChild( template <typename T>
"##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), class MultiSelect {
ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) { public:
// Callback function type for rendering an item
using ItemRenderer =
std::function<void(int index, const T &item, bool is_selected)>;
// Constructor with optional title and default flags
MultiSelect(
const char *title = "Selection",
ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape |
ImGuiMultiSelectFlags_BoxSelect1d; ImGuiMultiSelectFlags_BoxSelect1d)
: title_(title), flags_(flags), selection_() {}
// Set the items to display
void SetItems(const std::vector<T> &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 = ImGuiMultiSelectIO *ms_io =
ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT); ImGui::BeginMultiSelect(flags_, selection_.Size, items_.size());
selection.ApplyRequests(ms_io); selection_.ApplyRequests(ms_io);
ImGuiListClipper clipper; ImGuiListClipper clipper;
clipper.Begin(ITEMS_COUNT); clipper.Begin(items_.size());
if (ms_io->RangeSrcItem != -1) if (ms_io->RangeSrcItem != -1)
clipper.IncludeItemByIndex( clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem);
(int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
while (clipper.Step()) { while (clipper.Step()) {
for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++) { for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++) {
char label[64]; bool item_is_selected = selection_.Contains((ImGuiID)n);
// sprintf(label, "Object %05d: %s", n,
// ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
bool item_is_selected = selection.Contains((ImGuiID)n);
ImGui::SetNextItemSelectionUserData(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(); ms_io = ImGui::EndMultiSelect();
selection.ApplyRequests(ms_io); selection_.ApplyRequests(ms_io);
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::TreePop();
} }
// Get the selected indices
std::vector<int> GetSelectedIndices() const {
std::vector<int> 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<T> items_;
ItemRenderer item_renderer_;
float height_in_font_units_ = 20.0f;
ImGuiChildFlags child_flags_ =
ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY;
}; };
} // namespace gui } // namespace gui