mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 03:35:27 +00:00
Improve KeyboardNavigation to better handle modal windows
It's no longer possible to cycle to widgets that aren't part of the current modal window. The window manager will remember the focused widget of a modal window on a limited basis (it'll be discarded when a different modal window opens).
This commit is contained in:
parent
41fe16013b
commit
1714271a76
@ -77,7 +77,6 @@ namespace MWGui
|
|||||||
|
|
||||||
void PersuasionDialog::onOpen()
|
void PersuasionDialog::onOpen()
|
||||||
{
|
{
|
||||||
WindowModal::onOpen();
|
|
||||||
center();
|
center();
|
||||||
|
|
||||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
@ -88,6 +87,12 @@ namespace MWGui
|
|||||||
mBribe1000Button->setEnabled (playerGold >= 1000);
|
mBribe1000Button->setEnabled (playerGold >= 1000);
|
||||||
|
|
||||||
mGoldLabel->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
|
mGoldLabel->setCaptionWithReplacing("#{sGold}: " + MyGUI::utility::toString(playerGold));
|
||||||
|
WindowModal::onOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
MyGUI::Widget* PersuasionDialog::getDefaultKeyFocus()
|
||||||
|
{
|
||||||
|
return mAdmireButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
@ -32,6 +32,8 @@ namespace MWGui
|
|||||||
|
|
||||||
virtual void onOpen();
|
virtual void onOpen();
|
||||||
|
|
||||||
|
virtual MyGUI::Widget* getDefaultKeyFocus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::Button* mCancelButton;
|
MyGUI::Button* mCancelButton;
|
||||||
MyGUI::Button* mAdmireButton;
|
MyGUI::Button* mAdmireButton;
|
||||||
|
@ -38,6 +38,7 @@ bool shouldAcceptKeyFocus(MyGUI::Widget* w)
|
|||||||
|
|
||||||
KeyboardNavigation::KeyboardNavigation()
|
KeyboardNavigation::KeyboardNavigation()
|
||||||
: mCurrentFocus(nullptr)
|
: mCurrentFocus(nullptr)
|
||||||
|
, mModalWindow(nullptr)
|
||||||
{
|
{
|
||||||
MyGUI::WidgetManager::getInstance().registerUnlinker(this);
|
MyGUI::WidgetManager::getInstance().registerUnlinker(this);
|
||||||
}
|
}
|
||||||
@ -51,9 +52,13 @@ void KeyboardNavigation::saveFocus(int mode)
|
|||||||
{
|
{
|
||||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
if (shouldAcceptKeyFocus(focus))
|
if (shouldAcceptKeyFocus(focus))
|
||||||
|
{
|
||||||
mKeyFocus[mode] = focus;
|
mKeyFocus[mode] = focus;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
mKeyFocus[mode] = mCurrentFocus;
|
mKeyFocus[mode] = mCurrentFocus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardNavigation::restoreFocus(int mode)
|
void KeyboardNavigation::restoreFocus(int mode)
|
||||||
@ -87,6 +92,13 @@ void styleFocusedButton(MyGUI::Widget* w)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isRootParent(MyGUI::Widget* widget, MyGUI::Widget* root)
|
||||||
|
{
|
||||||
|
while (widget && widget->getParent())
|
||||||
|
widget = widget->getParent();
|
||||||
|
return widget == root;
|
||||||
|
}
|
||||||
|
|
||||||
void KeyboardNavigation::onFrame()
|
void KeyboardNavigation::onFrame()
|
||||||
{
|
{
|
||||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
@ -98,7 +110,7 @@ void KeyboardNavigation::onFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// workaround incorrect key focus resets (fix in MyGUI TBD)
|
// workaround incorrect key focus resets (fix in MyGUI TBD)
|
||||||
if (!shouldAcceptKeyFocus(focus) && shouldAcceptKeyFocus(mCurrentFocus))
|
if (!shouldAcceptKeyFocus(focus) && shouldAcceptKeyFocus(mCurrentFocus) && (!mModalWindow || isRootParent(mCurrentFocus, mModalWindow)))
|
||||||
{
|
{
|
||||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(mCurrentFocus);
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(mCurrentFocus);
|
||||||
focus = mCurrentFocus;
|
focus = mCurrentFocus;
|
||||||
@ -119,6 +131,25 @@ void KeyboardNavigation::onFrame()
|
|||||||
styleFocusedButton(mCurrentFocus);
|
styleFocusedButton(mCurrentFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::setDefaultFocus(MyGUI::Widget *window, MyGUI::Widget *defaultFocus)
|
||||||
|
{
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
if (!focus || !shouldAcceptKeyFocus(focus))
|
||||||
|
{
|
||||||
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(defaultFocus);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!isRootParent(focus, window))
|
||||||
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(defaultFocus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardNavigation::setModalWindow(MyGUI::Widget *window)
|
||||||
|
{
|
||||||
|
mModalWindow = window;
|
||||||
|
}
|
||||||
|
|
||||||
enum Direction
|
enum Direction
|
||||||
{
|
{
|
||||||
D_Left,
|
D_Left,
|
||||||
@ -152,29 +183,15 @@ bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool selectFirstWidget()
|
|
||||||
{
|
|
||||||
MyGUI::VectorWidgetPtr keyFocusList;
|
|
||||||
MyGUI::EnumeratorWidgetPtr enumerator = MyGUI::Gui::getInstance().getEnumerator();
|
|
||||||
while (enumerator.next())
|
|
||||||
getKeyFocusWidgets(enumerator.current(), keyFocusList);
|
|
||||||
|
|
||||||
if (!keyFocusList.empty())
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[0]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyboardNavigation::switchFocus(int direction, bool wrap)
|
bool KeyboardNavigation::switchFocus(int direction, bool wrap)
|
||||||
{
|
{
|
||||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
|
||||||
if ((focus && focus->getTypeName().find("Button") == std::string::npos) && direction != D_Prev && direction != D_Next)
|
bool isCycle = (direction == D_Prev || direction == D_Next);
|
||||||
|
|
||||||
|
if ((focus && focus->getTypeName().find("Button") == std::string::npos) && !isCycle)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool isCycle = (direction == D_Prev || direction == D_Next);
|
|
||||||
if (focus && isCycle && focus->getUserString("AcceptTab") == "true")
|
if (focus && isCycle && focus->getUserString("AcceptTab") == "true")
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -230,6 +247,23 @@ bool KeyboardNavigation::switchFocus(int direction, bool wrap)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeyboardNavigation::selectFirstWidget()
|
||||||
|
{
|
||||||
|
MyGUI::VectorWidgetPtr keyFocusList;
|
||||||
|
MyGUI::EnumeratorWidgetPtr enumerator = MyGUI::Gui::getInstance().getEnumerator();
|
||||||
|
if (mModalWindow)
|
||||||
|
enumerator = mModalWindow->getEnumerator();
|
||||||
|
while (enumerator.next())
|
||||||
|
getKeyFocusWidgets(enumerator.current(), keyFocusList);
|
||||||
|
|
||||||
|
if (!keyFocusList.empty())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool KeyboardNavigation::accept()
|
bool KeyboardNavigation::accept()
|
||||||
{
|
{
|
||||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
|
@ -23,15 +23,23 @@ namespace MWGui
|
|||||||
|
|
||||||
void onFrame();
|
void onFrame();
|
||||||
|
|
||||||
|
/// Set a key focus widget for this window, if one isn't already set.
|
||||||
|
void setDefaultFocus(MyGUI::Widget* window, MyGUI::Widget* defaultFocus);
|
||||||
|
|
||||||
|
void setModalWindow(MyGUI::Widget* window);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool switchFocus(int direction, bool wrap);
|
bool switchFocus(int direction, bool wrap);
|
||||||
|
|
||||||
|
bool selectFirstWidget();
|
||||||
|
|
||||||
/// Send button press event to focused button
|
/// Send button press event to focused button
|
||||||
bool accept();
|
bool accept();
|
||||||
|
|
||||||
std::map<int, MyGUI::Widget*> mKeyFocus;
|
std::map<int, MyGUI::Widget*> mKeyFocus;
|
||||||
|
|
||||||
MyGUI::Widget* mCurrentFocus;
|
MyGUI::Widget* mCurrentFocus;
|
||||||
|
MyGUI::Widget* mModalWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,14 +67,17 @@ WindowModal::WindowModal(const std::string& parLayout)
|
|||||||
|
|
||||||
void WindowModal::onOpen()
|
void WindowModal::onOpen()
|
||||||
{
|
{
|
||||||
// Order important. We need to save the key focus widget before its unset
|
|
||||||
MWBase::Environment::get().getWindowManager()->addCurrentModal(this); //Set so we can escape it if needed
|
MWBase::Environment::get().getWindowManager()->addCurrentModal(this); //Set so we can escape it if needed
|
||||||
|
|
||||||
|
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||||
MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget);
|
MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget);
|
||||||
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowModal::onClose()
|
void WindowModal::onClose()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeCurrentModal(this);
|
MWBase::Environment::get().getWindowManager()->removeCurrentModal(this);
|
||||||
|
|
||||||
MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget);
|
MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ namespace MWGui
|
|||||||
public:
|
public:
|
||||||
WindowBase(const std::string& parLayout);
|
WindowBase(const std::string& parLayout);
|
||||||
|
|
||||||
|
virtual MyGUI::Widget* getDefaultKeyFocus() { return NULL; }
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
typedef MyGUI::delegates::CMultiDelegate1<WindowBase*> EventHandle_WindowBase;
|
typedef MyGUI::delegates::CMultiDelegate1<WindowBase*> EventHandle_WindowBase;
|
||||||
|
|
||||||
|
@ -1738,6 +1738,10 @@ namespace MWGui
|
|||||||
mKeyboardNavigation->saveFocus(getMode());
|
mKeyboardNavigation->saveFocus(getMode());
|
||||||
|
|
||||||
mCurrentModals.push(input);
|
mCurrentModals.push(input);
|
||||||
|
mKeyboardNavigation->restoreFocus(-1);
|
||||||
|
|
||||||
|
mKeyboardNavigation->setModalWindow(input->mMainWidget);
|
||||||
|
mKeyboardNavigation->setDefaultFocus(input->mMainWidget, input->getDefaultKeyFocus());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::removeCurrentModal(WindowModal* input)
|
void WindowManager::removeCurrentModal(WindowModal* input)
|
||||||
@ -1747,13 +1751,21 @@ namespace MWGui
|
|||||||
if(!mCurrentModals.empty())
|
if(!mCurrentModals.empty())
|
||||||
{
|
{
|
||||||
if(input == mCurrentModals.top())
|
if(input == mCurrentModals.top())
|
||||||
|
{
|
||||||
mCurrentModals.pop();
|
mCurrentModals.pop();
|
||||||
|
mKeyboardNavigation->saveFocus(-1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
std::cout << " warning: modal widget " << input << " " << typeid(input).name() << " not found " << std::endl;
|
std::cout << " warning: modal widget " << input << " " << typeid(input).name() << " not found " << std::endl;
|
||||||
}
|
}
|
||||||
if (mCurrentModals.empty())
|
if (mCurrentModals.empty())
|
||||||
|
{
|
||||||
|
mKeyboardNavigation->setModalWindow(NULL);
|
||||||
mKeyboardNavigation->restoreFocus(getMode());
|
mKeyboardNavigation->restoreFocus(getMode());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
mKeyboardNavigation->setModalWindow(mCurrentModals.top()->mMainWidget);
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::onVideoKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
|
void WindowManager::onVideoKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +81,7 @@ color_misc=0,205,205 # ????
|
|||||||
<Resource type="ResourceSkin" name="SandTextButton" size="16 16">
|
<Resource type="ResourceSkin" name="SandTextButton" size="16 16">
|
||||||
<Property key="FontName" value="Default"/>
|
<Property key="FontName" value="Default"/>
|
||||||
<Property key="TextAlign" value="Left Bottom"/>
|
<Property key="TextAlign" value="Left Bottom"/>
|
||||||
|
<Property key="NeedKey" value="true"/>
|
||||||
<BasisSkin type="SimpleText" offset="0 0 16 16" align="Stretch">
|
<BasisSkin type="SimpleText" offset="0 0 16 16" align="Stretch">
|
||||||
<State name="disabled" colour="#{fontcolour=disabled}" shift="0"/>
|
<State name="disabled" colour="#{fontcolour=disabled}" shift="0"/>
|
||||||
<State name="normal" colour="#{fontcolour=normal}" shift="0"/>
|
<State name="normal" colour="#{fontcolour=normal}" shift="0"/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user