Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ExpandablePopup.qml « qml « resources - github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 219608a7622d0b657aebca7b3987a0f366f75041 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.

import QtQuick 2.7
import QtQuick.Controls 2.3

import UM 1.5 as UM
import Cura 1.0 as Cura

// 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("expandable_active")
    property color headerHoverColor: UM.Theme.getColor("expandable_hover")

    property alias mouseArea: headerMouseArea
    property alias enabled: headerMouseArea.enabled

    // Text to show when this component is disabled
    property alias disabledText: disabledLabel.text

    // 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

    property alias headerBackgroundBorder: background.border

    // Whether or not to show the background border
    property bool enableHeaderBackgroundBorder: true

    // 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

    // Distance between the header and the content.
    property int popupOffset: 2 * UM.Theme.getSize("default_lining").height

    onEnabledChanged:
    {
        if (!base.enabled && expanded)
        {
            toggleContent()
        }
    }

    function toggleContent()
    {
        if (content.visible)
        {
            content.close()
        }
        else
        {
            content.open()
        }
    }

    // Add this binding since the background color is not updated otherwise
    Binding
    {
        target: background
        property: "color"
        value: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
    }

    implicitHeight: 100 * screenScaleFactor
    implicitWidth: 400 * screenScaleFactor

    RoundedRectangle
    {
        id: background
        property real padding: UM.Theme.getSize("default_margin").width

        border.width: base.enableHeaderBackgroundBorder ? UM.Theme.getSize("default_lining").width : 0
        border.color: UM.Theme.getColor("lining")

        color: base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
        anchors.fill: parent

        UM.Label
        {
            id: disabledLabel
            visible: !base.enabled
            leftPadding: background.padding
            text: ""
            height: parent.height
        }

        Item
        {
            anchors.fill: parent
            visible: base.enabled

            MouseArea
            {
                id: headerMouseArea
                anchors.fill: parent
                onClicked: toggleContent()
                hoverEnabled: true
                onEntered: background.color = headerHoverColor
                onExited: background.color = base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
            }

            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
                }
                source: UM.Theme.getIcon("ChevronSingleDown")
                visible: source != ""
                width: UM.Theme.getSize("standard_arrow").width
                height: UM.Theme.getSize("standard_arrow").height
                color: UM.Theme.getColor("small_button_text")
            }
        }

    }

    Popup
    {
        id: content

        // Ensure that the content is located directly below the headerItem
        y: background.height + base.popupOffset

        // 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
            height: contentItem.implicitHeight || content.height
        }

        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
        function onWidthChanged() { content.width = content.contentItem.width + 2 * content.padding }
        function onHeightChanged() { content.height = content.contentItem.height + 2 * content.padding }
    }
}