Browse Source

Add another expandable component

Use one of them if the drop-panel has to act as a Popup and the other if it has to act as a standard component.

Contributes to CURA-5941.
Diego Prado Gesto 6 years ago
parent
commit
cdb8020029

+ 0 - 1
plugins/SimulationView/SimulationViewMenuComponent.qml

@@ -16,7 +16,6 @@ Cura.ExpandableComponent
     id: base
 
     width: UM.Theme.getSize("layerview_menu_size").width
-    contentType: Cura.ExpandableComponent.ContentType.Fixed
 
     Connections
     {

+ 16 - 50
resources/qml/ExpandableComponent.qml

@@ -20,20 +20,11 @@ Item
         AlignRight
     }
 
-    enum ContentType
-    {
-        Floating,
-        Fixed
-    }
-
     // The headerItem holds the QML item that is always displayed.
     property alias headerItem: headerItemLoader.sourceComponent
 
     // The contentItem holds the QML item that is shown when the "open" button is pressed
-    property var contentItem: content.contentItem
-
-    // Defines the type of the contents
-    property int contentType: ExpandableComponent.ContentType.Floating
+    property alias contentItem: content.contentItem
 
     property color contentBackgroundColor: UM.Theme.getColor("action_button")
 
@@ -48,7 +39,7 @@ Item
     property alias contentPadding: content.padding
 
     // How much spacing is needed for the contentItem by Y coordinate
-    property var contentSpacingY: 0
+    property var contentSpacingY: UM.Theme.getSize("narrow_margin").width
 
     // How much padding is needed around the header & button
     property alias headerPadding: background.padding
@@ -64,17 +55,12 @@ Item
     // Is the "drawer" open?
     readonly property alias expanded: content.visible
 
-    property alias expandedHighlightColor: expandedHighlight.color
-
     // What should the radius of the header be. This is also influenced by the headerCornerSide
     property alias headerRadius: background.radius
 
     // On what side should the header corners be shown? 1 is down, 2 is left, 3 is up and 4 is right.
     property alias headerCornerSide: background.cornerSide
 
-    // Change the contentItem close behaviour
-    property alias contentClosePolicy : content.closePolicy
-
     property alias headerShadowColor: shadow.color
 
     property alias enableHeaderShadow: shadow.visible
@@ -83,14 +69,7 @@ Item
 
     function toggleContent()
     {
-        if (content.visible)
-        {
-            content.close()
-        }
-        else
-        {
-            content.open()
-        }
+        content.visible = !content.visible
     }
 
     implicitHeight: 100 * screenScaleFactor
@@ -117,17 +96,6 @@ Item
             }
         }
 
-        // A highlight that is shown when the content is expanded
-        Rectangle
-        {
-            id: expandedHighlight
-            width: parent.width
-            height: UM.Theme.getSize("thick_lining").height
-            color: UM.Theme.getColor("primary")
-            visible: contentType == ExpandableComponent.ContentType.Floating && expanded
-            anchors.bottom: parent.bottom
-        }
-
         UM.RecolorImage
         {
             id: collapseButton
@@ -139,9 +107,7 @@ Item
             }
             sourceSize.width: width
             sourceSize.height: height
-            source: contentType == ExpandableComponent.ContentType.Floating ?
-                        (expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left")) :
-                        UM.Theme.getIcon("pencil")
+            source: UM.Theme.getIcon("pencil")
             visible: source != ""
             width: UM.Theme.getSize("standard_arrow").width
             height: UM.Theme.getSize("standard_arrow").height
@@ -155,8 +121,7 @@ Item
             onClicked: toggleContent()
             hoverEnabled: true
             onEntered: background.color = headerHoverColor
-            onExited: background.color = (contentType == ExpandableComponent.ContentType.Fixed && expanded) ?
-                            headerActiveColor : headerBackgroundColor
+            onExited: background.color = expanded ? headerActiveColor : headerBackgroundColor
         }
     }
 
@@ -174,9 +139,10 @@ Item
         z: background.z - 1
     }
 
-    Popup
+    Control
     {
         id: content
+        visible: false
 
         // Ensure that the content is located directly below the headerItem
         y: background.height + base.shadowOffset + base.contentSpacingY
@@ -185,7 +151,6 @@ Item
         // In case of right alignment, the 3x padding is due to left, right and padding between the button & text.
         x: contentAlignment == ExpandableComponent.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0
         padding: UM.Theme.getSize("default_margin").width
-        closePolicy: Popup.CloseOnPressOutsideParent
 
         background: Cura.RoundedRectangle
         {
@@ -195,15 +160,16 @@ Item
             border.color: UM.Theme.getColor("lining")
             radius: UM.Theme.getSize("default_radius").width
         }
-    }
 
