소스 검색

Replaced TryFocus event with UIMouseClick.
Added ListViewKey event for unhandled keypressed while the ListView is focused. Now ListView no longer equates enter press as a doubleclick by itself.

Lasse Öörni 15 년 전
부모
커밋
e343f0c631
9개의 변경된 파일181개의 추가작업 그리고 134개의 파일을 삭제
  1. 57 23
      Engine/UI/FileSelector.cpp
  2. 4 0
      Engine/UI/FileSelector.h
  3. 68 66
      Engine/UI/ListView.cpp
  4. 2 2
      Engine/UI/ListView.h
  5. 12 12
      Engine/UI/Menu.cpp
  6. 2 2
      Engine/UI/Menu.h
  7. 0 2
      Engine/UI/ScrollView.h
  8. 16 21
      Engine/UI/UI.cpp
  9. 20 6
      Engine/UI/UIEvents.h

+ 57 - 23
Engine/UI/FileSelector.cpp

@@ -26,6 +26,7 @@
 #include "Exception.h"
 #include "File.h"
 #include "FileSelector.h"
+#include "InputEvents.h"
 #include "LineEdit.h"
 #include "ListView.h"
 #include "Text.h"
@@ -111,6 +112,7 @@ FileSelector::FileSelector(UI* ui) :
     subscribeToEvent(mPathEdit, EVENT_TEXTFINISHED, EVENT_HANDLER(FileSelector, handlePathChanged));
     subscribeToEvent(mFileList, EVENT_ITEMSELECTED, EVENT_HANDLER(FileSelector, handleFileSelected));
     subscribeToEvent(mFileList, EVENT_ITEMDOUBLECLICKED, EVENT_HANDLER(FileSelector, handleFileDoubleClicked));
+    subscribeToEvent(mFileList, EVENT_LISTVIEWKEY, EVENT_HANDLER(FileSelector, handleFileListKey));
     subscribeToEvent(mOKButton, EVENT_PRESSED, EVENT_HANDLER(FileSelector, handleOKPressed));
     subscribeToEvent(mCancelButton, EVENT_PRESSED, EVENT_HANDLER(FileSelector, handleCancelPressed));
     
@@ -366,10 +368,44 @@ void FileSelector::refreshFiles()
     mLastUsedFilter = getFilter();
 }
 
+bool FileSelector::enterFile()
+{
+    unsigned index = mFileList->getSelection();
+    if (index >= mFileEntries.size())
+        return false;
+    
+    if (mFileEntries[index].mDirectory)
+    {
+        // If a directory doubleclicked, enter it. Recognize . and .. as a special case
+        const std::string& newPath = mFileEntries[index].mName;
+        if ((newPath != ".") &&  (newPath != ".."))
+            setPath(mPath + newPath);
+        else if (newPath == "..")
+        {
+            unsigned pos = unfixPath(mPath).rfind('/');
+            if (pos != std::string::npos)
+                setPath(mPath.substr(0, pos));
+        }
+    }
+    else
+    {
+        // Doubleclicking a file is the same as pressing OK
+        using namespace FileSelected;
+        
+        VariantMap eventData;
+        eventData[P_FILENAME] = mPath + mFileEntries[index].mName;
+        eventData[P_OK] = true;
+        sendEvent(EVENT_FILESELECTED, eventData);
+    }
+    
+    return true;
+}
+
 void FileSelector::handleFilterChanged(StringHash eventType, VariantMap& eventData)
 {
     if (mIgnoreEvents)
         return;
+    
     if (getFilter() != mLastUsedFilter)
         refreshFiles();
 }
