diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index 9dc3b67658..76875a035d 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/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 { diff --git a/resources/qml/ExpandableComponent.qml b/resources/qml/ExpandableComponent.qml index f6e340c4ea..4f4848ea8b 100644 --- a/resources/qml/ExpandableComponent.qml +++ b/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. diff --git a/resources/qml/ExpandablePopup.qml b/resources/qml/ExpandablePopup.qml new file mode 100644 index 0000000000..da79d9b77b --- /dev/null +++ b/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 + } +} diff --git a/resources/qml/Menus/ConfigurationMenu/QuickConfigurationSelector.qml b/resources/qml/Menus/ConfigurationMenu/QuickConfigurationSelector.qml index ea82f4fe13..138a1d6669 100644 --- a/resources/qml/Menus/ConfigurationMenu/QuickConfigurationSelector.qml +++ b/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 diff --git a/resources/qml/PrintSetupSelector/PrintSetupSelector.qml b/resources/qml/PrintSetupSelector/PrintSetupSelector.qml index 0eea697950..19c8067683 100644 --- a/resources/qml/PrintSetupSelector/PrintSetupSelector.qml +++ b/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 { diff --git a/resources/qml/PrinterSelector/MachineSelector.qml b/resources/qml/PrinterSelector/MachineSelector.qml index 69a1ac899c..ef766b6030 100644 --- a/resources/qml/PrinterSelector/MachineSelector.qml +++ b/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 { diff --git a/resources/qml/ViewsSelector.qml b/resources/qml/ViewsSelector.qml index d469202606..18d1f66759 100644 --- a/resources/qml/ViewsSelector.qml +++ b/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