plasma-framework/declarativeimports/plasmaextracomponents/qml/ScrollArea.qml

266 lines
8.9 KiB
QML
Raw Normal View History

/*
* Copyright 2012 Marco Martin <mart@kde.org>
*
* 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 Library 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.
*/
/**Documented API
Inherits:
Item
Imports:
QtQuick 1.1
org.kde.plasma.components 0.1
Description:
This item takes a Flickable and automatically puts scrollbars in adjusting the layout if needed. The scrollbars will be interactive or not, depending on the platform.
If flickableItem is a categorized ListView the vertical scrollbar will be a SectionScroller.
Properties:
Item flickableItem:
The Flickable of this area: it can be either a Flickable or a subclass, ListView or GridView
**/
import QtQuick 1.1
import org.kde.plasma.components 0.1
2012-04-03 13:48:42 +02:00
import org.kde.plasma.core 0.1 as PlasmaCore
Item {
id: root
property Flickable flickableItem
//FIXME: this alias seems necessary for it to correctly parse
default property alias flickableItemDefault: root.flickableItem
2012-08-09 11:45:42 +02:00
clip: true
Connections {
target: root
onFlickableItemChanged: {
root.flickableItem.parent = root
root.flickableItem.anchors.fill = root
internal.checkVerticalScrollBar()
internal.checkHorizontalScrollBar()
}
}
Component.onCompleted: {
root.flickableItem.parent = root
root.flickableItem.anchors.fill = root
internal.checkVerticalScrollBar()
internal.checkHorizontalScrollBar()
}
Connections {
target: flickableItem
onContentHeightChanged: internal.checkVerticalScrollBar()
onHeightChanged: internal.checkVerticalScrollBar()
onContentWidthChanged: internal.checkHorizontalScrollBar()
onWidthChanged: internal.checkHorizontalScrollBar()
}
QtObject {
id: internal
property Item verticalScrollBar
property Item horizontalScrollBar
function checkVerticalScrollBar() {
if (!flickableItem) {
return
}
if (flickableItem.contentHeight > flickableItem.height) {
//Do we have to change the type?
//from section to normal
if ((!flickableItem.model || flickableItem.model.get === undefined || !flickableItem.section || !flickableItem.section.property) &&
(!verticalScrollBar || verticalScrollBar.orientation === undefined)) {
if (verticalScrollBar) verticalScrollBar.destroy()
verticalScrollBar = verticalScrollBarComponent.createObject(root)
//from normal to section
} else if (flickableItem.section && flickableItem.section.property &&
2012-10-23 12:39:47 +02:00
flickableItem.model.get !== undefined &&
(!verticalScrollBar || verticalScrollBar.orientation !== undefined)) {
if (verticalScrollBar) verticalScrollBar.destroy()
verticalScrollBar = sectionScrollerComponent.createObject(root)
}
}
checkVerticalScrollBarMargins()
}
function checkVerticalScrollBarMargins() {
//undefined in case of SectionScroller
if ((flickableItem.contentHeight > flickableItem.height) &&
((verticalScrollBar.interactive && verticalScrollBar.visible) || (verticalScrollBar.orientation === undefined &&
//FIXME: heuristic on width to distinguish the touch sectionscroller
verticalScrollBar.width < 30))) {
flickableItem.anchors.rightMargin = verticalScrollBar.width
} else {
flickableItem.anchors.rightMargin = 0
}
}
function checkHorizontalScrollBar() {
if (!flickableItem || horizontalScrollBar) {
return
}
if (flickableItem.contentWidth > flickableItem.width) {
if (!horizontalScrollBar) {
horizontalScrollBar = horizontalScrollBarComponent.createObject(root)
}
}
checkHorizontalScrollBarMargins()
}
function checkHorizontalScrollBarMargins() {
if ((flickableItem.contentWidth > flickableItem.width) &&
horizontalScrollBar.interactive && horizontalScrollBar.visible) {
flickableItem.anchors.bottomMargin = horizontalScrollBar.height
} else {
flickableItem.anchors.bottomMargin = 0
}
}
}
Component {
id: verticalScrollBarComponent
ScrollBar {
flickableItem: root.flickableItem
orientation: Qt.Vertical
property bool isScrollBar: true
2012-10-26 19:46:36 +02:00
z: root.flickableItem.z + 1
anchors {
left: undefined
2012-10-26 18:12:51 +02:00
top: parent.top
right: parent.right
2012-10-26 18:12:51 +02:00
bottom: parent.bottom
bottomMargin: parent.height - root.flickableItem.height
}
onVisibleChanged: internal.checkVerticalScrollBarMargins()
}
}
Component {
id: horizontalScrollBarComponent
ScrollBar {
flickableItem: root.flickableItem
orientation: Qt.Horizontal
2012-10-26 19:46:36 +02:00
z: root.flickableItem.z + 1
anchors {
2012-10-26 18:12:51 +02:00
left: parent.left
top: undefined
2012-10-26 18:12:51 +02:00
right: parent.right
bottom: parent.bottom
2012-10-26 18:12:51 +02:00
rightMargin: parent.width - root.flickableItem.width
}
onVisibleChanged: internal.checkHorizontalScrollBarMargins()
}
}
Component {
id: sectionScrollerComponent
SectionScroller {
listView: root.flickableItem
property bool isScrollBar: false
2012-10-26 19:46:36 +02:00
z: root.flickableItem.z + 1
anchors {
left: undefined
2012-10-26 18:12:51 +02:00
top: parent.top
right: parent.right
2012-10-26 18:12:51 +02:00
bottom: parent.bottom
bottomMargin: parent.height - root.flickableItem.height
}
onVisibleChanged: internal.checkVerticalScrollBarMargins()
}
}
2012-04-03 13:48:42 +02:00
//FIXME: create all this stuff only on demand, like scrollbars?
PlasmaCore.Svg {
id: borderSvg
imagePath: "widgets/scrollwidget"
}
PlasmaCore.SvgItem {
svg: borderSvg
z: 1000
elementId: "border-top"
width: 100
height: naturalSize.height
opacity: flickableItem.atYBeginning ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: 250
easing.type: Easing.InOutQuad
}
}
anchors {
left: parent.left
top: parent.top
right: parent.right
topMargin: flickableItem.anchors.topMargin
2012-04-03 13:48:42 +02:00
}
}
PlasmaCore.SvgItem {
svg: borderSvg
z: 1000
elementId: "border-bottom"
width: 100
height: naturalSize.height
opacity: flickableItem.atYEnd ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: 250
easing.type: Easing.InOutQuad
}
}
anchors {
left: parent.left
bottom: parent.bottom
right: parent.right
bottomMargin: flickableItem.anchors.bottomMargin
2012-04-03 13:48:42 +02:00
}
}
PlasmaCore.SvgItem {
svg: borderSvg
z: 1000
elementId: "border-left"
width: naturalSize.width
opacity: flickableItem.atXBeginning ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: 250
easing.type: Easing.InOutQuad
}
}
anchors {
left: parent.left
top: parent.top
bottom: parent.bottom
leftMargin: flickableItem.anchors.leftMargin
2012-04-03 13:48:42 +02:00
}
}
PlasmaCore.SvgItem {
svg: borderSvg
z: 1000
elementId: "border-right"
width: naturalSize.width
opacity: flickableItem.atXEnd ? 0 : 1
Behavior on opacity {
NumberAnimation {
duration: 250
easing.type: Easing.InOutQuad
}
}
anchors {
top: parent.top
bottom: parent.bottom
right: parent.right
rightMargin: flickableItem.anchors.rightMargin
2012-04-03 13:48:42 +02:00
}
}
}