Add ScrollBar component

- The stepButtons are not yet implemented

Signed-off-by: Daker Fernandes Pinheiro <dakerfp@gmail.com>
This commit is contained in:
Daker Fernandes Pinheiro 2011-04-28 07:50:31 -03:00
parent cb00a42cb8
commit 6b291d0ac6
2 changed files with 228 additions and 74 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 by Marco Martin <mart@kde.org>
* Copyright (C) 2011 by Daker Fernandes Pinheiro <dakerfp@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
@ -17,91 +17,179 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import Qt 4.7
import QtQuick 1.0
import org.kde.plasma.core 0.1 as PlasmaCore
PlasmaCore.FrameSvgItem {
id: scrollBar
width: orientation==Qt.Horizontal?200:22
height: orientation==Qt.Horizontal?22:200
import QtQuick 1.0
import org.kde.plasma.core 0.1 as PlasmaCore
property int minimum: 0
property int maximum: 100
property int value: 0
property string orientation: Qt.Horizontal
// TODO: add support mouse wheel and key events
Item {
id: scrollbar
onValueChanged: {
if (drag.state != "dragging") {
if (orientation == Qt.Horizontal) {
drag.x = (value/(maximum-minimum))*(scrollBar.width - drag.width)
} else {
drag.y = (value/(maximum-minimum))*(scrollBar.height - drag.height)
}
}
}
// Common API
property Flickable flickableItem: null
imagePath: "widgets/scrollbar"
prefix: orientation==Qt.Horizontal?"background-horizontal":"background-vertical"
// Plasma API
property int orientation: Qt.Horizontal
property bool animated: false
property bool inverted: false
property bool updateValueWhileDragging: true
property alias stepSize: range.stepSize
property alias pressed: mouseArea.pressed
PlasmaCore.FrameSvgItem {
id: drag
anchors.top: orientation==Qt.Horizontal?parent.top:null
anchors.bottom: orientation==Qt.Horizontal?parent.bottom:null
anchors.left: orientation==Qt.Horizontal?null:parent.left
anchors.right: orientation==Qt.Horizontal?null:parent.right
state: "normal"
width: (orientation == Qt.Horizontal)?Math.max(12, (parent.width*1/(scrollBar.maximum-scrollBar.minimum))):0
height: (orientation != Qt.Horizontal)?Math.max(12, (parent.height*1/(scrollBar.maximum-scrollBar.minimum))):0
x: 0
y: 0
onXChanged: {
if (orientation == Qt.Horizontal && state == "dragging") {
value = (maximum - minimum)*(x/(scrollBar.width-width))
// Convinience API
property bool _isVertical: orientation == Qt.Vertical
width: _isVertical ? 22 : 200
height: _isVertical ? 200 : 22
visible: flickableItem && handle.width < contents.width
Item {
id: contents
width: _isVertical ? scrollbar.height : scrollbar.width
height: _isVertical ? scrollbar.width : scrollbar.height
rotation: _isVertical ? -90 : 0
anchors.centerIn: parent
PlasmaCore.RangeModel {
id: range
minimumValue: 0
maximumValue: {
var diff;
if (_isVertical)
diff = flickableItem.contentHeight - flickableItem.height;
else
diff = flickableItem.contentWidth - flickableItem.width;
return Math.max(0, diff);
}
}
onYChanged: {
if (orientation != Qt.Horizontal && state == "dragging") {
value = (maximum - minimum)*(x/(scrollBar.height-height))
stepSize: 0.0
inverted: _isVertical ? !scrollbar.inverted : scrollbar.inverted
positionAtMinimum: 0 + handle.width / 2
positionAtMaximum: contents.width - handle.width / 2
value: _isVertical ? flickableItem.contentY : flickableItem.contentX
onValueChanged: {
if (flickableItem.flicking)
return;
if (_isVertical)
flickableItem.contentY = value;
else
flickableItem.contentX = value;
}
position: handle.x
onPositionChanged: { handle.x = position; }
}
Behavior on x {
NumberAnimation {
duration: 200
}
}
Behavior on y {
NumberAnimation {
duration: 200
}
}
imagePath: "widgets/scrollbar"
prefix: "slider"
MouseArea {
PlasmaCore.FrameSvgItem {
id: groove
anchors.fill: parent
hoverEnabled: true
drag.target: parent;
drag.axis: orientation == Qt.Horizontal?"XAxis":"YAxis"
drag.minimumX: 0;
drag.maximumX: scrollBar.width-drag.width;
drag.minimumY: 0;
drag.maximumY: scrollBar.height-drag.height;
onEntered: drag.prefix = "mouseover-slider"
onExited: drag.prefix = "slider"
imagePath: "widgets/scrollbar"
prefix: "background-horizontal"
}
PlasmaCore.FrameSvgItem {
id: handle
transform: Translate { x: - handle.width / 2 }
x: fakeHandle.x
anchors.verticalCenter: groove.verticalCenter
width: {
var ratio;
if (_isVertical)
ratio = flickableItem.visibleArea.heightRatio;
else
ratio = flickableItem.visibleArea.widthRatio;
return ratio * parent.width;
}
height: parent.height - margins.top // TODO: check mergin
imagePath: "widgets/scrollbar"
prefix: {
if (scrollbar.pressed)
return "sunken-slider";
if (scrollbar.activeFocus || mouseArea.containsMouse)
return "mouseover-slider";
else
return "slider";
}
Behavior on x {
id: behavior
enabled: !mouseArea.drag.active && scrollbar.animated &&
!flickableItem.flicking
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
}
onPressed: {
drag.prefix = "sunken-slider"
drag.state = "dragging"
// 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;
scrollbar.forceActiveFocus();
}
onReleased: {
containsMouse?drag.prefix = "mouseover-slider":drag.prefix = "slider"
drag.state = "normal"
// If we don't update while dragging, this is the only
// moment that the range is updated.
if (!scrollbar.updateValueWhileDragging)
range.position = fakeHandle.x;
}
}
}
// 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
}
}

View File

@ -26,10 +26,11 @@ Rectangle {
color: "lightgrey"
Flickable {
id: buttonPage
id: page
anchors.fill: parent
contentWidth: 1200
contentWidth: 2200
contentHeight: 600
Row {
x: 30
@ -211,6 +212,71 @@ Rectangle {
text: slider2.value
}
}
Column {
spacing: 20
Text {
font.pixelSize: 20
text: "Scroll Bar"
}
ListView {
id: scrollList
width: 200
height: 200
clip: true
model: 100
delegate: Text {
width: 200
height: 18
text: index
}
PlasmaComponents.ScrollBar {
orientation: Qt.Vertical
flickableItem: parent
animated: true
anchors {
top: parent.top
right: parent.right
bottom: horizontalScrollBar.top
}
}
Rectangle {
anchors.fill: parent
color: "grey"
opacity: 0.3
}
}
}
}
}
PlasmaComponents.ScrollBar {
id: horizontalScrollBar
flickableItem: page
animated: true
anchors {
left: parent.left
right: verticalScrollBar.left
bottom: parent.bottom
}
}
PlasmaComponents.ScrollBar {
id: verticalScrollBar
orientation: Qt.Vertical
flickableItem: page
animated: true
anchors {
top: parent.top
right: parent.right
bottom: horizontalScrollBar.top
}
}
}