Commit 7336c447 authored by cutealien's avatar cutealien

Focus behavior of IGUIEnvironment now controllable (right-click focus,...

Focus behavior of IGUIEnvironment now controllable (right-click focus, mouse-over focus). Disabled elements no longer get the focus unless users enforce it.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4759 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 55508ee4
--------------------------
Changes in 1.9 (not yet released)
- Focus behavior of IGUIEnvironment now controllable (right-click focus, mouse-over focus). Disabled elements no longer get the focus unless users enforce it.
- Buttons can now now have 7 more image-states, 1 more sprite-state and the sprites are now scaleable.
- Spritebanks can now draw scaled sprites and are a little easier to use.
- Improved i18n key input for X11 (languages like cyrillic work now).
......
......@@ -640,9 +640,11 @@ public:
\param first: element with the highest/lowest known tab order depending on search direction
\param closest: the closest match, depending on tab order and direction
\param includeInvisible: includes invisible elements in the search (default=false)
\param includeDisabled: includes disabled elements in the search (default=false)
\return true if successfully found an element, false to continue searching/fail */
bool getNextElement(s32 startOrder, bool reverse, bool group,
IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false) const
IGUIElement*& first, IGUIElement*& closest, bool includeInvisible=false,
bool includeDisabled=false) const
{
// we'll stop searching if we find this number
s32 wanted = startOrder + ( reverse ? -1 : 1 );
......@@ -659,48 +661,52 @@ public:
if ( ( (*it)->isVisible() || includeInvisible ) &&
(group == true || (*it)->isTabGroup() == false) )
{
// only check tab stops and those with the same group status
if ((*it)->isTabStop() && ((*it)->isTabGroup() == group))
// ignore disabled, but children are checked (disabled is currently per element ignoring parent states)
if ( (*it)->isEnabled() || includeDisabled )
{
currentOrder = (*it)->getTabOrder();
// is this what we're looking for?
if (currentOrder == wanted)
// only check tab stops and those with the same group status
if ((*it)->isTabStop() && ((*it)->isTabGroup() == group))
{
closest = *it;
return true;
}
currentOrder = (*it)->getTabOrder();
// is it closer than the current closest?
if (closest)
{
closestOrder = closest->getTabOrder();
if ( ( reverse && currentOrder > closestOrder && currentOrder < startOrder)
||(!reverse && currentOrder < closestOrder && currentOrder > startOrder))
// is this what we're looking for?
if (currentOrder == wanted)
{
closest = *it;
return true;
}
}
else
if ( (reverse && currentOrder < startOrder) || (!reverse && currentOrder > startOrder) )
{
closest = *it;
}
// is it before the current first?
if (first)
{
closestOrder = first->getTabOrder();
// is it closer than the current closest?
if (closest)
{
closestOrder = closest->getTabOrder();
if ( ( reverse && currentOrder > closestOrder && currentOrder < startOrder)
||(!reverse && currentOrder < closestOrder && currentOrder > startOrder))
{
closest = *it;
}
}
else
if ( (reverse && currentOrder < startOrder) || (!reverse && currentOrder > startOrder) )
{
closest = *it;
}
// is it before the current first?
if (first)
{
closestOrder = first->getTabOrder();
if ( (reverse && closestOrder < currentOrder) || (!reverse && closestOrder > currentOrder) )
if ( (reverse && closestOrder < currentOrder) || (!reverse && closestOrder > currentOrder) )
{
first = *it;
}
}
else
{
first = *it;
}
}
else
{
first = *it;
}
}
// search within children
if ((*it)->getNextElement(startOrder, reverse, group, first, closest))
......
......@@ -9,6 +9,7 @@
#include "IGUISkin.h"
#include "rect.h"
#include "EMessageBoxFlags.h"
#include "EFocusFlags.h"
#include "IEventReceiver.h"
#include "IXMLReader.h"
#include "path.h"
......@@ -262,9 +263,8 @@ public:
\param modal Defines if the dialog is modal. This means, that all other
gui elements which were created before the message box cannot be used
until this messagebox is removed.
\param flags Flags specifying the layout of the message box. For example
to create a message box with an OK and a CANCEL button on it, set this
to (EMBF_OK | EMBF_CANCEL).
\param flags Flags specifying the layout of the message box using ::EMESSAGE_BOX_FLAG.
Create a message box with an OK and CANCEL button for example with (EMBF_OK | EMBF_CANCEL).
\param parent Parent gui element of the message box.
\param id Id with which the gui element can be identified.
\param image Optional texture which will be displayed beside the text as an image
......@@ -619,6 +619,17 @@ public:
\param group When true it will search for the next tab-group (like ctrl+tab)
*/
virtual IGUIElement* getNextElement(bool reverse=false, bool group=false) = 0;
//! Set the way the gui will handle automatic focus changes
/** The default is (EFF_SET_ON_LMOUSE_DOWN | EFF_SET_ON_TAB).
with the left mouse button.
This does not affect the setFocus function itself - users can still call that whenever they want on any element.
\param flags A bitmask which is a combination of ::EFOCUS_FLAG flags.*/
virtual void setFocusBehavior(u32 flags) = 0;
//! Get the way the gui does handle focus changes
/** \returns A bitmask which is a combination of ::EFOCUS_FLAG flags.*/
virtual u32 getFocusBehavior() const = 0;
};
......
......@@ -58,7 +58,7 @@ const io::path CGUIEnvironment::DefaultFontName = "#DefaultFont";
CGUIEnvironment::CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op)
: IGUIElement(EGUIET_ROOT, 0, 0, 0, core::rect<s32>(core::position2d<s32>(0,0), driver ? core::dimension2d<s32>(driver->getScreenSize()) : core::dimension2d<s32>(0,0))),
Driver(driver), Hovered(0), HoveredNoSubelement(0), Focus(0), LastHoveredMousePos(0,0), CurrentSkin(0),
FileSystem(fs), UserReceiver(0), Operator(op)
FileSystem(fs), UserReceiver(0), Operator(op), FocusFlags(EFF_SET_ON_LMOUSE_DOWN|EFF_SET_ON_TAB)
{
if (Driver)
Driver->grab();
......@@ -574,10 +574,30 @@ bool CGUIEnvironment::postEventFromUser(const SEvent& event)
updateHoveredElement(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
if ( (Hovered && Hovered != Focus) || !Focus )
if ( Hovered != Focus )
{
setFocus(Hovered);
IGUIElement * focusCandidate = Hovered;
// Only allow enabled elements to be focused (unless EFF_CAN_FOCUS_DISABLED is set)
if ( !Hovered->isEnabled() && !(FocusFlags & EFF_CAN_FOCUS_DISABLED))
focusCandidate = NULL; // we still remove focus from the active element
// Please don't merge this into a single if clause, it's easier to debug the way it is
if (FocusFlags & EFF_SET_ON_LMOUSE_DOWN &&
event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN )
{
setFocus(focusCandidate);
}
else if ( FocusFlags & EFF_SET_ON_RMOUSE_DOWN &&
event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN )
{
setFocus(focusCandidate);
}
else if ( FocusFlags & EFF_SET_ON_MOUSE_OVER &&
event.MouseInput.Event == EMIE_MOUSE_MOVED )
{
setFocus(focusCandidate);
}
}
// sending input to focus
......@@ -599,7 +619,8 @@ bool CGUIEnvironment::postEventFromUser(const SEvent& event)
// For keys we handle the event before changing focus to give elements the chance for catching the TAB
// Send focus changing event
if (event.EventType == EET_KEY_INPUT_EVENT &&
if (FocusFlags & EFF_SET_ON_TAB &&
event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.PressedDown &&
event.KeyInput.Key == KEY_TAB)
{
......@@ -610,7 +631,6 @@ bool CGUIEnvironment::postEventFromUser(const SEvent& event)
return true;
}
}
}
break;
default:
......@@ -1640,7 +1660,7 @@ IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group)
// find the element
IGUIElement *closest = 0;
IGUIElement *first = 0;
startPos->getNextElement(startOrder, reverse, group, first, closest);
startPos->getNextElement(startOrder, reverse, group, first, closest, false, FocusFlags & EFF_CAN_FOCUS_DISABLED);
if (closest)
return closest; // we found an element
......@@ -1652,6 +1672,15 @@ IGUIElement* CGUIEnvironment::getNextElement(bool reverse, bool group)
return 0;
}
void CGUIEnvironment::setFocusBehavior(u32 flags)
{
FocusFlags = flags;
}
u32 CGUIEnvironment::getFocusBehavior() const
{
return FocusFlags;
}
//! creates an GUI Environment
IGUIEnvironment* createGUIEnvironment(io::IFileSystem* fs,
......
......@@ -260,7 +260,13 @@ public:
virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node) _IRR_OVERRIDE_;
//! Find the next element which would be selected when pressing the tab-key
virtual IGUIElement* getNextElement(bool reverse=false, bool group=false);
virtual IGUIElement* getNextElement(bool reverse=false, bool group=false) _IRR_OVERRIDE_;
//! Set the way the gui will handle focus changes
virtual void setFocusBehavior(u32 flags) _IRR_OVERRIDE_;
//! Get the way the gui does handle focus changes
virtual u32 getFocusBehavior() const _IRR_OVERRIDE_;
private:
......@@ -314,6 +320,7 @@ private:
io::IFileSystem* FileSystem;
IEventReceiver* UserReceiver;
IOSOperator* Operator;
u32 FocusFlags;
static const io::path DefaultFontName;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment