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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as * 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. * 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 import org.kde.plasma.core 0.1 as PlasmaCore
import QtQuick 1.0
import org.kde.plasma.core 0.1 as PlasmaCore
PlasmaCore.FrameSvgItem { // TODO: add support mouse wheel and key events
id: scrollBar Item {
width: orientation==Qt.Horizontal?200:22 id: scrollbar
height: orientation==Qt.Horizontal?22:200
property int minimum: 0 // Common API
property int maximum: 100 property Flickable flickableItem: null
property int value: 0
property string orientation: Qt.Horizontal
onValueChanged: { // Plasma API
if (drag.state != "dragging") { property int orientation: Qt.Horizontal
if (orientation == Qt.Horizontal) { property bool animated: false
drag.x = (value/(maximum-minimum))*(scrollBar.width - drag.width) property bool inverted: false
} else { property bool updateValueWhileDragging: true
drag.y = (value/(maximum-minimum))*(scrollBar.height - drag.height) property alias stepSize: range.stepSize
property alias pressed: mouseArea.pressed
// 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);
} }
} 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;
imagePath: "widgets/scrollbar" if (_isVertical)
prefix: orientation==Qt.Horizontal?"background-horizontal":"background-vertical" flickableItem.contentY = value;
else
flickableItem.contentX = value;
}
position: handle.x
onPositionChanged: { handle.x = position; }
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))
}
}
onYChanged: {
if (orientation != Qt.Horizontal && state == "dragging") {
value = (maximum - minimum)*(x/(scrollBar.height-height))
}
} }
Behavior on x { PlasmaCore.FrameSvgItem {
NumberAnimation { id: groove
duration: 200
}
}
Behavior on y {
NumberAnimation {
duration: 200
}
}
imagePath: "widgets/scrollbar"
prefix: "slider"
MouseArea {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true imagePath: "widgets/scrollbar"
prefix: "background-horizontal"
}
drag.target: parent; PlasmaCore.FrameSvgItem {
drag.axis: orientation == Qt.Horizontal?"XAxis":"YAxis" id: handle
drag.minimumX: 0;
drag.maximumX: scrollBar.width-drag.width; transform: Translate { x: - handle.width / 2 }
drag.minimumY: 0; x: fakeHandle.x
drag.maximumY: scrollBar.height-drag.height; 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
}
onEntered: drag.prefix = "mouseover-slider"
onExited: drag.prefix = "slider"
onPressed: { onPressed: {
drag.prefix = "sunken-slider" // Clamp the value
drag.state = "dragging" 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: { onReleased: {
containsMouse?drag.prefix = "mouseover-slider":drag.prefix = "slider" // If we don't update while dragging, this is the only
drag.state = "normal" // 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" color: "lightgrey"
Flickable { Flickable {
id: buttonPage id: page
anchors.fill: parent anchors.fill: parent
contentWidth: 1200 contentWidth: 2200
contentHeight: 600
Row { Row {
x: 30 x: 30
@ -211,6 +212,71 @@ Rectangle {
text: slider2.value 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
} }
} }
} }