diff --git a/declarativeimports/plasmacomponents/Slider.qml b/declarativeimports/plasmacomponents/Slider.qml new file mode 100644 index 000000000..8a52b7d39 --- /dev/null +++ b/declarativeimports/plasmacomponents/Slider.qml @@ -0,0 +1,212 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +// TODO: add support mouse wheel and key events +// TODO: create a value indicator for plasma? +PlasmaCore.FrameSvgItem { + id: slider + + // Common API + property alias stepSize: range.stepSize + property alias minimumValue: range.minimumValue + property alias maximumValue: range.maximumValue + property alias value: range.value + property int orientation: Qt.Horizontal + property alias pressed: mouseArea.pressed + property bool valueIndicatorVisible: false + property string valueIndicatorText: value + + // Plasma API + property bool animated: false + property alias inverted: range.inverted + property bool updateValueWhileDragging: true + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + + width: _isVertical ? 22 : 200 + height: _isVertical ? 200 : 22 + + Item { + id: contents + + width: _isVertical ? slider.height : slider.width + height: _isVertical ? slider.width : slider.height + rotation: _isVertical ? -90 : 0 + + anchors.centerIn: parent + + PlasmaCore.RangeModel { + id: range + + minimumValue: 0.0 + maximumValue: 1.0 + value: 0 + stepSize: 0.0 + inverted: false + positionAtMinimum: 0 + handle.width / 2 + positionAtMaximum: contents.width - handle.width / 2 + } + + PlasmaCore.SvgItem { + id: groove + + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + height: 3 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-line" + } + + PlasmaCore.SvgItem { + id: focusSvg + + transform: Translate { x: - handle.width / 2 } + anchors { + fill: handle + margins: -1 // Hardcoded + } + opacity: slider.activeFocus ? 1 : 0 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.SvgItem { + id: hover + + transform: Translate { x: - handle.width / 2 } + anchors { + fill: handle + margins: -2 // Hardcoded + } + opacity: 0 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.SvgItem { + id: handle + + transform: Translate { x: - handle.width / 2 } + x: fakeHandle.x + anchors { + verticalCenter: groove.verticalCenter + } + width: height + height: parent.height + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-handle" + + Behavior on x { + id: behavior + enabled: !mouseArea.drag.active && slider.animated + + PropertyAnimation { + duration: behavior.enabled ? 150 : 0 + easing.type: Easing.OutSine + } + } + } + + Item { + id: fakeHandle + width: handle.width + height: handle.height + transform: Translate { x: - handle.width / 2 } + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + drag { + target: fakeHandle + axis: Drag.XAxis + minimumX: range.positionAtMinimum + maximumX: range.positionAtMaximum + } + hoverEnabled: true + + onEntered: { + hover.opacity = 1; + } + onExited: { + if (!pressed) + hover.opacity = 0; + } + onPressed: { + // Clamp the value + var newX = Math.max(mouse.x, drag.minimumX); + newX = Math.min(newX, drag.maximumX); + + // Debounce the press: a press event inside the handler will not + // change its position, the user needs to drag it. + if (Math.abs(newX - fakeHandle.x) > handle.width / 2) + range.position = newX; + + slider.forceActiveFocus(); + } + onReleased: { + // If we don't update while dragging, this is the only + // moment that the range is updated. + if (!slider.updateValueWhileDragging) + range.position = fakeHandle.x; + + if (!containsMouse) + hover.opacity = 0; + } + } + } + + // Range position normally follow fakeHandle, except when + // 'updateValueWhileDragging' is false. In this case it will only follow + // if the user is not pressing the handle. + Binding { + when: updateValueWhileDragging || !mouseArea.pressed + target: range + property: "position" + value: fakeHandle.x + } + + // During the drag, we simply ignore position set from the range, this + // means that setting a value while dragging will not "interrupt" the + // dragging activity. + Binding { + when: !mouseArea.drag.active + target: fakeHandle + property: "x" + value: range.position + } +} + + diff --git a/declarativeimports/plasmacomponents/qmldir b/declarativeimports/plasmacomponents/qmldir index dafc9dae7..017fa0e5e 100644 --- a/declarativeimports/plasmacomponents/qmldir +++ b/declarativeimports/plasmacomponents/qmldir @@ -7,4 +7,5 @@ IconWidget 0.1 IconWidget.qml PushButton 0.1 PushButton.qml RadioButton 0.1 RadioButton.qml ScrollBar 0.1 ScrollBar.qml +Slider 0.1 Slider.qml ToolButton 0.1 ToolButton.qml diff --git a/declarativeimports/test/ComponentsGallery.qml b/declarativeimports/test/ComponentsGallery.qml index 2474212d0..91c814a1b 100644 --- a/declarativeimports/test/ComponentsGallery.qml +++ b/declarativeimports/test/ComponentsGallery.qml @@ -17,11 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import QtQuick 1.1 +import QtQuick 1.0 import org.kde.plasma.components 0.1 as PlasmaComponents Rectangle { - width: 600 + width: 800 height: 400 color: "lightgrey" @@ -29,7 +29,7 @@ Rectangle { id: buttonPage anchors.fill: parent - contentWidth: 1000 + contentWidth: 1200 Row { x: 30 @@ -38,9 +38,9 @@ Rectangle { bottom: parent.bottom margins: 20 } + spacing: 30 Column { - width: 200 spacing: 20 Text { @@ -160,10 +160,56 @@ Rectangle { text: "BusyIndicator" } - PlasmaComponents.BusyIndicator { } PlasmaComponents.BusyIndicator { running: true } + + PlasmaComponents.BusyIndicator { + id: busy + running: mouse.pressed + MouseArea { + id: mouse + anchors.fill: parent + } + } + } + Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Slider" + } + + PlasmaComponents.Slider { + id: slider1 + width: 140 + height: 20 + animated: true + Component.onCompleted: { + forceActiveFocus(); + } + } + + Text { + text: slider1.value + } + + PlasmaComponents.Slider { + id: slider2 + width: 20 + height: 140 + orientation: Qt.Vertical + minimumValue: 10 + maximumValue: 1000 + stepSize: 50 + inverted: true + animated: true + } + + Text { + text: slider2.value + } } } }