-    onContentItemChanged:
-    {
-        // Since we want the size of the content to be set by the size of the content,
-        // we need to do it like this.
-        content.width = contentItem.width + 2 * content.padding
-        content.height = contentItem.height + 2 * content.padding
-        content.contentItem = contentItem
+        contentItem: Item {}
+
+        onContentItemChanged:
+        {
+            // Since we want the size of the content to be set by the size of the content,
+            // we need to do it like this.
+            content.width = contentItem.width + 2 * content.padding
+            content.height = contentItem.height + 2 * content.padding
+        }
     }
 
     // DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item.

+ 204 - 0
resources/qml/ExpandablePopup.qml

@@ -0,0 +1,204 @@
+import QtQuick 2.7
+import QtQuick.Controls 2.3
+
+import UM 1.2 as UM
+import Cura 1.0 as Cura
+
+import QtGraphicalEffects 1.0 // For the dropshadow
+
+// The expandable component has 2 major sub components:
+//      * The headerItem; Always visible and should hold some info about what happens if the component is expanded
+//      * The contentItem; The content that needs to be shown if the component is expanded.
+Item
+{
+    id: base
+
+    // Enumeration with the different possible alignments of the content with respect of the headerItem
+    enum ContentAlignment
+    {
+        AlignLeft,
+        AlignRight
+    }
+
+    // The headerItem holds the QML item that is always displayed.
+    property alias headerItem: headerItemLoader.sourceComponent
+
+    // The contentItem holds the QML item that is shown when the "open" button is pressed
+    property alias contentItem: content.contentItem
+
+    property color contentBackgroundColor: UM.Theme.getColor("action_button")
+
+    property color headerBackgroundColor: UM.Theme.getColor("action_button")
+    property color headerActiveColor: UM.Theme.getColor("secondary")
+    property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
+
+    // Defines the alignment of the content with respect of the headerItem, by default to the right
+    property int contentAlignment: ExpandablePopup.ContentAlignment.AlignRight
+
+    // How much spacing is needed around the contentItem
+    property alias contentPadding: content.padding
+
+    // How much padding is needed around the header & button
+    property alias headerPadding: background.padding
+
+    // What icon should be displayed on the right.
+    property alias iconSource: collapseButton.source
+
+    property alias iconColor: collapseButton.color
+
+    // The icon size (it's always drawn as a square)
+    property alias iconSize: collapseButton.height
+
+    // Is the "drawer" open?
+    readonly property alias expanded: content.visible
+
+    property alias expandedHighlightColor: expandedHighlight.color
+
+    // What should the radius of the header be. This is also influenced by the headerCornerSide
+    property alias headerRadius: background.radius
+
+    // On what side should the header corners be shown? 1 is down, 2 is left, 3 is up and 4 is right.
+    property alias headerCornerSide: background.cornerSide
+
+    // Change the contentItem close behaviour
+    property alias contentClosePolicy : content.closePolicy
+
+    property alias headerShadowColor: shadow.color
+
+    property alias enableHeaderShadow: shadow.visible
+
+    property int shadowOffset: 2
+
+    function toggleContent()
+    {
+        if (content.visible)
+        {
+            content.close()
+        }
+        else
+        {
+            content.open()
+        }
+    }
+
+    implicitHeight: 100 * screenScaleFactor
+    implicitWidth: 400 * screenScaleFactor
+
+    RoundedRectangle
+    {
+        id: background
+        property real padding: UM.Theme.getSize("default_margin").width
+
+        color: headerBackgroundColor
+        anchors.fill: parent
+
+        Loader
+        {
+            id: headerItemLoader
+            anchors
+            {
+                left: parent.left
+                right: collapseButton.visible ? collapseButton.left : parent.right
+                top: parent.top
+                bottom: parent.bottom
+                margins: background.padding
+            }
+        }
+
+        // A highlight that is shown when the content is expanded
+        Rectangle
+        {
+            id: expandedHighlight
+            width: parent.width
+            height: UM.Theme.getSize("thick_lining").height
+            color: UM.Theme.getColor("primary")
+            visible: expanded
+            anchors.bottom: parent.bottom
+        }
+
+        UM.RecolorImage
+        {
+            id: collapseButton
+            anchors
+            {
+                right: parent.right
+                verticalCenter: parent.verticalCenter
+                margins: background.padding
+            }
+            sourceSize.width: width
+            sourceSize.height: height
+            source: expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left")
+            visible: source != ""
+            width: UM.Theme.getSize("standard_arrow").width
+            height: UM.Theme.getSize("standard_arrow").height
+            color: UM.Theme.getColor("text")
+        }
+
+        MouseArea
+        {
+            id: mouseArea
+            anchors.fill: parent
+            onClicked: toggleContent()
+            hoverEnabled: true
+            onEntered: background.color = headerHoverColor
+            onExited: background.color = headerBackgroundColor
+        }
+    }
+
+    DropShadow
+    {
+        id: shadow
+        // Don't blur the shadow
+        radius: 0
+        anchors.fill: background
+        source: background
+        verticalOffset: base.shadowOffset
+        visible: true
+        color: UM.Theme.getColor("action_button_shadow")
+        // Should always be drawn behind the background.
+        z: background.z - 1
+    }
+
+    Popup
+    {
+        id: content
+
+        // Ensure that the content is located directly below the headerItem
+        y: background.height + base.shadowOffset
+
+        // Make the content aligned with the rest, using the property contentAlignment to decide whether is right or left.
+        // In case of right alignment, the 3x padding is due to left, right and padding between the button & text.
+        x: contentAlignment == ExpandablePopup.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0
+        padding: UM.Theme.getSize("default_margin").width
+        closePolicy: Popup.CloseOnPressOutsideParent
+
+        background: Cura.RoundedRectangle
+        {
+            cornerSide: Cura.RoundedRectangle.Direction.Down
+            color: contentBackgroundColor
+            border.width: UM.Theme.getSize("default_lining").width
+            border.color: UM.Theme.getColor("lining")
+            radius: UM.Theme.getSize("default_radius").width
+        }
+
+        contentItem: Item {}
+
+        onContentItemChanged:
+        {
+            // Since we want the size of the content to be set by the size of the content,
+            // we need to do it like this.
+            content.width = contentItem.width + 2 * content.padding
+            content.height = contentItem.height + 2 * content.padding
+        }
+    }
+
+    // DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item.
+    // Apparently the order in which these are handled matters and so the height is correctly updated if this is here.
+    Connections
+    {
+        // Since it could be that the content is dynamically populated, we should also take these changes into account.
+        target: content.contentItem
+        onWidthChanged: content.width = content.contentItem.width + 2 * content.padding
+        onHeightChanged: content.height = content.contentItem.height + 2 * content.padding
+    }
+}

