diff --git a/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj b/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj index 20ef2cfd5a2..e8857e7e27b 100644 --- a/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj +++ b/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj @@ -824,6 +824,10 @@ 91AF556D281101C4007A7652 /* input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF556C281101C3007A7652 /* input.cpp */; }; 91AF55B02827588B007A7652 /* texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF55AF2827588B007A7652 /* texture.cpp */; }; 91AF55DF2848472F007A7652 /* draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF55DE2848472F007A7652 /* draw.cpp */; }; + 91AF564F284D8A8B007A7652 /* walker_container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF5649284D88DA007A7652 /* walker_container.cpp */; }; + 91AF5654284D90ED007A7652 /* walker_container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF5649284D88DA007A7652 /* walker_container.cpp */; }; + 91AF565B284D9251007A7652 /* walker_scrollbar_container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF5659284D9251007A7652 /* walker_scrollbar_container.cpp */; }; + 91AF565C284D9251007A7652 /* walker_scrollbar_container.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AF5659284D9251007A7652 /* walker_scrollbar_container.cpp */; }; 91B621A21B76A3CC00B00E0F /* build_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B621A11B76A3CC00B00E0F /* build_info.cpp */; }; 91B621BA1B76B2C900B00E0F /* version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B621B91B76B2C900B00E0F /* version.cpp */; }; 91B6220A1B76C0A600B00E0F /* libcairo.2.dylib in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = B513B2270ED36BFB0006E551 /* libcairo.2.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; @@ -2141,6 +2145,10 @@ 91AF55AF2827588B007A7652 /* texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texture.cpp; sourceTree = ""; }; 91AF55DD2848472E007A7652 /* draw.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = draw.hpp; sourceTree = ""; }; 91AF55DE2848472F007A7652 /* draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = draw.cpp; sourceTree = ""; }; + 91AF5649284D88DA007A7652 /* walker_container.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = walker_container.cpp; sourceTree = ""; }; + 91AF564A284D88DA007A7652 /* walker_container.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = walker_container.hpp; sourceTree = ""; }; + 91AF5659284D9251007A7652 /* walker_scrollbar_container.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = walker_scrollbar_container.cpp; sourceTree = ""; }; + 91AF565A284D9251007A7652 /* walker_scrollbar_container.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = walker_scrollbar_container.hpp; sourceTree = ""; }; 91B621801B766ED500B00E0F /* buffered_istream.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = buffered_istream.hpp; sourceTree = ""; }; 91B621811B766F1900B00E0F /* carryover.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = carryover.hpp; sourceTree = ""; }; 91B621821B766FD200B00E0F /* display_context.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = display_context.hpp; sourceTree = ""; }; @@ -3773,8 +3781,12 @@ 46F92D0A2174F6A300602C1C /* iterator.hpp */, 46F92D072174F6A300602C1C /* policy_order.hpp */, 46F92D032174F6A300602C1C /* policy_visit.hpp */, + 91AF5649284D88DA007A7652 /* walker_container.cpp */, + 91AF564A284D88DA007A7652 /* walker_container.hpp */, 46F92D052174F6A300602C1C /* walker_grid.cpp */, 46F92D0C2174F6A300602C1C /* walker_grid.hpp */, + 91AF5659284D9251007A7652 /* walker_scrollbar_container.cpp */, + 91AF565A284D9251007A7652 /* walker_scrollbar_container.hpp */, 46F92D012174F6A300602C1C /* walker_tree_node.cpp */, 46F92D082174F6A300602C1C /* walker_tree_node.hpp */, 46F92D092174F6A300602C1C /* walker_widget.cpp */, @@ -5347,6 +5359,7 @@ 46F92EDC2174FD9900602C1C /* scrollarea.cpp in Sources */, ECA1E0F21A1271AC00426E00 /* lua_gui2.cpp in Sources */, 46F92D872174F6A300602C1C /* horizontal_list.cpp in Sources */, + 91AF564F284D8A8B007A7652 /* walker_container.cpp in Sources */, EC5401851EBE0C4500AE66EE /* display.cpp in Sources */, 46F92C1E2174F5D700602C1C /* help.cpp in Sources */, F4D5483E15198D060058C8A7 /* lua_jailbreak_exception.cpp in Sources */, @@ -5481,6 +5494,7 @@ B559986C0EC616B3008DD061 /* SDLMain.mm in Sources */, EC64D7611A085CE60092EF75 /* seed_rng.cpp in Sources */, B5599B030EC62181008DD061 /* map_settings.cpp in Sources */, + 91AF565B284D9251007A7652 /* walker_scrollbar_container.cpp in Sources */, 46F92C1A2174F5D700602C1C /* help_text_area.cpp in Sources */, 46F92DC12174F6A300602C1C /* game_version_dialog.cpp in Sources */, ECAB84551B0C1934001A3EB7 /* shroud_clearing_action.cpp in Sources */, @@ -5802,6 +5816,7 @@ 46F92EE42174FDA600602C1C /* menu.cpp in Sources */, 91E356691CACC6E000774252 /* mouse_events.cpp in Sources */, 91E3566A1CACC6E000774252 /* mouse_handler_base.cpp in Sources */, + 91AF565C284D9251007A7652 /* walker_scrollbar_container.cpp in Sources */, 46F92EEB2174FDAB00602C1C /* widget.cpp in Sources */, 91E3566B1CACC6E000774252 /* movetype.cpp in Sources */, 91E3566C1CACC6E000774252 /* mp_game_settings.cpp in Sources */, @@ -6084,6 +6099,7 @@ 91A214FA1CAD66B900927AEA /* hotkey_manager.cpp in Sources */, 46F92D802174F6A300602C1C /* static_registry.cpp in Sources */, 91A214FB1CAD66CC00927AEA /* picture.cpp in Sources */, + 91AF5654284D90ED007A7652 /* walker_container.cpp in Sources */, 91A214FC1CAD66CC00927AEA /* image_modifications.cpp in Sources */, 4649B88420288DFB00827CFB /* game.cpp in Sources */, 46F92E322174F6A400602C1C /* custom_tod.cpp in Sources */, diff --git a/source_lists/wesnoth b/source_lists/wesnoth index 929687480bd..fef0bfae825 100644 --- a/source_lists/wesnoth +++ b/source_lists/wesnoth @@ -142,7 +142,9 @@ game_initialization/singleplayer.cpp game_launcher.cpp game_state.cpp gui/auxiliary/iterator/iterator.cpp +gui/auxiliary/iterator/walker_container.cpp gui/auxiliary/iterator/walker_grid.cpp +gui/auxiliary/iterator/walker_scrollbar_container.cpp gui/auxiliary/iterator/walker_tree_node.cpp gui/auxiliary/iterator/walker_widget.cpp gui/auxiliary/tips.cpp diff --git a/src/gui/auxiliary/iterator/policy_order.hpp b/src/gui/auxiliary/iterator/policy_order.hpp index b66b20c8c7f..0ff15507ef3 100644 --- a/src/gui/auxiliary/iterator/policy_order.hpp +++ b/src/gui/auxiliary/iterator/policy_order.hpp @@ -198,6 +198,7 @@ public: bool at_end() const { + if(!root_) return true; return visit_widget::at_end(*root_) && visit_grid::at_end(*root_) && visit_child::at_end(*root_); } @@ -266,8 +267,8 @@ public: stack_.push_back(std::exchange(root_, visit_child::get(*root_)->create_walker())); assert(root_); - assert(!at_end()); TST_GUI_I << " Down and visit '" << operator*().id() << "'.\n"; + if(at_end()) up(); return true; } diff --git a/src/gui/auxiliary/iterator/walker_container.cpp b/src/gui/auxiliary/iterator/walker_container.cpp new file mode 100644 index 00000000000..4a7a0dfaf20 --- /dev/null +++ b/src/gui/auxiliary/iterator/walker_container.cpp @@ -0,0 +1,101 @@ +/* + Copyright (C) 2011 - 2022 + by Mark de Wever + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#define GETTEXT_DOMAIN "wesnoth-lib" + +#include "gui/auxiliary/iterator/walker_container.hpp" + +#include + +namespace gui2::iteration +{ + +container::container(gui2::container_base& container) + : container_(container), widget_(&container), itor_(container.begin()) +{ +} + +walker_base::state_t container::next(const level level) +{ + if(at_end(level)) { + return fail; + } + + switch(level) { + case self: + if(widget_) { + widget_ = nullptr; + return invalid; + } + assert(false); + return fail; + case internal: + if(!entered_grid) { + entered_grid = true; + in_grid = true; + return valid; + } + if(in_grid) { + in_grid = false; + return invalid; + } + assert(false); + return fail; + case child: + if(itor_ != container_.end()) { + ++itor_; + return itor_ == container_.end() ? invalid : valid; + } + } + + assert(false); + return fail; +} + +bool container::at_end(const level level) const +{ + switch(level) { + case self: + return widget_ == nullptr; + case internal: + return entered_grid && !in_grid; + case child: + return (itor_ == container_.end()); + } + + assert(false); + return true; +} + +gui2::widget* container::get(const level level) +{ + switch(level) { + case self: + return widget_; + case internal: + return &container_.get_grid(); + case child: + if(itor_ == container_.end()) { + return nullptr; + } else { + return *itor_; + } + } + + assert(false); + return nullptr; +} + +} // namespace gui2::iteration diff --git a/src/gui/auxiliary/iterator/walker_container.hpp b/src/gui/auxiliary/iterator/walker_container.hpp new file mode 100644 index 00000000000..f4e7fed45db --- /dev/null +++ b/src/gui/auxiliary/iterator/walker_container.hpp @@ -0,0 +1,74 @@ +/* + Copyright (C) 2011 - 2022 + by Mark de Wever + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#pragma once + +#include "gui/auxiliary/iterator/walker.hpp" + +#include "gui/widgets/container_base.hpp" + +namespace gui2::iteration +{ + +/** A walker for a @ref gui2::container_base. */ +class container : public walker_base +{ +public: + /** + * Constructor. + * + * @param grid The grid which the walker is attached to. + */ + explicit container(gui2::container_base& container); + + /** Inherited from @ref gui2::iteration::walker_base. */ + virtual state_t next(const level level); + + /** Inherited from @ref gui2::iteration::walker_base. */ + virtual bool at_end(const level level) const; + + /** Inherited from @ref gui2::iteration::walker_base. */ + virtual gui2::widget* get(const level level); + +private: + /** The container which the walker is attached to. */ + gui2::container_base& container_; + + /** + * The widget which the walker is attached to. + * + * This variable is used to track whether the + * gui2::iteration::walker_base::widget level has been visited. + */ + gui2::widget* widget_; + + /** + * Whether the grid has been yielded + * + * This variable is used to track whether the + * gui2::iteration::walker_base::internal level has been visited. + */ + bool entered_grid = false, in_grid = false; + + /** + * The iterator to the children of @ref container_. + * + * This variable is used to track where the + * gui2::iteration::walker_base::child level visiting is. + */ + gui2::grid::iterator itor_; +}; + +} // namespace gui2::iteration diff --git a/src/gui/auxiliary/iterator/walker_scrollbar_container.cpp b/src/gui/auxiliary/iterator/walker_scrollbar_container.cpp new file mode 100644 index 00000000000..6862f36991b --- /dev/null +++ b/src/gui/auxiliary/iterator/walker_scrollbar_container.cpp @@ -0,0 +1,111 @@ +/* + Copyright (C) 2011 - 2022 + by Mark de Wever + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#define GETTEXT_DOMAIN "wesnoth-lib" + +#include "gui/auxiliary/iterator/walker_scrollbar_container.hpp" + +#include + +namespace gui2::iteration +{ + +scrollbar_container::scrollbar_container(gui2::scrollbar_container& container) + : container_(container), widget_(&container), itor_(container.begin()) +{ +} + +walker_base::state_t scrollbar_container::next(const level level) +{ + if(at_end(level)) { + return fail; + } + + switch(level) { + case self: + if(widget_) { + widget_ = nullptr; + return invalid; + } + assert(false); + return fail; + case internal: + if(!entered_grid) { + entered_grid = true; + in_grid = true; + return valid; + } + if(in_grid) { + ++itor_; + if(itor_ == container_.end()) { + in_grid = false; + entered_children = true; + itor_ = container_.content_grid()->begin(); + return invalid; + } + return valid; + } + assert(false); + return fail; + case child: + if(itor_ != container_.content_grid()->end()) { + ++itor_; + return itor_ == container_.content_grid()->end() ? invalid : valid; + } + } + + assert(false); + return fail; +} + +bool scrollbar_container::at_end(const level level) const +{ + switch(level) { + case self: + return widget_ == nullptr; + case internal: + return entered_grid && !in_grid; + case child: + return entered_children && (itor_ == container_.content_grid()->end()); + } + + assert(false); + return true; +} + +gui2::widget* scrollbar_container::get(const level level) +{ + switch(level) { + case self: + return widget_; + case internal: + if(!in_grid || itor_ == container_.end()) { + return nullptr; + } else { + return *itor_; + } + case child: + if(!entered_children || itor_ == container_.content_grid()->end()) { + return nullptr; + } else { + return *itor_; + } + } + + assert(false); + return nullptr; +} + +} // namespace gui2::iteration diff --git a/src/gui/auxiliary/iterator/walker_scrollbar_container.hpp b/src/gui/auxiliary/iterator/walker_scrollbar_container.hpp new file mode 100644 index 00000000000..549681dd37a --- /dev/null +++ b/src/gui/auxiliary/iterator/walker_scrollbar_container.hpp @@ -0,0 +1,75 @@ +/* + Copyright (C) 2011 - 2022 + by Mark de Wever + Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#pragma once + +#include "gui/auxiliary/iterator/walker.hpp" + +#include "gui/widgets/scrollbar_container.hpp" + +namespace gui2::iteration +{ + +/** A walker for a @ref gui2::container_base. */ +class scrollbar_container : public walker_base +{ +public: + /** + * Constructor. + * + * @param grid The grid which the walker is attached to. + */ + explicit scrollbar_container(gui2::scrollbar_container& container); + + /** Inherited from @ref gui2::iteration::walker_base. */ + virtual state_t next(const level level); + + /** Inherited from @ref gui2::iteration::walker_base. */ + virtual bool at_end(const level level) const; + + /** Inherited from @ref gui2::iteration::walker_base. */ + virtual gui2::widget* get(const level level); + +private: + /** The container which the walker is attached to. */ + gui2::scrollbar_container& container_; + + /** + * The widget which the walker is attached to. + * + * This variable is used to track whether the + * gui2::iteration::walker_base::widget level has been visited. + */ + gui2::widget* widget_; + + /** + * Whether the grid has been yielded + * + * This variable is used to track whether the + * gui2::iteration::walker_base::internal level has been visited. + */ + bool entered_grid = false, in_grid = false, entered_children = false; + + /** + * The iterator to the children of @ref container_. + * + * This variable is used to track where the + * gui2::iteration::walker_base::child level and + * gui2::iteration::walker_base::internal level visiting is. + */ + gui2::grid::iterator itor_; +}; + +} // namespace gui2::iteration diff --git a/src/gui/widgets/container_base.cpp b/src/gui/widgets/container_base.cpp index 2d372d83e3b..dea3ae051e4 100644 --- a/src/gui/widgets/container_base.cpp +++ b/src/gui/widgets/container_base.cpp @@ -17,7 +17,7 @@ #include "gui/widgets/container_base.hpp" -#include "gui/auxiliary/iterator/walker.hpp" +#include "gui/auxiliary/iterator/walker_container.hpp" #include "gui/core/log.hpp" #include "gui/widgets/window.hpp" @@ -264,7 +264,7 @@ bool container_base::disable_click_dismiss() const iteration::walker_ptr container_base::create_walker() { - return nullptr; + return std::make_unique(*this); } void container_base::init_grid(const builder_grid& grid_builder) diff --git a/src/gui/widgets/container_base.hpp b/src/gui/widgets/container_base.hpp index 7ac879abf80..9bd3834b15c 100644 --- a/src/gui/widgets/container_base.hpp +++ b/src/gui/widgets/container_base.hpp @@ -143,8 +143,6 @@ public: /** * See @ref widget::create_walker. - * - * @todo Implement properly. */ virtual iteration::walker_ptr create_walker() override; diff --git a/src/gui/widgets/scrollbar_container.cpp b/src/gui/widgets/scrollbar_container.cpp index 333f710d2c8..8ed9754da59 100644 --- a/src/gui/widgets/scrollbar_container.cpp +++ b/src/gui/widgets/scrollbar_container.cpp @@ -18,6 +18,7 @@ #include "gui/widgets/scrollbar_container_private.hpp" #include "gui/auxiliary/find_widget.hpp" +#include "gui/auxiliary/iterator/walker_scrollbar_container.hpp" #include "gui/core/event/message.hpp" #include "gui/core/layout_exception.hpp" #include "gui/core/log.hpp" @@ -516,6 +517,11 @@ bool scrollbar_container::disable_click_dismiss() const return container_base::disable_click_dismiss() || content_grid_->disable_click_dismiss(); } +iteration::walker_ptr scrollbar_container::create_walker() +{ + return std::make_unique(*this); +} + bool scrollbar_container::content_resize_request(const bool force_sizing) { /** diff --git a/src/gui/widgets/scrollbar_container.hpp b/src/gui/widgets/scrollbar_container.hpp index 214196035c5..102fde3db6d 100644 --- a/src/gui/widgets/scrollbar_container.hpp +++ b/src/gui/widgets/scrollbar_container.hpp @@ -137,6 +137,11 @@ public: /** See @ref widget::disable_click_dismiss. */ bool disable_click_dismiss() const override; + + /** + * See @ref widget::create_walker. + */ + virtual iteration::walker_ptr create_walker() override; /***** ***** ***** setters / getters for members ***** ****** *****/