pragma ComponentBehavior: Bound import QtQuick import QtQuick.Templates as QQCT import Weave.Controls import Weave.Templates as T T.Slider { id: root implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitContentWidth + leftPadding + rightPadding, implicitHandleWidth + leftPadding + rightPadding) implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitContentHeight + topPadding + bottomPadding, implicitHandleHeight + topPadding + bottomPadding) opacity: enabled ? 1.0 : Theme.component.slider.opacity.disabled layer.enabled: !root.enabled hoverEnabled: root.enabled snapMode: stepSize > 0 ? QQCT.RangeSlider.SnapAlways : QQCT.RangeSlider.NoSnap ticksVisible: stepSize > 0 toolTipText: root.value.toFixed(2) background: Item { implicitWidth: root.orientation === Qt.Horizontal ? Theme.component.slider.continuous.minWidth : Theme.component.slider.thumbContainer.height implicitHeight: root.orientation === Qt.Horizontal ? Theme.component.slider.thumbContainer.height : Theme.component.slider.continuous.minWidth Rectangle { id: track anchors.centerIn: parent width: root.orientation === Qt.Horizontal ? parent.width : Theme.component.slider.rail.height height: root.orientation === Qt.Horizontal ? Theme.component.slider.rail.height : parent.height color: Theme.component.slider.rail.backgroundColor Rectangle { x: root.orientation === Qt.Horizontal ? (root.mirrored ? (root.visualPosition * parent.width) : 0.0) : 0.0 y: root.orientation === Qt.Horizontal ? 0.0 : (parent.height - height) width: root.orientation === Qt.Horizontal ? (root.position * parent.width) : parent.width height: root.orientation === Qt.Horizontal ? parent.height : (root.position * parent.height) color: Theme.component.slider.track.backgroundColor } } Row { id: tickMarkRow visible: root.ticksVisible && root.orientation === Qt.Horizontal anchors { left: parent.left right: parent.right top: track.bottom } height: Theme.component.slider.mark.height spacing: (root.stepSize/rangeMagnitude) * (width - (tickCount*tickWidth)) property real rangeMagnitude: Math.abs(root.to - root.from) property int tickCount: (root.ticksVisible && root.stepSize > 0) ? (rangeMagnitude / root.stepSize) + 1 : 0 property int tickWidth: Theme.component.slider.mark.width Repeater { model: tickMarkRow.visible ? tickMarkRow.tickCount : 0 delegate: Rectangle { height: tickMarkRow.height width: tickMarkRow.tickWidth color: Theme.component.slider.mark.backgroundColor } } } Column { id: tickMarkColumn visible: root.ticksVisible && root.orientation !== Qt.Horizontal anchors { top: parent.top bottom: parent.bottom right: track.left } width: Theme.component.slider.mark.height spacing: (root.stepSize/tickMarkRow.rangeMagnitude) * (height - (tickMarkRow.tickCount * tickHeight)) property int tickHeight: Theme.component.slider.mark.width Repeater { model: tickMarkColumn.visible ? tickMarkRow.tickCount : 0 delegate: Rectangle { height: tickMarkColumn.tickHeight width: tickMarkColumn.width color: Theme.component.slider.mark.backgroundColor } } } } handle: Item { // We don't want the handle to overspill the parent bounds, // otherwise the mouse/touch events won't be filtered/delivered appropriately. // But, we also want the track to span the entire width of the control. // So, in order to have an appropriately sized touch area handle, we cannot // merely center the handle on the visualPosition, or it will overspill bounds // when the visualPosition is 0.0 or 1.0. // Instead: map the span to a smaller span, and then map the visualPosition // onto the smaller span, and draw the handle as if centered on that mapped // position. property real mappedSpan: root.orientation === Qt.Horizontal ? (root.availableWidth - width) : (root.availableHeight - height) property real mappedPosition: root.visualPosition * mappedSpan x: root.orientation === Qt.Horizontal ? root.leftPadding + mappedPosition : root.leftPadding + (root.availableWidth-width)/2 y: root.orientation === Qt.Horizontal ? root.topPadding + (root.availableHeight-height)/2 : root.topPadding + mappedPosition implicitWidth: root.orientation === Qt.Horizontal ? Theme.component.slider.thumbContainer.width : Theme.component.slider.thumbContainer.height implicitHeight: root.orientation === Qt.Horizontal ? Theme.component.slider.thumbContainer.height : Theme.component.slider.thumbContainer.width Rectangle { id: visualHandle // Now, we cannot center the visual handle indicator within the handle touch area, // since the handle touch area is no longer centered on the visualPosition. // Instead, we map the handle to a position within the handle touch area, // based on the visual position. x: root.orientation === Qt.Horizontal ? ((parent.width - width) * root.visualPosition) : ((parent.width - width)/2) y: root.orientation === Qt.Horizontal ? ((parent.height - height)/2) : ((parent.height - height) * root.visualPosition) implicitWidth: root.orientation === Qt.Horizontal ? Theme.component.slider.thumb.width : Theme.component.slider.thumb.height implicitHeight: root.orientation === Qt.Horizontal ? Theme.component.slider.thumb.height : Theme.component.slider.thumb.width color: Theme.component.slider.thumb.backgroundColor radius: Theme.component.slider.thumb.borderRadius BoxShadow { anchors.fill: visualHandle radius: visualHandle.radius readonly property string shadowState: root.pressed ? "pressed" : (root.enabled && root.hovered) ? "hover" : root.visualFocus ? "focus" : "hover" offsetX: Theme.component.slider.thumb.boxShadowX[shadowState] offsetY: Theme.component.slider.thumb.boxShadowY[shadowState] blurRadius: Theme.component.slider.thumb.boxShadowBlur[shadowState] spreadRadius: Theme.component.slider.thumb.boxShadowSpread[shadowState] color: shadowState === "hover" && (!root.enabled || !root.hovered) ? "transparent" : Theme.component.slider.thumb.boxShadowColor[shadowState] } ToolTip.visible: root.toolTipEnabled && (root.pressed || root.hovered) ToolTip.preferredAlignment: root.orientation === Qt.Horizontal ? T.Flyout.PreferVertical : T.Flyout.PreferHorizontal ToolTip.text: root.toolTipText ToolTip.content: ToolTipContent {} } } }