FluentUI/src/controls/FluAutoSuggestBox.qml

298 lines
8.7 KiB
QML
Raw Normal View History

2023-03-25 13:35:21 +08:00
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
2023-03-09 15:49:37 +08:00
TextField{
2023-03-09 23:11:59 +08:00
2023-03-30 17:16:57 +08:00
property var items:[]
2023-03-09 23:11:59 +08:00
property int fontStyle: FluText.Body
property int pixelSize : FluTheme.textSize
2023-03-13 18:23:46 +08:00
property int iconSource: 0
2023-03-20 18:22:32 +08:00
property bool disabled: false
2023-03-30 17:16:57 +08:00
signal itemClicked(var data)
2023-03-29 21:43:01 +08:00
signal handleClicked
2023-03-30 18:23:33 +08:00
QtObject{
id:d
property bool flagVisible: true
}
2023-03-09 15:49:37 +08:00
id:input
width: 300
2023-03-20 18:22:32 +08:00
enabled: !disabled
color: {
if(disabled){
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
2023-03-20 18:22:32 +08:00
}
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
2023-03-20 18:22:32 +08:00
}
2023-03-30 18:23:33 +08:00
selectionColor: FluTheme.primaryColor.lightest
2023-03-28 21:37:10 +08:00
renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering
2023-03-09 23:11:59 +08:00
placeholderTextColor: {
2023-03-20 18:22:32 +08:00
if(disabled){
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
2023-03-20 18:22:32 +08:00
}
2023-03-09 23:11:59 +08:00
if(focus){
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1)
2023-03-09 23:11:59 +08:00
}
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1)
2023-03-09 23:11:59 +08:00
}
2023-03-11 20:33:29 +08:00
rightPadding: icon_right.visible ? 50 : 30
2023-03-09 15:49:37 +08:00
selectByMouse: true
2023-03-12 14:26:03 +08:00
Keys.onUpPressed: {
list_view.currentIndex = Math.max(list_view.currentIndex-1,0)
}
Keys.onDownPressed: {
list_view.currentIndex = Math.min(list_view.currentIndex+1,list_view.count-1)
}
Keys.onEnterPressed:handleClicked()
Keys.onReturnPressed:handleClicked()
2023-03-09 23:11:59 +08:00
font.bold: {
switch (fontStyle) {
case FluText.Display:
return true
case FluText.TitleLarge:
return true
case FluText.Title:
return true
2023-03-29 21:43:01 +08:00
case FluText.SubTitle:
2023-03-09 23:11:59 +08:00
return true
case FluText.BodyStrong:
return true
case FluText.Body:
return false
case FluText.Caption:
return false
default:
return false
}
}
font.pixelSize: {
switch (fontStyle) {
case FluText.Display:
2023-03-29 21:43:01 +08:00
return text.pixelSize * 4.857
2023-03-09 23:11:59 +08:00
case FluText.TitleLarge:
2023-03-29 21:43:01 +08:00
return text.pixelSize * 2.857
2023-03-09 23:11:59 +08:00
case FluText.Title:
2023-03-29 21:43:01 +08:00
return text.pixelSize * 2
case FluText.SubTitle:
return text.pixelSize * 1.428
2023-03-09 23:11:59 +08:00
case FluText.Body:
2023-03-29 21:43:01 +08:00
return text.pixelSize * 1.0
case FluText.BodyStrong:
return text.pixelSize * 1.0
2023-03-09 23:11:59 +08:00
case FluText.Caption:
2023-03-29 21:43:01 +08:00
return text.pixelSize * 0.857
2023-03-09 23:11:59 +08:00
default:
2023-03-29 21:43:01 +08:00
return text.pixelSize * 1.0
2023-03-09 23:11:59 +08:00
}
}
2023-03-09 15:49:37 +08:00
background: FluTextBoxBackground{
inputItem: input
FluIconButton{
2023-03-12 21:49:11 +08:00
iconSource:FluentIcons.ChromeClose
2023-03-11 14:43:07 +08:00
iconSize: 10
2023-03-09 15:49:37 +08:00
width: 20
height: 20
opacity: 0.5
visible: input.text !== ""
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
2023-03-11 20:33:29 +08:00
rightMargin: icon_right.visible ? 25 : 5
2023-03-09 15:49:37 +08:00
}
onClicked:{
input.text = ""
}
}
2023-03-11 20:33:29 +08:00
FluIcon{
id:icon_right
2023-03-12 21:49:11 +08:00
iconSource: input.iconSource
2023-03-11 20:33:29 +08:00
iconSize: 15
opacity: 0.5
2023-03-13 18:23:46 +08:00
visible: input.iconSource != 0
2023-03-11 20:33:29 +08:00
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 5
}
}
2023-03-09 15:49:37 +08:00
}
Component.onCompleted: {
searchData()
}
Popup{
id:input_popup
y:input.height
2023-03-30 18:23:33 +08:00
focus: false
2023-03-28 18:14:14 +08:00
enter: Transition {
NumberAnimation {
property: "y"
from:0
to:input_popup.y
duration: 150
}
2023-03-29 15:43:23 +08:00
NumberAnimation {
property: "opacity"
from:0
to:1
duration: 150
}
2023-03-28 18:14:14 +08:00
}
2023-03-12 14:26:03 +08:00
onVisibleChanged: {
if(visible){
list_view.currentIndex = -1
}
}
2023-03-09 15:49:37 +08:00
background: Rectangle{
width: input.width
radius: 4
FluShadow{
radius: 4
}
2023-03-28 21:37:10 +08:00
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
2023-03-09 15:49:37 +08:00
height: 38*Math.min(Math.max(list_view.count,1),8)
ListView{
id:list_view
anchors.fill: parent
clip: true
2023-03-12 14:26:03 +08:00
currentIndex: -1
2023-03-14 18:23:12 +08:00
ScrollBar.vertical: FluScrollBar {}
2023-03-09 15:49:37 +08:00
header: Item{
width: input.width
height: visible ? 38 : 0
visible: list_view.count === 0
FluText{
text:"没有找到结果"
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
2023-03-09 23:11:59 +08:00
leftMargin: 10
2023-03-09 15:49:37 +08:00
}
}
}
2023-03-12 14:26:03 +08:00
delegate:Control{
2023-03-09 15:49:37 +08:00
width: input.width
2023-03-12 14:26:03 +08:00
padding:10
background: Rectangle{
2023-03-09 15:49:37 +08:00
color: {
2023-03-12 14:26:03 +08:00
if(list_view.currentIndex === index){
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
2023-03-12 14:26:03 +08:00
}
if(hovered){
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
2023-03-09 15:49:37 +08:00
}
2023-03-28 21:37:10 +08:00
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
2023-03-09 15:49:37 +08:00
}
MouseArea{
2023-03-12 14:26:03 +08:00
id:mouse_area
2023-03-09 15:49:37 +08:00
anchors.fill: parent
2023-03-12 14:26:03 +08:00
Connections{
target: input
function onHandleClicked(){
if((list_view.currentIndex === index)){
mouse_area.handleClick()
}
}
}
2023-03-30 18:23:33 +08:00
onClicked: handleClick(modelData)
2023-03-09 15:49:37 +08:00
}
2023-03-12 14:26:03 +08:00
Rectangle{
width: 3
color:FluTheme.primaryColor.dark
visible: list_view.currentIndex === index
radius: 3
height: 20
2023-03-09 15:49:37 +08:00
anchors{
left: parent.left
2023-03-12 14:26:03 +08:00
verticalCenter: parent.verticalCenter
2023-03-09 15:49:37 +08:00
}
}
}
2023-03-12 14:26:03 +08:00
contentItem: FluText{
2023-03-30 17:16:57 +08:00
text:modelData.title
2023-03-12 14:26:03 +08:00
anchors{
verticalCenter: parent.verticalCenter
}
}
2023-03-09 15:49:37 +08:00
}
}
}
}
2023-03-30 18:23:33 +08:00
function handleClick(modelData){
input_popup.visible = false
input.itemClicked(modelData)
2023-03-30 18:34:03 +08:00
updateText(modelData.title)
}
function updateText(text){
2023-03-30 18:23:33 +08:00
d.flagVisible = false
2023-03-30 18:34:03 +08:00
input.text = text
2023-03-30 18:23:33 +08:00
d.flagVisible = true
}
2023-03-09 15:49:37 +08:00
onTextChanged: {
searchData()
2023-03-30 18:23:33 +08:00
if(d.flagVisible){
input_popup.visible = true
}
}
TapHandler {
acceptedButtons: Qt.RightButton
2023-03-30 18:34:03 +08:00
onTapped: input.echoMode !== TextInput.Password && menu.popup()
2023-03-30 18:23:33 +08:00
}
2023-03-30 18:34:03 +08:00
2023-03-30 18:23:33 +08:00
FluMenu{
id:menu
focus: false
FluMenuItem{
text: "剪切"
visible: input.text !== ""
onClicked: {
input.cut()
}
}
FluMenuItem{
text: "复制"
visible: input.selectedText !== ""
onClicked: {
input.copy()
}
}
FluMenuItem{
text: "粘贴"
visible: input.canPaste
onClicked: {
input.paste()
}
}
FluMenuItem{
text: "全选"
visible: input.text !== ""
onClicked: {
input.selectAll()
}
}
2023-03-09 15:49:37 +08:00
}
function searchData(){
var result = []
2023-03-30 17:16:57 +08:00
if(items==null){
2023-03-11 20:33:29 +08:00
list_view.model = result
return
}
2023-03-30 17:16:57 +08:00
items.map(function(item){
if(item.title.indexOf(input.text)!==-1){
2023-03-09 15:49:37 +08:00
result.push(item)
}
})
list_view.model = result
}
}