Browse Source

Changed ListView to use PODVector for the selections, and explicitly sort them when necessary.
Circumvented ListView selections set accessor not working by defining it as a method instead.

Lasse Öörni 13 years ago
parent
commit
1ca858cc2a

+ 3 - 1
Bin/Data/Scripts/Editor/EditorScene.as

@@ -585,8 +585,10 @@ void SceneSelectAll()
     {
     {
         BeginSelectionModify();
         BeginSelectionModify();
         Array<Node@> rootLevelNodes = editorScene.GetChildren();
         Array<Node@> rootLevelNodes = editorScene.GetChildren();
+        Array<uint> indices;
         for (uint i = 0; i < rootLevelNodes.length; ++i)
         for (uint i = 0; i < rootLevelNodes.length; ++i)
-            list.AddSelection(GetNodeListIndex(rootLevelNodes[i]));
+            indices.Push(GetNodeListIndex(rootLevelNodes[i]));
+        list.SetSelections(indices);
         EndSelectionModify();
         EndSelectionModify();
     }
     }
 }
 }

+ 2 - 1
Docs/ScriptAPI.dox

@@ -3466,6 +3466,7 @@ Methods:<br>
 - void RemoveSelection(uint)
 - void RemoveSelection(uint)
 - void ToggleSelection(uint)
 - void ToggleSelection(uint)
 - void ChangeSelection(int, bool)
 - void ChangeSelection(int, bool)
+- void SetSelections(uint[]@)
 - void ClearSelection()
 - void ClearSelection()
 - void SetChildItemsVisible(uint, bool)
 - void SetChildItemsVisible(uint, bool)
 - void SetChildItemsVisible(bool)
 - void SetChildItemsVisible(bool)
@@ -3530,7 +3531,7 @@ Properties:<br>
 - uint numItems (readonly)
 - uint numItems (readonly)
 - UIElement@[] items (readonly)
 - UIElement@[] items (readonly)
 - uint selection
 - uint selection
-- uint[]@ selections
+- uint[]@ selections (readonly)
 - UIElement@ selectedItem (readonly)
 - UIElement@ selectedItem (readonly)
 - UIElement@[]@ selectedItems (readonly)
 - UIElement@[]@ selectedItems (readonly)
 - HighlightMode highlightMode
 - HighlightMode highlightMode

+ 1 - 1
Engine/Engine/UIAPI.cpp

@@ -222,6 +222,7 @@ static void RegisterListView(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ListView", "void RemoveSelection(uint)", asMETHOD(ListView, RemoveSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void RemoveSelection(uint)", asMETHOD(ListView, RemoveSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void ToggleSelection(uint)", asMETHOD(ListView, ToggleSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void ToggleSelection(uint)", asMETHOD(ListView, ToggleSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void ChangeSelection(int, bool)", asMETHOD(ListView, ChangeSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void ChangeSelection(int, bool)", asMETHOD(ListView, ChangeSelection), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ListView", "void SetSelections(Array<uint>@+)", asFUNCTION(ListViewSetSelections), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("ListView", "void ClearSelection()", asMETHOD(ListView, ClearSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void ClearSelection()", asMETHOD(ListView, ClearSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void SetChildItemsVisible(uint, bool)", asMETHODPR(ListView, SetChildItemsVisible, (unsigned, bool), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void SetChildItemsVisible(uint, bool)", asMETHODPR(ListView, SetChildItemsVisible, (unsigned, bool), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void SetChildItemsVisible(bool)", asMETHODPR(ListView, SetChildItemsVisible, (bool), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void SetChildItemsVisible(bool)", asMETHODPR(ListView, SetChildItemsVisible, (bool), void), asCALL_THISCALL);
@@ -242,7 +243,6 @@ static void RegisterListView(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ListView", "UIElement@+ get_items(uint) const", asMETHOD(ListView, GetItem), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "UIElement@+ get_items(uint) const", asMETHOD(ListView, GetItem), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void set_selection(uint)", asMETHOD(ListView, SetSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "void set_selection(uint)", asMETHOD(ListView, SetSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "uint get_selection() const", asMETHOD(ListView, GetSelection), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "uint get_selection() const", asMETHOD(ListView, GetSelection), asCALL_THISCALL);
-    engine->RegisterObjectMethod("ListView", "void set_selections(Array<uint>@+)", asFUNCTION(ListViewSetSelections), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("ListView", "Array<uint>@ get_selections() const", asFUNCTION(ListViewGetSelections), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("ListView", "Array<uint>@ get_selections() const", asFUNCTION(ListViewGetSelections), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("ListView", "UIElement@+ get_selectedItem() const", asMETHOD(ListView, GetSelectedItem), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "UIElement@+ get_selectedItem() const", asMETHOD(ListView, GetSelectedItem), asCALL_THISCALL);
     engine->RegisterObjectMethod("ListView", "Array<UIElement@>@ get_selectedItems() const", asFUNCTION(ListViewGetSelectedItems), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("ListView", "Array<UIElement@>@ get_selectedItems() const", asFUNCTION(ListViewGetSelectedItems), asCALL_CDECL_OBJLAST);

+ 108 - 103
Engine/UI/ListView.cpp

@@ -279,15 +279,12 @@ void ListView::InsertItem(unsigned index, UIElement* item)
     // If necessary, shift the following selections
     // If necessary, shift the following selections
     if (!selections_.Empty())
     if (!selections_.Empty())
     {
     {
-        HashSet<unsigned> prevSelections = selections_;
-        selections_.Clear();
-        for (HashSet<unsigned>::Iterator j = prevSelections.Begin(); j != prevSelections.End(); ++j)
+        for (unsigned i = 0; i < selections_.Size(); ++i)
         {
         {
-            if (*j >= index)
-                selections_.Insert(*j + 1);
-            else
-                selections_.Insert(*j);
+            if (selections_[i] >= index)
+                ++selections_[i];
         }
         }
+        
         UpdateSelectionEffect();
         UpdateSelectionEffect();
     }
     }
 }
 }
@@ -301,7 +298,7 @@ void ListView::RemoveItem(UIElement* item)
         if (GetItem(i) == item)
         if (GetItem(i) == item)
         {
         {
             item->SetSelected(false);
             item->SetSelected(false);
-            selections_.Erase(i);
+            selections_.Erase(selections_.Find(i));
             
             
             // Remove any child items in hierarchy mode
             // Remove any child items in hierarchy mode
             unsigned removed = 1;
             unsigned removed = 1;
@@ -330,15 +327,12 @@ void ListView::RemoveItem(UIElement* item)
             // If necessary, shift the following selections
             // If necessary, shift the following selections
             if (!selections_.Empty())
             if (!selections_.Empty())
             {
             {
-                HashSet<unsigned> prevSelections = selections_;
-                selections_.Clear();
-                for (HashSet<unsigned>::Iterator j = prevSelections.Begin(); j != prevSelections.End(); ++j)
+                for (unsigned j = 0; j < selections_.Size(); ++j)
                 {
                 {
-                    if (*j > i)
-                        selections_.Insert(*j - removed);
-                    else
-                        selections_.Insert(*j);
+                    if (selections_[j] > i)
+                        selections_[j] -= removed;
                 }
                 }
+                
                 UpdateSelectionEffect();
                 UpdateSelectionEffect();
             }
             }
             break;
             break;
@@ -368,18 +362,72 @@ void ListView::RemoveAllItems()
 
 
 void ListView::SetSelection(unsigned index)
 void ListView::SetSelection(unsigned index)
 {
 {
-    HashSet<unsigned> indices;
-    indices.Insert(index);
+    PODVector<unsigned> indices;
+    indices.Push(index);
     SetSelections(indices);
     SetSelections(indices);
     EnsureItemVisibility(index);
     EnsureItemVisibility(index);
 }
 }
 
 
 void ListView::SetSelections(const PODVector<unsigned>& indices)
 void ListView::SetSelections(const PODVector<unsigned>& indices)
 {
 {
-    HashSet<unsigned> newSelection;
+    unsigned numItems = GetNumItems();
+    
+    // Remove first items that should no longer be selected
+    for (PODVector<unsigned>::Iterator i = selections_.Begin(); i != selections_.End();)
+    {
+        unsigned index = *i;
+        if (!indices.Contains(index))
+        {
+            i = selections_.Erase(i);
+            
+            using namespace ItemSelected;
+            
+            VariantMap eventData;
+            eventData[P_ELEMENT] = (void*)this;
+            eventData[P_SELECTION] = index;
+            SendEvent(E_ITEMDESELECTED, eventData);
+        }
+        else
+            ++i;
+    }
+    
+    bool added = false;
+    
+    // Then add missing items
     for (PODVector<unsigned>::ConstIterator i = indices.Begin(); i != indices.End(); ++i)
     for (PODVector<unsigned>::ConstIterator i = indices.Begin(); i != indices.End(); ++i)
-        newSelection.Insert(*i);
-    SetSelections(newSelection);
+    {
+        unsigned index = *i;
+        if (index < numItems)
+        {
+            // In singleselect mode, resend the event even for the same selection
+            bool duplicate = selections_.Contains(index);
+            if (!duplicate || !multiselect_)
+            {
+                if (!duplicate)
+                {
+                    selections_.Push(index);
+                    added = true;
+                }
+                
+                using namespace ItemSelected;
+                
+                VariantMap eventData;
+                eventData[P_ELEMENT] = (void*)this;
+                eventData[P_SELECTION] = *i;
+                SendEvent(E_ITEMSELECTED, eventData);
+            }
+        }
+        // If no multiselect enabled, allow setting only one item
+        if (!multiselect_)
+            break;
+    }
+    
+    // Re-sort selections if necessary
+    if (added)
+        Sort(selections_.Begin(), selections_.End());
+    
+    UpdateSelectionEffect();
+    SendEvent(E_SELECTIONCHANGED);
 }
 }
 
 
 void ListView::AddSelection(unsigned index)
 void ListView::AddSelection(unsigned index)
@@ -391,10 +439,24 @@ void ListView::AddSelection(unsigned index)
         if (index >= GetNumItems())
         if (index >= GetNumItems())
             return;
             return;
         
         
-        HashSet<unsigned> newSelections = selections_;
-        newSelections.Insert(index);
-        SetSelections(newSelections);
+        PODVector<unsigned>::Iterator i = selections_.Find(index);
+        if (i == selections_.End())
+        {
+            selections_.Push(index);
+            
+            using namespace ItemSelected;
+            
+            VariantMap eventData;
+            eventData[P_ELEMENT] = (void*)this;
+            eventData[P_SELECTION] = index;
+            SendEvent(E_ITEMSELECTED, eventData);
+            
+            Sort(selections_.Begin(), selections_.End());
+        }
+        
         EnsureItemVisibility(index);
         EnsureItemVisibility(index);
+        UpdateSelectionEffect();
+        SendEvent(E_SELECTIONCHANGED);
     }
     }
 }
 }
 
 
@@ -403,10 +465,22 @@ void ListView::RemoveSelection(unsigned index)
     if (index >= GetNumItems())
     if (index >= GetNumItems())
         return;
         return;
     
     
-    HashSet<unsigned> newSelections = selections_;
-    newSelections.Erase(index);
-    SetSelections(newSelections);
+    PODVector<unsigned>::Iterator i = selections_.Find(index);
+    if (i != selections_.End())
+    {
+        selections_.Erase(i);
+        
+        using namespace ItemSelected;
+        
+        VariantMap eventData;
+        eventData[P_ELEMENT] = (void*)this;
+        eventData[P_SELECTION] = index;
+        SendEvent(E_ITEMDESELECTED, eventData);
+    }
+    
     EnsureItemVisibility(index);
     EnsureItemVisibility(index);
+    UpdateSelectionEffect();
+    SendEvent(E_SELECTIONCHANGED);
 }
 }
 
 
 void ListView::ToggleSelection(unsigned index)
 void ListView::ToggleSelection(unsigned index)
@@ -466,7 +540,7 @@ void ListView::ChangeSelection(int delta, bool additive)
 
 
 void ListView::ClearSelection()
 void ListView::ClearSelection()
 {
 {
-    SetSelections(HashSet<unsigned>());
+    SetSelections(PODVector<unsigned>());
     UpdateSelectionEffect();
     UpdateSelectionEffect();
 }
 }
 
 
@@ -594,17 +668,6 @@ unsigned ListView::GetSelection() const
         return GetSelections().Front();
         return GetSelections().Front();
 }
 }
 
 
-PODVector<unsigned> ListView::GetSelections() const
-{
-    PODVector<unsigned> sortedIndices;
-    
-    for (HashSet<unsigned>::ConstIterator i = selections_.Begin(); i != selections_.End(); ++i)
-        sortedIndices.Push(*i);
-    Sort(sortedIndices.Begin(), sortedIndices.End());
-    
-    return sortedIndices;
-}
-
 UIElement* ListView::GetSelectedItem() const
 UIElement* ListView::GetSelectedItem() const
 {
 {
     return contentElement_->GetChild(GetSelection());
     return contentElement_->GetChild(GetSelection());
@@ -613,13 +676,8 @@ UIElement* ListView::GetSelectedItem() const
 PODVector<UIElement*> ListView::GetSelectedItems() const
 PODVector<UIElement*> ListView::GetSelectedItems() const
 {
 {
     PODVector<UIElement*> ret;
     PODVector<UIElement*> ret;
-    PODVector<unsigned> sortedIndices;
-    
-    for (HashSet<unsigned>::ConstIterator i = selections_.Begin(); i != selections_.End(); ++i)
-        sortedIndices.Push(*i);
-    Sort(sortedIndices.Begin(), sortedIndices.End());
     
     
-    for (PODVector<unsigned>::ConstIterator i = sortedIndices.Begin(); i != sortedIndices.End(); ++i)
+    for (PODVector<unsigned>::ConstIterator i = selections_.Begin(); i != selections_.End(); ++i)
     {
     {
         UIElement* item = GetItem(*i);
         UIElement* item = GetItem(*i);
         if (item)
         if (item)
@@ -672,59 +730,6 @@ void ListView::EnsureItemVisibility(UIElement* item)
     SetViewPosition(newView);
     SetViewPosition(newView);
 }
 }
 
 
-void ListView::SetSelections(const HashSet<unsigned>& indices)
-{
-    unsigned numItems = GetNumItems();
-    
-    // Remove first items that should no longer be selected
-    for (HashSet<unsigned>::Iterator i = selections_.Begin(); i != selections_.End();)
-    {
-        unsigned index = *i;
-        if (!indices.Contains(index))
-        {
-            HashSet<unsigned>::Iterator current = i++;
-            selections_.Erase(current);
-            
-            using namespace ItemSelected;
-            
-            VariantMap eventData;
-            eventData[P_ELEMENT] = (void*)this;
-            eventData[P_SELECTION] = index;
-            SendEvent(E_ITEMDESELECTED, eventData);
-        }
-        else
-            ++i;
-    }
-    
-    // Then add missing items
-    for (HashSet<unsigned>::ConstIterator i = indices.Begin(); i != indices.End(); ++i)
-    {
-        unsigned index = *i;
-        if (index < numItems)
-        {
-            // In singleselect mode, resend the event even for the same selection
-            if (selections_.Find(index) == selections_.End() || !multiselect_)
-            {
-                selections_.Insert(*i);
-                
-                using namespace ItemSelected;
-                
-                VariantMap eventData;
-                eventData[P_ELEMENT] = (void*)this;
-                eventData[P_SELECTION] = *i;
-                SendEvent(E_ITEMSELECTED, eventData);
-            }
-        }
-        // If no multiselect enabled, allow setting only one item
-        if (!multiselect_)
-            break;
-    }
-    
-    SendEvent(E_SELECTIONCHANGED);
-    
-    UpdateSelectionEffect();
-}
-
 void ListView::HandleUIMouseClick(StringHash eventType, VariantMap& eventData)
 void ListView::HandleUIMouseClick(StringHash eventType, VariantMap& eventData)
 {
 {
     if (eventData[UIMouseClick::P_BUTTON].GetInt() != MOUSEB_LEFT)
     if (eventData[UIMouseClick::P_BUTTON].GetInt() != MOUSEB_LEFT)
@@ -766,34 +771,34 @@ void ListView::HandleUIMouseClick(StringHash eventType, VariantMap& eventData)
                     {
                     {
                         unsigned first = selections_.Front();
                         unsigned first = selections_.Front();
                         unsigned last = selections_.Back();
                         unsigned last = selections_.Back();
-                        HashSet<unsigned> newSelections = selections_;
+                        PODVector<unsigned> newSelections = selections_;
                         if (i == first || i == last)
                         if (i == first || i == last)
                         {
                         {
                             for (unsigned j = first; j <= last; ++j)
                             for (unsigned j = first; j <= last; ++j)
-                                newSelections.Insert(j);
+                                newSelections.Push(j);
                         }
                         }
                         else if (i < first)
                         else if (i < first)
                         {
                         {
                             for (unsigned j = i; j <= first; ++j)
                             for (unsigned j = i; j <= first; ++j)
-                                newSelections.Insert(j);
+                                newSelections.Push(j);
                         }
                         }
                         else if (i < last)
                         else if (i < last)
                         {
                         {
                             if ((abs((int)i - (int)first)) <= (abs((int)i - (int)last)))
                             if ((abs((int)i - (int)first)) <= (abs((int)i - (int)last)))
                             {
                             {
                                 for (unsigned j = first; j <= i; ++j)
                                 for (unsigned j = first; j <= i; ++j)
-                                    newSelections.Insert(j);
+                                    newSelections.Push(j);
                             }
                             }
                             else
                             else
                             {
                             {
                                 for (unsigned j = i; j <= last; ++j)
                                 for (unsigned j = i; j <= last; ++j)
-                                    newSelections.Insert(j);
+                                    newSelections.Push(j);
                             }
                             }
                         }
                         }
                         else if (i > last)
                         else if (i > last)
                         {
                         {
                             for (unsigned j = last; j <= i; ++j)
                             for (unsigned j = last; j <= i; ++j)
-                                newSelections.Insert(j);
+                                newSelections.Push(j);
                         }
                         }
                         SetSelections(newSelections);
                         SetSelections(newSelections);
                     }
                     }

+ 2 - 4
Engine/UI/ListView.h

@@ -111,7 +111,7 @@ public:
     /// Return first selected index, or M_MAX_UNSIGNED if none selected.
     /// Return first selected index, or M_MAX_UNSIGNED if none selected.
     unsigned GetSelection() const;
     unsigned GetSelection() const;
     /// Return all selected indices.
     /// Return all selected indices.
-    PODVector<unsigned> GetSelections() const;
+    const PODVector<unsigned>& GetSelections() const { return selections_; }
     /// Return first selected item, or null if none selected.
     /// Return first selected item, or null if none selected.
     UIElement* GetSelectedItem() const;
     UIElement* GetSelectedItem() const;
     /// Return all selected items.
     /// Return all selected items.
@@ -138,7 +138,7 @@ protected:
     void EnsureItemVisibility(UIElement* item);
     void EnsureItemVisibility(UIElement* item);
     
     
     /// Current selection.
     /// Current selection.
-    HashSet<unsigned> selections_;
+    PODVector<unsigned> selections_;
     /// Highlight mode.
     /// Highlight mode.
     HighlightMode highlightMode_;
     HighlightMode highlightMode_;
     /// Multiselect flag.
     /// Multiselect flag.
@@ -155,8 +155,6 @@ protected:
     unsigned lastClickedItem_;
     unsigned lastClickedItem_;
     
     
 private:
 private:
-    /// %Set multiple selected items, used internally.
-    void SetSelections(const HashSet<unsigned>& indices);
     /// Handle global UI mouseclick to check for selection change.
     /// Handle global UI mouseclick to check for selection change.
     void HandleUIMouseClick(StringHash eventType, VariantMap& eventData);
     void HandleUIMouseClick(StringHash eventType, VariantMap& eventData);
     /// Handle global focus change to check whether an invisible item was focused.
     /// Handle global focus change to check whether an invisible item was focused.

+ 2 - 1
ThirdParty/AngelScript/source/as_compiler.cpp

@@ -5856,7 +5856,8 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr
 
 
 	// Urho3D: if there is a handle type, and it does not have an overloaded assignment operator, convert to an explicit handle
 	// Urho3D: if there is a handle type, and it does not have an overloaded assignment operator, convert to an explicit handle
 	// for scripting convenience. (For the Urho3D handle types, value assignment is not supported)
 	// for scripting convenience. (For the Urho3D handle types, value assignment is not supported)
-	if (lctx->type.dataType.IsObjectHandle() && !lctx->type.isExplicitHandle && !lctx->type.dataType.GetBehaviour()->copy)
+	if (lctx->type.dataType.IsObjectHandle() && !lctx->type.dataType.IsTemplate() && !lctx->type.isExplicitHandle &&
+		!lctx->type.dataType.GetBehaviour()->copy)
 		lctx->type.isExplicitHandle = true;
 		lctx->type.isExplicitHandle = true;
 
 
 	// If the left hand expression is a property accessor, then that should be used
 	// If the left hand expression is a property accessor, then that should be used