From e3ea342441f36eeacad77923b21f69cf0fe7a64b Mon Sep 17 00:00:00 2001 From: Lubos Date: Sat, 28 Oct 2023 12:36:54 +0200 Subject: [PATCH] New design for Toolbar, its buttons and menu --- app/icons/Delete.svg | 5 + app/icons/Done.svg | 11 ++ app/icons/Edit.svg | 4 + app/icons/More.svg | 5 + app/icons/icons.qrc | 4 + app/qmlV2/Style.js | 12 ++ app/qmlV2/component/MMMenuDrawer.qml | 87 ++++++++++++++ app/qmlV2/component/MMToolbar.qml | 124 ++++++++++++++++++++ app/qmlV2/component/MMToolbarButton.qml | 84 +++++++++++++ app/qmlV2/component/MMToolbarLongButton.qml | 72 ++++++++++++ app/qmlV2/component/MMToolbarMenuButton.qml | 59 ++++++++++ gallery/qml.qrc | 6 + gallery/qml/Main.qml | 4 + gallery/qml/pages/ToolbarPage.qml | 55 +++++++++ 14 files changed, 532 insertions(+) create mode 100644 app/icons/Delete.svg create mode 100644 app/icons/Done.svg create mode 100644 app/icons/Edit.svg create mode 100644 app/icons/More.svg create mode 100644 app/qmlV2/component/MMMenuDrawer.qml create mode 100644 app/qmlV2/component/MMToolbar.qml create mode 100644 app/qmlV2/component/MMToolbarButton.qml create mode 100644 app/qmlV2/component/MMToolbarLongButton.qml create mode 100644 app/qmlV2/component/MMToolbarMenuButton.qml create mode 100644 gallery/qml/pages/ToolbarPage.qml diff --git a/app/icons/Delete.svg b/app/icons/Delete.svg new file mode 100644 index 000000000..ad13d3664 --- /dev/null +++ b/app/icons/Delete.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/icons/Done.svg b/app/icons/Done.svg new file mode 100644 index 000000000..16b8b2190 --- /dev/null +++ b/app/icons/Done.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/app/icons/Edit.svg b/app/icons/Edit.svg new file mode 100644 index 000000000..0bde4f126 --- /dev/null +++ b/app/icons/Edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/icons/More.svg b/app/icons/More.svg new file mode 100644 index 000000000..2829355ba --- /dev/null +++ b/app/icons/More.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/icons/icons.qrc b/app/icons/icons.qrc index 7f82ade42..dd9ebb404 100644 --- a/app/icons/icons.qrc +++ b/app/icons/icons.qrc @@ -14,5 +14,9 @@ CloseButton.svg UploadImage.svg ReachedDataLimitImage.svg + Delete.svg + Done.svg + Edit.svg + More.svg diff --git a/app/qmlV2/Style.js b/app/qmlV2/Style.js index 98c8b2567..b64bef430 100644 --- a/app/qmlV2/Style.js +++ b/app/qmlV2/Style.js @@ -70,6 +70,10 @@ const arrowDownIcon = "qrc:/Arrow Down.svg" const qrCodeIcon = "qrc:/QR Code.svg" const checkmarkIcon = "qrc:/Checkmark.svg" const closeButtonIcon = "qrc:/CloseButton.svg" +const deleteIcon = "qrc:/Delete.svg" +const doneIcon = "qrc:/Done.svg" +const editIcon = "qrc:/Edit.svg" +const moreIcon = "qrc:/More.svg" // Images const uploadImage = "qrc:/UploadImage.svg" @@ -78,6 +82,14 @@ const ReachedDataLimitImage = "qrc:/ReachedDataLimitImage.svg" // Spacing const commonSpacing = 20 * __dp +// Toolbar +const toolbarHeight = 89 * __dp +const minimumToolbarButtonWidth = 100 * __dp +const menuDrawerHeight = 67 * __dp +const toolbarLongButtonWidth = 50 * __dp +const minimumToolbarLongButtonWidth = 200 * __dp +const maximumToolbarLongButtonWidth = 500 * __dp + function dynamicText() { return "Dynamic text" } diff --git a/app/qmlV2/component/MMMenuDrawer.qml b/app/qmlV2/component/MMMenuDrawer.qml new file mode 100644 index 000000000..42a115199 --- /dev/null +++ b/app/qmlV2/component/MMMenuDrawer.qml @@ -0,0 +1,87 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import "../Style.js" as Style +import "." + +Drawer { + id: control + + property alias title: title.text + property alias model: menuView.model + + signal clicked(var button) + + width: window.width + height: mainColumn.height + edge: Qt.BottomEdge + + Rectangle { + color: roundedRect.color + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: 2 * radius + anchors.topMargin: -radius + radius: Style.commonSpacing + } + + Rectangle { + id: roundedRect + + anchors.fill: parent + color: Style.white + + Column { + id: mainColumn + + width: parent.width + spacing: Style.commonSpacing + leftPadding: Style.commonSpacing + rightPadding: Style.commonSpacing + bottomPadding: Style.commonSpacing + + Image { + id: closeButton + + source: Style.closeButtonIcon + anchors.right: parent.right + anchors.rightMargin: Style.commonSpacing + + MouseArea { + anchors.fill: parent + onClicked: control.visible = false + } + } + + Text { + id: title + + anchors.horizontalCenter: parent.horizontalCenter + font: Qt.font(Style.t1) + width: parent.width - 2*Style.commonSpacing + color: Style.forest + visible: text.length > 0 + horizontalAlignment: Text.AlignHCenter + } + + GridView { + id: menuView + + width: parent.width - 2 * Style.commonSpacing + height: model ? model.count * Style.menuDrawerHeight : 0 + cellWidth: width + cellHeight: Style.menuDrawerHeight + } + } + } +} diff --git a/app/qmlV2/component/MMToolbar.qml b/app/qmlV2/component/MMToolbar.qml new file mode 100644 index 000000000..cf72f7ac3 --- /dev/null +++ b/app/qmlV2/component/MMToolbar.qml @@ -0,0 +1,124 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import Qt5Compat.GraphicalEffects +import "../Style.js" as Style + +Rectangle { + id: control + + signal clicked + + required property var model + + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + height: Style.toolbarHeight + color: Style.forest + + onWidthChanged: setupBottomBar() + + // buttons shown inside toolbar + ObjectModel { + id: visibleButtonModel + } + + // buttons that are not shown inside toolbar, due to small space + ObjectModel { + id: invisibleButtonModel + } + + GridView { + id: buttonView + + model: visibleButtonModel + anchors.fill: parent + leftMargin: Style.commonSpacing + rightMargin: Style.commonSpacing + cellHeight: Style.toolbarHeight + } + + MMMenuDrawer { + id: menu + + title: qsTr("More Options") + model: invisibleButtonModel + onClicked: function(button) { + menu.visible = false + buttonClicked(button) + } + } + + // Button More '...' + Component { + id: componentMore + MMToolbarButton { + text: "..." + iconSource: Style.deleteIcon + onClicked: menu.visible = true + } + } + Loader { id: buttonMore; sourceComponent: componentMore; visible: false } + + function setupBottomBar() { + var m = control.model + var c = m.count + var w = control.width - 2 * Style.commonSpacing + var button + + // add all buttons (max 4) into toolbar + visibleButtonModel.clear() + if(c <= 4 || w >= c*Style.minimumToolbarButtonWidth) { + for( var i = 0; i < c; i++ ) { + button = m.get(i) + if(button.isMenuButton !== undefined) + button.isMenuButton = false + button.width = w / c + visibleButtonModel.append(button) + } + buttonView.cellWidth = w / c + } + else { + // not all buttons are visible in toolbar due to width + // the past of them will apper in the menu inside '...' button + var maxVisible = Math.floor(w/Style.minimumToolbarButtonWidth) + if(maxVisible<4) + maxVisible = 4 + for( i = 0; i < maxVisible-1; i++ ) { + if(maxVisible===4 || w >= i*Style.minimumToolbarButtonWidth) { + button = m.get(i) + button.isMenuButton = false + button.width = w / maxVisible + visibleButtonModel.append(button) + } + } + // add More '...' button + button = buttonMore + button.visible = true + button.width = maxVisible ? w / maxVisible : w + visibleButtonModel.append( button ) + buttonView.cellWidth = maxVisible ? w / maxVisible : w + + // add all other buttons inside the '...' button + invisibleButtonModel.clear() + for( i = maxVisible-1; i < c; i++ ) { + if(i<0) + continue + button = m.get(i) + button.isMenuButton = true + button.width = w + invisibleButtonModel.append(button) + } + } + } +} diff --git a/app/qmlV2/component/MMToolbarButton.qml b/app/qmlV2/component/MMToolbarButton.qml new file mode 100644 index 000000000..4b3da615d --- /dev/null +++ b/app/qmlV2/component/MMToolbarButton.qml @@ -0,0 +1,84 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import "../Style.js" as Style + +Item { + id: control + + signal clicked + + required property var iconSource + required property string text + property var type: MMToolbarButton.Button.Normal + property bool isMenuButton: false + + enum Button { Normal, Save } + + height: isMenuButton ? Style.menuDrawerHeight/2 : Style.toolbarHeight + + Rectangle { + width: parent.width - Style.commonSpacing/2 + height: parent.height - Style.commonSpacing/2 + anchors.centerIn: parent + clip: control.type !== MMToolbarButton.Button.Save + color: Style.transparent + visible: !control.isMenuButton + + Image { + id: icon + + source: control.iconSource + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 2 * Style.commonSpacing + (control.type === MMToolbarButton.Button.Save ? 14 * __dp : 0) + + Rectangle { + visible: control.type === MMToolbarButton.Button.Save + anchors.centerIn: parent + width: 56 * __dp + height: width + radius: width / 2 + color: Style.transparent + border.color: Style.grass + border.width: 14 * __dp + } + } + Text { + id: text + + text: control.text + width: parent.width + color: Style.white + font: Qt.font(Style.t4) + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: Style.commonSpacing + horizontalAlignment: Text.AlignHCenter + } + + MouseArea { + anchors.fill: parent + onClicked: control.clicked() + } + } + + // Menu button + MMToolbarMenuButton { + width: control.width + height: Style.menuDrawerHeight + visible: control.isMenuButton + iconSource: control.iconSource + text: control.text + onClicked: control.clicked() + } +} diff --git a/app/qmlV2/component/MMToolbarLongButton.qml b/app/qmlV2/component/MMToolbarLongButton.qml new file mode 100644 index 000000000..6e26ef349 --- /dev/null +++ b/app/qmlV2/component/MMToolbarLongButton.qml @@ -0,0 +1,72 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import "../Style.js" as Style + +Item { + id: control + + signal clicked + + required property var iconSource + required property string text + + height: Style.toolbarHeight + + Button { + width: { + var w = parent.width - Style.commonSpacing/2 + if(w < Style.minimumToolbarLongButtonWidth) + return Style.minimumToolbarLongButtonWidth + else if(w > Style.maximumToolbarLongButtonWidth) + return Style.maximumToolbarLongButtonWidth + return w + } + height: Style.toolbarLongButtonWidth + anchors.centerIn: parent + + contentItem: Item { + width: parent.width + anchors.centerIn: parent + + Row { + id: row + + spacing: 5 * __dp + height: parent.height + anchors.centerIn: parent + + MMIcon { + source: control.iconSource + color: text.color + } + Text { + id: text + + text: control.text + color: Style.forest + font: Qt.font(Style.t3) + verticalAlignment: Text.AlignVCenter + topPadding: 10 * __dp + bottomPadding: 10 * __dp + } + } + } + + background: Rectangle { + color: Style.grass + radius: height / 2 + } + + onClicked: control.clicked() + } +} diff --git a/app/qmlV2/component/MMToolbarMenuButton.qml b/app/qmlV2/component/MMToolbarMenuButton.qml new file mode 100644 index 000000000..1b79efa07 --- /dev/null +++ b/app/qmlV2/component/MMToolbarMenuButton.qml @@ -0,0 +1,59 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import "../Style.js" as Style + +Item { + id: control + + signal clicked + + required property var iconSource + required property string text + + Item { + id: menuButton + + width: control.width + height: Style.menuDrawerHeight + + Rectangle { + anchors.top: parent.top + width: parent.width + height: 1 * __dp + color: Style.gray + } + + Row { + height: parent.height + width: parent.width + spacing: Style.commonSpacing + MMIcon { + height: parent.height + color: Style.forest + source: control.iconSource + } + Text { + text: control.text + color: Style.forest + font: Qt.font(Style.t3) + verticalAlignment: Text.AlignVCenter + height: parent.height + } + } + + MouseArea { + anchors.fill: parent + onClicked: control.clicked() + } + } +} diff --git a/gallery/qml.qrc b/gallery/qml.qrc index 3e165441a..f655acfa8 100644 --- a/gallery/qml.qrc +++ b/gallery/qml.qrc @@ -24,5 +24,11 @@ qml/pages/ChecksPage.qml ../app/qmlV2/component/MMComponent_reachedDataLimit.qml ../app/qmlV2/component/MMProgressBar.qml + ../app/qmlV2/component/MMToolbarButton.qml + ../app/qmlV2/component/MMToolbar.qml + qml/pages/ToolbarPage.qml + ../app/qmlV2/component/MMMenuDrawer.qml + ../app/qmlV2/component/MMToolbarMenuButton.qml + ../app/qmlV2/component/MMToolbarLongButton.qml diff --git a/gallery/qml/Main.qml b/gallery/qml/Main.qml index 1859be814..cdb194f03 100644 --- a/gallery/qml/Main.qml +++ b/gallery/qml/Main.qml @@ -128,6 +128,10 @@ ApplicationWindow { title: "Drawers" source: "DrawerPage.qml" } + ListElement { + title: "Toolbars" + source: "ToolbarPage.qml" + } } ScrollIndicator.vertical: ScrollIndicator {} diff --git a/gallery/qml/pages/ToolbarPage.qml b/gallery/qml/pages/ToolbarPage.qml new file mode 100644 index 000000000..5e619adf5 --- /dev/null +++ b/gallery/qml/pages/ToolbarPage.qml @@ -0,0 +1,55 @@ +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +import QtQuick +import QtQuick.Controls + +import "../../app/qmlV2/component" +import "../../app/qmlV2/Style.js" as Style + +Page { + id: pane + + MMToolbar { + model: ObjectModel { + MMToolbarLongButton { text: "Long button"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + } + anchors.bottomMargin: 360 * __dp + } + + MMToolbar { + model: ObjectModel { + MMToolbarButton { text: "aaa"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "bbb"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + } + anchors.bottomMargin: 240 * __dp + } + + MMToolbar { + model: ObjectModel { + MMToolbarButton { text: "1/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "2/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "3/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "4/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "5/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "6/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "7/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: "8/8"; iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + } + anchors.bottomMargin: 120 * __dp + } + + MMToolbar { + model: ObjectModel { + MMToolbarButton { text: qsTr("Delete"); iconSource: Style.deleteIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: qsTr("Edit Geometry"); iconSource: Style.editIcon; onClicked: console.log("tapped "+text) } + MMToolbarButton { text: qsTr("Save"); iconSource: Style.doneIcon; type: MMToolbarButton.Button.Save; onClicked: console.log("tapped "+text) } + } + } +}