add a new property in TabBar: tabPosition

it makes the tabbar eventually vertical and appearing oriented differently towards the content

possible values:
Qt.TopEdge (default)
Qt.LeftEdge
Qt.RightEdge
Qt.BottomEdge
This commit is contained in:
Marco Martin 2014-03-03 19:43:13 +01:00
parent 4f784339b6
commit 9c600c5d68
3 changed files with 160 additions and 76 deletions

View File

@ -41,6 +41,7 @@
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.1
import QtQuick.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import "private" as Private import "private" as Private
@ -68,6 +69,16 @@ FocusScope {
*/ */
property Item currentTab property Item currentTab
/**
* The position of the tabs regarding the contents.
* possibilities:
* Qt.TopEdge (default)
* Qt.LeftEdge
* Qt.RightEdge
* Qt.BottomEdge
*/
property alias tabPosition: tabBarLayout.tabPosition
implicitWidth: layout.implicitWidth + backgroundFrame.margins.left + backgroundFrame.margins.right implicitWidth: layout.implicitWidth + backgroundFrame.margins.left + backgroundFrame.margins.right
implicitHeight: layout.implicitHeight + backgroundFrame.margins.top + backgroundFrame.margins.bottom implicitHeight: layout.implicitHeight + backgroundFrame.margins.top + backgroundFrame.margins.bottom
@ -84,17 +95,19 @@ FocusScope {
anchors { anchors {
fill: parent fill: parent
leftMargin: 1 leftMargin: 1
rightMargin: (buttonsLayout.visible ? buttonsLayout.width : 0) + 1 topMargin: 1
rightMargin: (buttonsLayout.visible && layout.isHorizontal? buttonsLayout.width : 0) + 1
bottomMargin: (buttonsLayout.visible && !layout.isHorizontal? buttonsLayout.height : 0) + 1
} }
clip: true clip: true
PlasmaCore.FrameSvgItem { PlasmaCore.FrameSvgItem {
id: buttonFrame id: buttonFrame
visible: currentTab !== null visible: currentTab !== null
x: tabBarLayout.x + currentTab.x + backgroundFrame.margins.left -1 x: layout.isHorizontal ? tabBarLayout.x + currentTab.x : 0
y: backgroundFrame.margins.top y: layout.isHorizontal ? 0 : tabBarLayout.y + currentTab.y
width: currentTab.width + margins.left + margins.right -1 width: layout.isHorizontal ? currentTab.width + margins.left + margins.right -1 : parent.width
height: currentTab.height + margins.top + margins.bottom height: layout.isHorizontal ? parent.height : currentTab.height + margins.top + margins.bottom
imagePath: "widgets/button" imagePath: "widgets/button"
prefix: "normal" prefix: "normal"
Behavior on x { Behavior on x {
@ -103,6 +116,12 @@ FocusScope {
duration: units.longDuration duration: units.longDuration
} }
} }
Behavior on y {
PropertyAnimation {
easing.type: Easing.InQuad
duration: units.longDuration
}
}
} }
} }
@ -112,91 +131,132 @@ FocusScope {
} }
PlasmaCore.SvgItem { PlasmaCore.SvgItem {
svg: scrollWidgetSvg svg: scrollWidgetSvg
elementId: "border-left" elementId: layout.isHorizontal ? "border-left" : "border-top"
width: naturalSize.width width: naturalSize.width
height: naturalSize.height
visible: buttonsLayout.visible visible: buttonsLayout.visible
anchors { anchors {
margins: -1
left: buttonCutter.left left: buttonCutter.left
leftMargin: -1 right: layout.isHorizontal ? undefined : buttonCutter.right
top: buttonCutter.top top: buttonCutter.top
bottom: buttonCutter.bottom bottom: layout.isHorizontal ? buttonCutter.bottom : undefined
topMargin: backgroundFrame.margins.top
bottomMargin: backgroundFrame.margins.bottom
} }
} }
PlasmaCore.SvgItem { PlasmaCore.SvgItem {
svg: scrollWidgetSvg svg: scrollWidgetSvg
elementId: "border-right" elementId: layout.isHorizontal ? "border-right" : "border-bottom"
width: naturalSize.width width: naturalSize.width
height: naturalSize.height
visible: buttonsLayout.visible visible: buttonsLayout.visible
anchors { anchors {
margins: -1
left: layout.isHorizontal ? undefined : buttonCutter.left
right: buttonCutter.right right: buttonCutter.right
rightMargin: -1 top: layout.isHorizontal ? buttonCutter.top : undefined
top: buttonCutter.top
bottom: buttonCutter.bottom bottom: buttonCutter.bottom
topMargin: backgroundFrame.margins.top
bottomMargin: backgroundFrame.margins.bottom
} }
} }
onCurrentTabChanged: tabBarLayout.x = Math.max(Math.min(0, -(currentTab.x + currentTab.width/2) + tabbarScroller.width/2), -tabBarLayout.width + tabbarScroller.width) onCurrentTabChanged: {
if (layout.isHorizontal) {
tabBarLayout.x = Math.max(Math.min(0, -(currentTab.x + currentTab.width/2) + tabbarScroller.width/2), -tabBarLayout.width + tabbarScroller.width);
} else {
tabBarLayout.y = Math.max(Math.min(0, -(currentTab.y + currentTab.height/2) + tabbarScroller.height/2), -tabBarLayout.height + tabbarScroller.height);
}
}
onWidthChanged: { onWidthChanged: {
if (currentTab) { if (currentTab) {
tabBarLayout.x = Math.max(Math.min(0, -(currentTab.x + currentTab.width/2) + tabbarScroller.width/2), -tabBarLayout.width + tabbarScroller.width) if (layout.isHorizontal) {
tabBarLayout.x = Math.max(Math.min(0, -(currentTab.x + currentTab.width/2) + tabbarScroller.width/2), -tabBarLayout.width + tabbarScroller.width);
} else {
tabBarLayout.y = Math.max(Math.min(0, -(currentTab.y + currentTab.height/2) + tabbarScroller.height/2), -tabBarLayout.height + tabbarScroller.height);
}
} }
} }
Item { Item {
id: tabbarScroller id: tabbarScroller
clip: true clip: true
anchors { anchors {
fill: parent fill: parent
leftMargin: backgroundFrame.margins.left + buttonFrame.margins.left leftMargin: buttonFrame.margins.left
topMargin: backgroundFrame.margins.top + buttonFrame.margins.top topMargin: buttonFrame.margins.top
rightMargin: backgroundFrame.margins.right + (buttonsLayout.visible ? buttonsLayout.width : buttonFrame.margins.right) rightMargin: buttonsLayout.visible && layout.isHorizontal ? buttonsLayout.width : buttonFrame.margins.right
bottomMargin: backgroundFrame.margins.bottom + buttonFrame.margins.bottom bottomMargin: buttonsLayout.visible && !layout.isHorizontal ? buttonsLayout.height : buttonFrame.margins.bottom
} }
Private.TabBarLayout { Private.TabBarLayout {
id: tabBarLayout id: tabBarLayout
//A bit of snap before scrolling the layout //A bit of snap before scrolling the layout
width: (implicitWidth - parent.width < theme.mSize(theme.defaultFont).width*4) ? parent.width : implicitWidth width: layout.isHorizontal ? ((implicitWidth - parent.width < theme.mSize(theme.defaultFont).width*4) ? parent.width : implicitWidth) : root.width;
height: !layout.isHorizontal ? ((implicitHeight - parent.height < theme.mSize(theme.defaultFont).width*4) ? parent.height : implicitHeight) : root.height
anchors { anchors {
top: parent.top top: layout.isHorizontal ? parent.top : undefined
bottom: parent.bottom bottom: layout.isHorizontal ? parent.bottom : undefined
left: !layout.isHorizontal ? parent.left : undefined
right: !layout.isHorizontal ? parent.right : undefined
} }
Behavior on x { Behavior on x {
NumberAnimation { NumberAnimation {
duration: units.longDuration duration: units.longDuration
easing.type: Easing.InOutQuad easing.type: Easing.InOutQuad
} }
} }
Behavior on y {
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
} }
} }
Row { GridLayout {
id: buttonsLayout id: buttonsLayout
visible: tabBarLayout.width > root.width - backgroundFrame.margins.left - backgroundFrame.margins.right rows: 1
height: Math.min(parent.height, units.iconSizes.medium) columns: 1
flow: layout.isHorizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight
visible: layout.isHorizontal ? tabBarLayout.width > root.width : tabBarLayout.height > root.height
anchors { anchors {
right: parent.right right: layout.isHorizontal ? parent.right : undefined
verticalCenter: parent.verticalCenter verticalCenter: layout.isHorizontal ? parent.verticalCenter : undefined
bottom: !layout.isHorizontal ? parent.bottom : undefined
horizontalCenter: !layout.isHorizontal ? parent.horizontalCenter : undefined
rightMargin: Math.min(y, backgroundFrame.margins.right) rightMargin: Math.min(y, backgroundFrame.margins.right)
bottomMargin: Math.min(y, backgroundFrame.margins.bottom)
} }
ToolButton { ToolButton {
height: parent.height height: Math.min(parent.height, parent.width)
width: height width: height
iconSource: "go-previous" iconSource: layout.isHorizontal ? "go-previous" : "go-up"
enabled: tabBarLayout.x < 0 enabled: layout.isHorizontal ? tabBarLayout.x < 0 : tabBarLayout.y < 0
onClicked: tabBarLayout.x = Math.min(0, tabBarLayout.x + tabBarLayout.width/tabBarLayout.children.length) onClicked: {
if (layout.isHorizontal) {
tabBarLayout.x = Math.min(0, tabBarLayout.x + tabBarLayout.width/tabBarLayout.children.length);
} else {
tabBarLayout.y = Math.min(0, tabBarLayout.y + tabBarLayout.height/tabBarLayout.children.length);
}
}
} }
ToolButton { ToolButton {
height: parent.height height: Math.min(parent.height, parent.width)
width: height width: height
iconSource: "go-next" iconSource: layout.isHorizontal ? "go-next" : "go-down"
enabled: tabBarLayout.x > -tabBarLayout.width + tabbarScroller.width enabled: layout.isHorizontal ? tabBarLayout.x > -tabBarLayout.width + tabbarScroller.width : tabBarLayout.y > -tabBarLayout.height + tabbarScroller.height
onClicked: tabBarLayout.x = Math.max(-tabBarLayout.width + tabbarScroller.width, tabBarLayout.x - tabBarLayout.width/tabBarLayout.children.length) onClicked: {
if (layout.isHorizontal) {
tabBarLayout.x = Math.max(-tabBarLayout.width + tabbarScroller.width, tabBarLayout.x - tabBarLayout.width/tabBarLayout.children.length);
} else {
tabBarLayout.y = Math.max(-tabBarLayout.height + tabbarScroller.height, tabBarLayout.y - tabBarLayout.height/tabBarLayout.children.length);
}
}
} }
} }
} }

