diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 7fd56c9f7..2a4f92ab7 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3211,6 +3211,7 @@ Some types may inherit styles from parent types. * *all elements* * default - Equivalent to providing no states * button, button_exit, image_button, item_image_button + * focused - Active when button has focus * hovered - Active when the mouse is hovering over the element * pressed - Active when the button is pressed diff --git a/games/devtest/mods/testformspec/formspec.lua b/games/devtest/mods/testformspec/formspec.lua index 5f1f8970e..48c8763de 100644 --- a/games/devtest/mods/testformspec/formspec.lua +++ b/games/devtest/mods/testformspec/formspec.lua @@ -190,6 +190,7 @@ local style_fs = [[ style[one_btn14:hovered;bgimg=testformspec_bg_hovered.png;fgimg=testformspec_hovered.png;textcolor=yellow] style[one_btn14:pressed;bgimg=testformspec_bg_pressed.png;fgimg=testformspec_pressed.png;textcolor=blue] style[one_btn14:hovered+pressed;textcolor=purple] + style[one_btn14:focused;textcolor=red] image_button[0,9.6;1,1;testformspec_button_image.png;one_btn14;Bg] style[one_btn15;border=false;bgcolor=#1cc;bgimg=testformspec_bg.png;bgimg_hovered=testformspec_bg_hovered.png;bgimg_pressed=testformspec_bg_pressed.png] @@ -198,10 +199,10 @@ local style_fs = [[ style[one_btn16;border=false;bgimg=testformspec_bg_9slice.png;bgimg_middle=4,6;padding=5,7;fgimg=testformspec_bg.png;fgimg_middle=1] style[one_btn16:hovered;bgimg=testformspec_bg_9slice_hovered.png;fgimg=testformspec_bg_hovered.png] style[one_btn16:pressed;bgimg=testformspec_bg_9slice_pressed.png;fgimg=testformspec_bg_pressed.png] + style[one_btn16:focused;bgimg=testformspec_bg_9slice_focused.png;fgimg=testformspec_bg_focused.png] image_button[2.5,9.6;2,1;;one_btn16;9-Slice Bg] - container[2.75,0] style[one_tb1;textcolor=Yellow] diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_focused.png b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_focused.png new file mode 100644 index 000000000..b6d5a7886 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg_9slice_focused.png differ diff --git a/games/devtest/mods/testformspec/textures/testformspec_bg_focused.png b/games/devtest/mods/testformspec/textures/testformspec_bg_focused.png new file mode 100644 index 000000000..14d9ddbf9 Binary files /dev/null and b/games/devtest/mods/testformspec/textures/testformspec_bg_focused.png differ diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index 7a45e07d1..ab132f69e 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -61,13 +61,16 @@ public: NUM_PROPERTIES, NONE }; - enum State + + // State is a bitfield, it's possible to have multiple of these at once + enum State : u8 { STATE_DEFAULT = 0, - STATE_HOVERED = 1 << 0, - STATE_PRESSED = 1 << 1, - NUM_STATES = 1 << 2, - STATE_INVALID = 1 << 3, + STATE_FOCUSED = 1 << 0, + STATE_HOVERED = 1 << 1, + STATE_PRESSED = 1 << 2, + NUM_STATES = 1 << 3, // This includes all permutations + STATE_INVALID = 1 << 4, }; private: @@ -150,6 +153,8 @@ public: { if (name == "default") { return STATE_DEFAULT; + } else if (name == "focused") { + return STATE_FOCUSED; } else if (name == "hovered") { return STATE_HOVERED; } else if (name == "pressed") { diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index 3a2ddde1c..136a04a96 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -200,6 +200,7 @@ bool GUIButton::OnEvent(const SEvent& event) // mouse is outside of the formspec. Thus, we test the position here. if ( !IsPushButton && AbsoluteClippingRect.isPointInside( core::position2d(event.MouseInput.X, event.MouseInput.Y ))) { + Environment->setFocus(this); setPressed(true); } @@ -258,8 +259,10 @@ void GUIButton::draw() // PATCH // Track hovered state, if it has changed then we need to update the style. bool hovered = isHovered(); - if (hovered != WasHovered) { + bool focused = isFocused(); + if (hovered != WasHovered || focused != WasFocused) { WasHovered = hovered; + WasFocused = focused; setFromState(); } @@ -387,7 +390,7 @@ EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed, const ButtonImage { // figure state we should have EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED; - bool focused = Environment->hasFocus((IGUIElement*)this); + bool focused = isFocused(); bool mouseOver = isHovered(); if (isEnabled()) { @@ -582,6 +585,12 @@ bool GUIButton::isHovered() const IGUIElement *hovered = Environment->getHovered(); return hovered == this || (hovered != nullptr && hovered->getParent() == this); } + +//! Returns if this element (or one of its direct children) is focused +bool GUIButton::isFocused() const +{ + return Environment->hasFocus((IGUIElement*)this, true); +} // END PATCH //! Sets the pressed state of the button if this is a pushbutton @@ -662,6 +671,9 @@ void GUIButton::setFromState() if (isHovered()) state = static_cast(state | StyleSpec::STATE_HOVERED); + if (isFocused()) + state = static_cast(state | StyleSpec::STATE_FOCUSED); + setFromStyle(StyleSpec::getStyleFromStatePropagation(Styles, state)); } diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h index 31105bcda..5006e2df9 100644 --- a/src/gui/guiButton.h +++ b/src/gui/guiButton.h @@ -123,6 +123,9 @@ public: // PATCH //! Returns if this element (or one of its direct children) is hovered bool isHovered() const; + + //! Returns if this element (or one of its direct children) is focused + bool isFocused() const; // END PATCH //! Sets if the button should use the skin to draw its border @@ -268,6 +271,7 @@ private: video::SColor Colors[4]; // PATCH bool WasHovered = false; + bool WasFocused = false; ISimpleTextureSource *TSrc; gui::IGUIStaticText *StaticText;