@@ -378,6 +414,7 @@ void FileSelector::handlePathChanged(StringHash eventType, VariantMap& eventData
 {
     if (mIgnoreEvents)
         return;
+    
     // Attempt to set path. Restores old if does not exist
     setPath(mPathEdit->getText());
 }
@@ -386,6 +423,7 @@ void FileSelector::handleFileSelected(StringHash eventType, VariantMap& eventDat
 {
     if (mIgnoreEvents)
         return;
+    
     unsigned index = mFileList->getSelection();
     if (index >= mFileEntries.size())
         return;
@@ -399,37 +437,30 @@ void FileSelector::handleFileDoubleClicked(StringHash eventType, VariantMap& eve
     if (mIgnoreEvents)
         return;
     
-    unsigned index = mFileList->getSelection();
-    if (index >= mFileEntries.size())
+    enterFile();
+}
+
+void FileSelector::handleFileListKey(StringHash eventType, VariantMap& eventData)
+{
+    if (mIgnoreEvents)
         return;
     
-    if (mFileEntries[index].mDirectory)
-    {
-        // If a directory doubleclicked, enter it. Recognize . and .. as a special case
-        const std::string& newPath = mFileEntries[index].mName;
-        if ((newPath != ".") &&  (newPath != ".."))
-            setPath(mPath + newPath);
-        else if (newPath == "..")
-        {
-            unsigned pos = unfixPath(mPath).rfind('/');
-            if (pos != std::string::npos)
-                setPath(mPath.substr(0, pos));
-        }
-    }
-    else
+    using namespace ListViewKey;
+    
+    if (eventData[P_KEY].getInt() == KEY_RETURN)
     {
-        // Doubleclicking a file is the same as pressing OK
-        using namespace FileSelected;
-        
-        VariantMap eventData;
-        eventData[P_FILENAME] = mPath + mFileEntries[index].mName;
-        eventData[P_OK] = true;
-        sendEvent(EVENT_FILESELECTED, eventData);
+        bool entered = enterFile();
+        // When a key is used to enter a directory, select the first file if no selection
+        if ((entered) && (!mFileList->getSelectedItem()))
+            mFileList->setSelection(0);
     }
 }
 
 void FileSelector::handleOKPressed(StringHash eventType, VariantMap& eventData)
 {
+    if (mIgnoreEvents)
+        return;
+    
     const std::string& fileName = getFileName();
     if (!fileName.empty())
     {
@@ -444,6 +475,9 @@ void FileSelector::handleOKPressed(StringHash eventType, VariantMap& eventData)
 
 void FileSelector::handleCancelPressed(StringHash eventType, VariantMap& eventData)
 {
+    if (mIgnoreEvents)
+        return;
+    
     using namespace FileSelected;
     
     VariantMap newEventData;

+ 4 - 0
Engine/UI/FileSelector.h

@@ -97,6 +97,8 @@ public:
 private:
     //! Refresh the directory listing
     void refreshFiles();
+    //! Enter a directory or confirm a file. Return true if selection valid
+    bool enterFile();
     //! Handle filter changed
     void handleFilterChanged(StringHash eventType, VariantMap& eventData);
     //! Handle path edited
@@ -105,6 +107,8 @@ private:
     void handleFileSelected(StringHash eventType, VariantMap& eventData);
     //! Handle file doubleclicked from the list (enter directory / OK the file selection)
     void handleFileDoubleClicked(StringHash eventType, VariantMap& eventData);
+    //! Handle file list key pressed
+    void handleFileListKey(StringHash eventType, VariantMap& eventData);
     //! Handle OK button pressed
     void handleOKPressed(StringHash eventType, VariantMap& eventData);
     //! Handle cancel button pressed

+ 68 - 66
Engine/UI/ListView.cpp

@@ -41,7 +41,7 @@ ListView::ListView(const std::string& name) :
     container->setLayout(LM_VERTICAL);
     setContentElement(container);
     
-    subscribeToEvent(EVENT_TRYFOCUS, EVENT_HANDLER(ListView, handleTryFocus));
+    subscribeToEvent(EVENT_UIMOUSECLICK, EVENT_HANDLER(ListView, handleUIMouseClick));
 }
 
 ListView::~ListView()
@@ -81,76 +81,75 @@ void ListView::update(float timeStep)
 void ListView::onKey(int key, int buttons, int qualifiers)
 {
     // If no selection, can not move with keys
-    if ((mSelection == M_MAX_UNSIGNED) || (!getNumItems()))
-        return;
-    
-    switch (key)
+    if ((mSelection != M_MAX_UNSIGNED) && (getNumItems()))
     {
-    case KEY_UP:
-        if (qualifiers & QUAL_CTRL)
-            setSelection(0);
-        else
-            changeSelection(-1);
-        break;
-        
-    case KEY_DOWN:
-        if (qualifiers & QUAL_CTRL)
-            setSelection(getNumItems() - 1);
-        else
-            changeSelection(1);
-        break;
-        
-    case KEY_PAGEUP:
+        switch (key)
         {
-            // Convert page step to pixels and see how many items we have to skip to reach that many pixels
-            int stepPixels = ((int)(mPageStep * mScrollPanel->getHeight())) - getSelectedItem()->getHeight();
-            unsigned newSelection = mSelection;
-            while (newSelection)
+        case KEY_UP:
+            if (qualifiers & QUAL_CTRL)
+                setSelection(0);
+            else
+                changeSelection(-1);
+            break;
+            
+        case KEY_DOWN:
+            if (qualifiers & QUAL_CTRL)
+                setSelection(getNumItems() - 1);
+            else
+                changeSelection(1);
+            break;
+            
+        case KEY_PAGEUP:
             {
-                int height = getItem(newSelection)->getHeight();
-                if (stepPixels < height)
-                    break;
-                stepPixels -= height;
-                --newSelection;
+                // Convert page step to pixels and see how many items we have to skip to reach that many pixels
+                int stepPixels = ((int)(mPageStep * mScrollPanel->getHeight())) - getSelectedItem()->getHeight();
+                unsigned newSelection = mSelection;
+                while (newSelection)
+                {
+                    int height = getItem(newSelection)->getHeight();
+                    if (stepPixels < height)
+                        break;
+                    stepPixels -= height;
+                    --newSelection;
+                }
+                setSelection(newSelection);
             }
-            setSelection(newSelection);
-        }
-        break;
-        
-    case KEY_PAGEDOWN:
-        {
-            int stepPixels = ((int)(mPageStep * mScrollPanel->getHeight())) - getSelectedItem()->getHeight();
-            unsigned newSelection = mSelection;
-            while (newSelection < getNumItems() - 1)
+            break;
+            
+        case KEY_PAGEDOWN:
             {
-                int height = getItem(newSelection)->getHeight();
-                if (stepPixels < height)
-                    break;
-                stepPixels -= height;
-                ++newSelection;
+                int stepPixels = ((int)(mPageStep * mScrollPanel->getHeight())) - getSelectedItem()->getHeight();
+                unsigned newSelection = mSelection;
+                while (newSelection < getNumItems() - 1)
+                {
+                    int height = getItem(newSelection)->getHeight();
+                    if (stepPixels < height)
+                        break;
+                    stepPixels -= height;
+                    ++newSelection;
+                }
+                setSelection(newSelection);
             }
-            setSelection(newSelection);
-        }
-        break;
-        
-    case KEY_HOME:
-        setSelection(0);
-        break;
-        
-    case KEY_END:
-        setSelection(getNumItems() - 1);
-        break;
-    
-    case KEY_RETURN:
-        if (mSelection != M_MAX_UNSIGNED)
-        {
-            VariantMap eventData;
-            eventData[ItemDoubleClicked::P_ELEMENT] = (void*)this;
-            eventData[ItemDoubleClicked::P_SELECTION] = mSelection;
-            sendEvent(EVENT_ITEMDOUBLECLICKED, eventData);
+            break;
+            
+        case KEY_HOME:
+            setSelection(0);
+            break;
+            
+        case KEY_END:
+            setSelection(getNumItems() - 1);
+            break;
         }
-        break;
     }
+    
+    using namespace ListViewKey;
+    
+    VariantMap eventData;
+    eventData[P_ELEMENT] = (void*)this;
+    eventData[P_KEY] = key;
+    eventData[P_BUTTONS] = buttons;
+    eventData[P_QUALIFIERS] = qualifiers;
+    sendEvent(EVENT_LISTVIEWKEY, eventData);
 }
 
 void ListView::onResize()
@@ -305,14 +304,17 @@ void ListView::ensureItemVisibility()
     setViewPosition(newView);
 }
 
-void ListView::handleTryFocus(StringHash eventType, VariantMap& eventData)
+void ListView::handleUIMouseClick(StringHash eventType, VariantMap& eventData)
 {
-    UIElement* focusElement = static_cast<UIElement*>(eventData[TryFocus::P_ELEMENT].getPtr());
+    if (eventData[UIMouseClick::P_BUTTON].getInt() != MOUSEB_LEFT)
+        return;
+    
+    UIElement* element = static_cast<UIElement*>(eventData[UIMouseClick::P_ELEMENT].getPtr());
     
     unsigned numItems = getNumItems();
     for (unsigned i = 0; i < numItems; ++i)
     {
-        if (focusElement == getItem(i))
+        if (element == getItem(i))
         {
             bool isDoubleClick = false;
             if ((mDoubleClickTimer > 0.0f) && (mSelection == i))

+ 2 - 2
Engine/UI/ListView.h

@@ -100,8 +100,8 @@ protected:
     float mDoubleClickTimer;
     
 private:
-    //! Handle focus change to check for selection change
-    void handleTryFocus(StringHash eventType, VariantMap& eventData);
+    //! Handle global UI mouseclick to check for selection change
+    void handleUIMouseClick(StringHash eventType, VariantMap& eventData);
 };
 
 #endif // UI_LISTVIEW_H

+ 12 - 12
Engine/UI/Menu.cpp

@@ -33,7 +33,7 @@ Menu::Menu(const std::string& name) :
     mPopupOffset(IntVector2::sZero),
     mShowPopup(false)
 {
-    subscribeToEvent(EVENT_TRYFOCUS, EVENT_HANDLER(Menu, handleTryFocus));
+    subscribeToEvent(EVENT_UIMOUSECLICK, EVENT_HANDLER(Menu, handleUIMouseClick));
 }
 
 Menu::~Menu()
@@ -142,33 +142,33 @@ void Menu::showPopup(bool enable)
     mSelected = enable;
 }
 
-void Menu::handleTryFocus(StringHash eventType, VariantMap& eventData)
+void Menu::handleUIMouseClick(StringHash eventType, VariantMap& eventData)
 {
     if (!mShowPopup)
         return;
     
-    using namespace TryFocus;
+    using namespace UIMouseClick;
     
-    UIElement* focusElement = static_cast<UIElement*>(eventData[P_ELEMENT].getPtr());
+    UIElement* element = static_cast<UIElement*>(eventData[P_ELEMENT].getPtr());
     UIElement* root = getRootElement();
     
-    // If global defocus, hide the popup
-    if (!focusElement)
+    // If clicked emptiness, hide the popup
+    if (!element)
     {
         showPopup(false);
         return;
     }
     
-    // Otherwise see if the focused element has either the menu item or the popup in its parent chain.
+    // Otherwise see if the clicked element has either the menu item or the popup in its parent chain.
     // In that case, do not hide
-    while (focusElement)
+    while (element)
     {
-        if ((focusElement == this) || (focusElement == mPopup))
+        if ((element == this) || (element == mPopup))
             return;
-        if (focusElement->getParent() == root)
-            focusElement = focusElement->getOrigin();
+        if (element->getParent() == root)
+            element = element->getOrigin();
         else
-            focusElement = focusElement->getParent();
+            element = element->getParent();
     }
     
     showPopup(false);

+ 2 - 2
Engine/UI/Menu.h

@@ -68,8 +68,8 @@ protected:
     bool mShowPopup;
     
 private:
-    //! Handle focus change attempt in case the popup needs to be hidden
-    void handleTryFocus(StringHash eventType, VariantMap& eventData);
+    //! Handle global UI mouseclick to check for hiding the popup
+    void handleUIMouseClick(StringHash eventType, VariantMap& eventData);
 };
 
 #endif // UI_MENU_H

+ 0 - 2
Engine/UI/ScrollView.h

@@ -113,8 +113,6 @@ private:
     void handleScrollBarVisibleChanged(StringHash eventType, VariantMap& eventData);
     //! Handle content element resized
     void handleElementResized(StringHash eventType, VariantMap& eventData);
-    //! Handle focus change attempt (check if ScrollView needs to be focused)
-    void handleTryFocus(StringHash eventType, VariantMap& eventData);
 };
 
 #endif // UI_SCROLLVIEW_H

+ 16 - 21
Engine/UI/UI.cpp

@@ -113,22 +113,6 @@ void UI::setCursor(Cursor* cursor)
 
 void UI::setFocusElement(UIElement* element)
 {
-    using namespace TryFocus;
-   
-    UIElement* originalElement = element;
-    WeakPtr<UIElement> elementWeak(element);
-    
-    VariantMap eventData;
-    eventData[P_ELEMENT] = (void*)element;
-    sendEvent(EVENT_TRYFOCUS, eventData);
-    
-    // The event receivers may optionally divert the focus
-    element = static_cast<UIElement*>(eventData[P_ELEMENT].getPtr());
-    // If element is unchanged, check that it did not expire (the event may have caused its deletion)
-    // In that case it is better to not touch focus at all
-    if ((element) && (element == originalElement) && (elementWeak.isExpired()))
-        return;
-    
     if (element)
     {
         // Return if already has focus
@@ -498,16 +482,27 @@ void UI::handleMouseMove(StringHash eventType, VariantMap& eventData)
 
 void UI::handleMouseButtonDown(StringHash eventType, VariantMap& eventData)
 {
-    using namespace MouseButtonDown;
-    
-    mMouseButtons = eventData[P_BUTTONS].getInt();
-    mQualifiers = eventData[P_QUALIFIERS].getInt();
-    int button = eventData[P_BUTTON].getInt();
+    mMouseButtons = eventData[MouseButtonDown::P_BUTTONS].getInt();
+    mQualifiers = eventData[MouseButtonDown::P_QUALIFIERS].getInt();
+    int button = eventData[MouseButtonDown::P_BUTTON].getInt();
     
     if ((mCursor) && (mCursor->isVisible()))
     {
         IntVector2 pos = mCursor->getPosition();
         WeakPtr<UIElement> element(getElementAt(pos));
+        
+        // First send global click event, with or without an element
+        using namespace UIMouseClick;
+        
+        VariantMap eventData;
+        eventData[UIMouseClick::P_ELEMENT] = (void*)element.getPtr();
+        eventData[UIMouseClick::P_X] = pos.mX;
+        eventData[UIMouseClick::P_Y] = pos.mY;
+        eventData[UIMouseClick::P_BUTTON] = button;
+        eventData[UIMouseClick::P_BUTTONS] = mMouseButtons;
+        eventData[UIMouseClick::P_QUALIFIERS] = mQualifiers;
+        sendEvent(EVENT_UIMOUSECLICK, eventData);
+        
         if (element)
         {
             // Handle focusing & bringing to front

+ 20 - 6
Engine/UI/UIEvents.h

@@ -26,6 +26,17 @@
 
 #include "Event.h"
 
+//! Mouse click in the UI
+DEFINE_EVENT(EVENT_UIMOUSECLICK, UIMouseClick)
+{
+    EVENT_PARAM(P_ELEMENT, Element);            // UIElement pointer
+    EVENT_PARAM(P_X, X);                        // int
+    EVENT_PARAM(P_Y, Y);                        // int
+    EVENT_PARAM(P_BUTTON, Button);              // int
+    EVENT_PARAM(P_BUTTONS, Buttons);            // int
+    EVENT_PARAM(P_QUALIFIERS, Qualifiers);      // int
+}
+
 //! UI element resized
 DEFINE_EVENT(EVENT_RESIZED, Resized)
 {
@@ -41,12 +52,6 @@ DEFINE_EVENT(EVENT_VISIBLECHANGED, VisibleChanged)
     EVENT_PARAM(P_VISIBLE, Visible);            // bool
 }
 
-//! Trying to focus an UI element. Sent before checking for success. Also sent with 0 pointer for global defocus
-DEFINE_EVENT(EVENT_TRYFOCUS, TryFocus)
-{
-    EVENT_PARAM(P_ELEMENT, Element);            // UIElement pointer
-}
-
 //! UI element focused
 DEFINE_EVENT(EVENT_FOCUSED, Focused)
 {
@@ -128,6 +133,15 @@ DEFINE_EVENT(EVENT_ITEMDOUBLECLICKED, ItemDoubleClicked)
     EVENT_PARAM(P_SELECTION, Selection);        // int
 }
 
+//! Listview unhandled key pressed
+DEFINE_EVENT(EVENT_LISTVIEWKEY, ListViewKey)
+{
+    EVENT_PARAM(P_ELEMENT, Element);            // UIElement pointer
+    EVENT_PARAM(P_KEY, Key);                    // int
+    EVENT_PARAM(P_BUTTONS, Buttons);            // int
+    EVENT_PARAM(P_QUALIFIERS, Qualifiers);      // int
+}
+
 //! Fileselector choice
 DEFINE_EVENT(EVENT_FILESELECTED, FileSelected)
 {