diff --git a/example/example.qrc b/example/example.qrc index b2584b92..e188d4c6 100644 --- a/example/example.qrc +++ b/example/example.qrc @@ -207,5 +207,7 @@ res/template/src/zh_CN.ts.in res/template/src/README.md.in qml/global/GlobalModel.qml + qml/page/T_Sheet.qml + qml/page/T_GroupBox.qml diff --git a/example/example_en_US.ts b/example/example_en_US.ts index be4a9df1..6c797b1b 100644 --- a/example/example_en_US.ts +++ b/example/example_en_US.ts @@ -188,322 +188,332 @@ - + PaneItem Disabled - + + GroupBox + + + + Form - + TextBox - + TimePicker - + DatePicker - + CalendarPicker - + ColorPicker - + ShortcutPicker - + Surface - + InfoBar - + An inline message to display app-wide statuschange information. - + Progress - + RatingControl - + Badge - + Rectangle - + Clip - + Carousel - + Expander - + Watermark - + Layout - + StaggeredLayout - + SplitLayout - + StatusLayout - + Popus - + Dialog - + ComboBox - + Tooltip - + Menu - + + Sheet + + + + Navigation - + Pivot - + Presents information from different sources in a tabbed view. - + BreadcrumbBar - + TabView - + A control that displays a collection of tabs thatcan be used to display several documents. - + TreeView - + TableView - + The TableView control provides a flexible way to display a collection of data in rows and columns - + Pagination - + MultiWindow - + FlipView - + Presents a collection of items that the user canflip through, one item at a time. - + Theming - + Acrylic - + Theme - + Typography - + Awesome - + Chart - + Bar Chart - + Line Chart - + Pie Chart - + Polar Area Chart - + Bubble Chart - + Scatter Chart - + Radar Chart - + Other - + QRCode - + Tour - + Timeline - + Captcha - + Network - + Remote Loader - + Hot Loader - + 3D - + Test Crash @@ -1311,6 +1321,42 @@ My only desire is to be permitted to drive out the traitors and restore the Han. + + T_GroupBox + + + GroupBox + + + + + CheckBox Group + + + + + + E-mail + + + + + + Calendar + + + + + + Contacts + + + + + RadioButton Group + + + T_Home @@ -1831,6 +1877,46 @@ My only desire is to be permitted to drive out the traitors and restore the Han. + + T_Sheet + + + Sheet + + + + + Title + + + + + Some contents... +Some contents... +Some contents... + + + + + top + + + + + right + + + + + bottom + + + + + left + + + T_ShortcutPicker diff --git a/example/example_zh_CN.ts b/example/example_zh_CN.ts index 30b9f385..7af389cd 100644 --- a/example/example_zh_CN.ts +++ b/example/example_zh_CN.ts @@ -188,322 +188,332 @@ 切换开关 - + PaneItem Disabled PaneItem 已禁用 - + + GroupBox + 分组容器 + + + Form 表单 - + TextBox 文本框 - + TimePicker 时间选择器 - + DatePicker 日期选择器 - + CalendarPicker 日历选择器 - + ColorPicker 颜色选择器 - + ShortcutPicker 快捷键选择器 - + Surface 表面 - + InfoBar 信息栏 - + An inline message to display app-wide statuschange information. 用于显示应用范围状态更改信息的内联消息。 - + Progress 进度条 - + RatingControl 评级控制 - + Badge 徽章 - + Rectangle 矩形 - + Clip 裁剪 - + Carousel 轮播图 - + Expander 展开 - + Watermark 水印 - + Layout 布局 - + StaggeredLayout 瀑布流布局 - + SplitLayout 拆分布局 - + StatusLayout 状态布局 - + Popus 弹窗 - + Dialog 弹窗 - + ComboBox 组合框 - + Tooltip 工具提示 - + Menu 菜单 - + + Sheet + 抽屉 + + + Navigation 导航 - + Pivot 轴转 - + Presents information from different sources in a tabbed view. 在选项卡式视图中显示来自不同源的信息。 - + BreadcrumbBar 面包屑 - + TabView 选项卡 - + A control that displays a collection of tabs thatcan be used to display several documents. 一个控件,用于显示可用于显示多个文档的选项卡集合。 - + TreeView - + TableView 表格 - + The TableView control provides a flexible way to display a collection of data in rows and columns TableView 控件提供了一种以行和列形式显示数据集合的灵活方法 - + Pagination 分页 - + MultiWindow 多窗口 - + FlipView 翻转视图 - + Presents a collection of items that the user canflip through, one item at a time. 显示用户可以翻阅的项集合,一次翻阅一个项。 - + Theming 主题 - + Acrylic 亚克力 - + Theme 主题 - + Typography 字体 - + Awesome 图标 - + Chart 图表 - + Bar Chart 条形图 - + Line Chart 线型图 - + Pie Chart 饼图 - + Polar Area Chart 极坐标区域图 - + Bubble Chart 气泡图 - + Scatter Chart 散点图 - + Radar Chart 雷达图 - + Other 其他 - + QRCode 二维码 - + Tour 游览 - + Timeline 时间轴 - + Captcha 验证码 - + Network 网络 - + Remote Loader 远程加载 - + Hot Loader 热加载 - + 3D 3D - + Test Crash 测试崩溃 @@ -1342,6 +1352,42 @@ My only desire is to be permitted to drive out the traitors and restore the Han. 垂直方向的翻转视图 + + T_GroupBox + + + GroupBox + 分组容器 + + + + CheckBox Group + 复选框分组 + + + + + E-mail + 邮箱 + + + + + Calendar + 日历 + + + + + Contacts + 联系人 + + + + RadioButton Group + 单选框分组 + + T_Home @@ -1880,6 +1926,48 @@ My only desire is to be permitted to drive out the traitors and restore the Han. 语言 + + T_Sheet + + + Sheet + 抽屉 + + + + Title + 标题 + + + + Some contents... +Some contents... +Some contents... + 一些内容... +一些内容... +一些内容... + + + + top + + + + + right + + + + + bottom + + + + + left + + + T_ShortcutPicker diff --git a/example/qml/component/CodeExpander.qml b/example/qml/component/CodeExpander.qml index fe96d362..f66614b8 100644 --- a/example/qml/component/CodeExpander.qml +++ b/example/qml/component/CodeExpander.qml @@ -137,7 +137,9 @@ FluExpander{ "FluNetwork", "FluShortcutPicker", "FluWindowResultLauncher", - "FluRouter" + "FluRouter", + "FluGroupBox", + "FluSheet", ]; code = code.replace(/\n/g, "
"); code = code.replace(/ /g, " "); diff --git a/example/qml/global/ItemsOriginal.qml b/example/qml/global/ItemsOriginal.qml index 224d35a1..47615f0a 100644 --- a/example/qml/global/ItemsOriginal.qml +++ b/example/qml/global/ItemsOriginal.qml @@ -104,6 +104,12 @@ FluObject{ url: "qrc:/example/qml/page/T_ToggleSwitch.qml" onTap: { navigationView.push(url) } } + FluPaneItem{ + title: qsTr("GroupBox") + menuDelegate: paneItemMenu + url: "qrc:/example/qml/page/T_GroupBox.qml" + onTap: { navigationView.push(url) } + } FluPaneItem{ title: qsTr("PaneItem Disabled") disabled: true @@ -271,6 +277,12 @@ FluObject{ url: "qrc:/example/qml/page/T_Menu.qml" onTap: { navigationView.push(url) } } + FluPaneItem{ + title: qsTr("Sheet") + menuDelegate: paneItemMenu + url: "qrc:/example/qml/page/T_Sheet.qml" + onTap: { navigationView.push(url) } + } } FluPaneItemExpander{ diff --git a/example/qml/page/T_GroupBox.qml b/example/qml/page/T_GroupBox.qml new file mode 100644 index 00000000..7a9c698b --- /dev/null +++ b/example/qml/page/T_GroupBox.qml @@ -0,0 +1,48 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 +import "../component" + +FluScrollablePage{ + + title: qsTr("GroupBox") + + FluGroupBox { + title: qsTr("CheckBox Group") + ColumnLayout { + spacing: 10 + anchors.fill: parent + FluCheckBox { text: qsTr("E-mail") } + FluCheckBox { text: qsTr("Calendar") } + FluCheckBox { text: qsTr("Contacts") } + } + } + + FluGroupBox { + title: qsTr("RadioButton Group") + FluRadioButtons { + spacing: 10 + FluRadioButton { text: qsTr("E-mail") } + FluRadioButton { text: qsTr("Calendar") } + FluRadioButton { text: qsTr("Contacts") } + } + } + + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: 4 + code:'FluGroupBox { + title: qsTr("CheckBox Group") + ColumnLayout { + spacing: 10 + anchors.fill: parent + FluCheckBox { text: qsTr("E-mail") } + FluCheckBox { text: qsTr("Calendar") } + FluCheckBox { text: qsTr("Contacts") } + } +}' + } + +} diff --git a/example/qml/page/T_RemoteLoader.qml b/example/qml/page/T_RemoteLoader.qml index 422c8e11..58f8177e 100644 --- a/example/qml/page/T_RemoteLoader.qml +++ b/example/qml/page/T_RemoteLoader.qml @@ -7,7 +7,6 @@ import "../component" FluPage{ launchMode: FluPageType.SingleTop - header:Item{} FluRemoteLoader{ anchors.fill: parent source: "https://zhu-zichu.gitee.io/Qt_174_RemoteLoader.qml" diff --git a/example/qml/page/T_Sheet.qml b/example/qml/page/T_Sheet.qml new file mode 100644 index 00000000..5c3b07cf --- /dev/null +++ b/example/qml/page/T_Sheet.qml @@ -0,0 +1,90 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 +import "../component" + +FluScrollablePage{ + + title: qsTr("Sheet") + + FluSheet{ + id:sheet + title: qsTr("Title") + FluText{ + text: qsTr("Some contents...\nSome contents...\nSome contents...") + anchors{ + left: parent.left + leftMargin: 10 + } + } + } + + FluFrame{ + Layout.fillWidth: true + Layout.preferredHeight: 280 + padding: 10 + Column{ + anchors.centerIn: parent + spacing: 10 + Row{ + spacing: 10 + FluButton{ + width: 80 + height: 30 + text: qsTr("top") + onClicked: { + sheet.open(FluSheetType.Top) + } + } + FluButton{ + width: 80 + height: 30 + text: qsTr("right") + onClicked: { + sheet.open(FluSheetType.Right) + } + } + } + Row{ + spacing: 10 + FluButton{ + width: 80 + height: 30 + text: qsTr("bottom") + onClicked: { + sheet.open(FluSheetType.Bottom) + } + } + FluButton{ + width: 80 + height: 30 + text: qsTr("left") + onClicked: { + sheet.open(FluSheetType.Left) + } + } + } + } + } + + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -6 + code:'FluSheet{ + id:sheet + title: qsTr("Title") + FluText{ + text: qsTr("Some contents...") + anchors{ + left: parent.left + leftMargin: 10 + } + } +} +sheet.open(FluSheetType.Bottom) +' + } + +} diff --git a/src/Def.h b/src/Def.h index 53f587b0..12a2f371 100644 --- a/src/Def.h +++ b/src/Def.h @@ -4,6 +4,17 @@ #include #include +namespace FluSheetType { +Q_NAMESPACE +enum Position { + Left = 0x0000, + Top = 0x0001, + Right = 0x0002, + Bottom = 0x0004, +}; +Q_ENUM_NS(Position) +QML_NAMED_ELEMENT(FluSheetType) +} namespace FluThemeType { Q_NAMESPACE diff --git a/src/FluFrameless.cpp b/src/FluFrameless.cpp index 3c72e9a5..25a64aba 100644 --- a/src/FluFrameless.cpp +++ b/src/FluFrameless.cpp @@ -142,6 +142,7 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message, }else{ offsetSize = 1; } + _maximizeButton->setProperty("hover",false); if(!isCompositionEnabled()){ offsetSize = 0; } @@ -158,8 +159,11 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message, if (*result == HTNOWHERE) { *result = HTZOOM; } + _setMaximizeHoverd(true); return true; } + _setMaximizeHoverd(false); + _setMaximizePressed(false); *result = 0; POINT nativeGlobalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; POINT nativeLocalPos = nativeGlobalPos; @@ -205,12 +209,14 @@ bool FluFrameless::nativeEventFilter(const QByteArray &eventType, void *message, if(_hitMaximizeButton()){ QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QGuiApplication::sendEvent(_maximizeButton,&event); + _setMaximizePressed(true); return true; } }else if(uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP){ if(_hitMaximizeButton()){ QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QGuiApplication::sendEvent(_maximizeButton,&event); + _setMaximizePressed(false); return true; } }else if(uMsg == WM_NCPAINT){ @@ -331,6 +337,14 @@ bool FluFrameless::_hitMaximizeButton(){ return false; } +void FluFrameless::_setMaximizePressed(bool val){ + _maximizeButton->setProperty("down",val); +} + +void FluFrameless::_setMaximizeHoverd(bool val){ + _maximizeButton->setProperty("hover",val); +} + void FluFrameless::_updateCursor(int edges){ switch (edges) { case 0: @@ -377,7 +391,9 @@ void FluFrameless::showNormal(){ } void FluFrameless::setHitTestVisible(QQuickItem* val){ - _hitTestList.append(val); + if(!_hitTestList.contains(val)){ + _hitTestList.append(val); + } } diff --git a/src/FluFrameless.h b/src/FluFrameless.h index ce7173d4..95979d9a 100644 --- a/src/FluFrameless.h +++ b/src/FluFrameless.h @@ -47,6 +47,8 @@ private: bool _containsCursorToItem(QQuickItem* item); bool _hitAppBar(); bool _hitMaximizeButton(); + void _setMaximizePressed(bool val); + void _setMaximizeHoverd(bool val); private: qint64 _current; int _edges = 0; diff --git a/src/FluentUI.cpp b/src/FluentUI.cpp index 835d1164..36ed7472 100644 --- a/src/FluentUI.cpp +++ b/src/FluentUI.cpp @@ -124,6 +124,8 @@ void FluentUI::registerTypes(const char *uri){ qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluWindowResultLauncher.qml"),uri,major,minor,"FluWindowResultLauncher"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluLauncher.qml"),uri,major,minor,"FluLauncher"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEvent.qml"),uri,major,minor,"FluEvent"); + qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSheet.qml"),uri,major,minor,"FluSheet"); + qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluGroupBox.qml"),uri,major,minor,"FluGroupBox"); qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluRouter.qml"),uri,major,minor,"FluRouter"); qmlRegisterSingletonType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluEventBus.qml"),uri,major,minor,"FluEventBus"); @@ -139,6 +141,7 @@ void FluentUI::registerTypes(const char *uri){ qmlRegisterUncreatableMetaObject(FluTabViewType::staticMetaObject, uri,major,minor,"FluTabViewType", "Access to enums & flags only"); qmlRegisterUncreatableMetaObject(FluNavigationViewType::staticMetaObject, uri,major,minor,"FluNavigationViewType", "Access to enums & flags only"); qmlRegisterUncreatableMetaObject(FluTimelineType::staticMetaObject, uri,major,minor,"FluTimelineType", "Access to enums & flags only"); + qmlRegisterUncreatableMetaObject(FluSheetType::staticMetaObject, uri,major,minor,"FluSheetType", "Access to enums & flags only"); qmlRegisterModule(uri,major,minor); #endif diff --git a/src/Qt5/imports/FluentUI/Controls/FluAppBar.qml b/src/Qt5/imports/FluentUI/Controls/FluAppBar.qml index 006d4cc8..73e9b444 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluAppBar.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluAppBar.qml @@ -225,6 +225,7 @@ Rectangle{ } FluIconButton{ id:btn_maximize + property bool hover: btn_maximize.hovered Layout.preferredWidth: 40 Layout.preferredHeight: 30 padding: 0 @@ -232,10 +233,10 @@ Rectangle{ horizontalPadding: 0 iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize color: { - if(pressed){ + if(down){ return maximizePressColor } - return hovered ? maximizeHoverColor : maximizeNormalColor + return btn_maximize.hover ? maximizeHoverColor : maximizeNormalColor } Layout.alignment: Qt.AlignVCenter visible: d.resizable && !isMac && showMaximize diff --git a/src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml b/src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml index 08c37a73..9d3b05ca 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml @@ -41,6 +41,8 @@ Button { visible: control.activeFocus } } + focusPolicy:Qt.TabFocus + font:FluTextStyle.Body horizontalPadding:0 verticalPadding: 0 padding: 0 @@ -48,7 +50,6 @@ Button { Accessible.name: control.text Accessible.description: contentDescription Accessible.onPressAction: control.clicked() - focusPolicy:Qt.TabFocus contentItem: RowLayout{ spacing: control.textSpacing layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft @@ -133,6 +134,7 @@ Button { text: control.text Layout.alignment: Qt.AlignVCenter visible: text !== "" + font: control.font } } } diff --git a/src/Qt5/imports/FluentUI/Controls/FluGroupBox.qml b/src/Qt5/imports/FluentUI/Controls/FluGroupBox.qml new file mode 100644 index 00000000..443651f1 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluGroupBox.qml @@ -0,0 +1,39 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls.impl 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.GroupBox { + id: control + property int borderWidth : 1 + property color borderColor : FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1) + property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) + property int radius: 4 + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitLabelWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + spacing: 6 + padding: 12 + font: FluTextStyle.Body + topPadding: padding + (implicitLabelWidth > 0 ? implicitLabelHeight + spacing : 0) + label: FluText { + width: control.availableWidth + text: control.title + font: FluTextStyle.BodyStrong + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + background: Rectangle { + y: control.topPadding - control.bottomPadding + width: parent.width + height: parent.height - control.topPadding + control.bottomPadding + radius: control.radius + border.color: control.borderColor + border.width: control.borderWidth + color: control.color + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPage.qml b/src/Qt5/imports/FluentUI/Controls/FluPage.qml index ed33afe9..78da7788 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluPage.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluPage.qml @@ -16,7 +16,7 @@ Page { transform: Translate { y: control.visible ? 0 : 80 Behavior on y{ - enabled: control.animationEnabled + enabled: control.animationEnabled && FluTheme.animationEnabled NumberAnimation{ duration: 167 easing.type: Easing.OutCubic @@ -24,21 +24,27 @@ Page { } } Behavior on opacity { - enabled: control.animationEnabled + enabled: control.animationEnabled && FluTheme.animationEnabled NumberAnimation{ duration: 83 } } background: Item{} - header: Item{ - implicitHeight: 40 - FluText{ - id:text_title - text: control.title - font: FluTextStyle.Title - anchors{ - left: parent.left - leftMargin: 5 + header: FluLoader{ + sourceComponent: control.title === "" ? undefined : com_header + } + Component{ + id: com_header + Item{ + implicitHeight: 40 + FluText{ + id:text_title + text: control.title + font: FluTextStyle.Title + anchors{ + left: parent.left + leftMargin: 5 + } } } } diff --git a/src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml b/src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml index efa317d3..efd372f1 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml @@ -92,6 +92,7 @@ Button { id:btn_text text: control.text Layout.alignment: Qt.AlignVCenter + visible: text !== "" font: control.font } } diff --git a/src/Qt5/imports/FluentUI/Controls/FluShadow.qml b/src/Qt5/imports/FluentUI/Controls/FluShadow.qml index b16e73e6..0accdf7b 100644 --- a/src/Qt5/imports/FluentUI/Controls/FluShadow.qml +++ b/src/Qt5/imports/FluentUI/Controls/FluShadow.qml @@ -4,7 +4,7 @@ import FluentUI 1.0 Item { //高性能阴影!!!比DropShadow阴影性能高出数倍!!! - property color color: FluTheme.dark ? "#FFFFFF" : "#999999" + property color color: FluTheme.dark ? "#AAAAAA" : "#999999" property int elevation: 6 property int radius: 4 id:control diff --git a/src/Qt5/imports/FluentUI/Controls/FluSheet.qml b/src/Qt5/imports/FluentUI/Controls/FluSheet.qml new file mode 100644 index 00000000..796d56fb --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluSheet.qml @@ -0,0 +1,210 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Popup { + id: control + default property alias content : container.contentData + property string title + property var header : Item{ + implicitHeight: 40 + FluIconButton{ + id: btn_close + iconSource: FluentIcons.Clear + iconSize: 15 + verticalPadding: 6 + horizontalPadding: 6 + width: 30 + height: 30 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 5 + } + onClicked: { + control.visible = false + } + } + FluText{ + id:text_title + text: control.title + font: FluTextStyle.Subtitle + anchors{ + verticalCenter: parent.verticalCenter + left: btn_close.right + leftMargin: 5 + right: parent.right + rightMargin: 5 + } + } + } + property int size: 278 + + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + padding: 0 + modal:true + parent: Overlay.overlay + enter: { + if(d.position === FluSheetType.Top){ + return enter_top + }else if(d.position === FluSheetType.Left){ + return enter_left + }else if(d.position === FluSheetType.Right){ + return enter_right + }else{ + return enter_bottom + } + } + exit: { + if(d.position === FluSheetType.Top){ + return exit_top + }else if(d.position === FluSheetType.Left){ + return exit_left + }else if(d.position === FluSheetType.Right){ + return exit_right + }else{ + return exit_bottom + } + } + Item { + id: d + property var win: Window.window + onWinChanged: { + if(win instanceof FluWindow){ + win.setHitTestVisible(container) + } + } + property int position: FluSheetType.Bottom + property int parentHeight: { + if(control.parent){ + return control.parent.height + } + return control.height + } + property int parentWidth: { + if(control.parent){ + return control.parent.width + } + return control.width + } + } + Transition { + id:enter_right + onRunningChanged: { + if(!running){ + control.x = Qt.binding(function(){return d.parentWidth - control.width}) + } + } + NumberAnimation{ + property: "x" + duration: 167 + from: d.parentWidth + to: d.parentWidth - control.width + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_right + NumberAnimation{ + property: "x" + duration: 167 + from: d.parentWidth - control.width + to: d.parentWidth + easing.type: Easing.OutCubic + } + } + Transition { + id:enter_left + NumberAnimation{ + property: "x" + duration: 167 + from: -control.width + to: 0 + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_left + NumberAnimation{ + property: "x" + duration: 167 + from: 0 + to: -control.width + easing.type: Easing.OutCubic + } + } + Transition { + id:enter_top + NumberAnimation{ + property: "y" + duration: 167 + from: -control.height + to: 0 + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_top + NumberAnimation{ + property: "y" + duration: 167 + from: 0 + to: -control.height + easing.type: Easing.OutCubic + } + } + Transition { + id:enter_bottom + onRunningChanged: { + if(!running){ + control.y = Qt.binding(function(){return d.parentHeight - control.height}) + } + } + NumberAnimation{ + property: "y" + duration: 167 + from: d.parentHeight + to: d.parentHeight - control.height + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_bottom + NumberAnimation{ + property: "y" + duration: 167 + from: d.parentHeight - control.height + to: d.parentHeight + easing.type: Easing.OutCubic + } + } + background: Rectangle { + FluShadow{ + radius: 0 + } + border.color: FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1) + color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) + } + Page{ + id: container + anchors.fill: parent + header: control.header + background: Item{} + } + function open(position = FluSheetType.Bottom){ + control.x = 0 + control.y = 0 + + d.position = position + if(d.position === FluSheetType.Top || d.position === FluSheetType.Bottom){ + control.width = Qt.binding(function(){return d.parentWidth}) + control.height = size + }else{ + control.width = size + control.height = Qt.binding(function(){return d.parentHeight}) + } + control.visible = true + } +} diff --git a/src/Qt5/imports/fluentui.qrc b/src/Qt5/imports/fluentui.qrc index 4e46ee11..aff88eb9 100644 --- a/src/Qt5/imports/fluentui.qrc +++ b/src/Qt5/imports/fluentui.qrc @@ -107,5 +107,7 @@ FluentUI/Controls/FluEvent.qml FluentUI/Controls/FluEventBus.qml FluentUI/Controls/FluFrame.qml + FluentUI/Controls/FluSheet.qml + FluentUI/Controls/FluGroupBox.qml diff --git a/src/Qt6/imports/FluentUI/Controls/FluAppBar.qml b/src/Qt6/imports/FluentUI/Controls/FluAppBar.qml index c75c8165..1724cc5f 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluAppBar.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluAppBar.qml @@ -225,6 +225,7 @@ Rectangle{ } FluIconButton{ id:btn_maximize + property bool hover: btn_maximize.hovered Layout.preferredWidth: 40 Layout.preferredHeight: 30 padding: 0 @@ -232,10 +233,10 @@ Rectangle{ horizontalPadding: 0 iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize color: { - if(pressed){ + if(down){ return maximizePressColor } - return hovered ? maximizeHoverColor : maximizeNormalColor + return btn_maximize.hover ? maximizeHoverColor : maximizeNormalColor } Layout.alignment: Qt.AlignVCenter visible: d.resizable && !isMac && showMaximize diff --git a/src/Qt6/imports/FluentUI/Controls/FluCheckBox.qml b/src/Qt6/imports/FluentUI/Controls/FluCheckBox.qml index 177cb084..d9f9d454 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluCheckBox.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluCheckBox.qml @@ -42,6 +42,8 @@ Button { visible: control.activeFocus } } + focusPolicy:Qt.TabFocus + font:FluTextStyle.Body horizontalPadding:0 verticalPadding: 0 padding: 0 @@ -49,7 +51,6 @@ Button { Accessible.name: control.text Accessible.description: contentDescription Accessible.onPressAction: control.clicked() - focusPolicy:Qt.TabFocus contentItem: RowLayout{ spacing: control.textSpacing layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft @@ -134,6 +135,7 @@ Button { text: control.text Layout.alignment: Qt.AlignVCenter visible: text !== "" + font: control.font } } } diff --git a/src/Qt6/imports/FluentUI/Controls/FluGroupBox.qml b/src/Qt6/imports/FluentUI/Controls/FluGroupBox.qml new file mode 100644 index 00000000..b93f576e --- /dev/null +++ b/src/Qt6/imports/FluentUI/Controls/FluGroupBox.qml @@ -0,0 +1,39 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Window +import QtQuick.Controls.impl +import QtQuick.Templates as T +import FluentUI + +T.GroupBox { + id: control + property int borderWidth : 1 + property color borderColor : FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1) + property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) + property int radius: 4 + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitLabelWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + spacing: 6 + padding: 12 + font: FluTextStyle.Body + topPadding: padding + (implicitLabelWidth > 0 ? implicitLabelHeight + spacing : 0) + label: FluText { + width: control.availableWidth + text: control.title + font: FluTextStyle.BodyStrong + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + background: Rectangle { + y: control.topPadding - control.bottomPadding + width: parent.width + height: parent.height - control.topPadding + control.bottomPadding + radius: control.radius + border.color: control.borderColor + border.width: control.borderWidth + color: control.color + } +} diff --git a/src/Qt6/imports/FluentUI/Controls/FluPage.qml b/src/Qt6/imports/FluentUI/Controls/FluPage.qml index 95dd1a64..7faea87f 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluPage.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluPage.qml @@ -16,7 +16,7 @@ Page { transform: Translate { y: control.visible ? 0 : 80 Behavior on y{ - enabled: control.animationEnabled + enabled: control.animationEnabled && FluTheme.animationEnabled NumberAnimation{ duration: 167 easing.type: Easing.OutCubic @@ -24,21 +24,27 @@ Page { } } Behavior on opacity { - enabled: control.animationEnabled + enabled: control.animationEnabled && FluTheme.animationEnabled NumberAnimation{ duration: 83 } } background: Item{} - header: Item{ - implicitHeight: 40 - FluText{ - id:text_title - text: control.title - font: FluTextStyle.Title - anchors{ - left: parent.left - leftMargin: 5 + header: FluLoader{ + sourceComponent: control.title === "" ? undefined : com_header + } + Component{ + id: com_header + Item{ + implicitHeight: 40 + FluText{ + id:text_title + text: control.title + font: FluTextStyle.Title + anchors{ + left: parent.left + leftMargin: 5 + } } } } diff --git a/src/Qt6/imports/FluentUI/Controls/FluRadioButton.qml b/src/Qt6/imports/FluentUI/Controls/FluRadioButton.qml index ab75823a..449c8e2c 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluRadioButton.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluRadioButton.qml @@ -89,6 +89,7 @@ Button { text: control.text Layout.alignment: Qt.AlignVCenter font: control.font + visible: text !== "" } } } diff --git a/src/Qt6/imports/FluentUI/Controls/FluShadow.qml b/src/Qt6/imports/FluentUI/Controls/FluShadow.qml index af236e1e..6f9439d4 100644 --- a/src/Qt6/imports/FluentUI/Controls/FluShadow.qml +++ b/src/Qt6/imports/FluentUI/Controls/FluShadow.qml @@ -4,7 +4,7 @@ import FluentUI Item { //高性能阴影!!!比DropShadow阴影性能高出数倍!!! - property color color: FluTheme.dark ? "#FFFFFF" : "#999999" + property color color: FluTheme.dark ? "#AAAAAA" : "#999999" property int elevation: 6 property int radius: 4 id:control diff --git a/src/Qt6/imports/FluentUI/Controls/FluSheet.qml b/src/Qt6/imports/FluentUI/Controls/FluSheet.qml new file mode 100644 index 00000000..852a8cda --- /dev/null +++ b/src/Qt6/imports/FluentUI/Controls/FluSheet.qml @@ -0,0 +1,210 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Window +import FluentUI + +Popup { + id: control + default property alias content : container.contentData + property string title + property var header : Item{ + implicitHeight: 40 + FluIconButton{ + id: btn_close + iconSource: FluentIcons.Clear + iconSize: 15 + verticalPadding: 6 + horizontalPadding: 6 + width: 30 + height: 30 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 5 + } + onClicked: { + control.visible = false + } + } + FluText{ + id:text_title + text: control.title + font: FluTextStyle.Subtitle + anchors{ + verticalCenter: parent.verticalCenter + left: btn_close.right + leftMargin: 5 + right: parent.right + rightMargin: 5 + } + } + } + property int size: 278 + + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + padding: 0 + modal:true + parent: Overlay.overlay + enter: { + if(d.position === FluSheetType.Top){ + return enter_top + }else if(d.position === FluSheetType.Left){ + return enter_left + }else if(d.position === FluSheetType.Right){ + return enter_right + }else{ + return enter_bottom + } + } + exit: { + if(d.position === FluSheetType.Top){ + return exit_top + }else if(d.position === FluSheetType.Left){ + return exit_left + }else if(d.position === FluSheetType.Right){ + return exit_right + }else{ + return exit_bottom + } + } + Item { + id: d + property var win: Window.window + onWinChanged: { + if(win instanceof FluWindow){ + win.setHitTestVisible(container) + } + } + property int position: FluSheetType.Bottom + property int parentHeight: { + if(control.parent){ + return control.parent.height + } + return control.height + } + property int parentWidth: { + if(control.parent){ + return control.parent.width + } + return control.width + } + } + Transition { + id:enter_right + onRunningChanged: { + if(!running){ + control.x = Qt.binding(function(){return d.parentWidth - control.width}) + } + } + NumberAnimation{ + property: "x" + duration: 167 + from: d.parentWidth + to: d.parentWidth - control.width + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_right + NumberAnimation{ + property: "x" + duration: 167 + from: d.parentWidth - control.width + to: d.parentWidth + easing.type: Easing.OutCubic + } + } + Transition { + id:enter_left + NumberAnimation{ + property: "x" + duration: 167 + from: -control.width + to: 0 + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_left + NumberAnimation{ + property: "x" + duration: 167 + from: 0 + to: -control.width + easing.type: Easing.OutCubic + } + } + Transition { + id:enter_top + NumberAnimation{ + property: "y" + duration: 167 + from: -control.height + to: 0 + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_top + NumberAnimation{ + property: "y" + duration: 167 + from: 0 + to: -control.height + easing.type: Easing.OutCubic + } + } + Transition { + id:enter_bottom + onRunningChanged: { + if(!running){ + control.y = Qt.binding(function(){return d.parentHeight - control.height}) + } + } + NumberAnimation{ + property: "y" + duration: 167 + from: d.parentHeight + to: d.parentHeight - control.height + easing.type: Easing.OutCubic + } + } + Transition { + id:exit_bottom + NumberAnimation{ + property: "y" + duration: 167 + from: d.parentHeight - control.height + to: d.parentHeight + easing.type: Easing.OutCubic + } + } + background: Rectangle { + FluShadow{ + radius: 0 + } + border.color: FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1) + color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) + } + Page{ + id: container + anchors.fill: parent + header: control.header + background: Item{} + } + function open(position = FluSheetType.Bottom){ + control.x = 0 + control.y = 0 + + d.position = position + if(d.position === FluSheetType.Top || d.position === FluSheetType.Bottom){ + control.width = Qt.binding(function(){return d.parentWidth}) + control.height = size + }else{ + control.width = size + control.height = Qt.binding(function(){return d.parentHeight}) + } + control.visible = true + } +}