diff options
author | Henning Gruendl <henning.gruendl@qt.io> | 2019-07-05 14:58:20 +0200 |
---|---|---|
committer | Thomas Hartmann <thomas.hartmann@qt.io> | 2019-08-05 14:43:03 +0000 |
commit | 98085e69a6d250321b3012671c6b4ba50be4370a (patch) | |
tree | 848309d3bf0b6b8f12ce4c23640d2f3a012c77dd | |
parent | bb54345474c928250f65f778fcfc2fb061f72406 (diff) |
Adds new controls for the property editor based on Controls 2. The
included controls are SpinBox (RealSpinBox), ComboBox, TextField,
TextArea (experimental), CheckBox (with tri-state), Button (ButtonRow),
ContextMenu, ScrollView and ScrollBar.
Each control contains an ActionIndicator which can be hidden on demand.
The ActionIndicator itself can also be used standalone. It also a flag
to draw it without borders and background.
The reason for two SpinBox implementations is the following bug QDS-806.
Usage of SpinBox should be avoided rather use RealSpinBox.
Change-Id: Ie647f05d02e8de8d31da9556126ce2cabe9009e9
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
40 files changed, 4631 insertions, 0 deletions
diff --git a/src/imports/StudioControls/AbstractButton.qml b/src/imports/StudioControls/AbstractButton.qml new file mode 100644 index 0000000..222334f --- /dev/null +++ b/src/imports/StudioControls/AbstractButton.qml @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.AbstractButton { + id: myButton + + property alias buttonIcon: buttonIcon.text + property alias iconColor: buttonIcon.color + property alias backgroundVisible: buttonBackground.visible + property alias backgroundRadius: buttonBackground.radius + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + height: StudioTheme.Values.height + width: StudioTheme.Values.height + z: myButton.checked ? 10 : 3 + activeFocusOnTab: false + + background: Rectangle { + id: buttonBackground + color: myButton.checked ? StudioTheme.Values.themeControlBackgroundChecked : StudioTheme.Values.themeControlBackground + border.color: myButton.checked ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } + + indicator: Item { + x: 0 + y: 0 + implicitWidth: myButton.width + implicitHeight: myButton.height + + T.Label { + id: buttonIcon + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + renderType: Text.QtRendering + } + } + + states: [ + State { + name: "default" + when: myButton.enabled && !myButton.hovered && !myButton.pressed + && !myButton.checked + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackground + } + PropertyChanges { + target: myButton + z: 3 + } + }, + State { + name: "hovered" + when: myButton.hovered && !myButton.pressed + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: myButton.hovered && myButton.pressed + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackgroundPressed + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: myButton + z: 10 + } + }, + State { + name: "disabled" + when: !myButton.enabled + PropertyChanges { + target: buttonBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: buttonIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/ActionIndicator.qml b/src/imports/StudioControls/ActionIndicator.qml new file mode 100644 index 0000000..e261ebe --- /dev/null +++ b/src/imports/StudioControls/ActionIndicator.qml @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: actionIndicator + + property Item myControl + + property bool showBackground: true + property alias icon: actionIndicatorIcon + + property bool hover: false + property bool pressed: false + + color: actionIndicator.showBackground ? StudioTheme.Values.themeControlBackground : "transparent" + border.color: actionIndicator.showBackground ? StudioTheme.Values.themeControlOutline : "transparent" + + implicitWidth: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + + signal clicked + + T.Label { + id: actionIndicatorIcon + anchors.fill: parent + text: StudioTheme.Constants.actionIcon + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.myIconFontSize + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + states: [ + State { + name: "hovered" + when: actionIndicator.hover && !actionIndicator.pressed + && (!myControl || (!myControl.edit && !myControl.drag)) + && actionIndicator.enabled + PropertyChanges { + target: actionIndicatorIcon + scale: 1.2 + } + }, + State { + name: "disabled" + when: !actionIndicator.enabled + PropertyChanges { + target: actionIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] + } + + MouseArea { + id: actionIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: actionIndicator.hover = containsMouse + onClicked: actionIndicator.clicked() + } + + states: [ + State { + name: "default" + when: myControl.enabled && !actionIndicator.hover + && !actionIndicator.pressed && !myControl.hover + && !myControl.edit && !myControl.drag && actionIndicator.showBackground + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "globalHover" + when: myControl.hover && !actionIndicator.hover + && !actionIndicator.pressed && !myControl.edit + && !myControl.drag && actionIndicator.showBackground + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: myControl.edit && actionIndicator.showBackground + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: myControl.drag && actionIndicator.showBackground + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled && actionIndicator.showBackground + PropertyChanges { + target: actionIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/Button.qml b/src/imports/StudioControls/Button.qml new file mode 100644 index 0000000..42d7b3e --- /dev/null +++ b/src/imports/StudioControls/Button.qml @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +ButtonRow { + id: myButtonRow + + property alias buttonIcon: myAbstractButton.buttonIcon + property alias iconColor: myAbstractButton.iconColor + property alias checkable: myAbstractButton.checkable + property alias checked: myAbstractButton.checked + + signal onCheckedChanged() + + AbstractButton { + id: myAbstractButton + onCheckedChanged: myButtonRow.onCheckedChanged() + } +} diff --git a/src/imports/StudioControls/ButtonGroup.qml b/src/imports/StudioControls/ButtonGroup.qml new file mode 100644 index 0000000..1b233c5 --- /dev/null +++ b/src/imports/StudioControls/ButtonGroup.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T + +T.ButtonGroup { + +} diff --git a/src/imports/StudioControls/ButtonRow.qml b/src/imports/StudioControls/ButtonRow.qml new file mode 100644 index 0000000..059c38a --- /dev/null +++ b/src/imports/StudioControls/ButtonRow.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Row { + // TODO When using Item as root it won't react to outer layout + id: myButtonGroup + + property alias actionIndicator: actionIndicator + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + ActionIndicator { + id: actionIndicator + myControl: myButtonGroup // TODO global hover issue. Can be solved with extra property in ActionIndicator + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + spacing: -StudioTheme.Values.border // TODO Which one is better? Spacing vs. layout function. ALso depends on root item +} diff --git a/src/imports/StudioControls/CheckBox.qml b/src/imports/StudioControls/CheckBox.qml new file mode 100644 index 0000000..5ec29bb --- /dev/null +++ b/src/imports/StudioControls/CheckBox.qml @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.CheckBox { + id: myCheckBox + + property alias actionIndicator: actionIndicator + + property bool hover: myCheckBox.hovered + property bool edit: false + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property alias labelVisible: checkBoxLabel.visible + property alias labelColor: checkBoxLabel.color + + font.pixelSize: StudioTheme.Values.myFontSize + + implicitWidth: Math.max( + implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding + + implicitIndicatorWidth + spacing + actionIndicator.width) + implicitHeight: Math.max( + implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + spacing: StudioTheme.Values.checkBoxSpacing + hoverEnabled: true + activeFocusOnTab: false + + contentItem: T.Label { + id: checkBoxLabel + leftPadding: 0 + rightPadding: 0 + verticalAlignment: Text.AlignVCenter + text: myCheckBox.text + font: myCheckBox.font + color: StudioTheme.Values.themeTextColor + visible: text !== "" + } + + ActionIndicator { + id: actionIndicator + myControl: myCheckBox // TODO global hover issue. Can be solved with extra property in ActionIndicator + + x: checkBoxLabel.visible ? checkBoxLabel.contentWidth + myCheckBox.spacing : 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + indicator: Rectangle { + id: checkBoxBackground + x: actionIndicator.x + actionIndicator.width + - (actionIndicator.visible ? StudioTheme.Values.border : 0) + y: 0 + z: 5 + implicitWidth: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + + T.Label { + id: checkedIcon + x: (parent.width - checkedIcon.width) / 2 + y: (parent.height - checkedIcon.height) / 2 + text: StudioTheme.Constants.tickIcon + visible: myCheckBox.checkState === Qt.Checked + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderControlSizeMulti + font.family: StudioTheme.Constants.iconFont.family + } + + T.Label { + id: partiallyCheckedIcon + x: (parent.width - checkedIcon.width) / 2 + y: (parent.height - checkedIcon.height) / 2 + text: StudioTheme.Constants.triState + visible: myCheckBox.checkState === Qt.PartiallyChecked + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderControlSizeMulti + font.family: StudioTheme.Constants.iconFont.family + } + } + + states: [ + State { + name: "default" + when: myCheckBox.enabled && !myCheckBox.hovered + && !myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "hovered" + when: myCheckBox.hovered && !myCheckBox.pressed + && !actionIndicator.hover + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: myCheckBox.hovered && myCheckBox.pressed + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myCheckBox.enabled + PropertyChanges { + target: checkBoxBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: checkedIcon + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: partiallyCheckedIcon + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: checkBoxLabel + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/CheckIndicator.qml b/src/imports/StudioControls/CheckIndicator.qml new file mode 100644 index 0000000..4c314b9 --- /dev/null +++ b/src/imports/StudioControls/CheckIndicator.qml @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: checkIndicator + + property T.Control myControl + property T.Popup myPopup + + property bool hover: false + property bool checked: false + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + state: "default" + + Connections { + target: myPopup + onClosed: checkIndicator.checked = false + onOpened: checkIndicator.checked = true + } + + MouseArea { + id: checkIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: checkIndicator.hover = checkIndicatorMouseArea.containsMouse + onPressed: { + myControl.forceActiveFocus() // TODO + myPopup.opened ? myPopup.close() : myPopup.open() + } + } + + T.Label { + id: checkIndicatorIcon + anchors.fill: parent + color: StudioTheme.Values.themeTextColor + text: StudioTheme.Constants.upDownSquare2 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: StudioTheme.Values.sliderControlSizeMulti + font.family: StudioTheme.Constants.iconFont.family + } + + states: [ + State { + name: "default" + when: myControl.enabled && !(checkIndicator.hover + || myControl.hover) + && !checkIndicator.checked && !myControl.edit + && !myControl.drag + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "hovered" + when: (checkIndicator.hover || myControl.hover) + && !checkIndicator.checked && !myControl.edit + && !myControl.drag + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "checked" + when: checkIndicator.checked + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: myControl.edit && !checkIndicator.checked + && !(checkIndicator.hover && myControl.hover) + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: myControl.drag && !checkIndicator.checked + && !(checkIndicator.hover && myControl.hover) + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: checkIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: checkIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/ComboBox.qml b/src/imports/StudioControls/ComboBox.qml new file mode 100644 index 0000000..1b693be --- /dev/null +++ b/src/imports/StudioControls/ComboBox.qml @@ -0,0 +1,257 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Window 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ComboBox { + id: myComboBox + + property alias actionIndicator: actionIndicator + property alias labelColor: comboBoxInput.color + + property bool hover: false // This property is used to indicate the global hover state + property bool edit: myComboBox.activeFocus + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property string __lastAcceptedText: "" + signal compressedActivated + + width: StudioTheme.Values.squareComponentWidth * 5 + height: StudioTheme.Values.height + + leftPadding: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: popupIndicator.width - StudioTheme.Values.border + font.pixelSize: StudioTheme.Values.myFontSize + wheelEnabled: false + + onFocusChanged: { + if (!myComboBox.focus) + comboBoxPopup.close() + } + + ActionIndicator { + id: actionIndicator + myControl: myComboBox + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + contentItem: ComboBoxInput { + id: comboBoxInput + myControl: myComboBox + text: myComboBox.editText + } + + indicator: CheckIndicator { + id: popupIndicator + myControl: myComboBox + myPopup: myComboBox.popup + x: comboBoxInput.x + comboBoxInput.width - StudioTheme.Values.border + y: 0 + width: StudioTheme.Values.squareComponentWidth + height: StudioTheme.Values.height + } + + background: Rectangle { + id: comboBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + x: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + width: myComboBox.width - actionIndicator.width + height: myComboBox.height + } + + // Set the initial value for __lastAcceptedText + Component.onCompleted: __lastAcceptedText = myComboBox.editText + + onAccepted: { + if (myComboBox.editText != __lastAcceptedText) { + var pos = find(myComboBox.editText) + activated(pos) + } + __lastAcceptedText = myComboBox.editText + } + + Timer { + id: myTimer + repeat: false + running: false + interval: 100 + onTriggered: myComboBox.compressedActivated() + } + + onActivated: myTimer.restart() + + delegate: ItemDelegate { + id: myItemDelegate + + width: comboBoxPopup.width - comboBoxPopup.leftPadding - comboBoxPopup.rightPadding + - (comboBoxPopupScrollBar.visible ? comboBoxPopupScrollBar.contentItem.implicitWidth + + 2 : 0) // TODO Magic number + height: StudioTheme.Values.height - 2 * StudioTheme.Values.border + padding: 0 + + contentItem: Text { + leftPadding: itemDelegateIconArea.width + text: modelData + color: StudioTheme.Values.themeTextColor + font: myComboBox.font + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + + Item { + id: itemDelegateIconArea + width: myItemDelegate.height + height: myItemDelegate.height + + T.Label { + id: itemDelegateIcon + text: StudioTheme.Constants.tickIcon + color: myItemDelegate.highlighted ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeInteraction + font.family: StudioTheme.Constants.iconFont.family + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + visible: myComboBox.currentIndex === index ? true : false + anchors.fill: parent + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + highlighted: myComboBox.highlightedIndex === index + + background: Rectangle { + id: itemDelegateBackground + x: 0 + y: 0 + width: myItemDelegate.width + height: myItemDelegate.height + color: myItemDelegate.highlighted ? StudioTheme.Values.themeInteraction : "transparent" + } + } + + popup: T.Popup { + id: comboBoxPopup + x: comboBoxInput.x + y: myComboBox.height - StudioTheme.Values.border + width: comboBoxInput.width + popupIndicator.width - StudioTheme.Values.border + // TODO Setting the height on the popup solved the problem with the popup of height 0, + // but it has the problem that it sometimes extend over the border of the actual window + // and is then cut off. + height: Math.min(contentItem.implicitHeight + comboBoxPopup.topPadding + + comboBoxPopup.bottomPadding, + myComboBox.Window.height - topMargin - bottomMargin, + StudioTheme.Values.maxComboBoxPopupHeight) + padding: StudioTheme.Values.border + margins: 0 // If not defined margin will be -1 + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: myComboBox.popup.visible ? myComboBox.delegateModel : null + currentIndex: myComboBox.highlightedIndex + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ControlScrollBar { + id: comboBoxPopupScrollBar + } + } + + background: Rectangle { + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeInteraction + border.width: StudioTheme.Values.border + } + + enter: Transition { + } + exit: Transition { + } + } + + states: [ + State { + name: "default" + when: !myComboBox.hover && !myComboBox.edit + PropertyChanges { + target: myComboBox + wheelEnabled: false + } + PropertyChanges { + target: comboBoxInput + selectByMouse: false + } + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "focus" + when: myComboBox.edit && !myComboBox.editable + PropertyChanges { + target: myComboBox + wheelEnabled: true + } + PropertyChanges { + target: comboBoxInput + focus: true + } + }, + State { + name: "edit" + when: myComboBox.edit && myComboBox.editable + PropertyChanges { + target: myComboBox + wheelEnabled: true + } + PropertyChanges { + target: comboBoxInput + selectByMouse: true + } + PropertyChanges { + target: comboBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + } + ] + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) + myComboBox.focus = false + } +} diff --git a/src/imports/StudioControls/ComboBoxInput.qml b/src/imports/StudioControls/ComboBoxInput.qml new file mode 100644 index 0000000..3485316 --- /dev/null +++ b/src/imports/StudioControls/ComboBoxInput.qml @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextInput { + id: textInput + + property T.Control myControl + + property bool edit: textInput.activeFocus + property bool drag: false + + z: 2 + font: myControl.font + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + leftPadding: StudioTheme.Values.inputHorizontalPadding + rightPadding: StudioTheme.Values.inputHorizontalPadding + + readOnly: !myControl.editable + validator: myControl.validator + inputMethodHints: myControl.inputMethodHints + selectByMouse: false + activeFocusOnPress: false + clip: true + + Rectangle { + id: textInputArea + x: 0 + y: 0 + z: -1 + width: textInput.width + height: StudioTheme.Values.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } + + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse + enabled: true + onTapped: { + if (textInput.readOnly) { + if (myControl.popup.opened) { + myControl.popup.close() + } else { + myControl.forceActiveFocus() + myControl.popup.open() + } + } else { + textInput.forceActiveFocus() + } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: myControl.hover = containsMouse + onPressed: mouse.accepted = false + } + + states: [ + State { + name: "default" + when: myControl.enabled && !textInput.edit + && !mouseArea.containsMouse && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: tapHandler + enabled: true + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myControl.hover && !textInput.edit && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "focus" + when: textInput.edit && !myControl.editable + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: textInput.edit && myControl.editable + extend: "focus" + PropertyChanges { + target: tapHandler + enabled: false + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/ContextMenu.qml b/src/imports/StudioControls/ContextMenu.qml new file mode 100644 index 0000000..9d76855 --- /dev/null +++ b/src/imports/StudioControls/ContextMenu.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 + +Menu { + id: contextMenu + + property Item myTextEdit + + MenuItem { + text: "Undo" + enabled: myTextEdit.canUndo + onTriggered: myTextEdit.undo() + /* shortcut: StandardKey.Undo Shortcuts in QQC2 seem to override global shortcuts */ + } + MenuItem { + text: "Redo" + enabled: myTextEdit.canRedo + onTriggered: myTextEdit.redo() + /* shortcut: StandardKey.Redo Shortcuts in QQC2 seem to override global shortcuts */ + } + + MenuSeparator { + } + + MenuItem { + text: "Copy" + enabled: myTextEdit.selectedText !== "" + onTriggered: myTextEdit.copy() + /* shortcut: StandardKey.Copy Shortcuts in QQC2 seem to override global shortcuts */ + } + MenuItem { + text: "Cut" + enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly + onTriggered: myTextEdit.cut() + /* shortcut: StandardKey.Cut Shortcuts in QQC2 seem to override global shortcuts */ + } + MenuItem { + text: "Paste" + enabled: myTextEdit.canPaste + onTriggered: myTextEdit.paste() + /* shortcut: StandardKey.Paste Shortcuts in QQC2 seem to override global shortcuts */ + } + MenuItem { + text: "Delete" + enabled: myTextEdit.selectedText !== "" + onTriggered: myTextEdit.remove(myTextEdit.selectionStart, + myTextEdit.selectionEnd) + /* shortcut: StandardKey.Delete Shortcuts in QQC2 seem to override global shortcuts */ + } + MenuItem { + text: "Clear" + enabled: myTextEdit.text !== "" + onTriggered: myTextEdit.clear() + /* shortcut: StandardKey.DeleteCompleteLine Shortcuts in QQC2 seem to override global shortcuts */ + } + + MenuSeparator { + } + + MenuItem { + text: "Select All" + enabled: myTextEdit.text !== "" + && myTextEdit.selectedText !== myTextEdit.text + onTriggered: myTextEdit.selectAll() + /* shortcut: StandardKey.SelectAll Shortcuts in QQC2 seem to override global shortcuts */ + } +} diff --git a/src/imports/StudioControls/ControlScrollBar.qml b/src/imports/StudioControls/ControlScrollBar.qml new file mode 100644 index 0000000..886e922 --- /dev/null +++ b/src/imports/StudioControls/ControlScrollBar.qml @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollBar { + id: control + + // This needs to be set, when using T.ScrollBar + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + active: true + interactive: true + visible: control.size < 1.0 || T.ScrollBar.AlwaysOn + + snapMode: T.ScrollBar.SnapAlways // TODO + policy: T.ScrollBar.AsNeeded + + padding: 1 // TODO 0 + size: 1.0 + position: 1.0 + //orientation: Qt.Vertical + + contentItem: Rectangle { + id: controlHandle + implicitWidth: 4 + implicitHeight: 4 + radius: width / 2 // TODO 0 + color: StudioTheme.Values.themeScrollBarHandle + } + + background: Rectangle { + id: controlTrack + color: StudioTheme.Values.themeScrollBarTrack + } +} diff --git a/src/imports/StudioControls/ExpandingSpacer.qml b/src/imports/StudioControls/ExpandingSpacer.qml new file mode 100644 index 0000000..9e48128 --- /dev/null +++ b/src/imports/StudioControls/ExpandingSpacer.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + +Item { + Layout.fillWidth: true +} diff --git a/src/imports/StudioControls/ItemDelegate.qml b/src/imports/StudioControls/ItemDelegate.qml new file mode 100644 index 0000000..c2190c5 --- /dev/null +++ b/src/imports/StudioControls/ItemDelegate.qml @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T + +T.ItemDelegate { + +} diff --git a/src/imports/StudioControls/Menu.qml b/src/imports/StudioControls/Menu.qml new file mode 100644 index 0000000..01a8684 --- /dev/null +++ b/src/imports/StudioControls/Menu.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Window 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Menu { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + font.family: StudioTheme.Constants.font.family + font.pixelSize: StudioTheme.Values.myFontSize + + margins: 0 + overlap: 1 + padding: 0 + + closePolicy: T.Popup.CloseOnPressOutside | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnEscape + + delegate: MenuItem { + } + + contentItem: ListView { + model: control.contentModel + interactive: Window.window ? contentHeight > Window.window.height : false + clip: false + currentIndex: control.currentIndex + } + + background: Rectangle { + implicitWidth: contentItem.childrenRect.width + implicitHeight: contentItem.childrenRect.height + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + } +} diff --git a/src/imports/StudioControls/MenuItem.qml b/src/imports/StudioControls/MenuItem.qml new file mode 100644 index 0000000..023f9b0 --- /dev/null +++ b/src/imports/StudioControls/MenuItem.qml @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme +import QtQuick.Controls 2.12 + +T.MenuItem { + id: control + + property int labelSpacing: StudioTheme.Values.contextMenuLabelSpacing + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max( + implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 0 + spacing: 0 + horizontalPadding: StudioTheme.Values.contextMenuHorizontalPadding + action: Action {} + + contentItem: Item { + Text { + id: textLabel + text: control.text + font: control.font + color: control.enabled ? StudioTheme.Values.themeTextColor : StudioTheme.Values.themeTextColorDisabled + anchors.verticalCenter: parent.verticalCenter + } + + Text { + id: shortcutLabel + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: shortcut.nativeText + font: control.font + color: textLabel.color + + Shortcut { + id: shortcut + property int shortcutWorkaround: control.action.shortcut ? control.action.shortcut : 0 + sequence: shortcutWorkaround + } + } + } + + background: Rectangle { + implicitWidth: textLabel.implicitWidth + control.labelSpacing + shortcutLabel.implicitWidth + + control.leftPadding + control.rightPadding + implicitHeight: StudioTheme.Values.height + x: StudioTheme.Values.border + y: StudioTheme.Values.border + width: control.menu.width - (StudioTheme.Values.border * 2) + height: control.height - (StudioTheme.Values.border * 2) + color: control.down ? control.palette.midlight : control.highlighted ? StudioTheme.Values.themeInteraction : "transparent" + } +} diff --git a/src/imports/StudioControls/MenuSeparator.qml b/src/imports/StudioControls/MenuSeparator.qml new file mode 100644 index 0000000..a2f2f57 --- /dev/null +++ b/src/imports/StudioControls/MenuSeparator.qml @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.MenuSeparator { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 0 + + contentItem: Rectangle { + width: control.parent.width + height: StudioTheme.Values.border + color: StudioTheme.Values.themeControlOutline + } +} diff --git a/src/imports/StudioControls/RealSliderPopup.qml b/src/imports/StudioControls/RealSliderPopup.qml new file mode 100644 index 0000000..d260940 --- /dev/null +++ b/src/imports/StudioControls/RealSliderPopup.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Popup { + id: sliderPopup + + property T.Control myControl + + dim: false + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + + background: Rectangle { + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeInteraction + } + + contentItem: T.Slider { + id: slider + anchors.fill: parent + + bottomPadding: 0 + topPadding: 0 + rightPadding: 3 + leftPadding: 3 + + from: myControl.realFrom + value: myControl.realValue + to: myControl.realTo + + focusPolicy: Qt.NoFocus + + handle: Rectangle { + x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width) + y: slider.topPadding + (slider.availableHeight / 2) - (height / 2) + width: StudioTheme.Values.sliderHandleWidth + height: StudioTheme.Values.sliderHandleHeight + radius: 0 + color: slider.pressed ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + } + + background: Rectangle { + x: slider.leftPadding + y: slider.topPadding + (slider.availableHeight / 2) - (height / 2) + width: slider.availableWidth + height: StudioTheme.Values.sliderTrackHeight + radius: 0 + color: StudioTheme.Values.themeSliderInactiveTrack + + Rectangle { + width: slider.visualPosition * parent.width + height: parent.height + color: StudioTheme.Values.themeSliderActiveTrack + radius: 0 + } + } + + onMoved: { + var currValue = myControl.value + myControl.realValue = slider.value + + if (currValue !== myControl.realValue) + myControl.realValueModified() + } + } +} diff --git a/src/imports/StudioControls/RealSpinBox.qml b/src/imports/StudioControls/RealSpinBox.qml new file mode 100644 index 0000000..d1d738e --- /dev/null +++ b/src/imports/StudioControls/RealSpinBox.qml @@ -0,0 +1,354 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.SpinBox { + id: mySpinBox + + property real realFrom: 0.0 + property real realTo: 99.0 + property real realValue: 1.0 + property real realStepSize: 1.0 + + property alias labelColor: spinBoxInput.color + property alias actionIndicator: actionIndicator + + property int decimals: 0 + + property real minStepSize: { + var tmpMinStepSize = Number((mySpinBox.realStepSize * 0.1).toFixed(mySpinBox.decimals)) + return (tmpMinStepSize) ? tmpMinStepSize : mySpinBox.realStepSize + } + property real maxStepSize: { + var tmpMaxStepSize = Number((mySpinBox.realStepSize * 10.0).toFixed(mySpinBox.decimals)) + return (tmpMaxStepSize < mySpinBox.realTo) ? tmpMaxStepSize : mySpinBox.realStepSize + } + + property bool edit: spinBoxInput.activeFocus + property bool hover: false // This property is used to indicate the global hover state + property bool drag: false + + property real realDragRange: realTo - realFrom + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property bool spinBoxIndicatorVisible: true + property real __spinBoxIndicatorWidth: StudioTheme.Values.smallRectWidth - 2 + * StudioTheme.Values.border + property real __spinBoxIndicatorHeight: StudioTheme.Values.height / 2 + - StudioTheme.Values.border + + property alias sliderIndicatorVisible: sliderIndicator.visible + property real __sliderIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __sliderIndicatorHeight: StudioTheme.Values.height + + signal realValueModified + signal compressedRealValueModified + signal dragStarted + signal dragEnded + + // Use custom wheel handling due to bugs + property bool __wheelEnabled: false + wheelEnabled: false + + width: StudioTheme.Values.squareComponentWidth * 5 + height: StudioTheme.Values.height + + leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width + - (spinBoxIndicatorVisible ? 0 : StudioTheme.Values.border) + rightPadding: sliderIndicator.width - (sliderIndicatorVisible ? StudioTheme.Values.border : 0) + + font.pixelSize: StudioTheme.Values.myFontSize + editable: true + + // Leave this in for now + from: -99 + value: 0 + to: 99 + + validator: DoubleValidator { + id: doubleValidator + locale: mySpinBox.locale.name + notation: DoubleValidator.StandardNotation + decimals: mySpinBox.decimals + bottom: Math.min(mySpinBox.realFrom, mySpinBox.realTo) + top: Math.max(mySpinBox.realFrom, mySpinBox.realTo) + } + + ActionIndicator { + id: actionIndicator + myControl: mySpinBox + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + up.indicator: RealSpinBoxIndicator { + id: spinBoxIndicatorUp + myControl: mySpinBox + iconFlip: -1 + visible: spinBoxIndicatorVisible + onRealReleased: mySpinBox.realIncrease() + onRealPressAndHold: mySpinBox.realIncrease() + x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + y: StudioTheme.Values.border + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + + realEnabled: (mySpinBox.realFrom < mySpinBox.realTo) ? (mySpinBox.realValue < mySpinBox.realTo) : (mySpinBox.realValue > mySpinBox.realTo) + } + + down.indicator: RealSpinBoxIndicator { + id: spinBoxIndicatorDown + myControl: mySpinBox + visible: spinBoxIndicatorVisible + onRealReleased: mySpinBox.realDecrease() + onRealPressAndHold: mySpinBox.realDecrease() + x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + + realEnabled: (mySpinBox.realFrom < mySpinBox.realTo) ? (mySpinBox.realValue > mySpinBox.realFrom) : (mySpinBox.realValue < mySpinBox.realFrom) + } + + contentItem: RealSpinBoxInput { + id: spinBoxInput + myControl: mySpinBox + validator: doubleValidator + } + + background: Rectangle { + id: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + x: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + width: mySpinBox.width - actionIndicator.width + height: mySpinBox.height + } + + CheckIndicator { + id: sliderIndicator + myControl: mySpinBox + myPopup: sliderPopup + x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border + width: sliderIndicator.visible ? __sliderIndicatorWidth : 0 + height: sliderIndicator.visible ? __sliderIndicatorHeight : 0 + visible: false // reasonable default + } + + RealSliderPopup { + id: sliderPopup + myControl: mySpinBox + x: spinBoxInput.x + y: StudioTheme.Values.height - StudioTheme.Values.border + width: spinBoxInput.width + sliderIndicator.width - StudioTheme.Values.border + height: StudioTheme.Values.sliderHeight + + enter: Transition { + } + exit: Transition { + } + } + + textFromValue: function (value, locale) { + return Number(mySpinBox.realValue).toLocaleString(locale, 'f', mySpinBox.decimals) + } + + valueFromText: function (text, locale) { + mySpinBox.setRealValue(Number.fromLocaleString(locale, spinBoxInput.text)) + return 0 + } + + states: [ + State { + name: "default" + when: mySpinBox.enabled && !mySpinBox.hover + && !mySpinBox.edit && !mySpinBox.drag + PropertyChanges { + target: mySpinBox + __wheelEnabled: false + } + PropertyChanges { + target: spinBoxInput + selectByMouse: false + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: mySpinBox.edit + PropertyChanges { + target: mySpinBox + __wheelEnabled: true + } + PropertyChanges { + target: spinBoxInput + selectByMouse: true + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: mySpinBox.drag + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !mySpinBox.enabled + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutlineDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] + + Timer { + id: myTimer + repeat: false + running: false + interval: 200 + onTriggered: mySpinBox.compressedRealValueModified() + } + + onRealValueChanged: { + spinBoxInput.text = mySpinBox.textFromValue(mySpinBox.realValue, mySpinBox.locale) + mySpinBox.value = 0 // Without setting value back to 0, it can happen that one of + // the indicator will be disabled due to range logic. + } + onRealValueModified: myTimer.restart() + onFocusChanged: mySpinBox.setValueFromInput() + onDisplayTextChanged: spinBoxInput.text = mySpinBox.displayText + onActiveFocusChanged: { + if (mySpinBox.activeFocus) + // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) + spinBoxInput.selectAll() + + if (sliderPopup.opened && !mySpinBox.activeFocus) + sliderPopup.close() + } + + Keys.onPressed: { + if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) { + event.accepted = true + + // Store current step size + var currStepSize = mySpinBox.realStepSize + + // Set realStepSize according to used modifier key + if (event.modifiers & Qt.ControlModifier) + mySpinBox.realStepSize = mySpinBox.minStepSize + + if (event.modifiers & Qt.ShiftModifier) + mySpinBox.realStepSize = mySpinBox.maxStepSize + + if (event.key === Qt.Key_Up) + mySpinBox.realIncrease() + else + mySpinBox.realDecrease() + + // Reset realStepSize + mySpinBox.realStepSize = currStepSize + } + + if (event.key === Qt.Key_Escape) + mySpinBox.focus = false + + // FIX: This is a temporary fix for QTBUG-74239 + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) + mySpinBox.setValueFromInput() + } + + function clamp(v, lo, hi) { + return (v < lo || v > hi) ? Math.min(Math.max(lo, v), hi) : v + } + + function setValueFromInput() { + // FIX: This is a temporary fix for QTBUG-74239 + var currValue = mySpinBox.realValue + + // Call the function but don't use return value. The realValue property + // will be implicitly set inside the function/procedure. + mySpinBox.valueFromText(spinBoxInput.text, mySpinBox.locale) + + if (mySpinBox.realValue !== currValue) { + mySpinBox.realValueModified() + } else { + // Check if input text differs in format from the current value + var tmpInputValue = mySpinBox.textFromValue(mySpinBox.realValue, mySpinBox.locale) + + if (tmpInputValue !== spinBoxInput.text) + spinBoxInput.text = tmpInputValue + } + } + + function setRealValue(value) { + mySpinBox.realValue = clamp(value, + mySpinBox.validator.bottom, + mySpinBox.validator.top) + } + + function realDecrease() { + // Store the current value for comparison + var currValue = mySpinBox.realValue + mySpinBox.valueFromText(spinBoxInput.text, mySpinBox.locale) + + setRealValue(mySpinBox.realValue - realStepSize) + + if (mySpinBox.realValue !== currValue) + mySpinBox.realValueModified() + } + + function realIncrease() { + // Store the current value for comparison + var currValue = mySpinBox.realValue + mySpinBox.valueFromText(spinBoxInput.text, mySpinBox.locale) + + setRealValue(mySpinBox.realValue + realStepSize) + + if (mySpinBox.realValue !== currValue) + mySpinBox.realValueModified() + } +} diff --git a/src/imports/StudioControls/RealSpinBoxIndicator.qml b/src/imports/StudioControls/RealSpinBoxIndicator.qml new file mode 100644 index 0000000..7cebe1c --- /dev/null +++ b/src/imports/StudioControls/RealSpinBoxIndicator.qml @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: spinBoxIndicator + + property T.Control myControl + + property bool hover: false + property bool pressed: false + property bool released: false + property bool realEnabled: true + + signal realPressed + signal realPressAndHold + signal realReleased + + property alias iconFlip: spinBoxIndicatorIconScale.yScale + + color: StudioTheme.Values.themeControlBackground + border.width: 0 + + onEnabledChanged: invalidateEnabled() + onRealEnabledChanged: { + invalidateEnabled() + if (spinBoxIndicator.realEnabled === false) + pressAndHoldTimer.stop() + } + + // This function is meant to synchronize enabled with realEnabled to avoid + // the internal logic messing with the actual state. + function invalidateEnabled() { + spinBoxIndicator.enabled = spinBoxIndicator.realEnabled + } + + Timer { + id: pressAndHoldTimer + repeat: true + running: false + interval: 100 + onTriggered: spinBoxIndicator.realPressAndHold() + } + + // This MouseArea is a workaround to avoid some hover state related bugs + // when using the actual signal 'up.hovered'. QTBUG-74688 + MouseArea { + id: spinBoxIndicatorMouseArea + + property bool pressedAndHeld: false + + anchors.fill: parent + // Shift the MouseArea down by 1 pixel due to potentially overlapping areas + anchors.topMargin: iconFlip < 0 ? 0 : 1 + anchors.bottomMargin: iconFlip < 0 ? 1 : 0 + hoverEnabled: true + pressAndHoldInterval: 500 + onContainsMouseChanged: spinBoxIndicator.hover = containsMouse + onContainsPressChanged: spinBoxIndicator.pressed = containsPress + onPressed: { + myControl.forceActiveFocus() + spinBoxIndicator.realPressed() + mouse.accepted = true + } + onPressAndHold: { + pressAndHoldTimer.restart() + pressedAndHeld = true + } + onReleased: { + // Only trigger real released when pressAndHold isn't active + if (!pressAndHoldTimer.running && containsMouse) + spinBoxIndicator.realReleased() + pressAndHoldTimer.stop() + mouse.accepted = true + pressedAndHeld = false + } + onEntered: { + if (pressedAndHeld) + pressAndHoldTimer.restart() + } + onExited: { + if (pressAndHoldTimer.running) + pressAndHoldTimer.stop() + } + } + + T.Label { + id: spinBoxIndicatorIcon + text: StudioTheme.Constants.upDownSquare2 + color: StudioTheme.Values.themeTextColor + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + font.family: StudioTheme.Constants.iconFont.family + anchors.fill: parent + transform: Scale { + id: spinBoxIndicatorIconScale + origin.x: 0 + origin.y: spinBoxIndicatorIcon.height / 2 + yScale: 1 + } + + states: [ + State { + name: "default" + when: myControl.enabled && spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColor + } + }, + State { + name: "disabled" + when: !myControl.enabled || !spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] + } + + states: [ + State { + name: "default" + when: myControl.enabled && !(spinBoxIndicator.hover + || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "hovered" + when: (spinBoxIndicator.hover || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: spinBoxIndicator.pressed + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: myControl.edit + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusEdit + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusDrag + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/RealSpinBoxInput.qml b/src/imports/StudioControls/RealSpinBoxInput.qml new file mode 100644 index 0000000..7de0eb7 --- /dev/null +++ b/src/imports/StudioControls/RealSpinBoxInput.qml @@ -0,0 +1,252 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextInput { + id: textInput + + property T.Control myControl + + property bool edit: textInput.activeFocus + property bool drag: false + + z: 2 + font: myControl.font + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + horizontalAlignment: Qt.AlignRight + verticalAlignment: Qt.AlignVCenter + leftPadding: StudioTheme.Values.inputHorizontalPadding + rightPadding: StudioTheme.Values.inputHorizontalPadding + + readOnly: !myControl.editable + validator: myControl.validator + inputMethodHints: myControl.inputMethodHints + selectByMouse: false + activeFocusOnPress: false + clip: true + + // TextInput focus needs to be set to activeFocus whenever it changes, + // otherwise TextInput will get activeFocus whenever the parent SpinBox gets + // activeFocus. This will lead to weird side effects. + onActiveFocusChanged: textInput.focus = activeFocus + + Rectangle { + id: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + x: 0 + y: 0 + z: -1 + width: textInput.width + height: StudioTheme.Values.height + } + + DragHandler { + id: dragHandler + target: null + acceptedDevices: PointerDevice.Mouse + enabled: true + + property real initialValue: myControl.realValue + property real multiplier: 1.0 + + onActiveChanged: { + if (dragHandler.active) { + dragHandler.initialValue = myControl.realValue + mouseArea.cursorShape = Qt.ClosedHandCursor // TODO + myControl.drag = true + myControl.dragStarted() + // Force focus on the non visible component to receive key events + dragModifierWorkaround.forceActiveFocus() + } else { + mouseArea.cursorShape = Qt.PointingHandCursor // TODO + myControl.drag = false + myControl.dragEnded() + // Avoid active focus on the component after dragging + dragModifierWorkaround.focus = false + textInput.focus = false + myControl.focus = false + } + } + onTranslationChanged: calcValue() + onMultiplierChanged: calcValue() + + function calcValue() { + var tmp = myControl.realDragRange / StudioTheme.Values.dragLength + var currValue = myControl.realValue + myControl.setRealValue(dragHandler.initialValue + (tmp * dragHandler.translation.x * dragHandler.multiplier)) + if (currValue !== myControl.realValue) + myControl.realValueModified() + } + } + + Item { + id: dragModifierWorkaround + Keys.onPressed: { + event.accepted = true + + if (event.modifiers & Qt.ControlModifier) + dragHandler.multiplier = 0.1 + + if (event.modifiers & Qt.ShiftModifier) + dragHandler.multiplier = 10.0 + } + Keys.onReleased: { + event.accepted = true + dragHandler.multiplier = 1.0 + } + } + + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse + enabled: true + onTapped: { + textInput.forceActiveFocus() + textInput.deselect() // QTBUG-75862 + } + } + + MouseArea { + id: mouseArea + + property real stepSize: myControl.realStepSize + + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: myControl.hover = containsMouse + onPressed: mouse.accepted = false + onWheel: { + if (!myControl.__wheelEnabled) + return + + // Set stepSize according to used modifier key + if (wheel.modifiers & Qt.ControlModifier) + mouseArea.stepSize = myControl.minStepSize + + if (wheel.modifiers & Qt.ShiftModifier) + mouseArea.stepSize = myControl.maxStepSize + + var currValue = myControl.realValue + myControl.valueFromText(textInput.text, myControl.locale) + myControl.setRealValue(myControl.realValue + (wheel.angleDelta.y / 120.0 * mouseArea.stepSize)) + + if (currValue !== myControl.realValue) + myControl.realValueModified() + + // Reset stepSize + mouseArea.stepSize = myControl.realStepSize + } + } + + states: [ + State { + name: "default" + when: myControl.enabled && !textInput.edit + && !mouseArea.containsMouse && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: dragHandler + enabled: true + } + PropertyChanges { + target: tapHandler + enabled: true + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myControl.hover && !textInput.edit && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: textInput.edit && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: dragHandler + enabled: false + } + PropertyChanges { + target: tapHandler + enabled: false + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/ScrollBar.qml b/src/imports/StudioControls/ScrollBar.qml new file mode 100644 index 0000000..f1bb045 --- /dev/null +++ b/src/imports/StudioControls/ScrollBar.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollBar { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 0 + size: 1.0 + position: 1.0 + active: true + interactive: true + visible: control.size < 1.0 + + snapMode: T.ScrollBar.NoSnap + policy: T.ScrollBar.AsNeeded + + contentItem: Rectangle { + id: controlHandle + implicitWidth: 10 + implicitHeight: 10 + radius: 0 + color: "#595b5c" //StudioTheme.Values.themeScrollBarHandle + } + + background: Rectangle { + id: controlTrack + color: "#191919" //StudioTheme.Values.themeScrollBarTrack + } +} diff --git a/src/imports/StudioControls/ScrollView.qml b/src/imports/StudioControls/ScrollView.qml new file mode 100644 index 0000000..f8a1875 --- /dev/null +++ b/src/imports/StudioControls/ScrollView.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollView { + id: control + + property alias horizontalThickness: horizontalScrollBar.height + property alias verticalThickness: verticalScrollBar.width + property bool bothVisible: verticalScrollBar.visible + && horizontalScrollBar.visible + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + anchors.fill: parent + + rightPadding: verticalScrollBar.visible ? verticalThickness : 0 + bottomPadding: horizontalScrollBar.visible ? horizontalThickness : 0 + + ScrollBar.vertical: ScrollBar { + id: verticalScrollBar + parent: control + x: control.width - verticalThickness + y: 0 + height: control.availableHeight + active: horizontalScrollBar.active + } + + ScrollBar.horizontal: ScrollBar { + id: horizontalScrollBar + parent: control + x: 0 + y: control.height - horizontalThickness + width: control.availableWidth + active: verticalScrollBar.active + } + + contentItem: Flickable { + boundsMovement: Flickable.StopAtBounds + boundsBehavior: Flickable.StopAtBounds + interactive: false + } +} diff --git a/src/imports/StudioControls/SecondColumnLayout.qml b/src/imports/StudioControls/SecondColumnLayout.qml new file mode 100644 index 0000000..d5c917f --- /dev/null +++ b/src/imports/StudioControls/SecondColumnLayout.qml @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + +RowLayout { + Layout.fillWidth: true + spacing: 4 +} diff --git a/src/imports/StudioControls/Section.qml b/src/imports/StudioControls/Section.qml new file mode 100644 index 0000000..98a163a --- /dev/null +++ b/src/imports/StudioControls/Section.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import StudioTheme 1.0 as StudioTheme + +Item { + id: section + property alias caption: label.text + property int leftPadding: 8 + property int topPadding: 4 + property int rightPadding: 0 + + property int animationDuration: 0 + + property bool expanded: true + + clip: true + + Rectangle { + id: header + height: StudioTheme.Values.height + + anchors.left: parent.left + anchors.right: parent.right + + color: StudioTheme.Values.themeControlBackground + + SectionLabel { + id: label + anchors.verticalCenter: parent.verticalCenter + color: StudioTheme.Values.themeTextColor + x: 22 + //font.bold: true + font.pixelSize: StudioTheme.Values.myFontSize + // TODO font size? + } + + SectionLabel { + id: arrow + width: StudioTheme.Values.spinControlIconSizeMulti + height: StudioTheme.Values.spinControlIconSizeMulti + text: StudioTheme.Constants.upDownSquare2 + color: StudioTheme.Values.themeTextColor + renderType: Text.NativeRendering + anchors.left: parent.left + anchors.leftMargin: 4 + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + font.family: StudioTheme.Constants.iconFont.family + Behavior on rotation { + NumberAnimation { + easing.type: Easing.OutCubic + duration: animationDuration + } + } + } + + MouseArea { + anchors.fill: parent + onClicked: { + section.animationDuration = 120 + section.expanded = !section.expanded + if (!section.expanded) // TODO + section.forceActiveFocus() + } + } + } + + default property alias __content: row.children + + readonly property alias contentItem: row + + implicitHeight: Math.round(row.height + header.height) + + Row { + id: row + anchors.left: parent.left + anchors.leftMargin: leftPadding + anchors.right: parent.right + anchors.rightMargin: rightPadding + anchors.top: header.bottom + anchors.topMargin: topPadding + } + + Behavior on implicitHeight { + NumberAnimation { + easing.type: Easing.OutCubic + duration: animationDuration + } + } + + states: [ + State { + name: "Collapsed" + when: !section.expanded + PropertyChanges { + target: section + implicitHeight: header.height + } + PropertyChanges { + target: arrow + rotation: -90 + } + } + ] +} diff --git a/src/imports/StudioControls/SectionLabel.qml b/src/imports/StudioControls/SectionLabel.qml new file mode 100644 index 0000000..73fec21 --- /dev/null +++ b/src/imports/StudioControls/SectionLabel.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Label { + id: label + + //property alias tooltip: toolTipArea.tooltip + // workaround because PictureSpecifics.qml still use this + //property alias toolTip: toolTipArea.tooltip + + width: Math.max(Math.min(240, parent.width - 220), 80) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.myFontSize // TODO + elide: Text.ElideRight + + Layout.preferredWidth: width + Layout.minimumWidth: width + Layout.maximumWidth: width +/* + ToolTipArea { + id: toolTipArea + anchors.fill: parent + tooltip: label.text + } +*/ +} diff --git a/src/imports/StudioControls/SectionLayout.qml b/src/imports/StudioControls/SectionLayout.qml new file mode 100644 index 0000000..22054fe --- /dev/null +++ b/src/imports/StudioControls/SectionLayout.qml @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + +GridLayout { + columns: 2 + columnSpacing: 12 + rowSpacing: 4 + width: parent.width - 16 +} diff --git a/src/imports/StudioControls/Slider.qml b/src/imports/StudioControls/Slider.qml new file mode 100644 index 0000000..e8cfe2a --- /dev/null +++ b/src/imports/StudioControls/Slider.qml @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Shapes 1.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Slider { + id: slider + + property int decimals: 0 + property bool labels: true + property bool tickMarks: false + property real tickMarkStepSize: 0.0 // StepSize bug QTBUG-76136 + property real tickMarkWidth: 1.0 + property real tickMarkHeight: 4.0 + readonly property int tickMarkCount: tickMarkStepSize + !== 0.0 ? (to - from) / tickMarkStepSize + 1 : 0 + readonly property real tickMarkSpacing: tickMarkCount + !== 0 ? (sliderTrack.width - tickMarkWidth + * tickMarkCount) / (tickMarkCount - 1) : 0.0 + + property string __activeColor: StudioTheme.Values.themeSliderActiveTrack + property string __inactiveColor: StudioTheme.Values.themeSliderInactiveTrack + + property bool hover: false // This property is used to indicate the global hover state + property bool edit: slider.activeFocus + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitHandleWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitHandleHeight + topPadding + bottomPadding, + StudioTheme.Values.height) + padding: 0 + leftPadding: actionIndicator.width + - (actionIndicatorVisible ? StudioTheme.Values.border + - StudioTheme.Values.sliderPadding : 0) + + wheelEnabled: false + + ActionIndicator { + id: actionIndicator + myControl: slider + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + handle: Rectangle { + id: sliderHandle + x: slider.leftPadding + (slider.visualPosition * slider.availableWidth) + - (sliderHandle.width / 2) + y: slider.topPadding + (slider.availableHeight / 2) - (sliderHandle.height / 2) + z: 20 + implicitWidth: StudioTheme.Values.sliderHandleWidth + implicitHeight: StudioTheme.Values.sliderHandleHeight + color: StudioTheme.Values.themeSliderHandle + + Shape { + id: sliderHandleLabelPointer + + property real __width: StudioTheme.Values.sliderPointerWidth + property real __height: StudioTheme.Values.sliderPointerHeight + property bool antiAlias: true + + layer.enabled: antiAlias + layer.smooth: antiAlias + layer.textureSize: Qt.size(width * 2, height * 2) + + implicitWidth: __width + implicitHeight: __height + + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: sliderHandleLabelBackground.bottom + + ShapePath { + id: sliderHandleLabelPointerPath + strokeColor: "transparent" + strokeWidth: 0 + fillColor: StudioTheme.Values.themeInteraction + + startX: 0 + startY: 0 + + PathLine { + x: sliderHandleLabelPointer.__width + y: 0 + } + PathLine { + x: sliderHandleLabelPointer.__width / 2 + y: sliderHandleLabelPointer.__height + } + } + } + + Rectangle { + id: sliderHandleLabelBackground + x: -(sliderHandleLabelBackground.width / 2) + (sliderHandle.width / 2) + width: makeEven( + sliderHandleLabel.width + StudioTheme.Values.inputHorizontalPadding) + height: sliderHandleLabel.height + anchors.bottom: parent.top + anchors.bottomMargin: StudioTheme.Values.sliderMargin + color: StudioTheme.Values.themeInteraction + + Text { + id: sliderHandleLabel + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + text: Number.parseFloat(slider.value).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + } + } + } + + function makeEven(value) { + var v = Math.round(value) + return (v % 2 === 0) ? v : v + 1 + } + + background: Rectangle { + id: sliderTrack + x: slider.leftPadding + y: slider.topPadding + slider.availableHeight / 2 - height / 2 + width: slider.availableWidth + height: StudioTheme.Values.sliderTrackHeight + color: __inactiveColor + + Rectangle { + width: slider.visualPosition * parent.width + height: parent.height + color: __activeColor + } + } + + Item { + id: tickmarkBounds + x: sliderTrack.x + y: sliderTrack.y + + Text { + id: tickmarkFromLabel + x: 0 + y: StudioTheme.Values.sliderPadding + text: Number.parseFloat(slider.from).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + visible: slider.labels + } + + Text { + id: tickmarkToLabel + x: slider.availableWidth - width + y: StudioTheme.Values.sliderPadding + text: Number.parseFloat(slider.to).toFixed(slider.decimals) + color: StudioTheme.Values.themeTextColor + font.pixelSize: StudioTheme.Values.sliderFontSize + visible: slider.labels + } + + Row { + id: tickmarkRow + spacing: tickMarkSpacing + visible: slider.tickMarks + + Repeater { + id: tickmarkRepeater + model: tickMarkCount + delegate: Rectangle { + implicitWidth: tickMarkWidth + implicitHeight: StudioTheme.Values.sliderTrackHeight + color: x < (slider.visualPosition + * slider.availableWidth) ? __inactiveColor : __activeColor + } + } + } + } + + MouseArea { + id: mouseArea + x: actionIndicator.width + y: 0 + width: slider.width - actionIndicator.width + height: slider.height + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: slider.hover = containsMouse + onPressed: mouse.accepted = false + } + + states: [ + State { + name: "default" + when: slider.enabled && !slider.hover && !slider.edit + PropertyChanges { + target: slider + wheelEnabled: false + } + }, + State { + name: "hovered" + when: slider.enabled && slider.hover && !slider.edit + PropertyChanges { + target: slider + __activeColor: StudioTheme.Values.themeSliderActiveTrackHover + __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackHover + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeSliderHandleHover + } + }, + State { + name: "focus" + when: slider.enabled && slider.edit + PropertyChanges { + target: slider + wheelEnabled: true + __activeColor: StudioTheme.Values.themeSliderActiveTrackFocus + __inactiveColor: StudioTheme.Values.themeSliderInactiveTrackFocus + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeSliderHandleFocus + } + }, + State { + name: "disabled" + when: !slider.enabled + PropertyChanges { + target: tickmarkFromLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: tickmarkToLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: sliderHandleLabel + color: StudioTheme.Values.themeTextColorDisabled + } + PropertyChanges { + target: slider + __activeColor: StudioTheme.Values.themeControlBackgroundDisabled + __inactiveColor: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandleLabelBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandleLabelPointerPath + fillColor: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: sliderHandle + color: StudioTheme.Values.themeControlBackgroundDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/SliderPopup.qml b/src/imports/StudioControls/SliderPopup.qml new file mode 100644 index 0000000..a80ff78 --- /dev/null +++ b/src/imports/StudioControls/SliderPopup.qml @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.Popup { + id: sliderPopup + + property T.Control myControl + + dim: false + closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent + + background: Rectangle { + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeInteraction + } + + contentItem: T.Slider { + id: slider + anchors.fill: parent + + bottomPadding: 0 + topPadding: 0 + rightPadding: 3 + leftPadding: 3 + + from: myControl.from + value: myControl.value + to: myControl.to + + focusPolicy: Qt.NoFocus + + handle: Rectangle { + x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width) + y: slider.topPadding + (slider.availableHeight / 2) - (height / 2) + width: StudioTheme.Values.sliderHandleWidth + height: StudioTheme.Values.sliderHandleHeight + radius: 0 + color: slider.pressed ? StudioTheme.Values.themeInteraction : StudioTheme.Values.themeControlOutline + } + + background: Rectangle { + x: slider.leftPadding + y: slider.topPadding + (slider.availableHeight / 2) - (height / 2) + width: slider.availableWidth + height: StudioTheme.Values.sliderTrackHeight + radius: 0 + color: StudioTheme.Values.themeSliderInactiveTrack + + Rectangle { + width: slider.visualPosition * parent.width + height: parent.height + color: StudioTheme.Values.themeSliderActiveTrack + radius: 0 + } + } + + onMoved: { + var currValue = myControl.value + myControl.value = slider.value + + if (currValue !== myControl.value) + myControl.valueModified() + } + } + + onOpened: { + // Check if value is in sync with text input, if not sync it! + var val = myControl.valueFromText(myControl.contentItem.text, + myControl.locale) + if (myControl.value !== val) { + myControl.value = val + myControl.valueModified() + } + } +} diff --git a/src/imports/StudioControls/SpinBox.qml b/src/imports/StudioControls/SpinBox.qml new file mode 100644 index 0000000..60d35ac --- /dev/null +++ b/src/imports/StudioControls/SpinBox.qml @@ -0,0 +1,329 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.SpinBox { + id: mySpinBox + + property alias labelColor: spinBoxInput.color + property alias actionIndicator: actionIndicator + + property int decimals: 0 + property int factor: Math.pow(10, decimals) + + property real minStepSize: 1 + property real maxStepSize: 10 + + property bool edit: spinBoxInput.activeFocus + property bool hover: false // This property is used to indicate the global hover state + property bool drag: false + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property bool spinBoxIndicatorVisible: true + property real __spinBoxIndicatorWidth: StudioTheme.Values.smallRectWidth - (2 + * StudioTheme.Values.border) + property real __spinBoxIndicatorHeight: (StudioTheme.Values.height / 2) + - StudioTheme.Values.border + + property alias sliderIndicatorVisible: sliderIndicator.visible + property real __sliderIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __sliderIndicatorHeight: StudioTheme.Values.height + + signal compressedValueModified + + // Use custom wheel handling due to bugs + property bool __wheelEnabled: false + wheelEnabled: false + + width: StudioTheme.Values.squareComponentWidth * 5 + height: StudioTheme.Values.height + + leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width + - (spinBoxIndicatorVisible ? 0 : StudioTheme.Values.border) + rightPadding: sliderIndicator.width - (sliderIndicatorVisible ? StudioTheme.Values.border : 0) + + font.pixelSize: StudioTheme.Values.myFontSize + editable: true + validator: mySpinBox.decimals ? doubleValidator : intValidator + + DoubleValidator { + id: doubleValidator + locale: mySpinBox.locale.name + notation: DoubleValidator.StandardNotation + decimals: mySpinBox.decimals + bottom: Math.min(mySpinBox.from, mySpinBox.to) / mySpinBox.factor + top: Math.max(mySpinBox.from, mySpinBox.to) / mySpinBox.factor + } + + IntValidator { + id: intValidator + locale: mySpinBox.locale.name + bottom: Math.min(mySpinBox.from, mySpinBox.to) + top: Math.max(mySpinBox.from, mySpinBox.to) + } + + ActionIndicator { + id: actionIndicator + myControl: mySpinBox + + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + up.indicator: SpinBoxIndicator { + id: spinBoxIndicatorUp + myControl: mySpinBox + + visible: spinBoxIndicatorVisible + //hover: mySpinBox.up.hovered // TODO QTBUG-74688 + pressed: mySpinBox.up.pressed + iconFlip: -1 + + x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + y: StudioTheme.Values.border + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + + enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value < mySpinBox.to : mySpinBox.value > mySpinBox.to + } + + down.indicator: SpinBoxIndicator { + id: spinBoxIndicatorDown + myControl: mySpinBox + + visible: spinBoxIndicatorVisible + //hover: mySpinBox.down.hovered // TODO QTBUG-74688 + pressed: mySpinBox.down.pressed + + x: actionIndicator.width + (actionIndicatorVisible ? 0 : StudioTheme.Values.border) + y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height + width: spinBoxIndicatorVisible ? __spinBoxIndicatorWidth : 0 + height: spinBoxIndicatorVisible ? __spinBoxIndicatorHeight : 0 + + enabled: (mySpinBox.from < mySpinBox.to) ? mySpinBox.value > mySpinBox.from : mySpinBox.value < mySpinBox.from + } + + contentItem: SpinBoxInput { + id: spinBoxInput + myControl: mySpinBox + } + + background: Rectangle { + id: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + x: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + width: mySpinBox.width - actionIndicator.width + height: mySpinBox.height + } + + CheckIndicator { + id: sliderIndicator + myControl: mySpinBox + myPopup: sliderPopup + + x: spinBoxInput.x + spinBoxInput.width - StudioTheme.Values.border + width: sliderIndicator.visible ? __sliderIndicatorWidth : 0 + height: sliderIndicator.visible ? __sliderIndicatorHeight : 0 + visible: false // reasonable default + } + + SliderPopup { + id: sliderPopup + myControl: mySpinBox + + x: spinBoxInput.x + y: StudioTheme.Values.height - StudioTheme.Values.border + width: spinBoxInput.width + sliderIndicator.width - StudioTheme.Values.border + height: StudioTheme.Values.sliderHeight + + enter: Transition { + } + exit: Transition { + } + } + + textFromValue: function (value, locale) { + return Number(value / mySpinBox.factor).toLocaleString(locale, 'f', + mySpinBox.decimals) + } + + valueFromText: function (text, locale) { + return Number.fromLocaleString(locale, text) * mySpinBox.factor + } + + states: [ + State { + name: "default" + when: mySpinBox.enabled && !mySpinBox.hover + && !mySpinBox.edit && !mySpinBox.drag + PropertyChanges { + target: mySpinBox + __wheelEnabled: false + } + PropertyChanges { + target: spinBoxInput + selectByMouse: false + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutline + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: mySpinBox.edit + PropertyChanges { + target: mySpinBox + __wheelEnabled: true + } + PropertyChanges { + target: spinBoxInput + selectByMouse: true + } + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "drag" + when: mySpinBox.drag + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeInteraction + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !mySpinBox.enabled + PropertyChanges { + target: spinBoxBackground + color: StudioTheme.Values.themeControlOutlineDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] + + Timer { + id: myTimer + repeat: false + running: false + interval: 100 + onTriggered: mySpinBox.compressedValueModified() + } + + onValueModified: myTimer.restart() + onFocusChanged: mySpinBox.setValueFromInput() + onDisplayTextChanged: spinBoxInput.text = mySpinBox.displayText + onActiveFocusChanged: { + if (mySpinBox.activeFocus) + // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason) + spinBoxInput.selectAll() + + if (sliderPopup.opened && !mySpinBox.activeFocus) + sliderPopup.close() + } + + Keys.onPressed: { + if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) { + event.accepted = true + + // Store current step size + var currStepSize = mySpinBox.stepSize + + if (event.modifiers & Qt.ControlModifier) + mySpinBox.stepSize = mySpinBox.minStepSize + + if (event.modifiers & Qt.ShiftModifier) + mySpinBox.stepSize = mySpinBox.maxStepSize + + // Check if value is in sync with text input, if not sync it! + var val = mySpinBox.valueFromText(spinBoxInput.text, + mySpinBox.locale) + if (mySpinBox.value !== val) + mySpinBox.value = val + + var currValue = mySpinBox.value + + if (event.key === Qt.Key_Up) + mySpinBox.increase() + else + mySpinBox.decrease() + + if (currValue !== mySpinBox.value) + mySpinBox.valueModified() + + // Reset step size + mySpinBox.stepSize = currStepSize + } + + if (event.key === Qt.Key_Escape) + mySpinBox.focus = false + + // FIX: This is a temporary fix for QTBUG-74239 + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) + mySpinBox.setValueFromInput() + } + + function clamp(v, lo, hi) { + if (v < lo || v > hi) + return Math.min(Math.max(lo, v), hi) + + return v + } + + function setValueFromInput() { + // FIX: This is a temporary fix for QTBUG-74239 + var currValue = mySpinBox.value + + if (!spinBoxInput.acceptableInput) + mySpinBox.value = clamp(valueFromText(spinBoxInput.text, + mySpinBox.locale), + mySpinBox.validator.bottom * mySpinBox.factor, + mySpinBox.validator.top * mySpinBox.factor) + else + mySpinBox.value = valueFromText(spinBoxInput.text, + mySpinBox.locale) + + if (spinBoxInput.text !== mySpinBox.displayText) + spinBoxInput.text = mySpinBox.displayText + + if (mySpinBox.value !== currValue) + mySpinBox.valueModified() + } +} diff --git a/src/imports/StudioControls/SpinBoxIndicator.qml b/src/imports/StudioControls/SpinBoxIndicator.qml new file mode 100644 index 0000000..3f27286 --- /dev/null +++ b/src/imports/StudioControls/SpinBoxIndicator.qml @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Rectangle { + id: spinBoxIndicator + + property T.Control myControl + + property bool hover: false + property bool pressed: false + + property alias iconFlip: spinBoxIndicatorIconScale.yScale + + color: StudioTheme.Values.themeControlBackground + border.width: 0 + + // This MouseArea is a workaround to avoid some hover state related bugs + // when using the actual signal 'up.hovered'. QTBUG-74688 + MouseArea { + id: spinBoxIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: spinBoxIndicator.hover = containsMouse + onPressed: { + myControl.forceActiveFocus() + mouse.accepted = false + } + } + + T.Label { + id: spinBoxIndicatorIcon + text: StudioTheme.Constants.upDownSquare2 + color: StudioTheme.Values.themeTextColor + renderType: Text.NativeRendering + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: StudioTheme.Values.spinControlIconSizeMulti + font.family: StudioTheme.Constants.iconFont.family + anchors.fill: parent + transform: Scale { + id: spinBoxIndicatorIconScale + origin.x: 0 + origin.y: spinBoxIndicatorIcon.height / 2 + yScale: 1 + } + } + + states: [ + State { + name: "default" + when: myControl.enabled && !(spinBoxIndicator.hover + || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag && spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackground + } + }, + State { + name: "hovered" + when: (spinBoxIndicator.hover || myControl.hover) + && !spinBoxIndicator.pressed && !myControl.edit + && !myControl.drag && spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeHoverHighlight + } + }, + State { + name: "pressed" + when: spinBoxIndicator.pressed && spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "edit" + when: myControl.edit && spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusEdit + } + }, + State { + name: "drag" + when: myControl.drag && spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeFocusDrag + } + }, + State { + name: "disabled" + when: !myControl.enabled || !spinBoxIndicator.enabled + PropertyChanges { + target: spinBoxIndicator + color: StudioTheme.Values.themeControlBackgroundDisabled + } + PropertyChanges { + target: spinBoxIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/SpinBoxInput.qml b/src/imports/StudioControls/SpinBoxInput.qml new file mode 100644 index 0000000..50b4a06 --- /dev/null +++ b/src/imports/StudioControls/SpinBoxInput.qml @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextInput { + id: textInput + + property T.Control myControl + + property bool edit: textInput.activeFocus + property bool drag: false + + z: 2 + font: myControl.font + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + horizontalAlignment: Qt.AlignRight + verticalAlignment: Qt.AlignVCenter + leftPadding: StudioTheme.Values.inputHorizontalPadding + rightPadding: StudioTheme.Values.inputHorizontalPadding + + readOnly: !myControl.editable + validator: myControl.validator + inputMethodHints: myControl.inputMethodHints + selectByMouse: false + activeFocusOnPress: false + clip: true + + // TextInput focus needs to be set to activeFocus whenever it changes, + // otherwise TextInput will get activeFocus whenever the parent SpinBox gets + // activeFocus. This will lead to weird side effects. + onActiveFocusChanged: textInput.focus = activeFocus + + Rectangle { + id: textInputArea + + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + + x: 0 + y: 0 + z: -1 + width: textInput.width + height: StudioTheme.Values.height + } + + DragHandler { + id: dragHandler + target: null + acceptedDevices: PointerDevice.Mouse + enabled: true + + property int initialValue: 0 + + onActiveChanged: { + if (active) { + initialValue = myControl.value + mouseArea.cursorShape = Qt.ClosedHandCursor + myControl.drag = true + } else { + mouseArea.cursorShape = Qt.PointingHandCursor + myControl.drag = false + } + } + onTranslationChanged: { + var currValue = myControl.value + myControl.value = initialValue + translation.x + + if (currValue !== myControl.value) + myControl.valueModified() + } + } + + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse + enabled: true + onTapped: { + textInput.forceActiveFocus() + textInput.deselect() // QTBUG-75862 + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton + cursorShape: Qt.PointingHandCursor + // Sets the global hover + onContainsMouseChanged: myControl.hover = containsMouse + onPressed: mouse.accepted = false + onWheel: { + if (!myControl.__wheelEnabled) + return + + var val = myControl.valueFromText(textInput.text, myControl.locale) + if (myControl.value !== val) + myControl.value = val + + var currValue = myControl.value + myControl.value += wheel.angleDelta.y / 120 + + if (currValue !== myControl.value) + myControl.valueModified() + } + } + + states: [ + State { + name: "default" + when: myControl.enabled && !textInput.edit + && !mouseArea.containsMouse && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: dragHandler + enabled: true + } + PropertyChanges { + target: tapHandler + enabled: true + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myControl.hover && !textInput.edit && !myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: textInput.edit + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: dragHandler + enabled: false + } + PropertyChanges { + target: tapHandler + enabled: false + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "drag" + when: myControl.drag + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeFocusDrag + border.color: StudioTheme.Values.themeInteraction + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: textInputArea + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: textInput + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/TextArea.qml b/src/imports/StudioControls/TextArea.qml new file mode 100644 index 0000000..1af1758 --- /dev/null +++ b/src/imports/StudioControls/TextArea.qml @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +TextField { + id: myTextField + + property real relativePopupX: 0 // TODO Maybe call it leftPadding + property real popupWidth: myTextField.width + property string txtStorage + + property int temp: 0 + + T.Popup { + id: popup + x: myTextField.relativePopupX + y: myTextField.height - StudioTheme.Values.border + width: myTextField.popupWidth + height: scrollView.height + background: Rectangle { + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + border.width: StudioTheme.Values.border + } + + contentItem: TextAreaScrollView { + id: scrollView + padding: 0 + height: Math.min(textAreaPopup.contentHeight + scrollView.topPadding + + scrollView.bottomPadding, + StudioTheme.Values.maxTextAreaPopupHeight) + ScrollBar.horizontal.policy: ScrollBar.AlwaysOn + ScrollBar.vertical.policy: ScrollBar.AlwaysOn + + T.TextArea { + id: textAreaPopup + padding: 10 + width: textAreaPopup.contentWidth + textAreaPopup.leftPadding + + textAreaPopup.rightPadding + anchors.fill: parent + font.pixelSize: StudioTheme.Values.myFontSize + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + selectByMouse: true + persistentSelection: textAreaPopup.focus + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + cursorShape: Qt.IBeamCursor + acceptedButtons: Qt.RightButton + onPressed: contextMenu.popup(textAreaPopup) + } + } + } + + ContextMenu { + id: contextMenu + myTextEdit: textAreaPopup + } + + AbstractButton { + id: acceptButton + x: popup.width - acceptButton.width + y: popup.height - StudioTheme.Values.border + width: Math.round(StudioTheme.Values.smallRectWidth) + height: Math.round(StudioTheme.Values.smallRectWidth) + buttonIcon: StudioTheme.Constants.tickIcon + } + + AbstractButton { + id: discardButton + x: popup.width - acceptButton.width - discardButton.width + StudioTheme.Values.border + y: popup.height - StudioTheme.Values.border + width: Math.round(StudioTheme.Values.smallRectWidth) + height: Math.round(StudioTheme.Values.smallRectWidth) + buttonIcon: StudioTheme.Constants.closeCross + } + + Component.onCompleted: { + storeAndFormatTextInput(myTextField.text) + } + + onOpened: { + textAreaPopup.text = txtStorage + myTextField.clear() + } + + onClosed: { + storeAndFormatTextInput(textAreaPopup.text) + myTextField.forceActiveFocus() + textAreaPopup.deselect() + } + } + + function storeAndFormatTextInput(inputText) { + txtStorage = inputText + var pos = txtStorage.search(/\n/g) + var sliceAt = Math.min(pos, 15) + myTextField.text = txtStorage.slice(0, sliceAt).padEnd(sliceAt + 3, '.') + } + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) + popup.opened ? popup.close() : myTextField.focus = false + + if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) + && !popup.opened) { + popup.open() + textAreaPopup.forceActiveFocus() + } + } +} diff --git a/src/imports/StudioControls/TextAreaScrollView.qml b/src/imports/StudioControls/TextAreaScrollView.qml new file mode 100644 index 0000000..2975622 --- /dev/null +++ b/src/imports/StudioControls/TextAreaScrollView.qml @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.ScrollView { + id: control + + property alias horizontalThickness: horizontalScrollBar.height + property alias verticalThickness: verticalScrollBar.width + property bool bothVisible: verticalScrollBar.visible + && horizontalScrollBar.visible + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + + ScrollBar.vertical: ControlScrollBar { + id: verticalScrollBar + parent: control + x: control.width - verticalScrollBar.width - StudioTheme.Values.border + y: StudioTheme.Values.border + height: control.availableHeight - (2 * StudioTheme.Values.border) + - (control.bothVisible ? control.horizontalThickness : 0) + active: control.ScrollBar.horizontal.active + } + + ScrollBar.horizontal: ControlScrollBar { + id: horizontalScrollBar + parent: control + x: StudioTheme.Values.border + y: control.height - horizontalScrollBar.height - StudioTheme.Values.border + width: control.availableWidth - (2 * StudioTheme.Values.border) + - (control.bothVisible ? control.verticalThickness : 0) + active: control.ScrollBar.vertical.active + } +} diff --git a/src/imports/StudioControls/TextField.qml b/src/imports/StudioControls/TextField.qml new file mode 100644 index 0000000..7c14e83 --- /dev/null +++ b/src/imports/StudioControls/TextField.qml @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +T.TextField { + id: myTextField + + property alias actionIndicator: actionIndicator + property alias translationIndicator: translationIndicator + + property bool edit: myTextField.activeFocus + property bool hover: false // This property is used to indicate the global hover state + + property alias actionIndicatorVisible: actionIndicator.visible + property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __actionIndicatorHeight: StudioTheme.Values.height + + property alias translationIndicatorVisible: translationIndicator.visible + property real __translationIndicatorWidth: StudioTheme.Values.squareComponentWidth + property real __translationIndicatorHeight: StudioTheme.Values.height + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + + font.pixelSize: StudioTheme.Values.myFontSize + + color: StudioTheme.Values.themeTextColor + selectionColor: StudioTheme.Values.themeTextSelectionColor + selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor + + readOnly: false + selectByMouse: true + persistentSelection: focus // QTBUG-73807 + clip: true + + width: StudioTheme.Values.height * 5 + height: StudioTheme.Values.height + implicitHeight: StudioTheme.Values.height + + leftPadding: StudioTheme.Values.inputHorizontalPadding + actionIndicator.width + - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + rightPadding: StudioTheme.Values.inputHorizontalPadding + translationIndicator.width + - (translationIndicatorVisible ? StudioTheme.Values.border : 0) + + MouseArea { + id: mouseArea + anchors.fill: parent + enabled: true + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + cursorShape: Qt.PointingHandCursor + onContainsMouseChanged: myTextField.hover = containsMouse // Sets the global hover + onPressed: { + if (mouse.button === Qt.RightButton) + contextMenu.popup(myTextField) + + mouse.accepted = false + } + } + + onPersistentSelectionChanged: { + if (!persistentSelection) + myTextField.deselect() + } + + ContextMenu { + id: contextMenu + myTextEdit: myTextField + } + + ActionIndicator { + id: actionIndicator + myControl: myTextField + x: 0 + y: 0 + width: actionIndicator.visible ? __actionIndicatorWidth : 0 + height: actionIndicator.visible ? __actionIndicatorHeight : 0 + } + + background: Rectangle { + id: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + border.width: StudioTheme.Values.border + x: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) + width: myTextField.width - actionIndicator.width + height: myTextField.height + } + + TranslationIndicator { + id: translationIndicator + myControl: myTextField + x: myTextField.width - translationIndicator.width + width: translationIndicator.visible ? __translationIndicatorWidth : 0 + height: translationIndicator.visible ? __translationIndicatorHeight : 0 + } + + states: [ + State { + name: "default" + when: myTextField.enabled && !myTextField.hover + && !myTextField.edit + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackground + border.color: StudioTheme.Values.themeControlOutline + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.PointingHandCursor + } + }, + State { + name: "hovered" + when: myTextField.hover && !myTextField.edit + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeHoverHighlight + border.color: StudioTheme.Values.themeControlOutline + } + }, + State { + name: "edit" + when: myTextField.edit + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeFocusEdit + border.color: StudioTheme.Values.themeInteraction + } + PropertyChanges { + target: mouseArea + cursorShape: Qt.IBeamCursor + } + }, + State { + name: "disabled" + when: !myTextField.enabled + PropertyChanges { + target: textFieldBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + } + ] + + Keys.onPressed: { + if (event.key === Qt.Key_Escape) + myTextField.focus = false + } +} diff --git a/src/imports/StudioControls/TranslationIndicator.qml b/src/imports/StudioControls/TranslationIndicator.qml new file mode 100644 index 0000000..7c4e0c9 --- /dev/null +++ b/src/imports/StudioControls/TranslationIndicator.qml @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Templates 2.12 as T +import StudioTheme 1.0 as StudioTheme + +Item { + id: translationIndicator + + property Item myControl + + property bool hover: false + property bool pressed: false + property bool checked: false + + signal clicked + + state: "default" + + Rectangle { + id: translationIndicatorBackground + color: StudioTheme.Values.themeColumnBackground // TODO create extra variable, this one is used + border.color: StudioTheme.Values.themeTranslationIndicatorBorder + + anchors.centerIn: parent + + width: matchParity(translationIndicator.height, + StudioTheme.Values.smallRectWidth) + height: matchParity(translationIndicator.height, + StudioTheme.Values.smallRectWidth) + + function matchParity(root, value) { + // TODO maybe not necessary + var v = Math.round(value) + + if (root % 2 == 0) + // even + return (v % 2 == 0) ? v : v - 1 + else + // odd + return (v % 2 == 0) ? v - 1 : v + } + + MouseArea { + id: translationIndicatorMouseArea + anchors.fill: parent + hoverEnabled: true + onContainsMouseChanged: translationIndicator.hover = containsMouse + onPressed: mouse.accepted = true // TODO + onClicked: { + translationIndicator.checked = !translationIndicator.checked + translationIndicator.clicked() + } + } + } + + T.Label { + id: translationIndicatorIcon + text: "tr" + color: StudioTheme.Values.themeTextColor + font.family: StudioTheme.Constants.font.family + font.pixelSize: StudioTheme.Values.myIconFontSize + font.italic: true + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + } + + states: [ + State { + name: "default" + when: myControl.enabled && !translationIndicator.hover + && !translationIndicator.pressed && !myControl.hover + && !myControl.edit && !myControl.drag + && !translationIndicator.checked + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeColumnBackground + border.color: StudioTheme.Values.themeTranslationIndicatorBorder + } + }, + State { + name: "checked" + when: translationIndicator.checked + + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeInteraction // TODO + } + }, + State { + name: "hovered" + when: translationIndicator.hover && !translationIndicator.pressed + && !myControl.edit && !myControl.drag && !myControl.drag + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeFocusDrag // TODO + } + }, + State { + name: "disabled" + when: !myControl.enabled + PropertyChanges { + target: translationIndicatorBackground + color: StudioTheme.Values.themeControlBackgroundDisabled + border.color: StudioTheme.Values.themeControlOutlineDisabled + } + PropertyChanges { + target: translationIndicatorIcon + color: StudioTheme.Values.themeTextColorDisabled + } + } + ] +} diff --git a/src/imports/StudioControls/qmldir b/src/imports/StudioControls/qmldir new file mode 100644 index 0000000..02e83ed --- /dev/null +++ b/src/imports/StudioControls/qmldir @@ -0,0 +1,35 @@ +AbstractButton 1.0 AbstractButton.qml +ActionIndicator 1.0 ActionIndicator.qml +Button 1.0 Button.qml +ButtonGroup 1.0 ButtonGroup.qml +ButtonRow 1.0 ButtonRow.qml +CheckBox 1.0 CheckBox.qml +CheckIndicator 1.0 CheckIndicator.qml +ComboBox 1.0 ComboBox.qml +ComboBoxInput 1.0 ComboBoxInput.qml +ContextMenu 1.0 ContextMenu.qml +ControlScrollBar 1.0 ControlScrollBar.qml +ExpandingSpacer 1.0 ExpandingSpacer.qml +ItemDelegate 1.0 ItemDelegate.qml +Menu 1.0 Menu.qml +MenuItem 1.0 MenuItem.qml +MenuSeparator 1.0 MenuSeparator.qml +RealSliderPopup 1.0 RealSliderPopup.qml +RealSpinBox 1.0 RealSpinBox.qml +RealSpinBoxIndicator 1.0 RealSpinBoxIndicator.qml +RealSpinBoxInput 1.0 RealSpinBoxInput.qml +ScrollBar 1.0 ScrollBar.qml +ScrollView 1.0 ScrollView.qml +SecondColumnLayout 1.0 SecondColumnLayout.qml +Section 1.0 Section.qml +SectionLabel 1.0 SectionLabel.qml +SectionLayout 1.0 SectionLayout.qml +Slider 1.0 Slider.qml +SliderPopup 1.0 SliderPopup.qml +SpinBox 1.0 SpinBox.qml +SpinBoxIndicator 1.0 SpinBoxIndicator.qml +SpinBoxInput 1.0 SpinBoxInput.qml +TextArea 1.0 TextArea.qml +TextAreaScrollView 1.0 TextAreaScrollView.qml +TextField 1.0 TextField.qml +TranslationIndicator 1.0 TranslationIndicator.qml diff --git a/src/imports/StudioTheme/Constants.qml b/src/imports/StudioTheme/Constants.qml new file mode 100644 index 0000000..207a154 --- /dev/null +++ b/src/imports/StudioTheme/Constants.qml @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +pragma Singleton +import QtQuick 2.10 + +QtObject { + readonly property int width: 1920 + readonly property int height: 1080 + readonly property FontLoader mySystemFont: FontLoader { + name: "Arial" + } + readonly property FontLoader controlIcons: FontLoader { + source: "icons.ttf" + } + + readonly property string actionIcon: "\u0021" + readonly property string actionIconBinding: "\u0022" + readonly property string anchorBaseline: "\u0023" + readonly property string anchorBottom: "\u0024" + readonly property string anchorFill: "\u0025" + readonly property string anchorLeft: "\u0026" + readonly property string anchorRight: "\u0027" + readonly property string anchorTop: "\u0028" + readonly property string centerHorizontal: "\u0029" + readonly property string centerVertical: "\u002A" + readonly property string closeCross: "\u002B" + readonly property string fontStyleBold: "\u002C" + readonly property string fontStyleItalic: "\u002D" + readonly property string fontStyleStrikethrough: "\u002E" + readonly property string fontStyleUnderline: "\u002F" + readonly property string textAlignBottom: "\u0030" + readonly property string textAlignCenter: "\u0031" + readonly property string textAlignLeft: "\u0032" + readonly property string textAlignMiddle: "\u0033" + readonly property string textAlignRight: "\u0034" + readonly property string textAlignTop: "\u0035" + readonly property string tickIcon: "\u0036" + readonly property string triState: "\u0037" + readonly property string upDownIcon: "\u0038" + readonly property string upDownSquare2: "\u0039" + + readonly property font iconFont: Qt.font({ + "family": controlIcons.name, + "pixelSize": 12 + }) + + readonly property font font: Qt.font({ + "family": mySystemFont.name, + "pointSize": Qt.application.font.pixelSize + }) + + readonly property font largeFont: Qt.font({ + "family": mySystemFont.name, + "pointSize": Qt.application.font.pixelSize * 1.6 + }) + + readonly property color backgroundColor: "#c2c2c2" +} diff --git a/src/imports/StudioTheme/Values.qml b/src/imports/StudioTheme/Values.qml new file mode 100644 index 0000000..67438bc --- /dev/null +++ b/src/imports/StudioTheme/Values.qml @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +pragma Singleton +import QtQuick 2.12 + +QtObject { + id: values + + property real baseHeight: 20 + property real baseFont: 12 + property real baseIconFont: 10 + + property real scaleFactor: 1.1 + + property real height: Math.round(values.baseHeight * values.scaleFactor) + property real myFontSize: Math.round(values.baseFont * values.scaleFactor) + property real myIconFontSize: Math.round(values.baseIconFont * values.scaleFactor) + + property real squareComponentWidth: values.height + property real smallRectWidth: values.height / 2 * 1.5 + + property real inputWidth: values.height * 4 + + property real sliderHeight: values.height / 2 * 1.5 // TODO:Have a look at -> sliderAreaHeight: Data.Values.height/2*1.5 + + property real sliderControlSize: 12 + property real sliderControlSizeMulti: values.sliderControlSize * values.scaleFactor + + property int dragLength: 400 // px + property real spinControlIconSize: 8 + property real spinControlIconSizeMulti: values.spinControlIconSize * values.scaleFactor + + property real sliderTrackHeight: values.height / 4 + property real sliderHandleHeight: values.sliderTrackHeight * 2 + property real sliderHandleWidth: values.sliderTrackHeight + property real sliderFontSize: Math.round(8 * values.scaleFactor) + property real sliderPadding: Math.round(6 * values.scaleFactor) + property real sliderMargin: Math.round(3 * values.scaleFactor) + + property real sliderPointerWidth: Math.round(7 * values.scaleFactor) + property real sliderPointerHeight: Math.round(2 * values.scaleFactor) + + property real checkBoxSpacing: Math.round(6 * values.scaleFactor) + + property real columnWidth: 225 + (175 * (values.scaleFactor * 2)) + + property real marginTopBottom: 4 + property real border: 1 + + property real maxComboBoxPopupHeight: Math.round(300 * values.scaleFactor) + property real maxTextAreaPopupHeight: Math.round(150 * values.scaleFactor) + + property real contextMenuLabelSpacing: Math.round(30 * values.scaleFactor) + property real contextMenuHorizontalPadding: Math.round(6 * values.scaleFactor) + + property real inputHorizontalPadding: Math.round(4 * values.scaleFactor) + + // Theme Colors + + // Dark Theme Defaults + property string themeControlBackground: "#242424" + property string themeControlOutline: "#404040" + property string themeTextColor: "#ffffff" + + property string themePanelBackground: "#2a2a2a" + property string themeHoverHighlight: "#313131" + property string themeColumnBackground: "#363636" + property string themeFocusEdit: "#444444" + property string themeFocusDrag: "#565656" + + property string themeControlBackgroundPressed: "#606060" + property string themeControlBackgroundChecked: "#565656" + + property string themeInteraction: "#029de0" + + property string themeSliderActiveTrack: "#606060" + property string themeSliderInactiveTrack: "#404040" + property string themeSliderHandle: "#505050" + + property string themeSliderActiveTrackHover: "#7f7f7f" + property string themeSliderInactiveTrackHover: "#505050" + property string themeSliderHandleHover: "#606060" + + property string themeSliderActiveTrackFocus: "#aaaaaa" + property string themeSliderInactiveTrackFocus: "#606060" + property string themeSliderHandleFocus: values.themeInteraction + + // NEW NEW NEW NEW NEW + property string themeControlBackgroundDisabled: "#363636" + property string themeControlOutlineDisabled: "#404040" + property string themeTextColorDisabled: "#606060" + + property string themeTextSelectionColor: "#029de0" + property string themeTextSelectedTextColor: "#ffffff" + + property string themeScrollBarTrack: "#404040" + property string themeScrollBarHandle: "#505050" + + property string themeControlBackgroundInteraction: "#404040" // TODO Name. Right now themeFocusEdit is used for all 'edit' states. Is that correct? Different color! + + property string themeTranslationIndicatorBorder: "#7f7f7f" +} diff --git a/src/imports/StudioTheme/icons.ttf b/src/imports/StudioTheme/icons.ttf Binary files differnew file mode 100644 index 0000000..9658c01 --- /dev/null +++ b/src/imports/StudioTheme/icons.ttf diff --git a/src/imports/StudioTheme/qmldir b/src/imports/StudioTheme/qmldir new file mode 100644 index 0000000..b768fe6 --- /dev/null +++ b/src/imports/StudioTheme/qmldir @@ -0,0 +1,2 @@ +singleton Values 1.0 Values.qml +singleton Constants 1.0 Constants.qml |