Fixed keyboard navigation & text boxes, improved the visual clues that it's focused
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@4184 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
f28379a9ff
commit
729ccbc79b
@ -165,6 +165,7 @@ when the border that intersect at this corner are enabled.
|
||||
<color type="dialog_background" state="neutral" a="120" r="0" g="0" b="0" />
|
||||
|
||||
<!-- Text field color -->
|
||||
<color type="text_field" state="neutral" a="100" r="150" g="150" b="150" />
|
||||
<color type="text_field" state="neutral" a="255" r="215" g="215" b="215" />
|
||||
<color type="text_field" state="focused" a="255" r="0" g="150" b="0" />
|
||||
|
||||
</skin>
|
@ -89,6 +89,9 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
Widget* w = GUIEngine::getWidget(id);
|
||||
if (w == NULL) break;
|
||||
|
||||
// When a modal dialog is shown, don't select widgets out of the dialog
|
||||
if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(w)) break;
|
||||
|
||||
// select ribbons on hover
|
||||
if (w->m_event_handler != NULL && w->m_event_handler->m_type == WTYPE_RIBBON)
|
||||
{
|
||||
@ -117,7 +120,8 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case EGET_ELEMENT_FOCUSED: // FIXME: is this still used with the new focus implementation?
|
||||
/*
|
||||
case EGET_ELEMENT_FOCUSED: // is this still used with the new focus implementation?
|
||||
{
|
||||
Widget* w = GUIEngine::getWidget(id);
|
||||
if (w == NULL) break;
|
||||
@ -128,7 +132,7 @@ EventPropagation EventHandler::onGUIEvent(const SEvent& event)
|
||||
return w->focused(0);
|
||||
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
case EGET_EDITBOX_ENTER:
|
||||
{
|
||||
// currently, enter pressed in text ctrl events can only happen in dialogs.
|
||||
|
@ -59,6 +59,13 @@ public:
|
||||
/** Returns whether to block event propagation (usually, you will want to block events you processed) */
|
||||
virtual EventPropagation processEvent(std::string& eventSource){ return EVENT_LET; }
|
||||
|
||||
bool isMyChild(Widget* widget) const { return m_children.contains(widget); }
|
||||
|
||||
irr::gui::IGUIWindow* getIrrlichtElement()
|
||||
{
|
||||
return m_irrlicht_window;
|
||||
}
|
||||
|
||||
static void dismiss();
|
||||
static void onEnterPressed();
|
||||
static ModalDialog* getCurrent();
|
||||
|
@ -1092,14 +1092,7 @@ void Skin::draw3DButtonPaneStandard (IGUIElement *element, const core::rect< s32
|
||||
}
|
||||
|
||||
void Skin::draw3DSunkenPane (IGUIElement *element, video::SColor bgcolor, bool flat, bool fillBackGround, const core::rect< s32 > &rect, const core::rect< s32 > *clip)
|
||||
{
|
||||
if (element->getType()==gui::EGUIET_EDIT_BOX)
|
||||
{
|
||||
SColor& color = SkinConfig::m_colors["text_field::neutral"];
|
||||
GUIEngine::getDriver()->draw2DRectangle( color, rect );
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const int id = element->getID();
|
||||
Widget* widget = GUIEngine::getWidget(id);
|
||||
|
||||
@ -1117,7 +1110,30 @@ void Skin::draw3DSunkenPane (IGUIElement *element, video::SColor bgcolor, bool f
|
||||
|
||||
const bool focused = (focusedElem == element);
|
||||
|
||||
if (type == WTYPE_LIST)
|
||||
if (element->getType()==gui::EGUIET_EDIT_BOX)
|
||||
{
|
||||
SColor& color = SkinConfig::m_colors["text_field::neutral"];
|
||||
SColor& colorFocus = SkinConfig::m_colors["text_field::focused"];
|
||||
|
||||
if (focused)
|
||||
{
|
||||
core::rect< s32 > borderArea = rect;
|
||||
borderArea.UpperLeftCorner -= position2d< s32 >( 2, 2 );
|
||||
borderArea.LowerRightCorner += position2d< s32 >( 2, 2 );
|
||||
GUIEngine::getDriver()->draw2DRectangle( colorFocus, borderArea );
|
||||
|
||||
core::rect< s32 > innerArea = rect;
|
||||
innerArea.UpperLeftCorner += position2d< s32 >( 2, 2 );
|
||||
innerArea.LowerRightCorner -= position2d< s32 >( 2, 2 );
|
||||
GUIEngine::getDriver()->draw2DRectangle( color, innerArea );
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIEngine::getDriver()->draw2DRectangle( color, rect );
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (type == WTYPE_LIST)
|
||||
{
|
||||
drawList(rect, widget, focused);
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ void Widget::setFocusForPlayer(const int playerID)
|
||||
// Unset focus flag on previous widget that had focus
|
||||
if (GUIEngine::getFocusForPlayer(playerID) != NULL)
|
||||
{
|
||||
GUIEngine::getFocusForPlayer(playerID)->unfocused(playerID);
|
||||
GUIEngine::getFocusForPlayer(playerID)->m_player_focus[playerID] = false;
|
||||
}
|
||||
|
||||
@ -134,6 +135,7 @@ void Widget::setFocusForPlayer(const int playerID)
|
||||
|
||||
void Widget::unsetFocusForPlayer(const int playerID)
|
||||
{
|
||||
if (m_player_focus[playerID]) this->unfocused(playerID);
|
||||
m_player_focus[playerID] = false;
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,9 @@ namespace GUIEngine
|
||||
/** override in children if you need to know when the widget is focused. return whether to block event */
|
||||
virtual EventPropagation focused(const int playerID) { isWithinATextBox = false; return EVENT_LET; }
|
||||
|
||||
/** override in children if you need to know when the widget is unfocused. */
|
||||
virtual void unfocused(const int playerID) { }
|
||||
|
||||
/**
|
||||
* The XML loader stored coords in their raw string form inside this widget.
|
||||
* This method parses the strings. Most notably, expands coords relative to parent
|
||||
|
@ -16,6 +16,7 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/modaldialog.hpp"
|
||||
#include "guiengine/widgets/text_box_widget.hpp"
|
||||
using namespace GUIEngine;
|
||||
using namespace irr::core;
|
||||
@ -37,6 +38,7 @@ void TextBoxWidget::add()
|
||||
id = m_element->getID();
|
||||
m_element->setTabOrder(id);
|
||||
m_element->setTabGroup(false);
|
||||
m_element->setTabStop(true);
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
stringw TextBoxWidget::getText() const
|
||||
@ -46,4 +48,26 @@ stringw TextBoxWidget::getText() const
|
||||
|
||||
return stringw(textCtrl->getText());
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
EventPropagation TextBoxWidget::focused(const int playerID)
|
||||
{
|
||||
assert(playerID == 0); // No support for multiple players in text areas!
|
||||
|
||||
// special case : to work, the text box must receive "irrLicht focus", STK focus is not enough
|
||||
GUIEngine::getGUIEnv()->setFocus(m_element);
|
||||
isWithinATextBox = true;
|
||||
return EVENT_LET;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
void TextBoxWidget::unfocused(const int playerID)
|
||||
{
|
||||
assert(playerID == 0); // No support for multiple players in text areas!
|
||||
|
||||
// special case : to work, the text box must receive "irrLicht focus", STK focus is not enough
|
||||
// below is a cheap way to unset the irrLicht focus from the widget (nope, 'removeFocus' from
|
||||
// IGUIEnv doesn't work reliably, not sure why)
|
||||
// currently, text boxes are only used in modal dialogs, so I shift the focus to the dialog
|
||||
assert( ModalDialog::isADialogActive() );
|
||||
GUIEngine::getGUIEnv()->setFocus( ModalDialog::getCurrent()->getIrrlichtElement() );
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,8 @@ namespace GUIEngine
|
||||
void add();
|
||||
void addItem(const char* item);
|
||||
|
||||
virtual EventPropagation focused(const int playerID) { isWithinATextBox = true; return EVENT_LET; }
|
||||
virtual EventPropagation focused(const int playerID);
|
||||
virtual void unfocused(const int playerID);
|
||||
|
||||
core::stringw getText() const;
|
||||
};
|
||||
|
@ -460,12 +460,16 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
}
|
||||
// 'backspace' in a text control must never be mapped, since user can be in a text
|
||||
// area trying to erase text (and if it's mapped to rescue that would dismiss the
|
||||
// dialog instead of erasing a single letter)
|
||||
// dialog instead of erasing a single letter). Same for spacebar.
|
||||
if (key == KEY_BACK && GUIEngine::isWithinATextBox)
|
||||
{
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
if (key == KEY_SPACE && GUIEngine::isWithinATextBox)
|
||||
{
|
||||
return EVENT_LET;
|
||||
}
|
||||
|
||||
dispatchInput(Input::IT_KEYBOARD, 0, key,
|
||||
// FIXME: not sure why this happens: with plib the unicode
|
||||
// value is 0. Since all values defined in user_config
|
||||
|
@ -59,9 +59,6 @@ void PlayerInfoDialog::showRegularDialog()
|
||||
textCtrl->setParent(m_irrlicht_window);
|
||||
m_children.push_back(textCtrl);
|
||||
textCtrl->add();
|
||||
|
||||
const int playerID = 0; // FIXME: don't hardcode player ID
|
||||
textCtrl->setFocusForPlayer( playerID );
|
||||
}
|
||||
|
||||
{
|
||||
@ -115,6 +112,8 @@ void PlayerInfoDialog::showRegularDialog()
|
||||
widget->add();
|
||||
}
|
||||
|
||||
const int playerID = 0; // FIXME: don't hardcode player ID
|
||||
textCtrl->setFocusForPlayer( playerID );
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
void PlayerInfoDialog::showConfirmDialog()
|
||||
|
Loading…
Reference in New Issue
Block a user