refactor(ui): extract MapPropertiesDialog into MapPropertiesPanel#29
Conversation
Extracted map property editing logic into a reusable `MapPropertiesPanel` to unify UI patterns with `NewMapPanel` and added client version registry support. Improved dialog layout by using child containers for better space management and added support for escaping the dialog. - `ImguiMapEditor/Application/CallbackMediator.cpp` — injected version registry into `map_properties` dialog - `ImguiMapEditor/CMakeLists.txt` — added `MapPropertiesPanel.cpp` to build - `ImguiMapEditor/UI/Dialogs/NewMapDialog.cpp` — improved modal layout using `BeginChild` and added Escape key handler - `ImguiMapEditor/UI/Dialogs/Properties/MapPropertiesDialog.cpp` — refactored to use `MapPropertiesPanel` and added support for disabling on SEC maps - `ImguiMapEditor/UI/Dialogs/Properties/MapPropertiesDialog.h` — updated to use `MapPropertiesPanel` component - `ImguiMapEditor/UI/Panels/MapPropertiesPanel.cpp` — implemented new panel for rendering and managing map properties - `ImguiMapEditor/UI/Panels/MapPropertiesPanel.h` — defined interface for `MapPropertiesPanel` - `ImguiMapEditor/UI/Panels/NewMapPanel.cpp` — updated child container borders and height configuration
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request refactors the map property editing logic by introducing a dedicated MapPropertiesPanel. This change standardizes the UI across the editor, improves space management within dialogs, and adds necessary support for client versioning and better keyboard interaction. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughThis pull request refactors map-properties UI handling by extracting it into a reusable 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Reviewer's GuideRefactors the map properties dialog to delegate property rendering to a new reusable MapPropertiesPanel (shared layout patterns with NewMapPanel), injects the client version registry for richer version display, and unifies modal layouts (child containers, fixed button footer, Escape handling) in the New Map and Map Properties dialogs while adding SEC-map restrictions. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| ErrorProne | 6 medium |
| Complexity | 1 medium |
🟢 Metrics 7 complexity · 9 duplication
Metric Results Complexity 7 Duplication 9
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
📋 Review Summary
The PR refactors the map properties UI logic into a reusable MapPropertiesPanel, which improves code modularity and aligns it with the NewMapPanel pattern. The addition of SEC map validation and the Escape key handler are great UX improvements.
🔍 General Feedback
- Regression: The most critical issue is the loss of map resizing functionality. The UI fields for Width/Height are now disabled, and the code that applies these changes to the map has been removed.
- C++20 Dependency: The use of
std::formatintroduces a dependency on C++20. Please confirm if the project has officially moved to C++20. - Version Matching: Double-check the argument order in
registry_->findBestMatch. It currently passes(minor, major), which is unconventional.
Overall, the refactoring is clean, but the regression in functionality should be addressed.
| map_->setSize(static_cast<uint16_t>(width_), static_cast<uint16_t>(height_)); | ||
| map_->setHouseFile(house_filename_); | ||
| map_->setSpawnFile(spawn_filename_); | ||
| map_->setDescription(state_.description); |
There was a problem hiding this comment.
🔴 Regression: The map resizing functionality has been removed. In the previous implementation, map_->setSize was called in applyToMap. In the refactored version, the size fields are read-only in the UI and the call to setSize is missing.
If resizing is intended to be supported, these fields should be enabled in MapPropertiesPanel and the values applied here.
| auto *cv = registry_->findBestMatch(ver.items_minor_version, | ||
| ver.items_major_version); | ||
| if (cv) { | ||
| s.client_version_name = |
There was a problem hiding this comment.
🟡 Compatibility: std::format is a C++20 feature. If the project is targeting an older standard (like C++17), this will cause build failures. Please ensure the compiler flags are updated to C++20 or use std::string concatenation / std::stringstream / fmt library if C++20 is not yet adopted.
| ImGui::BeginDisabled(); | ||
| ImGui::TextColored(label, "Size"); | ||
| ImGui::SameLine(90); | ||
| ImGui::TextColored(label, "X"); |
There was a problem hiding this comment.
🟡 The map size fields are marked as read-only here (BeginDisabled). As noted in the dialog's applyToMap, this prevents users from resizing existing maps, which was possible before this refactor.
| } | ||
| } | ||
|
|
||
| if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { |
There was a problem hiding this comment.
🟢 Good addition of the Escape key handler to improve UX consistency across dialogs.
| ImGui::SetTooltip( | ||
| "External XML file for spawn data (e.g., map-spawns.xml)"); | ||
| } | ||
| constexpr float PROPERTIES_DIALOG_H = Config::UI::NEW_MAP_DIALOG_H + 50.0f; |
There was a problem hiding this comment.
🟡 FLT_MAX requires <cfloat> or <float.h>. Consider using std::numeric_limits<float>::max() from <limits> for a more modern C++ approach, or ensure the header is included.
| is_open_ = false; | ||
| } | ||
| } else { | ||
| // Content area: fill all space minus footer |
There was a problem hiding this comment.
🟢 The addition of this check for SEC maps is a good safety measure since they don't support metadata properties.
| s.items_minor = ver.items_minor_version; | ||
|
|
||
| if (registry_) { | ||
| auto *cv = registry_->findBestMatch(ver.items_minor_version, |
There was a problem hiding this comment.
🟡 Please verify the parameter order for findBestMatch. Usually, version lookups take (major, minor), but here it is called with (minor, major).
auto *cv = registry_->findBestMatch(ver.items_minor_version, ver.items_major_version);There was a problem hiding this comment.
Code Review
This pull request refactors the map properties dialog by introducing a reusable MapPropertiesPanel to handle the rendering and state management of map metadata, and updates the layout of the new map dialog to use child windows. Feedback on the changes highlights two key improvements in MapPropertiesPanel.cpp: first, avoiding string copies of the map description inside the render loop to prevent heap allocations, which violates the project's no-allocation zone guidelines; and second, ensuring a fallback client version name is set when the version registry is null to prevent empty fields in the UI.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| auto desc_before = state.description; | ||
| ImGui::InputTextMultiline("##desc", &state.description, | ||
| ImVec2(-1, ImGui::GetContentRegionAvail().y - 1), | ||
| ImGuiInputTextFlags_None); | ||
| if (state.description != desc_before) | ||
| changed = true; |
There was a problem hiding this comment.
Avoid copying state.description on every frame to check for changes. This introduces unnecessary heap allocations in the render loop, violating the NO-ALLOCATION ZONE guideline. Instead, leverage the return value of ImGui::InputTextMultiline, which returns true when the text is modified.
if (ImGui::InputTextMultiline("##desc", &state.description,
ImVec2(-1, ImGui::GetContentRegionAvail().y - 1),
ImGuiInputTextFlags_None)) {
changed = true;
}References
- The render loop is a no-allocation zone. Avoid heap allocations such as copying strings on every frame. (link)
| if (registry_) { | ||
| auto *cv = registry_->findBestMatch(ver.items_minor_version, | ||
| ver.items_major_version); | ||
| if (cv) { | ||
| s.client_version_name = | ||
| std::format("{} ({})", cv->getName(), cv->getVersion()); | ||
| } else { | ||
| s.client_version_name = | ||
| std::format("Unknown (v{})", ver.client_version); | ||
| } | ||
| } |
There was a problem hiding this comment.
If registry_ is null, s.client_version_name is left empty, which will display as an empty read-only field in the UI. We should always provide a fallback value (e.g., Unknown (v...)) and simplify the logic.
s.client_version_name = std::format("Unknown (v{})", ver.client_version);
if (registry_) {
if (auto *cv = registry_->findBestMatch(ver.items_minor_version,
ver.items_major_version)) {
s.client_version_name =
std::format("{} ({})", cv->getName(), cv->getVersion());
}
}There was a problem hiding this comment.
Pull Request Overview
This PR refactors map property editing into a reusable panel but introduces a critical regression: map resizing (Width/Height) functionality has been removed. While the UI layout has been improved and new features like the Client Version Registry and Escape key support have been added, the implementation does not yet meet quality standards due to significant code duplication (9 new clones) and 7 new issues flagged by static analysis. Most notably, the intended unification of UI patterns resulted in duplicated code rather than shared logic between the new MapPropertiesPanel and NewMapPanel. These issues, particularly the regression in map resizing, should be addressed before merging.
About this PR
- The refactor has removed the ability to resize maps. In the previous implementation, the Width and Height fields were editable and persisted via
map_->setSize(). In the current version, these fields are read-only and the persistence logic is missing. This functionality must be restored or the removal explicitly justified. - No new or updated unit tests were included to verify the logic of the MapPropertiesPanel, the client version resolution, or the SEC map detection logic. Adding automated tests for these areas is recommended to prevent future regressions.
Test suggestions
- Missing recommended test scenario: MapPropertiesPanel correctly populates its state from a ChunkedMap including version resolution via the registry.
- Missing recommended test scenario: MapPropertiesPanel marks description and external file fields as editable while keeping version/size metadata read-only.
- Missing recommended test scenario: MapPropertiesDialog correctly identifies SEC maps by file extension and displays the 'not supported' warning.
- Missing recommended test scenario: Pressing the Escape key inside the NewMapDialog modal closes the popup and resets state.
- Missing recommended test scenario: Clicking 'OK' in MapPropertiesDialog correctly persists description and external file paths back to the ChunkedMap instance.
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Missing recommended test scenario: MapPropertiesPanel correctly populates its state from a ChunkedMap including version resolution via the registry.
2. Missing recommended test scenario: MapPropertiesPanel marks description and external file fields as editable while keeping version/size metadata read-only.
3. Missing recommended test scenario: MapPropertiesDialog correctly identifies SEC maps by file extension and displays the 'not supported' warning.
4. Missing recommended test scenario: Pressing the Escape key inside the NewMapDialog modal closes the popup and resets state.
5. Missing recommended test scenario: Clicking 'OK' in MapPropertiesDialog correctly persists description and external file paths back to the ChunkedMap instance.
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| if (!map_) | ||
| return; | ||
|
|
||
| map_->setDescription(description_buffer_); | ||
| map_->setSize(static_cast<uint16_t>(width_), static_cast<uint16_t>(height_)); | ||
| map_->setHouseFile(house_filename_); | ||
| map_->setSpawnFile(spawn_filename_); | ||
| map_->setDescription(state_.description); |
There was a problem hiding this comment.
🔴 HIGH RISK
This refactor removes the map resizing feature. The width and height inputs are now disabled in the UI, and the corresponding map_->setSize() call was removed from applyToMap(). If this was not intentional, please re-enable the inputs and restore the call to setSize.
| ImGui::Spacing(); | ||
|
|
||
| // ---- Size (read-only) ---- | ||
| ImGui::BeginDisabled(); |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Map size editing (Width/Height) has been disabled in this refactor. If this was intentional, it should be noted in the PR description; otherwise, it is a regression from the previous dialog behavior.
| return s; | ||
| } | ||
|
|
||
| bool MapPropertiesPanel::render(State &state) { |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: The render method is becoming monolithic as it handles multiple distinct property groups (Metadata, Version, Sizes, External Files, and Description). Breaking this down into private helper methods for the left and right columns would improve testability and readability.
| auto desc_before = state.description; | ||
| ImGui::InputTextMultiline("##desc", &state.description, | ||
| ImVec2(-1, ImGui::GetContentRegionAvail().y - 1), | ||
| ImGuiInputTextFlags_None); | ||
| if (state.description != desc_before) | ||
| changed = true; |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: Creating a copy of the description string (desc_before) every frame is inefficient for potential performance and memory. Since ImGui::InputTextMultiline returns true when the input changes, you can use its return value directly to trigger updates instead of performing a manual string comparison.
| ImGuiWindowFlags_None)) { | ||
|
|
||
| bool is_otbm = map_ && | ||
| std::filesystem::path(map_->getFilename()).extension() == ".otbm"; |
There was a problem hiding this comment.
🟡 MEDIUM RISK
Suggestion: The OTBM format check (checking file extension) is performed every frame during rendering. Since the map type does not change while the dialog is open, this should be calculated once in the show() method and stored in a boolean member variable to reduce overhead.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ImguiMapEditor/UI/Panels/MapPropertiesPanel.cpp`:
- Around line 37-47: The code only sets s.client_version_name when registry_ is
non-null and a match is found, leaving s.client_version_name empty if registry_
is null; add an else branch for the registry_ check that assigns
s.client_version_name (e.g., std::format("Unknown (v{})", ver.client_version))
so the ImGui InputText for state.client_version_name always has a fallback; keep
the existing findBestMatch(ver.items_minor_version, ver.items_major_version)
call as-is and update the block around registry_, findBestMatch,
s.client_version_name and ver.client_version accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2afcf74a-190f-40c5-9382-27c3376aaf7a
📒 Files selected for processing (8)
ImguiMapEditor/Application/CallbackMediator.cppImguiMapEditor/CMakeLists.txtImguiMapEditor/UI/Dialogs/NewMapDialog.cppImguiMapEditor/UI/Dialogs/Properties/MapPropertiesDialog.cppImguiMapEditor/UI/Dialogs/Properties/MapPropertiesDialog.hImguiMapEditor/UI/Panels/MapPropertiesPanel.cppImguiMapEditor/UI/Panels/MapPropertiesPanel.hImguiMapEditor/UI/Panels/NewMapPanel.cpp
Simplified description input change detection in map panels and streamlined client version naming logic in properties. Replaced manual state comparison with return-value checking for ImGui inputs and consolidated version formatting defaults. - `ImguiMapEditor/UI/Panels/MapPropertiesPanel.cpp` — initialized client_version_name before lookup, simplified InputTextMultiline change detection - `ImguiMapEditor/UI/Panels/NewMapPanel.cpp` — simplified InputTextMultiline change detection using function return value
| } | ||
| } | ||
|
|
||
| if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { |
There was a problem hiding this comment.
🟢 Great addition! Adding Escape key support improves the UX consistency for modal dialogs.
| ImGui::BeginDisabled(); | ||
| ImGui::TextColored(label, "Size"); | ||
| ImGui::SameLine(90); | ||
| ImGui::TextColored(label, "X"); |
There was a problem hiding this comment.
🟠 Regression: Map size fields are now read-only. In the previous implementation, they were editable. If editing map dimensions should still be supported, these fields should be enabled and the state updated.
| ImGui::SameLine(0, 8); | ||
| ImGui::SetNextItemWidth(80); | ||
| int h = state.map_height; | ||
| ImGui::InputInt("##h", &h, 0, 0); |
There was a problem hiding this comment.
🟡 Potential UI Bug: ImGui::InputInt is used with a local temporary int w. If this field were enabled, changes would be lost as they are not written back to state.map_width. Also, since map_width is uint16_t, it's safer to use ImGui::InputScalar with ImGuiDataType_U16 or update the state explicitly after the call.
Since it's currently disabled, this is only a "dormant" bug.
| strncpy(spawn_filename_, map_->getSpawnFile().c_str(), | ||
| sizeof(spawn_filename_) - 1); | ||
| spawn_filename_[sizeof(spawn_filename_) - 1] = '\0'; | ||
| return result; |
There was a problem hiding this comment.
🟠 Regression: Map width and height are no longer applied to the map. Previously, map_->setSize was called here. Is this removal intentional?
| return result; | |
| map_->setDescription(state_.description); | |
| map_->setSize(state_.map_width, state_.map_height); | |
| map_->setHouseFile(state_.house_file); |
| if (ImGui::Button("Close", ImVec2(button_width, 0))) { | ||
| result = Result::Cancelled; | ||
| ImGui::CloseCurrentPopup(); | ||
| is_open_ = false; |
There was a problem hiding this comment.
🟢 Good safety check. Note that map_->getFilename() might return an empty string for a new map that hasn't been saved yet. However, since map properties are mostly relevant for loaded OTBM files, this is likely fine for now.
Extracted map property editing logic into a reusable
MapPropertiesPanelto unify UI patterns withNewMapPaneland added client version registry support. Improved dialog layout by using child containers for better space management and added support for escaping the dialog.ImguiMapEditor/Application/CallbackMediator.cpp— injected version registry intomap_propertiesdialogImguiMapEditor/CMakeLists.txt— addedMapPropertiesPanel.cppto buildImguiMapEditor/UI/Dialogs/NewMapDialog.cpp— improved modal layout usingBeginChildand added Escape key handlerImguiMapEditor/UI/Dialogs/Properties/MapPropertiesDialog.cpp— refactored to useMapPropertiesPaneland added support for disabling on SEC mapsImguiMapEditor/UI/Dialogs/Properties/MapPropertiesDialog.h— updated to useMapPropertiesPanelcomponentImguiMapEditor/UI/Panels/MapPropertiesPanel.cpp— implemented new panel for rendering and managing map propertiesImguiMapEditor/UI/Panels/MapPropertiesPanel.h— defined interface forMapPropertiesPanelImguiMapEditor/UI/Panels/NewMapPanel.cpp— updated child container borders and height configurationSummary by CodeRabbit
New Features
Bug Fixes
Refactor
Chores