// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Templates 2.15 as T
import HelperWidgets 2.0
import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
Section {
id: root
anchors.left: parent.left
anchors.right: parent.right
caption: qsTr("Character")
property bool showVerticalAlignment: false
property bool showLineHeight: false
property bool richTextEditorAvailable: false
property string fontName: "font"
property bool showStyle: false
function getBackendValue(name) {
return backendValues[root.fontName + "_" + name]
}
property variant fontFamily: root.getBackendValue("family")
property variant pointSize: root.getBackendValue("pointSize")
property variant pixelSize: root.getBackendValue("pixelSize")
property variant boldStyle: root.getBackendValue("bold")
property variant italicStyle: root.getBackendValue("italic")
property variant underlineStyle: root.getBackendValue("underline")
property variant strikeoutStyle: root.getBackendValue("strikeout")
onPointSizeChanged: sizeWidget.setPointPixelSize()
onPixelSizeChanged: sizeWidget.setPointPixelSize()
SectionLayout {
PropertyLabel {
text: qsTr("Text")
tooltip: qsTr("Sets the text to display.")
}
SecondColumnLayout {
LineEdit {
implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
backendValue: backendValues.text
}
Spacer { implicitWidth: StudioTheme.Values.twoControlColumnGap }
Rectangle {
id: richTextEditorIndicator
visible: root.richTextEditorAvailable
color: "transparent"
border.color: "transparent"
implicitWidth: StudioTheme.Values.iconAreaWidth // TODO dedicated value
implicitHeight: StudioTheme.Values.height // TODO dedicated value
T.Label {
id: richTextEditorIcon
anchors.fill: parent
text: StudioTheme.Constants.edit
color: StudioTheme.Values.themeTextColor
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: StudioTheme.Values.myIconFontSize + 4 // TODO
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
states: [
State {
name: "default"
when: !richTextEditorMouseArea.containsMouse
PropertyChanges {
target: richTextEditorIcon
color: StudioTheme.Values.themeLinkIndicatorColor
}
},
State {
name: "hover"
when: richTextEditorMouseArea.containsMouse
PropertyChanges {
target: richTextEditorIcon
color: StudioTheme.Values.themeLinkIndicatorColorHover
}
}
]
}
MouseArea {
id: richTextEditorMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: richTextDialogLoader.show()
}
}
ExpandingSpacer {}
RichTextEditor {
onRejected: hideWidget()
onAccepted: hideWidget()
}
}
PropertyLabel {
text: qsTr("Font")
tooltip: qsTr("Sets the font of the text.")
}
SecondColumnLayout {
FontComboBox {
id: fontComboBox
property string familyName: backendValue.value
backendValue: root.fontFamily
implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
}
ExpandingSpacer {}
}
PropertyLabel {
text: qsTr("Style name")
tooltip: qsTr("Sets the style of the selected font. This is prioritized over Weight and Emphasis.")
enabled: styleNameComboBox.model.length
blockedByTemplate: !styleNameComboBox.backendValue.isAvailable
}
SecondColumnLayout {
ComboBox {
id: styleNameComboBox
property bool styleSet: styleNameComboBox.backendValue.isInModel
implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
backendValue: root.getBackendValue("styleName")
model: styleNamesForFamily(fontComboBox.familyName)
valueType: ComboBox.String
enabled: styleNameComboBox.backendValue.isAvailable && styleNameComboBox.model.length
}
ExpandingSpacer {}
}
PropertyLabel {
text: qsTr("Size")
tooltip: qsTr("Sets the font size in pixels or points.")
}
SecondColumnLayout {
id: sizeWidget
property bool selectionFlag: selectionChanged
property bool pixelSize: sizeType.currentText === "px"
property bool isSetup
function setPointPixelSize() {
sizeWidget.isSetup = true
sizeType.currentIndex = 1
if (root.pixelSize.isInModel)
sizeType.currentIndex = 0
sizeWidget.isSetup = false
}
onSelectionFlagChanged: sizeWidget.setPointPixelSize()
Item {
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
height: sizeSpinBox.height
SpinBox {
id: sizeSpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
minimumValue: 0
visible: !sizeWidget.pixelSize
z: !sizeWidget.pixelSize ? 1 : 0
maximumValue: 400
backendValue: pointSize
}
SpinBox {
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
minimumValue: 0
visible: sizeWidget.pixelSize
z: sizeWidget.pixelSize ? 1 : 0
maximumValue: 400
backendValue: pixelSize
}
}
Spacer {
implicitWidth: StudioTheme.Values.twoControlColumnGap
+ StudioTheme.Values.actionIndicatorWidth
}
StudioControls.ComboBox {
id: sizeType
implicitWidth: StudioTheme.Values.twoControlColumnWidth
width: implicitWidth
model: ["px", "pt"]
actionIndicatorVisible: false
onActivated: {
if (sizeWidget.isSetup)
return
if (sizeType.currentText === "px") {
pointSize.resetValue()
pixelSize.value = 8
} else {
pixelSize.resetValue()
}
}
}
ExpandingSpacer {}
}
PropertyLabel {
text: qsTr("Text color")
tooltip: qsTr("Sets the text color.")
}
ColorEditor {
backendValue: backendValues.color
supportGradient: false
}
PropertyLabel {
text: qsTr("Weight")
tooltip: qsTr("Sets the overall thickness of the font.")
enabled: !styleNameComboBox.styleSet
}
SecondColumnLayout {
ComboBox {
implicitWidth: StudioTheme.Values.singleControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
width: implicitWidth
backendValue: root.getBackendValue("weight")
model: ["Normal", "Light", "ExtraLight", "Thin", "Medium", "DemiBold", "Bold", "ExtraBold", "Black"]
scope: "Font"
enabled: !styleNameComboBox.styleSet
}
ExpandingSpacer {}
}
PropertyLabel {
text: qsTr("Emphasis")
tooltip: qsTr("Sets the text to bold, italic, underlined, or strikethrough.")
enabled: !styleNameComboBox.styleSet
}
FontStyleButtons {
bold: root.boldStyle
italic: root.italicStyle
underline: root.underlineStyle
strikeout: root.strikeoutStyle
enabled: !styleNameComboBox.styleSet
}
PropertyLabel {
text: qsTr("Alignment H")
tooltip: qsTr("Sets the horizontal alignment position.")
}
SecondColumnLayout {
AlignmentHorizontalButtons {}
ExpandingSpacer {}
}
PropertyLabel {
text: qsTr("Alignment V")
tooltip: qsTr("Sets the vertical alignment position.")
}
SecondColumnLayout {
AlignmentVerticalButtons { visible: root.showVerticalAlignment }
ExpandingSpacer {}
}
PropertyLabel {
text: qsTr("Letter spacing")
tooltip: qsTr("Sets the letter spacing for the text.")
blockedByTemplate: !root.getBackendValue("letterSpacing").isAvailable
}
SecondColumnLayout {
SpinBox {
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: root.getBackendValue("letterSpacing")
decimals: 2
minimumValue: -500
maximumValue: 500
stepSize: 0.1
enabled: backendValue.isAvailable
}
ExpandingSpacer {}
}
PropertyLabel {
text: qsTr("Word spacing")
tooltip: qsTr("Sets the word spacing for the text.")
blockedByTemplate: !root.getBackendValue("wordSpacing").isAvailable
}
SecondColumnLayout {
SpinBox {
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: root.getBackendValue("wordSpacing")
decimals: 2
minimumValue: -500
maximumValue: 500
stepSize: 0.1
enabled: backendValue.isAvailable
}
ExpandingSpacer {}
}
PropertyLabel {
visible: root.showLineHeight
text: qsTr("Line height")
tooltip: qsTr("Sets the line height for the text.")
blockedByTemplate: !lineHeightSpinBox.enabled
}
SecondColumnLayout {
visible: root.showLineHeight
SpinBox {
id: lineHeightSpinBox
implicitWidth: StudioTheme.Values.twoControlColumnWidth
+ StudioTheme.Values.actionIndicatorWidth
backendValue: (backendValues.lineHeight === undefined) ? 1.0
: backendValues.lineHeight
decimals: 2
minimumValue: 0
maximumValue: 500
stepSize: 0.1
enabled: (backendValues.lineHeight === undefined) ? false
: backendValue.isAvailable
}
ExpandingSpacer {}
}
}
Loader {
id: richTextDialogLoader
visible: false
active: visible
function show() {
richTextDialogLoader.visible = true
}
sourceComponent: Item {
id: richTextEditorParent
Component.onCompleted: {
richTextEditor.showWidget()
richTextEditor.richText = backendValues.text.value
}
RichTextEditor {
id: richTextEditor
onRejected: {
hideWidget()
richTextDialogLoader.visible = false
}
onAccepted: {
backendValues.text.value = richTextEditor.richText
backendValues.textFormat.setEnumeration("Text", "RichText")
hideWidget()
richTextDialogLoader.visible = false
}
}
}
}
}