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 iconColor: buttonIcon.color
|
||||
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 backgroundRadius: buttonBackground.radius
|
||||
|
||||
|
@@ -122,6 +122,8 @@ QtObject {
|
||||
property string themeTabDark: Theme.color(Theme.QmlDesigner_TabDark)
|
||||
property string themeTabLight: Theme.color(Theme.QmlDesigner_TabLight)
|
||||
|
||||
property string themeStateDefaultHighlight: "#ffe400"
|
||||
|
||||
// Taken out of Constants.js
|
||||
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/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
@@ -24,6 +24,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuickDesignerTheme 1.0
|
||||
import HelperWidgets 2.0
|
||||
import StudioControls 1.0 as StudioControls
|
||||
@@ -32,7 +33,8 @@ import StudioTheme 1.0 as StudioTheme
|
||||
Rectangle {
|
||||
id: myRoot
|
||||
|
||||
border.width: 1
|
||||
color: baseColor
|
||||
|
||||
property bool isBaseState
|
||||
property bool isCurrentState
|
||||
property color baseColor
|
||||
@@ -42,13 +44,19 @@ Rectangle {
|
||||
property bool delegateHasWhenCondition
|
||||
property string delegateWhenConditionString
|
||||
property bool hasAnnotation: checkAnnotation()
|
||||
property int topAreaHeight
|
||||
property int bottomAreaHeight
|
||||
property int stateMargin
|
||||
property int previewMargin
|
||||
property int columnSpacing
|
||||
|
||||
readonly property bool isDefaultState: isDefault
|
||||
|
||||
signal delegateInteraction
|
||||
property int closeButtonMargin: 6
|
||||
property int textFieldMargin: 4
|
||||
property int highlightBorderWidth: 2
|
||||
|
||||
color: baseColor
|
||||
border.color: Theme.qmlDesignerBorderColor()
|
||||
signal delegateInteraction
|
||||
|
||||
function autoComplete(text, pos, explicitComplete, filter) {
|
||||
var stringList = statesEditorModel.autoComplete(text, pos, explicitComplete)
|
||||
@@ -62,7 +70,6 @@ Rectangle {
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
|
||||
acceptedButtons: Qt.LeftButton
|
||||
onClicked: {
|
||||
focus = true
|
||||
@@ -74,11 +81,15 @@ Rectangle {
|
||||
|
||||
StudioControls.AbstractButton {
|
||||
id: removeStateButton
|
||||
|
||||
buttonIcon: StudioTheme.Constants.closeCross
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 4
|
||||
anchors.verticalCenter: stateNameField.verticalCenter
|
||||
visible: !isBaseState
|
||||
anchors.rightMargin: myRoot.closeButtonMargin
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: myRoot.closeButtonMargin
|
||||
|
||||
visible: !isBaseState && isCurrentState
|
||||
|
||||
onClicked: {
|
||||
myRoot.delegateInteraction()
|
||||
@@ -156,98 +167,135 @@ Rectangle {
|
||||
}
|
||||
|
||||
|
||||
StudioControls.TextField {
|
||||
id: stateNameField
|
||||
|
||||
actionIndicator.onClicked: {
|
||||
stateNameField.actionIndicator.forceVisible = true
|
||||
contextMenu.popup()
|
||||
}
|
||||
|
||||
onEditChanged: {
|
||||
if (contextMenu.open && stateNameField.edit)
|
||||
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: {
|
||||
if (activeFocus)
|
||||
root.currentStateInternalId = internalNodeId
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
text = delegateStateName
|
||||
}
|
||||
|
||||
property string oldValue
|
||||
|
||||
onEditingFinished: {
|
||||
if (stateNameField.oldValue === stateNameField.text)
|
||||
return
|
||||
|
||||
stateNameField.oldValue = stateNameField.text
|
||||
|
||||
if (stateNameField.text !== delegateStateName)
|
||||
statesEditorModel.renameState(internalNodeId, stateNameField.text)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
Item {
|
||||
id: stateImageArea
|
||||
anchors.topMargin: 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: stateNameField.bottom
|
||||
|
||||
height: delegateStateImageSize + 2
|
||||
width: delegateStateImageSize + 2
|
||||
Column {
|
||||
id: column
|
||||
|
||||
anchors.margins: myRoot.stateMargin
|
||||
anchors.fill: parent
|
||||
spacing: expanded ? myRoot.columnSpacing : 0
|
||||
|
||||
visible: expanded
|
||||
Rectangle {
|
||||
anchors.margins: -1
|
||||
anchors.fill: stateImage
|
||||
border.width: 1
|
||||
border.color: Theme.qmlDesignerBackgroundColorDarker()
|
||||
|
||||
width: myRoot.width - 2 * myRoot.stateMargin
|
||||
height: myRoot.topAreaHeight
|
||||
|
||||
color: Theme.color(Theme.DShoverHighlight)
|
||||
|
||||
StudioControls.TextField {
|
||||
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: {
|
||||
stateNameField.actionIndicator.forceVisible = true
|
||||
contextMenu.popup()
|
||||
}
|
||||
|
||||
onEditChanged: {
|
||||
if (contextMenu.open && stateNameField.edit)
|
||||
contextMenu.dismiss()
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus)
|
||||
root.currentStateInternalId = internalNodeId
|
||||
}
|
||||
|
||||
onEditingFinished: {
|
||||
if (stateNameField.oldValue === stateNameField.text)
|
||||
return
|
||||
|
||||
stateNameField.oldValue = stateNameField.text
|
||||
|
||||
if (stateNameField.text !== myRoot.delegateStateName)
|
||||
statesEditorModel.renameState(internalNodeId, stateNameField.text)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
text = myRoot.delegateStateName
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: stateDefaultIndicator
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: myRoot.previewMargin
|
||||
anchors.verticalCenter: stateNameField.verticalCenter
|
||||
|
||||
color: Theme.color(Theme.DStextColor)
|
||||
font.italic: true
|
||||
font.pixelSize: StudioTheme.Values.myFontSize
|
||||
font.family: StudioTheme.Constants.font
|
||||
|
||||
visible: (isDefaultState || (isBaseState && !modelHasDefaultState))
|
||||
|
||||
text: qsTr("Default")
|
||||
}
|
||||
}
|
||||
Image {
|
||||
id: stateImage
|
||||
anchors.centerIn: parent
|
||||
source: delegateStateImageSource
|
||||
sourceSize.width: delegateStateImageSize
|
||||
sourceSize.height: delegateStateImageSize
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
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)
|
||||
font.italic: true
|
||||
font.pixelSize: Theme.smallFontPixelSize()
|
||||
|
||||
visible: expanded && (isDefaultState || (isBaseState && !modelHasDefaultState))
|
||||
|
||||
text: ("* " + qsTr("Default"))
|
||||
}
|
||||
|
||||
BindingEditor {
|
||||
id: bindingEditor
|
||||
|
||||
property string newWhenCondition
|
||||
|
||||
property Timer timer: Timer {
|
||||
@@ -258,8 +306,6 @@ Rectangle {
|
||||
onTriggered: statesEditorModel.setWhenCondition(internalNodeId, bindingEditor.newWhenCondition)
|
||||
}
|
||||
|
||||
id: bindingEditor
|
||||
|
||||
stateModelNodeProperty: statesEditorModel.stateModelNode()
|
||||
|
||||
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/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
@@ -33,16 +33,29 @@ import StudioTheme 1.0 as StudioTheme
|
||||
FocusScope {
|
||||
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 deleteState(int internalNodeId)
|
||||
signal duplicateCurrentState
|
||||
|
||||
property int stateImageSize: 180
|
||||
property int stateImageSize: 200
|
||||
property int padding: 2
|
||||
property int delegateWidth: root.stateImageSize + 44
|
||||
property int delegateHeight: root.height - StudioTheme.Values.scrollBarThickness - root.padding * 2 + 1
|
||||
property int innerSpacing: 0
|
||||
property int delegateWidth: root.stateImageSize
|
||||
+ 2 * (root.delegateStateMargin + root.delegatePreviewMargin)
|
||||
property int delegateHeight: root.height
|
||||
- StudioTheme.Values.scrollBarThickness
|
||||
- 2 * (root.padding + StudioTheme.Values.border)
|
||||
property int innerSpacing: 2
|
||||
property int currentStateInternalId: 0
|
||||
|
||||
property bool expanded: true
|
||||
@@ -59,7 +72,7 @@ FocusScope {
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: Theme.qmlDesignerBackgroundColorDarkAlternate()
|
||||
color: Theme.color(Theme.QmlDesigner_BackgroundColorDarkAlternate)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -95,7 +108,7 @@ FocusScope {
|
||||
Item {
|
||||
id: addStateItem
|
||||
|
||||
property int buttonLeftSpacing: 8 * (root.expanded ? 1 : 2)
|
||||
property int buttonLeftSpacing: 8 * (root.expanded ? 1 : 2)
|
||||
|
||||
anchors.right: parent.right
|
||||
width: root.delegateHeight / 2 + buttonLeftSpacing
|
||||
@@ -103,37 +116,35 @@ FocusScope {
|
||||
|
||||
AbstractButton {
|
||||
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.")
|
||||
|
||||
visible: canAddNewStates
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.max(parent.height / 2 - 8, 18)
|
||||
height: width
|
||||
height: root.expanded ? 80 : width
|
||||
|
||||
onClicked: {
|
||||
root.closeContextMenu()
|
||||
root.createNewState()
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
property color buttonBaseColor: Qt.darker(Theme.qmlDesignerBackgroundColorDarkAlternate(), 1.1)
|
||||
color: addStateButton.hovered ? Qt.lighter(buttonBaseColor, 1.2) : buttonBaseColor
|
||||
border.color: Theme.qmlDesignerBorderColor()
|
||||
border.width: 1
|
||||
Image {
|
||||
source: "image://icons/plus"
|
||||
width: 16
|
||||
height: 16
|
||||
anchors.centerIn: parent
|
||||
smooth: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: Theme.color(Theme.DSsliderActiveTrackFocus)
|
||||
x: root.padding
|
||||
y: root.padding
|
||||
width: Math.min((root.delegateWidth * flickable.count) + (2 * (flickable.count - 1)),
|
||||
flickable.width)
|
||||
height: root.delegateHeight
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: flickable
|
||||
|
||||
@@ -155,15 +166,21 @@ FocusScope {
|
||||
id: statesDelegate
|
||||
width: root.delegateWidth
|
||||
height: root.delegateHeight
|
||||
isBaseState: 0 == internalNodeId
|
||||
isCurrentState: root.currentStateInternalId == internalNodeId
|
||||
baseColor: isCurrentState ? Theme.color(Theme.QmlDesigner_HighlightColor) : background.color
|
||||
isBaseState: 0 === internalNodeId
|
||||
isCurrentState: root.currentStateInternalId === internalNodeId
|
||||
baseColor: isCurrentState ? Theme.color(Theme.DSinteraction) : background.color
|
||||
delegateStateName: stateName
|
||||
delegateStateImageSource: stateImageSource
|
||||
delegateStateImageSize: stateImageSize
|
||||
delegateHasWhenCondition: hasWhenCondition
|
||||
delegateWhenConditionString: whenConditionString
|
||||
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
|
||||
|
Reference in New Issue
Block a user