diff --git a/sandbox/Buttons.qml b/sandbox/Buttons.qml new file mode 100644 index 00000000..f1a261a3 --- /dev/null +++ b/sandbox/Buttons.qml @@ -0,0 +1,239 @@ +import QtQuick 2.14 +import QtQuick.Layouts 1.14 + +import StatusQ.Controls 0.1 +import StatusQ.Core.Theme 0.1 + +Grid { + + columns: 3 + columnSpacing: 38 + rowSpacing: 10 + + horizontalItemAlignment: Grid.AlignHCenter + + // Large + StatusButton { + text: "Button" + } + + StatusButton { + text: "Button" + enabled: false + } + + StatusButton { + text: "Button" + loading: true + } + + StatusButton { + text: "Button" + type: StatusBaseButton.Type.Danger + } + + StatusButton { + text: "Button" + type: StatusBaseButton.Type.Danger + enabled: false + } + + StatusButton { + text: "Button" + loading: true + type: StatusBaseButton.Type.Danger + } + + StatusFlatButton { + text: "Button" + } + + StatusFlatButton { + text: "Button" + enabled: false + + } + + StatusFlatButton { + text: "Button" + loading: true + } + + StatusFlatButton { + text: "Button" + type: StatusBaseButton.Type.Danger + } + + StatusFlatButton { + text: "Button" + type: StatusBaseButton.Type.Danger + enabled: false + } + + StatusFlatButton { + text: "Button" + type: StatusBaseButton.Type.Danger + loading: true + } + + // Small + StatusButton { + text: "Button" + size: StatusBaseButton.Size.Small + } + + StatusButton { + text: "Button" + enabled: false + size: StatusBaseButton.Size.Small + } + + StatusButton { + text: "Button" + size: StatusBaseButton.Size.Small + loading: true + } + + StatusButton { + text: "Button" + type: StatusBaseButton.Type.Danger + size: StatusBaseButton.Size.Small + } + + StatusButton { + text: "Button" + type: StatusBaseButton.Type.Danger + size: StatusBaseButton.Size.Small + enabled: false + } + + StatusButton { + text: "Button" + type: StatusBaseButton.Type.Danger + size: StatusBaseButton.Size.Small + loading: true + } + + StatusFlatButton { + text: "Button" + size: StatusBaseButton.Size.Small + } + + StatusFlatButton { + text: "Button" + enabled: false + size: StatusBaseButton.Size.Small + } + + StatusFlatButton { + text: "Button" + enabled: false + size: StatusBaseButton.Size.Small + loading: true + } + + // Icon buttons + + // blue + + StatusRoundButton { + icon: "info" + } + + StatusRoundButton { + icon: "info" + enabled: false + } + + StatusRoundButton { + icon: "info" + loading: true + } + + // black + + StatusRoundButton { + type: StatusRoundButton.Type.Secondary + icon: "info" + } + + StatusRoundButton { + type: StatusRoundButton.Type.Secondary + icon: "info" + enabled: false + } + + StatusRoundButton { + type: StatusRoundButton.Type.Secondary + icon: "info" + loading: true + } + + // Rounded blue + + StatusFlatRoundButton { + width: 44 + height: 44 + + icon: "info" + } + + StatusFlatRoundButton { + width: 44 + height: 44 + icon: "info" + enabled: false + } + + StatusFlatRoundButton { + width: 44 + height: 44 + icon: "info" + loading: true + } + + // Rounded white + + StatusFlatRoundButton { + type: StatusFlatRoundButton.Type.Secondary + width: 44 + height: 44 + + icon: "info" + } + + StatusFlatRoundButton { + type: StatusFlatRoundButton.Type.Secondary + width: 44 + height: 44 + icon: "info" + enabled: false + } + + StatusFlatRoundButton { + type: StatusFlatRoundButton.Type.Secondary + width: 44 + height: 44 + icon: "info" + loading: true + } + + StatusFlatButton { + iconName: "info" + text: "Button" + size: StatusBaseButton.Size.Small + } + StatusFlatButton { + iconName: "info" + text: "Button" + enabled: false + size: StatusBaseButton.Size.Small + } + + StatusFlatButton { + iconName: "info" + text: "Button" + loading: true + size: StatusBaseButton.Size.Small + } +} diff --git a/sandbox/main.qml b/sandbox/main.qml index 4a09074b..e7d904e2 100644 --- a/sandbox/main.qml +++ b/sandbox/main.qml @@ -7,19 +7,29 @@ import StatusQ.Core.Theme 0.1 Window { id: rootWindow - width: 640 - height: 480 + width: 1024 + height: 840 visible: true title: qsTr("Status App Sandbox") + property ThemePalette lightTheme: StatusLightTheme {} + property ThemePalette darkTheme: StatusDarkTheme { } + ButtonGroup { id: topicsGroup buttons: tabs.children } + ButtonGroup { + buttons: switchRow.children + } + Flow { id: tabs - width: parent.width + anchors.left: parent.left + anchors.leftMargin: 100 + anchors.right: parent.right + Button { text: "Reload QML" onClicked: app.restartQml() @@ -39,8 +49,16 @@ Window { checkable: true text: "Other" } + + Button { + id: buttonsTab + checkable: true + text: "Buttons" + } } + + ScrollView { width: parent.width anchors.top: tabs.bottom @@ -48,70 +66,62 @@ Window { contentHeight: rootWindow.height * rootWindow.factor contentWidth: rootWindow.width * rootWindow.factor clip: true - SplitView { - width: parent.width - height: rootWindow.height - handle: Item {} + + Rectangle { + id: lightThemeBg + + width: rootWindow.width + height: parent.height + color: Theme.palette.baseColor5 + clip: true scale: rootWindow.factor - Rectangle { - id: lightThemeBg + Loader { + active: true + anchors.centerIn: parent - SplitView.minimumWidth: rootWindow.width / 2 - height: parent.height - color: lightTheme.baseColor5 - clip: true - - Loader { - active: true - anchors.centerIn: parent - property var currentTheme: StatusLightTheme { id: lightTheme } - - sourceComponent: { - switch(topicsGroup.checkedButton) { - case iconsTab: - return iconsComponent; - case controlsTab: - return controlsComponent; - case otherTab: - return othersComponent; - default: - return null; - } + sourceComponent: { + switch(topicsGroup.checkedButton) { + case iconsTab: + return iconsComponent; + case controlsTab: + return controlsComponent; + case otherTab: + return othersComponent; + case buttonsTab: + return buttonsComponent; + default: + return null; } } - } + Row { + id: switchRow + scale: 0.8 + anchors.right: parent.right + anchors.top: parent.top - Rectangle { - id: darkThemeBg - - SplitView.fillWidth: true - SplitView.minimumWidth: rootWindow.width / 2 - height: parent.height - color: darkTheme.baseColor5 - clip: true - - Loader { - active: true - anchors.centerIn: parent - property var currentTheme: StatusDarkTheme { id: darkTheme } - - sourceComponent: { - switch(topicsGroup.checkedButton) { - case iconsTab: - return iconsComponent; - case controlsTab: - return controlsComponent; - case otherTab: - return othersComponent; - default: - return null; + Button { + checkable: true + checked: true + text: "Light Theme" + onCheckedChanged: { + if (checked) { + Theme.setTheme(lightTheme) } } } + Button { + checkable: true + text: "Dark Theme" + onCheckedChanged: { + if (checked) { + Theme.setTheme(darkTheme) + } + } + } } } } @@ -147,7 +157,7 @@ Window { id: iconsComponent Icons { anchors.centerIn: parent - iconColor: parent? parent.currentTheme.primaryColor1 : "#ffffff" + iconColor: Theme.palette.primaryColor1 } } @@ -155,7 +165,7 @@ Window { id: controlsComponent Controls { anchors.centerIn: parent - theme: parent.currentTheme + theme: Theme.palette } } @@ -163,7 +173,14 @@ Window { id: othersComponent Others { anchors.centerIn: parent - theme: parent.currentTheme + theme: Theme.palette + } + } + + Component { + id: buttonsComponent + Buttons { + anchors.centerIn: parent } } } diff --git a/sandbox/qml.qrc b/sandbox/qml.qrc index 34dd3676..4e1d556b 100644 --- a/sandbox/qml.qrc +++ b/sandbox/qml.qrc @@ -4,5 +4,6 @@ Controls.qml Icons.qml Others.qml + Buttons.qml diff --git a/sandbox/sandbox.pro b/sandbox/sandbox.pro index f9823b5c..e3fe24c5 100644 --- a/sandbox/sandbox.pro +++ b/sandbox/sandbox.pro @@ -29,3 +29,8 @@ OTHER_FILES += $$files($$PWD/../src/*, true) HEADERS += \ handler.h \ sandboxapp.h + +DISTFILES += \ + ../src/StatusQ/Controls/StatusBaseButton.qml \ + ../src/StatusQ/Controls/StatusButton.qml \ + ../src/StatusQ/Controls/StatusFlatRoundButton.qml diff --git a/src/StatusQ/Controls/StatusBaseButton.qml b/src/StatusQ/Controls/StatusBaseButton.qml new file mode 100644 index 00000000..0ce98ef8 --- /dev/null +++ b/src/StatusQ/Controls/StatusBaseButton.qml @@ -0,0 +1,142 @@ +import QtQuick 2.14 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 + +Rectangle { + id: statusBaseButton + + enum Size { + Small, + Large + } + + enum Type { + Normal, + Danger + } + + property alias iconName: icon.icon + + property bool loading: false + + property alias hovered: sensor.containsMouse + + property int size: StatusBaseButton.Size.Large + property int type: StatusBaseButton.Type.Normal + + property alias text: label.text + property alias font: label.font + + property real defaultLeftPadding: size === StatusBaseButton.Size.Large ? 24 : 12 + property real defaultRightPadding: size === StatusBaseButton.Size.Large ? 24 : 12 + property real defaultTopPadding: size === StatusBaseButton.Size.Large ? 11 : 10 + property real defaultBottomPadding: size === StatusBaseButton.Size.Large ? 11 : 10 + + + property real leftPadding: defaultLeftPadding + property real rightPadding: defaultRightPadding + property real topPadding: defaultTopPadding + property real bottomPadding: defaultBottomPadding + + property color normalColor + property color hoverColor + property color disaledColor + + property color textColor + property color disabledTextColor + + signal pressed(var mouse) + signal released(var mouse) + signal clicked(var mouse) + signal pressAndHold(var mouse) + + + + /// Implementation + + implicitWidth: sensor.width + implicitHeight: sensor.height + + radius: 8 + + color: { + if (statusBaseButton.enabled) { + return sensor.containsMouse ? hoverColor + : normalColor + } else { + return disaledColor + } + } + + + MouseArea { + id: sensor + width: layout.width + statusBaseButton.leftPadding + statusBaseButton.rightPadding + height: layout.height + statusBaseButton.topPadding + statusBaseButton.bottomPadding + + cursorShape: loading ? Qt.ArrowCursor + : Qt.PointingHandCursor + hoverEnabled: !loading + enabled: !loading + + Row { + id: layout + anchors.left: parent.left + anchors.leftMargin: statusBaseButton.leftPadding + anchors.verticalCenter: parent.verticalCenter + spacing: 4 + StatusIcon { + id: icon + anchors.verticalCenter: parent.verticalCenter + visible: !loading && iconName !== "" + color: statusBaseButton.enabled ? textColor + : disabledTextColor + } // Icon + StatusBaseText { + id: label + visible: !loading + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: size === StatusBaseButton.Size.Large ? 15 : 13 // by design + + color: statusBaseButton.enabled ? textColor + : disabledTextColor + } // Text + + Loader { + anchors.verticalCenter: parent.verticalCenter + active: loading + sourceComponent: StatusLoadingIndicator { + color: statusBaseButton.enabled ? textColor + : disabledTextColor + } // Indicator + } // Loader + } // Ro + + + onPressed: { + if (!loading) { + statusBaseButton.pressed(mouse) + } + } + + onReleased: { + if (!loading) { + statusBaseButton.released(mouse) + } + } + + onClicked: { + if (!loading) { + statusBaseButton.clicked(mouse) + } + } + + onPressAndHold: { + if (!loading) { + statusBaseButton.pressAndHold(mouse) + } + } + } // Sensor + +} diff --git a/src/StatusQ/Controls/StatusButton.qml b/src/StatusQ/Controls/StatusButton.qml new file mode 100644 index 00000000..b1317474 --- /dev/null +++ b/src/StatusQ/Controls/StatusButton.qml @@ -0,0 +1,17 @@ +import QtQuick 2.14 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +StatusBaseButton { + id: statusButton + + normalColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3 + : Theme.palette.dangerColor3 + hoverColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor2 + : Theme.palette.dangerColor2 + disaledColor: Theme.palette.baseColor2 + + textColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor1 + : Theme.palette.dangerColor1 + disabledTextColor: Theme.palette.baseColor1 +} diff --git a/src/StatusQ/Controls/StatusFlatButton.qml b/src/StatusQ/Controls/StatusFlatButton.qml new file mode 100644 index 00000000..bf8cde78 --- /dev/null +++ b/src/StatusQ/Controls/StatusFlatButton.qml @@ -0,0 +1,21 @@ +import QtQuick 2.14 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +StatusBaseButton { + id: statusFlatButton + + normalColor: "transparent" + hoverColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor3 + : Theme.palette.dangerColor3 + disaledColor: "transparent" + + textColor: type === StatusBaseButton.Type.Normal ? Theme.palette.primaryColor1 + : Theme.palette.dangerColor1 + disabledTextColor: Theme.palette.baseColor1 + + border.color: type === StatusBaseButton.Type.Normal || hovered ? "transparent" + : Theme.palette.baseColor2 + rightPadding: iconName !== "" ? 18 : defaultRightPadding + leftPadding: iconName !== "" ? 14 : defaultLeftPadding +} diff --git a/src/StatusQ/Controls/StatusFlatRoundButton.qml b/src/StatusQ/Controls/StatusFlatRoundButton.qml new file mode 100644 index 00000000..818396ad --- /dev/null +++ b/src/StatusQ/Controls/StatusFlatRoundButton.qml @@ -0,0 +1,138 @@ +import QtQuick 2.14 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 + + +Rectangle { + id: statusFlatRoundButton + + property alias icon: iconSettings.name + + property bool loading: false + + property int type: StatusFlatRoundButton.Type.Primary + + signal pressed(var mouse) + signal released(var mouse) + signal clicked(var mouse) + signal pressAndHold(var mouse) + + enum Type { + Primary, + Secondary + } + + + + /// Implementation + + QtObject { + id: iconSettings + property alias name: statusIcon.icon + property color color: { + switch(statusFlatRoundButton.type) { + case StatusFlatRoundButton.Type.Secondary: + return Theme.palette.directColor1; + case StatusFlatRoundButton.Type.Primary: + return Theme.palette.primaryColor1; + } + } + + property color disabledColor: { + switch(statusFlatRoundButton.type) { + case StatusFlatRoundButton.Type.Secondary: + return Theme.palette.baseColor1; + case StatusFlatRoundButton.Type.Primary: + return Theme.palette.baseColor1; + } + } + } + + QtObject { + id: backgroundSettings + + property color color: { + switch(statusFlatRoundButton.type) { + case StatusFlatRoundButton.Type.Primary: + case StatusFlatRoundButton.Type.Secondary: + return "transparent"; + } + } + + property color hoverColor: { + switch(statusFlatRoundButton.type) { + case StatusFlatRoundButton.Type.Primary: + return Theme.palette.primaryColor2; + case StatusFlatRoundButton.Type.Secondary: + return "transparent"; + } + } + + property color disabledColor: { + switch(statusFlatRoundButton.type) { + case StatusFlatRoundButton.Type.Primary: + case StatusFlatRoundButton.Type.Secondary: + return "transparent"; + } + } + } + + implicitWidth: 44 + implicitHeight: 44 + radius: 8 + + color: { + if (statusFlatRoundButton.enabled) { + return sensor.containsMouse ? backgroundSettings.hoverColor + : backgroundSettings.color + } else { + return backgroundSettings.disabledColor + } + } + MouseArea { + id: sensor + + anchors.fill: parent + cursorShape: loading ? Qt.ArrowCursor + : Qt.PointingHandCursor + hoverEnabled: !loading + enabled: !loading + + + StatusIcon { + id: statusIcon + anchors.centerIn: parent + visible: !loading + + width: statusFlatRoundButton.width - 20 + height: statusFlatRoundButton.height - 20 + + color: { + if (statusFlatRoundButton.enabled) { + return iconSettings.color + } else { + return iconSettings.disabledColor + } + } + } // Icon + Loader { + active: loading + anchors.centerIn: parent + sourceComponent: StatusLoadingIndicator { + color: { + if (statusFlatRoundButton.enabled) { + return iconSettings.color + } else { + return iconSettings.disabledColor + } + } + } // Indicator + } // Loader + + onClicked: statusFlatRoundButton.clicked(mouse) + onPressed: statusFlatRoundButton.pressed(mouse) + onReleased: statusFlatRoundButton.released(mouse) + onPressAndHold: statusFlatRoundButton.pressAndHold(mouse) + } // Sensor +} // Rectangle diff --git a/src/StatusQ/Controls/StatusRoundButton.qml b/src/StatusQ/Controls/StatusRoundButton.qml new file mode 100644 index 00000000..383737b9 --- /dev/null +++ b/src/StatusQ/Controls/StatusRoundButton.qml @@ -0,0 +1,140 @@ +import QtQuick 2.14 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 + + +Rectangle { + id: statusRoundButton + + property alias icon: iconSettings.name + + property bool loading: false + + property int type: StatusRoundButton.Type.Primary + + signal pressed(var mouse) + signal released(var mouse) + signal clicked(var mouse) + signal pressAndHold(var mouse) + + enum Type { + Primary, + Secondary + } + + + + /// Implementation + + QtObject { + id: iconSettings + property alias name: statusIcon.icon + property color color: { + switch(statusRoundButton.type) { + case StatusRoundButton.Type.Primary: + return Theme.palette.primaryColor1; + case StatusRoundButton.Type.Secondary: + return Theme.palette.indirectColor1; + } + } + + property color disabledColor: { + switch(statusRoundButton.type) { + case StatusRoundButton.Type.Primary: + return Theme.palette.baseColor1; + case StatusRoundButton.Type.Secondary: + return Theme.palette.indirectColor1; + } + } + } + + QtObject { + id: backgroundSettings + + property color color: { + switch(statusRoundButton.type) { + case StatusRoundButton.Type.Primary: + return Theme.palette.primaryColor3; + case StatusRoundButton.Type.Secondary: + return Theme.palette.primaryColor1; + } + } + + property color hoverColor: { + switch(statusRoundButton.type) { + case StatusRoundButton.Type.Primary: + return Theme.palette.primaryColor2; + case StatusRoundButton.Type.Secondary: + return Theme.palette.miscColor1; + } + } + + property color disabledColor: { + switch(statusRoundButton.type) { + case StatusRoundButton.Type.Primary: + return Theme.palette.indirectColor1; + case StatusRoundButton.Type.Secondary: + return Theme.palette.baseColor1; + } + } + } + + implicitWidth: 44 + implicitHeight: 44 + radius: width / 2; + + color: { + if (statusRoundButton.enabled) { + return sensor.containsMouse ? backgroundSettings.hoverColor + : backgroundSettings.color + } else { + return backgroundSettings.disabledColor + } + } + MouseArea { + id: sensor + + anchors.fill: parent + cursorShape: loading ? Qt.ArrowCursor + : Qt.PointingHandCursor + hoverEnabled: !loading + enabled: !loading + + + StatusIcon { + id: statusIcon + anchors.centerIn: parent + visible: !loading + + width: statusRoundButton.width - 20 + height: statusRoundButton.height - 20 + + color: { + if (statusRoundButton.enabled) { + return iconSettings.color + } else { + return iconSettings.disabledColor + } + } + } // Icon + Loader { + active: loading + anchors.centerIn: parent + sourceComponent: StatusLoadingIndicator { + color: { + if (statusRoundButton.enabled) { + return iconSettings.color + } else { + return iconSettings.disabledColor + } + } + } // Indicator + } // Loader + + onClicked: statusRoundButton.clicked(mouse) + onPressed: statusRoundButton.pressed(mouse) + onReleased: statusRoundButton.released(mouse) + onPressAndHold: statusRoundButton.pressAndHold(mouse) + } // Sensor +} // Rectangle diff --git a/src/StatusQ/Controls/qmldir b/src/StatusQ/Controls/qmldir index 196583b3..d10d2d81 100644 --- a/src/StatusQ/Controls/qmldir +++ b/src/StatusQ/Controls/qmldir @@ -3,4 +3,9 @@ module StatusQ.Controls StatusIconTabButton 0.1 StatusIconTabButton.qml StatusNavBarTabButton 0.1 StatusNavBarTabButton.qml StatusToolTip 0.1 StatusToolTip.qml +StatusBaseButton 0.1 StatusBaseButton.qml +StatusButton 0.1 StatusButton.qml +StatusFlatButton 0.1 StatusFlatButton.qml +StatusRoundButton 0.1 StatusRoundButton.qml +StatusFlatRoundButton 0.1 StatusFlatRoundButton.qml