+ 1 - 1
resources/qml/Menus/ConfigurationMenu/QuickConfigurationSelector.qml

@@ -12,7 +12,7 @@ import UM 1.2 as UM
 import Cura 1.0 as Cura
 
 
-Cura.ExpandableComponent
+Cura.ExpandablePopup
 {
     id: base
 

+ 0 - 4
resources/qml/PrintSetupSelector/PrintSetupSelector.qml

@@ -14,11 +14,7 @@ Cura.ExpandableComponent
     property string enabledText: catalog.i18nc("@label:Should be short", "On")
     property string disabledText: catalog.i18nc("@label:Should be short", "Off")
 
-    contentType: Cura.ExpandableComponent.ContentType.Fixed
     contentPadding: UM.Theme.getSize("default_lining").width
-    contentSpacingY: UM.Theme.getSize("narrow_margin").width
-
-    contentClosePolicy: Popup.CloseOnEscape
 
     UM.I18nCatalog
     {

+ 2 - 2
resources/qml/PrinterSelector/MachineSelector.qml

@@ -7,7 +7,7 @@ import QtQuick.Controls 2.3
 import UM 1.2 as UM
 import Cura 1.0 as Cura
 
-Cura.ExpandableComponent
+Cura.ExpandablePopup
 {
     id: machineSelector
 
@@ -16,7 +16,7 @@ Cura.ExpandableComponent
     property var outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
 
     contentPadding: UM.Theme.getSize("default_lining").width
-    contentAlignment: Cura.ExpandableComponent.ContentAlignment.AlignLeft
+    contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft
 
     UM.I18nCatalog
     {

+ 4 - 4
resources/qml/ViewsSelector.qml

@@ -7,12 +7,12 @@ import QtQuick.Controls 2.3
 import UM 1.2 as UM
 import Cura 1.0 as Cura
 
-Cura.ExpandableComponent
+Cura.ExpandablePopup
 {
     id: viewSelector
 
     contentPadding: UM.Theme.getSize("default_lining").width
-    contentAlignment: Cura.ExpandableComponent.ContentAlignment.AlignLeft
+    contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft
 
     property var viewModel: UM.ViewModel { }
 
@@ -72,13 +72,13 @@ Cura.ExpandableComponent
     contentItem: Column
     {
         id: viewSelectorPopup
-        width: viewSelector.width - 2 * viewSelector.popupPadding
+        width: viewSelector.width - 2 * viewSelector.contentPadding
 
         // For some reason the height/width of the column gets set to 0 if this is not set...
         Component.onCompleted:
         {
             height = implicitHeight
-            width = viewSelector.width - 2 * viewSelector.popupPadding
+            width = viewSelector.width - 2 * viewSelector.contentPadding
         }
 
         Repeater