274 lines
10 KiB
QML
274 lines
10 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Templates 2.15 as T
|
|
import DelegateUI 1.0
|
|
|
|
Item {
|
|
id: control
|
|
|
|
enum SnapMode
|
|
{
|
|
NoSnap = 0,
|
|
SnapAlways = 1,
|
|
SnapOnRelease = 2
|
|
}
|
|
|
|
signal firstMoved()
|
|
signal firstReleased()
|
|
signal secondMoved()
|
|
signal secondReleased()
|
|
|
|
property bool animationEnabled: DelTheme.animationEnabled
|
|
property int hoverCursorShape: Qt.PointingHandCursor
|
|
property real min: 0
|
|
property real max: 100
|
|
property real stepSize: 0.0
|
|
property var value: range ? [0, 0] : 0
|
|
readonly property var currentValue: {
|
|
if (__sliderLoader.item) {
|
|
return range ? [__sliderLoader.item.first.value, __sliderLoader.item.second.value] : __sliderLoader.item.value;
|
|
} else {
|
|
return value;
|
|
}
|
|
}
|
|
property bool range: false
|
|
property bool hovered: __sliderLoader.item ? __sliderLoader.item.hovered : false
|
|
property int snapMode: DelSlider.NoSnap
|
|
property int orientation: Qt.Horizontal
|
|
property int radiusBg: 6
|
|
property color colorBg: (enabled && hovered) ? DelTheme.DelSlider.colorBgHover : DelTheme.DelSlider.colorBg
|
|
property color colorHandle: DelTheme.DelSlider.colorHandle
|
|
property color colorTrack: {
|
|
if (!enabled) return DelTheme.DelSlider.colorTrackDisabled;
|
|
|
|
if (DelTheme.isDark)
|
|
return hovered ? DelTheme.DelSlider.colorTrackHoverDark : DelTheme.DelSlider.colorTrackDark;
|
|
else
|
|
return hovered ? DelTheme.DelSlider.colorTrackHover : DelTheme.DelSlider.colorTrack;
|
|
}
|
|
property Component handleToolTipDelegate: Item { }
|
|
property Component handleDelegate: Rectangle {
|
|
id: __handleItem
|
|
x: {
|
|
if (control.orientation == Qt.Horizontal) {
|
|
return slider.leftPadding + visualPosition * (slider.availableWidth - width);
|
|
} else {
|
|
return slider.topPadding + (slider.availableWidth - width) * 0.5;
|
|
}
|
|
}
|
|
y: {
|
|
if (control.orientation == Qt.Horizontal) {
|
|
return slider.topPadding + (slider.availableHeight - height) * 0.5;
|
|
} else {
|
|
return slider.leftPadding + visualPosition * (slider.availableHeight - height);
|
|
}
|
|
}
|
|
implicitWidth: active ? 18 : 14
|
|
implicitHeight: active ? 18 : 14
|
|
radius: height * 0.5
|
|
color: control.colorHandle
|
|
border.color: {
|
|
if (control.enabled) {
|
|
if (DelTheme.isDark)
|
|
return active ? DelTheme.DelSlider.colorHandleBorderHoverDark : DelTheme.DelSlider.colorHandleBorderDark;
|
|
else
|
|
return active ? DelTheme.DelSlider.colorHandleBorderHover : DelTheme.DelSlider.colorHandleBorder;
|
|
} else {
|
|
return DelTheme.DelSlider.colorHandleBorderDisabled;
|
|
}
|
|
}
|
|
border.width: active ? 4 : 2
|
|
|
|
property bool down: pressed
|
|
property bool active: __hoverHandler.hovered || down
|
|
|
|
Behavior on implicitWidth { enabled: control.animationEnabled; NumberAnimation { duration: DelTheme.Primary.durationFast } }
|
|
Behavior on implicitHeight { enabled: control.animationEnabled; NumberAnimation { duration: DelTheme.Primary.durationFast } }
|
|
Behavior on border.width { enabled: control.animationEnabled; NumberAnimation { duration: DelTheme.Primary.durationFast } }
|
|
Behavior on color { enabled: control.animationEnabled; ColorAnimation { duration: DelTheme.Primary.durationFast } }
|
|
Behavior on border.color { enabled: control.animationEnabled; ColorAnimation { duration: DelTheme.Primary.durationFast } }
|
|
|
|
HoverHandler {
|
|
id: __hoverHandler
|
|
cursorShape: control.hoverCursorShape
|
|
}
|
|
|
|
Loader {
|
|
sourceComponent: handleToolTipDelegate
|
|
onLoaded: item.parent = __handleItem;
|
|
property alias handleHovered: __hoverHandler.hovered
|
|
property alias handlePressed: __handleItem.down
|
|
}
|
|
}
|
|
property Component bgDelegate: Item {
|
|
Rectangle {
|
|
width: control.orientation == Qt.Horizontal ? parent.width : 4
|
|
height: control.orientation == Qt.Horizontal ? 4 : parent.height
|
|
anchors.horizontalCenter: control.orientation == Qt.Horizontal ? undefined : parent.horizontalCenter
|
|
anchors.verticalCenter: control.orientation == Qt.Horizontal ? parent.verticalCenter : undefined
|
|
radius: control.radiusBg
|
|
color: control.colorBg
|
|
|
|
Behavior on color { enabled: control.animationEnabled; ColorAnimation { duration: DelTheme.Primary.durationFast } }
|
|
|
|
Rectangle {
|
|
x: {
|
|
if (control.orientation == Qt.Horizontal)
|
|
return range ? (slider.first.visualPosition * parent.width) : 0;
|
|
else
|
|
return 0;
|
|
}
|
|
y: {
|
|
if (control.orientation == Qt.Horizontal)
|
|
return 0;
|
|
else
|
|
return range ? (slider.second.visualPosition * parent.height) : slider.visualPosition * parent.height;
|
|
}
|
|
width: {
|
|
if (control.orientation == Qt.Horizontal)
|
|
return range ? (slider.second.visualPosition * parent.width - x) : slider.visualPosition * parent.width;
|
|
else
|
|
return parent.width;
|
|
}
|
|
height: {
|
|
if (control.orientation == Qt.Horizontal)
|
|
return parent.height;
|
|
else
|
|
return range ? (slider.first.visualPosition * parent.height - y) : ((1.0 - slider.visualPosition) * parent.height);
|
|
}
|
|
color: colorTrack
|
|
radius: parent.radius
|
|
|
|
Behavior on color { enabled: control.animationEnabled; ColorAnimation { duration: DelTheme.Primary.durationFast } }
|
|
}
|
|
}
|
|
}
|
|
property string contentDescription: ""
|
|
|
|
onValueChanged: __fromValueUpdate();
|
|
|
|
function decrease(first = true) {
|
|
if (__sliderLoader.item) {
|
|
if (range) {
|
|
if (first)
|
|
__sliderLoader.item.first.decrease();
|
|
else
|
|
__sliderLoader.item.second.decrease();
|
|
} else {
|
|
__sliderLoader.item.decrease();
|
|
}
|
|
}
|
|
}
|
|
function increase(first = true) {
|
|
if (range) {
|
|
if (first)
|
|
__sliderLoader.item.first.increase();
|
|
else
|
|
__sliderLoader.item.second.increase();
|
|
} else {
|
|
__sliderLoader.item.decrease();
|
|
}
|
|
}
|
|
function __fromValueUpdate() {
|
|
if (__sliderLoader.item) {
|
|
if (range) {
|
|
__sliderLoader.item.setValues(...value);
|
|
} else {
|
|
__sliderLoader.item.value = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: __sliderComponent
|
|
|
|
T.Slider {
|
|
id: __control
|
|
from: min
|
|
to: max
|
|
stepSize: control.stepSize
|
|
orientation: control.orientation
|
|
snapMode: {
|
|
switch (control.snapMode) {
|
|
case DelSlider.SnapAlways: return T.Slider.SnapAlways;
|
|
case DelSlider.SnapOnRelease: return T.Slider.SnapOnRelease;
|
|
default: return T.Slider.NoSnap;
|
|
}
|
|
}
|
|
handle: Loader {
|
|
sourceComponent: handleDelegate
|
|
property alias slider: __control
|
|
property alias visualPosition: __control.visualPosition
|
|
property alias pressed: __control.pressed
|
|
}
|
|
background: Loader {
|
|
sourceComponent: bgDelegate
|
|
property alias slider: __control
|
|
property alias visualPosition: __control.visualPosition
|
|
}
|
|
onMoved: control.firstMoved();
|
|
onPressedChanged: {
|
|
if (!pressed)
|
|
control.firstReleased();
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: __rangeSliderComponent
|
|
|
|
T.RangeSlider {
|
|
id: __control
|
|
from: min
|
|
to: max
|
|
stepSize: control.stepSize
|
|
snapMode: {
|
|
switch (control.snapMode) {
|
|
case DelSlider.SnapAlways: return T.RangeSlider.SnapAlways;
|
|
case DelSlider.SnapOnRelease: return T.RangeSlider.SnapOnRelease;
|
|
default: return T.RangeSlider.NoSnap;
|
|
}
|
|
}
|
|
orientation: control.orientation
|
|
first.handle: Loader {
|
|
sourceComponent: handleDelegate
|
|
property alias slider: __control
|
|
property alias visualPosition: __control.first.visualPosition
|
|
property alias pressed: __control.first.pressed
|
|
}
|
|
first.onMoved: control.firstMoved();
|
|
first.onPressedChanged: {
|
|
if (!first.pressed)
|
|
control.firstReleased();
|
|
}
|
|
second.handle: Loader {
|
|
sourceComponent: handleDelegate
|
|
property alias slider: __control
|
|
property alias visualPosition: __control.second.visualPosition
|
|
property alias pressed: __control.second.pressed
|
|
}
|
|
second.onMoved: control.secondMoved();
|
|
second.onPressedChanged: {
|
|
if (!second.pressed)
|
|
control.secondReleased();
|
|
}
|
|
background: Loader {
|
|
sourceComponent: bgDelegate
|
|
property alias slider: __control
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: __sliderLoader
|
|
anchors.fill: parent
|
|
sourceComponent: control.range ? __rangeSliderComponent : __sliderComponent
|
|
onLoaded: __fromValueUpdate();
|
|
}
|
|
|
|
Accessible.role: Accessible.Slider
|
|
Accessible.name: control.contentDescription
|
|
Accessible.description: control.contentDescription
|
|
Accessible.onIncreaseAction: increase();
|
|
Accessible.onDecreaseAction: decrease();
|
|
}
|