refactor(StatusBaseInput): use RowLayout for position management

This commit is contained in:
Patryk Osmaczko 2022-03-18 13:08:02 +01:00 committed by Michał Cieślak
parent ffb7289b9f
commit f2c832e015
2 changed files with 165 additions and 207 deletions

View File

@ -146,7 +146,7 @@ Column {
StatusInput { StatusInput {
label: "Label" label: "Label"
input.placeholderText: "Input width component (right side)" input.placeholderText: "Input width component (right side)"
input.component: StatusIcon { input.rightComponent: StatusIcon {
icon: "cancel" icon: "cancel"
height: 16 height: 16
color: Theme.palette.dangerColor1 color: Theme.palette.dangerColor1
@ -173,25 +173,27 @@ Column {
} }
StatusInput { StatusInput {
property bool toggled: true
label: "Input with emoji icon" label: "Input with emoji icon"
input.placeholderText: "Enter Name" input.placeholderText: "Enter Name"
input.icon.emoji: "😁" input.icon.emoji: toggled ? "😁" : "🧸"
input.icon.color: "blue" input.icon.color: "blue"
input.isIconSelectable: true input.isIconSelectable: true
onIconClicked: { onIconClicked: {
// launch emoji popup toggled = !toggled
} }
} }
StatusInput { StatusInput {
property bool toggled: true
label: "Input with selectable icon which is not an emoji" label: "Input with selectable icon which is not an emoji"
input.placeholderText: "Enter Name" input.placeholderText: "Enter Name"
input.icon.emoji: "" input.icon.emoji: ""
input.icon.name: "filled-account" input.icon.name: toggled ? "filled-account" : "image"
input.icon.color: "blue" input.icon.color: "blue"
input.isIconSelectable: true input.isIconSelectable: true
onIconClicked: { onIconClicked: {
// launch emoji popup toggled = !toggled
} }
} }
} }

View File

@ -1,15 +1,15 @@
import QtQuick 2.14 import QtQuick 2.14
import QtQuick.Controls 2.14 as QC import QtQuick.Controls 2.14 as QC
import QtQuick.Layouts 1.14
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
Item { Item {
id: statusBaseInput id: root
property bool multiline: false property bool multiline: false
@ -66,40 +66,24 @@ Item {
} }
} }
property Item leftComponent property Component leftComponent
property Item component property Component rightComponent
signal iconClicked() signal iconClicked
onClearableChanged: {
if (clearable && !component) {
clearButtonLoader.active = true
clearButtonLoader.parent = statusBaseInputComponentSlot
} else {
clearButtonLoader.active = false
}
}
onLeftComponentChanged: {
if (!!leftComponent) {
leftComponent.parent = statusBaseInputLeftComponentSlot;
}
}
onComponentChanged: {
if (!!component) {
component.parent = statusBaseInputComponentSlot
}
}
implicitWidth: 448 implicitWidth: 448
implicitHeight: multiline ? Math.max((edit.implicitHeight + topPadding + bottomPadding), 44) : 44 implicitHeight: multiline ? Math.min(Math.max(
(edit.implicitHeight + topPadding + bottomPadding),
44, root.minimumHeight), root.maximumHeight) : 44
Rectangle { Rectangle {
width: parent.width width: parent.width
height: maximumHeight != 0 ? Math.min( height: maximumHeight != 0 ? Math.min(
minimumHeight != 0 ? Math.max(statusBaseInput.implicitHeight, minimumHeight) minimumHeight
: statusBaseInput.implicitHeight, maximumHeight) : parent.height != 0 ? Math.max(
root.implicitHeight,
minimumHeight) : root.implicitHeight,
maximumHeight) : parent.height
color: Theme.palette.baseColor2 color: Theme.palette.baseColor2
radius: 8 radius: 8
@ -107,16 +91,15 @@ Item {
border.width: 1 border.width: 1
border.color: { border.color: {
if (!statusBaseInput.valid && statusBaseInput.dirty) { if (!root.valid && root.dirty) {
return Theme.palette.dangerColor1; return Theme.palette.dangerColor1
} }
if (edit.activeFocus) { if (edit.activeFocus) {
return Theme.palette.primaryColor1; return Theme.palette.primaryColor1
} }
return sensor.containsMouse ? Theme.palette.primaryColor2 : "transparent" return sensor.containsMouse ? Theme.palette.primaryColor2 : "transparent"
} }
MouseArea { MouseArea {
id: sensor id: sensor
enabled: !edit.activeFocus enabled: !edit.activeFocus
@ -127,100 +110,58 @@ Item {
edit.forceActiveFocus() edit.forceActiveFocus()
} }
StatusSmartIdenticon { RowLayout {
id: emoji anchors {
anchors.left: parent.left fill: parent
anchors.leftMargin: 10 leftMargin: root.leftPadding
anchors.verticalCenter: parent.verticalCenter rightMargin: root.rightPadding
icon.width: !statusBaseInput.icon.emoji ? 20 : 30
icon.height: !statusBaseInput.icon.emoji ? 20 : 30
icon.background: statusBaseInput.icon.background
icon.color: statusBaseInput.icon.color
icon.letterSize: statusBaseInput.icon.letterSize
icon.emoji: statusBaseInput.icon.emoji
icon.name: !statusBaseInput.icon.emoji ? statusBaseInput.icon.name : ""
visible: (!!statusBaseInput.icon.emoji || !!statusBaseInput.icon.name) && statusBaseInput.isIconSelectable
MouseArea {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
hoverEnabled: true
enabled: emoji.visible
onClicked: statusBaseInput.iconClicked()
}
} }
StatusIcon { clip: true
id: statusIcon
anchors.topMargin: 10
anchors.left: statusBaseInput.leftIcon ? parent.left : undefined
anchors.right: !statusBaseInput.leftIcon ? parent.right : undefined
anchors.leftMargin: 10
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
icon: statusBaseInput.icon.name
width: statusBaseInput.icon.width
height: statusBaseInput.icon.height
color: statusBaseInput.icon.color
visible: !!statusBaseInput.icon.name && !statusBaseInput.isIconSelectable
}
Item { Loader {
id: statusBaseInputLeftComponentSlot sourceComponent: {
anchors.left: parent.left if (root.leftComponent) return root.leftComponent
anchors.leftMargin: 12 if (!root.leftIcon) return undefined
width: childrenRect.width if (root.icon.emoji) return identiconComponent
height: childrenRect.height if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
anchors.verticalCenter: parent.verticalCenter return undefined
}
} }
Flickable { Flickable {
id: flick id: flick
anchors.top: parent.top
anchors.bottom: parent.bottom Layout.fillHeight: true
anchors.left: { Layout.fillWidth: true
if (statusIcon.visible && statusBaseInput.leftIcon) { Layout.topMargin: root.topPadding
return statusIcon.right; Layout.bottomMargin: root.bottomPadding
} else if (emoji.visible) {
return emoji.right;
} else if (!!statusBaseInput.leftComponent) {
return statusBaseInputLeftComponentSlot.right;
} else {
return parent.left;
}
}
anchors.right: {
if (!!statusBaseInput.component) {
return statusBaseInputComponentSlot.left
}
return statusIcon.visible && !statusBaseInput.leftIcon ? statusIcon.left : parent.right
}
anchors.leftMargin: (statusIcon.visible && statusBaseInput.leftIcon)
|| !!statusBaseInput.leftComponent ? 8
: statusBaseInput.leftPadding
anchors.rightMargin: {
return clearable ? clearButtonLoader.width + 12 :
(statusIcon.visible && !leftIcon) || !!statusBaseInput.component ? 8 : 0
}
contentWidth: edit.paintedWidth contentWidth: edit.paintedWidth
contentHeight: edit.paintedHeight contentHeight: edit.paintedHeight
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
QC.ScrollBar.vertical: QC.ScrollBar { interactive: multiline; enabled: multiline } QC.ScrollBar.vertical: QC.ScrollBar {
interactive: multiline
enabled: multiline
}
clip: true clip: true
function ensureVisible(r) { function ensureVisible(r) {
if (contentX >= r.x) if (contentX >= r.x)
contentX = r.x; contentX = r.x
else if (contentX+width <= r.x+r.width) else if (contentX + width <= r.x + r.width)
contentX = r.x+r.width-width; contentX = r.x + r.width - width
if (contentY >= r.y) if (contentY >= r.y)
contentY = r.y; contentY = r.y
else if (contentY+height <= r.y+r.height) else if (contentY + height <= r.y + r.height)
contentY = r.y+r.height-height; contentY = r.y + r.height - height
} }
TextEdit { TextEdit {
id: edit id: edit
property string previousText: text property string previousText: text
property var keyEvent
width: flick.width width: flick.width
height: flick.height height: flick.height
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@ -231,87 +172,66 @@ Item {
font.pixelSize: 15 font.pixelSize: 15
font.family: Theme.palette.baseFont.name font.family: Theme.palette.baseFont.name
color: Theme.palette.directColor1 color: Theme.palette.directColor1
onCursorRectangleChanged: { flick.ensureVisible(cursorRectangle); } wrapMode: root.multiline ? Text.WrapAtWordBoundaryOrAnywhere : TextEdit.NoWrap
wrapMode: statusBaseInput.multiline ? Text.WrapAtWordBoundaryOrAnywhere : TextEdit.NoWrap
onActiveFocusChanged: {
if (statusBaseInput.pristine) {
statusBaseInput.pristine = false
}
}
Keys.onPressed: {
edit.keyEvent = event.key;
}
Keys.onReturnPressed: {
if (multiline) {
event.accepted = false
} else {
event.accepted = true
}
}
Keys.onEnterPressed: {
if (multiline) {
event.accepted = false
} else {
event.accepted = true
}
}
Keys.onReturnPressed: event.accepted = !multiline
Keys.onEnterPressed: event.accepted = !multiline
Keys.forwardTo: [statusBaseInput] Keys.forwardTo: [statusBaseInput]
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
onActiveFocusChanged: if (root.pristine) root.pristine = false
onTextChanged: { onTextChanged: {
statusBaseInput.dirty = true root.dirty = true
if (statusBaseInput.maximumLength > 0) { if (root.maximumLength > 0) {
if (text.length > statusBaseInput.maximumLength) { if (text.length > root.maximumLength) {
var cursor = cursorPosition; var cursor = cursorPosition
text = previousText; text = previousText
if (cursor > text.length) { if (cursor > text.length) {
cursorPosition = text.length; cursorPosition = text.length
} else { } else {
cursorPosition = cursor-1; cursorPosition = cursor - 1
} }
} }
previousText = text previousText = text
} }
} }
StatusBaseText { StatusBaseText {
id: placeholder id: placeholder
visible: (edit.text.length === 0) visible: (edit.text.length === 0)
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: statusBaseInput.rightPadding anchors.rightMargin: root.rightPadding
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 15 font.pixelSize: 15
elide: StatusBaseText.ElideRight elide: StatusBaseText.ElideRight
font.family: Theme.palette.baseFont.name font.family: Theme.palette.baseFont.name
color: statusBaseInput.enabled ? Theme.palette.baseColor1 : color: root.enabled ? Theme.palette.baseColor1 : Theme.palette.directColor6
Theme.palette.directColor6
} }
} }
} // Flickable } // Flickable
Item { Loader {
id: statusBaseInputComponentSlot sourceComponent: {
anchors.right: parent.right if (root.rightComponent) return root.rightComponent
anchors.rightMargin: 12 if (root.clearable) return clearButton
width: childrenRect.width if (root.leftIcon) return undefined
height: childrenRect.height if (root.icon.emoji) return identiconComponent
anchors.verticalCenter: parent.verticalCenter if (root.icon.name) return isIconSelectable ? identiconComponent : iconComponent
return undefined
}
}
} }
} }
} // Rectangle } // Rectangle
Loader {
id: clearButtonLoader Component {
sourceComponent: StatusFlatRoundButton {
id: clearButton id: clearButton
visible: edit.text.length != 0 &&
statusBaseInput.clearable && StatusFlatRoundButton {
!statusBaseInput.multiline && visible: edit.text.length != 0 && root.clearable && !root.multiline
edit.activeFocus && edit.activeFocus
type: StatusFlatRoundButton.Type.Secondary type: StatusFlatRoundButton.Type.Secondary
width: 24 width: 24
height: 24 height: 24
@ -325,5 +245,41 @@ Item {
} }
} }
Component {
id: identiconComponent
StatusSmartIdenticon {
id: identicon
icon.width: !root.icon.emoji ? 20 : 30
icon.height: !root.icon.emoji ? 20 : 30
icon.background: root.icon.background
icon.color: root.icon.color
icon.letterSize: root.icon.letterSize
icon.emoji: root.icon.emoji
icon.name: !root.icon.emoji ? root.icon.name : ""
MouseArea {
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
hoverEnabled: true
enabled: identicon.visible
onClicked: root.iconClicked()
}
}
}
Component {
id: iconComponent
StatusIcon {
id: statusIcon
icon: root.icon.name
width: root.icon.width
height: root.icon.height
color: root.icon.color
}
}
} }