diff --git a/src/gui/qml2/DissolveDark/Button.qml b/src/gui/qml2/DissolveDark/Button.qml new file mode 100644 index 0000000000..8a2e36f749 --- /dev/null +++ b/src/gui/qml2/DissolveDark/Button.qml @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T +import QtQuick.Controls.impl + +T.Button { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 4 + spacing: 6 + + icon.width: 16 + icon.height: 16 + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + text: control.text + font: Theme.normalFont + color: Theme.getForegroundColour(control) + } + + background: ButtonPanel { + implicitWidth: 80 + implicitHeight: 24 + + control: control + visible: !control.flat || control.down || control.checked || control.highlighted || control.visualFocus + || (enabled && control.hovered) + } +} diff --git a/src/gui/qml2/DissolveDark/ButtonPanel.qml b/src/gui/qml2/DissolveDark/ButtonPanel.qml new file mode 100644 index 0000000000..c5c6995b0a --- /dev/null +++ b/src/gui/qml2/DissolveDark/ButtonPanel.qml @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick + +Rectangle { + id: panel + + property Item control + property bool highlighted: control.highlighted + + visible: !control.flat || control.down || control.checked + + gradient: { + if (!control.enabled) { Theme.disabledGradient } + else (control.down || control.checked ? Theme.controlBackgroundGradient : Theme.controlForegroundGradient) + } + + radius: 2 + border.color: Theme.colours.mid + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + border.color: Theme.colours.background + color: "transparent" + + radius: 2 + } +} diff --git a/src/gui/qml2/DissolveDark/CheckBox.qml b/src/gui/qml2/DissolveDark/CheckBox.qml new file mode 100644 index 0000000000..5c210c7723 --- /dev/null +++ b/src/gui/qml2/DissolveDark/CheckBox.qml @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T + +T.CheckBox { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 6 + spacing: 6 + + indicator: CheckIndicator { + x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 + y: control.topPadding + (control.availableHeight - height) / 2 + control: control + } + + contentItem: Text { + leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0 + + text: control.text + font: Theme.normalFont + color: Theme.getForegroundColour(control) + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } +} diff --git a/src/gui/qml2/DissolveDark/CheckIndicator.qml b/src/gui/qml2/DissolveDark/CheckIndicator.qml new file mode 100644 index 0000000000..0da4583637 --- /dev/null +++ b/src/gui/qml2/DissolveDark/CheckIndicator.qml @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick + +Rectangle { + id: indicator + + property Item control + + implicitWidth: 16 + implicitHeight: 16 + + gradient: Theme.controlBackgroundGradient + border.color: Theme.colours.mid + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.width - 2 + border.color: Theme.colours.background + gradient: Theme.controlBackgroundGradient + + Image { + x: 1; y: 1 + width: parent.width - 2 + height: parent.width - 2 + visible: indicator.control.checkState === Qt.Checked + source: "assets/tick.png" + } + + Rectangle { + x: 2; y: 2 + width: parent.width - 4 + height: parent.width - 4 + + visible: indicator.control.checkState === Qt.PartiallyChecked + + gradient: Theme.getAccentGradient(indicator.control) + border.color: Theme.colours.background + } + } +} diff --git a/src/gui/qml2/DissolveDark/GroupBox.qml b/src/gui/qml2/DissolveDark/GroupBox.qml new file mode 100644 index 0000000000..9788f4baa2 --- /dev/null +++ b/src/gui/qml2/DissolveDark/GroupBox.qml @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T + +T.GroupBox { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitLabelWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + spacing: 4 + padding: 4 + topPadding: padding + (implicitLabelWidth > 0 ? implicitLabelHeight + spacing : 0) + + label: Text { + x: control.leftPadding + width: control.availableWidth + + text: control.title + font: Theme.normalFont + color: Theme.getForegroundColour(control) + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + + background: Rectangle { + y: control.topPadding - control.bottomPadding + width: parent.width + height: parent.height - control.topPadding + control.bottomPadding + + radius: 2 + gradient: Theme.controlBackgroundGradient + border.color: Theme.colours.mid + } +} diff --git a/src/gui/qml2/DissolveDark/Label.qml b/src/gui/qml2/DissolveDark/Label.qml new file mode 100644 index 0000000000..775c084c00 --- /dev/null +++ b/src/gui/qml2/DissolveDark/Label.qml @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T + +T.Label { + id: control + + font: Theme.normalFont + color: Theme.getForegroundColour(control) +} diff --git a/src/gui/qml2/DissolveDark/Pane.qml b/src/gui/qml2/DissolveDark/Pane.qml new file mode 100644 index 0000000000..d034006638 --- /dev/null +++ b/src/gui/qml2/DissolveDark/Pane.qml @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T + +T.Pane { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + topPadding: background ? background.topPadding : 0 + leftPadding: background ? background.leftPadding : 0 + rightPadding: background ? background.rightPadding : 0 + bottomPadding: background ? background.bottomPadding : 0 + + topInset: background ? -background.topInset || 0 : 0 + leftInset: background ? -background.leftInset || 0 : 0 + rightInset: background ? -background.rightInset || 0 : 0 + bottomInset: background ? -background.bottomInset || 0 : 0 + + background: Rectangle { + gradient: Theme.mainGradient + } +} diff --git a/src/gui/qml2/DissolveDark/SquareButton.qml b/src/gui/qml2/DissolveDark/SquareButton.qml new file mode 100644 index 0000000000..321846d1e5 --- /dev/null +++ b/src/gui/qml2/DissolveDark/SquareButton.qml @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T +import QtQuick.Controls.impl + +T.Button { + id: control + + property int size: 32 + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + width: size + height: size + padding: 4 + spacing: 4 + + icon.width: size + icon.height: size + + contentItem: IconLabel { + width: 50 + height: 50 + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + font: Theme.normalFont + color: Theme.getForegroundColour(control) + } + + background: ButtonPanel { + implicitWidth: parent.width + implicitHeight: parent.height + + control: control + visible: !control.flat || control.down || control.checked || control.highlighted || control.visualFocus + || (enabled && control.hovered) + } +} diff --git a/src/gui/qml2/DissolveDark/Switch.qml b/src/gui/qml2/DissolveDark/Switch.qml new file mode 100644 index 0000000000..c5c776f25e --- /dev/null +++ b/src/gui/qml2/DissolveDark/Switch.qml @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T + +T.Switch { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 6 + spacing: 6 + + indicator: SwitchIndicator { + x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2 + y: control.topPadding + (control.availableHeight - height) / 2 + control: control + } + + contentItem: Text { + leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0 + rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0 + + font: Theme.normalFont + text: control.text + color: Theme.getForegroundColour(control) + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } +} diff --git a/src/gui/qml2/DissolveDark/SwitchIndicator.qml b/src/gui/qml2/DissolveDark/SwitchIndicator.qml new file mode 100644 index 0000000000..60f8565663 --- /dev/null +++ b/src/gui/qml2/DissolveDark/SwitchIndicator.qml @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T + +Rectangle { + id: indicator + + property T.AbstractButton control + + implicitWidth: 40 + implicitHeight: 16 + + radius: 2 + border.color: Theme.colours.mid + + gradient: Theme.controlBackgroundGradient + + Rectangle { + x: indicator.control.mirrored ? handle.x : 0 + width: indicator.control.mirrored ? parent.width - handle.x : handle.x + handle.width + height: parent.height + + opacity: indicator.control.checked ? 1 : 0 + Behavior on opacity { + enabled: !indicator.control.down + NumberAnimation { duration: 80 } + } + + radius: 2 + border.color: Theme.colours.background + //border.width: indicator.control.enabled ? 1 : 0 + + gradient: Theme.getAccentGradient(indicator.control) + } + + Rectangle { + id: handle + x: Math.max(0, Math.min(parent.width - width, indicator.control.visualPosition * parent.width - (width / 2))) + y: (parent.height - height) / 2 + width: 20 + height: 16 + radius: 2 + + gradient: Theme.getForegroundGradient(control) + border.width: 1 + border.color: "transparent" + + Rectangle { + width: parent.width + height: parent.height + border.color: Theme.getForegroundColour(control) + color: "transparent" + radius: 2 + + Rectangle { + x: 1; y: 1 + width: parent.width - 2 + height: parent.height - 2 + border.color: Theme.colours.mid + color: "transparent" + radius: 2 + } + } + + Behavior on x { + enabled: !indicator.control.down + SmoothedAnimation { velocity: 200 } + } + } +} diff --git a/src/gui/qml2/DissolveDark/Text.qml b/src/gui/qml2/DissolveDark/Text.qml new file mode 100644 index 0000000000..b47bc9cc13 --- /dev/null +++ b/src/gui/qml2/DissolveDark/Text.qml @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick +import QtQuick.Templates as T + +T.Text { + font.pointSize: 9 + wrapMode: Text.Wrap + color: #f00 +} diff --git a/src/gui/qml2/DissolveDark/Theme.qml b/src/gui/qml2/DissolveDark/Theme.qml new file mode 100644 index 0000000000..4cbe56043d --- /dev/null +++ b/src/gui/qml2/DissolveDark/Theme.qml @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +pragma Singleton + +import QtQuick + +QtObject { + id: root + + property real baseSize: 1.0 + + /* + * Fonts + */ + property font normalFont: Qt.font({ + pointSize: 10 * baseSize + }) + + /* + * Colours + */ + + // Choose theme colours (TODO Light / normal version) + property ThemeColoursDark colours: ThemeColoursDark {} + + // Functions + function getForegroundColour(control){ + if (!control.enabled) { return colours.foregroundDisabled } + else return (control.down || control.checked ? colours.foregroundHighlighted : colours.foregroundNormal) + } + function getPrincipalColour(control){ + if (!control.enabled) { return colours.darker(colours.principal) } + else return (control.down || control.checked ? colours.brighter(colours.principal) : colours.principal) + } + + /* + * Gradients + */ + + // Basic Gradients + property Gradient mainGradient: Gradient { + GradientStop { position: 0.0; color: colours.background } + GradientStop { position: 0.9; color: colours.background } + GradientStop { position: 1.0; color: colours.extraDark(colours.principal) } + } + property Gradient disabledGradient: Gradient { + GradientStop { position: 0.0; color: colours.extraDark(colours.principal) } + GradientStop { position: 1.0; color: colours.background } + } + property Gradient testGradient: Gradient { + GradientStop { position: 0.0; color: "#100" } + GradientStop { position: 1.0; color: "#110" } + } + + // Foreground Gradients + property Gradient foregroundNormalGradient: Gradient { + GradientStop { position: 0.0; color: colours.foregroundNormal } + GradientStop { position: 1.0; color: colours.foregroundDisabled } + } + property Gradient foregroundHighlightGradient: Gradient { + GradientStop { position: 0.0; color: colours.foregroundNormal } + GradientStop { position: 1.0; color: colours.foregroundHighlighted } + } + property Gradient foregroundDisabledGradient: Gradient { + GradientStop { position: 0.0; color: colours.foregroundDisabled } + GradientStop { position: 1.0; color: colours.background } + } + + // Control Element Gradients + property Gradient controlForegroundGradient: Gradient { + GradientStop { position: 0.0; color: colours.brighter(colours.principal) } + GradientStop { position: 1.0; color: colours.darker(colours.principal) } + } + property Gradient controlBackgroundGradient: Gradient { + GradientStop { position: 0.0; color: colours.extraDark(colours.principal) } + GradientStop { position: 1.0; color: colours.background } + } + + // Accent Gradients + property Gradient accentNormalGradient: Gradient { + GradientStop { position: 0.0; color: colours.accent } + GradientStop { position: 1.0; color: colours.extraDark(colours.accent) } + } + property Gradient accentDisabledGradient: Gradient { + GradientStop { position: 0.0; color: colours.extraDark(colours.accent) } + GradientStop { position: 1.0; color: colours.background } + } + + // Functions + function getForegroundGradient(control){ + if (!control.enabled) { return foregroundDisabledGradient } + else return (control.down || control.checked ? foregroundHighlightGradient : foregroundNormalGradient) + } + function getAccentGradient(control){ + return control.enabled ? accentNormalGradient : accentDisabledGradient + } +} diff --git a/src/gui/qml2/DissolveDark/ThemeColoursDark.qml b/src/gui/qml2/DissolveDark/ThemeColoursDark.qml new file mode 100644 index 0000000000..2c976f270e --- /dev/null +++ b/src/gui/qml2/DissolveDark/ThemeColoursDark.qml @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2024 Team Dissolve and contributors + +import QtQuick + +QtObject { + // Constants & Factors + readonly property real brightenFactor: 1.2 + readonly property real darkenFactor: 0.8 + readonly property real extraDarkenFactor: darkenFactor*0.6 + + // Core Colour Definitions + readonly property color foreground: "#ddd" + readonly property color background: "#101" + readonly property color principal: "#313" + readonly property color accent: "#316549" + + // Derived Colours + readonly property color foregroundNormal: foreground + readonly property color foregroundHighlighted: brighter(foreground) + readonly property color foregroundDisabled: extraDark(foreground) + readonly property color mid: Qt.rgba( + (background.r + principal.r)*0.5, + (background.g + principal.g)*0.5, + (background.b + principal.b)*0.5, + 1.0 + ) + + // Colour Functions + function brighter(colour) { + return Qt.rgba(colour.r*brightenFactor, colour.g*brightenFactor, colour.b*brightenFactor, 1.0) + } + function darker(colour) { + return Qt.rgba(colour.r*darkenFactor, colour.g*darkenFactor, colour.b*darkenFactor, 1.0) + } + function extraDark(colour) { + return Qt.rgba(colour.r*extraDarkenFactor, colour.g*extraDarkenFactor, colour.b*extraDarkenFactor, 1.0) + } +} diff --git a/src/gui/qml2/DissolveDark/assets/tick.png b/src/gui/qml2/DissolveDark/assets/tick.png new file mode 100644 index 0000000000..7bf3b5693d Binary files /dev/null and b/src/gui/qml2/DissolveDark/assets/tick.png differ diff --git a/src/gui/qml2/DissolveDark/assets/tick.svg b/src/gui/qml2/DissolveDark/assets/tick.svg new file mode 100644 index 0000000000..a0af2bf255 --- /dev/null +++ b/src/gui/qml2/DissolveDark/assets/tick.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/gui/qml2/DissolveDark/qmldir b/src/gui/qml2/DissolveDark/qmldir new file mode 100644 index 0000000000..bd53880808 --- /dev/null +++ b/src/gui/qml2/DissolveDark/qmldir @@ -0,0 +1,16 @@ +module DissolveDark + +singleton Theme 1.0 Theme.qml +ThemeColoursDark 1.0 ThemeColoursDark.qml + +Button 1.0 Button.qml +ButtonPanel 1.0 ButtonPanel.qml +CheckBox 1.0 CheckBox.qml +CheckIndicator 1.0 CheckIndicator.qml +GroupBox 1.0 GroupBox.qml +Label 1.0 Label.qml +Pane 1.0 Pane.qml +Switch 1.0 Switch.qml +SwitchIndicator 1.0 SwitchIndicator.qml +SquareButton 1.0 SquareButton.qml +Text 1.0 Text.qml diff --git a/src/gui/qml2/README.md b/src/gui/qml2/README.md new file mode 100644 index 0000000000..fac2e8b0a9 --- /dev/null +++ b/src/gui/qml2/README.md @@ -0,0 +1,7 @@ +Testing a new Theme and widgets for the Dissolve GUI v2.0. + +To show the test widget gallery (on Linux at least) run the following from the directory containing the testGallery.qml file: + +user:~> export QML_IMPORT_PATH=`pwd` +user:~> qml6 testGallery.qml --style DissolveDark + diff --git a/src/gui/qml2/icons/add.png b/src/gui/qml2/icons/add.png new file mode 100644 index 0000000000..0e35226595 Binary files /dev/null and b/src/gui/qml2/icons/add.png differ diff --git a/src/gui/qml2/icons/threeSpecies.png b/src/gui/qml2/icons/threeSpecies.png new file mode 100644 index 0000000000..42cf5d8f9a Binary files /dev/null and b/src/gui/qml2/icons/threeSpecies.png differ diff --git a/src/gui/qml2/icons/warnBox.png b/src/gui/qml2/icons/warnBox.png new file mode 100644 index 0000000000..7417a5c466 Binary files /dev/null and b/src/gui/qml2/icons/warnBox.png differ diff --git a/src/gui/qml2/testGallery.qml b/src/gui/qml2/testGallery.qml new file mode 100644 index 0000000000..d5c100959c --- /dev/null +++ b/src/gui/qml2/testGallery.qml @@ -0,0 +1,64 @@ +import QtQuick 2.11 +import QtQuick.Controls 2.1 +import QtQuick.Layouts 2.1 + +Pane { + width: 600 + height: 600 + + Grid { + anchors.fill: parent + columns: 3 + + padding: 4 + spacing: 4 + + GroupBox { + title: "Button" + ColumnLayout { + spacing: 4 + Button { text: "Normal" } + Button { text: "Disabled"; enabled: false } + Button { text: "Icon"; icon.source: "icons/add.png" } + Button { text: "Icon, Disabled"; enabled: false; icon.source: "icons/add.png" } + } + } + + GroupBox { + title: "CheckBox" + ColumnLayout { + spacing: 4 + CheckBox { text: "Normal" } + CheckBox { text: "Tristate"; tristate: true } + CheckBox { text: "Disabled"; checked: true; enabled: false } + CheckBox { text: "Disabled, Tristate"; tristate: true; checkState: Qt.PartiallyChecked; enabled: false } + } + } + + GroupBox { + title: "Switch" + ColumnLayout { + spacing: 4 + Switch { text: "Normal" } + Switch { text: "Disabled"; checked: true; enabled: false } + } + } + + GroupBox { + title: "SquareButton" + ColumnLayout { + spacing: 4 + SquareButton { icon.source: "icons/warnBox.png"; text: "Test"; size: 64 } + } + } + + GroupBox { + title: "Label" + ColumnLayout { + spacing: 4 + Label { text: "Normal" } + Label { text: "Disabled"; enabled: false } + } + } + } +}