diff --git a/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj b/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj index 28c592c7b35..93cc1a008a4 100644 --- a/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj +++ b/projectfiles/Xcode/The Battle for Wesnoth.xcodeproj/project.pbxproj @@ -585,19 +585,13 @@ 46F92EDD2174FD9900602C1C /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED32174FD9700602C1C /* scrollbar.cpp */; }; 46F92EDE2174FD9900602C1C /* textbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED52174FD9800602C1C /* textbox.cpp */; }; 46F92EDF2174FD9900602C1C /* button.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED72174FD9800602C1C /* button.cpp */; }; - 46F92EE02174FD9900602C1C /* menu_style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED82174FD9800602C1C /* menu_style.cpp */; }; - 46F92EE12174FD9900602C1C /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EDA2174FD9900602C1C /* menu.cpp */; }; 46F92EE22174FDA100602C1C /* button.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED72174FD9800602C1C /* button.cpp */; }; - 46F92EE32174FDA600602C1C /* menu_style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED82174FD9800602C1C /* menu_style.cpp */; }; - 46F92EE42174FDA600602C1C /* menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EDA2174FD9900602C1C /* menu.cpp */; }; 46F92EE82174FDAB00602C1C /* scrollarea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED12174FD9700602C1C /* scrollarea.cpp */; }; 46F92EE92174FDAB00602C1C /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED32174FD9700602C1C /* scrollbar.cpp */; }; 46F92EEA2174FDAB00602C1C /* textbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92ED52174FD9800602C1C /* textbox.cpp */; }; 46F92EEB2174FDAB00602C1C /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B55999600EC62181008DD061 /* widget.cpp */; }; 46F92EEE2174FE0E00602C1C /* floating_textbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EED2174FE0E00602C1C /* floating_textbox.cpp */; }; 46F92EEF2174FE0E00602C1C /* floating_textbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EED2174FE0E00602C1C /* floating_textbox.cpp */; }; - 46F92EF22174FE5600602C1C /* show_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EF12174FE5500602C1C /* show_dialog.cpp */; }; - 46F92EF32174FE5600602C1C /* show_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EF12174FE5500602C1C /* show_dialog.cpp */; }; 46F92F0F2174FEC000602C1C /* standard_colors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EF52174FEBD00602C1C /* standard_colors.cpp */; }; 46F92F102174FEC000602C1C /* standard_colors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EF52174FEBD00602C1C /* standard_colors.cpp */; }; 46F92F172174FEC000602C1C /* font_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46F92EFC2174FEBE00602C1C /* font_config.cpp */; }; @@ -2112,18 +2106,13 @@ 46F92ED12174FD9700602C1C /* scrollarea.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scrollarea.cpp; sourceTree = ""; }; 46F92ED22174FD9700602C1C /* scrollarea.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scrollarea.hpp; sourceTree = ""; }; 46F92ED32174FD9700602C1C /* scrollbar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scrollbar.cpp; sourceTree = ""; }; - 46F92ED42174FD9700602C1C /* menu.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = menu.hpp; sourceTree = ""; }; 46F92ED52174FD9800602C1C /* textbox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = textbox.cpp; sourceTree = ""; }; 46F92ED62174FD9800602C1C /* button.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = button.hpp; sourceTree = ""; }; 46F92ED72174FD9800602C1C /* button.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = button.cpp; sourceTree = ""; }; - 46F92ED82174FD9800602C1C /* menu_style.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = menu_style.cpp; sourceTree = ""; }; 46F92ED92174FD9900602C1C /* textbox.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = textbox.hpp; sourceTree = ""; }; - 46F92EDA2174FD9900602C1C /* menu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = menu.cpp; sourceTree = ""; }; 46F92EDB2174FD9900602C1C /* scrollbar.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scrollbar.hpp; sourceTree = ""; }; 46F92EEC2174FE0D00602C1C /* floating_textbox.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = floating_textbox.hpp; sourceTree = ""; }; 46F92EED2174FE0E00602C1C /* floating_textbox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = floating_textbox.cpp; sourceTree = ""; }; - 46F92EF02174FE5500602C1C /* show_dialog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = show_dialog.hpp; sourceTree = ""; }; - 46F92EF12174FE5500602C1C /* show_dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = show_dialog.cpp; sourceTree = ""; }; 46F92EF42174FEBD00602C1C /* standard_colors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = standard_colors.hpp; path = font/standard_colors.hpp; sourceTree = ""; }; 46F92EF52174FEBD00602C1C /* standard_colors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = standard_colors.cpp; path = font/standard_colors.cpp; sourceTree = ""; }; 46F92EF92174FEBE00602C1C /* error.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = error.hpp; path = font/error.hpp; sourceTree = ""; }; @@ -3482,8 +3471,6 @@ EC64D75F1A085CE60092EF75 /* seed_rng.cpp */, 91B621971B7672B400B00E0F /* seed_rng.hpp */, B55999A60EC62181008DD061 /* serialization */, - 46F92EF12174FE5500602C1C /* show_dialog.cpp */, - 46F92EF02174FE5500602C1C /* show_dialog.hpp */, 9577DD2E2C1E1BEB0031135F /* side_controller.hpp */, B5CE46F712A0417D00D665EE /* side_filter.cpp */, B5CE46F812A0417D00D665EE /* side_filter.hpp */, @@ -4818,9 +4805,6 @@ children = ( 46F92ED72174FD9800602C1C /* button.cpp */, 46F92ED62174FD9800602C1C /* button.hpp */, - 46F92ED82174FD9800602C1C /* menu_style.cpp */, - 46F92EDA2174FD9900602C1C /* menu.cpp */, - 46F92ED42174FD9700602C1C /* menu.hpp */, 46F92ED12174FD9700602C1C /* scrollarea.cpp */, 46F92ED22174FD9700602C1C /* scrollarea.hpp */, 46F92ED32174FD9700602C1C /* scrollbar.cpp */, @@ -5549,7 +5533,6 @@ 46F92DAB2174F6A300602C1C /* unit_recall.cpp in Sources */, B5599B7B0EC62181008DD061 /* config_cache.cpp in Sources */, 9154743D2C8FBAC800EB1C94 /* lua_attributes.cpp in Sources */, - 46F92EF22174FE5600602C1C /* show_dialog.cpp in Sources */, B5599B7D0EC62181008DD061 /* config.cpp in Sources */, EC0680291EA920A300EEE03B /* random_deterministic.cpp in Sources */, B54AC69D0FEA9E8F006F6FBD /* configuration.cpp in Sources */, @@ -5603,7 +5586,6 @@ ECC84C1D1B973C5900A5F451 /* quit_confirmation.cpp in Sources */, B559A0160EC8FE2E008DD061 /* editor_main.cpp in Sources */, 6295C3C2150FC9750077D8C5 /* editor_map.cpp in Sources */, - 46F92EE02174FD9900602C1C /* menu_style.cpp in Sources */, ECF44F6A1FC8A82B00B404D6 /* make.cpp in Sources */, 6295C3D6150FC9EB0077D8C5 /* editor_palettes.cpp in Sources */, 46F92E7D2174F6A400602C1C /* label.cpp in Sources */, @@ -5764,7 +5746,6 @@ 46F92DC52174F6A300602C1C /* modeless_dialog.cpp in Sources */, 46F92D9B2174F6A300602C1C /* depcheck_confirm_change.cpp in Sources */, 469BDB55205C357500DBF748 /* base64.cpp in Sources */, - 46F92EE12174FD9900602C1C /* menu.cpp in Sources */, B5599B250EC62181008DD061 /* minimap.cpp in Sources */, 4685124A24AE1535005B6EB1 /* game_config_view.cpp in Sources */, 46EEFB762087434300E1E75A /* chat_log.cpp in Sources */, @@ -6190,7 +6171,6 @@ 46F92E522174F6A400602C1C /* widget.cpp in Sources */, 46F92DC82174F6A300602C1C /* end_credits.cpp in Sources */, 46F92DCC2174F6A300602C1C /* drop_down_menu.cpp in Sources */, - 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 */, @@ -6439,7 +6419,6 @@ 91E357001CACC9B200774252 /* flg_manager.cpp in Sources */, 91E357011CACC9B200774252 /* mp_game_utils.cpp in Sources */, 91E357031CACC9B200774252 /* multiplayer.cpp in Sources */, - 46F92EF32174FE5600602C1C /* show_dialog.cpp in Sources */, 46F92E142174F6A400602C1C /* player_list_helper.cpp in Sources */, 91E3570A1CACC9B200774252 /* playcampaign.cpp in Sources */, 46F92DBC2174F6A300602C1C /* file_dialog.cpp in Sources */, @@ -6670,7 +6649,6 @@ 46F92DFE2174F6A400602C1C /* wml_error.cpp in Sources */, 9164077F1D3C381B0057C4DE /* chat_command_handler.cpp in Sources */, 9193FC7B1D5AE5B2004F6C07 /* name_generator_factory.cpp in Sources */, - 46F92EE32174FDA600602C1C /* menu_style.cpp in Sources */, 9193FC7F1D5BB64F004F6C07 /* advancement.cpp in Sources */, 9193FC831D5C2D00004F6C07 /* lua_unit.cpp in Sources */, 9193FC871D5D7461004F6C07 /* lua_unit_attacks.cpp in Sources */, diff --git a/source_lists/libwesnoth b/source_lists/libwesnoth index 0ea37b74ae5..48423f560f1 100644 --- a/source_lists/libwesnoth +++ b/source_lists/libwesnoth @@ -41,7 +41,6 @@ pathfind/astarsearch.cpp pathutils.cpp quit_confirmation.cpp reports.cpp -show_dialog.cpp sound.cpp sound_music_track.cpp soundsource.cpp @@ -54,8 +53,6 @@ time_of_day.cpp tooltips.cpp video.cpp widgets/button.cpp -widgets/menu.cpp -widgets/menu_style.cpp widgets/scrollarea.cpp widgets/scrollbar.cpp widgets/textbox.cpp diff --git a/src/controller_base.cpp b/src/controller_base.cpp index c6b49947caf..870b00a7115 100644 --- a/src/controller_base.cpp +++ b/src/controller_base.cpp @@ -24,7 +24,6 @@ #include "mouse_handler_base.hpp" #include "preferences/preferences.hpp" #include "scripting/plugins/context.hpp" -#include "show_dialog.hpp" //gui::in_dialog #include "gui/core/event/handler.hpp" // gui2::is_in_dialog #include "soundsource.hpp" #include "gui/core/timer.hpp" @@ -97,7 +96,7 @@ void controller_base::long_touch_callback(int x, int y) void controller_base::handle_event(const SDL_Event& event) { - if(gui::in_dialog()) { + if(gui2::is_in_dialog()) { return; } diff --git a/src/display.cpp b/src/display.cpp index 599957994e5..c7b3eb3931c 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -26,9 +26,11 @@ #include "draw_manager.hpp" #include "fake_unit_manager.hpp" #include "filesystem.hpp" +#include "floating_label.hpp" #include "font/sdl_ttf_compat.hpp" #include "font/text.hpp" #include "global.hpp" +#include "gui/core/event/handler.hpp" // is_in_dialog #include "preferences/preferences.hpp" #include "halo.hpp" #include "hotkey/command_executor.hpp" @@ -40,7 +42,6 @@ #include "play_controller.hpp" //note: this can probably be refactored out #include "reports.hpp" #include "resources.hpp" -#include "show_dialog.hpp" #include "synced_context.hpp" #include "team.hpp" #include "terrain/builder.hpp" @@ -2345,7 +2346,7 @@ void display::queue_rerender() } } - if (!gui::in_dialog()) { + if(!gui2::is_in_dialog()) { labels().recalculate_labels(); } diff --git a/src/help/help.cpp b/src/help/help.cpp index b3dc0ef9c9c..6399fdbd0f0 100644 --- a/src/help/help.cpp +++ b/src/help/help.cpp @@ -33,7 +33,6 @@ #include "help/help_impl.hpp" // for hidden_symbol, toplevel, etc #include "key.hpp" // for CKey #include "log.hpp" // for LOG_STREAM, log_domain -#include "show_dialog.hpp" // for dialog_frame, etc #include "terrain/terrain.hpp" // for terrain_type #include "units/unit.hpp" // for unit #include "units/types.hpp" // for unit_type, unit_type_data, etc diff --git a/src/show_dialog.cpp b/src/show_dialog.cpp deleted file mode 100644 index 3e7ddee426f..00000000000 --- a/src/show_dialog.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - Copyright (C) 2003 - 2024 - by David White - 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 "show_dialog.hpp" - -#include "draw.hpp" -#include "draw_manager.hpp" -#include "picture.hpp" -#include "gettext.hpp" -#include "gui/core/event/handler.hpp" // is_in_dialog -#include "log.hpp" -#include "font/sdl_ttf_compat.hpp" -#include "font/standard_colors.hpp" -#include "sdl/rect.hpp" -#include "sdl/input.hpp" // get_mouse_state -#include "video.hpp" - -static lg::log_domain log_display("display"); -#define ERR_DP LOG_STREAM(err, log_display) -#define WRN_DP LOG_STREAM(warn, log_display) -#define DBG_DP LOG_STREAM(debug, log_display) -#define ERR_G LOG_STREAM(err, lg::general) - -namespace { -bool is_in_dialog = false; -} - -namespace gui { - -//static initialization -const int ButtonHPadding = 10; -const int ButtonVPadding = 10; - -//note: style names are directly related to the panel image file names -const dialog_frame::style dialog_frame::default_style("opaque", 0); - -const int dialog_frame::title_border_w = 10; -const int dialog_frame::title_border_h = 5; - - - -bool in_dialog() -{ - return is_in_dialog || gui2::is_in_dialog(); -} - -dialog_manager::dialog_manager() : cursor::setter(cursor::NORMAL), reset_to(is_in_dialog) -{ - is_in_dialog = true; -} - -dialog_manager::~dialog_manager() -{ - is_in_dialog = reset_to; - int mousex, mousey; - sdl::get_mouse_state(&mousex, &mousey); - SDL_Event pb_event; - pb_event.type = SDL_MOUSEMOTION; - pb_event.motion.state = 0; - pb_event.motion.x = mousex; - pb_event.motion.y = mousey; - pb_event.motion.xrel = 0; - pb_event.motion.yrel = 0; - SDL_PushEvent(&pb_event); -} - -dialog_frame::dialog_frame(const std::string& title, - const style& style, - std::vector* buttons, button* help_button) : - title_(title), - dialog_style_(style), - buttons_(buttons), - help_button_(help_button), - dim_(), - top_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-top.png")), - bot_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-bottom.png")), - left_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-left.png")), - right_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-right.png")), - top_left_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-topleft.png")), - bot_left_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-botleft.png")), - top_right_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-topright.png")), - bot_right_(image::get_texture("dialogs/" + dialog_style_.panel + "-border-botright.png")), - bg_(image::get_texture("dialogs/" + dialog_style_.panel + "-background.png")), - have_border_(top_ && bot_ && left_ && right_), - dirty_(true) -{ - // Raise buttons so they are drawn on top. - // and BTW buttons_ being a pointer to a vector is fucking insane - for (button* b : *buttons_) { - draw_manager::raise_drawable(b); - } - if (help_button) { - draw_manager::raise_drawable(help_button_); - } -} - -dialog_frame::~dialog_frame() -{ - draw_manager::invalidate_region(screen_location()); -} - -dialog_frame::dimension_measurements::dimension_measurements() : - interior(sdl::empty_rect), exterior(sdl::empty_rect), title(sdl::empty_rect), button_row(sdl::empty_rect) -{} - -dialog_frame::dimension_measurements dialog_frame::layout(const SDL_Rect& rect) -{ - return layout(rect.x, rect.y, rect.w, rect.h); -} - -int dialog_frame::top_padding() const -{ - int padding = 0; - if(have_border_) { - padding += top_.h(); - } - if(!title_.empty()) { - padding += font::get_max_height(font::SIZE_TITLE) + 2*dialog_frame::title_border_h; - } - return padding; -} - -void dialog_frame::set_dirty(bool dirty) -{ - dirty_ = dirty; -} - -int dialog_frame::bottom_padding() const { - int padding = 0; - if(buttons_ != nullptr) { - for(std::vector::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) { - padding = std::max((**b).height() + ButtonVPadding, padding); - } - } - if(have_border_) { - padding += bot_.h(); - } - return padding; -} - -dialog_frame::dimension_measurements dialog_frame::layout(int x, int y, int w, int h) { - dim_ = dimension_measurements(); - if(!title_.empty()) { - dim_.title = draw_title(false); - dim_.title.w += title_border_w; - } - if(buttons_ != nullptr) { - for(std::vector::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) { - dim_.button_row.w += (**b).width() + ButtonHPadding; - dim_.button_row.h = std::max((**b).height() + ButtonVPadding,dim_.button_row.h); - } - - dim_.button_row.x = -dim_.button_row.w; - dim_.button_row.y = y + h; - - dim_.button_row.w += ButtonHPadding; - } - - std::size_t buttons_width = dim_.button_row.w; - - if(help_button_ != nullptr) { - buttons_width += help_button_->width() + ButtonHPadding*2; - dim_.button_row.y = y + h; - } - - y -= dim_.title.h; - w = std::max(w, std::max(dim_.title.w, static_cast(buttons_width))); - h += dim_.title.h + dim_.button_row.h; - dim_.button_row.x += x + w; - - rect bounds = video::game_canvas(); - if(have_border_) { - bounds.x += left_.w(); - bounds.y += top_.h(); - bounds.w -= left_.w(); - bounds.h -= top_.h(); - } - if(x < bounds.x) { - w += x; - x = bounds.x; - } - if(y < bounds.y) { - h += y; - y = bounds.y; - } - if(x > bounds.w) { - w = 0; - } else if(x + w > bounds.w) { - w = bounds.w - x; - } - if(y > bounds.h) { - h = 0; - } else if(y + h > bounds.h) { - h = bounds.h - y; - } - dim_.interior.x = x; - dim_.interior.y = y; - dim_.interior.w = w; - dim_.interior.h = h; - if(have_border_) { - dim_.exterior.x = dim_.interior.x - left_.w(); - dim_.exterior.y = dim_.interior.y - top_.h(); - dim_.exterior.w = dim_.interior.w + left_.w() + right_.w(); - dim_.exterior.h = dim_.interior.h + top_.h() + bot_.h(); - } else { - dim_.exterior = dim_.interior; - } - dim_.title.x = dim_.interior.x + title_border_w; - dim_.title.y = dim_.interior.y + title_border_h; - - draw_manager::invalidate_region(dim_.exterior); - - return dim_; -} - -void dialog_frame::draw_border() -{ - if(have_border_ == false) { - return; - } - - // Too much typing is bad for you. - const SDL_Rect& i = dim_.interior; - const SDL_Rect& e = dim_.exterior; - - if(top_) { - draw::blit(top_, {i.x, e.y, i.w, top_.h()}); - } - - if(bot_) { - draw::blit(bot_, {i.x, i.y + i.h, i.w, bot_.h()}); - } - - if(left_) { - draw::blit(left_, {e.x, i.y, left_.w(), i.h}); - } - - if(right_) { - draw::blit(right_, {i.x + i.w, i.y, right_.w(), i.h}); - } - - if(!top_left_ || !bot_left_ || !top_right_ || !bot_right_) { - return; - } - - draw::blit(top_left_, - {i.x - left_.w(), i.y - top_.h(), top_left_.w(), top_left_.h()}); - - draw::blit(bot_left_, { - i.x - left_.w(), - i.y + i.h + bot_.h() - bot_left_.h(), - bot_left_.w(), - bot_left_.h() - }); - - draw::blit(top_right_, { - i.x + i.w + right_.w() - top_right_.w(), - i.y - top_.h(), - top_right_.w(), - top_right_.h(), - }); - - draw::blit(bot_right_, { - i.x + i.w + right_.w() - bot_right_.w(), - i.y + i.h + bot_.h() - bot_right_.h(), - bot_right_.w(), - bot_right_.h() - }); -} - -void dialog_frame::draw_background() -{ - if (dialog_style_.blur_radius) { - // This is no longer used by anything. - // The only thing that uses dialog_frame is help/help.cpp, - // and it uses the default style with no blur. - ERR_DP << "GUI1 dialog_frame blur has been removed"; - } - - if (!bg_) { - ERR_DP << "could not find dialog background '" << dialog_style_.panel << "'"; - return; - } - - auto clipper = draw::reduce_clip(dim_.interior); - for(int i = 0; i < dim_.interior.w; i += bg_.w()) { - for(int j = 0; j < dim_.interior.h; j += bg_.h()) { - SDL_Rect src {0,0,0,0}; - src.w = std::min(dim_.interior.w - i, bg_.w()); - src.h = std::min(dim_.interior.h - j, bg_.h()); - SDL_Rect dst = src; - dst.x = dim_.interior.x + i; - dst.y = dim_.interior.y + j; - draw::blit(bg_, dst); - } - } -} - -rect dialog_frame::draw_title(bool actually_draw) -{ - rect r = video::game_canvas(); - return font::pango_draw_text( - actually_draw, r, font::SIZE_TITLE, font::TITLE_COLOR, title_, - dim_.title.x, dim_.title.y, false, font::pango_text::STYLE_NORMAL - ); -} - -void dialog_frame::draw() -{ - //draw background - draw_background(); - - //draw frame border - draw_border(); - - //draw title - if (!title_.empty()) { - draw_title(true); - } -} - -void dialog_frame::layout() -{ - if (!dirty_) { - return; - } - - // Layout buttons - SDL_Rect buttons_area = dim_.button_row; - if(buttons_ != nullptr) { -#ifdef OK_BUTTON_ON_RIGHT - std::reverse(buttons_->begin(),buttons_->end()); -#endif - for(std::vector::const_iterator b = buttons_->begin(); b != buttons_->end(); ++b) { - (**b).set_location(buttons_area.x, buttons_area.y); - buttons_area.x += (**b).width() + ButtonHPadding; - } - } - - // Layout help button, if any - if(help_button_ != nullptr) { - help_button_->set_location(dim_.interior.x+ButtonHPadding, buttons_area.y); - } - - dirty_ = false; -} - -bool dialog_frame::expose(const rect& region) -{ - DBG_DP << "dialog_frame::expose " << region; - // Just draw everthing. - draw(); - return true; -} - -rect dialog_frame::screen_location() -{ - return dim_.exterior; -} - -} diff --git a/src/show_dialog.hpp b/src/show_dialog.hpp deleted file mode 100644 index a803cd4f621..00000000000 --- a/src/show_dialog.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - Copyright (C) 2003 - 2024 - by David White - 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 "cursor.hpp" -#include "floating_label.hpp" -#include "gui/core/top_level_drawable.hpp" -#include "widgets/button.hpp" - -namespace gui -{ - -extern const int ButtonHPadding; -extern const int ButtonVPadding; -enum DIALOG_RESULT { - DIALOG_BACK=-7, - DIALOG_FORWARD=-6, - CREATE_ITEM =-5, - DELETE_ITEM=-4, - ESCAPE_DIALOG=-3, //special return used by WML event dialogs - CONTINUE_DIALOG=-2, - CLOSE_DIALOG=-1 - /* results (0..N) reserved for standard button indices */ -}; - -bool in_dialog(); - -struct dialog_manager : private cursor::setter, private font::floating_label_context { - dialog_manager(); - ~dialog_manager(); - -private: - bool reset_to; -}; - -class dialog_frame : public gui2::top_level_drawable { -public: - struct dimension_measurements { - dimension_measurements(); - SDL_Rect interior, exterior, title, button_row; - }; - class style { - public: - style(const std::string& p, int br) : panel(p), blur_radius(br) {} - std::string panel; - int blur_radius; - }; - - //Static members - static const int title_border_w, title_border_h; - static const style default_style; - - dialog_frame(const std::string& title="", - const style& dialog_style=default_style, - std::vector* buttons=nullptr, - button* help_button=nullptr); - ~dialog_frame(); - - dimension_measurements layout(int x, int y, int w, int h); - dimension_measurements layout(const SDL_Rect& frame_area); - void set_layout(dimension_measurements &new_dim) { dim_ = new_dim; } - dimension_measurements get_layout() const { return dim_; } - - int top_padding() const; - int bottom_padding() const; - - void draw(); - - /** Called by draw_manager to validate layout. */ - virtual void layout() override; - - /** Called by draw_manager when it believes a redraw is necessary. */ - virtual bool expose(const rect& region) override; - - /** The current draw location of the window, on the screen. */ - virtual rect screen_location() override; - - //called by draw - void draw_border(); - void draw_background(); - - //also called by layout with null param - rect draw_title(bool actually_draw); - - void set_dirty(bool dirty = true); - -private: - void clear_background(); - - std::string title_; - const style& dialog_style_; - std::vector* buttons_; - button* help_button_; - bool auto_restore_; - dimension_measurements dim_; - texture top_, bot_, left_, right_, top_left_, bot_left_, top_right_, bot_right_, bg_; - bool have_border_; - bool dirty_; -}; - -} diff --git a/src/video.cpp b/src/video.cpp index 5e8d96244a1..1b3fd7d2095 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -24,7 +24,6 @@ #include "sdl/texture.hpp" #include "sdl/utils.hpp" #include "sdl/window.hpp" -#include "widgets/menu.hpp" // for bluebg_style.unload_images #ifdef TARGET_OS_OSX #include "desktop/apple_video.hpp" @@ -122,7 +121,6 @@ void deinit() font::flush_texture_cache(); render_texture_.reset(); current_render_target_.reset(); - gui::menu::bluebg_style.unload_images(); // Destroy the window, and thus also the renderer. window.reset(); diff --git a/src/widgets/menu.cpp b/src/widgets/menu.cpp deleted file mode 100644 index ecc5f0e0b1a..00000000000 --- a/src/widgets/menu.cpp +++ /dev/null @@ -1,688 +0,0 @@ -/* - Copyright (C) 2003 - 2024 - by David White - 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 "widgets/menu.hpp" - -#include "draw.hpp" -#include "font/sdl_ttf_compat.hpp" -#include "font/standard_colors.hpp" -#include "game_config.hpp" -#include "language.hpp" -#include "picture.hpp" -#include "sdl/rect.hpp" -#include "sdl/texture.hpp" -#include "sound.hpp" -#include "video.hpp" - - -namespace { - /** - * For converting indented_menu_item.indent_level into a width in pixels. - * The text size might change, so instead of caching a value pango_line_size - * is called repeatedly with this as an argument. - */ - const std::string indent_string{" "}; -}; - -namespace gui { - -menu::menu(bool click_selects, int max_height, int max_width, style *menu_style, const bool auto_join) -: scrollarea(auto_join), silent_(false), - max_height_(max_height), max_width_(max_width), - max_items_(-1), item_height_(-1), - selected_(0), click_selects_(click_selects), out_(false), - previous_button_(true), show_result_(false), - double_clicked_(false), - num_selects_(true), - ignore_next_doubleclick_(false), - last_was_doubleclick_(false), use_ellipsis_(false) -{ - style_ = (menu_style) ? menu_style : &default_style; - style_->init(); - fill_items({}); -} - -menu::~menu() -{ -} - -void menu::fill_items(const std::vector& items) -{ - for(const auto& itor : items) { - const std::size_t id = items_.size(); - item_pos_.push_back(id); - items_.emplace_back(itor, id); - } - - update_size(); -} - -void menu::update_scrollbar_grip_height() -{ - set_full_size(items_.size()); - set_shown_size(max_items_onscreen()); -} - -void menu::update_size() -{ - int h = 0; - for(std::size_t i = get_position(), - i_end = std::min(items_.size(), i + max_items_onscreen()); - i < i_end; ++i) - h += get_item_rect(i).h; - h = std::max(h, height()); - if (max_height_ > 0 && h > (max_height_)) { - h = max_height_; - } - - use_ellipsis_ = false; - int w = widest_row_width(); - if (items_.size() > max_items_onscreen()) - w += scrollbar_width(); - w = std::max(w, width()); - if (max_width_ > 0 && w > (max_width_)) { - use_ellipsis_ = true; - w = max_width_; - } - - update_scrollbar_grip_height(); - set_measurements(w, h); -} - -int menu::selection() const -{ - if (selected_ >= items_.size()) { - return -1; - } - - return items_[selected_].id; -} - -void menu::set_inner_location(const SDL_Rect& /*rect*/) -{ - itemRects_.clear(); - update_scrollbar_grip_height(); -} - -void menu::set_items(const std::vector& items, utils::optional selected) -{ - const bool scrolled_to_max = (has_scrollbar() && get_position() == get_max_position()); - items_.clear(); - item_pos_.clear(); - itemRects_.clear(); - widest_row_width_.reset(); - //undrawn_items_.clear(); - max_items_ = -1; // Force recalculation of the max items. - item_height_ = -1; // Force recalculation of the item height. - - if(selected) { - selected_ = *selected; - } else { - selected_ = 0; - } - - fill_items(items); - if(scrolled_to_max) { - set_position(get_max_position()); - } - - update_scrollbar_grip_height(); - - adjust_viewport_to_selection(); - - queue_redraw(); -} - -void menu::set_max_height(const int new_max_height) -{ - max_height_ = new_max_height; - itemRects_.clear(); - max_items_ = -1; - update_size(); -} - -void menu::set_max_width(const int new_max_width) -{ - max_width_ = new_max_width; - itemRects_.clear(); - widest_row_width_.reset(); - update_size(); -} - -std::size_t menu::max_items_onscreen() const -{ - if(max_items_ != -1) { - return std::size_t(max_items_); - } - - const std::size_t max_height = ( - max_height_ == -1 - ? (video::game_canvas_size().y * 66) / 100 - : max_height_ - ); - - std::vector heights; - std::size_t n; - for(n = 0; n != items_.size(); ++n) { - // The for loop, sort and sum around this are unnecessary, because - // get_item_height has ignored its argument since Wesnoth 0.6.99.1. - // It caches and returns the height of the tallest item. - heights.push_back(get_item_height(n)); - } - - std::sort(heights.begin(),heights.end(),std::greater()); - std::size_t sum = 0; - for(n = 0; n != items_.size() && sum < max_height; ++n) { - sum += heights[n]; - } - - if(sum > max_height && n > 1) - --n; - - return max_items_ = n; -} - -void menu::adjust_viewport_to_selection() -{ - if(click_selects_) - return; - adjust_position(selected_); -} - -void menu::set_selection_pos(std::size_t new_selected, bool silent, SELECTION_MOVE_VIEWPORT move_viewport) -{ - if (new_selected >= items_.size()) - return; - - bool changed = false; - if (new_selected != selected_) { - invalidate_row_pos(selected_); - invalidate_row_pos(new_selected); - selected_ = new_selected; - changed = true; - } - - if(move_viewport == MOVE_VIEWPORT) { - adjust_viewport_to_selection(); - if(!silent_ && !silent && changed) { - sound::play_UI_sound(game_config::sounds::menu_select); - } - } -} - -void menu::move_selection_up(std::size_t dep) -{ - set_selection_pos(selected_ > dep ? selected_ - dep : 0); -} - -void menu::move_selection_down(std::size_t dep) -{ - std::size_t nb_items = items_.size(); - set_selection_pos(selected_ + dep >= nb_items ? nb_items - 1 : selected_ + dep); -} - -// private function with control over sound and viewport -void menu::move_selection_to(std::size_t id, bool silent, SELECTION_MOVE_VIEWPORT move_viewport) -{ - if(id < item_pos_.size()) { - set_selection_pos(item_pos_[id], silent, move_viewport); - } -} - -// public function -void menu::move_selection(std::size_t id) -{ - if(id < item_pos_.size()) { - set_selection_pos(item_pos_[id], true, MOVE_VIEWPORT); - } -} - -// public function -void menu::move_selection_keeping_viewport(std::size_t id) -{ - if(id < item_pos_.size()) { - set_selection_pos(item_pos_[id], true, NO_MOVE_VIEWPORT); - } -} - -void menu::reset_selection() -{ - set_selection_pos(0, true); -} - -void menu::key_press(SDL_Keycode key) -{ - if (!click_selects_) { - switch(key) { - case SDLK_UP: - move_selection_up(1); - break; - case SDLK_DOWN: - move_selection_down(1); - break; - case SDLK_PAGEUP: - move_selection_up(max_items_onscreen()); - break; - case SDLK_PAGEDOWN: - move_selection_down(max_items_onscreen()); - break; - case SDLK_HOME: - set_selection_pos(0); - break; - case SDLK_END: - set_selection_pos(items_.size() - 1); - break; - //case SDLK_RETURN: - // double_clicked_ = true; - // break; - default: - break; - } - } - - if (num_selects_ && key >= SDLK_1 && key <= SDLK_9) - set_selection_pos(key - SDLK_1); -} - -bool menu::requires_event_focus(const SDL_Event* event) const -{ - if(!focus_ || height() == 0 || hidden()) { - return false; - } - if(event == nullptr) { - //when event is not specified, signal that focus may be desired later - return true; - } - - if(event->type == SDL_KEYDOWN) { - SDL_Keycode key = event->key.keysym.sym; - if (!click_selects_) { - switch(key) { - case SDLK_UP: - case SDLK_DOWN: - case SDLK_PAGEUP: - case SDLK_PAGEDOWN: - case SDLK_HOME: - case SDLK_END: - return true; - default: - break; - } - } - if (num_selects_ && key >= SDLK_1 && key <= SDLK_9) { - return true; - } - } - //mouse events are processed regardless of focus - return false; -} - -void menu::handle_event(const SDL_Event& event) -{ - scrollarea::handle_event(event); - if (height()==0 || hidden()) - return; - - if(event.type == SDL_KEYDOWN) { - // Only pass key events if we have the focus - if (focus(&event)) - key_press(event.key.keysym.sym); - } else if(!mouse_locked() && ((event.type == SDL_MOUSEBUTTONDOWN && - (event.button.button == SDL_BUTTON_LEFT || event.button.button == SDL_BUTTON_RIGHT)) || - event.type == DOUBLE_CLICK_EVENT)) { - - int x = 0; - int y = 0; - if(event.type == SDL_MOUSEBUTTONDOWN) { - x = event.button.x; - y = event.button.y; - } else { - x = reinterpret_cast(event.user.data1); - y = reinterpret_cast(event.user.data2); - } - - const int item = hit(x,y); - if(item != -1) { - set_focus(true); - move_selection_to(item); - - if(click_selects_) { - show_result_ = true; - } - - if(event.type == DOUBLE_CLICK_EVENT) { - if (ignore_next_doubleclick_) { - ignore_next_doubleclick_ = false; - } else { - double_clicked_ = true; - last_was_doubleclick_ = true; - if(!silent_) { - sound::play_UI_sound(game_config::sounds::button_press); - } - } - } else if (last_was_doubleclick_) { - // If we have a double click as the next event, it means - // this double click was generated from a click that - // already has helped in generating a double click. - SDL_Event ev; - SDL_PeepEvents(&ev, 1, SDL_PEEKEVENT, DOUBLE_CLICK_EVENT, DOUBLE_CLICK_EVENT); - if (ev.type == DOUBLE_CLICK_EVENT) { - ignore_next_doubleclick_ = true; - } - last_was_doubleclick_ = false; - } - } - - } else if(!mouse_locked() && event.type == SDL_MOUSEMOTION) { - if(click_selects_) { - const int item = hit(event.motion.x,event.motion.y); - const bool out = (item == -1); - if (out_ != out) { - out_ = out; - invalidate_row_pos(selected_); - } - if (item != -1) { - move_selection_to(item); - } - } - } -} - -int menu::process() -{ - if(show_result_) { - show_result_ = false; - return selected_; - } else { - return -1; - } -} - -bool menu::double_clicked() -{ - bool old = double_clicked_; - double_clicked_ = false; - return old; -} - -void menu::set_click_selects(bool value) -{ - click_selects_ = value; -} - -void menu::set_numeric_keypress_selection(bool value) -{ - num_selects_ = value; -} - -void menu::scroll(unsigned int) -{ - itemRects_.clear(); - queue_redraw(); -} - -SDL_Rect menu::style::item_size(const indented_menu_item& imi) const { - SDL_Rect res {0,0,0,0}; - - res.w = imi.indent_level * font::pango_line_size(indent_string, get_font_size()).first; - - if (!imi.icon.empty()) { - // Not the first item, add the spacing. - res.w += 5; - - const texture img = image::get_texture(imi.icon); - res.w += img.w(); - res.h = std::max(img.h(), res.h); - } - - if (!imi.text.empty()) { - // Not the first item, add the spacing. - res.w += 5; - - const SDL_Rect area {0,0,10000,10000}; - const SDL_Rect font_size = - font::pango_draw_text(false, area, get_font_size(), - font::NORMAL_COLOR, imi.text, 0, 0); - res.w += font_size.w; - res.h = std::max(font_size.h, res.h); - } - return res; -} - -void menu::style::draw_row_bg(menu& /*menu_ref*/, const std::size_t /*row_index*/, const SDL_Rect& rect, ROW_TYPE type) -{ - int rgb = 0; - double alpha = 0.0; - - switch(type) { - case NORMAL_ROW: - rgb = normal_rgb_; - alpha = normal_alpha_; - break; - case SELECTED_ROW: - rgb = selected_rgb_; - alpha = selected_alpha_; - break; - } - - // FIXME: make this clearer - color_t c((rgb & 0xff0000) >> 16, (rgb & 0xff00) >> 8, rgb & 0xff); - c.a = 255 * alpha; - - draw::fill(rect, c); -} - -void menu::style::draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type) -{ - if(rect.w == 0 || rect.h == 0) { - return; - } - draw_row_bg(menu_ref, row_index, rect, type); - - SDL_Rect minirect = rect; - minirect.x += thickness_; - minirect.y += thickness_; - minirect.w -= 2*thickness_; - minirect.h -= 2*thickness_; - menu_ref.draw_row(row_index, minirect, type); -} - -int menu::widest_row_width() const -{ - if(!widest_row_width_) { - int widest = 0; - for(const auto& row : items_) { - const SDL_Rect size = style_->item_size(row.fields); - widest = std::max(widest, size.w); - } - // Assume there's text at the end of the item, and add padding accordingly. - widest_row_width_ = static_cast(widest + style_->get_cell_padding()); - } - - return *widest_row_width_; -} - -bool menu::hit_on_indent_or_icon(std::size_t row_index, int x) const -{ - if(row_index >= items_.size()) { - return false; - } - - // The virtual method item_size() is overloaded by imgsel_style::item_size(), - // which adds borders on both sides. Call it twice and remove one side's padding. - const auto& imi = items_[row_index].fields; - int width_used_so_far = style_->item_size({imi.indent_level, imi.icon, ""}).w; - width_used_so_far -= style_->item_size({0, "", ""}).w / 2; - - const SDL_Rect& loc = inner_location(); - if (current_language_rtl()) { - // inner_location() already takes account of the scrollbar width - return x > loc.x + loc.w - width_used_so_far; - } - return x < loc.x + width_used_so_far; -} - -void menu::draw_row(const std::size_t row_index, const SDL_Rect& loc, ROW_TYPE) -{ - //called from style, draws one row's contents in a generic and adaptable way - const auto& imi = items_[row_index].fields; - rect area = video::game_canvas(); - bool lang_rtl = current_language_rtl(); - - // There's nothing to draw for the indent, just mark the space as used - int width_used_so_far = imi.indent_level * font::pango_line_size(indent_string, style_->get_font_size()).first; - - if (!imi.icon.empty()) { - const texture img = image::get_texture(imi.icon); - int img_w = img.w(); - int img_h = img.h(); - const int remaining_width = max_width_ < 0 ? area.w : std::min(max_width_, loc.w - width_used_so_far); - if(img && img_w <= remaining_width && loc.y + img_h < area.h) { - const std::size_t y = loc.y + (loc.h - img_h)/2; - const std::size_t x = loc.x + (lang_rtl ? loc.w - width_used_so_far - img_w : width_used_so_far); - draw::blit(img, {int(x), int(y), img_w, img_h}); - - // If there wasn't space for the icon, it doesn't get drawn, nor does the width get used. - // If it is drawn, add 5 pixels of padding. - width_used_so_far += img_w + 5; - } - } - - // Expected to be non-empty, but I guess a unit type could have a blank name - if (!imi.text.empty()) { - const auto text_size = font::pango_line_size(imi.text, style_->get_font_size()); - const std::size_t x = loc.x + (lang_rtl ? std::max(0, loc.w - width_used_so_far - text_size.first) : width_used_so_far); - const std::size_t y = loc.y + (loc.h - text_size.second)/2; - rect text_loc = loc; - text_loc.w = loc.w - (width_used_so_far) - 2 * style_->get_thickness(); - text_loc.h = text_size.second; - font::pango_draw_text(true, text_loc, style_->get_font_size(), font::NORMAL_COLOR, imi.text, - x, y); - } -} - -void menu::draw_contents() -{ - for(std::size_t i = 0; i != item_pos_.size(); ++i) { - style_->draw_row(*this,item_pos_[i],get_item_rect(i), - (!out_ && item_pos_[i] == selected_) ? SELECTED_ROW : NORMAL_ROW); - } -} - -int menu::hit(int x, int y) const -{ - const SDL_Rect& loc = inner_location(); - if (x >= loc.x && x < loc.x + loc.w && y >= loc.y && y < loc.y + loc.h) { - for(std::size_t i = 0; i != items_.size(); ++i) { - const SDL_Rect& rect = get_item_rect(i); - if (y >= rect.y && y < rect.y + rect.h) - return i; - } - } - - return -1; -} - -SDL_Rect menu::get_item_rect(int item) const -{ - return get_item_rect_internal(item_pos_[item]); -} - -SDL_Rect menu::get_item_rect_internal(std::size_t item) const -{ - unsigned int first_item_on_screen = get_position(); - if (item < first_item_on_screen || - item >= first_item_on_screen + max_items_onscreen()) { - return sdl::empty_rect; - } - - const std::map::const_iterator i = itemRects_.find(item); - if(i != itemRects_.end()) - return i->second; - - const SDL_Rect& loc = inner_location(); - - int y = loc.y; - if (item != first_item_on_screen) { - const SDL_Rect& prev = get_item_rect_internal(item-1); - y = prev.y + prev.h; - } - - rect res(loc.x, y, loc.w, get_item_height(item)); - - const point canvas_size = video::game_canvas_size(); - - if(res.x > canvas_size.x) { - return sdl::empty_rect; - } else if(res.x + res.w > canvas_size.x) { - res.w = canvas_size.x - res.x; - } - - if(res.y > canvas_size.y) { - return sdl::empty_rect; - } else if(res.y + res.h > canvas_size.y) { - res.h = canvas_size.y - res.y; - } - - //only insert into the cache if the menu's co-ordinates have - //been initialized - if (loc.x > 0 && loc.y > 0) - itemRects_.emplace(item, res); - - return res; -} - -std::size_t menu::get_item_height_internal(const indented_menu_item& imi) const -{ - return style_->item_size(imi).h; -} - -std::size_t menu::get_item_height(int) const -{ - // This could probably return the height of a single line of Pango text, plus - // padding. However, keeping compatibility with the current numbers means - // less unknowns about what the numbers should actually be. - if(item_height_ != -1) - return std::size_t(item_height_); - - std::size_t max_height = 0; - for(const auto& item : items_) { - max_height = std::max(max_height,get_item_height_internal(item.fields)); - } - - return item_height_ = max_height; -} - -void menu::invalidate_row(std::size_t id) -{ - if(id >= items_.size()) { - return; - } - - queue_redraw(get_item_rect(id)); -} - -void menu::invalidate_row_pos(std::size_t pos) -{ - if(pos >= items_.size()) { - return; - } - - invalidate_row(items_[pos].id); -} - -} diff --git a/src/widgets/menu.hpp b/src/widgets/menu.hpp deleted file mode 100644 index 2c3458e3def..00000000000 --- a/src/widgets/menu.hpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - Copyright (C) 2003 - 2024 - by David White - 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 "utils/optional_fwd.hpp" -#include -#include - -#include "scrollarea.hpp" - -namespace gui { - -/** - * The only kind of row still supported by the menu class. - * - * If comparing to 1.17.24 or before, these three items were held as a single string, thus a single member - * of the "fields" and a single "column" of the multi-column support. - */ -struct indented_menu_item -{ - /** An amount of blank space at the start of the row, measured in tab-stops (so 1 is around 4 en-widths) */ - int indent_level; - /** If non-empty, a picture to display before the text */ - std::string icon; - std::string text; -}; - -/** - * Superclass of the help_menu, which displays the left-hand pane of the GUI1 help browser. - * Historically a more generic class, but now only used for that singular purpose. - */ -class menu : public scrollarea -{ -public: - - enum ROW_TYPE { NORMAL_ROW, SELECTED_ROW }; - //basic menu style - class style - { - public: - style(); - virtual ~style(); - virtual void init() {} - - virtual SDL_Rect item_size(const indented_menu_item& imi) const; - virtual void draw_row_bg(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type); - virtual void draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type); - std::size_t get_font_size() const; - std::size_t get_cell_padding() const; - std::size_t get_thickness() const; - - protected: - std::size_t font_size_; - std::size_t cell_padding_; - std::size_t thickness_; //additional cell padding for style use only - - int normal_rgb_, selected_rgb_; - double normal_alpha_, selected_alpha_; - }; - - //image-border selection style - class imgsel_style : public style - { - public: - imgsel_style(const std::string &img_base, bool has_bg, - int normal_rgb, int selected_rgb, - double normal_alpha, double selected_alpha); - virtual ~imgsel_style(); - - virtual SDL_Rect item_size(const indented_menu_item& imi) const; - virtual void draw_row_bg(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type); - virtual void draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type); - - virtual void init() { load_images(); } - bool load_images(); - void unload_images(); - - protected: - const std::string img_base_; - std::map img_map_; - - private: - bool load_image(const std::string &img_sub); - bool has_background_; - bool initialized_; - bool load_failed_; - int normal_rgb2_, selected_rgb2_; - double normal_alpha2_, selected_alpha2_; - }; - - friend class style; - friend class imgsel_style; - static style &default_style; - static imgsel_style bluebg_style; - - struct item - { - item(const indented_menu_item& fields, std::size_t id) - : fields(fields), id(id) - {} - - indented_menu_item fields; - std::size_t id; - }; - - menu( - bool click_selects=false, int max_height=-1, int max_width=-1, - style *menu_style=nullptr, const bool auto_join=true); - - /** Default implementation, but defined out-of-line for efficiency reasons. */ - ~menu(); - - int selection() const; - - void move_selection(std::size_t id); - void move_selection_keeping_viewport(std::size_t id); - void reset_selection(); - - /** - * Set new items to show and redraw/recalculate everything. The menu tries - * to keep the selection at the same position as it were before the items - * were set. - */ - virtual void set_items(const std::vector& items, utils::optional selected); - - /** - * Set a new max height for this menu. Note that this does not take - * effect immediately, only after certain operations that clear - * everything, such as set_items(). - */ - void set_max_height(const int new_max_height); - void set_max_width(const int new_max_width); - - int get_max_height() const { return max_height_; } - int get_max_width() const { return max_width_; } - - std::size_t number_of_items() const { return items_.size(); } - - int process(); - - bool double_clicked(); - - void set_click_selects(bool value); - void set_numeric_keypress_selection(bool value); - - // scrollarea override - void scroll(unsigned int pos) override; - -protected: - virtual void handle_event(const SDL_Event& event) override; - void set_inner_location(const SDL_Rect& rect) override; - - bool requires_event_focus(const SDL_Event *event=nullptr) const override; - int widest_row_width() const; - virtual void draw_row(const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type); - - style *style_; - bool silent_; - - int hit(int x, int y) const; - - /** - * Returns true if a mouse-click with the given x-coordinate, and an - * appropriate y-coordinate would lie within the indent or icon part of - * the given row. - * - * The unusual combination of arguments fit with this being called when - * handling a mouse event, where we already know which row was selected, - * and are just inquiring a bit more about the details of that row. - */ - bool hit_on_indent_or_icon(std::size_t row_index, int x) const; - - void invalidate_row(std::size_t id); - void invalidate_row_pos(std::size_t pos); - -private: - std::size_t max_items_onscreen() const; - - int max_height_, max_width_; - mutable int max_items_, item_height_; - - void adjust_viewport_to_selection(); - void key_press(SDL_Keycode key); - - std::vector items_; - std::vector item_pos_; - - /** - * Cached return value of widest_row_width(), calculated on demand when calling that function. - */ - mutable utils::optional widest_row_width_; - - std::size_t selected_; - bool click_selects_; - bool out_; - bool previous_button_; - //std::set undrawn_items_; - - bool show_result_; - - bool double_clicked_; - - void draw_contents() override; - - mutable std::map itemRects_; - - SDL_Rect get_item_rect(int item) const; - SDL_Rect get_item_rect_internal(std::size_t pos) const; - std::size_t get_item_height_internal(const indented_menu_item& imi) const; - std::size_t get_item_height(int item) const; - int items_start() const; - - int items_end() const; - int items_height() const; - - void update_scrollbar_grip_height(); - - /** - * variable which determines whether a numeric keypress should - * select an item on the dialog - */ - bool num_selects_; - // These two variables are used to get the correct double click - // behavior so that a click that causes one double click won't be - // counted as a first click in the "next" double click. - bool ignore_next_doubleclick_; - bool last_was_doubleclick_; - - //ellipsis calculation is slightly off, so default to false - bool use_ellipsis_; - - /** - * Set new items to show. - */ - void fill_items(const std::vector& imi); - - void update_size(); - enum SELECTION_MOVE_VIEWPORT { MOVE_VIEWPORT, NO_MOVE_VIEWPORT }; - void set_selection_pos(std::size_t pos, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT); - void move_selection_to(std::size_t id, bool silent=false, SELECTION_MOVE_VIEWPORT move_viewport=MOVE_VIEWPORT); - void move_selection_up(std::size_t dep); - void move_selection_down(std::size_t dep); - - std::set invalid_; -}; - -} diff --git a/src/widgets/menu_style.cpp b/src/widgets/menu_style.cpp deleted file mode 100644 index 80285a65b4c..00000000000 --- a/src/widgets/menu_style.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - Copyright (C) 2006 - 2024 - by Patrick Parker - Copyright (C) 2003 - 2005 by David White - 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 "widgets/menu.hpp" - -#include "draw.hpp" -#include "font/constants.hpp" -#include "picture.hpp" - -namespace gui { - - //static initializations -menu::imgsel_style menu::bluebg_style("dialogs/selection", true, - 0x000000, 0x000000, - 0.35, 0.0); - -menu::style &menu::default_style = menu::bluebg_style; - - //constructors -menu::style::style() : font_size_(font::SIZE_NORMAL), - cell_padding_(font::SIZE_NORMAL * 3/5), thickness_(0), - normal_rgb_(0x000000), selected_rgb_(0x000099), - normal_alpha_(0.2), selected_alpha_(0.6) -{} - -menu::style::~style() -{} -menu::imgsel_style::imgsel_style(const std::string &img_base, bool has_bg, - int normal_rgb, int selected_rgb, - double normal_alpha, double selected_alpha) - : img_base_(img_base), has_background_(has_bg), initialized_(false), load_failed_(false), - normal_rgb2_(normal_rgb), selected_rgb2_(selected_rgb), - normal_alpha2_(normal_alpha), selected_alpha2_(selected_alpha) -{} -menu::imgsel_style::~imgsel_style() -{} - -std::size_t menu::style::get_font_size() const { return font_size_; } -std::size_t menu::style::get_cell_padding() const { return cell_padding_; } -std::size_t menu::style::get_thickness() const { return thickness_; } - -bool menu::imgsel_style::load_image(const std::string &img_sub) -{ - std::string path = img_base_ + "-" + img_sub + ".png"; - const texture image = image::get_texture(path); - img_map_[img_sub] = image; - return bool(image); -} - -bool menu::imgsel_style::load_images() -{ - if(!initialized_) - { - - if( load_image("border-botleft") - && load_image("border-botright") - && load_image("border-topleft") - && load_image("border-topright") - && load_image("border-left") - && load_image("border-right") - && load_image("border-top") - && load_image("border-bottom") ) - { - thickness_ = std::min( - img_map_["border-top"].h(), - img_map_["border-left"].w()); - - - if(has_background_ && !load_image("background")) - { - load_failed_ = true; - } - else - { - normal_rgb_ = normal_rgb2_; - normal_alpha_ = normal_alpha2_; - selected_rgb_ = selected_rgb2_; - selected_alpha_ = selected_alpha2_; - - load_failed_ = false; - } - initialized_ = true; - } - else - { - thickness_ = 0; - initialized_ = true; - load_failed_ = true; - } - } - return (!load_failed_); -} - -void menu::imgsel_style::unload_images() -{ - img_map_.clear(); -} - -void menu::imgsel_style::draw_row_bg(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type) -{ - if(type == SELECTED_ROW && has_background_ && !load_failed_) { - draw::blit(img_map_["background"], rect); - } - else { - style::draw_row_bg(menu_ref, row_index, rect, type); - } -} - -void menu::imgsel_style::draw_row(menu& menu_ref, const std::size_t row_index, const SDL_Rect& rect, ROW_TYPE type) -{ - if(!load_failed_) { - //draw item inside - style::draw_row(menu_ref, row_index, rect, type); - - if(type == SELECTED_ROW) { - // draw border - texture image; - SDL_Rect area; - auto clipper = draw::reduce_clip(rect); - area.x = rect.x; - area.y = rect.y; - - image = img_map_["border-top"]; - area.x = rect.x; - area.y = rect.y; - area.w = image.w(); - area.h = image.h(); - do { - draw::blit(image, area); - area.x += area.w; - } while( area.x < rect.x + rect.w ); - - image = img_map_["border-left"]; - area.x = rect.x; - area.y = rect.y; - area.w = image.w(); - area.h = image.h(); - do { - draw::blit(image, area); - area.y += area.h; - } while( area.y < rect.y + rect.h ); - - image = img_map_["border-right"]; - area.x = rect.x + rect.w - thickness_; - area.y = rect.y; - area.w = image.w(); - area.h = image.h(); - do { - draw::blit(image, area); - area.y += area.h; - } while( area.y < rect.y + rect.h ); - - image = img_map_["border-bottom"]; - area.x = rect.x; - area.y = rect.y + rect.h - thickness_; - area.w = image.w(); - area.h = image.h(); - do { - draw::blit(image, area); - area.x += area.w; - } while( area.x < rect.x + rect.w ); - - image = img_map_["border-topleft"]; - area.x = rect.x; - area.y = rect.y; - area.w = image.w(); - area.h = image.h(); - draw::blit(image, area); - - image = img_map_["border-topright"]; - area.x = rect.x + rect.w - image.w(); - area.y = rect.y; - area.w = image.w(); - area.h = image.h(); - draw::blit(image, area); - - image = img_map_["border-botleft"]; - area.x = rect.x; - area.y = rect.y + rect.h - image.h(); - area.w = image.w(); - area.h = image.h(); - draw::blit(image, area); - - image = img_map_["border-botright"]; - area.x = rect.x + rect.w - image.w(); - area.y = rect.y + rect.h - image.h(); - area.w = image.w(); - area.h = image.h(); - draw::blit(image, area); - } - } - else { - //default drawing - style::draw_row(menu_ref, row_index, rect, type); - } -} - -SDL_Rect menu::imgsel_style::item_size(const indented_menu_item& imi) const -{ - SDL_Rect bounds = style::item_size(imi); - - bounds.w += 2 * thickness_; - bounds.h += 2 * thickness_ + 4; - - return bounds; -} - - -} //namesapce gui