Browse Source

Manipulation of UI-element's style in the Attribute Inspector's Style drop down list is now functional. At the moment new style is applied on top of existing attribute values (i.e. without first removing the effect of existing style). Adjusted DefaultStyle.xml to enable highlight on selected item in DropDownList.

Wei Tjong Yao 12 years ago
parent
commit
fe5b26abd7

+ 62 - 0
Bin/Data/Scripts/Editor/EditorActions.as

@@ -487,6 +487,8 @@ class CreateUIElementAction : EditAction
         parentID = GetUIElementID(element.parent);
         elementData = XMLFile();
         XMLElement rootElem = elementData.CreateRoot("element");
+        // No style processing for the root element
+        rootElem.SetAttribute("style", "none");
         // Need another nested element tag otherwise the LoadXML() does not work as expected
         XMLElement childElem = rootElem.CreateChild("element");
         element.SaveXML(childElem);
@@ -538,6 +540,9 @@ class DeleteUIElementAction : EditAction
         parentID = GetUIElementID(element.parent);
         elementData = XMLFile();
         XMLElement rootElem = elementData.CreateRoot("element");
+        // No style processing for the root element
+        rootElem.SetAttribute("style", "none");
+        // Need another nested element tag otherwise the LoadXML() does not work as expected
         XMLElement childElem = rootElem.CreateChild("element");
         element.SaveXML(childElem);
         childElem.SetUInt("index", element.parent.FindChild(element));
@@ -611,3 +616,60 @@ class ReparentUIElementAction : EditAction
             element.parent = parent;
     }
 }
+
+class ApplyUIElementStyleAction : EditAction
+{
+    Variant elementID;
+    Variant parentID;
+    XMLFile@ elementData;
+    XMLFile@ styleFile;
+    String style;
+
+    void Define(UIElement@ element, const String&in newStyle)
+    {
+        elementID = GetUIElementID(element);
+        parentID = GetUIElementID(element.parent);
+        elementData = XMLFile();
+        XMLElement rootElem = elementData.CreateRoot("element");
+        // No style processing for the root element
+        rootElem.SetAttribute("style", "none");
+        // Need another nested element tag otherwise the LoadXML() does not work as expected
+        XMLElement childElem = rootElem.CreateChild("element");
+        element.SaveXML(childElem);
+        childElem.SetUInt("index", element.parent.FindChild(element));
+        styleFile = element.defaultStyle;
+        style = newStyle;
+    }
+
+    void Undo()
+    {
+        UIElement@ parent = GetUIElementByID(parentID);
+        UIElement@ element = GetUIElementByID(elementID);
+        if (parent !is null && element !is null)
+        {
+            // Suppress updating hierarchy list as we are "just" reverting the attribute values of the whole structure without changing the structure itself
+            suppressUIElementChanges = true;
+
+            parent.RemoveChild(element);
+            parent.LoadXML(elementData.root, styleFile);
+
+            suppressUIElementChanges = false;
+
+            SetSceneModified();
+            // Although the selections are not changed, call to ensure attribute inspector notices reverted element
+            HandleHierarchyListSelectionChange();
+        }
+    }
+
+    void Redo()
+    {
+        UIElement@ element = GetUIElementByID(elementID);
+        if (element !is null)
+        {
+            element.SetStyle(styleFile, style);
+
+            SetSceneModified();
+            attributesDirty = true;
+        }
+    }
+}

+ 79 - 11
Bin/Data/Scripts/Editor/EditorNodeWindow.as

@@ -70,7 +70,7 @@ UIElement@ GetComponentContainer(uint index)
     return container;
 }
 
-UIElement@ GetElementContainer()
+UIElement@ GetUIElementContainer()
 {
     if (elementContainerIndex != M_MAX_UNSIGNED)
         return GetContainer(elementContainerIndex);
@@ -79,15 +79,15 @@ UIElement@ GetElementContainer()
     parentContainer.LoadXML(xmlResources[ATTRIBUTE_RES], uiStyle);
     UIElement@ container = GetContainer(elementContainerIndex);
     container.LoadXML(xmlResources[VARIABLE_RES], uiStyle);
-    // Style child XML resource is always inserted at child index 2 because it is explicitly requested in the XML definition
     container.LoadXML(xmlResources[STYLE_RES], uiStyle);
-    container.children[2].children[0].SetFixedWidth(LABEL_WIDTH);
-    DropDownList@ styleList = container.children[2].children[1];
+    DropDownList@ styleList = container.GetChild("StyleDropDown", true);
     styleList.placeholderText = STRIKED_OUT;
+    styleList.parent.GetChild("StyleDropDownLabel").SetFixedWidth(LABEL_WIDTH);
     PopulateStyleList(styleList);
     SubscribeToEvent(container.GetChild("ResetToDefault", true), "Released", "HandleResetToDefault");
     SubscribeToEvent(container.GetChild("NewVarDropDown", true), "ItemSelected", "CreateUIElementVariable");
     SubscribeToEvent(container.GetChild("DeleteVarButton", true), "Released", "DeleteUIElementVariable");
+    SubscribeToEvent(styleList, "ItemSelected", "HandleStyleItemSelected");
     return container;
 }
 
@@ -214,7 +214,7 @@ void UpdateAttributeInspector(bool fullUpdate = true)
             // Resize the node editor according to the number of variables, up to a certain maximum
             uint maxAttrs = Clamp(list.contentElement.numChildren, MIN_NODE_ATTRIBUTES, MAX_NODE_ATTRIBUTES);
             list.SetFixedHeight(maxAttrs * ATTR_HEIGHT + 2);
-            container.SetFixedHeight(maxAttrs * ATTR_HEIGHT + 60);
+            container.SetFixedHeight(maxAttrs * ATTR_HEIGHT + 58);
         }
 
         // Set icon's target in the icon panel
@@ -247,30 +247,39 @@ void UpdateAttributeInspector(bool fullUpdate = true)
 
     if (!editUIElements.empty)
     {
-        UIElement@ container = GetElementContainer();
+        UIElement@ container = GetUIElementContainer();
 
         Text@ titleText = container.GetChild("TitleText");
+        DropDownList@ styleList = container.GetChild("StyleDropDown", true);
         String elementType;
 
         if (editUIElement !is null)
         {
             elementType = editUIElement.typeName;
             titleText.text = elementType + " [ID " + GetUIElementID(editUIElement).ToString() + "]";
+            SetStyleListSelection(styleList, editUIElement.appliedStyle);
         }
         else
         {
             elementType = editUIElements[0].typeName;
+            String appliedStyle = cast<UIElement>(editUIElements[0]).appliedStyle;
 
             bool sameType = true;
+            bool sameStyle = true;
             for (uint i = 1; i < editUIElements.length; ++i)
             {
                 if (editUIElements[i].typeName != elementType)
                 {
                     sameType = false;
+                    sameStyle = false;
                     break;
                 }
+
+                if (sameStyle && cast<UIElement>(editUIElements[i]).appliedStyle != appliedStyle)
+                    sameStyle = false;
             }
             titleText.text = (sameType ? elementType : "Mixed type") + " [ID " + STRIKED_OUT + " : " + editUIElements.length + "x]";
+            SetStyleListSelection(SetEditable(styleList, sameStyle), sameStyle ? appliedStyle : STRIKED_OUT);
             if (!sameType)
                 elementType = "";   // No icon
         }
@@ -292,7 +301,7 @@ void UpdateAttributeInspector(bool fullUpdate = true)
             panel.visible = false;
     }
 
-    // Adjust the icons panel's width
+    // Adjust size and position of manual-layout UI-elements, e.g. icons panel
     if (fullUpdate)
         HandleWindowLayoutUpdated();
 }
@@ -508,7 +517,7 @@ void HandleResetToDefault(StringHash eventType, VariantMap& eventData)
 
 void CreateNodeVariable(StringHash eventType, VariantMap& eventData)
 {
-    if (editNodes.length == 0)
+    if (editNodes.empty)
         return;
 
     String newName = ExtractVariableName(eventData);
@@ -535,7 +544,7 @@ void CreateNodeVariable(StringHash eventType, VariantMap& eventData)
 
 void DeleteNodeVariable(StringHash eventType, VariantMap& eventData)
 {
-    if (editNodes.length == 0)
+    if (editNodes.empty)
         return;
 
     String delName = ExtractVariableName(eventData);
@@ -556,7 +565,7 @@ void DeleteNodeVariable(StringHash eventType, VariantMap& eventData)
 
 void CreateUIElementVariable(StringHash eventType, VariantMap& eventData)
 {
-    if (editUIElements.length == 0)
+    if (editUIElements.empty)
         return;
 
     String newName = ExtractVariableName(eventData);
@@ -584,7 +593,7 @@ void CreateUIElementVariable(StringHash eventType, VariantMap& eventData)
 
 void DeleteUIElementVariable(StringHash eventType, VariantMap& eventData)
 {
-    if (editUIElements.length == 0)
+    if (editUIElements.empty)
         return;
 
     String delName = ExtractVariableName(eventData);
@@ -641,3 +650,62 @@ String GetVariableName(ShortStringHash hash)
         name = uiElementVarNames[hash].ToString();
     return name;    // Since this is a reverse mapping, it does not really matter from which side the name is retrieved back
 }
+
+bool inSetStyleListSelection = false;
+
+void SetStyleListSelection(DropDownList@ styleList, const String&in style)
+{
+    // Prevent infinite loop upon initial style selection
+    inSetStyleListSelection = true;
+
+    uint selection = M_MAX_UNSIGNED;
+    String styleName = style.empty ? "auto" : style;
+    Array<UIElement@> items = styleList.GetItems();
+    for (uint i = 0; i < items.length; ++i)
+    {
+        Text@ element = cast<Text>(items[i]);
+        if (element is null)
+            continue;   // It may be a divider
+        if (element.text == styleName)
+        {
+            selection = i;
+            break;
+        }
+    }
+    styleList.selection = selection;
+
+    inSetStyleListSelection = false;
+}
+
+void HandleStyleItemSelected(StringHash eventType, VariantMap& eventData)
+{
+    if (inSetStyleListSelection || editUIElements.empty)
+        return;
+
+    ui.cursor.shape = CS_BUSY;
+
+    DropDownList@ styleList = eventData["Element"].GetUIElement();
+    Text@ text = cast<Text>(styleList.selectedItem);
+    if (text is null)
+        return;
+    String newStyle = text.text;
+    bool autoStyle = newStyle == "auto";
+
+    // Group for storing undo actions
+    EditActionGroup group;
+
+    // Apply new style to selected UI-elements
+    for (uint i = 0; i < editUIElements.length; ++i)
+    {
+        UIElement@ element = editUIElements[i];
+
+        ApplyUIElementStyleAction action;
+        action.Define(element, autoStyle ? element.typeName : newStyle);
+        group.actions.Push(action);
+        
+        // Use the Redo() to actually do the action 
+        action.Redo();
+    }
+
+    SaveEditActionGroup(group);
+}

+ 5 - 0
Bin/Data/Scripts/Editor/EditorUIElement.as

@@ -290,6 +290,8 @@ bool SaveChildUIElement(const String&in fileName)
 
     XMLFile@ elementData = XMLFile();
     XMLElement rootElem = elementData.CreateRoot("element");
+    // No style processing for the root element
+    rootElem.SetAttribute("style", "none");
     // Need another nested element tag otherwise the LoadXML() does not work as expected
     XMLElement childElem = rootElem.CreateChild("element");
     bool success = editUIElement.SaveXML(childElem);
@@ -429,6 +431,9 @@ bool UIElementCopy()
     {
         XMLFile@ xml = XMLFile();
         XMLElement rootElem = xml.CreateRoot("element");
+        // No style processing for the root element
+        rootElem.SetAttribute("style", "none");
+        // Need another nested element tag otherwise the LoadXML() does not work as expected
         XMLElement childElem = rootElem.CreateChild("element");
         selectedUIElements[i].SaveXML(childElem);
         uiElementCopyBuffer.Push(xml);

+ 7 - 4
Bin/Data/UI/DefaultStyle.xml

@@ -74,6 +74,7 @@
         <element type="Window" internal="true" popup="true">
             <attribute name="Layout Border" value="2 2 2 2" />
             <element type="ListView" internal="true">
+                <attribute name="Highlight Mode" value="Always" />
                 <element type="BorderImage" internal="true">    <!-- Override scroll panel attributes from default ListView -->
                     <attribute name="Texture" value="Texture2D;Textures/UI.png" />
                     <attribute name="Image Rect" value="96 0 112 16" />
@@ -238,10 +239,11 @@
         <attribute name="Resize Popup" value="true" />
     </element>
     <element type="FileSelectorFilterText" auto="false">
+        <attribute name="Is Enabled" value="true" />
         <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
         <attribute name="Font Size" value="11" />
-        <attribute name="Hover Color" value="0.45 0.70 0.45" />
-        <attribute name="Is Enabled" value="true" />
+        <attribute name="Selection Color" value="0.7 0.7 0.7 1" />
+        <attribute name="Hover Color" value="0.45 0.7 0.45 1" />
     </element>
     <element type="FileSelectorTitleLayout" auto="false">
         <attribute name="Min Size" value="0 16" />
@@ -258,7 +260,7 @@
         <attribute name="Selection Color" value="0.70 0.70 0.70" />
     </element>
     <element type="FileSelectorTitleText" style="Text" auto="false" />
-    <element type="EditorDivider">
+    <element type="EditorDivider" auto="false">
         <attribute name="Texture" value="Texture2D;Textures/UI.png" />
         <attribute name="Image Rect" value="144 32 160 43" />
         <attribute name="Border" value="2 2 2 2" />
@@ -276,8 +278,9 @@
         <attribute name="Font Size" value="12" />
     </element>
     <element type="EditorEnumAttributeText" style="EditorAttributeText" auto="false">
-        <attribute name="Hover Color" value="0.45 0.70 0.45" />
         <attribute name="Is Enabled" value="true" />
+        <attribute name="Selection Color" value="0.7 0.7 0.7 1" />
+        <attribute name="Hover Color" value="0.45 0.7 0.45 1" />
     </element>
     <element type="EditorAttributeEdit" style="LineEdit" auto="false" />
 </elements>

+ 1 - 0
Bin/Data/UI/EditorInspector_Style.xml

@@ -5,6 +5,7 @@
         <attribute name="Layout Mode" value="Horizontal" />
         <attribute name="Layout Spacing" value="4" />
         <element type="Text" style="EditorAttributeText">
+            <attribute name="Name" value="StyleDropDownLabel" />
             <attribute name="Text" value="Style" />
         </element>
         <element type="DropDownList">

+ 3 - 0
Engine/UI/DropDownList.cpp

@@ -94,9 +94,12 @@ void DropDownList::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& ver
         IntVector2 offset = targetPos - originalPos;
 
         // GetBatches() usually resets the hover flag. Therefore get its value and then reset it for the real rendering
+        // Render the selected item without its selection color, so temporarily reset the item's selected attribute
         bool hover = selectedItem->IsHovering();
+        selectedItem->SetSelected(false);
         selectedItem->SetHovering(false);
         selectedItem->GetBatchesWithOffset(offset, batches, vertexData, currentScissor);
+        selectedItem->SetSelected(true);
         selectedItem->SetHovering(hover);
     }
 }

+ 7 - 4
Engine/UI/UIElement.cpp

@@ -226,10 +226,7 @@ bool UIElement::LoadXML(const XMLElement& source, XMLFile* styleFile, bool setIn
         if (styleName.Empty())
             styleName = GetTypeName();
 
-        if (styleName == "none")
-            appliedStyle_ = styleName;
-        else
-            SetStyle(styleFile, styleName);
+        SetStyle(styleFile, styleName);
     }
     // The 'style' attribute value in the style file cannot be equals to original's applied style to prevent infinite loop
     else if (!styleName.Empty() && styleName != appliedStyle_)
@@ -844,6 +841,12 @@ void UIElement::SetDragDropMode(unsigned mode)
 
 void UIElement::SetStyle(XMLFile* file, const String& typeName)
 {
+    if (typeName == "none")
+    {
+        appliedStyle_ = typeName;
+        return;
+    }
+
     if (!file)
         return;