mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 06:35:30 +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()
|
||||
{
|
||||
WindowModal::onOpen();
|
||||
center();
|
||||
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
@ -88,6 +87,12 @@ namespace MWGui
|
||||
mBribe1000Button->setEnabled (playerGold >= 1000);
|
||||
|
||||
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 MyGUI::Widget* getDefaultKeyFocus();
|
||||
|
||||
private:
|
||||
MyGUI::Button* mCancelButton;
|
||||
MyGUI::Button* mAdmireButton;
|
||||
|
@ -38,6 +38,7 @@ bool shouldAcceptKeyFocus(MyGUI::Widget* w)
|
||||
|
||||
KeyboardNavigation::KeyboardNavigation()
|
||||
: mCurrentFocus(nullptr)
|
||||
, mModalWindow(nullptr)
|
||||
{
|
||||
MyGUI::WidgetManager::getInstance().registerUnlinker(this);
|
||||
}
|
||||
@ -51,9 +52,13 @@ void KeyboardNavigation::saveFocus(int mode)
|
||||
{
|
||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||
if (shouldAcceptKeyFocus(focus))
|
||||
{
|
||||
mKeyFocus[mode] = focus;
|
||||
}
|
||||
else
|
||||
{
|
||||
mKeyFocus[mode] = mCurrentFocus;
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||
@ -98,7 +110,7 @@ void KeyboardNavigation::onFrame()
|
||||
}
|
||||
|
||||
// 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);
|
||||
focus = mCurrentFocus;
|
||||
@ -119,6 +131,25 @@ void KeyboardNavigation::onFrame()
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
bool isCycle = (direction == D_Prev || direction == D_Next);
|
||||
if (focus && isCycle && focus->getUserString("AcceptTab") == "true")
|
||||
return false;
|
||||
|
||||
@ -230,6 +247,23 @@ bool KeyboardNavigation::switchFocus(int direction, bool wrap)
|
||||
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()
|
||||
{
|
||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||
|
@ -23,15 +23,23 @@ namespace MWGui
|
||||
|
||||
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:
|
||||
bool switchFocus(int direction, bool wrap);
|
||||
|
||||
bool selectFirstWidget();
|
||||
|
||||
/// Send button press event to focused button
|
||||
bool accept();
|
||||
|
||||
std::map<int, MyGUI::Widget*> mKeyFocus;
|
||||
|
||||
MyGUI::Widget* mCurrentFocus;
|
||||
MyGUI::Widget* mModalWindow;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -67,14 +67,17 @@ WindowModal::WindowModal(const std::string& parLayout)
|
||||
|
||||
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
|
||||
|
||||
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
|
||||
MyGUI::InputManager::getInstance ().addWidgetModal (mMainWidget);
|
||||
MyGUI::InputManager::getInstance().setKeyFocusWidget(focus);
|
||||
}
|
||||
|
||||
void WindowModal::onClose()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeCurrentModal(this);
|
||||
|
||||
MyGUI::InputManager::getInstance ().removeWidgetModal (mMainWidget);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ namespace MWGui
|
||||
public:
|
||||
WindowBase(const std::string& parLayout);
|
||||
|
||||
virtual MyGUI::Widget* getDefaultKeyFocus() { return NULL; }
|
||||
|
||||
// Events
|
||||
typedef MyGUI::delegates::CMultiDelegate1<WindowBase*> EventHandle_WindowBase;
|
||||
|
||||
|
@ -1738,6 +1738,10 @@ namespace MWGui
|
||||
mKeyboardNavigation->saveFocus(getMode());
|
||||
|
||||
mCurrentModals.push(input);
|
||||
mKeyboardNavigation->restoreFocus(-1);
|
||||
|
||||
mKeyboardNavigation->setModalWindow(input->mMainWidget);
|
||||
mKeyboardNavigation->setDefaultFocus(input->mMainWidget, input->getDefaultKeyFocus());
|
||||
}
|
||||
|
||||
void WindowManager::removeCurrentModal(WindowModal* input)
|
||||
@ -1747,12 +1751,20 @@ namespace MWGui
|
||||
if(!mCurrentModals.empty())
|
||||
{
|
||||
if(input == mCurrentModals.top())
|
||||
{
|
||||
mCurrentModals.pop();
|
||||
mKeyboardNavigation->saveFocus(-1);
|
||||
}
|
||||
else
|
||||
std::cout << " warning: modal widget " << input << " " << typeid(input).name() << " not found " << std::endl;
|
||||
}
|
||||
if (mCurrentModals.empty())
|
||||
{
|
||||
mKeyboardNavigation->setModalWindow(NULL);
|
||||
mKeyboardNavigation->restoreFocus(getMode());
|
||||
}
|
||||
else
|
||||
mKeyboardNavigation->setModalWindow(mCurrentModals.top()->mMainWidget);
|
||||
}
|
||||
|
||||
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">
|
||||
<Property key="FontName" value="Default"/>
|
||||
<Property key="TextAlign" value="Left Bottom"/>
|
||||
<Property key="NeedKey" value="true"/>
|
||||
<BasisSkin type="SimpleText" offset="0 0 16 16" align="Stretch">
|
||||
<State name="disabled" colour="#{fontcolour=disabled}" shift="0"/>
|
||||
<State name="normal" colour="#{fontcolour=normal}" shift="0"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user