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: eb949a84ecf882dfd47b824fc1fc2d555f4a3251 (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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
// 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.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")

    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

    // 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()
        }
    }

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

    // The panel needs to close when it becomes disabled
    Connections
    {
        target: base
        onEnabledChanged:
        {
            if (!base.enabled && expanded)
            {
                toggleContent()
            }
        }
    }

    implicitHeight: 100 * screenScaleFactor
    implicitWidth: 400 * screenScaleFactor

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

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

        Label
        {
            id: disabledLabel
            visible: !base.enabled
            leftPadding: background.padding
            text: ""
            font: UM.Theme.getFont("default")
            renderType: Text.NativeRendering
            verticalAlignment: Text.AlignVCenter
            color: UM.Theme.getColor("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: 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("small_button_text")
            }
        }

    }

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