View File

@ -41,6 +41,7 @@
****************************************************************************/ ****************************************************************************/
import QtQuick 2.1 import QtQuick 2.1
import QtQuick.Layouts 1.1
import "private/AppManager.js" as Utils import "private/AppManager.js" as Utils
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
@ -86,8 +87,8 @@ Item {
*/ */
signal clicked signal clicked
implicitWidth: label.implicitWidth + (internal.portrait ? 0 : (iconSource != null ? 16 : 0)) implicitWidth: Math.max(label.implicitWidth + (internal.portrait ? 0 : (iconSource != null ? units.iconSizes.small : 0)), height)
implicitHeight: label.implicitHeight + (internal.portrait ? (iconSource != null ? 16 : 0) : 0) implicitHeight: label.implicitHeight + (internal.portrait ? (iconSource != null ? units.iconSizes.small : 0) : 0)
opacity: enabled ? 1 : 0.6 opacity: enabled ? 1 : 0.6
//long notation to not make it overwritten by implementations //long notation to not make it overwritten by implementations
@ -113,7 +114,7 @@ Item {
property Item tabBar: Utils.findParent(root, "currentTab") property Item tabBar: Utils.findParent(root, "currentTab")
property Item tabGroup: Utils.findParent(tab, "currentTab") property Item tabGroup: Utils.findParent(tab, "currentTab")
property bool portrait: (root != undefined) && (label != undefined) && root.height >= label.paintedHeight + 16 property bool portrait: (root != undefined) && (label != undefined) && root.height >= label.paintedHeight + units.iconSizes.small
function click() { function click() {
root.clicked() root.clicked()
@ -129,36 +130,36 @@ Item {
} }
} }
Label { GridLayout {
id: label anchors.fill: parent
rows: 1
columns: 1
flow: internal.portrait ? GridLayout.LeftToRight : GridLayout.TopToBottom
objectName: "label" PlasmaCore.IconItem {
id: imageLoader
visible: iconSource != null
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
implicitWidth: 16//internal.portrait ? Math.max(units.iconSizes.small, root.height - (label.text ? label.height : 0)) : Math.max(units.iconSizes.small, root.height)
implicitHeight: implicitWidth
anchors {
top: internal.portrait && iconSource != null ? imageLoader.bottom : parent.top
left: internal.portrait || iconSource == null ? parent.left : imageLoader.right
leftMargin: iconSource == null ? 0 : theme.mSize(theme.defaultFont).width
right: parent.right
bottom: parent.bottom
} }
elide: Text.ElideRight Label {
horizontalAlignment: !internal.portrait && iconSource != null ? Text.AlignLeft : Text.AlignHCenter id: label
verticalAlignment: Text.AlignVCenter
color: root.checked ? theme.buttonTextColor : theme.textColor objectName: "label"
}
PlasmaCore.IconItem { Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
id: imageLoader Layout.preferredWidth: internal.portrait ? root.width : implicitWidth
Layout.preferredHeight: internal.portrait ? implicitHeight : root.height
implicitWidth: internal.portrait ? Math.max(units.iconSizes.small, root.height - (label.text ? label.height : 0)) : Math.max(units.iconSizes.small, root.height) elide: Text.ElideRight
implicitHeight: implicitWidth horizontalAlignment: !internal.portrait && iconSource != null ? Text.AlignLeft : Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors { color: root.checked ? theme.buttonTextColor : theme.textColor
left: internal.portrait ? undefined : parent.left
horizontalCenter: internal.portrait ? parent.horizontalCenter : undefined
verticalCenter: internal.portrait ? undefined : parent.verticalCenter
} }
} }

View File

@ -61,6 +61,10 @@ import "AppManager.js" as Utils
Item { Item {
id: root id: root
property int tabPosition: Qt.TopEdge
property bool isHorizontal: (tabPosition != Qt.LeftEdge && tabPosition != Qt.RightEdge)
Component.onCompleted: priv.layoutChildren() Component.onCompleted: priv.layoutChildren()
onChildrenChanged: priv.layoutChildren() onChildrenChanged: priv.layoutChildren()
onWidthChanged: priv.layoutChildren() onWidthChanged: priv.layoutChildren()
@ -69,7 +73,6 @@ Item {
Keys.onPressed: { Keys.onPressed: {
if (event.key == Qt.Key_Right || event.key == Qt.Key_Left) { if (event.key == Qt.Key_Right || event.key == Qt.Key_Left) {
if (event.key == Qt.Key_Right || priv.mirrored) { if (event.key == Qt.Key_Right || priv.mirrored) {
priv.goNextTab() priv.goNextTab()
event.accepted = true event.accepted = true
@ -164,9 +167,9 @@ Item {
priv.tabBar = Utils.findParent(root, "currentTab") priv.tabBar = Utils.findParent(root, "currentTab")
var childCount = root.children.length var childCount = root.children.length
var visibleChildCount = childCount var visibleChildCount = childCount
var contentWidth = 0 var contentWidth = theme.mSize(theme.defaultFont).width * 3
var contentHeight = 0 var contentHeight = theme.mSize(theme.defaultFont).height * 2
var maxChildWidth = 0 var maxChildSize = 0
if (childCount != 0) { if (childCount != 0) {
//not too much efficient but the loop over children needs to be done two times to get the proper child width //not too much efficient but the loop over children needs to be done two times to get the proper child width
for (var i = 0; i < childCount; ++i) { for (var i = 0; i < childCount; ++i) {
@ -175,8 +178,9 @@ Item {
} }
} }
var maxAllowedWidth = theme.mSize(theme.defaultFont).width * 14 var maxAllowedSize = theme.mSize(theme.defaultFont).width * 14
var itemWidth = (root.width - (visibleChildCount-1)*10) / visibleChildCount var itemWidth = (root.width - (visibleChildCount-1)*10) / visibleChildCount
var itemHeight = (root.height - (visibleChildCount-1)*10) / visibleChildCount
var itemIndex = mirrored ? childCount - 1 : 0 var itemIndex = mirrored ? childCount - 1 : 0
var increment = mirrored ? - 1 : 1 var increment = mirrored ? - 1 : 1
@ -188,16 +192,35 @@ Item {
continue continue
} }
child.x = visibleIndex * itemWidth + visibleIndex*10 //Vertical
++visibleIndex if (!root.isHorizontal) {
child.y = 0 child.x = 0
child.width = itemWidth child.y = visibleIndex * itemHeight + visibleIndex*10
child.height = root.height ++visibleIndex
child.width = root.width
child.height = itemHeight
if (child.implicitWidth != undefined) { if (child.implicitHeight != undefined) {
maxChildWidth = Math.max(maxChildWidth, Math.min(maxAllowedWidth, child.implicitWidth)) maxChildSize = Math.max(maxChildSize, Math.min(maxAllowedSize, child.implicitHeight));
contentWidth = Math.max(contentWidth, (maxChildWidth + buttonFrame.margins.left + buttonFrame.margins.right) * childCount)
contentHeight = Math.max(contentHeight, (child.implicitHeight + buttonFrame.margins.top + buttonFrame.margins.bottom)) contentWidth = Math.max(contentWidth, (child.implicitWidth + buttonFrame.margins.left + buttonFrame.margins.right));
contentHeight = Math.max(contentHeight, (maxChildSize + buttonFrame.margins.top + buttonFrame.margins.bottom) * childCount);
}
//Horizontal
} else {
child.x = visibleIndex * itemWidth + visibleIndex*10
++visibleIndex
child.y = 0
child.width = itemWidth
child.height = root.height
if (child.implicitWidth != undefined) {
maxChildSize = Math.max(maxChildSize, Math.min(maxAllowedSize, child.implicitWidth))
contentWidth = Math.max(contentWidth, (maxChildSize + buttonFrame.margins.left + buttonFrame.margins.right) * childCount)
contentHeight = Math.max(contentHeight, (child.implicitHeight + buttonFrame.margins.top + buttonFrame.margins.bottom))
}
} }
} }
} }