gui: Fix theme UI buttons missing icons or toggle state upon recreation

This is a blanket fix for the issue I previously tried to fix for
specific cases in the following two commits:

 * 1df73b9e4c Call display::draw() before setting theme UI button states
 * f93b439e13 Call set_button_state() from playsingle_controller::init_gui()

This final version of the fix is far superior as it doesn't involve
sloppy guesswork regarding the various display class redraw methods and
their call sites. Instead, we just copy the previous state for each
button during reconstruction regardless of the situation at hand. We
know they are the right buttons because they have the same id strings.

It is a little more involved than I would've liked because it has to
deal with a quirk in gui::button's implementation that becomes more
evident with this fix. The following primarily applies to
gui::button::load_images():

gui::button generates its own built-in image size filename suffix for
the button overlays and frames when the button dimensions are already
known, usually after a method call that sets the button's geometry with
a valid size (i.e. not -1234 x -1234). button::set_overlay() happens to
be such a method, but not all buttons use it to set their initial
overlay, and that's where trouble begins...

 * Some theme UI buttons (mostly in the editor, and the Draw Terrains
   and Draw Units toggles on the minimap area in-game) have their
   overlay icon paths set in the WML, including their _25 size suffix.
   These have their overlays (and frames) set initially set by the
   gui::button ctor, which loads the images and figures out the button
   dimensions in the process (via button::load_images()). The ctor
   always does this unconditionally.

 * At that time, button::load_images() will not add an engine-defined
   suffix because the button dimensions are still unknown until it
   finishes. The images are loaded successfully.

 * Subsequent calls to button::set_overlay() *with the same path* will
   have button::load_images() append its own suffix determined from the
   previously determined button dimensions. Hilarity ensues.

The hotkeys engine (via hotkey::command_executor::set_button_state())
and the theme WML have different notions of which button icons have a
suffix defined externally to gui::button. This results in situations
where restoring the previous icons in display::create_buttons() causes
gui::button to look for inexistent images with duplicate size suffixes
("_25_25"). Although modifying the mainline WML to avoid using those
suffixes in the first place would be the most elegant solution, it also
has the potential to cause issues with UMC themes (esp. forks of the
mainine themes), even if those are relatively rare. Moreover, it counts
as a violation of the stable branch ban on API changes.

In other words, even if this part of the fix is very ugly, it's
ultimately necessary if we are to fix the original bug in a stable
branch without breaking the theme WML API contract. This is also why
everything is in a single commit instead of split in two.

Also note that the aforementioned commits aren't fully obsolete; the
most recent one is actually still required so that the hotkeys engine
gets to set the button icon overlays at least once (for those buttons
which don't have this defined by WML) before running WML events. Any
redundancy arising from keeping them wouldn't hurt anyway.

Finally, all this has been rendered irrelevant in master by Aginor's
refactoring and bug fixes, so this code is a technological dead end
anyway.
This commit is contained in:
Ignacio R. Morelle 2016-05-16 05:37:32 -04:00
parent 3d904a3ae7
commit e3970e8cb4
5 changed files with 49 additions and 2 deletions

View file

@ -6,6 +6,11 @@ Version 1.12.5+dev:
* Fixed glitches of river ford transitions.
* User interface:
* GUI1 comboboxes now use the thinner menu frame style.
* Fixed minimap buttons appearing without contents or in the wrong state
when the game window is resized, when using debug commands to toggle fog
and/or shroud, and probably a lot of other occurrences that are now
covered by a proper fix on top of the quick hacks shipped with versions
1.11.16 and 1.12.3.
* Miscellaneous and bug fixes:
* Revert all updates to hot-key handling which broke letter-based short-cuts
on non-US keyboard layouts, where characters are in different key

View file

@ -7,6 +7,13 @@ Version 1.12.5+dev:
* Updated translations: British English, Galician, Italian, Japanese,
Portuguese, RACV, Russian, Scottish Gaelic, Slovak, Spanish, Swedish.
* User interface:
* Fixed minimap buttons appearing without contents or in the wrong state
when the game window is resized, when using debug commands to toggle fog
and/or shroud, and probably a lot of other occurrences that are now
covered by a proper fix on top of the quick hacks shipped with versions
1.11.16 and 1.12.3.
Version 1.12.5:
* Campaigns:

View file

@ -965,7 +965,13 @@ void display::create_buttons()
}
gui::button* b_prev = find_menu_button(b.id());
if(b_prev) b.enable(b_prev->enabled());
if(b_prev) {
b.enable(b_prev->enabled());
const std::string& ov = b_prev->overlay();
if(!ov.empty()) {
b.set_overlay(ov);
}
}
menu_work.push_back(b);
}
@ -987,7 +993,14 @@ void display::create_buttons()
}
gui::button* b_prev = find_action_button(b.id());
if(b_prev) b.enable(b_prev->enabled());
if(b_prev) {
b.enable(b_prev->enabled());
b.set_check(b_prev->checked());
const std::string& ov = b_prev->overlay();
if(!ov.empty()) {
b.set_overlay(ov);
}
}
action_work.push_back(b);
}

View file

@ -102,7 +102,21 @@ void button::load_images() {
disabled_image.assign((image::get_image(button_image_name_ + "-disabled.png")));
surface pressed_disabled_image, pressed_active_image, touched_image;
const std::string original_size_postfix = size_postfix;
if (!button_overlay_image_name_.empty()) {
const size_t postfix_len = size_postfix.length();
const size_t stem_len = button_overlay_image_name_.length();
if (stem_len >= postfix_len &&
button_overlay_image_name_.substr(stem_len - postfix_len) == size_postfix)
{
// Don't duplicate the size postfix if already part of the image path stem.
// This is needed to address a bug with UI button overlays disappearing in
// 1.12 due to inconsistent image path conventions in themes, without
// breaking backwards compatibility with broken mainline and UMC themes.
size_postfix.clear();
}
overlayImage_.assign(image::get_image(button_overlay_image_name_ + size_postfix + ".png"));
overlayPressedImage_.assign(image::get_image(button_overlay_image_name_ + size_postfix + "-pressed.png"));
@ -122,6 +136,8 @@ void button::load_images() {
overlayImage_.assign(NULL);
}
size_postfix = original_size_postfix;
if (disabled_image == NULL) {
disabled_image = image::get_image(button_image_name_ + ".png~GS()");
}
@ -397,6 +413,11 @@ void button::set_overlay(const std::string& image_file)
set_dirty();
}
const std::string& button::overlay() const
{
return button_overlay_image_name_;
}
void button::set_label(const std::string& val)
{
label_ = val;

View file

@ -47,6 +47,7 @@ public:
void set_label(const std::string& val);
void set_image(const std::string& image_file_base);
void set_overlay(const std::string& image_file_base);
const std::string& overlay() const;
bool pressed();
bool hit(int x, int y) const;