mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
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.
This commit is contained in:
parent
47ff95b1f3
commit
cdb8020029
7 changed files with 227 additions and 62 deletions
|
@ -16,7 +16,6 @@ Cura.ExpandableComponent
|
||||||
id: base
|
id: base
|
||||||
|
|
||||||
width: UM.Theme.getSize("layerview_menu_size").width
|
width: UM.Theme.getSize("layerview_menu_size").width
|
||||||
contentType: Cura.ExpandableComponent.ContentType.Fixed
|
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,20 +20,11 @@ Item
|
||||||
AlignRight
|
AlignRight
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ContentType
|
|
||||||
{
|
|
||||||
Floating,
|
|
||||||
Fixed
|
|
||||||
}
|
|
||||||
|
|
||||||
// The headerItem holds the QML item that is always displayed.
|
// The headerItem holds the QML item that is always displayed.
|
||||||
property alias headerItem: headerItemLoader.sourceComponent
|
property alias headerItem: headerItemLoader.sourceComponent
|
||||||
|
|
||||||
// The contentItem holds the QML item that is shown when the "open" button is pressed
|
// The contentItem holds the QML item that is shown when the "open" button is pressed
|
||||||
property var contentItem: content.contentItem
|
property alias contentItem: content.contentItem
|
||||||
|
|
||||||
// Defines the type of the contents
|
|
||||||
property int contentType: ExpandableComponent.ContentType.Floating
|
|
||||||
|
|
||||||
property color contentBackgroundColor: UM.Theme.getColor("action_button")
|
property color contentBackgroundColor: UM.Theme.getColor("action_button")
|
||||||
|
|
||||||
|
@ -48,7 +39,7 @@ Item
|
||||||
property alias contentPadding: content.padding
|
property alias contentPadding: content.padding
|
||||||
|
|
||||||
// How much spacing is needed for the contentItem by Y coordinate
|
// 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
|
// How much padding is needed around the header & button
|
||||||
property alias headerPadding: background.padding
|
property alias headerPadding: background.padding
|
||||||
|
@ -64,17 +55,12 @@ Item
|
||||||
// Is the "drawer" open?
|
// Is the "drawer" open?
|
||||||
readonly property alias expanded: content.visible
|
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
|
// What should the radius of the header be. This is also influenced by the headerCornerSide
|
||||||
property alias headerRadius: background.radius
|
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.
|
// 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
|
property alias headerCornerSide: background.cornerSide
|
||||||
|
|
||||||
// Change the contentItem close behaviour
|
|
||||||
property alias contentClosePolicy : content.closePolicy
|
|
||||||
|
|
||||||
property alias headerShadowColor: shadow.color
|
property alias headerShadowColor: shadow.color
|
||||||
|
|
||||||
property alias enableHeaderShadow: shadow.visible
|
property alias enableHeaderShadow: shadow.visible
|
||||||
|
@ -83,14 +69,7 @@ Item
|
||||||
|
|
||||||
function toggleContent()
|
function toggleContent()
|
||||||
{
|
{
|
||||||
if (content.visible)
|
content.visible = !content.visible
|
||||||
{
|
|
||||||
content.close()
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
content.open()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitHeight: 100 * screenScaleFactor
|
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
|
UM.RecolorImage
|
||||||
{
|
{
|
||||||
id: collapseButton
|
id: collapseButton
|
||||||
|
@ -139,9 +107,7 @@ Item
|
||||||
}
|
}
|
||||||
sourceSize.width: width
|
sourceSize.width: width
|
||||||
sourceSize.height: height
|
sourceSize.height: height
|
||||||
source: contentType == ExpandableComponent.ContentType.Floating ?
|
source: UM.Theme.getIcon("pencil")
|
||||||
(expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left")) :
|
|
||||||
UM.Theme.getIcon("pencil")
|
|
||||||
visible: source != ""
|
visible: source != ""
|
||||||
width: UM.Theme.getSize("standard_arrow").width
|
width: UM.Theme.getSize("standard_arrow").width
|
||||||
height: UM.Theme.getSize("standard_arrow").height
|
height: UM.Theme.getSize("standard_arrow").height
|
||||||
|
@ -155,8 +121,7 @@ Item
|
||||||
onClicked: toggleContent()
|
onClicked: toggleContent()
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: background.color = headerHoverColor
|
onEntered: background.color = headerHoverColor
|
||||||
onExited: background.color = (contentType == ExpandableComponent.ContentType.Fixed && expanded) ?
|
onExited: background.color = expanded ? headerActiveColor : headerBackgroundColor
|
||||||
headerActiveColor : headerBackgroundColor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,9 +139,10 @@ Item
|
||||||
z: background.z - 1
|
z: background.z - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup
|
Control
|
||||||
{
|
{
|
||||||
id: content
|
id: content
|
||||||
|
visible: false
|
||||||
|
|
||||||
// Ensure that the content is located directly below the headerItem
|
// Ensure that the content is located directly below the headerItem
|
||||||
y: background.height + base.shadowOffset + base.contentSpacingY
|
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.
|
// 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
|
x: contentAlignment == ExpandableComponent.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0
|
||||||
padding: UM.Theme.getSize("default_margin").width
|
padding: UM.Theme.getSize("default_margin").width
|
||||||
closePolicy: Popup.CloseOnPressOutsideParent
|
|
||||||
|
|
||||||
background: Cura.RoundedRectangle
|
background: Cura.RoundedRectangle
|
||||||
{
|
{
|
||||||
|
@ -195,15 +160,16 @@ Item
|
||||||
border.color: UM.Theme.getColor("lining")
|
border.color: UM.Theme.getColor("lining")
|
||||||
radius: UM.Theme.getSize("default_radius").width
|
radius: UM.Theme.getSize("default_radius").width
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onContentItemChanged:
|
contentItem: Item {}
|
||||||
{
|
|
||||||
// Since we want the size of the content to be set by the size of the content,
|
onContentItemChanged:
|
||||||
// we need to do it like this.
|
{
|
||||||
content.width = contentItem.width + 2 * content.padding
|
// Since we want the size of the content to be set by the size of the content,
|
||||||
content.height = contentItem.height + 2 * content.padding
|
// we need to do it like this.
|
||||||
content.contentItem = contentItem
|
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.
|
// DO NOT MOVE UP IN THE CODE: This connection has to be here, after the definition of the content item.
|
||||||
|
|
204
resources/qml/ExpandablePopup.qml
Normal file
204
resources/qml/ExpandablePopup.qml
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import UM 1.2 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
|
|
||||||
Cura.ExpandableComponent
|
Cura.ExpandablePopup
|
||||||
{
|
{
|
||||||
id: base
|
id: base
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,7 @@ Cura.ExpandableComponent
|
||||||
property string enabledText: catalog.i18nc("@label:Should be short", "On")
|
property string enabledText: catalog.i18nc("@label:Should be short", "On")
|
||||||
property string disabledText: catalog.i18nc("@label:Should be short", "Off")
|
property string disabledText: catalog.i18nc("@label:Should be short", "Off")
|
||||||
|
|
||||||
contentType: Cura.ExpandableComponent.ContentType.Fixed
|
|
||||||
contentPadding: UM.Theme.getSize("default_lining").width
|
contentPadding: UM.Theme.getSize("default_lining").width
|
||||||
contentSpacingY: UM.Theme.getSize("narrow_margin").width
|
|
||||||
|
|
||||||
contentClosePolicy: Popup.CloseOnEscape
|
|
||||||
|
|
||||||
UM.I18nCatalog
|
UM.I18nCatalog
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ import QtQuick.Controls 2.3
|
||||||
import UM 1.2 as UM
|
import UM 1.2 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
Cura.ExpandableComponent
|
Cura.ExpandablePopup
|
||||||
{
|
{
|
||||||
id: machineSelector
|
id: machineSelector
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ Cura.ExpandableComponent
|
||||||
property var outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
|
property var outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
|
||||||
|
|
||||||
contentPadding: UM.Theme.getSize("default_lining").width
|
contentPadding: UM.Theme.getSize("default_lining").width
|
||||||
contentAlignment: Cura.ExpandableComponent.ContentAlignment.AlignLeft
|
contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft
|
||||||
|
|
||||||
UM.I18nCatalog
|
UM.I18nCatalog
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,12 +7,12 @@ import QtQuick.Controls 2.3
|
||||||
import UM 1.2 as UM
|
import UM 1.2 as UM
|
||||||
import Cura 1.0 as Cura
|
import Cura 1.0 as Cura
|
||||||
|
|
||||||
Cura.ExpandableComponent
|
Cura.ExpandablePopup
|
||||||
{
|
{
|
||||||
id: viewSelector
|
id: viewSelector
|
||||||
|
|
||||||
contentPadding: UM.Theme.getSize("default_lining").width
|
contentPadding: UM.Theme.getSize("default_lining").width
|
||||||
contentAlignment: Cura.ExpandableComponent.ContentAlignment.AlignLeft
|
contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft
|
||||||
|
|
||||||
property var viewModel: UM.ViewModel { }
|
property var viewModel: UM.ViewModel { }
|
||||||
|
|
||||||
|
@ -72,13 +72,13 @@ Cura.ExpandableComponent
|
||||||
contentItem: Column
|
contentItem: Column
|
||||||
{
|
{
|
||||||
id: viewSelectorPopup
|
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...
|
// For some reason the height/width of the column gets set to 0 if this is not set...
|
||||||
Component.onCompleted:
|
Component.onCompleted:
|
||||||
{
|
{
|
||||||
height = implicitHeight
|
height = implicitHeight
|
||||||
width = viewSelector.width - 2 * viewSelector.popupPadding
|
width = viewSelector.width - 2 * viewSelector.contentPadding
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater
|
Repeater
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue