This commit is contained in:
朱子楚\zhuzi 2023-04-10 22:05:20 +08:00
parent 1f2d0d9b9f
commit 70f048f629
9 changed files with 381 additions and 815 deletions

View File

@ -35,13 +35,12 @@ FluScrollablePage{
Repeater{ Repeater{
id:repeater id:repeater
model: [{title:"Top",mode:FluNavigationView2.Top},{title:"Open",mode:FluNavigationView2.Open},{title:"Compact",mode:FluNavigationView2.Compact},{title:"Minimal",mode:FluNavigationView2.Minimal},{title:"Auto",mode:FluNavigationView2.Auto}] model: [{title:"Open",mode:FluNavigationView.Open},{title:"Compact",mode:FluNavigationView.Compact},{title:"Minimal",mode:FluNavigationView.Minimal},{title:"Auto",mode:FluNavigationView.Auto}]
delegate: FluRadioButton{ delegate: FluRadioButton{
selected : MainEvent.displayMode===modelData.mode selected : MainEvent.displayMode===modelData.mode
text:modelData.title text:modelData.title
onClicked:{ onClicked:{
MainEvent.displayMode = modelData.mode MainEvent.displayMode = modelData.mode
console.debug(modelData.mode)
} }
} }
} }

View File

@ -5,6 +5,6 @@ import FluentUI
QtObject { QtObject {
property int displayMode : FluNavigationView2.Open property int displayMode : FluNavigationView.Auto
} }

View File

@ -21,7 +21,7 @@ FluWindow {
darkText: "Dark Mode" darkText: "Dark Mode"
} }
FluNavigationView2{ FluNavigationView{
id:nav_view id:nav_view
anchors.fill: parent anchors.fill: parent
items: ItemsOriginal items: ItemsOriginal
@ -33,7 +33,7 @@ FluWindow {
autoSuggestBox:FluAutoSuggestBox{ autoSuggestBox:FluAutoSuggestBox{
width: 280 width: 280
anchors.centerIn: parent anchors.centerIn: parent
iconSource: FluentIcons.Zoom iconSource: FluentIcons.Search
items: ItemsOriginal.getSearchData() items: ItemsOriginal.getSearchData()
placeholderText: "Search" placeholderText: "Search"
onItemClicked: onItemClicked:

View File

@ -33,7 +33,6 @@ void Fluent::registerTypes(const char *uri){
qmlRegisterType<WindowHelper>(uri,major,minor,"WindowHelper"); qmlRegisterType<WindowHelper>(uri,major,minor,"WindowHelper");
qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet"); qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluNavigationView2.qml"),uri,major,minor,"FluNavigationView2");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluStatusView.qml"),uri,major,minor,"FluStatusView"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluStatusView.qml"),uri,major,minor,"FluStatusView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPagination.qml"),uri,major,minor,"FluPagination"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPagination.qml"),uri,major,minor,"FluPagination");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluToggleButton.qml"),uri,major,minor,"FluToggleButton"); qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluToggleButton.qml"),uri,major,minor,"FluToggleButton");

View File

@ -5,7 +5,7 @@ import FluentUI
FluTextBox{ FluTextBox{
property var items:[] property var items:[]
property string emptyText: "没有找到结果" property string emptyText: "没有找到结果"
property int autoSuggestBoxReplacement: FluentIcons.Zoom property int autoSuggestBoxReplacement: FluentIcons.Search
signal itemClicked(var data) signal itemClicked(var data)
signal handleClicked signal handleClicked
QtObject{ QtObject{

View File

@ -6,48 +6,112 @@ import FluentUI
Item { Item {
property alias logo : image_logo.source
property string title: ""
property FluObject items
property FluObject footerItems
property int displayMode: width<=700 ? FluNavigationView.Minimal : FluNavigationView.Open
property bool displaMinimalMenu : false
property Component autoSuggestBox
id:root
onDisplayModeChanged: {
if(displayMode === FluNavigationView.Minimal){
anim_navi.enabled = false
displaMinimalMenu = false
timer_anim_enable.restart()
}
}
Timer{
id:timer_anim_enable
interval: 150
onTriggered: {
anim_navi.enabled = true
}
}
enum DisplayMode { enum DisplayMode {
Minimal,
Open, Open,
Compact,
Minimal,
Auto Auto
} }
property url logo
property string title: ""
property FluObject items
property FluObject footerItems
property int displayMode: FluNavigationView.Auto
property Component autoSuggestBox
property var window : { property var window : {
if(Window.window == null) if(Window.window == null)
return null return null
return Window.window return Window.window
} }
id:control
QtObject{
id:d
property bool enableStack: true
property int displayMode: {
if(control.displayMode !==FluNavigationView.Auto){
return control.displayMode
}
if(control.width<=700){
return FluNavigationView.Minimal
}else if(control.width<=900){
return FluNavigationView.Compact
}else{
return FluNavigationView.Open
}
}
property var stackItems: []
property bool enableNavigationPanel: false
property bool isCompact: d.displayMode === FluNavigationView.Compact
property bool isMinimal: d.displayMode === FluNavigationView.Minimal
property bool isCompactAndPanel: d.displayMode === FluNavigationView.Compact && d.enableNavigationPanel
property bool isCompactAndNotPanel:d.displayMode === FluNavigationView.Compact && !d.enableNavigationPanel
property bool isMinimalAndPanel: d.displayMode === FluNavigationView.Minimal && d.enableNavigationPanel
onIsCompactAndNotPanelChanged: {
collapseAll()
}
onDisplayModeChanged: {
if(d.displayMode === FluNavigationView.Compact){
collapseAll()
}
if(d.displayMode === FluNavigationView.Minimal){
anim_layout_list_x.enabled = false
d.enableNavigationPanel = false
timer_anim_x_enable.restart()
}
}
function handleItems(){
var idx = 0
var data = []
if(items){
for(var i=0;i<items.children.length;i++){
var item = items.children[i]
item.idx = idx
data.push(item)
idx++
if(item instanceof FluPaneItemExpander){
for(var j=0;j<item.children.length;j++){
var itemChild = item.children[j]
itemChild.parent = item
itemChild.idx = idx
data.push(itemChild)
idx++
}
}
}
if(footerItems){
var comEmpty = Qt.createComponent("FluPaneItemEmpty.qml");
for(var k=0;k<footerItems.children.length;k++){
var itemFooter = footerItems.children[k]
if (comEmpty.status === Component.Ready) {
var objEmpty = comEmpty.createObject(items,{idx:idx});
itemFooter.idx = idx;
data.push(objEmpty)
idx++
}
}
}
}
return data
}
}
Component{
id:com_panel_item_empty
Item{
visible: false
}
}
Component{ Component{
id:com_panel_item_separatorr id:com_panel_item_separatorr
FluDivider{ FluDivider{
width: nav_list.width width: layout_list.width
height: { height: {
if(model.parent){ if(model.parent){
return model.parent.isExpand ? 1 : 0 return model.parent.isExpand ? 1 : 0
@ -76,7 +140,7 @@ Item {
duration: 150 duration: 150
} }
} }
width: nav_list.width width: layout_list.width
FluText{ FluText{
text:model.title text:model.title
fontStyle: FluText.BodyStrong fontStyle: FluText.BodyStrong
@ -93,8 +157,7 @@ Item {
id:com_panel_item_expander id:com_panel_item_expander
Item{ Item{
height: 38 height: 38
width: nav_list.width width: layout_list.width
Rectangle{ Rectangle{
radius: 4 radius: 4
anchors{ anchors{
@ -134,6 +197,18 @@ Item {
right: parent.right right: parent.right
rightMargin: 12 rightMargin: 12
} }
opacity: {
if(d.isCompactAndNotPanel){
return false
}
return true
}
visible:opacity
Behavior on opacity {
NumberAnimation{
duration: 220
}
}
Behavior on rotation { Behavior on rotation {
NumberAnimation{ NumberAnimation{
duration: 150 duration: 150
@ -145,12 +220,16 @@ Item {
hoverEnabled: true hoverEnabled: true
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
if(d.isCompactAndNotPanel){
control_popup.showPopup(Qt.point(50,mapToItem(control,0,0).y),model.children)
return
}
model.isExpand = !model.isExpand model.isExpand = !model.isExpand
} }
} }
color: { color: {
if(FluTheme.dark){ if(FluTheme.dark){
if((nav_list.currentIndex === position)&&type===0){ if((nav_list.currentIndex === idx)&&type===0){
return Qt.rgba(1,1,1,0.06) return Qt.rgba(1,1,1,0.06)
} }
if(item_mouse.containsMouse){ if(item_mouse.containsMouse){
@ -158,7 +237,7 @@ Item {
} }
return Qt.rgba(0,0,0,0) return Qt.rgba(0,0,0,0)
}else{ }else{
if(nav_list.currentIndex === position&&type===0){ if(nav_list.currentIndex === idx&&type===0){
return Qt.rgba(0,0,0,0.06) return Qt.rgba(0,0,0,0.06)
} }
if(item_mouse.containsMouse){ if(item_mouse.containsMouse){
@ -167,7 +246,6 @@ Item {
return Qt.rgba(0,0,0,0) return Qt.rgba(0,0,0,0)
} }
} }
FluIcon{ FluIcon{
id:item_icon id:item_icon
iconSource: { iconSource: {
@ -185,10 +263,21 @@ Item {
leftMargin: 3 leftMargin: 3
} }
} }
FluText{ FluText{
id:item_title id:item_title
text:model.title text:model.title
opacity: {
if(d.isCompactAndNotPanel){
return false
}
return true
}
visible:opacity
Behavior on opacity {
NumberAnimation{
duration: 220
}
}
anchors{ anchors{
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
left:item_icon.right left:item_icon.right
@ -219,8 +308,7 @@ Item {
} }
return 38 return 38
} }
width: nav_list.width width: layout_list.width
Rectangle{ Rectangle{
radius: 4 radius: 4
anchors{ anchors{
@ -238,41 +326,62 @@ Item {
hoverEnabled: true hoverEnabled: true
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
if(type===0){ if(type === 0){
if(model.tapFunc){ if(model.tapFunc){
model.tapFunc() model.tapFunc()
return }else{
nav_list.currentIndex = idx
layout_footer.currentIndex = -1
if(d.isMinimal || d.isCompact){
d.enableNavigationPanel = false
} }
if(nav_list.currentIndex !== position){
nav_list.currentIndex = position
model.tap()
} }
}else{
if(model.tapFunc){
model.tapFunc()
}else{ }else{
model.tap() model.tap()
d.stackItems.push(model)
nav_list.currentIndex = nav_list.count-layout_footer.count+idx
layout_footer.currentIndex = idx
if(d.isMinimal || d.isCompact){
d.enableNavigationPanel = false
}
}
} }
displaMinimalMenu = false
} }
} }
color: { color: {
if(FluTheme.dark){ if(FluTheme.dark){
if((nav_list.currentIndex === position)&&type===0){ if(type===0){
if(nav_list.currentIndex === idx){
return Qt.rgba(1,1,1,0.06) return Qt.rgba(1,1,1,0.06)
} }
}else{
if(nav_list.currentIndex === (nav_list.count-layout_footer.count+idx)){
return Qt.rgba(1,1,1,0.06)
}
}
if(item_mouse.containsMouse){ if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03) return Qt.rgba(1,1,1,0.03)
} }
return Qt.rgba(0,0,0,0) return Qt.rgba(0,0,0,0)
}else{ }else{
if(nav_list.currentIndex === position&&type===0){ if(type===0){
if(nav_list.currentIndex === idx){
return Qt.rgba(0,0,0,0.06) return Qt.rgba(0,0,0,0.06)
} }
}else{
if(nav_list.currentIndex === (nav_list.count-layout_footer.count+idx)){
return Qt.rgba(0,0,0,0.06)
}
}
if(item_mouse.containsMouse){ if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03) return Qt.rgba(0,0,0,0.03)
} }
return Qt.rgba(0,0,0,0) return Qt.rgba(0,0,0,0)
} }
} }
FluIcon{ FluIcon{
id:item_icon id:item_icon
iconSource: { iconSource: {
@ -290,10 +399,21 @@ Item {
leftMargin: 3 leftMargin: 3
} }
} }
FluText{ FluText{
id:item_title id:item_title
text:model.title text:model.title
opacity: {
if(d.isCompactAndNotPanel){
return false
}
return true
}
visible:opacity
Behavior on opacity {
NumberAnimation{
duration: 220
}
}
color:{ color:{
if(item_mouse.pressed){ if(item_mouse.pressed){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120 return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
@ -309,6 +429,7 @@ Item {
} }
} }
Item { Item {
id:nav_app_bar id:nav_app_bar
width: parent.width width: parent.width
@ -327,11 +448,17 @@ Item {
iconSize: 13 iconSize: 13
onClicked: { onClicked: {
nav_swipe.pop() nav_swipe.pop()
nav_list.stackIndex.pop() d.stackItems.pop()
var index = nav_list.stackIndex[nav_list.stackIndex.length-1] var item = d.stackItems[d.stackItems.length-1]
nav_list.enableStack = false d.enableStack = false
nav_list.currentIndex = index if(item.idx<(nav_list.count - layout_footer.count)){
nav_list.enableStack = true layout_footer.currentIndex = -1
}else{
console.debug(item.idx-(nav_list.count-layout_footer.count))
layout_footer.currentIndex = item.idx-(nav_list.count-layout_footer.count)
}
nav_list.currentIndex = item.idx
d.enableStack = true
} }
} }
FluIconButton{ FluIconButton{
@ -340,17 +467,17 @@ Item {
iconSize: 15 iconSize: 15
Layout.preferredWidth: 40 Layout.preferredWidth: 40
Layout.preferredHeight: 40 Layout.preferredHeight: 40
visible: displayMode === FluNavigationView.Minimal visible: d.isMinimal
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
onClicked: { onClicked: {
displaMinimalMenu = !displaMinimalMenu d.enableNavigationPanel = !d.enableNavigationPanel
} }
} }
Image{ Image{
id:image_logo id:image_logo
Layout.preferredHeight: 20 Layout.preferredHeight: 20
Layout.preferredWidth: 20 Layout.preferredWidth: 20
source: control.logo
Layout.leftMargin: { Layout.leftMargin: {
if(btn_nav.visible){ if(btn_nav.visible){
return 12 return 12
@ -361,7 +488,7 @@ Item {
} }
FluText{ FluText{
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
text:root.title text:control.title
Layout.leftMargin: 12 Layout.leftMargin: 12
fontStyle: FluText.Body fontStyle: FluText.Body
} }
@ -370,12 +497,12 @@ Item {
Item{ Item{
anchors{ anchors{
left: displayMode === FluNavigationView.Minimal ? parent.left : layout_list.right left: d.isMinimal || d.isCompactAndPanel ? parent.left : layout_list.right
top: nav_app_bar.bottom top: nav_app_bar.bottom
right: parent.right right: parent.right
bottom: parent.bottom bottom: parent.bottom
leftMargin: d.isCompactAndPanel ? 50 : 0
} }
StackView{ StackView{
id:nav_swipe id:nav_swipe
anchors.fill: parent anchors.fill: parent
@ -395,19 +522,39 @@ Item {
MouseArea{ MouseArea{
anchors.fill: parent anchors.fill: parent
enabled: (displayMode === FluNavigationView.Minimal && displaMinimalMenu) enabled: d.isMinimalAndPanel||d.isCompactAndPanel
onClicked: { onClicked: {
displaMinimalMenu = false d.enableNavigationPanel = false
} }
} }
Rectangle{ Rectangle{
id:layout_list id:layout_list
width: 300 width: {
if(d.isCompactAndNotPanel){
return 50
}
return 300
}
Behavior on width{
NumberAnimation{
duration: 150
}
}
Behavior on x{
id:anim_layout_list_x
NumberAnimation{
duration: 150
}
}
anchors{
top: parent.top
bottom: parent.bottom
}
border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,230/255,234/255,1) border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,230/255,234/255,1)
border.width: displayMode === FluNavigationView.Minimal ? 1 : 0 border.width: d.isMinimal || d.isCompactAndPanel ? 1 : 0
color: { color: {
if(displayMode === FluNavigationView.Minimal){ if(d.isMinimal || d.isCompactAndPanel){
return FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(243/255,243/255,243/255,1) return FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(243/255,243/255,243/255,1)
} }
if(window && window.active){ if(window && window.active){
@ -415,64 +562,62 @@ Item {
} }
return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
} }
anchors{
top: parent.top
bottom: parent.bottom
}
x: {
if(displayMode !== FluNavigationView.Minimal)
return 0
return (displayMode === FluNavigationView.Minimal && displaMinimalMenu) ? 0 : -width
}
Behavior on x{
id:anim_navi
NumberAnimation{
duration: 150
}
}
Behavior on color{ Behavior on color{
ColorAnimation { ColorAnimation {
duration: 300 duration: 300
} }
} }
x: {
if(d.displayMode !== FluNavigationView.Minimal)
return 0
return d.isMinimalAndPanel ? 0 : -width
}
Item{ Item{
id:layout_header id:layout_header
width: layout_list.width width: layout_list.width
clip: true
y:nav_app_bar.height y:nav_app_bar.height
height: { height: 38
Loader{
id:loader_auto_suggest_box
anchors.centerIn: parent
sourceComponent: autoSuggestBox
visible: {
if(d.isCompactAndNotPanel){
return false
}
return true
}
}
FluIconButton{
visible:d.isCompactAndNotPanel
hoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
pressedColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
normalColor: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0)
width:38
height:34
x:6
y:2
iconSize: 15
iconSource: {
if(loader_auto_suggest_box.item){ if(loader_auto_suggest_box.item){
return loader_auto_suggest_box.item.height return loader_auto_suggest_box.item.autoSuggestBoxReplacement
} }
return 0 return 0
} }
Loader{ onClicked: {
id:loader_auto_suggest_box d.enableNavigationPanel = !d.enableNavigationPanel
anchors.horizontalCenter: parent.horizontalCenter }
sourceComponent: autoSuggestBox
} }
} }
ListView{ ListView{
id:nav_list id:nav_list
property bool enableStack: true
property var stackIndex: []
clip: true clip: true
anchors{ ScrollBar.vertical: FluScrollBar {}
top: layout_header.bottom model:d.handleItems()
topMargin: 6
left: parent.left
right: parent.right
bottom: layout_footer.top
}
highlightMoveDuration: 150 highlightMoveDuration: 150
currentIndex: -1
onCurrentIndexChanged: {
if(enableStack){
stackIndex.push(currentIndex)
}
}
highlight: Item{ highlight: Item{
clip: true clip: true
Rectangle{ Rectangle{
@ -487,11 +632,26 @@ Item {
} }
} }
} }
ScrollBar.vertical: FluScrollBar {} onCurrentIndexChanged: {
model:handleItems() if(d.enableStack){
var item = model[currentIndex]
if(item instanceof FluPaneItem){
item.tap()
d.stackItems.push(item)
}
}
}
currentIndex: -1
anchors{
top: layout_header.bottom
topMargin: 6
left: parent.left
right: parent.right
bottom: layout_footer.top
}
delegate: Loader{ delegate: Loader{
property var model: modelData property var model: modelData
property var position: index property var idx: index
property int type: 0 property int type: 0
sourceComponent: { sourceComponent: {
if(modelData instanceof FluPaneItem){ if(modelData instanceof FluPaneItem){
@ -506,25 +666,43 @@ Item {
if(modelData instanceof FluPaneItemExpander){ if(modelData instanceof FluPaneItemExpander){
return com_panel_item_expander return com_panel_item_expander
} }
if(modelData instanceof FluPaneItemEmpty){
return com_panel_item_empty
}
} }
} }
} }
ListView{ ListView{
id:layout_footer id:layout_footer
clip: true
width: layout_list.width width: layout_list.width
height: childrenRect.height height: childrenRect.height
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
interactive: false
currentIndex: -1
model: { model: {
if(footerItems){ if(footerItems){
return footerItems.children return footerItems.children
} }
} }
interactive: false highlightMoveDuration: 150
currentIndex: -1 highlight: Item{
clip: true
Rectangle{
height: 18
radius: 1.5
color: FluTheme.primaryColor.dark
width: 3
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 6
}
}
}
delegate: Loader{ delegate: Loader{
property var model: modelData property var model: modelData
property var position: index property var idx: index
property int type: 1 property int type: 1
sourceComponent: { sourceComponent: {
if(modelData instanceof FluPaneItem){ if(modelData instanceof FluPaneItem){
@ -541,27 +719,91 @@ Item {
} }
} }
function handleItems(){ Popup{
var idx = 0 property var childModel
var data = [] id:control_popup
if(items){ enter: Transition {
for(var i=0;i<items.children.length;i++){ NumberAnimation {
var item = items.children[i] property: "opacity"
item.idx = idx from:0
data.push(item) to:1
idx++ duration: 150
}
}
background: Rectangle{
width: 160
radius: 4
FluShadow{
radius: 4
}
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
height: 38*Math.min(Math.max(list_view.count,1),8)
ListView{
id:list_view
anchors.fill: parent
clip: true
currentIndex: -1
model: control_popup.childModel
ScrollBar.vertical: FluScrollBar {}
delegate:FluControl{
width: 160
padding:10
background: Rectangle{
color: {
if(hovered){
return FluTheme.dark ? Qt.rgba(63/255,60/255,61/255,1) : Qt.rgba(237/255,237/255,242/255,1)
}
return FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(0,0,0,0)
}
}
contentItem: FluText{
text:modelData.title
anchors{
verticalCenter: parent.verticalCenter
}
}
onClicked: {
if(modelData.tapFunc){
modelData.tapFunc()
}else{
nav_list.currentIndex = idx
layout_footer.currentIndex = -1
if(d.isMinimal || d.isCompact){
d.enableNavigationPanel = false
}
}
control_popup.close()
}
}
}
}
function showPopup(pos,model){
control_popup.x = pos.x
control_popup.y = pos.y
control_popup.childModel = model
control_popup.open()
}
}
Timer{
id:timer_anim_x_enable
interval: 150
onTriggered: {
anim_layout_list_x.enabled = true
}
}
function collapseAll(){
for(var i=0;i<nav_list.model.length;i++){
var item = nav_list.model[i]
if(item instanceof FluPaneItemExpander){ if(item instanceof FluPaneItemExpander){
for(var j=0;j<item.children.length;j++){ item.isExpand = false
var itemChild = item.children[j]
itemChild.parent = item
itemChild.idx = idx
data.push(itemChild)
idx++
} }
} }
} }
}
return data function setCurrentIndex(index){
nav_list.currentIndex = index
} }
function getItems(){ function getItems(){
@ -572,10 +814,6 @@ Item {
nav_swipe.push(url) nav_swipe.push(url)
} }
function setCurrentIndex(index){
nav_list.currentIndex = index
}
function getCurrentIndex(){ function getCurrentIndex(){
return nav_list.currentIndex return nav_list.currentIndex
} }

View File

@ -1,668 +0,0 @@
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
Item {
enum DisplayMode {
Open,
Top,
Compact,
Minimal,
Auto
}
property url logo
property string title: ""
property FluObject items
property FluObject footerItems
property int displayMode: FluNavigationView2.Open
property Component autoSuggestBox
property var window : {
if(Window.window == null)
return null
return Window.window
}
id:control
QtObject{
id:d
property bool enableStack: true
property var stackItems: []
property bool enableNavigationPanel: false
function handleItems(){
var idx = 0
var data = []
if(items){
for(var i=0;i<items.children.length;i++){
var item = items.children[i]
item.idx = idx
data.push(item)
idx++
if(item instanceof FluPaneItemExpander){
for(var j=0;j<item.children.length;j++){
var itemChild = item.children[j]
itemChild.parent = item
itemChild.idx = idx
data.push(itemChild)
idx++
}
}
}
if(footerItems){
var comEmpty = Qt.createComponent("FluPaneItemEmpty.qml");
for(var k=0;k<footerItems.children.length;k++){
var itemFooter = footerItems.children[k]
if (comEmpty.status === Component.Ready) {
var objEmpty = comEmpty.createObject(items,{idx:idx});
itemFooter.idx = idx;
data.push(objEmpty)
idx++
}
}
}
}
return data
}
}
Component{
id:com_panel_item_empty
Item{
visible: false
}
}
Component{
id:com_panel_item_separatorr
FluDivider{
width: layout_list.width
height: {
if(model.parent){
return model.parent.isExpand ? 1 : 0
}
return 1
}
Behavior on height {
NumberAnimation{
duration: 150
}
}
}
}
Component{
id:com_panel_item_header
Item{
height: {
if(model.parent){
return model.parent.isExpand ? 30 : 0
}
return 30
}
Behavior on height {
NumberAnimation{
duration: 150
}
}
width: layout_list.width
FluText{
text:model.title
fontStyle: FluText.BodyStrong
anchors{
bottom: parent.bottom
left:parent.left
leftMargin: 10
}
}
}
}
Component{
id:com_panel_item_expander
Item{
height: 38
width: layout_list.width
Rectangle{
radius: 4
anchors{
top: parent.top
bottom: parent.bottom
left: parent.left
right: parent.right
topMargin: 2
bottomMargin: 2
leftMargin: 6
rightMargin: 6
}
Rectangle{
width: 3
height: 18
radius: 1.5
color: FluTheme.primaryColor.dark
visible: {
for(var i=0;i<model.children.length;i++){
var item = model.children[i]
if(item.idx === nav_list.currentIndex && !model.isExpand){
return true
}
}
return false
}
anchors{
verticalCenter: parent.verticalCenter
}
}
FluIcon{
rotation: model.isExpand?0:180
iconSource:FluentIcons.ChevronUp
iconSize: 15
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 12
}
visible: {
if(displayMode === FluNavigationView2.Compact){
return false
}
return true
}
Behavior on rotation {
NumberAnimation{
duration: 150
}
}
}
MouseArea{
id:item_mouse
hoverEnabled: true
anchors.fill: parent
onClicked: {
if(displayMode === FluNavigationView2.Compact){
return
}
model.isExpand = !model.isExpand
}
}
color: {
if(FluTheme.dark){
if((nav_list.currentIndex === idx)&&type===0){
return Qt.rgba(1,1,1,0.06)
}
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0)
}else{
if(nav_list.currentIndex === idx&&type===0){
return Qt.rgba(0,0,0,0.06)
}
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0)
}
}
FluIcon{
id:item_icon
iconSource: {
if(model.icon){
return model.icon
}
return 0
}
width: 30
height: 30
iconSize: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
leftMargin: 3
}
}
FluText{
id:item_title
text:model.title
visible: {
if(displayMode === FluNavigationView2.Compact){
return false
}
return true
}
anchors{
verticalCenter: parent.verticalCenter
left:item_icon.right
}
color:{
if(item_mouse.pressed){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
}
}
}
}
Component{
id:com_panel_item
Item{
Behavior on height {
NumberAnimation{
duration: 150
}
}
clip: true
height: {
if(model.parent){
return model.parent.isExpand ? 38 : 0
}
return 38
}
width: layout_list.width
Rectangle{
radius: 4
anchors{
top: parent.top
bottom: parent.bottom
left: parent.left
right: parent.right
topMargin: 2
bottomMargin: 2
leftMargin: 6
rightMargin: 6
}
MouseArea{
id:item_mouse
hoverEnabled: true
anchors.fill: parent
onClicked: {
if(type === 0){
if(model.tapFunc){
model.tapFunc()
}else{
nav_list.currentIndex = idx
layout_footer.currentIndex = -1
}
}else{
if(model.tapFunc){
model.tapFunc()
}else{
model.tap()
d.stackItems.push(model)
nav_list.currentIndex = nav_list.count-layout_footer.count+idx
layout_footer.currentIndex = idx
}
}
}
}
color: {
if(FluTheme.dark){
if(type===0){
if(nav_list.currentIndex === idx){
return Qt.rgba(1,1,1,0.06)
}
}else{
if(nav_list.currentIndex === (nav_list.count-layout_footer.count+idx)){
return Qt.rgba(1,1,1,0.06)
}
}
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0)
}else{
if(type===0){
if(nav_list.currentIndex === idx){
return Qt.rgba(0,0,0,0.06)
}
}else{
if(nav_list.currentIndex === (nav_list.count-layout_footer.count+idx)){
return Qt.rgba(0,0,0,0.06)
}
}
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0)
}
}
FluIcon{
id:item_icon
iconSource: {
if(model.icon){
return model.icon
}
return 0
}
width: 30
height: 30
iconSize: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
leftMargin: 3
}
}
FluText{
id:item_title
text:model.title
visible: {
if(displayMode === FluNavigationView2.Compact){
return false
}
return true
}
color:{
if(item_mouse.pressed){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
anchors{
verticalCenter: parent.verticalCenter
left:item_icon.right
}
}
}
}
}
Item {
id:nav_app_bar
width: parent.width
height: 50
z:999
RowLayout{
height:parent.height
spacing: 0
FluIconButton{
iconSource: FluentIcons.ChromeBack
Layout.leftMargin: 5
Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignVCenter
disabled: nav_swipe.depth === 1
iconSize: 13
onClicked: {
nav_swipe.pop()
d.stackItems.pop()
var item = d.stackItems[d.stackItems.length-1]
d.enableStack = false
if(item.idx<(nav_list.count - layout_footer.count)){
layout_footer.currentIndex = -1
}else{
console.debug(item.idx-(nav_list.count-layout_footer.count))
layout_footer.currentIndex = item.idx-(nav_list.count-layout_footer.count)
}
nav_list.currentIndex = item.idx
d.enableStack = true
}
}
FluIconButton{
id:btn_nav
iconSource: FluentIcons.GlobalNavButton
iconSize: 15
Layout.preferredWidth: 40
Layout.preferredHeight: 40
visible: displayMode === FluNavigationView2.Minimal
Layout.alignment: Qt.AlignVCenter
onClicked: {
d.enableNavigationPanel = !d.enableNavigationPanel
}
}
Image{
id:image_logo
Layout.preferredHeight: 20
Layout.preferredWidth: 20
source: control.logo
Layout.leftMargin: {
if(btn_nav.visible){
return 12
}
return 5
}
Layout.alignment: Qt.AlignVCenter
}
FluText{
Layout.alignment: Qt.AlignVCenter
text:control.title
Layout.leftMargin: 12
fontStyle: FluText.Body
}
}
}
Item{
anchors{
left: displayMode === FluNavigationView2.Minimal ? parent.left : layout_list.right
top: nav_app_bar.bottom
right: parent.right
bottom: parent.bottom
}
StackView{
id:nav_swipe
anchors.fill: parent
clip: true
popEnter : Transition{}
popExit : Transition {
NumberAnimation { properties: "y"; from: 0; to: nav_swipe.height; duration: 200 }
}
pushEnter: Transition {
NumberAnimation { properties: "y"; from: nav_swipe.height; to: 0; duration: 200 }
}
pushExit : Transition{}
replaceEnter : Transition{}
replaceExit : Transition{}
}
}
MouseArea{
anchors.fill: parent
enabled: (displayMode === FluNavigationView2.Minimal && d.enableNavigationPanel)
onClicked: {
d.enableNavigationPanel = false
}
}
Rectangle{
id:layout_list
width: {
if(displayMode === FluNavigationView2.Compact){
return 50
}
return 300
}
anchors{
top: parent.top
bottom: parent.bottom
}
border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,230/255,234/255,1)
border.width: displayMode === FluNavigationView2.Minimal ? 1 : 0
color: {
if(displayMode === FluNavigationView2.Minimal){
return FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(243/255,243/255,243/255,1)
}
if(window && window.active){
return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(238/255,244/255,249/255,1)
}
return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
}
Behavior on color{
ColorAnimation {
duration: 300
}
}
x: {
if(displayMode !== FluNavigationView2.Minimal)
return 0
return (displayMode === FluNavigationView2.Minimal && d.enableNavigationPanel) ? 0 : -width
}
Item{
id:layout_header
width: layout_list.width
clip: true
y:nav_app_bar.height
height: 38
Loader{
id:loader_auto_suggest_box
anchors.centerIn: parent
sourceComponent: autoSuggestBox
visible: {
if(displayMode === FluNavigationView2.Compact){
return false
}
return true
}
}
FluIconButton{
visible:displayMode === FluNavigationView2.Compact
hoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
pressedColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
normalColor: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0)
width:38
height:34
x:6
y:2
iconSize: 15
iconSource: {
if(loader_auto_suggest_box.item){
return loader_auto_suggest_box.item.autoSuggestBoxReplacement
}
return 0
}
}
}
ListView{
id:nav_list
clip: true
ScrollBar.vertical: FluScrollBar {}
model:d.handleItems()
highlightMoveDuration: 150
highlight: Item{
clip: true
Rectangle{
height: 18
radius: 1.5
color: FluTheme.primaryColor.dark
width: 3
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 6
}
}
}
onCurrentIndexChanged: {
if(d.enableStack){
var item = model[currentIndex]
if(item instanceof FluPaneItem){
item.tap()
d.stackItems.push(item)
}
}
}
currentIndex: -1
anchors{
top: layout_header.bottom
topMargin: 6
left: parent.left
right: parent.right
bottom: layout_footer.top
}
delegate: Loader{
property var model: modelData
property var idx: index
property int type: 0
sourceComponent: {
if(modelData instanceof FluPaneItem){
return com_panel_item
}
if(modelData instanceof FluPaneItemHeader){
return com_panel_item_header
}
if(modelData instanceof FluPaneItemSeparator){
return com_panel_item_separatorr
}
if(modelData instanceof FluPaneItemExpander){
return com_panel_item_expander
}
if(modelData instanceof FluPaneItemEmpty){
return com_panel_item_empty
}
}
}
}
ListView{
id:layout_footer
clip: true
width: layout_list.width
height: childrenRect.height
anchors.bottom: parent.bottom
interactive: false
currentIndex: -1
model: {
if(footerItems){
return footerItems.children
}
}
highlightMoveDuration: 150
highlight: Item{
clip: true
Rectangle{
height: 18
radius: 1.5
color: FluTheme.primaryColor.dark
width: 3
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 6
}
}
}
delegate: Loader{
property var model: modelData
property var idx: index
property int type: 1
sourceComponent: {
if(modelData instanceof FluPaneItem){
return com_panel_item
}
if(modelData instanceof FluPaneItemHeader){
return com_panel_item_header
}
if(modelData instanceof FluPaneItemSeparator){
return com_panel_item_separatorr
}
}
}
}
}
function setCurrentIndex(index){
nav_list.currentIndex = index
}
function getItems(){
return nav_list.model
}
function push(url){
nav_swipe.push(url)
}
function getCurrentIndex(){
return nav_list.currentIndex
}
}

View File

@ -10,7 +10,6 @@ ScrollBar {
property color handlePressColor: Qt.darker(handleNormalColor) property color handlePressColor: Qt.darker(handleNormalColor)
property bool expand: false property bool expand: false
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
implicitContentWidth + leftPadding + rightPadding) implicitContentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
@ -144,7 +143,7 @@ ScrollBar {
iconSize: 8 iconSize: 8
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 4 anchors.topMargin: 4
visible:vertical && expand visible:vertical && expand && item_react.opacity
onClicked:{ onClicked:{
decrease() decrease()
} }
@ -152,7 +151,7 @@ ScrollBar {
FluIconButton{ FluIconButton{
id:btn_bottom id:btn_bottom
iconSource: FluentIcons.CaretSolidDown iconSource: FluentIcons.CaretSolidDown
visible:vertical && expand visible:vertical && expand && item_react.opacity
width:10 width:10
height:10 height:10
iconSize: 8 iconSize: 8
@ -167,7 +166,7 @@ ScrollBar {
FluIconButton{ FluIconButton{
id:btn_left id:btn_left
iconSource: FluentIcons.CaretSolidLeft iconSource: FluentIcons.CaretSolidLeft
visible:!vertical && expand visible:!vertical && expand && item_react.opacity
width:10 width:10
height:10 height:10
iconSize: 8 iconSize: 8
@ -182,7 +181,7 @@ ScrollBar {
FluIconButton{ FluIconButton{
id:btn_right id:btn_right
iconSource: FluentIcons.CaretSolidRight iconSource: FluentIcons.CaretSolidRight
visible:!vertical && expand visible:!vertical && expand && item_react.opacity
width:10 width:10
height:10 height:10
iconSize: 8 iconSize: 8

View File

@ -71,7 +71,6 @@
<file>controls/FluPagination.qml</file> <file>controls/FluPagination.qml</file>
<file>controls/FluToggleButton.qml</file> <file>controls/FluToggleButton.qml</file>
<file>controls/FluStatusView.qml</file> <file>controls/FluStatusView.qml</file>
<file>controls/FluNavigationView2.qml</file>
<file>controls/FluPaneItemEmpty.qml</file> <file>controls/FluPaneItemEmpty.qml</file>
</qresource> </qresource>
</RCC> </RCC>