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.Layouts 1.1
import org.kde.plasma.core 2.0 as PlasmaCore
import "private" as Private
@ -68,6 +69,16 @@ FocusScope {
*/
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
implicitHeight: layout.implicitHeight + backgroundFrame.margins.top + backgroundFrame.margins.bottom
@ -84,17 +95,19 @@ FocusScope {
anchors {
fill: parent
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
PlasmaCore.FrameSvgItem {
id: buttonFrame
visible: currentTab !== null
x: tabBarLayout.x + currentTab.x + backgroundFrame.margins.left -1
y: backgroundFrame.margins.top
width: currentTab.width + margins.left + margins.right -1
height: currentTab.height + margins.top + margins.bottom
x: layout.isHorizontal ? tabBarLayout.x + currentTab.x : 0
y: layout.isHorizontal ? 0 : tabBarLayout.y + currentTab.y
width: layout.isHorizontal ? currentTab.width + margins.left + margins.right -1 : parent.width
height: layout.isHorizontal ? parent.height : currentTab.height + margins.top + margins.bottom
imagePath: "widgets/button"
prefix: "normal"
Behavior on x {
@ -103,6 +116,12 @@ FocusScope {
duration: units.longDuration
}
}
Behavior on y {
PropertyAnimation {
easing.type: Easing.InQuad
duration: units.longDuration
}
}
}
}
@ -112,91 +131,132 @@ FocusScope {
}
PlasmaCore.SvgItem {
svg: scrollWidgetSvg
elementId: "border-left"
elementId: layout.isHorizontal ? "border-left" : "border-top"
width: naturalSize.width
height: naturalSize.height
visible: buttonsLayout.visible
anchors {
margins: -1
left: buttonCutter.left
leftMargin: -1
right: layout.isHorizontal ? undefined : buttonCutter.right
top: buttonCutter.top
bottom: buttonCutter.bottom
topMargin: backgroundFrame.margins.top
bottomMargin: backgroundFrame.margins.bottom
bottom: layout.isHorizontal ? buttonCutter.bottom : undefined
}
}
PlasmaCore.SvgItem {
svg: scrollWidgetSvg
elementId: "border-right"
elementId: layout.isHorizontal ? "border-right" : "border-bottom"
width: naturalSize.width
height: naturalSize.height
visible: buttonsLayout.visible
anchors {
margins: -1
left: layout.isHorizontal ? undefined : buttonCutter.left
right: buttonCutter.right
rightMargin: -1
top: buttonCutter.top
top: layout.isHorizontal ? buttonCutter.top : undefined
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: {
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 {
id: tabbarScroller
clip: true
anchors {
fill: parent
leftMargin: backgroundFrame.margins.left + buttonFrame.margins.left
topMargin: backgroundFrame.margins.top + buttonFrame.margins.top
rightMargin: backgroundFrame.margins.right + (buttonsLayout.visible ? buttonsLayout.width : buttonFrame.margins.right)
bottomMargin: backgroundFrame.margins.bottom + buttonFrame.margins.bottom
leftMargin: buttonFrame.margins.left
topMargin: buttonFrame.margins.top
rightMargin: buttonsLayout.visible && layout.isHorizontal ? buttonsLayout.width : buttonFrame.margins.right
bottomMargin: buttonsLayout.visible && !layout.isHorizontal ? buttonsLayout.height : buttonFrame.margins.bottom
}
Private.TabBarLayout {
id: tabBarLayout
//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 {
top: parent.top
bottom: parent.bottom
top: layout.isHorizontal ? parent.top : undefined
bottom: layout.isHorizontal ? parent.bottom : undefined
left: !layout.isHorizontal ? parent.left : undefined
right: !layout.isHorizontal ? parent.right : undefined
}
Behavior on x {
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
Behavior on y {
NumberAnimation {
duration: units.longDuration
easing.type: Easing.InOutQuad
}
}
}
}
Row {
GridLayout {
id: buttonsLayout
visible: tabBarLayout.width > root.width - backgroundFrame.margins.left - backgroundFrame.margins.right
height: Math.min(parent.height, units.iconSizes.medium)
rows: 1
columns: 1
flow: layout.isHorizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight
visible: layout.isHorizontal ? tabBarLayout.width > root.width : tabBarLayout.height > root.height
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
right: layout.isHorizontal ? parent.right : undefined
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)
bottomMargin: Math.min(y, backgroundFrame.margins.bottom)
}
ToolButton {
height: parent.height
height: Math.min(parent.height, parent.width)
width: height
iconSource: "go-previous"
enabled: tabBarLayout.x < 0
onClicked: tabBarLayout.x = Math.min(0, tabBarLayout.x + tabBarLayout.width/tabBarLayout.children.length)
iconSource: layout.isHorizontal ? "go-previous" : "go-up"
enabled: layout.isHorizontal ? tabBarLayout.x < 0 : tabBarLayout.y < 0
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 {
height: parent.height
height: Math.min(parent.height, parent.width)
width: height
iconSource: "go-next"
enabled: tabBarLayout.x > -tabBarLayout.width + tabbarScroller.width
onClicked: tabBarLayout.x = Math.max(-tabBarLayout.width + tabbarScroller.width, tabBarLayout.x - tabBarLayout.width/tabBarLayout.children.length)
iconSource: layout.isHorizontal ? "go-next" : "go-down"
enabled: layout.isHorizontal ? tabBarLayout.x > -tabBarLayout.width + tabbarScroller.width : tabBarLayout.y > -tabBarLayout.height + tabbarScroller.height
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.Layouts 1.1
import "private/AppManager.js" as Utils
import org.kde.plasma.core 2.0 as PlasmaCore
@ -86,8 +87,8 @@ Item {
*/
signal clicked
implicitWidth: label.implicitWidth + (internal.portrait ? 0 : (iconSource != null ? 16 : 0))
implicitHeight: label.implicitHeight + (internal.portrait ? (iconSource != null ? 16 : 0) : 0)
implicitWidth: Math.max(label.implicitWidth + (internal.portrait ? 0 : (iconSource != null ? units.iconSizes.small : 0)), height)
implicitHeight: label.implicitHeight + (internal.portrait ? (iconSource != null ? units.iconSizes.small : 0) : 0)
opacity: enabled ? 1 : 0.6
//long notation to not make it overwritten by implementations
@ -113,7 +114,7 @@ Item {
property Item tabBar: Utils.findParent(root, "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() {
root.clicked()
@ -129,36 +130,36 @@ Item {
}
}
Label {
id: label
GridLayout {
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
horizontalAlignment: !internal.portrait && iconSource != null ? Text.AlignLeft : Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
Label {
id: label
color: root.checked ? theme.buttonTextColor : theme.textColor
}
objectName: "label"
PlasmaCore.IconItem {
id: imageLoader
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
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)
implicitHeight: implicitWidth
elide: Text.ElideRight
horizontalAlignment: !internal.portrait && iconSource != null ? Text.AlignLeft : Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors {
left: internal.portrait ? undefined : parent.left
horizontalCenter: internal.portrait ? parent.horizontalCenter : undefined
verticalCenter: internal.portrait ? undefined : parent.verticalCenter
color: root.checked ? theme.buttonTextColor : theme.textColor
}
}

View File

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