This commit is contained in:
朱子楚\zhuzi
2024-03-31 10:59:15 +08:00
parent 6a5f9d04a9
commit 0ab7f811e3
27 changed files with 1040 additions and 161 deletions

View File

@ -4,6 +4,17 @@
#include <QObject>
#include <QtQml/qqml.h>
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

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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
}
}
}
}

View File

@ -92,6 +92,7 @@ Button {
id:btn_text
text: control.text
Layout.alignment: Qt.AlignVCenter
visible: text !== ""
font: control.font
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -107,5 +107,7 @@
<file>FluentUI/Controls/FluEvent.qml</file>
<file>FluentUI/Controls/FluEventBus.qml</file>
<file>FluentUI/Controls/FluFrame.qml</file>
<file>FluentUI/Controls/FluSheet.qml</file>
<file>FluentUI/Controls/FluGroupBox.qml</file>
</qresource>
</RCC>

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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
}
}

View File

@ -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
}
}
}
}

View File

@ -89,6 +89,7 @@ Button {
text: control.text
Layout.alignment: Qt.AlignVCenter
font: control.font
visible: text !== ""
}
}
}

View File

@ -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

View File

@ -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
}
}