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

LayerSlider.qml « SimulationView « plugins - github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6f608fe47428f163e0bc063538380d51577cfa7a (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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
// Copyright (c) 2017 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.

import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.1

import UM 1.0 as UM
import Cura 1.0 as Cura

Item
{
    id: sliderRoot

    // Handle properties
    property real handleSize: UM.Theme.getSize("slider_handle").width
    property real handleRadius: handleSize / 2
    property real minimumRangeHandleSize: handleSize / 2
    property color upperHandleColor: UM.Theme.getColor("slider_handle")
    property color lowerHandleColor: UM.Theme.getColor("slider_handle")
    property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
    property color handleActiveColor: UM.Theme.getColor("slider_handle_active")
    property var activeHandle: upperHandle

    // Track properties
    property real trackThickness: UM.Theme.getSize("slider_groove").width // width of the slider track
    property real trackRadius: UM.Theme.getSize("slider_groove_radius").width
    property color trackColor: UM.Theme.getColor("slider_groove")

    // value properties
    property real maximumValue: 100
    property real minimumValue: 0
    property real minimumRange: 0 // minimum range allowed between min and max values
    property bool roundValues: true
    property real upperValue: maximumValue
    property real lowerValue: minimumValue

    property bool layersVisible: true
    property bool manuallyChanged: true     // Indicates whether the value was changed manually or during simulation

    function getUpperValueFromSliderHandle()
    {
        return upperHandle.getValue()
    }

    function setUpperValue(value)
    {
        upperHandle.setValue(value)
        updateRangeHandle()
    }

    function getLowerValueFromSliderHandle()
    {
        return lowerHandle.getValue()
    }

    function setLowerValue(value)
    {
        lowerHandle.setValue(value)
        updateRangeHandle()
    }

    function updateRangeHandle()
    {
        rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height)
    }

    // set the active handle to show only one label at a time
    function setActiveHandle(handle)
    {
        activeHandle = handle
    }

    function normalizeValue(value)
    {
        return Math.min(Math.max(value, sliderRoot.minimumValue), sliderRoot.maximumValue)
    }

    // Slider track
    Rectangle
    {
        id: track

        width: sliderRoot.trackThickness
        height: sliderRoot.height - sliderRoot.handleSize
        radius: sliderRoot.trackRadius
        anchors.centerIn: sliderRoot
        color: sliderRoot.trackColor
        visible: sliderRoot.layersVisible
    }

    // Range handle
    Item
    {
        id: rangeHandle

        y: upperHandle.y + upperHandle.height
        width: sliderRoot.handleSize
        height: sliderRoot.minimumRangeHandleSize
        anchors.horizontalCenter: sliderRoot.horizontalCenter
        visible: sliderRoot.layersVisible

        // Set the new value when dragging
        function onHandleDragged()
        {
            sliderRoot.manuallyChanged = true

            upperHandle.y = y - upperHandle.height
            lowerHandle.y = y + height

            var upperValue = sliderRoot.getUpperValueFromSliderHandle()
            var lowerValue = sliderRoot.getLowerValueFromSliderHandle()

            // set both values after moving the handle position
            UM.SimulationView.setCurrentLayer(upperValue)
            UM.SimulationView.setMinimumLayer(lowerValue)
        }

        function setValueManually(value)
        {
            sliderRoot.manuallyChanged = true
            upperHandle.setValue(value)
        }

        function setValue(value)
        {
            var range = sliderRoot.upperValue - sliderRoot.lowerValue
            value = Math.min(value, sliderRoot.maximumValue)
            value = Math.max(value, sliderRoot.minimumValue + range)

            UM.SimulationView.setCurrentLayer(value)
            UM.SimulationView.setMinimumLayer(value - range)
        }

        Rectangle
        {
            width: sliderRoot.trackThickness
            height: parent.height + sliderRoot.handleSize
            anchors.centerIn: parent
            radius: sliderRoot.trackRadius
            color: sliderRoot.rangeHandleColor
        }

        MouseArea
        {
            anchors.fill: parent

            drag
            {
                target: parent
                axis: Drag.YAxis
                minimumY: upperHandle.height
                maximumY: sliderRoot.height - (rangeHandle.height + lowerHandle.height)
            }

            onPositionChanged: parent.onHandleDragged()
            onPressed:
            {
                sliderRoot.setActiveHandle(rangeHandle)
                sliderRoot.forceActiveFocus()
            }
        }

    }

    onHeightChanged : {
        // After a height change, the pixel-position of the handles is out of sync with the property value
        setLowerValue(lowerValue)
        setUpperValue(upperValue)
    }

    // Upper handle
    Rectangle
    {
        id: upperHandle

        y: sliderRoot.height - (sliderRoot.minimumRangeHandleSize + 2 * sliderRoot.handleSize)
        width: sliderRoot.handleSize
        height: sliderRoot.handleSize
        anchors.horizontalCenter: sliderRoot.horizontalCenter
        radius: sliderRoot.handleRadius
        color: upperHandleLabel.activeFocus ? sliderRoot.handleActiveColor : sliderRoot.upperHandleColor
        visible: sliderRoot.layersVisible

        function onHandleDragged()
        {
            sliderRoot.manuallyChanged = true

            // don't allow the lower handle to be heigher than the upper handle
            if (lowerHandle.y - (y + height) < sliderRoot.minimumRangeHandleSize)
            {
                lowerHandle.y = y + height + sliderRoot.minimumRangeHandleSize
            }

            // update the range handle
            sliderRoot.updateRangeHandle()

            // set the new value after moving the handle position
            UM.SimulationView.setCurrentLayer(getValue())
        }

        // get the upper value based on the slider position
        function getValue()
        {
            var result = y / (sliderRoot.height - (2 * sliderRoot.handleSize + sliderRoot.minimumRangeHandleSize))
            result = sliderRoot.maximumValue + result * (sliderRoot.minimumValue - (sliderRoot.maximumValue - sliderRoot.minimumValue))
            result = sliderRoot.roundValues ? Math.round(result) : result
            return result
        }

        function setValueManually(value)
        {
            sliderRoot.manuallyChanged = true
            upperHandle.setValue(value)
        }

        // set the slider position based on the upper value
        function setValue(value)
        {
            // Normalize values between range, since using arrow keys will create out-of-the-range values
            value = sliderRoot.normalizeValue(value)

            UM.SimulationView.setCurrentLayer(value)

            var diff = (value - sliderRoot.maximumValue) / (sliderRoot.minimumValue - sliderRoot.maximumValue)
            // In case there is only one layer, the diff value results in a NaN, so this is for catching this specific case
            if (isNaN(diff))
            {
                diff = 0
            }
            var newUpperYPosition = Math.round(diff * (sliderRoot.height - (2 * sliderRoot.handleSize + sliderRoot.minimumRangeHandleSize)))
            y = newUpperYPosition

            // update the range handle
            sliderRoot.updateRangeHandle()
        }

        Keys.onUpPressed: upperHandleLabel.setValue(upperHandleLabel.value + ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
        Keys.onDownPressed: upperHandleLabel.setValue(upperHandleLabel.value - ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))

        // dragging
        MouseArea
        {
            anchors.fill: parent

            drag
            {
                target: parent
                axis: Drag.YAxis
                minimumY: 0
                maximumY: sliderRoot.height - (2 * sliderRoot.handleSize + sliderRoot.minimumRangeHandleSize)
            }

            onPositionChanged: parent.onHandleDragged()
            onPressed:
            {
                sliderRoot.setActiveHandle(upperHandle)
                upperHandleLabel.forceActiveFocus()
            }
        }

        SimulationSliderLabel
        {
            id: upperHandleLabel

            height: sliderRoot.handleSize + UM.Theme.getSize("small_margin").height
            anchors.bottom: parent.top
            anchors.bottomMargin: UM.Theme.getSize("narrow_margin").height
            anchors.horizontalCenter: parent.horizontalCenter
            target: Qt.point(parent.width / 2, parent.top)
            visible: sliderRoot.activeHandle == parent || sliderRoot.activeHandle == rangeHandle

            // custom properties
            maximumValue: sliderRoot.maximumValue
            value: sliderRoot.upperValue
            busy: UM.SimulationView.busy
            setValue: upperHandle.setValueManually // connect callback functions
        }
    }

    // Lower handle
    Rectangle
    {
        id: lowerHandle

        y: sliderRoot.height - sliderRoot.handleSize
        width: parent.handleSize
        height: parent.handleSize
        anchors.horizontalCenter: parent.horizontalCenter
        radius: sliderRoot.handleRadius
        color: lowerHandleLabel.activeFocus ? sliderRoot.handleActiveColor : sliderRoot.lowerHandleColor

        visible: sliderRoot.layersVisible

        function onHandleDragged()
        {
            sliderRoot.manuallyChanged = true

            // don't allow the upper handle to be lower than the lower handle
            if (y - (upperHandle.y + upperHandle.height) < sliderRoot.minimumRangeHandleSize)
            {
                upperHandle.y = y - (upperHandle.heigth + sliderRoot.minimumRangeHandleSize)
            }

            // update the range handle
            sliderRoot.updateRangeHandle()

            // set the new value after moving the handle position
            UM.SimulationView.setMinimumLayer(getValue())
        }

        // get the lower value from the current slider position
        function getValue()
        {
            var result = (y - (sliderRoot.handleSize + sliderRoot.minimumRangeHandleSize)) / (sliderRoot.height - (2 * sliderRoot.handleSize + sliderRoot.minimumRangeHandleSize));
            result = sliderRoot.maximumValue - sliderRoot.minimumRange + result * (sliderRoot.minimumValue - (sliderRoot.maximumValue - sliderRoot.minimumRange))
            result = sliderRoot.roundValues ? Math.round(result) : result
            return result
        }

        function setValueManually(value)
        {
            sliderRoot.manuallyChanged = true
            lowerHandle.setValue(value)
        }

        // set the slider position based on the lower value
        function setValue(value)
        {
            // Normalize values between range, since using arrow keys will create out-of-the-range values
            value = sliderRoot.normalizeValue(value)

            UM.SimulationView.setMinimumLayer(value)

            var diff = (value - sliderRoot.maximumValue) / (sliderRoot.minimumValue - sliderRoot.maximumValue)
            // In case there is only one layer, the diff value results in a NaN, so this is for catching this specific case
            if (isNaN(diff))
            {
                diff = 0
            }
            var newLowerYPosition = Math.round((sliderRoot.handleSize + sliderRoot.minimumRangeHandleSize) + diff * (sliderRoot.height - (2 * sliderRoot.handleSize + sliderRoot.minimumRangeHandleSize)))
            y = newLowerYPosition

            // update the range handle
            sliderRoot.updateRangeHandle()
        }

        Keys.onUpPressed: lowerHandleLabel.setValue(lowerHandleLabel.value + ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
        Keys.onDownPressed: lowerHandleLabel.setValue(lowerHandleLabel.value - ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))

        // dragging
        MouseArea
        {
            anchors.fill: parent

            drag
            {
                target: parent
                axis: Drag.YAxis
                minimumY: upperHandle.height + sliderRoot.minimumRangeHandleSize
                maximumY: sliderRoot.height - parent.height
            }

            onPositionChanged: parent.onHandleDragged()
            onPressed:
            {
                sliderRoot.setActiveHandle(lowerHandle)
                lowerHandleLabel.forceActiveFocus()
            }
        }

        SimulationSliderLabel
        {
            id: lowerHandleLabel

            height: sliderRoot.handleSize + UM.Theme.getSize("small_margin").height
            anchors.top: parent.bottom
            anchors.topMargin: UM.Theme.getSize("narrow_margin").height
            anchors.horizontalCenter: parent.horizontalCenter
            target: Qt.point(parent.width / 2, parent.bottom)
            visible: sliderRoot.activeHandle == parent || sliderRoot.activeHandle == rangeHandle

            // custom properties
            maximumValue: sliderRoot.maximumValue
            value: sliderRoot.lowerValue
            busy: UM.SimulationView.busy
            setValue: lowerHandle.setValueManually // connect callback functions
        }
    }
}