From 4e911b7eea2d1b0abdf464b9e7640f4cac7ff7af Mon Sep 17 00:00:00 2001 From: David Capello Date: Wed, 6 May 2015 16:27:45 -0300 Subject: [PATCH] Esc key close the combobox popup --- src/app/ui/file_selector.cpp | 95 +++++++++++++++++++++++++----------- src/app/ui/file_selector.h | 9 ++-- src/ui/combobox.cpp | 18 ++++++- 3 files changed, 87 insertions(+), 35 deletions(-) diff --git a/src/app/ui/file_selector.cpp b/src/app/ui/file_selector.cpp index 92f522c04..53b9327c0 100644 --- a/src/app/ui/file_selector.cpp +++ b/src/app/ui/file_selector.cpp @@ -167,6 +167,50 @@ public: } }; +// We have this dummy/hidden widget only to handle special navigation +// with arrow keys. In the past this code was in the same FileSelector +// itself, but there were problems adding that window as a message +// filter. Mainly there is a special combination of widgets +// (comboboxes) that need to filter Esc key (e.g. to close the +// combobox popup). And we cannot pre-add a filter that send that key +// to the Manager before it's processed by the combobox filter. +class ArrowNavigator : public Widget { +public: + ArrowNavigator(FileSelector* filesel) + : Widget(kGenericWidget) + , m_filesel(filesel) { + setVisible(false); + } + +protected: + bool onProcessMessage(ui::Message* msg) override { + switch (msg->type()) { + case kOpenMessage: + getManager()->addMessageFilter(kKeyDownMessage, this); + break; + case kCloseMessage: + getManager()->removeMessageFilter(kKeyDownMessage, this); + break; + case kKeyDownMessage: + if (msg->ctrlPressed() || msg->cmdPressed()) { + KeyMessage* keyMsg = static_cast(msg); + KeyScancode scancode = keyMsg->scancode(); + switch (scancode) { + case kKeyUp: m_filesel->goUp(); return true; + case kKeyLeft: m_filesel->goBack(); return true; + case kKeyRight: m_filesel->goForward(); return true; + case kKeyDown: m_filesel->goInsideFolder(); return true; + } + } + return false; + } + return Widget::onProcessMessage(msg); + } + +private: + FileSelector* m_filesel; +}; + FileSelector::FileSelector() : Window(WithTitleBar, "") , m_navigationLocked(false) @@ -177,6 +221,7 @@ FileSelector::FileSelector() // Load the main widget. Box* box = loader.loadWidgetT("file_selector.xml", "main"); addChild(box); + addChild(new ArrowNavigator(this)); View* view; app::finder(this) @@ -234,13 +279,30 @@ FileSelector::FileSelector() m_fileList->FileSelected.connect(Bind(&FileSelector::onFileListFileSelected, this)); m_fileList->FileAccepted.connect(Bind(&FileSelector::onFileListFileAccepted, this)); m_fileList->CurrentFolderChanged.connect(Bind(&FileSelector::onFileListCurrentFolderChanged, this)); - - getManager()->addMessageFilter(kKeyDownMessage, this); } -FileSelector::~FileSelector() +void FileSelector::goBack() { - getManager()->removeMessageFilter(kKeyDownMessage, this); + onGoBack(); +} + +void FileSelector::goForward() +{ + onGoForward(); +} + +void FileSelector::goUp() +{ + onGoUp(); +} + +void FileSelector::goInsideFolder() +{ + if (m_fileList->getSelectedFileItem() && + m_fileList->getSelectedFileItem()->isBrowsable()) { + m_fileList->setCurrentFolder( + m_fileList->getSelectedFileItem()); + } } std::string FileSelector::show(const std::string& title, @@ -442,31 +504,6 @@ again: return result; } -bool FileSelector::onProcessMessage(ui::Message* msg) -{ - switch (msg->type()) { - case kKeyDownMessage: - if (msg->ctrlPressed() || msg->cmdPressed()) { - KeyMessage* keyMsg = static_cast(msg); - KeyScancode scancode = keyMsg->scancode(); - switch (scancode) { - case kKeyUp: onGoUp(); return true; - case kKeyLeft: onGoBack(); return true; - case kKeyRight: onGoForward(); return true; - case kKeyDown: - if (m_fileList->getSelectedFileItem() && - m_fileList->getSelectedFileItem()->isBrowsable()) { - m_fileList->setCurrentFolder( - m_fileList->getSelectedFileItem()); - } - return true; - } - } - break; - } - return Window::onProcessMessage(msg); -} - // Updates the content of the combo-box that shows the current // location in the file-system. void FileSelector::updateLocation() diff --git a/src/app/ui/file_selector.h b/src/app/ui/file_selector.h index 8fcbf1686..89ed8222e 100644 --- a/src/app/ui/file_selector.h +++ b/src/app/ui/file_selector.h @@ -28,16 +28,17 @@ namespace app { class FileSelector : public ui::Window { public: FileSelector(); - ~FileSelector(); + + void goBack(); + void goForward(); + void goUp(); + void goInsideFolder(); // Shows the dialog to select a file in the program. std::string show(const std::string& title, const std::string& initialPath, const std::string& showExtensions); - protected: - bool onProcessMessage(ui::Message* msg) override; - private: void updateLocation(); void updateNavigationButtons(); diff --git a/src/ui/combobox.cpp b/src/ui/combobox.cpp index a2ee62e86..957845ab6 100644 --- a/src/ui/combobox.cpp +++ b/src/ui/combobox.cpp @@ -338,6 +338,19 @@ bool ComboBox::onProcessMessage(Message* msg) m_window->moveWindow(getListBoxPos()); break; + case kKeyDownMessage: + if (m_window) { + KeyMessage* keymsg = static_cast(msg); + KeyScancode scancode = keymsg->scancode(); + + // If the popup is opened + if (scancode == kKeyEsc) { + closeListBox(); + return true; + } + } + break; + case kMouseDownMessage: if (m_window) { if (!View::getView(m_listbox)->hasMouse()) { @@ -577,10 +590,10 @@ void ComboBox::openListBox() gfx::Rect rc = getListBoxPos(); m_window->positionWindow(rc.x, rc.y); + m_window->openWindow(); getManager()->addMessageFilter(kMouseDownMessage, this); - - m_window->openWindow(); + getManager()->addMessageFilter(kKeyDownMessage, this); if (isEditable()) m_entry->requestFocus(); @@ -601,6 +614,7 @@ void ComboBox::closeListBox() m_listbox = nullptr; getManager()->removeMessageFilter(kMouseDownMessage, this); + getManager()->removeMessageFilter(kKeyDownMessage, this); m_entry->requestFocus(); onCloseListBox();