mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-04-22 13:49:39 +08:00
392 lines
13 KiB
QML
392 lines
13 KiB
QML
// 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 higher 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
|
|
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.height + 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
|
|
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
|
|
}
|
|
}
|
|
}
|