forked from qt-creator/qt-creator
QmlDesigner: Update StateEditor layout
* Add alias properties to StudioControls AbstractButton * Add color to StudioControls theme * Update StateEditor layout due to issue with default label placement Task-number: QDS-2623 Task-number: QDS-2615 Change-Id: If46daab2293d42dff7d73c4cf9a0c370442c5694 Reviewed-by: Brook Cronin <brook.cronin@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
72406c69ce
commit
431667925e
@@ -33,6 +33,9 @@ T.AbstractButton {
|
|||||||
property alias buttonIcon: buttonIcon.text
|
property alias buttonIcon: buttonIcon.text
|
||||||
property alias iconColor: buttonIcon.color
|
property alias iconColor: buttonIcon.color
|
||||||
property alias iconFont: buttonIcon.font.family
|
property alias iconFont: buttonIcon.font.family
|
||||||
|
property alias iconSize: buttonIcon.font.pixelSize
|
||||||
|
property alias iconItalic: buttonIcon.font.italic
|
||||||
|
property alias iconBold: buttonIcon.font.bold
|
||||||
property alias backgroundVisible: buttonBackground.visible
|
property alias backgroundVisible: buttonBackground.visible
|
||||||
property alias backgroundRadius: buttonBackground.radius
|
property alias backgroundRadius: buttonBackground.radius
|
||||||
|
|
||||||
|
@@ -122,6 +122,8 @@ QtObject {
|
|||||||
property string themeTabDark: Theme.color(Theme.QmlDesigner_TabDark)
|
property string themeTabDark: Theme.color(Theme.QmlDesigner_TabDark)
|
||||||
property string themeTabLight: Theme.color(Theme.QmlDesigner_TabLight)
|
property string themeTabLight: Theme.color(Theme.QmlDesigner_TabLight)
|
||||||
|
|
||||||
|
property string themeStateDefaultHighlight: "#ffe400"
|
||||||
|
|
||||||
// Taken out of Constants.js
|
// Taken out of Constants.js
|
||||||
property string themeChangedStateText: Theme.color(Theme.DSchangedStateText)
|
property string themeChangedStateText: Theme.color(Theme.DSchangedStateText)
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of Qt Creator.
|
** This file is part of Qt Creator.
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Layouts 1.15
|
||||||
import QtQuickDesignerTheme 1.0
|
import QtQuickDesignerTheme 1.0
|
||||||
import HelperWidgets 2.0
|
import HelperWidgets 2.0
|
||||||
import StudioControls 1.0 as StudioControls
|
import StudioControls 1.0 as StudioControls
|
||||||
@@ -32,7 +33,8 @@ import StudioTheme 1.0 as StudioTheme
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: myRoot
|
id: myRoot
|
||||||
|
|
||||||
border.width: 1
|
color: baseColor
|
||||||
|
|
||||||
property bool isBaseState
|
property bool isBaseState
|
||||||
property bool isCurrentState
|
property bool isCurrentState
|
||||||
property color baseColor
|
property color baseColor
|
||||||
@@ -42,13 +44,19 @@ Rectangle {
|
|||||||
property bool delegateHasWhenCondition
|
property bool delegateHasWhenCondition
|
||||||
property string delegateWhenConditionString
|
property string delegateWhenConditionString
|
||||||
property bool hasAnnotation: checkAnnotation()
|
property bool hasAnnotation: checkAnnotation()
|
||||||
|
property int topAreaHeight
|
||||||
|
property int bottomAreaHeight
|
||||||
|
property int stateMargin
|
||||||
|
property int previewMargin
|
||||||
|
property int columnSpacing
|
||||||
|
|
||||||
readonly property bool isDefaultState: isDefault
|
readonly property bool isDefaultState: isDefault
|
||||||
|
|
||||||
signal delegateInteraction
|
property int closeButtonMargin: 6
|
||||||
|
property int textFieldMargin: 4
|
||||||
|
property int highlightBorderWidth: 2
|
||||||
|
|
||||||
color: baseColor
|
signal delegateInteraction
|
||||||
border.color: Theme.qmlDesignerBorderColor()
|
|
||||||
|
|
||||||
function autoComplete(text, pos, explicitComplete, filter) {
|
function autoComplete(text, pos, explicitComplete, filter) {
|
||||||
var stringList = statesEditorModel.autoComplete(text, pos, explicitComplete)
|
var stringList = statesEditorModel.autoComplete(text, pos, explicitComplete)
|
||||||
@@ -62,7 +70,6 @@ Rectangle {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onClicked: {
|
onClicked: {
|
||||||
focus = true
|
focus = true
|
||||||
@@ -74,11 +81,15 @@ Rectangle {
|
|||||||
|
|
||||||
StudioControls.AbstractButton {
|
StudioControls.AbstractButton {
|
||||||
id: removeStateButton
|
id: removeStateButton
|
||||||
|
|
||||||
buttonIcon: StudioTheme.Constants.closeCross
|
buttonIcon: StudioTheme.Constants.closeCross
|
||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 4
|
anchors.rightMargin: myRoot.closeButtonMargin
|
||||||
anchors.verticalCenter: stateNameField.verticalCenter
|
anchors.top: parent.top
|
||||||
visible: !isBaseState
|
anchors.topMargin: myRoot.closeButtonMargin
|
||||||
|
|
||||||
|
visible: !isBaseState && isCurrentState
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
myRoot.delegateInteraction()
|
myRoot.delegateInteraction()
|
||||||
@@ -156,9 +167,49 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.margins: (isDefaultState || (isBaseState && !modelHasDefaultState)) ? -myRoot.highlightBorderWidth : 0
|
||||||
|
anchors.fill: column
|
||||||
|
color: Theme.color(Theme.DSsliderActiveTrackFocus)
|
||||||
|
border.color: StudioTheme.Values.themeStateDefaultHighlight
|
||||||
|
border.width: (isDefaultState || (isBaseState && !modelHasDefaultState)) ? myRoot.highlightBorderWidth : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
|
||||||
|
anchors.margins: myRoot.stateMargin
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: expanded ? myRoot.columnSpacing : 0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
|
||||||
|
width: myRoot.width - 2 * myRoot.stateMargin
|
||||||
|
height: myRoot.topAreaHeight
|
||||||
|
|
||||||
|
color: Theme.color(Theme.DShoverHighlight)
|
||||||
|
|
||||||
StudioControls.TextField {
|
StudioControls.TextField {
|
||||||
id: stateNameField
|
id: stateNameField
|
||||||
|
|
||||||
|
property string oldValue
|
||||||
|
|
||||||
|
width: StudioTheme.Values.height * 7
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: myRoot.textFieldMargin
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: myRoot.textFieldMargin
|
||||||
|
|
||||||
|
translationIndicatorVisible: false
|
||||||
|
readOnly: isBaseState
|
||||||
|
|
||||||
|
actionIndicator.icon.text: delegateHasWhenCondition
|
||||||
|
? StudioTheme.Constants.actionIconBinding
|
||||||
|
: StudioTheme.Constants.actionIcon
|
||||||
|
|
||||||
|
|
||||||
actionIndicator.onClicked: {
|
actionIndicator.onClicked: {
|
||||||
stateNameField.actionIndicator.forceVisible = true
|
stateNameField.actionIndicator.forceVisible = true
|
||||||
contextMenu.popup()
|
contextMenu.popup()
|
||||||
@@ -169,85 +220,82 @@ Rectangle {
|
|||||||
contextMenu.dismiss()
|
contextMenu.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
actionIndicator.icon.text: delegateHasWhenCondition
|
|
||||||
? StudioTheme.Constants.actionIconBinding : StudioTheme.Constants.actionIcon
|
|
||||||
|
|
||||||
translationIndicatorVisible: false
|
|
||||||
y: 4
|
|
||||||
anchors.left: parent.left
|
|
||||||
// use the spacing which the image to the delegate rectangle has
|
|
||||||
anchors.leftMargin: 4
|
|
||||||
anchors.right: removeStateButton.left
|
|
||||||
anchors.rightMargin: 2
|
|
||||||
|
|
||||||
readOnly: isBaseState
|
|
||||||
|
|
||||||
onActiveFocusChanged: {
|
onActiveFocusChanged: {
|
||||||
if (activeFocus)
|
if (activeFocus)
|
||||||
root.currentStateInternalId = internalNodeId
|
root.currentStateInternalId = internalNodeId
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
text = delegateStateName
|
|
||||||
}
|
|
||||||
|
|
||||||
property string oldValue
|
|
||||||
|
|
||||||
onEditingFinished: {
|
onEditingFinished: {
|
||||||
if (stateNameField.oldValue === stateNameField.text)
|
if (stateNameField.oldValue === stateNameField.text)
|
||||||
return
|
return
|
||||||
|
|
||||||
stateNameField.oldValue = stateNameField.text
|
stateNameField.oldValue = stateNameField.text
|
||||||
|
|
||||||
if (stateNameField.text !== delegateStateName)
|
if (stateNameField.text !== myRoot.delegateStateName)
|
||||||
statesEditorModel.renameState(internalNodeId, stateNameField.text)
|
statesEditorModel.renameState(internalNodeId, stateNameField.text)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
Component.onCompleted: {
|
||||||
id: stateImageArea
|
text = myRoot.delegateStateName
|
||||||
anchors.topMargin: 2
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.top: stateNameField.bottom
|
|
||||||
|
|
||||||
height: delegateStateImageSize + 2
|
|
||||||
width: delegateStateImageSize + 2
|
|
||||||
|
|
||||||
visible: expanded
|
|
||||||
Rectangle {
|
|
||||||
anchors.margins: -1
|
|
||||||
anchors.fill: stateImage
|
|
||||||
border.width: 1
|
|
||||||
border.color: Theme.qmlDesignerBackgroundColorDarker()
|
|
||||||
}
|
|
||||||
Image {
|
|
||||||
id: stateImage
|
|
||||||
anchors.centerIn: parent
|
|
||||||
source: delegateStateImageSource
|
|
||||||
sourceSize.width: delegateStateImageSize
|
|
||||||
sourceSize.height: delegateStateImageSize
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: stateDefaultIndicator
|
id: stateDefaultIndicator
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: StudioTheme.Values.height
|
|
||||||
anchors.right: removeStateButton.left
|
|
||||||
anchors.rightMargin: 4
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 4
|
|
||||||
|
|
||||||
color: Theme.color(Theme.PanelTextColorLight)
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: myRoot.previewMargin
|
||||||
|
anchors.verticalCenter: stateNameField.verticalCenter
|
||||||
|
|
||||||
|
color: Theme.color(Theme.DStextColor)
|
||||||
font.italic: true
|
font.italic: true
|
||||||
font.pixelSize: Theme.smallFontPixelSize()
|
font.pixelSize: StudioTheme.Values.myFontSize
|
||||||
|
font.family: StudioTheme.Constants.font
|
||||||
|
|
||||||
visible: expanded && (isDefaultState || (isBaseState && !modelHasDefaultState))
|
visible: (isDefaultState || (isBaseState && !modelHasDefaultState))
|
||||||
|
|
||||||
text: ("* " + qsTr("Default"))
|
text: qsTr("Default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: stateImageArea
|
||||||
|
|
||||||
|
width: myRoot.width - 2 * myRoot.stateMargin
|
||||||
|
height: myRoot.bottomAreaHeight
|
||||||
|
|
||||||
|
color: Theme.color(Theme.DShoverHighlight)
|
||||||
|
|
||||||
|
visible: expanded
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
border.width: StudioTheme.Values.border
|
||||||
|
border.color: Theme.color(Theme.DSsliderActiveTrackFocus)
|
||||||
|
color: Theme.color(Theme.DSsliderInactiveTrack)
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
width: Math.round(stateImage.paintedWidth) + 2 * StudioTheme.Values.border
|
||||||
|
height: Math.round(stateImage.paintedHeight) + 2 * StudioTheme.Values.border
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
id: stateImage
|
||||||
|
|
||||||
|
anchors.margins: myRoot.previewMargin
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.fill: parent
|
||||||
|
source: delegateStateImageSource
|
||||||
|
sourceSize.width: delegateStateImageSize
|
||||||
|
sourceSize.height: delegateStateImageSize
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BindingEditor {
|
BindingEditor {
|
||||||
|
id: bindingEditor
|
||||||
|
|
||||||
property string newWhenCondition
|
property string newWhenCondition
|
||||||
|
|
||||||
property Timer timer: Timer {
|
property Timer timer: Timer {
|
||||||
@@ -258,8 +306,6 @@ Rectangle {
|
|||||||
onTriggered: statesEditorModel.setWhenCondition(internalNodeId, bindingEditor.newWhenCondition)
|
onTriggered: statesEditorModel.setWhenCondition(internalNodeId, bindingEditor.newWhenCondition)
|
||||||
}
|
}
|
||||||
|
|
||||||
id: bindingEditor
|
|
||||||
|
|
||||||
stateModelNodeProperty: statesEditorModel.stateModelNode()
|
stateModelNodeProperty: statesEditorModel.stateModelNode()
|
||||||
|
|
||||||
onRejected: {
|
onRejected: {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of Qt Creator.
|
** This file is part of Qt Creator.
|
||||||
@@ -33,16 +33,29 @@ import StudioTheme 1.0 as StudioTheme
|
|||||||
FocusScope {
|
FocusScope {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
height: (root.expanded ? 192 : 40) + StudioTheme.Values.scrollBarThickness
|
property int delegateTopAreaHeight: 30
|
||||||
|
property int delegateBottomAreaHeight: 200
|
||||||
|
property int delegateColumnSpacing: 2
|
||||||
|
property int delegateStateMargin: 16
|
||||||
|
property int delegatePreviewMargin: 16
|
||||||
|
|
||||||
|
height: (root.expanded ? (root.delegateTopAreaHeight + root.delegateBottomAreaHeight + root.delegateColumnSpacing)
|
||||||
|
: root.delegateTopAreaHeight)
|
||||||
|
+ StudioTheme.Values.scrollBarThickness
|
||||||
|
+ 2 * (root.delegateStateMargin + StudioTheme.Values.border + root.padding)
|
||||||
|
|
||||||
signal createNewState
|
signal createNewState
|
||||||
signal deleteState(int internalNodeId)
|
signal deleteState(int internalNodeId)
|
||||||
signal duplicateCurrentState
|
signal duplicateCurrentState
|
||||||
|
|
||||||
property int stateImageSize: 180
|
property int stateImageSize: 200
|
||||||
property int padding: 2
|
property int padding: 2
|
||||||
property int delegateWidth: root.stateImageSize + 44
|
property int delegateWidth: root.stateImageSize
|
||||||
property int delegateHeight: root.height - StudioTheme.Values.scrollBarThickness - root.padding * 2 + 1
|
+ 2 * (root.delegateStateMargin + root.delegatePreviewMargin)
|
||||||
property int innerSpacing: 0
|
property int delegateHeight: root.height
|
||||||
|
- StudioTheme.Values.scrollBarThickness
|
||||||
|
- 2 * (root.padding + StudioTheme.Values.border)
|
||||||
|
property int innerSpacing: 2
|
||||||
property int currentStateInternalId: 0
|
property int currentStateInternalId: 0
|
||||||
|
|
||||||
property bool expanded: true
|
property bool expanded: true
|
||||||
@@ -59,7 +72,7 @@ FocusScope {
|
|||||||
Rectangle {
|
Rectangle {
|
||||||
id: background
|
id: background
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Theme.qmlDesignerBackgroundColorDarkAlternate()
|
color: Theme.color(Theme.QmlDesigner_BackgroundColorDarkAlternate)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -103,35 +116,33 @@ FocusScope {
|
|||||||
|
|
||||||
AbstractButton {
|
AbstractButton {
|
||||||
id: addStateButton
|
id: addStateButton
|
||||||
visible: canAddNewStates
|
|
||||||
|
|
||||||
|
buttonIcon: root.expanded ? qsTr("Create New State") : StudioTheme.Constants.plus
|
||||||
|
iconFont: root.expanded ? StudioTheme.Constants.font : StudioTheme.Constants.iconFont
|
||||||
|
iconSize: root.expanded ? StudioTheme.Values.myFontSize : StudioTheme.Values.myIconFontSize
|
||||||
|
iconItalic: root.expanded ? true : false
|
||||||
tooltip: qsTr("Add a new state.")
|
tooltip: qsTr("Add a new state.")
|
||||||
|
visible: canAddNewStates
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 8
|
anchors.rightMargin: 8
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
width: Math.max(parent.height / 2 - 8, 18)
|
width: Math.max(parent.height / 2 - 8, 18)
|
||||||
height: width
|
height: root.expanded ? 80 : width
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.closeContextMenu()
|
root.closeContextMenu()
|
||||||
root.createNewState()
|
root.createNewState()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
background: Rectangle {
|
Rectangle {
|
||||||
property color buttonBaseColor: Qt.darker(Theme.qmlDesignerBackgroundColorDarkAlternate(), 1.1)
|
color: Theme.color(Theme.DSsliderActiveTrackFocus)
|
||||||
color: addStateButton.hovered ? Qt.lighter(buttonBaseColor, 1.2) : buttonBaseColor
|
x: root.padding
|
||||||
border.color: Theme.qmlDesignerBorderColor()
|
y: root.padding
|
||||||
border.width: 1
|
width: Math.min((root.delegateWidth * flickable.count) + (2 * (flickable.count - 1)),
|
||||||
Image {
|
flickable.width)
|
||||||
source: "image://icons/plus"
|
height: root.delegateHeight
|
||||||
width: 16
|
|
||||||
height: 16
|
|
||||||
anchors.centerIn: parent
|
|
||||||
smooth: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
@@ -155,15 +166,21 @@ FocusScope {
|
|||||||
id: statesDelegate
|
id: statesDelegate
|
||||||
width: root.delegateWidth
|
width: root.delegateWidth
|
||||||
height: root.delegateHeight
|
height: root.delegateHeight
|
||||||
isBaseState: 0 == internalNodeId
|
isBaseState: 0 === internalNodeId
|
||||||
isCurrentState: root.currentStateInternalId == internalNodeId
|
isCurrentState: root.currentStateInternalId === internalNodeId
|
||||||
baseColor: isCurrentState ? Theme.color(Theme.QmlDesigner_HighlightColor) : background.color
|
baseColor: isCurrentState ? Theme.color(Theme.DSinteraction) : background.color
|
||||||
delegateStateName: stateName
|
delegateStateName: stateName
|
||||||
delegateStateImageSource: stateImageSource
|
delegateStateImageSource: stateImageSource
|
||||||
delegateStateImageSize: stateImageSize
|
delegateStateImageSize: stateImageSize
|
||||||
delegateHasWhenCondition: hasWhenCondition
|
delegateHasWhenCondition: hasWhenCondition
|
||||||
delegateWhenConditionString: whenConditionString
|
delegateWhenConditionString: whenConditionString
|
||||||
onDelegateInteraction: root.closeContextMenu()
|
onDelegateInteraction: root.closeContextMenu()
|
||||||
|
|
||||||
|
columnSpacing: root.delegateColumnSpacing
|
||||||
|
topAreaHeight: root.delegateTopAreaHeight
|
||||||
|
bottomAreaHeight: root.delegateBottomAreaHeight
|
||||||
|
stateMargin: root.delegateStateMargin
|
||||||
|
previewMargin: root.delegatePreviewMargin
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool bothVisible: horizontal.scrollBarVisible && vertical.scrollBarVisible
|
property bool bothVisible: horizontal.scrollBarVisible && vertical.scrollBarVisible
|
||||||
|
Reference in New Issue
Block a user