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:
auria 2009-10-31 23:06:58 +00:00
parent f28379a9ff
commit 729ccbc79b
10 changed files with 79 additions and 18 deletions

View File

@ -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>

View File

@ -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.

View File

@ -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();

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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() );
}

View File

@ -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;
};

View File

@ -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

View File

@ -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()