status-desktop/ui/app/AppLayouts/Chat/panels/InlineSelectorPanel.qml

272 lines
10 KiB
QML
Raw Normal View History

import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtGraphicalEffects 1.0
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Popups.Dialog 0.1
import utils 1.0
Item {
id: root
property alias model: listView.model
property alias delegate: listView.delegate
property alias suggestionsModel: suggestionsListView.model
property alias suggestionsDelegate: suggestionsListView.delegate
property size suggestionsDelegateSize: Qt.size(344, 64)
readonly property alias label: label
readonly property alias warningLabel: warningLabel
readonly property alias edit: edit
signal confirmed()
signal rejected()
signal enterKeyPressed()
signal upKeyPressed()
signal downKeyPressed()
signal entryAccepted(var suggestionsDelegate)
signal entryRemoved(var delegate)
signal textPasted(string text)
implicitWidth: mainLayout.implicitWidth
implicitHeight: mainLayout.implicitHeight
RowLayout {
id: mainLayout
anchors.fill: parent
spacing: Style.current.padding
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.current.halfPadding
color: Theme.palette.baseColor2
radius: Style.current.radius
RowLayout {
anchors.fill: parent
spacing: Style.current.halfPadding
StatusBaseText {
id: label
Layout.leftMargin: Style.current.padding
Layout.alignment: Qt.AlignVCenter
visible: text !== ""
font.pixelSize: 15
color: Theme.palette.baseColor1
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
StatusScrollView {
id: scrollView
function positionViewAtEnd() {
if (scrollView.contentWidth > scrollView.width) {
scrollView.contentX = scrollView.contentWidth - scrollView.width
} else {
scrollView.contentX = 0
}
}
anchors.fill: parent
padding: 0
onContentWidthChanged: positionViewAtEnd()
onWidthChanged: positionViewAtEnd()
RowLayout {
height: scrollView.height
StatusListView {
id: listView
Layout.fillWidth: true
Layout.preferredHeight: 30
implicitWidth: contentWidth
orientation: ListView.Horizontal
spacing: Style.current.halfPadding
}
TextInput {
id: edit
Layout.minimumWidth: 4
Layout.fillHeight: true
verticalAlignment: Text.AlignVCenter
font.pixelSize: 15
color: Theme.palette.directColor1
selectByMouse: true
selectionColor: Theme.palette.primaryColor2
selectedTextColor: color
cursorDelegate: Rectangle {
color: Theme.palette.primaryColor1
implicitWidth: 2
radius: 1
visible: edit.cursorVisible
SequentialAnimation on visible {
loops: Animation.Infinite
running: edit.cursorVisible
PropertyAnimation { to: false; duration: 600; }
PropertyAnimation { to: true; duration: 600; }
}
}
Keys.onPressed: {
if (event.matches(StandardKey.Paste)) {
event.accepted = true
const previousText = text;
const previousSelectedText = selectedText;
paste()
if (previousText === "" || previousSelectedText.length === previousText.length)
root.textPasted(text)
return;
}
if (suggestionsDialog.visible) {
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
root.entryAccepted(suggestionsListView.itemAtIndex(suggestionsListView.currentIndex))
} else if (event.key === Qt.Key_Up) {
suggestionsListView.decrementCurrentIndex()
} else if (event.key === Qt.Key_Down) {
suggestionsListView.incrementCurrentIndex()
}
} else {
if (event.key === Qt.Key_Backspace && edit.text === "") {
root.entryRemoved(listView.itemAtIndex(listView.count - 1))
} else if (event.key === Qt.Key_Return || event.key === Qt.Enter) {
root.enterKeyPressed()
} else if (event.key === Qt.Key_Escape) {
root.rejected()
} else if (event.key === Qt.Key_Up) {
root.upKeyPressed()
} else if (event.key === Qt.Key_Down) {
root.downKeyPressed()
}
}
}
}
// ensure edit cursor is visible
Item {
Layout.fillHeight: true
implicitWidth: 1
}
}
ScrollBar.horizontal: StatusScrollBar {
id: scrollBar
parent: scrollView.parent
anchors.top: scrollView.bottom
anchors.left: scrollView.left
anchors.right: scrollView.right
policy: ScrollBar.AsNeeded
visible: resolveVisibility(policy, scrollView.width, scrollView.contentWidth)
}
}
}
StatusBaseText {
id: warningLabel
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.rightMargin: Style.current.padding
visible: text !== ""
font.pixelSize: 10
color: Theme.palette.dangerColor1
}
}
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onPressed: {
edit.forceActiveFocus()
mouse.accepted = false
}
}
}
StatusButton {
objectName: "inlineSelectorConfirmButton"
Layout.alignment: Qt.AlignVCenter
enabled: (listView.count > 0)
text: qsTr("Confirm")
onClicked: root.confirmed()
}
StatusButton {
Layout.alignment: Qt.AlignVCenter
text: qsTr("Cancel")
type: StatusBaseButton.Type.Danger
onClicked: root.rejected()
}
}
Popup {
id: suggestionsDialog
parent: scrollView
x: Math.min(parent.width, parent.contentWidth)
y: parent.height + Style.current.halfPadding
visible: edit.text !== ""
padding: Style.current.halfPadding
background: StatusDialogBackground {
id: bg
layer.enabled: true
layer.effect: DropShadow {
source: bg
horizontalOffset: 0
verticalOffset: 4
radius: 12
samples: 25
spread: 0.2
color: Theme.palette.dropShadow
}
}
height: suggestionsListView.count ?
Math.min(400, suggestionsListView.count * suggestionsDelegateSize.height + 2 * padding) :
noResultsFoundText.height + 2 * padding
width: suggestionsDelegateSize.width
ColumnLayout {
anchors.fill: parent
StatusBaseText {
id: noResultsFoundText
Layout.fillWidth: true
visible: root.suggestionsModel.count === 0
text: qsTr("No results found")
color: Theme.palette.baseColor1
}
StatusListView {
id: suggestionsListView
Layout.fillWidth: true
Layout.fillHeight: true
visible: root.suggestionsModel.count
highlightMoveDuration: 0
highlightMoveVelocity: -1
verticalScrollBar {
visible: contentHeight > height
policy: ScrollBar.AlwaysOn
}
onVisibleChanged: currentIndex = 0
onCountChanged: currentIndex = 0
}
}
}
}