diff --git a/src/controls/swipenavigator/PrivateSwipeTab.qml b/src/controls/swipenavigator/PrivateSwipeTab.qml index ab83bcba..19be8eb1 100644 --- a/src/controls/swipenavigator/PrivateSwipeTab.qml +++ b/src/controls/swipenavigator/PrivateSwipeTab.qml @@ -1,120 +1,152 @@ /* * SPDX-FileCopyrightText: 2020 Carson Black * * SPDX-License-Identifier: LGPL-2.0-or-later */ import QtQuick 2.12 import QtQuick.Layouts 1.12 import QtQuick.Controls 2.12 import org.kde.kirigami 2.12 as Kirigami Rectangle { id: tabRoot + property bool small: false Keys.onPressed: { if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return) { columnView.currentIndex = index } } activeFocusOnTab: true + implicitHeight: small ? Kirigami.Units.gridUnit*3 : Kirigami.Units.gridUnit*2 Connections { target: columnView function onCurrentIndexChanged() { if (index == columnView.currentIndex) { swipeTabBarRoot.indexChanged(tabRoot.x) } } } Accessible.name: modelData.title Accessible.description: { if (!!modelData.progress) { if (index == columnView.currentIndex) { return i18nc("Accessibility text for a page tab. Keep the text as concise as possible and don't use a percent sign.", "Current page. Progress: %1 percent.", Math.round(modelData.progress*100)) } else { return i18nc("Accessibility text for a page tab. Keep the text as concise as possible.", "Navigate to %1. Progress: %1 percent.", modelData.title, Math.round(modelData.progress*100)) } } else { if (index == columnView.currentIndex) { return i18nc("Accessibility text for a page tab. Keep the text as concise as possible.", "Current page.") } else if (modelData.needsAttention) { return i18nc("Accessibility text for a page tab that's requesting the user's attention. Keep the text as concise as possible.", "Navigate to %1. Demanding attention.", modelData.title) } else { return i18nc("Accessibility text for a page tab that's requesting the user's attention. Keep the text as concise as possible.", "Navigate to %1.", modelData.title) } } } Accessible.role: Accessible.PageTab Accessible.focusable: true Accessible.onPressAction: columnView.currentIndex = index - implicitWidth: largeTitleRow.implicitWidth + implicitWidth: small ? smallTitleRow.implicitWidth : largeTitleRow.implicitWidth border { width: activeFocus ? 2 : 0 color: Kirigami.Theme.textColor } color: { if (index == columnView.currentIndex) { return Kirigami.ColorUtils.adjustColor(Kirigami.Theme.activeTextColor, {"alpha": 0.2*255}) } else if (modelData.needsAttention) { return Kirigami.ColorUtils.adjustColor(Kirigami.Theme.negativeTextColor, {"alpha": 0.2*255}) } else { return "transparent" } } PrivateSwipeHighlight { states: [ State { name: "highlighted"; when: index == columnView.currentIndex }, State { name: "requestingAttention"; when: modelData.needsAttention } ] } PrivateSwipeProgress { anchors.fill: parent visible: modelData.progress != undefined progress: modelData.progress } + RowLayout { + id: smallTitleRow + anchors.fill: parent + Accessible.ignored: true + visible: small + + ColumnLayout { + Layout.margins: Kirigami.Units.largeSpacing + Layout.alignment: Qt.AlignVCenter + + Kirigami.Icon { + visible: !!modelData.icon.name + source: modelData.icon.name + + Layout.preferredHeight: Kirigami.Units.iconSizes.small + Layout.preferredWidth: Layout.preferredHeight + + Layout.alignment: (Qt.AlignHCenter | Qt.AlignBottom) + } + Kirigami.Heading { + level: 5 + text: modelData.title + + Layout.fillWidth: true + Layout.alignment: (Qt.AlignLeft | Qt.AlignVCenter) + } + } + } + RowLayout { id: largeTitleRow anchors.fill: parent Accessible.ignored: true + visible: !small RowLayout { Layout.margins: Kirigami.Units.largeSpacing Layout.alignment: Qt.AlignVCenter Kirigami.Icon { visible: !!modelData.icon.name source: modelData.icon.name Layout.preferredHeight: Kirigami.Units.iconSizes.small Layout.preferredWidth: Layout.preferredHeight Layout.alignment: (Qt.AlignLeft | Qt.AlignVCenter) } Kirigami.Heading { level: 2 text: modelData.title Layout.fillWidth: true Layout.alignment: (Qt.AlignLeft | Qt.AlignVCenter) } } } MouseArea { id: mouse anchors.fill: parent Accessible.ignored: true onClicked: { columnView.currentIndex = index } } Layout.fillHeight: true Layout.alignment: Qt.AlignHCenter } \ No newline at end of file diff --git a/src/controls/swipenavigator/PrivateSwipeTabBar.qml b/src/controls/swipenavigator/PrivateSwipeTabBar.qml index 9649b721..84f35156 100644 --- a/src/controls/swipenavigator/PrivateSwipeTabBar.qml +++ b/src/controls/swipenavigator/PrivateSwipeTabBar.qml @@ -1,25 +1,36 @@ /* * SPDX-FileCopyrightText: 2020 Carson Black * * SPDX-License-Identifier: LGPL-2.0-or-later */ import QtQuick 2.12 import QtQuick.Layouts 1.12 import QtQuick.Controls 2.12 import org.kde.kirigami 2.12 as Kirigami RowLayout { id: swipeTabBarRoot property bool small: false spacing: 0 signal indexChanged(real xPos) + property Item layouter: Item { + Row { + id: expandedLayouter + Repeater { + model: swipeNavigatorRoot.pages + delegate: PrivateSwipeTab { small: false } + } + } + } + Repeater { model: swipeNavigatorRoot.pages delegate: PrivateSwipeTab { Layout.fillHeight: true + small: expandedLayouter.width > swipeNavigatorRoot.width } } } diff --git a/src/controls/swipenavigator/SwipeNavigator.qml b/src/controls/swipenavigator/SwipeNavigator.qml index 1bd0648d..fa67595c 100644 --- a/src/controls/swipenavigator/SwipeNavigator.qml +++ b/src/controls/swipenavigator/SwipeNavigator.qml @@ -1,94 +1,143 @@ /* * SPDX-FileCopyrightText: 2020 Carson Black * * SPDX-License-Identifier: LGPL-2.0-or-later */ import QtQuick 2.12 import QtQuick.Layouts 1.12 import QtQuick.Controls 2.12 import org.kde.kirigami 2.13 as Kirigami /** * SwipeNavigator is a control providing for lateral navigation. * * @include swipenavigator/main.qml */ GridLayout { id: swipeNavigatorRoot rowSpacing: 0 columns: 1 /** * pages: list * * A list of pages to swipe between. */ default property list pages /** * type: int * * What type of SwipeNavigator this is. * * `Kirigami.SwipeNavigatorType.Top`: this SwipeNavigator presents its UI as a top bar. * * `Kirigami.SwipeNavigatorType.Left`: this SwipeNavigator presents its UI as a sidebar or drawer depending on available width. */ property int type: Kirigami.SwipeNavigatorType.Top /** * layers: StackView * * The StackView holding the core item, allowing users of a SwipeNavigator * in order to push pages on top of the SwipeNavigator. */ property alias layers: stackView + /** + * header: Item + * + * The item that will be displayed before the tabs. + */ + property Item header: Item {visible: false} + onHeaderChanged: { + header.parent = _grid + header.Layout.alignment = Qt.AlignLeft | Qt.AlignVcenter + } + + /** + * footer: Item + * + * The item that will be displayed after the tabs. + */ + property Item footer: Item {visible: false} + onFooterChanged: { + footer.parent = _grid + footer.Layout.alignment = Qt.AlignLeft | Qt.AlignVcenter + } + + Item { + visible: false + id: layouter + property bool tall: (swipeNavigatorRoot.header.width + __main.width + swipeNavigatorRoot.footer.width) > swipeNavigatorRoot.width + states: [ + State { + name: "small" + when: !layouter.tall + PropertyChanges { target: swipeNavigatorRoot.header; Layout.row: 0; Layout.column: 0} + PropertyChanges { target: __main; Layout.row: 0; Layout.column: 1} + PropertyChanges { target: swipeNavigatorRoot.footer; Layout.row: 0; Layout.column: 2} + }, + State { + name: "tall" + when: layouter.tall + PropertyChanges { target: swipeNavigatorRoot.header; Layout.row: 0; Layout.column: 0} + PropertyChanges { target: __main; Layout.row: 1; Layout.column: 0; Layout.columnSpan: 3} + PropertyChanges { target: swipeNavigatorRoot.footer; Layout.row: 0; Layout.column: 2} + PropertyChanges { target: _spacer; Layout.row: 0; Layout.column: 1; Layout.fillWidth: true; visible: true } + } + ] + } + ToolBar { id: topToolBar padding: 0 bottomPadding: 1 position: Kirigami.Settings.isMobile ? ToolBar.Footer : ToolBar.Header Layout.row: Kirigami.Settings.isMobile ? 1 : 0 - ColumnLayout { - id: __column - spacing: 0 + GridLayout { + id: _grid + + rowSpacing: 0 + columnSpacing: 0 anchors.fill: parent - RowLayout { - PrivateSwipeTabBar { - id: __main - Layout.fillWidth: true - Layout.fillHeight: true - } - Item { Layout.fillWidth: true } + rows: 2 + columns: 3 + + Item { id: _spacer; visible: false } + PrivateSwipeTabBar { + id: __main + Layout.fillWidth: true + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter } } Layout.fillWidth: true Accessible.role: Accessible.PageTabList } StackView { id: stackView Layout.fillWidth: true Layout.fillHeight: true Layout.row: Kirigami.Settings.isMobile ? 0 : 1 Kirigami.ColumnView { id: columnView columnResizeMode: Kirigami.ColumnView.SingleColumn contentChildren: swipeNavigatorRoot.pages anchors.fill: parent Component.onCompleted: { columnView.currentIndex = 0 } } } }