197 lines
6.1 KiB
QML
197 lines
6.1 KiB
QML
import QtQuick 2.13
|
|
import QtQuick.Controls 2.13
|
|
import QtQuick.Layouts 1.13
|
|
import QtGraphicalEffects 1.13
|
|
|
|
import utils 1.0
|
|
import "../"
|
|
import "../panels"
|
|
|
|
Item {
|
|
enum MenuAlignment {
|
|
Left,
|
|
Right,
|
|
Center
|
|
}
|
|
property string label: ""
|
|
readonly property bool hasLabel: label !== ""
|
|
property color bgColor: Style.current.inputBackground
|
|
readonly property int labelMargin: 7
|
|
property var model
|
|
property alias menu: selectMenu
|
|
property color bgColorHover: bgColor
|
|
property alias selectedItemView: selectedItemContainer.children
|
|
property int caretRightMargin: Style.current.padding
|
|
property int caretLeftMargin: Style.current.halfPadding
|
|
property alias select: inputRectangle
|
|
property int menuAlignment: Select.MenuAlignment.Right
|
|
property Item zeroItemsView: Item {}
|
|
property int selectedItemRightMargin: caret.width + caretRightMargin + caretLeftMargin
|
|
property string validationError: ""
|
|
property alias validationErrorAlignment: validationErrorText.horizontalAlignment
|
|
property int validationErrorTopMargin: Style.current.halfPadding
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
|
|
id: root
|
|
height: inputRectangle.height + (hasLabel ? inputLabel.height + labelMargin : 0) + (!!validationError ? (validationErrorText.height + validationErrorTopMargin) : 0)
|
|
|
|
StyledText {
|
|
id: inputLabel
|
|
visible: hasLabel
|
|
text: root.label
|
|
font.weight: Font.Medium
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 0
|
|
anchors.top: parent.top
|
|
anchors.topMargin: 0
|
|
font.pixelSize: 13
|
|
height: 18
|
|
}
|
|
|
|
Rectangle {
|
|
property bool hovered: false
|
|
id: inputRectangle
|
|
height: 56
|
|
color: hovered ? bgColorHover : bgColor
|
|
radius: Style.current.radius
|
|
anchors.top: root.hasLabel ? inputLabel.bottom : parent.top
|
|
anchors.topMargin: root.hasLabel ? root.labelMargin : 0
|
|
anchors.right: parent.right
|
|
anchors.left: parent.left
|
|
border.width: !!validationError ? 1 : 0
|
|
border.color: Style.current.danger
|
|
|
|
Item {
|
|
id: selectedItemContainer
|
|
anchors.fill: parent
|
|
}
|
|
|
|
SVGImage {
|
|
id: caret
|
|
width: 11
|
|
height: 6
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: caretRightMargin
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
fillMode: Image.PreserveAspectFit
|
|
source: Style.svg("caret")
|
|
}
|
|
ColorOverlay {
|
|
anchors.fill: caret
|
|
source: caret
|
|
color: Style.current.secondaryText
|
|
}
|
|
}
|
|
|
|
// create a drop shadow externally so that it is not clipped by the
|
|
// rounded corners of the menu background
|
|
Rectangle {
|
|
width: selectMenu.width
|
|
height: selectMenu.height
|
|
x: selectMenu.x
|
|
y: selectMenu.y
|
|
visible: selectMenu.opened
|
|
color: Style.current.background
|
|
radius: Style.current.radius
|
|
border.color: Style.current.border
|
|
layer.enabled: true
|
|
layer.effect: DropShadow {
|
|
verticalOffset: 3
|
|
radius: Style.current.radius
|
|
samples: 15
|
|
fast: true
|
|
cached: true
|
|
color: "#22000000"
|
|
}
|
|
}
|
|
|
|
Menu {
|
|
id: selectMenu
|
|
property var items: []
|
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
|
width: parent.width
|
|
background: Rectangle {
|
|
// do not add a drop shadow effect here or it will be clipped
|
|
radius: Style.current.radius
|
|
color: Style.current.background
|
|
}
|
|
clip: true
|
|
delegate: menuItem
|
|
|
|
Repeater {
|
|
id: menuItems
|
|
model: root.model
|
|
property int zeroItemsViewHeight
|
|
delegate: selectMenu.delegate
|
|
onItemAdded: {
|
|
root.zeroItemsView.visible = false
|
|
root.zeroItemsView.height = 0
|
|
}
|
|
onItemRemoved: {
|
|
if (count === 0) {
|
|
root.zeroItemsView.visible = true
|
|
root.zeroItemsView.height = zeroItemsViewHeight
|
|
}
|
|
}
|
|
Component.onCompleted: {
|
|
zeroItemsViewHeight = root.zeroItemsView.height
|
|
root.zeroItemsView.visible = count === 0
|
|
root.zeroItemsView.height = count !== 0 ? 0 : root.zeroItemsView.height
|
|
selectMenu.insertItem(0, root.zeroItemsView)
|
|
}
|
|
}
|
|
}
|
|
TextEdit {
|
|
id: validationErrorText
|
|
visible: !!validationError
|
|
text: validationError
|
|
anchors.top: inputRectangle.bottom
|
|
anchors.topMargin: validationErrorTopMargin
|
|
selectByMouse: true
|
|
readOnly: true
|
|
font.pixelSize: 12
|
|
height: 16
|
|
color: Style.current.danger
|
|
width: parent.width
|
|
horizontalAlignment: TextEdit.AlignRight
|
|
}
|
|
MouseArea {
|
|
id: mouseArea
|
|
anchors.fill: inputRectangle
|
|
cursorShape: Qt.PointingHandCursor
|
|
hoverEnabled: true
|
|
onEntered: {
|
|
inputRectangle.hovered = true
|
|
}
|
|
onExited: {
|
|
inputRectangle.hovered = false
|
|
}
|
|
onClicked: {
|
|
if (selectMenu.opened) {
|
|
selectMenu.close()
|
|
} else {
|
|
const rightOffset = inputRectangle.width - selectMenu.width
|
|
let offset = rightOffset
|
|
switch (root.menuAlignment) {
|
|
case Select.MenuAlignment.Left:
|
|
offset = 0
|
|
break
|
|
case Select.MenuAlignment.Right:
|
|
offset = rightOffset
|
|
break
|
|
case Select.MenuAlignment.Center:
|
|
offset = rightOffset / 2
|
|
}
|
|
selectMenu.popup(inputRectangle.x + offset, inputRectangle.y + inputRectangle.height + 8)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*##^##
|
|
Designer {
|
|
D{i:0;formeditorColor:"#ffffff";formeditorZoom:1.25}
|
|
}
|
|
##^##*/
|