HMI/PropertyEditor/resources/Qml/ValueEditor/FontBox.qml

356 lines
12 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import ColorPalette
Item {
id: control
property font value
property var fontFamilies: []
property bool expanded: false
property bool internalUpdate: false
property int sizeValue: control.value.pointSize
readonly property int kRowHeight: 25
readonly property int kEditRowCount: 5
readonly property int kExpandedHeight: kRowHeight + kEditRowCount * kRowHeight + (kEditRowCount - 1) * 2
implicitHeight: height
implicitWidth: 100
height: expanded ? kExpandedHeight : kRowHeight
signal asValueChanged(value: var)
function setValue(newValue: var) {
if (internalUpdate) return
if (newValue !== value) {
internalUpdate = true
value = newValue
sizeValue = value.pointSize
internalUpdate = false
asValueChanged(value)
}
}
function applySizeEdit() {
if (control.internalUpdate) return
control.internalUpdate = true
control.value.pointSize = sizeValue
control.internalUpdate = false
control.asValueChanged(control.value)
}
// Header row
Rectangle {
id: headerRow
height: kRowHeight
width: parent.width
color: ColorPalette.theme.textBoxBackground
border.color: expanded ? ColorPalette.theme.comboBoxItemBackgroundHover : ColorPalette.theme.textBoxBackground
border.width: 1
Text {
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 20
verticalAlignment: Text.AlignVCenter
text: value.family + ", " + value.pointSize + "pt"
color: ColorPalette.theme.textPrimary
elide: Text.ElideRight
}
Text {
anchors.right: parent.right
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
text: expanded ? "▲" : "▼"
color: ColorPalette.theme.labelPrimary
font.pixelSize: 10
}
MouseArea {
anchors.fill: parent
onClicked: control.expanded = !control.expanded
}
}
// Edit pane — 5 rows
Column {
id: editPane
visible: control.expanded
anchors.top: headerRow.bottom
anchors.left: parent.left
anchors.right: parent.right
spacing: 2
// Row 1: Font Family
ComboBox {
id: familyCombo
width: parent.width
height: kRowHeight
model: control.fontFamilies.length > 0 ? control.fontFamilies : []
currentIndex: -1
clip: true
background: Rectangle {
color: ColorPalette.theme.comboBoxBackground
border.color: familyCombo.activeFocus ? ColorPalette.theme.comboBoxItemBackgroundHover : ColorPalette.theme.rowBorder
border.width: 1
}
contentItem: Text {
text: familyCombo.currentIndex >= 0 ? familyCombo.currentText : value.family
color: ColorPalette.theme.textPrimary
verticalAlignment: Text.AlignVCenter
leftPadding: 6
elide: Text.ElideRight
}
popup: Popup {
y: familyCombo.height
width: familyCombo.width
implicitHeight: Math.min(contentItem.contentHeight, 200)
padding: 1
contentItem: ListView {
clip: true
implicitHeight: Math.min(contentHeight, 200)
model: familyCombo.delegateModel
currentIndex: familyCombo.highlightedIndex
ScrollIndicator.vertical: ScrollIndicator {}
}
background: Rectangle {
color: ColorPalette.theme.comboBoxItemBackground
border.color: ColorPalette.theme.rowBorder
}
}
// Sync ComboBox selection when fontFamilies arrives (C++ sets it after value)
function syncComboIndex() {
if (control.fontFamilies.length > 0 && value.family) {
var idx = find(value.family)
if (idx >= 0) currentIndex = idx
}
}
Component.onCompleted: syncComboIndex()
onModelChanged: syncComboIndex()
onActivated: control.applyEdit()
}
// Row 2: Font Size — left spacer aligns "Size" with checkbox text below
RowLayout {
width: parent.width
height: kRowHeight
spacing: 0
// Spacer to align "Size" with checkbox text (indicator 14 + spacing 6 = 20)
Item { Layout.preferredWidth: 20 }
Text {
text: "Size"
color: ColorPalette.theme.labelPrimary
verticalAlignment: Text.AlignVCenter
Layout.preferredWidth: 28
Layout.alignment: Qt.AlignVCenter
}
// Decrease button
Rectangle {
implicitWidth: 22; implicitHeight: kRowHeight
Layout.alignment: Qt.AlignVCenter
color: sizeDownMa.pressed ? ColorPalette.theme.comboBoxItemBackgroundHover : "transparent"
border.color: ColorPalette.theme.rowBorder
border.width: 0.5
Text {
anchors.centerIn: parent
text: ""
font.pixelSize: 12
color: ColorPalette.theme.labelPrimary
}
MouseArea {
id: sizeDownMa
anchors.fill: parent
onClicked: { if (sizeValue > 1) sizeValue--; applySizeEdit() }
}
}
// Number input
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
implicitHeight: kRowHeight
color: ColorPalette.theme.comboBoxBackground
border.color: sizeInput.activeFocus ? ColorPalette.theme.comboBoxItemBackgroundHover : ColorPalette.theme.rowBorder
border.width: 1
TextInput {
id: sizeInput
anchors.fill: parent
anchors.leftMargin: 4
anchors.rightMargin: 4
color: ColorPalette.theme.textPrimary
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
validator: IntValidator { bottom: 1; top: 512 }
inputMethodHints: Qt.ImhDigitsOnly
text: sizeValue
onEditingFinished: { sizeValue = parseInt(text) || 1; applySizeEdit() }
}
}
// Increase button
Rectangle {
implicitWidth: 22; implicitHeight: kRowHeight
Layout.alignment: Qt.AlignVCenter
color: sizeUpMa.pressed ? ColorPalette.theme.comboBoxItemBackgroundHover : "transparent"
border.color: ColorPalette.theme.rowBorder
border.width: 0.5
Text {
anchors.centerIn: parent
text: "+"
font.pixelSize: 12
color: ColorPalette.theme.labelPrimary
}
MouseArea {
id: sizeUpMa
anchors.fill: parent
onClicked: { if (sizeValue < 512) sizeValue++; applySizeEdit() }
}
}
Text {
text: "pt"
color: ColorPalette.theme.labelPrimary
verticalAlignment: Text.AlignVCenter
Layout.preferredWidth: 20
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: 2
}
}
// Row 3: Bold
CheckBox {
id: boldCheck
text: "Bold"
height: kRowHeight
checked: control.value.bold
leftPadding: 0
spacing: 6
indicator: Rectangle {
implicitWidth: 14; implicitHeight: 14
x: boldCheck.leftPadding
y: (boldCheck.height - height) / 2
color: boldCheck.checked ? ColorPalette.theme.comboBoxItemBackgroundHover : "transparent"
border.color: boldCheck.checked ? ColorPalette.theme.comboBoxItemBackgroundHover : ColorPalette.theme.rowBorder
border.width: 1.5
radius: 2
Rectangle {
visible: boldCheck.checked
anchors.centerIn: parent
width: 8; height: 8
color: ColorPalette.theme.labelPrimary
radius: 1
}
}
contentItem: Text {
text: boldCheck.text
color: ColorPalette.theme.textPrimary
verticalAlignment: Text.AlignVCenter
leftPadding: boldCheck.indicator.width + boldCheck.spacing
}
onToggled: control.applyEdit()
}
// Row 4: Italic
CheckBox {
id: italicCheck
text: "Italic"
height: kRowHeight
checked: control.value.italic
leftPadding: 0
spacing: 6
indicator: Rectangle {
implicitWidth: 14; implicitHeight: 14
x: italicCheck.leftPadding
y: (italicCheck.height - height) / 2
color: italicCheck.checked ? ColorPalette.theme.comboBoxItemBackgroundHover : "transparent"
border.color: italicCheck.checked ? ColorPalette.theme.comboBoxItemBackgroundHover : ColorPalette.theme.rowBorder
border.width: 1.5
radius: 2
Rectangle {
visible: italicCheck.checked
anchors.centerIn: parent
width: 8; height: 8
color: ColorPalette.theme.labelPrimary
radius: 1
}
}
contentItem: Text {
text: italicCheck.text
color: ColorPalette.theme.textPrimary
verticalAlignment: Text.AlignVCenter
leftPadding: italicCheck.indicator.width + italicCheck.spacing
}
onToggled: control.applyEdit()
}
// Row 5: Underline
CheckBox {
id: underlineCheck
text: "Underline"
height: kRowHeight
checked: control.value.underline
leftPadding: 0
spacing: 6
indicator: Rectangle {
implicitWidth: 14; implicitHeight: 14
x: underlineCheck.leftPadding
y: (underlineCheck.height - height) / 2
color: underlineCheck.checked ? ColorPalette.theme.comboBoxItemBackgroundHover : "transparent"
border.color: underlineCheck.checked ? ColorPalette.theme.comboBoxItemBackgroundHover : ColorPalette.theme.rowBorder
border.width: 1.5
radius: 2
Rectangle {
visible: underlineCheck.checked
anchors.centerIn: parent
width: 8; height: 8
color: ColorPalette.theme.labelPrimary
radius: 1
}
}
contentItem: Text {
text: underlineCheck.text
color: ColorPalette.theme.textPrimary
verticalAlignment: Text.AlignVCenter
leftPadding: underlineCheck.indicator.width + underlineCheck.spacing
}
onToggled: control.applyEdit()
}
}
function applyEdit() {
if (control.internalUpdate) return
control.internalUpdate = true
control.value = Qt.font({
family: familyCombo.currentText || value.family,
pointSize: sizeValue,
bold: boldCheck.checked,
italic: italicCheck.checked,
underline: underlineCheck.checked
})
control.internalUpdate = false
control.asValueChanged(control.value)
}
}