From 9c600c5d68e767bf72d26396042024a4c6f23133 Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Mon, 3 Mar 2014 19:43:13 +0100 Subject: [PATCH] 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 --- .../plasmacomponents/qml/TabBar.qml | 134 +++++++++++++----- .../plasmacomponents/qml/TabButton.qml | 51 +++---- .../qml/private/TabBarLayout.qml | 51 +++++-- 3 files changed, 160 insertions(+), 76 deletions(-) diff --git a/src/declarativeimports/plasmacomponents/qml/TabBar.qml b/src/declarativeimports/plasmacomponents/qml/TabBar.qml index 71dfebcd8..ff4fa45fe 100644 --- a/src/declarativeimports/plasmacomponents/qml/TabBar.qml +++ b/src/declarativeimports/plasmacomponents/qml/TabBar.qml @@ -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); + } + } } } } diff --git a/src/declarativeimports/plasmacomponents/qml/TabButton.qml b/src/declarativeimports/plasmacomponents/qml/TabButton.qml index 1618815bd..46b64d87e 100644 --- a/src/declarativeimports/plasmacomponents/qml/TabButton.qml +++ b/src/declarativeimports/plasmacomponents/qml/TabButton.qml @@ -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 } } diff --git a/src/declarativeimports/plasmacomponents/qml/private/TabBarLayout.qml b/src/declarativeimports/plasmacomponents/qml/private/TabBarLayout.qml index 238bbfcd2..3823e3144 100644 --- a/src/declarativeimports/plasmacomponents/qml/private/TabBarLayout.qml +++ b/src/declarativeimports/plasmacomponents/qml/private/TabBarLayout.qml @@ -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)) + } } } }