From be5e8a4a8894b2bfaf03975baa8997332e92032a Mon Sep 17 00:00:00 2001 From: zhuzichu Date: Thu, 24 Aug 2023 15:50:37 +0800 Subject: [PATCH] Qt5.15.2 compatible --- .cmake/QmlPlugin.cmake | 139 + CMakeLists.txt | 5 +- example/CMakeLists.txt | 72 +- example/qml-Qt6/App.qml | 44 + example/qml-Qt6/component/CodeExpander.qml | 145 + example/qml-Qt6/component/CustomWindow.qml | 64 + example/qml-Qt6/global/ItemsFooter.qml | 30 + example/qml-Qt6/global/ItemsOriginal.qml | 483 + example/qml-Qt6/global/MainEvent.qml | 9 + example/qml-Qt6/global/qmldir | 3 + example/qml-Qt6/page/T_Acrylic.qml | 114 + example/qml-Qt6/page/T_Awesome.qml | 71 + example/qml-Qt6/page/T_Badge.qml | 129 + example/qml-Qt6/page/T_BreadcrumbBar.qml | 94 + example/qml-Qt6/page/T_Buttons.qml | 348 + example/qml-Qt6/page/T_CalendarPicker.qml | 50 + example/qml-Qt6/page/T_Captcha.qml | 54 + example/qml-Qt6/page/T_Carousel.qml | 132 + example/qml-Qt6/page/T_Chart.qml | 331 + example/qml-Qt6/page/T_CheckBox.qml | 50 + example/qml-Qt6/page/T_ColorPicker.qml | 69 + example/qml-Qt6/page/T_ComboBox.qml | 81 + example/qml-Qt6/page/T_DatePicker.qml | 70 + example/qml-Qt6/page/T_Dialog.qml | 118 + example/qml-Qt6/page/T_Expander.qml | 102 + example/qml-Qt6/page/T_FlipView.qml | 117 + example/qml-Qt6/page/T_Home.qml | 284 + example/qml-Qt6/page/T_Http.qml | 279 + example/qml-Qt6/page/T_Image.qml | 48 + example/qml-Qt6/page/T_InfoBar.qml | 66 + example/qml-Qt6/page/T_Menu.qml | 175 + example/qml-Qt6/page/T_MultiWindow.qml | 186 + example/qml-Qt6/page/T_Pagination.qml | 49 + example/qml-Qt6/page/T_Pivot.qml | 79 + example/qml-Qt6/page/T_Progress.qml | 103 + example/qml-Qt6/page/T_QRCode.qml | 106 + example/qml-Qt6/page/T_RadioButton.qml | 101 + example/qml-Qt6/page/T_RatingControl.qml | 35 + example/qml-Qt6/page/T_Rectangle.qml | 147 + example/qml-Qt6/page/T_RemoteLoader.qml | 14 + example/qml-Qt6/page/T_Screenshot.qml | 55 + example/qml-Qt6/page/T_Settings.qml | 108 + example/qml-Qt6/page/T_Slider.qml | 50 + example/qml-Qt6/page/T_StatusView.qml | 86 + example/qml-Qt6/page/T_TabView.qml | 130 + example/qml-Qt6/page/T_TableView.qml | 171 + example/qml-Qt6/page/T_Text.qml | 32 + example/qml-Qt6/page/T_TextBox.qml | 191 + example/qml-Qt6/page/T_Theme.qml | 99 + example/qml-Qt6/page/T_TimePicker.qml | 79 + example/qml-Qt6/page/T_Timeline.qml | 170 + example/qml-Qt6/page/T_ToggleSwitch.qml | 51 + example/qml-Qt6/page/T_Tooltip.qml | 103 + example/qml-Qt6/page/T_Tour.qml | 80 + example/qml-Qt6/page/T_TreeView.qml | 156 + example/qml-Qt6/page/T_Typography.qml | 84 + example/qml-Qt6/page/T_Watermark.qml | 132 + example/qml-Qt6/window/AboutWindow.qml | 150 + example/qml-Qt6/window/HotloadWindow.qml | 85 + example/qml-Qt6/window/LoginWindow.qml | 63 + example/qml-Qt6/window/MainWindow.qml | 280 + .../qml-Qt6/window/SingleInstanceWindow.qml | 35 + example/qml-Qt6/window/SingleTaskWindow.qml | 21 + example/qml-Qt6/window/StandardWindow.qml | 43 + example/qml/App.qml | 10 +- example/qml/component/CodeExpander.qml | 10 +- example/qml/component/CustomWindow.qml | 8 +- example/qml/global/ItemsFooter.qml | 4 +- example/qml/global/ItemsOriginal.qml | 4 +- example/qml/global/MainEvent.qml | 6 +- example/qml/page/T_Acrylic.qml | 10 +- example/qml/page/T_Awesome.qml | 10 +- example/qml/page/T_Badge.qml | 10 +- example/qml/page/T_BreadcrumbBar.qml | 10 +- example/qml/page/T_Buttons.qml | 11 +- example/qml/page/T_CalendarPicker.qml | 10 +- example/qml/page/T_Captcha.qml | 10 +- example/qml/page/T_Carousel.qml | 10 +- example/qml/page/T_Chart.qml | 10 +- example/qml/page/T_CheckBox.qml | 10 +- example/qml/page/T_ColorPicker.qml | 10 +- example/qml/page/T_ComboBox.qml | 10 +- example/qml/page/T_DatePicker.qml | 10 +- example/qml/page/T_Dialog.qml | 10 +- example/qml/page/T_Expander.qml | 10 +- example/qml/page/T_FlipView.qml | 10 +- example/qml/page/T_Home.qml | 10 +- example/qml/page/T_Http.qml | 14 +- example/qml/page/T_Image.qml | 10 +- example/qml/page/T_InfoBar.qml | 10 +- example/qml/page/T_Menu.qml | 10 +- example/qml/page/T_MultiWindow.qml | 10 +- example/qml/page/T_Pagination.qml | 10 +- example/qml/page/T_Pivot.qml | 10 +- example/qml/page/T_Progress.qml | 10 +- example/qml/page/T_QRCode.qml | 12 +- example/qml/page/T_RadioButton.qml | 10 +- example/qml/page/T_RatingControl.qml | 10 +- example/qml/page/T_Rectangle.qml | 10 +- example/qml/page/T_RemoteLoader.qml | 10 +- example/qml/page/T_Screenshot.qml | 10 +- example/qml/page/T_Settings.qml | 10 +- example/qml/page/T_Slider.qml | 10 +- example/qml/page/T_StatusView.qml | 10 +- example/qml/page/T_TabView.qml | 10 +- example/qml/page/T_TableView.qml | 10 +- example/qml/page/T_Text.qml | 10 +- example/qml/page/T_TextBox.qml | 10 +- example/qml/page/T_Theme.qml | 10 +- example/qml/page/T_TimePicker.qml | 10 +- example/qml/page/T_Timeline.qml | 10 +- example/qml/page/T_ToggleSwitch.qml | 10 +- example/qml/page/T_Tooltip.qml | 10 +- example/qml/page/T_Tour.qml | 10 +- example/qml/page/T_TreeView.qml | 10 +- example/qml/page/T_Typography.qml | 8 +- example/qml/page/T_Watermark.qml | 10 +- example/qml/window/AboutWindow.qml | 8 +- example/qml/window/HotloadWindow.qml | 10 +- example/qml/window/LoginWindow.qml | 8 +- example/qml/window/MainWindow.qml | 14 +- example/qml/window/SingleInstanceWindow.qml | 8 +- example/qml/window/SingleTaskWindow.qml | 8 +- example/qml/window/StandardWindow.qml | 8 +- example/resource.qrc | 188 + example/src/component/CircularReveal.h | 1 - example/src/component/FileWatcher.h | 1 - example/src/main.cpp | 4 + example/src/stdafx.h | 6 +- src/CMakeLists.txt | 91 +- src/Def.h | 1 - src/FluTextStyle.cpp | 11 + src/FluTextStyle.h | 12 +- src/FluTools.cpp | 5 + src/FluTools.h | 8 + .../Controls/ColorPicker/ColorPicker.qml | 233 + .../ColorPicker/Content/Checkerboard.qml | 16 + .../ColorPicker/Content/ColorSlider.qml | 44 + .../ColorPicker/Content/NumberBox.qml | 39 + .../ColorPicker/Content/PanelBorder.qml | 16 + .../Controls/ColorPicker/Content/SBPicker.qml | 62 + .../imports/FluentUI/Controls/FluAcrylic.qml | 40 + .../imports/FluentUI/Controls/FluAppBar.qml | 166 + src/Qt5/imports/FluentUI/Controls/FluArea.qml | 27 + .../FluentUI/Controls/FluAutoSuggestBox.qml | 135 + .../imports/FluentUI/Controls/FluBadge.qml | 79 + .../FluentUI/Controls/FluBreadcrumbBar.qml | 92 + .../imports/FluentUI/Controls/FluButton.qml | 63 + .../FluentUI/Controls/FluCalendarPicker.qml | 114 + .../FluentUI/Controls/FluCalendarView.qml | 435 + .../imports/FluentUI/Controls/FluCarousel.qml | 201 + .../imports/FluentUI/Controls/FluChart.qml | 122 + .../imports/FluentUI/Controls/FluCheckBox.qml | 120 + .../FluentUI/Controls/FluColorPicker.qml | 93 + .../FluentUI/Controls/FluColorView.qml | 24 + .../imports/FluentUI/Controls/FluComboBox.qml | 137 + .../FluentUI/Controls/FluContentDialog.qml | 129 + .../FluentUI/Controls/FluContentPage.qml | 60 + .../imports/FluentUI/Controls/FluControl.qml | 27 + .../FluentUI/Controls/FluCopyableText.qml | 35 + .../FluentUI/Controls/FluDatePicker.qml | 401 + .../imports/FluentUI/Controls/FluDivider.qml | 18 + .../FluentUI/Controls/FluDropDownButton.qml | 94 + .../imports/FluentUI/Controls/FluExpander.qml | 122 + .../FluentUI/Controls/FluFilledButton.qml | 56 + .../imports/FluentUI/Controls/FluFlipView.qml | 106 + .../FluentUI/Controls/FluFocusRectangle.qml | 19 + src/Qt5/imports/FluentUI/Controls/FluIcon.qml | 19 + .../FluentUI/Controls/FluIconButton.qml | 140 + .../imports/FluentUI/Controls/FluImage.qml | 48 + .../imports/FluentUI/Controls/FluInfoBar.qml | 210 + src/Qt5/imports/FluentUI/Controls/FluItem.qml | 57 + .../FluentUI/Controls/FluItemDelegate.qml | 38 + src/Qt5/imports/FluentUI/Controls/FluMenu.qml | 59 + .../imports/FluentUI/Controls/FluMenuBar.qml | 20 + .../FluentUI/Controls/FluMenuBarItem.qml | 69 + .../imports/FluentUI/Controls/FluMenuItem.qml | 115 + .../FluentUI/Controls/FluMenuSeparator.qml | 18 + .../FluentUI/Controls/FluMultilineTextBox.qml | 65 + .../FluentUI/Controls/FluNavigationView.qml | 1222 + .../imports/FluentUI/Controls/FluObject.qml | 8 + src/Qt5/imports/FluentUI/Controls/FluPage.qml | 34 + .../FluentUI/Controls/FluPagination.qml | 100 + .../imports/FluentUI/Controls/FluPaneItem.qml | 25 + .../FluentUI/Controls/FluPaneItemEmpty.qml | 10 + .../FluentUI/Controls/FluPaneItemExpander.qml | 16 + .../FluentUI/Controls/FluPaneItemHeader.qml | 10 + .../Controls/FluPaneItemSeparator.qml | 11 + .../FluentUI/Controls/FluPasswordBox.qml | 84 + .../imports/FluentUI/Controls/FluPivot.qml | 92 + .../FluentUI/Controls/FluPivotItem.qml | 9 + .../imports/FluentUI/Controls/FluPopup.qml | 47 + .../FluentUI/Controls/FluProgressBar.qml | 60 + .../FluentUI/Controls/FluProgressRing.qml | 74 + .../imports/FluentUI/Controls/FluQRCode.qml | 23 + .../FluentUI/Controls/FluRadioButton.qml | 98 + .../FluentUI/Controls/FluRadioButtons.qml | 29 + .../FluentUI/Controls/FluRatingControl.qml | 54 + .../FluentUI/Controls/FluRectangle.qml | 71 + .../FluentUI/Controls/FluRemoteLoader.qml | 39 + .../FluentUI/Controls/FluScreenshot.qml | 523 + .../FluentUI/Controls/FluScrollBar.qml | 85 + .../FluentUI/Controls/FluScrollIndicator.qml | 48 + .../FluentUI/Controls/FluScrollablePage.qml | 79 + .../imports/FluentUI/Controls/FluShadow.qml | 66 + .../imports/FluentUI/Controls/FluSlider.qml | 73 + .../imports/FluentUI/Controls/FluSpinBox.qml | 156 + .../FluentUI/Controls/FluStatusView.qml | 116 + .../imports/FluentUI/Controls/FluTabView.qml | 307 + .../FluentUI/Controls/FluTableModelColumn.qml | 5 + .../FluentUI/Controls/FluTableView.qml | 531 + src/Qt5/imports/FluentUI/Controls/FluText.qml | 11 + .../imports/FluentUI/Controls/FluTextBox.qml | 101 + .../Controls/FluTextBoxBackground.qml | 57 + .../FluentUI/Controls/FluTextBoxMenu.qml | 51 + .../FluentUI/Controls/FluTextButton.qml | 64 + .../FluentUI/Controls/FluTimePicker.qml | 400 + .../imports/FluentUI/Controls/FluTimeline.qml | 294 + .../FluentUI/Controls/FluToggleButton.qml | 108 + .../FluentUI/Controls/FluToggleSwitch.qml | 111 + .../imports/FluentUI/Controls/FluTooltip.qml | 29 + src/Qt5/imports/FluentUI/Controls/FluTour.qml | 201 + .../imports/FluentUI/Controls/FluTreeView.qml | 292 + .../imports/FluentUI/Controls/FluWindow.qml | 138 + .../FluentUI/Font/Segoe_Fluent_Icons.ttf | Bin .../imports/FluentUI/Image/noise.png | Bin src/{ => Qt5}/imports/FluentUI/JS/Chart.js | 0 src/Qt5/imports/FluentUI/plugins.qmltypes | 1834 ++ src/Qt5/imports/FluentUI/qmldir | 95 + .../Controls/ColorPicker/ColorPicker.qml | 0 .../ColorPicker/Content/Checkerboard.qml | 0 .../ColorPicker/Content/ColorSlider.qml | 0 .../ColorPicker/Content/NumberBox.qml | 0 .../ColorPicker/Content/PanelBorder.qml | 0 .../Controls/ColorPicker/Content/SBPicker.qml | 0 .../imports/FluentUI/Controls/FluAcrylic.qml | 0 .../imports/FluentUI/Controls/FluAppBar.qml | 0 .../imports/FluentUI/Controls/FluArea.qml | 0 .../FluentUI/Controls/FluAutoSuggestBox.qml | 0 .../imports/FluentUI/Controls/FluBadge.qml | 0 .../FluentUI/Controls/FluBreadcrumbBar.qml | 0 .../imports/FluentUI/Controls/FluButton.qml | 0 .../FluentUI/Controls/FluCalendarPicker.qml | 0 .../FluentUI/Controls/FluCalendarView.qml | 0 .../imports/FluentUI/Controls/FluCarousel.qml | 0 .../imports/FluentUI/Controls/FluChart.qml | 0 .../imports/FluentUI/Controls/FluCheckBox.qml | 0 .../FluentUI/Controls/FluColorPicker.qml | 0 .../FluentUI/Controls/FluColorView.qml | 0 .../imports/FluentUI/Controls/FluComboBox.qml | 0 .../FluentUI/Controls/FluContentDialog.qml | 0 .../FluentUI/Controls/FluContentPage.qml | 0 .../imports/FluentUI/Controls/FluControl.qml | 0 .../FluentUI/Controls/FluCopyableText.qml | 0 .../FluentUI/Controls/FluDatePicker.qml | 0 .../imports/FluentUI/Controls/FluDivider.qml | 0 .../FluentUI/Controls/FluDropDownButton.qml | 0 .../imports/FluentUI/Controls/FluExpander.qml | 0 .../FluentUI/Controls/FluFilledButton.qml | 0 .../imports/FluentUI/Controls/FluFlipView.qml | 0 .../FluentUI/Controls/FluFocusRectangle.qml | 0 .../imports/FluentUI/Controls/FluIcon.qml | 0 .../FluentUI/Controls/FluIconButton.qml | 0 .../imports/FluentUI/Controls/FluImage.qml | 0 .../imports/FluentUI/Controls/FluInfoBar.qml | 0 .../imports/FluentUI/Controls/FluItem.qml | 0 .../FluentUI/Controls/FluItemDelegate.qml | 0 .../imports/FluentUI/Controls/FluMenu.qml | 0 .../imports/FluentUI/Controls/FluMenuBar.qml | 0 .../FluentUI/Controls/FluMenuBarItem.qml | 0 .../imports/FluentUI/Controls/FluMenuItem.qml | 0 .../FluentUI/Controls/FluMenuSeparator.qml | 0 .../FluentUI/Controls/FluMultilineTextBox.qml | 0 .../FluentUI/Controls/FluNavigationView.qml | 0 .../imports/FluentUI/Controls/FluObject.qml | 0 .../imports/FluentUI/Controls/FluPage.qml | 0 .../FluentUI/Controls/FluPagination.qml | 0 .../imports/FluentUI/Controls/FluPaneItem.qml | 0 .../FluentUI/Controls/FluPaneItemEmpty.qml | 0 .../FluentUI/Controls/FluPaneItemExpander.qml | 0 .../FluentUI/Controls/FluPaneItemHeader.qml | 0 .../Controls/FluPaneItemSeparator.qml | 0 .../FluentUI/Controls/FluPasswordBox.qml | 0 .../imports/FluentUI/Controls/FluPivot.qml | 0 .../FluentUI/Controls/FluPivotItem.qml | 0 .../imports/FluentUI/Controls/FluPopup.qml | 0 .../FluentUI/Controls/FluProgressBar.qml | 0 .../FluentUI/Controls/FluProgressRing.qml | 0 .../imports/FluentUI/Controls/FluQRCode.qml | 0 .../FluentUI/Controls/FluRadioButton.qml | 0 .../FluentUI/Controls/FluRadioButtons.qml | 0 .../FluentUI/Controls/FluRatingControl.qml | 0 .../FluentUI/Controls/FluRectangle.qml | 0 .../FluentUI/Controls/FluRemoteLoader.qml | 0 .../FluentUI/Controls/FluScreenshot.qml | 0 .../FluentUI/Controls/FluScrollBar.qml | 0 .../FluentUI/Controls/FluScrollIndicator.qml | 0 .../FluentUI/Controls/FluScrollablePage.qml | 0 .../imports/FluentUI/Controls/FluShadow.qml | 0 .../imports/FluentUI/Controls/FluSlider.qml | 0 .../imports/FluentUI/Controls/FluSpinBox.qml | 0 .../FluentUI/Controls/FluStatusView.qml | 0 .../imports/FluentUI/Controls/FluTabView.qml | 0 .../FluentUI/Controls/FluTableModelColumn.qml | 0 .../FluentUI/Controls/FluTableView.qml | 0 .../imports/FluentUI/Controls/FluText.qml | 0 .../imports/FluentUI/Controls/FluTextBox.qml | 0 .../Controls/FluTextBoxBackground.qml | 0 .../FluentUI/Controls/FluTextBoxMenu.qml | 0 .../FluentUI/Controls/FluTextButton.qml | 0 .../FluentUI/Controls/FluTimePicker.qml | 0 .../imports/FluentUI/Controls/FluTimeline.qml | 0 .../FluentUI/Controls/FluToggleButton.qml | 0 .../FluentUI/Controls/FluToggleSwitch.qml | 0 .../imports/FluentUI/Controls/FluTooltip.qml | 0 .../imports/FluentUI/Controls/FluTour.qml | 0 .../imports/FluentUI/Controls/FluTreeView.qml | 0 .../imports/FluentUI/Controls/FluWindow.qml | 0 .../FluentUI/Font/Segoe_Fluent_Icons.ttf | Bin 0 -> 408752 bytes src/Qt6/imports/FluentUI/Image/noise.png | Bin 0 -> 271829 bytes src/Qt6/imports/FluentUI/JS/Chart.js | 20782 ++++++++++++++++ src/fluentuiplugin.cpp | 87 + src/fluentuiplugin.h | 21 + src/resource.qrc | 96 + 324 files changed, 40654 insertions(+), 365 deletions(-) create mode 100644 .cmake/QmlPlugin.cmake create mode 100644 example/qml-Qt6/App.qml create mode 100644 example/qml-Qt6/component/CodeExpander.qml create mode 100644 example/qml-Qt6/component/CustomWindow.qml create mode 100644 example/qml-Qt6/global/ItemsFooter.qml create mode 100644 example/qml-Qt6/global/ItemsOriginal.qml create mode 100644 example/qml-Qt6/global/MainEvent.qml create mode 100644 example/qml-Qt6/global/qmldir create mode 100644 example/qml-Qt6/page/T_Acrylic.qml create mode 100644 example/qml-Qt6/page/T_Awesome.qml create mode 100644 example/qml-Qt6/page/T_Badge.qml create mode 100644 example/qml-Qt6/page/T_BreadcrumbBar.qml create mode 100644 example/qml-Qt6/page/T_Buttons.qml create mode 100644 example/qml-Qt6/page/T_CalendarPicker.qml create mode 100644 example/qml-Qt6/page/T_Captcha.qml create mode 100644 example/qml-Qt6/page/T_Carousel.qml create mode 100644 example/qml-Qt6/page/T_Chart.qml create mode 100644 example/qml-Qt6/page/T_CheckBox.qml create mode 100644 example/qml-Qt6/page/T_ColorPicker.qml create mode 100644 example/qml-Qt6/page/T_ComboBox.qml create mode 100644 example/qml-Qt6/page/T_DatePicker.qml create mode 100644 example/qml-Qt6/page/T_Dialog.qml create mode 100644 example/qml-Qt6/page/T_Expander.qml create mode 100644 example/qml-Qt6/page/T_FlipView.qml create mode 100644 example/qml-Qt6/page/T_Home.qml create mode 100644 example/qml-Qt6/page/T_Http.qml create mode 100644 example/qml-Qt6/page/T_Image.qml create mode 100644 example/qml-Qt6/page/T_InfoBar.qml create mode 100644 example/qml-Qt6/page/T_Menu.qml create mode 100644 example/qml-Qt6/page/T_MultiWindow.qml create mode 100644 example/qml-Qt6/page/T_Pagination.qml create mode 100644 example/qml-Qt6/page/T_Pivot.qml create mode 100644 example/qml-Qt6/page/T_Progress.qml create mode 100644 example/qml-Qt6/page/T_QRCode.qml create mode 100644 example/qml-Qt6/page/T_RadioButton.qml create mode 100644 example/qml-Qt6/page/T_RatingControl.qml create mode 100644 example/qml-Qt6/page/T_Rectangle.qml create mode 100644 example/qml-Qt6/page/T_RemoteLoader.qml create mode 100644 example/qml-Qt6/page/T_Screenshot.qml create mode 100644 example/qml-Qt6/page/T_Settings.qml create mode 100644 example/qml-Qt6/page/T_Slider.qml create mode 100644 example/qml-Qt6/page/T_StatusView.qml create mode 100644 example/qml-Qt6/page/T_TabView.qml create mode 100644 example/qml-Qt6/page/T_TableView.qml create mode 100644 example/qml-Qt6/page/T_Text.qml create mode 100644 example/qml-Qt6/page/T_TextBox.qml create mode 100644 example/qml-Qt6/page/T_Theme.qml create mode 100644 example/qml-Qt6/page/T_TimePicker.qml create mode 100644 example/qml-Qt6/page/T_Timeline.qml create mode 100644 example/qml-Qt6/page/T_ToggleSwitch.qml create mode 100644 example/qml-Qt6/page/T_Tooltip.qml create mode 100644 example/qml-Qt6/page/T_Tour.qml create mode 100644 example/qml-Qt6/page/T_TreeView.qml create mode 100644 example/qml-Qt6/page/T_Typography.qml create mode 100644 example/qml-Qt6/page/T_Watermark.qml create mode 100644 example/qml-Qt6/window/AboutWindow.qml create mode 100644 example/qml-Qt6/window/HotloadWindow.qml create mode 100644 example/qml-Qt6/window/LoginWindow.qml create mode 100644 example/qml-Qt6/window/MainWindow.qml create mode 100644 example/qml-Qt6/window/SingleInstanceWindow.qml create mode 100644 example/qml-Qt6/window/SingleTaskWindow.qml create mode 100644 example/qml-Qt6/window/StandardWindow.qml create mode 100644 example/resource.qrc create mode 100644 src/Qt5/imports/FluentUI/Controls/ColorPicker/ColorPicker.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/ColorSlider.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/NumberBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/PanelBorder.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/SBPicker.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluAppBar.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluArea.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluBadge.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluBreadcrumbBar.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluButton.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluCalendarPicker.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluCalendarView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluCarousel.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluChart.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluColorPicker.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluColorView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluComboBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluContentDialog.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluContentPage.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluControl.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluCopyableText.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluDivider.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluDropDownButton.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluExpander.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluFilledButton.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluFlipView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluFocusRectangle.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluIcon.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluIconButton.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluImage.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluInfoBar.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluItem.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluItemDelegate.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluMenu.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluMenuBar.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluMenuItem.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluMenuSeparator.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluMultilineTextBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluObject.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPage.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPagination.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPaneItem.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPaneItemEmpty.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPaneItemExpander.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPaneItemHeader.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPaneItemSeparator.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPasswordBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPivot.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPivotItem.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluPopup.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluProgressRing.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluQRCode.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluRadioButtons.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluRatingControl.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluRectangle.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluRemoteLoader.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluScreenshot.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluScrollBar.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluScrollIndicator.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluScrollablePage.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluShadow.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluSlider.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluStatusView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTabView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTableModelColumn.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTableView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluText.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTextBox.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTextBoxMenu.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTextButton.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTimePicker.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTimeline.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluToggleButton.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluToggleSwitch.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTooltip.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTour.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluTreeView.qml create mode 100644 src/Qt5/imports/FluentUI/Controls/FluWindow.qml rename src/{ => Qt5}/imports/FluentUI/Font/Segoe_Fluent_Icons.ttf (100%) rename src/{ => Qt5}/imports/FluentUI/Image/noise.png (100%) rename src/{ => Qt5}/imports/FluentUI/JS/Chart.js (100%) create mode 100644 src/Qt5/imports/FluentUI/plugins.qmltypes create mode 100644 src/Qt5/imports/FluentUI/qmldir rename src/{ => Qt6}/imports/FluentUI/Controls/ColorPicker/ColorPicker.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/ColorPicker/Content/ColorSlider.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/ColorPicker/Content/NumberBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/ColorPicker/Content/PanelBorder.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/ColorPicker/Content/SBPicker.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluAcrylic.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluAppBar.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluArea.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluAutoSuggestBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluBadge.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluBreadcrumbBar.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluButton.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluCalendarPicker.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluCalendarView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluCarousel.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluChart.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluCheckBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluColorPicker.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluColorView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluComboBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluContentDialog.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluContentPage.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluControl.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluCopyableText.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluDatePicker.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluDivider.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluDropDownButton.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluExpander.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluFilledButton.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluFlipView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluFocusRectangle.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluIcon.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluIconButton.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluImage.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluInfoBar.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluItem.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluItemDelegate.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluMenu.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluMenuBar.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluMenuBarItem.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluMenuItem.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluMenuSeparator.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluMultilineTextBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluNavigationView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluObject.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPage.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPagination.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPaneItem.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPaneItemEmpty.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPaneItemExpander.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPaneItemHeader.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPaneItemSeparator.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPasswordBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPivot.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPivotItem.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluPopup.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluProgressBar.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluProgressRing.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluQRCode.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluRadioButton.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluRadioButtons.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluRatingControl.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluRectangle.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluRemoteLoader.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluScreenshot.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluScrollBar.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluScrollIndicator.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluScrollablePage.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluShadow.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluSlider.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluSpinBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluStatusView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTabView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTableModelColumn.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTableView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluText.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTextBox.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTextBoxBackground.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTextBoxMenu.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTextButton.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTimePicker.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTimeline.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluToggleButton.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluToggleSwitch.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTooltip.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTour.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluTreeView.qml (100%) rename src/{ => Qt6}/imports/FluentUI/Controls/FluWindow.qml (100%) create mode 100644 src/Qt6/imports/FluentUI/Font/Segoe_Fluent_Icons.ttf create mode 100644 src/Qt6/imports/FluentUI/Image/noise.png create mode 100644 src/Qt6/imports/FluentUI/JS/Chart.js create mode 100644 src/fluentuiplugin.cpp create mode 100644 src/fluentuiplugin.h create mode 100644 src/resource.qrc diff --git a/.cmake/QmlPlugin.cmake b/.cmake/QmlPlugin.cmake new file mode 100644 index 00000000..29aec2fc --- /dev/null +++ b/.cmake/QmlPlugin.cmake @@ -0,0 +1,139 @@ +include(CMakeParseArguments) +find_package(Qt5 REQUIRED COMPONENTS Core) + +function(FindQmlPluginDump) + get_target_property (QT_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION) + execute_process( + COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_BINS + OUTPUT_VARIABLE QT_BIN_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endfunction() + +function(FindQtInstallQml) + execute_process( + COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_QML + OUTPUT_VARIABLE PROC_RESULT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +set(QT_INSTALL_QML ${PROC_RESULT} PARENT_SCOPE) +endfunction() + +function(add_qmlplugin TARGET) + set(options NO_AUTORCC NO_AUTOMOC) + set(oneValueArgs URI VERSION BINARY_DIR QMLDIR LIBTYPE) + set(multiValueArgs SOURCES QMLFILES QMLFILESALIAS) + cmake_parse_arguments(QMLPLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT QMLPLUGIN_URI OR NOT QMLPLUGIN_VERSION OR NOT QMLPLUGIN_QMLDIR OR NOT QMLPLUGIN_LIBTYPE) + message(WARNING "TARGET,URI,VERSION,qmldir and LIBTYPE must be set, no files generated") + return() + endif() + if(NOT QMLPLUGIN_BINARY_DIR) + set(QMLPLUGIN_BINARY_DIR ${CMAKE_BINARY_DIR}/${QMLPLUGIN_URI}) + endif() + add_library(${TARGET} ${QMLPLUGIN_LIBTYPE} + ${QMLPLUGIN_SOURCES} + ) +set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) +add_custom_target("${TARGET}-qmlfiles" SOURCES ${QMLPLUGIN_QMLFILES}) + +if(QMLPLUGIN_NO_AUTORCC) + set_target_properties(${TARGET} PROPERTIES AUTOMOC OFF) +else() + set_target_properties(${TARGET} PROPERTIES AUTOMOC ON) +endif() +if(QMLPLUGIN_NO_AUTOMOC) + set_target_properties(${TARGET} PROPERTIES AUTOMOC OFF) +else() + set_target_properties(${TARGET} PROPERTIES AUTOMOC ON) +endif() + +if (${QMLPLUGIN_LIBTYPE} MATCHES "SHARED") + FindQmlPluginDump() + FindQtInstallQml() + if(QMLPLUGIN_BINARY_DIR) + set(MAKE_QMLPLUGINDIR_COMMAND ${CMAKE_COMMAND} -E make_directory ${QMLPLUGIN_BINARY_DIR}) + endif() + set(COPY_QMLDIR_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/Qt5/${QMLPLUGIN_QMLDIR}/qmldir $/${QMLPLUGIN_URI}/qmldir) + set(INSTALL_QMLDIR_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/Qt5/${QMLPLUGIN_QMLDIR}/qmldir ${QMLPLUGIN_BINARY_DIR}/qmldir) + set(COPY_QMLTYPES_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/Qt5/${QMLPLUGIN_QMLDIR}/plugins.qmltypes $/${QMLPLUGIN_URI}/plugins.qmltypes) + set(INSTALL_QMLTYPES_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/Qt5/${QMLPLUGIN_QMLDIR}/plugins.qmltypes ${QMLPLUGIN_BINARY_DIR}/plugins.qmltypes) + set(COPY_LIBRARY_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/$ $/${QMLPLUGIN_URI}) + set(INSTALL_LIBRARY_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/$ ${QMLPLUGIN_BINARY_DIR}) + if(QMLPLUGIN_QMLDIR) + set(COPY_QMLFILES_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/Qt5/${QMLPLUGIN_QMLDIR} $/${QMLPLUGIN_URI}) + else() + set(COPY_QMLFILES_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/${QMLPLUGIN_QMLFILES} $/${QMLPLUGIN_URI}) + endif() + set(INSTALL_QMLFILES_COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/Qt5/${QMLPLUGIN_QMLDIR} ${QMLPLUGIN_BINARY_DIR}) + if(QMLPLUGIN_BINARY_DIR) + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${MAKE_QMLPLUGINDIR_COMMAND} + COMMAND ${COPY_QMLDIR_COMMAND} + COMMENT "Copying qmldir to binary directory" + ) +else() + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${COPY_QMLDIR_COMMAND} + COMMENT "Copying qmldir to binary directory" + ) +endif() + +if(QMLPLUGIN_BINARY_DIR) + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${MAKE_QMLPLUGINDIR_COMMAND} + COMMAND ${COPY_QMLTYPES_COMMAND} + COMMENT "Copying qmltypes to binary directory" + ) +else() + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${COPY_QMLTYPES_COMMAND} + COMMENT "Copying qmltypes to binary directory" + ) +endif() + +add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${COPY_LIBRARY_COMMAND} + COMMENT "Copying Lib to binary plugin directory" +) + +if(QMLPLUGIN_QMLFILES) + add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${COPY_QMLFILES_COMMAND} + COMMENT "Copying QML files to binary directory" + ) +endif() + +add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${GENERATE_QMLTYPES_COMMAND} + COMMENT "Generating plugin.qmltypes" +) + +string(REPLACE "." "/" QMLPLUGIN_INSTALL_URI ${QMLPLUGIN_URI}) + +add_custom_command( + TARGET ${TARGET} + POST_BUILD + COMMAND ${INSTALL_QMLTYPES_COMMAND} + COMMAND ${INSTALL_QMLDIR_COMMAND} + COMMAND ${INSTALL_LIBRARY_COMMAND} + COMMAND ${INSTALL_QMLFILES_COMMAND} + COMMAND ${INSTALL_QMLTYPES_COMMAND} + COMMENT "Install library and aditional files" +) +endif() +endfunction() diff --git a/CMakeLists.txt b/CMakeLists.txt index 703b6fcf..59421d76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,10 @@ option(FLUENTUI_BUILD_EXAMPLES "Build FluentUI demo applications." ON) option(FLUENTUI_BUILD_FRAMELESSHEPLER "Build FramelessHelper." ON) option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF) -find_package(Qt6 REQUIRED COMPONENTS Core) +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) -set(QT_SDK_DIR "${Qt6_DIR}") +set(QT_SDK_DIR "${Qt${QT_VERSION_MAJOR}_DIR}") cmake_path(GET QT_SDK_DIR PARENT_PATH QT_SDK_DIR) cmake_path(GET QT_SDK_DIR PARENT_PATH QT_SDK_DIR) cmake_path(GET QT_SDK_DIR PARENT_PATH QT_SDK_DIR) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index ccf0f1a7..57e86631 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -26,7 +26,8 @@ endif() #获取文件路径分隔符(解决执行命令的时候有些平台会报错) file(TO_CMAKE_PATH "/" PATH_SEPARATOR) -find_package(Qt6 REQUIRED COMPONENTS Quick Svg Network) +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick Svg Network) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Quick Svg Network) if(QT_VERSION VERSION_GREATER_EQUAL "6.3") qt_standard_project_setup() @@ -50,19 +51,25 @@ foreach(filepath ${CPP_FILES}) list(APPEND sources_files ${filename}) endforeach(filepath) -#遍历所有qml文件 -file(GLOB_RECURSE QML_PATHS *.qml) -foreach(filepath ${QML_PATHS}) - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) - list(APPEND qml_files ${filename}) -endforeach(filepath) +if(QT_VERSION VERSION_GREATER_EQUAL "6.2") + #遍历所有qml文件 + file(GLOB_RECURSE QML_PATHS *.qml qmldir) + foreach(filepath ${QML_PATHS}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) + if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/") + string(REPLACE "qml-Qt${QT_VERSION_MAJOR}" "qml" filealias ${filename}) + set_source_files_properties(${filename} PROPERTIES QT_RESOURCE_ALIAS ${filealias}) + list(APPEND qml_files ${filename}) + endif() + endforeach(filepath) -#遍历所有资源文件 -file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp qmldir) -foreach(filepath ${RES_PATHS}) - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) - list(APPEND resource_files ${filename}) -endforeach(filepath) + #遍历所有资源文件 + file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp) + foreach(filepath ${RES_PATHS}) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) + list(APPEND resource_files ${filename}) + endforeach(filepath) +endif() #如果是Windows平台,则生成rc文件 set(EXAMPLE_VERSION_RC_PATH "") @@ -76,12 +83,12 @@ endif() #添加可执行文件 if (WIN32) - qt_add_executable(example + add_executable(example ${sources_files} ${EXAMPLE_VERSION_RC_PATH} ) else () - qt_add_executable(example + add_executable(example ${sources_files} ) endif () @@ -102,14 +109,21 @@ if(WIN32) ) endif() -#添加qml模块 -qt_add_qml_module(example - URI "example" - VERSION 1.0 - QML_FILES ${qml_files} - RESOURCES ${resource_files} - RESOURCE_PREFIX "/" -) +if(QT_VERSION VERSION_GREATER_EQUAL "6.2") + #添加qml模块 + qt_add_qml_module(example + URI "example" + VERSION 1.0 + QML_FILES ${qml_files} + RESOURCES ${resource_files} + RESOURCE_PREFIX "/" + ) +else() + target_include_directories(example PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ) + target_sources(example PRIVATE resource.qrc) +endif() #导入component头文件,不然通过QML_NAMED_ELEMENT生成的c++类会找不到头文件报错 target_include_directories(example PRIVATE @@ -128,9 +142,9 @@ set_target_properties(example PROPERTIES #链接库 if (FLUENTUI_BUILD_STATIC_LIB) target_link_libraries(example PRIVATE - Qt::Quick - Qt::Svg - Qt::Network + Qt${QT_VERSION_MAJOR}::Quick + Qt${QT_VERSION_MAJOR}::Svg + Qt${QT_VERSION_MAJOR}::Network fluentui fluentuiplugin FramelessHelper::Core @@ -138,9 +152,9 @@ if (FLUENTUI_BUILD_STATIC_LIB) ) else() target_link_libraries(example PRIVATE - Qt::Quick - Qt::Svg - Qt::Network + Qt${QT_VERSION_MAJOR}::Quick + Qt${QT_VERSION_MAJOR}::Svg + Qt${QT_VERSION_MAJOR}::Network fluentuiplugin FramelessHelper::Core FramelessHelper::Quick diff --git a/example/qml-Qt6/App.qml b/example/qml-Qt6/App.qml new file mode 100644 index 00000000..f0af5371 --- /dev/null +++ b/example/qml-Qt6/App.qml @@ -0,0 +1,44 @@ +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +Window { + id: app + flags: Qt.SplashScreen + + FluHttpInterceptor{ + id:interceptor + function onIntercept(request){ + if(request.method === "get"){ + request.params["method"] = "get" + } + if(request.method === "post"){ + request.params["method"] = "post" + } + request.headers["token"] ="yyds" + request.headers["os"] ="pc" + console.debug(JSON.stringify(request)) + return request + } + } + + Component.onCompleted: { + FluApp.init(app) + FluTheme.darkMode = FluThemeType.System + FluTheme.enableAnimation = true + FluApp.routes = { + "/":"qrc:/example/qml/window/MainWindow.qml", + "/about":"qrc:/example/qml/window/AboutWindow.qml", + "/login":"qrc:/example/qml/window/LoginWindow.qml", + "/hotload":"qrc:/example/qml/window/HotloadWindow.qml", + "/singleTaskWindow":"qrc:/example/qml/window/SingleTaskWindow.qml", + "/standardWindow":"qrc:/example/qml/window/StandardWindow.qml", + "/singleInstanceWindow":"qrc:/example/qml/window/SingleInstanceWindow.qml" + } + FluApp.initialRoute = "/" + FluApp.httpInterceptor = interceptor + FluApp.run() + } +} diff --git a/example/qml-Qt6/component/CodeExpander.qml b/example/qml-Qt6/component/CodeExpander.qml new file mode 100644 index 00000000..f69c879a --- /dev/null +++ b/example/qml-Qt6/component/CodeExpander.qml @@ -0,0 +1,145 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI + +FluExpander{ + + id:control + property string code: "" + headerText: "Source" + contentHeight:content.height + focus: false + + FluMultilineTextBox{ + id:content + width:parent.width + activeFocusOnTab: false + activeFocusOnPress: false + readOnly: true + text:highlightQmlCode(code) + textFormat: FluMultilineTextBox.RichText + KeyNavigation.priority: KeyNavigation.BeforeItem + background:Rectangle{ + radius: 4 + color:FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1) + border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1) + border.width: 1 + } + } + + FluIconButton{ + iconSource:FluentIcons.Copy + anchors{ + right: parent.right + top: parent.top + rightMargin: 5 + topMargin: 5 + } + onClicked:{ + FluTools.clipText(FluTools.html2PlantText(content.text)) + showSuccess("复制成功") + } + } + + function htmlEncode(e){ + var i,s; + for(i in s={ + "&":/&/g,//""//":/"/g,"'":/'/g, + "<":/":/>/g,"
":/\n/g, + " ":/ /g," ":/\t/g + })e=e.replace(s[i],i); + return e; + } + + function highlightQmlCode(code) { + // 定义 QML 关键字列表 + var qmlKeywords = [ + "FluTextButton", + "FluAppBar", + "FluAutoSuggestBox", + "FluBadge", + "FluButton", + "FluCalendarPicker", + "FluCalendarView", + "FluCarousel", + "FluCheckBox", + "FluColorPicker", + "FluColorView", + "FluComboBox", + "FluContentDialog", + "FluContentPage", + "FluDatePicker", + "FluDivider", + "FluDropDownButton", + "FluExpander", + "FluFilledButton", + "FluFlipView", + "FluFocusRectangle", + "FluIcon", + "FluIconButton", + "FluInfoBar", + "FluItem", + "FluMediaPlayer", + "FluMenu", + "FluMenuItem", + "FluMultilineTextBox", + "FluNavigationView", + "FluObject", + "FluPaneItem", + "FluPaneItemExpander", + "FluPaneItemHeader", + "FluPaneItemSeparator", + "FluPivot", + "FluPivotItem", + "FluProgressBar", + "FluProgressRing", + "FluRadioButton", + "FluRectangle", + "FluScrollablePage", + "FluScrollBar", + "FluShadow", + "FluSlider", + "FluTabView", + "FluText", + "FluTextArea", + "FluTextBox", + "FluTextBoxBackground", + "FluTextBoxMenu", + "FluTextButton", + "FluTextFiled", + "FluTimePicker", + "FluToggleSwitch", + "FluTooltip", + "FluTreeView", + "FluWindow", + "FluWindowResize", + "FluToggleButton", + "FluTableView", + "FluColors", + "FluTheme", + "FluStatusView", + "FluRatingControl", + "FluPasswordBox", + "FluBreadcrumbBar", + "FluCopyableText", + "FluAcrylic", + "FluRemoteLoader", + "FluMenuBar", + "FluPagination", + "FluRadioButtons", + "FluImage", + "FluSpinBox", + "FluHttp", + "FluWatermark", + "FluTour", + "FluQRCode", + "FluTimeline", + "FluChart" + ]; + code = code.replace(/\n/g, "
"); + code = code.replace(/ /g, " "); + return code.replace(RegExp("\\b(" + qmlKeywords.join("|") + ")\\b", "g"), "$1"); + } +} diff --git a/example/qml-Qt6/component/CustomWindow.qml b/example/qml-Qt6/component/CustomWindow.qml new file mode 100644 index 00000000..88451d28 --- /dev/null +++ b/example/qml-Qt6/component/CustomWindow.qml @@ -0,0 +1,64 @@ +import QtQuick +import QtQuick.Layouts +import FluentUI +import org.wangwenx190.FramelessHelper + +FluWindow { + id:window + property bool fixSize + property alias titleVisible: title_bar.titleVisible + property bool appBarVisible: true + default property alias content: container.data + FluAppBar { + id: title_bar + title: window.title + visible: window.appBarVisible + icon:"qrc:/example/res/image/favicon.ico" + anchors { + top: parent.top + left: parent.left + right: parent.right + } + darkText: lang.dark_mode + } + Item{ + id:container + anchors{ + top: title_bar.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + clip: true + } + FramelessHelper{ + id:framless_helper + onReady: { + setTitleBarItem(title_bar) + moveWindowToDesktopCenter() + setHitTestVisible(title_bar.minimizeButton()) + setHitTestVisible(title_bar.maximizeButton()) + setHitTestVisible(title_bar.closeButton()) + setWindowFixedSize(fixSize) + title_bar.maximizeButton.visible = !fixSize + if (blurBehindWindowEnabled) + window.background = undefined + window.show() + } + } + Connections{ + target: FluTheme + function onDarkChanged(){ + if (FluTheme.dark) + FramelessUtils.systemTheme = FramelessHelperConstants.Dark + else + FramelessUtils.systemTheme = FramelessHelperConstants.Light + } + } + function setHitTestVisible(com){ + framless_helper.setHitTestVisible(com) + } + function setTitleBarItem(com){ + framless_helper.setTitleBarItem(com) + } +} diff --git a/example/qml-Qt6/global/ItemsFooter.qml b/example/qml-Qt6/global/ItemsFooter.qml new file mode 100644 index 00000000..c6742d06 --- /dev/null +++ b/example/qml-Qt6/global/ItemsFooter.qml @@ -0,0 +1,30 @@ +pragma Singleton + +import QtQuick +import FluentUI + +FluObject{ + + property var navigationView + + id:footer_items + + FluPaneItemSeparator{} + + FluPaneItem{ + title:lang.about + icon:FluentIcons.Contact + tapFunc:function(){ + FluApp.navigate("/about") + } + } + + FluPaneItem{ + title:lang.settings + icon:FluentIcons.Settings + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Settings.qml") + } + } + +} diff --git a/example/qml-Qt6/global/ItemsOriginal.qml b/example/qml-Qt6/global/ItemsOriginal.qml new file mode 100644 index 00000000..3f3beb48 --- /dev/null +++ b/example/qml-Qt6/global/ItemsOriginal.qml @@ -0,0 +1,483 @@ +pragma Singleton + +import QtQuick +import FluentUI + +FluObject{ + + property var navigationView + + function rename(item, newName){ + if(newName && newName.trim().length>0){ + item.title = newName; + } + } + + FluPaneItem{ + id:item_home + count: 9 + title:lang.home + infoBadge:FluBadge{ + count: item_home.count + } + icon:FluentIcons.Home + onTap:{ + if(navigationView.getCurrentUrl()){ + item_home.count = 0 + } + navigationView.push("qrc:/example/qml/page/T_Home.qml") + } + editDelegate: FluTextBox{ + text:item_home.title + } + menuDelegate: FluMenu{ + id:nav_item_right_menu + width: 120 + FluMenuItem{ + text: "重命名" + visible: true + onClicked: { + item_home.showEdit = true + } + } + } + } + + FluPaneItemExpander{ + id:item_expander_basic_input + title:lang.basic_input + icon:FluentIcons.CheckboxComposite + editDelegate: FluTextBox{ + text:item_expander_basic_input.title + } + menuDelegate: FluMenu{ + FluMenuItem{ + text: "重命名" + visible: true + onClicked: { + item_expander_basic_input.showEdit = true + } + } + } + FluPaneItem{ + id:item_buttons + count: 99 + infoBadge:FluBadge{ + count: item_buttons.count + } + title:"Buttons" + image:"qrc:/example/res/image/control/Button.png" + recentlyUpdated:true + desc:"A control that responds to user input and raisesa Click event." + onTap:{ + item_buttons.count = 0 + navigationView.push("qrc:/example/qml/page/T_Buttons.qml") + } + } + FluPaneItem{ + id:item_text + title:"Text" + count: 5 + infoBadge:FluBadge{ + count: item_text.count + color: Qt.rgba(82/255,196/255,26/255,1) + } + onTap:{ + item_text.count = 0 + navigationView.push("qrc:/example/qml/page/T_Text.qml") + } + } + FluPaneItem{ + title:"Image" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Image.qml") + } + } + FluPaneItem{ + title:"Slider" + image:"qrc:/example/res/image/control/Slider.png" + recentlyUpdated:true + desc:"A control that lets the user select from a rangeof values by moving a Thumb control along atrack." + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Slider.qml") + } + } + FluPaneItem{ + title:"CheckBox" + image:"qrc:/example/res/image/control/Checkbox.png" + recentlyUpdated:true + desc:"A control that a user can select or clear." + onTap:{ + navigationView.push("qrc:/example/qml/page/T_CheckBox.qml") + } + } + FluPaneItem{ + title:"RadioButton" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_RadioButton.qml") + } + } + FluPaneItem{ + title:"ToggleSwitch" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_ToggleSwitch.qml") + } + } + } + + FluPaneItemExpander{ + title:lang.form + icon:FluentIcons.GridView + FluPaneItem{ + title:"TextBox" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_TextBox.qml") + } + } + FluPaneItem{ + title:"TimePicker" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_TimePicker.qml") + } + } + FluPaneItem{ + title:"DatePicker" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_DatePicker.qml") + } + } + FluPaneItem{ + title:"CalendarPicker" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_CalendarPicker.qml") + } + } + FluPaneItem{ + title:"ColorPicker" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_ColorPicker.qml") + } + } + } + + FluPaneItemExpander{ + title:lang.surface + icon:FluentIcons.SurfaceHub + FluPaneItem{ + title:"InfoBar" + image:"qrc:/example/res/image/control/InfoBar.png" + recentlyUpdated:true + desc:"An inline message to display app-wide statuschange information." + onTap:{ + navigationView.push("qrc:/example/qml/page/T_InfoBar.qml") + } + } + FluPaneItem{ + title:"Progress" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Progress.qml") + } + } + FluPaneItem{ + title:"RatingControl" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_RatingControl.qml") + } + } + FluPaneItem{ + title:"Badge" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Badge.qml") + } + } + FluPaneItem{ + title:"Rectangle" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Rectangle.qml") + } + } + FluPaneItem{ + title:"StatusView" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_StatusView.qml") + } + } + FluPaneItem{ + title:"Carousel" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Carousel.qml") + } + } + FluPaneItem{ + title:"Expander" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Expander.qml") + } + } + FluPaneItem{ + title:"Watermark" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Watermark.qml") + } + } + } + + FluPaneItemExpander{ + title:lang.popus + icon:FluentIcons.ButtonMenu + FluPaneItem{ + title:"Dialog" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Dialog.qml") + } + } + FluPaneItem{ + id:item_combobox + title:"ComboBox" + count: 9 + infoBadge:FluBadge{ + count: item_combobox.count + color: Qt.rgba(250/255,173/255,20/255,1) + } + onTap:{ + item_combobox.count = 0 + navigationView.push("qrc:/example/qml/page/T_ComboBox.qml") + } + } + FluPaneItem{ + title:"Tooltip" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Tooltip.qml") + } + } + FluPaneItem{ + title:"Menu" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Menu.qml") + } + } + } + + FluPaneItemExpander{ + title:lang.navigation + icon:FluentIcons.AllApps + FluPaneItem{ + title:"Pivot" + image:"qrc:/example/res/image/control/Pivot.png" + recentlyAdded:true + order:3 + desc:"Presents information from different sources in atabbed view." + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Pivot.qml") + } + } + FluPaneItem{ + title:"BreadcrumbBar" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_BreadcrumbBar.qml") + } + } + FluPaneItem{ + title:"TabView" + image:"qrc:/example/res/image/control/TabView.png" + recentlyAdded:true + order:1 + desc:"A control that displays a collection of tabs thatcan be used to display several documents." + onTap:{ + navigationView.push("qrc:/example/qml/page/T_TabView.qml") + } + } + FluPaneItem{ + title:"TreeView" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_TreeView.qml") + } + } + FluPaneItem{ + title:"TableView" + image:"qrc:/example/res/image/control/DataGrid.png" + recentlyAdded:true + order:4 + desc:"The TableView control provides a flexible way to display a collection of data in rows and columns" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_TableView.qml") + } + } + FluPaneItem{ + title:"Pagination" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Pagination.qml") + } + } + FluPaneItem{ + title:"MultiWindow" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_MultiWindow.qml") + } + } + FluPaneItem{ + title:"FlipView" + image:"qrc:/example/res/image/control/FlipView.png" + recentlyAdded:true + order:2 + desc:"Presents a collection of items that the user canflip through, one item at a time." + onTap:{ + navigationView.push("qrc:/example/qml/page/T_FlipView.qml") + } + } + } + + FluPaneItemExpander{ + title:lang.theming + icon:FluentIcons.Brightness + FluPaneItem{ + title:"Acrylic" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Acrylic.qml") + } + } + FluPaneItem{ + title:"Theme" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Theme.qml") + } + } + FluPaneItem{ + title:"Typography" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Typography.qml") + } + } + FluPaneItem{ + title:"Awesome" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Awesome.qml") + } + } + } + + FluPaneItemSeparator{ + spacing:10 + size:1 + } + + FluPaneItemExpander{ + title:lang.other + icon:FluentIcons.Shop + FluPaneItem{ + title:"QRCode" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_QRCode.qml") + } + } + FluPaneItem{ + title:"Tour" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Tour.qml") + } + } + FluPaneItem{ + title:"Timeline" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Timeline.qml") + } + } + FluPaneItem{ + title:"Screenshot" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Screenshot.qml") + } + } + FluPaneItem{ + title:"Captcha" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Captcha.qml") + } + } + FluPaneItem{ + title:"Chart" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Chart.qml") + } + } + FluPaneItem{ + title:"Http" + onTap:{ + navigationView.push("qrc:/example/qml/page/T_Http.qml") + } + } + FluPaneItem{ + id:item_other + title:"RemoteLoader" + count: 99 + infoBadge:FluBadge{ + count: item_other.count + color: Qt.rgba(82/255,196/255,26/255,1) + } + onTap:{ + item_other.count = 0 + navigationView.push("qrc:/example/qml/page/T_RemoteLoader.qml") + } + } + FluPaneItem{ + title:"HotLoader" + tapFunc:function(){ + FluApp.navigate("/hotload") + } + } + } + + function getRecentlyAddedData(){ + var arr = [] + for(var i=0;i ${item.title}`,key:item.key}) + } + else + arr.push({title:item.title,key:item.key}) + } + } + return arr + } + + function startPageByItem(data){ + navigationView.startPageByItem(data) + } + +} diff --git a/example/qml-Qt6/global/MainEvent.qml b/example/qml-Qt6/global/MainEvent.qml new file mode 100644 index 00000000..7119ffc6 --- /dev/null +++ b/example/qml-Qt6/global/MainEvent.qml @@ -0,0 +1,9 @@ +pragma Singleton + +import QtQuick +import QtQuick.Controls +import FluentUI + +QtObject { + property int displayMode : FluNavigationViewType.Auto +} diff --git a/example/qml-Qt6/global/qmldir b/example/qml-Qt6/global/qmldir new file mode 100644 index 00000000..a1122801 --- /dev/null +++ b/example/qml-Qt6/global/qmldir @@ -0,0 +1,3 @@ +singleton ItemsOriginal 1.0 ItemsOriginal.qml +singleton ItemsFooter 1.0 ItemsFooter.qml +singleton MainEvent 1.0 MainEvent.qml diff --git a/example/qml-Qt6/page/T_Acrylic.qml b/example/qml-Qt6/page/T_Acrylic.qml new file mode 100644 index 00000000..ae83a596 --- /dev/null +++ b/example/qml-Qt6/page/T_Acrylic.qml @@ -0,0 +1,114 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Acrylic" + + RowLayout{ + spacing: 10 + Layout.topMargin: 20 + FluText{ + text:"tintColor:" + Layout.alignment: Qt.AlignVCenter + } + FluColorPicker{ + id:color_picker + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"tintOpacity:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_tint_opacity + value: 65 + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"blurRadius:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_blur_radius + value: 32 + } + } + FluArea{ + Layout.fillWidth: true + height: 1200/4+20 + paddings: 10 + Layout.topMargin: 10 + FluRectangle{ + width: 1920/4 + height: 1200/4 + radius:[15,15,15,15] + Image { + id:image + asynchronous: true + source: "qrc:/example/res/image/bg_scenic.png" + anchors.fill: parent + sourceSize: Qt.size(2*width,2*height) + } + FluAcrylic { + id:acrylic + target: image + width: 200 + height: 200 + tintOpacity: slider_tint_opacity.value/100 + tintColor: color_picker.colorValue + blurRadius: slider_blur_radius.value + x:(image.width-width)/2 + y:(image.height-height)/2 + FluText { + anchors.centerIn: parent + text: "Acrylic" + color: "#FFFFFF" + font.bold: true + } + MouseArea { + property point clickPos: Qt.point(0,0) + id:drag_area + anchors.fill: parent + onPressed: (mouse)=>{ + clickPos = Qt.point(mouse.x, mouse.y) + } + onPositionChanged: (mouse)=>{ + var delta = Qt.point(mouse.x - clickPos.x,mouse.y - clickPos.y) + acrylic.x = acrylic.x + delta.x + acrylic.y = acrylic.y + delta.y + } + } + } + Layout.topMargin: 20 + } + + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'Image{ + id:image + width: 800 + height: 600 + source: "qrc:/example/res/image/image_huoyin.webp" + radius: 8 + } + FluAcrylic{ + target:image + width: 100 + height: 100 + anchors.centerIn: parent + } +}' + } + +} diff --git a/example/qml-Qt6/page/T_Awesome.qml b/example/qml-Qt6/page/T_Awesome.qml new file mode 100644 index 00000000..182ce910 --- /dev/null +++ b/example/qml-Qt6/page/T_Awesome.qml @@ -0,0 +1,71 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI + +FluContentPage { + + title:"Awesome" + + FluTextBox{ + id:text_box + placeholderText: "请输入关键字" + anchors{ + topMargin: 20 + top:parent.top + } + } + + FluFilledButton{ + text:"搜索" + anchors{ + left: text_box.right + verticalCenter: text_box.verticalCenter + leftMargin: 14 + } + onClicked: { + grid_view.model = FluApp.awesomelist(text_box.text) + } + } + GridView{ + id:grid_view + cellWidth: 80 + cellHeight: 80 + clip: true + boundsBehavior: GridView.StopAtBounds + model:FluApp.awesomelist() + ScrollBar.vertical: FluScrollBar {} + anchors{ + topMargin: 10 + top:text_box.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + delegate: Item { + width: 68 + height: 80 + FluIconButton{ + id:item_icon + iconSource:modelData.icon + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + var text ="FluentIcons."+modelData.name; + FluTools.clipText(text) + showSuccess("您复制了 "+text) + } + } + FluText { + id:item_name + font.pixelSize: 10 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: item_icon.bottom + width:parent.width + wrapMode: Text.WrapAnywhere + text: modelData.name + horizontalAlignment: Text.AlignHCenter + } + } + } +} diff --git a/example/qml-Qt6/page/T_Badge.qml b/example/qml-Qt6/page/T_Badge.qml new file mode 100644 index 00000000..baccc3d7 --- /dev/null +++ b/example/qml-Qt6/page/T_Badge.qml @@ -0,0 +1,129 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Badge" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 106 + paddings: 10 + + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"一般出现在通知图标或头像的右上角,用于显示需要处理的消息条数" + } + + Row{ + spacing: 20 + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + topRight: true + showZero: true + count:0 + } + } + + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + topRight: true + showZero: true + count:5 + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + topRight: true + showZero: true + count:50 + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + topRight: true + showZero: true + count:100 + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + topRight: true + showZero: true + isDot:true + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + topRight: true + showZero: true + count:99 + color: Qt.rgba(250/255,173/255,20/255,1) + } + } + Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + topRight: true + showZero: true + count:99 + color: Qt.rgba(82/255,196/255,26/255,1) + } + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'Rectangle{ + width: 40 + height: 40 + radius: 8 + color: Qt.rgba(191/255,191/255,191/255,1) + FluBadge{ + count: 100 + isDot: false + color: Qt.rgba(82/255,196/255,26/255,1) + } +}' + } + +} diff --git a/example/qml-Qt6/page/T_BreadcrumbBar.qml b/example/qml-Qt6/page/T_BreadcrumbBar.qml new file mode 100644 index 00000000..f6a1ba08 --- /dev/null +++ b/example/qml-Qt6/page/T_BreadcrumbBar.qml @@ -0,0 +1,94 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"BreadcurmbBar" + + Component.onCompleted: { + var items = [] + for(var i=0;i<10;i++){ + items.push({title:"Item_"+(i+1)}) + } + breadcrumb_1.items = items + breadcrumb_2.items = items + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + + FluBreadcrumbBar{ + id:breadcrumb_1 + width:parent.width + anchors.verticalCenter: parent.verticalCenter + onClickItem: + (model)=>{ + showSuccess(model.title) + } + } + } + + + FluArea{ + Layout.fillWidth: true + height: 100 + paddings: 10 + Layout.topMargin: 20 + + ColumnLayout{ + anchors.verticalCenter: parent.verticalCenter + width:parent.width + spacing: 10 + + FluFilledButton{ + text:"Reset sample" + onClicked:{ + var items = [] + for(var i=0;i<10;i++){ + items.push({title:"Item_"+(i+1)}) + } + breadcrumb_2.items = items + } + } + + FluBreadcrumbBar{ + id:breadcrumb_2 + separator:">" + spacing:8 + textSize:18 + Layout.fillWidth: true + onClickItem: + (model)=>{ + //不是点击最后一个item元素 + if(model.index+1!==count()){ + breadcrumb_2.remove(model.index+1,count()-model.index-1) + } + showSuccess(model.title) + } + } + } + } + + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluBreadcrumbBar{ + width:parent.width + separator:">" + spacing:8 + textSize:18 + onClickItem: (model)=>{ + + } +}' + } + + +} diff --git a/example/qml-Qt6/page/T_Buttons.qml b/example/qml-Qt6/page/T_Buttons.qml new file mode 100644 index 00000000..7707333f --- /dev/null +++ b/example/qml-Qt6/page/T_Buttons.qml @@ -0,0 +1,348 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Buttons" + + FluText{ + Layout.topMargin: 20 + text:"支持Tab键切换焦点,空格键执行点击事件" + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + + FluTextButton{ + disabled:text_button_switch.checked + text:"Text Button" + contentDescription: "文本按钮" + onClicked: { + showInfo("点击Text Button") + } + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + FluToggleSwitch{ + id:text_button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTextButton{ + text:"Text Button" + onClicked: { + + } +}' + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + + FluButton{ + disabled:button_switch.checked + text:"Standard Button" + onClicked: { + showInfo("点击StandardButton") + } + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + FluToggleSwitch{ + id:button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluButton{ + text:"Standard Button" + onClicked: { + + } +}' + } + + FluArea{ + Layout.fillWidth: true + height: 68 + Layout.topMargin: 20 + paddings: 10 + + FluFilledButton{ + disabled:filled_button_switch.checked + text:"Filled Button" + onClicked: { + showWarning("点击FilledButton"+height) + } + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + FluToggleSwitch{ + id:filled_button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluFilledButton{ + text:"Filled Button" + onClicked: { + + } +}' + } + + FluArea{ + Layout.fillWidth: true + height: 68 + Layout.topMargin: 20 + paddings: 10 + + FluToggleButton{ + disabled:toggle_button_switch.checked + text:"Toggle Button" + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + FluToggleSwitch{ + id:toggle_button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluToggleButton{ + text:"Toggle Button" + onClicked: { + checked = !checked + } +}' + } + + + FluArea{ + Layout.fillWidth: true + height: layout_icon_button.height + 30 + paddings: 10 + Layout.topMargin: 20 + Flow{ + id:layout_icon_button + spacing: 10 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + right: icon_button_switch.left + } + FluIconButton{ + disabled:icon_button_switch.checked + iconDelegate: Image{ sourceSize: Qt.size(40,40) ; width: 20; height: 20; source: "qrc:/example/res/image/ic_home_github.png" } + onClicked:{ + showSuccess("点击IconButton") + } + } + FluIconButton{ + iconSource:FluentIcons.ChromeCloseContrast + disabled:icon_button_switch.checked + iconSize: 15 + text:"IconOnly" + display: Button.IconOnly + onClicked:{ + showSuccess("Button.IconOnly") + } + } + FluIconButton{ + iconSource:FluentIcons.ChromeCloseContrast + disabled:icon_button_switch.checked + iconSize: 15 + text:"TextOnly" + display: Button.TextOnly + onClicked:{ + showSuccess("Button.TextOnly") + } + } + FluIconButton{ + iconSource:FluentIcons.ChromeCloseContrast + disabled:icon_button_switch.checked + iconSize: 15 + text:"TextBesideIcon" + display: Button.TextBesideIcon + onClicked:{ + showSuccess("Button.TextBesideIcon") + } + } + FluIconButton{ + iconSource:FluentIcons.ChromeCloseContrast + disabled:icon_button_switch.checked + iconSize: 15 + text:"TextUnderIcon" + display: Button.TextUnderIcon + onClicked:{ + showSuccess("Button.TextUnderIcon") + } + } + } + FluToggleSwitch{ + id:icon_button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluIconButton{ + iconSource:FluentIcons.ChromeCloseContrast + onClicked: { + + } +}' + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + FluDropDownButton{ + disabled:drop_down_button_switch.checked + text:"DropDownButton" + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluMenuItem{ + text:"Menu_1" + } + FluMenuItem{ + text:"Menu_2" + } + FluMenuItem{ + text:"Menu_3" + } + FluMenuItem{ + text:"Menu_4" + onClicked: { + + } + } + } + FluToggleSwitch{ + id:drop_down_button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluDropDownButton{ + text:"DropDownButton" + FluMenuItem{ + text:"Menu_1" + }, + FluMenuItem{ + text:"Menu_2" + }, + FluMenuItem{ + text:"Menu_3" + }, + FluMenuItem{ + text:"Menu_4" + } +}' + } + + FluArea{ + Layout.fillWidth: true + height: 100 + paddings: 10 + Layout.topMargin: 20 + FluRadioButtons{ + spacing: 8 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluRadioButton{ + disabled:radio_button_switch.checked + text:"Radio Button_1" + } + FluRadioButton{ + disabled:radio_button_switch.checked + text:"Radio Button_2" + } + FluRadioButton{ + disabled:radio_button_switch.checked + text:"Radio Button_3" + } + } + FluToggleSwitch{ + id:radio_button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluRadioButton{ + checked:true + text:"Text Button" + onClicked: { + + } +}' + } + +} diff --git a/example/qml-Qt6/page/T_CalendarPicker.qml b/example/qml-Qt6/page/T_CalendarPicker.qml new file mode 100644 index 00000000..4cb67901 --- /dev/null +++ b/example/qml-Qt6/page/T_CalendarPicker.qml @@ -0,0 +1,50 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"CalendarPicker" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 350 + paddings: 10 + FluCalendarView{ + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluCalendarView{ + +}' + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 80 + paddings: 10 + ColumnLayout{ + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluCalendarPicker{ + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluCalendarPicker{ + +}' + } + +} diff --git a/example/qml-Qt6/page/T_Captcha.qml b/example/qml-Qt6/page/T_Captcha.qml new file mode 100644 index 00000000..8ac59e75 --- /dev/null +++ b/example/qml-Qt6/page/T_Captcha.qml @@ -0,0 +1,54 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Captcha" + + + FluCaptcha{ + id:captcha + Layout.topMargin: 20 + MouseArea{ + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + captcha.refresh() + } + } + } + + FluButton{ + text:"Refresh" + Layout.topMargin: 20 + onClicked: { + captcha.refresh() + } + } + + RowLayout{ + spacing: 10 + Layout.topMargin: 10 + FluTextBox{ + id:text_box + placeholderText: "请输入验证码" + } + FluButton{ + text:"verify" + onClicked: { + var success = captcha.verify(text_box.text) + if(success){ + showSuccess("验证码正确") + }else{ + showError("错误验证,请重新输入") + } + } + } + } + + +} diff --git a/example/qml-Qt6/page/T_Carousel.qml b/example/qml-Qt6/page/T_Carousel.qml new file mode 100644 index 00000000..75cc647c --- /dev/null +++ b/example/qml-Qt6/page/T_Carousel.qml @@ -0,0 +1,132 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Carousel" + + ListModel{ + id:data_model + ListElement{ + url:"qrc:/example/res/image/banner_1.jpg" + } + ListElement{ + url:"qrc:/example/res/image/banner_2.jpg" + } + ListElement{ + url:"qrc:/example/res/image/banner_3.jpg" + } + } + + FluArea{ + Layout.fillWidth: true + height: 370 + paddings: 10 + Layout.topMargin: 20 + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left:parent.left + } + FluText{ + text:"轮播图,支持无限轮播,无限滑动,用ListView实现的组件" + } + FluCarousel{ + radius:[5,5,5,5] + delegate: Component{ + Image { + anchors.fill: parent + source: model.url + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + } + Layout.topMargin: 20 + Layout.leftMargin: 5 + Component.onCompleted: { + model = [{url:"qrc:/example/res/image/banner_1.jpg"},{url:"qrc:/example/res/image/banner_2.jpg"},{url:"qrc:/example/res/image/banner_3.jpg"}] + } + } + } + } + + FluArea{ + Layout.fillWidth: true + height: 340 + paddings: 10 + Layout.topMargin: 10 + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left:parent.left + } + FluCarousel{ + radius:[15,15,15,15] + loopTime:1500 + indicatorGravity: Qt.AlignHCenter | Qt.AlignTop + indicatorMarginTop:15 + delegate: Component{ + Item{ + anchors.fill: parent + Image { + anchors.fill: parent + source: model.url + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Rectangle{ + height: 40 + width: parent.width + anchors.bottom: parent.bottom + color: "#33000000" + FluText{ + anchors.fill: parent + verticalAlignment: Qt.AlignVCenter + horizontalAlignment: Qt.AlignHCenter + text:model.title + color: FluColors.Grey10 + font.pixelSize: 15 + } + } + } + } + Layout.topMargin: 20 + Layout.leftMargin: 5 + Component.onCompleted: { + var arr = [] + arr.push({url:"qrc:/example/res/image/banner_1.jpg",title:"共同应对全球性问题"}) + arr.push({url:"qrc:/example/res/image/banner_2.jpg",title:"三小只全程没互动"}) + arr.push({url:"qrc:/example/res/image/banner_3.jpg",title:"有效投资扩大 激发增长动能"}) + model = arr + } + } + } + } + + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluCarousel{ + id:carousel + width: 400 + height: 300 + delegate: Component{ + Image { + anchors.fill: parent + source: model.url + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + } + Component.onCompleted: { + carousel.model = [{url:"qrc:/example/res/image/banner_1.jpg"},{url:"qrc:/example/res/image/banner_2.jpg"},{url:"qrc:/example/res/image/banner_3.jpg"}] + } +}' + } +} diff --git a/example/qml-Qt6/page/T_Chart.qml b/example/qml-Qt6/page/T_Chart.qml new file mode 100644 index 00000000..7582b210 --- /dev/null +++ b/example/qml-Qt6/page/T_Chart.qml @@ -0,0 +1,331 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Chart" + + function randomScalingFactor() { + return Math.random().toFixed(1); + } + + FluArea{ + height: 370 + width: 500 + paddings: 10 + Layout.topMargin: 20 + FluChart{ + anchors.fill: parent + chartType: 'scatter' + chartData: { + return { + datasets: [{ + label: 'My First dataset', + xAxisID: 'x-axis-1', + yAxisID: 'y-axis-1', + borderColor: '#ff5555', + backgroundColor: 'rgba(255,192,192,0.3)', + data: [{ + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }] + }, { + label: 'My Second dataset', + xAxisID: 'x-axis-1', + yAxisID: 'y-axis-2', + borderColor: '#5555ff', + backgroundColor: 'rgba(192,192,255,0.3)', + data: [{ + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }, { + x: randomScalingFactor(), + y: randomScalingFactor(), + }] + }] + }} + chartOptions: {return { + maintainAspectRatio: false, + responsive: true, + hoverMode: 'nearest', + intersect: true, + title: { + display: true, + text: 'Chart.js Scatter Chart - Multi Axis' + }, + scales: { + xAxes: [{ + position: 'bottom', + gridLines: { + zeroLineColor: 'rgba(0,0,0,1)' + } + }], + yAxes: [{ + type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance + display: true, + position: 'left', + id: 'y-axis-1', + }, { + type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance + display: true, + position: 'right', + reverse: true, + id: 'y-axis-2', + + // grid line settings + gridLines: { + drawOnChartArea: false, // only want the grid lines for one axis to show up + }, + }], + } + } + } + } + } + + FluArea{ + width: 500 + height: 370 + paddings: 10 + Layout.topMargin: 20 + FluChart{ + anchors.fill: parent + chartType: 'bar' + chartData: { return { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + datasets: [{ + label: 'Dataset 1', + backgroundColor: '#ff9999', + stack: 'Stack 0', + data: [ + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor() + ] + }, { + label: 'Dataset 2', + backgroundColor: '#9999ff', + stack: 'Stack 0', + data: [ + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor() + ] + }, { + label: 'Dataset 3', + backgroundColor: '#99ff99', + stack: 'Stack 1', + data: [ + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor() + ] + }] + } + } + + chartOptions: { return { + maintainAspectRatio: false, + title: { + display: true, + text: 'Chart.js Bar Chart - Stacked' + }, + tooltips: { + mode: 'index', + intersect: false + }, + responsive: true, + scales: { + xAxes: [{ + stacked: true, + }], + yAxes: [{ + stacked: true + }] + } + } + } + } + } + + FluArea{ + width: 500 + height: 370 + paddings: 10 + Layout.topMargin: 20 + FluChart{ + anchors.fill: parent + chartType: 'pie' + chartData: {return { + datasets: [{ + data: [ + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + ], + backgroundColor: [ + '#ffbbbb', + '#ffddaa', + '#ffffbb', + '#bbffbb', + '#bbbbff' + ], + label: 'Dataset 1' + }], + labels: [ + 'Red', + 'Orange', + 'Yellow', + 'Green', + 'Blue' + ] + }} + chartOptions: {return {maintainAspectRatio: false, responsive: true}} + } + } + + FluArea{ + width: 500 + height: 370 + paddings: 10 + Layout.topMargin: 20 + FluChart{ + anchors.fill: parent + chartType: 'line' + chartData: { return { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + datasets: [{ + label: 'Filled', + fill: true, + backgroundColor: 'rgba(192,222,255,0.3)', + borderColor: 'rgba(128,192,255,255)', + data: [ + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor() + ], + }, { + label: 'Dashed', + fill: false, + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#009900', + borderDash: [5, 5], + data: [ + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor() + ], + }, { + label: 'Filled', + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#990000', + data: [ + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor(), + randomScalingFactor() + ], + fill: false, + }] + } + } + + chartOptions: {return { + maintainAspectRatio: false, + responsive: true, + title: { + display: true, + text: 'Chart.js Line Chart' + }, + tooltips: { + mode: 'index', + intersect: false, + }, + hover: { + mode: 'nearest', + intersect: true + }, + scales: { + xAxes: [{ + display: true, + scaleLabel: { + display: true, + labelString: 'Month' + } + }], + yAxes: [{ + display: true, + scaleLabel: { + display: true, + labelString: 'Value' + } + }] + } + } + } + } + } + +} diff --git a/example/qml-Qt6/page/T_CheckBox.qml b/example/qml-Qt6/page/T_CheckBox.qml new file mode 100644 index 00000000..e3c6ea4a --- /dev/null +++ b/example/qml-Qt6/page/T_CheckBox.qml @@ -0,0 +1,50 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"CheckBox" + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + Row{ + spacing: 30 + anchors.verticalCenter: parent.verticalCenter + FluCheckBox{ + disabled: check_box_switch.checked + } + FluCheckBox{ + disabled: check_box_switch.checked + text:"Right" + } + FluCheckBox{ + disabled: check_box_switch.checked + text:"Left" + textRight: false + } + } + FluToggleSwitch{ + id:check_box_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluCheckBox{ + text:"Text" +}' + } + +} diff --git a/example/qml-Qt6/page/T_ColorPicker.qml b/example/qml-Qt6/page/T_ColorPicker.qml new file mode 100644 index 00000000..24954589 --- /dev/null +++ b/example/qml-Qt6/page/T_ColorPicker.qml @@ -0,0 +1,69 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"ColorPicker" + + FluArea{ + Layout.fillWidth: true + height: 280 + Layout.topMargin: 20 + paddings: 10 + ColumnLayout{ + anchors{ + verticalCenter: parent.verticalCenter + left:parent.left + } + FluText{ + text:"此颜色组件是Github上的开源项目" + } + FluTextButton{ + text:"https://github.com/rshest/qml-colorpicker" + onClicked: { + Qt.openUrlExternally(text) + } + } + FluColorView{ + + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluColorView{ + +}' + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 60 + paddings: 10 + + RowLayout{ + FluText{ + text:"点击选择颜色->" + Layout.alignment: Qt.AlignVCenter + } + FluColorPicker{ + + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluColorPicker{ + +}' + } + +} + diff --git a/example/qml-Qt6/page/T_ComboBox.qml b/example/qml-Qt6/page/T_ComboBox.qml new file mode 100644 index 00000000..15fba70b --- /dev/null +++ b/example/qml-Qt6/page/T_ComboBox.qml @@ -0,0 +1,81 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"ComboBox" + + FluArea{ + Layout.fillWidth: true + height: 80 + paddings: 5 + Layout.topMargin: 20 + Column{ + spacing: 5 + anchors.verticalCenter: parent.verticalCenter + FluText{ + text: "editable=false" + x:10 + } + FluComboBox { + model: ListModel { + id: model_1 + ListElement { text: "Banana" } + ListElement { text: "Apple" } + ListElement { text: "Coconut" } + } + } + } + } + + FluArea{ + Layout.fillWidth: true + height: 80 + paddings: 10 + Layout.topMargin: 20 + Column{ + spacing: 5 + anchors.verticalCenter: parent.verticalCenter + FluText{ + text: "editable=true" + x:5 + } + FluComboBox { + editable: true + font:FluTextStyle.BodyStrong + model: ListModel { + id: model_2 + ListElement { text: "Banana" } + ListElement { text: "Apple" } + ListElement { text: "Coconut" } + } + onAccepted: { + if (find(editText) === -1) + model_2.append({text: editText}) + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluComboBox{ + editable: true + model: ListModel { + id: model + ListElement { text: "Banana" } + ListElement { text: "Apple" } + ListElement { text: "Coconut" } + } + onAccepted: { + if (find(editText) === -1) + model.append({text: editText}) + } +}' + } + +} diff --git a/example/qml-Qt6/page/T_DatePicker.qml b/example/qml-Qt6/page/T_DatePicker.qml new file mode 100644 index 00000000..0fe6c4df --- /dev/null +++ b/example/qml-Qt6/page/T_DatePicker.qml @@ -0,0 +1,70 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"TimePicker" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 80 + paddings: 10 + ColumnLayout{ + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"showYear=true" + } + FluDatePicker{ + onCurrentChanged: { + showSuccess(current.toLocaleDateString()) + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluDatePicker{ + +}' + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 80 + paddings: 10 + ColumnLayout{ + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"showYear=false" + } + + FluDatePicker{ + showYear:false + onCurrentChanged: { + showSuccess(current.toLocaleDateString()) + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluDatePicker{ + showYear:false +}' + } + +} diff --git a/example/qml-Qt6/page/T_Dialog.qml b/example/qml-Qt6/page/T_Dialog.qml new file mode 100644 index 00000000..b1e8b6b5 --- /dev/null +++ b/example/qml-Qt6/page/T_Dialog.qml @@ -0,0 +1,118 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Dialog" + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + FluButton{ + anchors.verticalCenter: parent.verticalCenter + Layout.topMargin: 20 + text:"Show Double Button Dialog" + onClicked: { + double_btn_dialog.open() + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluContentDialog{ + id:dialog + title:"友情提示" + message:"确定要退出程序么?" + negativeText:"取消" + buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton + onNegativeClicked:{ + showSuccess("点击取消按钮") + } + positiveText:"确定" + onPositiveClicked:{ + showSuccess("点击确定按钮") + } + } + dialog.open()' + } + + FluContentDialog{ + id:double_btn_dialog + title:"友情提示" + message:"确定要退出程序么?" + buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton + negativeText:"取消" + onNegativeClicked:{ + showSuccess("点击取消按钮") + } + positiveText:"确定" + onPositiveClicked:{ + showSuccess("点击确定按钮") + } + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + FluButton{ + anchors.verticalCenter: parent.verticalCenter + Layout.topMargin: 20 + text:"Show Triple Button Dialog" + onClicked: { + triple_btn_dialog.open() + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluContentDialog{ + id:dialog + title:"友情提示" + message:"确定要退出程序么?" + negativeText:"取消" + buttonFlags: FluContentDialogType.NeutralButton | FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton + negativeText:"取消" + onNegativeClicked:{ + showSuccess("点击取消按钮") + } + positiveText:"确定" + onPositiveClicked:{ + showSuccess("点击确定按钮") + } + neutralText:"最小化" + onNeutralClicked:{ + showSuccess("点击最小化按钮") + } + } + dialog.open()' + } + + FluContentDialog{ + id:triple_btn_dialog + title:"友情提示" + message:"确定要退出程序么?" + buttonFlags: FluContentDialogType.NeutralButton | FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton + negativeText:"取消" + onNegativeClicked:{ + showSuccess("点击取消按钮") + } + positiveText:"确定" + onPositiveClicked:{ + showSuccess("点击确定按钮") + } + neutralText:"最小化" + onNeutralClicked:{ + showSuccess("点击最小化按钮") + } + } +} diff --git a/example/qml-Qt6/page/T_Expander.qml b/example/qml-Qt6/page/T_Expander.qml new file mode 100644 index 00000000..36f390e3 --- /dev/null +++ b/example/qml-Qt6/page/T_Expander.qml @@ -0,0 +1,102 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Expander" + + FluArea{ + Layout.fillWidth: true + height: layout_column.height+20 + paddings: 10 + Layout.topMargin: 20 + Column{ + id:layout_column + spacing: 15 + anchors{ + top:parent.top + left:parent.left + } + + FluExpander{ + headerText:"打开一个单选框" + Layout.topMargin: 20 + Item{ + anchors.fill: parent + FluRadioButtons{ + spacing: 8 + anchors{ + top: parent.top + left: parent.left + topMargin: 15 + leftMargin: 15 + } + FluRadioButton{ + text:"Radio Button_1" + } + FluRadioButton{ + text:"Radio Button_2" + } + FluRadioButton{ + text:"Radio Button_3" + } + } + } + } + + FluExpander{ + Layout.topMargin: 20 + headerText:"打开一个滑动文本框" + Item{ + anchors.fill: parent + Flickable{ + id:scrollview + width: parent.width + height: parent.height + contentWidth: width + contentHeight: text_info.height + ScrollBar.vertical: FluScrollBar {} + FluText{ + id:text_info + width: scrollview.width + wrapMode: Text.WrapAnywhere + padding: 14 + text:"先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。宫中府中,俱为一体;陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐托付不效,以伤先帝之明;故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏。臣不胜受恩感激。今当远离,临表涕零,不知所言。" + } + } + } + } + } + } + + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluExpander{ + headerText:"打开一个单选框" + Item{ + anchors.fill: parent + Flickable{ + width: parent.width + height: parent.height + contentWidth: width + contentHeight: text_info.height + ScrollBar.vertical: FluScrollBar {} + FluText{ + id:text_info + width: scrollview.width + wrapMode: Text.WrapAnywhere + padding: 14 + text:"先帝创业未半而中道崩殂,今天下三分......"" + } + } + } +}' + } + + +} diff --git a/example/qml-Qt6/page/T_FlipView.qml b/example/qml-Qt6/page/T_FlipView.qml new file mode 100644 index 00000000..3baf06c1 --- /dev/null +++ b/example/qml-Qt6/page/T_FlipView.qml @@ -0,0 +1,117 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"FlipView" + + FluArea{ + Layout.fillWidth: true + height: 340 + paddings: 10 + Layout.topMargin: 20 + ColumnLayout{ + anchors.verticalCenter: parent.verticalCenter + FluText{ + text:"水平方向的FlipView" + } + FluFlipView{ + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_2.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_3.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluFlipView{ + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } +} +' + } + + FluArea{ + Layout.fillWidth: true + height: 340 + paddings: 10 + Layout.topMargin: 20 + ColumnLayout{ + anchors.verticalCenter: parent.verticalCenter + FluText{ + text:"垂直方向的FlipView" + } + FluFlipView{ + vertical:true + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_2.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_3.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluFlipView{ + vertical:true + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } + Image{ + source: "qrc:/example/res/image/banner_1.jpg" + asynchronous: true + fillMode:Image.PreserveAspectCrop + } +} +' + } +} diff --git a/example/qml-Qt6/page/T_Home.qml b/example/qml-Qt6/page/T_Home.qml new file mode 100644 index 00000000..c6acc672 --- /dev/null +++ b/example/qml-Qt6/page/T_Home.qml @@ -0,0 +1,284 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import "qrc:///example/qml/global" +import FluentUI + +FluScrollablePage{ + + launchMode: FluPageType.SingleTask + animDisabled: true + + ListModel{ + id:model_header + ListElement{ + icon:"qrc:/example/res/image/ic_home_github.png" + title:"FluentUI GitHub" + desc:"The latest FluentUI controls and styles for your applications." + url:"https://github.com/zhuzichu520/FluentUI" + } + } + + Item{ + Layout.fillWidth: true + Layout.preferredHeight: 320 + Image { + id: bg + fillMode:Image.PreserveAspectCrop + anchors.fill: parent + verticalAlignment: Qt.AlignTop + source: "qrc:/example/res/image/bg_home_header.png" + } + Rectangle{ + anchors.fill: parent + gradient: Gradient{ + GradientStop { position: 0.8; color: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(1,1,1,0) } + GradientStop { position: 1.0; color: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) } + } + } + FluText{ + text:"FluentUI Gallery" + font: FluTextStyle.TitleLarge + anchors{ + top: parent.top + left: parent.left + topMargin: 20 + leftMargin: 20 + } + } + + ListView{ + id: list + anchors{ + left: parent.left + right: parent.right + bottom: parent.bottom + } + orientation: ListView.Horizontal + height: 240 + model: model_header + header: Item{height: 10;width: 10} + footer: Item{height: 10;width: 10} + ScrollBar.horizontal: FluScrollBar{ + id: scrollbar_header + } + clip: false + delegate:Item{ + id: control + width: 220 + height: 240 + FluShadow{ + radius:8 + anchors.fill: item_content + } + FluItem{ + id:item_content + radius: [8,8,8,8] + width: 200 + height: 220 + anchors.centerIn: parent + FluAcrylic{ + anchors.fill: parent + tintColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) + target: bg + tintOpacity: FluTheme.dark ? 0.8 : 0.9 + blurRadius : 40 + targetRect: Qt.rect(list.x-list.contentX+10+(control.width)*index,list.y+10,width,height) + } + Rectangle{ + anchors.fill: parent + radius: 8 + color:{ + if(FluTheme.dark){ + if(item_mouse.containsMouse){ + return Qt.rgba(1,1,1,0.03) + } + return Qt.rgba(0,0,0,0.0) + }else{ + if(item_mouse.containsMouse){ + return Qt.rgba(0,0,0,0.03) + } + return Qt.rgba(0,0,0,0.0) + } + } + } + ColumnLayout{ + Image { + Layout.topMargin: 20 + Layout.leftMargin: 20 + Layout.preferredWidth: 50 + Layout.preferredHeight: 50 + source: model.icon + } + FluText{ + text: model.title + font: FluTextStyle.Body + Layout.topMargin: 20 + Layout.leftMargin: 20 + } + FluText{ + text: model.desc + Layout.topMargin: 5 + Layout.preferredWidth: 160 + Layout.leftMargin: 20 + color: FluColors.Grey120 + font.pixelSize: 12 + wrapMode: Text.WrapAnywhere + } + } + FluIcon{ + iconSource: FluentIcons.OpenInNewWindow + iconSize: 15 + anchors{ + bottom: parent.bottom + right: parent.right + rightMargin: 10 + bottomMargin: 10 + } + } + MouseArea{ + id:item_mouse + anchors.fill: parent + hoverEnabled: true + onWheel: + (wheel)=>{ + if (wheel.angleDelta.y > 0) scrollbar_header.decrease() + else scrollbar_header.increase() + } + onClicked: { + Qt.openUrlExternally(model.url) + } + } + } + } + } + } + + Component{ + id:com_item + Item{ + width: 320 + height: 120 + FluArea{ + radius: 8 + width: 300 + height: 100 + anchors.centerIn: parent + Rectangle{ + anchors.fill: parent + radius: 8 + color:{ + if(FluTheme.dark){ + if(item_mouse.containsMouse){ + return Qt.rgba(1,1,1,0.03) + } + return Qt.rgba(0,0,0,0) + }else{ + if(item_mouse.containsMouse){ + return Qt.rgba(0,0,0,0.03) + } + return Qt.rgba(0,0,0,0) + } + } + } + Image{ + id:item_icon + height: 40 + width: 40 + source: modelData.image + anchors{ + left: parent.left + leftMargin: 20 + verticalCenter: parent.verticalCenter + } + } + + FluText{ + id:item_title + text:modelData.title + font: FluTextStyle.BodyStrong + anchors{ + left: item_icon.right + leftMargin: 20 + top: item_icon.top + } + } + + FluText{ + id:item_desc + text:modelData.desc + color:FluColors.Grey120 + wrapMode: Text.WrapAnywhere + elide: Text.ElideRight + font: FluTextStyle.Caption + maximumLineCount: 2 + anchors{ + left: item_title.left + right: parent.right + rightMargin: 20 + top: item_title.bottom + topMargin: 5 + } + } + + Rectangle{ + height: 12 + width: 12 + radius: 6 + color: FluTheme.primaryColor.dark + anchors{ + right: parent.right + top: parent.top + rightMargin: 14 + topMargin: 14 + } + } + + MouseArea{ + id:item_mouse + anchors.fill: parent + hoverEnabled: true + onClicked: { + ItemsOriginal.startPageByItem(modelData) + } + } + } + } + } + + FluText{ + text: "Recently added samples" + font: FluTextStyle.Title + Layout.topMargin: 20 + Layout.leftMargin: 20 + } + + GridView{ + Layout.fillWidth: true + Layout.preferredHeight: contentHeight + cellHeight: 120 + cellWidth: 320 + model:ItemsOriginal.getRecentlyAddedData() + interactive: false + delegate: com_item + } + + FluText{ + text: "Recently updated samples" + font: FluTextStyle.Title + Layout.topMargin: 20 + Layout.leftMargin: 20 + } + + GridView{ + Layout.fillWidth: true + Layout.preferredHeight: contentHeight + cellHeight: 120 + cellWidth: 320 + interactive: false + model: ItemsOriginal.getRecentlyUpdatedData() + delegate: com_item + } + +} diff --git a/example/qml-Qt6/page/T_Http.qml b/example/qml-Qt6/page/T_Http.qml new file mode 100644 index 00000000..58942ade --- /dev/null +++ b/example/qml-Qt6/page/T_Http.qml @@ -0,0 +1,279 @@ +import QtQuick +import Qt.labs.platform +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Dialogs +import FluentUI +import "qrc:///example/qml/component" + +FluContentPage{ + + title:"Http" + + FluHttp{ + id:http + } + + Flickable{ + id:layout_flick + width: 160 + clip: true + anchors{ + top: parent.top + topMargin: 20 + bottom: parent.bottom + left: parent.left + } + ScrollBar.vertical: FluScrollBar {} + contentHeight:layout_column.height + Column{ + spacing: 2 + id:layout_column + width: parent.width + FluButton{ + implicitWidth: parent.width + implicitHeight: 36 + text: "Get请求" + onClicked: { + var callable = {} + callable.onStart = function(){ + showLoading() + } + callable.onFinish = function(){ + hideLoading() + } + callable.onSuccess = function(result){ + text_info.text = result + console.debug(result) + } + callable.onError = function(status,errorString){ + console.debug(status+";"+errorString) + } + http.get("https://httpbingo.org/get",callable) + } + } + FluButton{ + implicitWidth: parent.width + implicitHeight: 36 + text: "Post表单请求" + onClicked: { + var callable = {} + callable.onStart = function(){ + showLoading() + } + callable.onFinish = function(){ + hideLoading() + } + callable.onSuccess = function(result){ + text_info.text = result + console.debug(result) + } + callable.onError = function(status,errorString){ + console.debug(status+";"+errorString) + } + var param = {} + param.custname = "朱子楚" + param.custtel = "1234567890" + param.custemail = "zhuzichu520@gmail.com" + http.post("https://httpbingo.org/post",callable,param) + } + } + FluButton{ + implicitWidth: parent.width + implicitHeight: 36 + text: "Post Json请求" + onClicked: { + var callable = {} + callable.onStart = function(){ + showLoading() + } + callable.onFinish = function(){ + hideLoading() + } + callable.onSuccess = function(result){ + text_info.text = result + console.debug(result) + } + callable.onError = function(status,errorString){ + console.debug(status+";"+errorString) + } + var param = {} + param.custname = "朱子楚" + param.custtel = "1234567890" + param.custemail = "zhuzichu520@gmail.com" + http.postJson("https://httpbingo.org/post",callable,param) + } + } + FluButton{ + implicitWidth: parent.width + implicitHeight: 36 + text: "Post String请求" + onClicked: { + var callable = {} + callable.onStart = function(){ + showLoading() + } + callable.onFinish = function(){ + hideLoading() + } + callable.onSuccess = function(result){ + text_info.text = result + console.debug(result) + } + callable.onError = function(status,errorString){ + console.debug(status+";"+errorString) + } + var param = "我命由我不由天" + http.postString("https://httpbingo.org/post",callable,param) + } + } + FluButton{ + id:btn_download + implicitWidth: parent.width + implicitHeight: 36 + text: "下载文件" + onClicked: { + folder_dialog.open() + } + } + FluButton{ + id:btn_upload + implicitWidth: parent.width + implicitHeight: 36 + text: "文件上传" + onClicked: { + file_dialog.open() + } + } + } + } + + FileDialog { + id: file_dialog + onAccepted: { + var param = {} + for(var i=0;iStandard模式窗口,每次都会创建新窗口" + } + FluButton{ + text:"点击创建窗口" + onClicked: { + FluApp.navigate("/standardWindow") + } + } + } + } + + FluArea{ + Layout.fillWidth: true + height: 86 + paddings: 10 + Layout.topMargin: 10 + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"SingleTask模式窗口,如果窗口存在,这激活该窗口" + textFormat: Text.RichText + } + FluButton{ + text:"点击创建窗口" + onClicked: { + FluApp.navigate("/singleTaskWindow") + } + } + } + } + + FluArea{ + Layout.fillWidth: true + height: 86 + paddings: 10 + Layout.topMargin: 10 + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"SingleInstance模式窗口,如果窗口存在,则销毁窗口,然后新建窗口" + } + FluButton{ + text:"点击创建窗口" + onClicked: { + FluApp.navigate("/singleInstanceWindow") + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluWindow{ + //launchMode: FluWindowType.Standard + //launchMode: FluWindowType.SingleTask + launchMode: FluWindowType.SingleInstance +} +' + } + + + FluArea{ + Layout.fillWidth: true + height: 100 + paddings: 10 + Layout.topMargin: 20 + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"页面跳转,不携带任何参数" + } + FluButton{ + text:"点击跳转" + onClicked: { + FluApp.navigate("/about") + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluButton{ + text:"点击跳转" + onClicked: { + FluApp.navigate("/about") + } +} +' + } + + FluArea{ + Layout.fillWidth: true + height: 130 + paddings: 10 + Layout.topMargin: 20 + + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"页面跳转,并携带参数用户名:zhuzichu" + } + FluButton{ + text:"点击跳转到登录" + onClicked: { + loginPageRegister.launch({username:"zhuzichu"}) + } + } + FluText{ + text:"登录窗口返回过来的密码->"+password + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'property var loginPageRegister: registerForWindowResult("/login") + +Connections{ + target: loginPageRegister + function onResult(data) + { + password = data.password + } +} + +FluButton{ + text:"点击跳转" + onClicked: { + loginPageRegister.launch({username:"zhuzichu"}) + } +} +' + } + +} diff --git a/example/qml-Qt6/page/T_Pagination.qml b/example/qml-Qt6/page/T_Pagination.qml new file mode 100644 index 00000000..fa072dc6 --- /dev/null +++ b/example/qml-Qt6/page/T_Pagination.qml @@ -0,0 +1,49 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import "qrc:///example/qml/component" +import FluentUI + +FluScrollablePage{ + + title:"Pagination" + + FluArea{ + Layout.fillWidth: true + height: 200 + paddings: 10 + Layout.topMargin: 20 + ColumnLayout{ + spacing: 20 + anchors.verticalCenter: parent.verticalCenter + FluPagination{ + pageCurrent: 1 + pageButtonCount: 5 + itemCount: 5000 + } + FluPagination{ + pageCurrent: 2 + itemCount: 5000 + pageButtonCount: 7 + } + FluPagination{ + pageCurrent: 3 + itemCount: 5000 + pageButtonCount: 9 + } + } + + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluPagination{ + pageCurrent: 1 + itemCount: 1000 + pageButtonCount: 9 +}' + } + + +} diff --git a/example/qml-Qt6/page/T_Pivot.qml b/example/qml-Qt6/page/T_Pivot.qml new file mode 100644 index 00000000..0fe52dfd --- /dev/null +++ b/example/qml-Qt6/page/T_Pivot.qml @@ -0,0 +1,79 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Pivot" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 400 + paddings: 10 + + FluPivot{ + anchors.fill: parent + currentIndex: 2 + FluPivotItem{ + title:"All" + contentItem:FluText{ + text:"All emails go here." + } + } + FluPivotItem{ + title:"Unread" + contentItem:FluText{ + text:"Unread emails go here." + } + } + FluPivotItem{ + title:"Flagged" + contentItem:FluText{ + text:"Flagged emails go here." + } + } + FluPivotItem{ + title:"Urgent" + contentItem:FluText{ + text:"Urgent emails go here." + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluPivot{ + anchors.fill: parent + FluPivotItem:{ + text:"All" + contentItem: FluText{ + text:"All emails go here." + } + } + FluPivotItem:{ + text:"Unread" + contentItem: FluText{ + text:"Unread emails go here." + } + } + FluPivotItem:{ + text:"Flagged" + contentItem: FluText{ + text:"Flagged emails go here." + } + } + FluPivotItem:{ + text:"Urgent" + contentItem: FluText{ + text:"Urgent emails go here." + } + } +} +' + } +} diff --git a/example/qml-Qt6/page/T_Progress.qml b/example/qml-Qt6/page/T_Progress.qml new file mode 100644 index 00000000..cb4740b5 --- /dev/null +++ b/example/qml-Qt6/page/T_Progress.qml @@ -0,0 +1,103 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Progress" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 130 + paddings: 10 + + ColumnLayout{ + spacing: 10 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text: "indeterminate = true" + } + FluProgressBar{ + } + FluProgressRing{ + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluProgressBar{ + +} +FluProgressRing{ + +} +' + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 286 + paddings: 10 + + ColumnLayout{ + spacing: 10 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text: "indeterminate = false" + } + FluProgressBar{ + indeterminate: false + value:slider.value/100 + Layout.topMargin: 10 + } + FluProgressBar{ + indeterminate: false + value:slider.value/100 + progressVisible: true + Layout.topMargin: 10 + } + FluProgressRing{ + indeterminate: false + value: slider.value/100 + Layout.topMargin: 10 + } + FluProgressRing{ + progressVisible: true + indeterminate: false + value: slider.value/100 + } + FluSlider{ + id:slider + Component.onCompleted: { + value = 50 + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluProgressBar{ + indeterminate: false +} +FluProgressRing{ + indeterminate: false + progressVisible: true +} +' + } + + +} diff --git a/example/qml-Qt6/page/T_QRCode.qml b/example/qml-Qt6/page/T_QRCode.qml new file mode 100644 index 00000000..24f60f20 --- /dev/null +++ b/example/qml-Qt6/page/T_QRCode.qml @@ -0,0 +1,106 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import Qt5Compat.GraphicalEffects +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"QRCode" + + FluQRCode{ + id:qrcode + Layout.topMargin: 20 + size:slider_size.value + text:text_box.text + color:color_picker.colorValue + bgColor: bgcolor_picker.colorValue + margins:slider_margins.value + Layout.preferredWidth: size + Layout.preferredHeight: size + } + + RowLayout{ + spacing: 10 + Layout.topMargin: 20 + FluText{ + text:"text:" + Layout.alignment: Qt.AlignVCenter + } + FluTextBox{ + id:text_box + text:"会磨刀的小猪" + } + } + + RowLayout{ + spacing: 10 + Layout.topMargin: 10 + FluText{ + text:"color:" + Layout.alignment: Qt.AlignVCenter + } + FluColorPicker{ + id:color_picker + Component.onCompleted: { + setColor(Qt.rgba(0,0,0,1)) + } + } + } + + RowLayout{ + spacing: 10 + Layout.topMargin: 10 + FluText{ + text:"bgColor:" + Layout.alignment: Qt.AlignVCenter + } + FluColorPicker{ + id:bgcolor_picker + Component.onCompleted: { + setColor(Qt.rgba(1,1,1,1)) + } + } + } + + RowLayout{ + spacing: 10 + FluText{ + text:"margins:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_margins + from:0 + to:80 + value: 0 + } + } + + RowLayout{ + spacing: 10 + FluText{ + text:"size:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_size + from:120 + to:260 + value: 120 + } + } + + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: 20 + code:'FluQRCode{ + color:"red" + text:"会磨刀的小猪" + size:100 +}' + } + +} diff --git a/example/qml-Qt6/page/T_RadioButton.qml b/example/qml-Qt6/page/T_RadioButton.qml new file mode 100644 index 00000000..07b383b7 --- /dev/null +++ b/example/qml-Qt6/page/T_RadioButton.qml @@ -0,0 +1,101 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"RadioButton" + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + Row{ + spacing: 30 + anchors.verticalCenter: parent.verticalCenter + FluRadioButton{ + disabled: radio_button_switch.checked + } + FluRadioButton{ + disabled: radio_button_switch.checked + text:"Right" + } + FluRadioButton{ + disabled: radio_button_switch.checked + text:"Left" + textRight: false + } + } + FluToggleSwitch{ + id:radio_button_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluRadioButton{ + text:"Text" +}' + } + + FluArea{ + Layout.fillWidth: true + height: 100 + paddings: 10 + Layout.topMargin: 20 + FluRadioButtons{ + spacing: 8 + anchors.verticalCenter: parent.verticalCenter + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluRadioButton{ + disabled: radio_button_switch2.checked + text:"Radio Button_1" + } + FluRadioButton{ + disabled: radio_button_switch2.checked + text:"Radio Button_2" + } + FluRadioButton{ + disabled: radio_button_switch2.checked + text:"Radio Button_3" + } + } + FluToggleSwitch{ + id:radio_button_switch2 + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluRadioButtons{ + spacing: 8 + FluRadioButton{ + text:"Radio Button_1" + } + FluRadioButton{ + text:"Radio Button_2" + } + FluRadioButton{ + text:"Radio Button_3" + } +}' + } + +} diff --git a/example/qml-Qt6/page/T_RatingControl.qml b/example/qml-Qt6/page/T_RatingControl.qml new file mode 100644 index 00000000..4c39d380 --- /dev/null +++ b/example/qml-Qt6/page/T_RatingControl.qml @@ -0,0 +1,35 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage { + + title: "RatingControl" + + FluArea { + Layout.fillWidth: true + height: 100 + paddings: 10 + Layout.topMargin: 20 + + Column { + spacing: 10 + anchors.verticalCenter: parent.verticalCenter + FluRatingControl {} + FluRatingControl { + number: 10 + } + } + } + + CodeExpander { + Layout.fillWidth: true + Layout.topMargin: -1 + code: 'FluRatingControl{ + +}' + } +} diff --git a/example/qml-Qt6/page/T_Rectangle.qml b/example/qml-Qt6/page/T_Rectangle.qml new file mode 100644 index 00000000..9cfe42aa --- /dev/null +++ b/example/qml-Qt6/page/T_Rectangle.qml @@ -0,0 +1,147 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Rectangle" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 460 + paddings: 10 + + Column{ + spacing: 15 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + + RowLayout{ + Layout.topMargin: 20 + FluRectangle{ + width: 50 + height: 50 + color:"#0078d4" + radius:[0,0,0,0] + } + FluRectangle{ + width: 50 + height: 50 + color:"#744da9" + radius:[15,15,15,15] + } + FluRectangle{ + width: 50 + height: 50 + color:"#ffeb3b" + radius:[15,0,0,0] + } + FluRectangle{ + width: 50 + height: 50 + color:"#f7630c" + radius:[0,15,0,0] + } + FluRectangle{ + width: 50 + height: 50 + color:"#e71123" + radius:[0,0,15,0] + } + FluRectangle{ + width: 50 + height: 50 + color:"#b4009e" + radius:[0,0,0,15] + } + } + FluText{ + text:"配合图片使用" + font: FluTextStyle.Subtitle + Layout.topMargin: 20 + } + RowLayout{ + spacing: 14 + FluRectangle{ + width: 50 + height: 50 + radius:[25,0,25,25] + Image { + asynchronous: true + anchors.fill: parent + source: "qrc:/example/res/svg/avatar_1.svg" + sourceSize: Qt.size(width,height) + } + } + FluRectangle{ + width: 50 + height: 50 + radius:[10,10,10,10] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_2.svg" + } + } + FluRectangle{ + width: 50 + height: 50 + radius:[25,25,25,25] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_3.svg" + } + } + FluRectangle{ + width: 50 + height: 50 + radius:[0,25,25,25] + Image { + asynchronous: true + anchors.fill: parent + sourceSize: Qt.size(width,height) + source: "qrc:/example/res/svg/avatar_4.svg" + } + } + } + FluRectangle{ + width: 1920/5 + height: 1200/5 + radius:[15,15,15,15] + Image { + asynchronous: true + source: "qrc:/example/res/image/banner_1.jpg" + anchors.fill: parent + sourceSize: Qt.size(2*width,2*height) + } + Layout.topMargin: 20 + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluRectangle{ + radius: [25,25,25,25] + width: 50 + height: 50 + Image{ + asynchronous: true + anchors.fill: parent + source: "qrc:/example/res/svg/avatar_4.svg" + sourceSize: Qt.size(width,height) + } +}' + } + + +} diff --git a/example/qml-Qt6/page/T_RemoteLoader.qml b/example/qml-Qt6/page/T_RemoteLoader.qml new file mode 100644 index 00000000..03dd73cf --- /dev/null +++ b/example/qml-Qt6/page/T_RemoteLoader.qml @@ -0,0 +1,14 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluPage{ + launchMode: FluPageType.SingleTop + FluRemoteLoader{ + anchors.fill: parent + source: "https://zhu-zichu.gitee.io/T_RemoteLoader.qml" + } +} diff --git a/example/qml-Qt6/page/T_Screenshot.qml b/example/qml-Qt6/page/T_Screenshot.qml new file mode 100644 index 00000000..1a5cf38f --- /dev/null +++ b/example/qml-Qt6/page/T_Screenshot.qml @@ -0,0 +1,55 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Screenshot" + + FluArea{ + Layout.fillWidth: true + height: 100 + paddings: 10 + Layout.topMargin: 20 + + FluFilledButton{ + anchors.verticalCenter: parent.verticalCenter + text:"Open Screenshot" + onClicked: { + screenshot.open() + } + } + } + + Rectangle{ + Layout.preferredHeight: 400 + Layout.preferredWidth: 400 + Layout.topMargin: 10 + Layout.leftMargin: 4 + Layout.bottomMargin: 4 + color: FluTheme.dark ? FluColors.Black : FluColors.White + FluShadow{ + radius: 0 + color: FluTheme.primaryColor.dark + } + Image{ + id:image + anchors.fill: parent + fillMode: Image.PreserveAspectFit + asynchronous: true + } + } + + FluScreenshot{ + id:screenshot + captrueMode: FluScreenshotType.File + saveFolder: FluTools.getApplicationDirPath()+"/screenshot" + onCaptrueCompleted: + (captrue)=>{ + image.source = captrue + } + } +} diff --git a/example/qml-Qt6/page/T_Settings.qml b/example/qml-Qt6/page/T_Settings.qml new file mode 100644 index 00000000..8c2fcefd --- /dev/null +++ b/example/qml-Qt6/page/T_Settings.qml @@ -0,0 +1,108 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/global" +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Settings" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 128 + paddings: 10 + + ColumnLayout{ + spacing: 5 + anchors{ + top: parent.top + left: parent.left + } + FluText{ + text:lang.dark_mode + font: FluTextStyle.BodyStrong + Layout.bottomMargin: 4 + } + Repeater{ + model: [{title:"System",mode:FluThemeType.System},{title:"Light",mode:FluThemeType.Light},{title:"Dark",mode:FluThemeType.Dark}] + delegate: FluRadioButton{ + checked : FluTheme.darkMode === modelData.mode + text:modelData.title + clickListener:function(){ + FluTheme.darkMode = modelData.mode + } + } + } + } + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 160 + paddings: 10 + + ColumnLayout{ + spacing: 5 + anchors{ + top: parent.top + left: parent.left + } + FluText{ + text:lang.navigation_view_display_mode + font: FluTextStyle.BodyStrong + Layout.bottomMargin: 4 + } + Repeater{ + model: [{title:"Open",mode:FluNavigationViewType.Open},{title:"Compact",mode:FluNavigationViewType.Compact},{title:"Minimal",mode:FluNavigationViewType.Minimal},{title:"Auto",mode:FluNavigationViewType.Auto}] + delegate: FluRadioButton{ + checked : MainEvent.displayMode===modelData.mode + text:modelData.title + clickListener:function(){ + MainEvent.displayMode = modelData.mode + } + } + } + } + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 80 + paddings: 10 + + ColumnLayout{ + spacing: 10 + anchors{ + top: parent.top + left: parent.left + } + + FluText{ + text:lang.locale + font: FluTextStyle.BodyStrong + Layout.bottomMargin: 4 + } + + Flow{ + spacing: 5 + Repeater{ + model: ["Zh","En"] + delegate: FluRadioButton{ + checked: appInfo.lang.objectName === modelData + text:modelData + clickListener:function(){ + appInfo.changeLang(modelData) + } + } + } + } + } + } + +} diff --git a/example/qml-Qt6/page/T_Slider.qml b/example/qml-Qt6/page/T_Slider.qml new file mode 100644 index 00000000..517904a6 --- /dev/null +++ b/example/qml-Qt6/page/T_Slider.qml @@ -0,0 +1,50 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import "qrc:///example/qml/component" +import FluentUI + +FluScrollablePage{ + + title:"Slider" + + FluArea{ + Layout.fillWidth: true + height: 100 + paddings: 10 + Layout.topMargin: 20 + FluSlider{ + anchors.verticalCenter: parent.verticalCenter + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluSlider{ + value:50 +}' + } + + FluArea{ + Layout.fillWidth: true + height: 200 + paddings: 10 + Layout.topMargin: 20 + FluSlider{ + orientation: Qt.Vertical + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluSlider{ + orientation: Qt.Vertical + value:50 +}' + } + + +} diff --git a/example/qml-Qt6/page/T_StatusView.qml b/example/qml-Qt6/page/T_StatusView.qml new file mode 100644 index 00000000..3a94578d --- /dev/null +++ b/example/qml-Qt6/page/T_StatusView.qml @@ -0,0 +1,86 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"StatusView" + + FluArea{ + id:layout_actions + Layout.fillWidth: true + Layout.topMargin: 20 + height: 50 + paddings: 10 + RowLayout{ + spacing: 14 + FluDropDownButton{ + id:btn_status_mode + Layout.preferredWidth: 140 + text:"Loading" + FluMenuItem{ + text:"Loading" + onClicked: { + btn_status_mode.text = text + status_view.statusMode = FluStatusViewType.Loading + } + } + FluMenuItem{ + text:"Empty" + onClicked: { + btn_status_mode.text = text + status_view.statusMode = FluStatusViewType.Empty + } + } + FluMenuItem{ + text:"Error" + onClicked: { + btn_status_mode.text = text + status_view.statusMode = FluStatusViewType.Error + } + } + FluMenuItem{ + text:"Success" + onClicked: { + btn_status_mode.text = text + status_view.statusMode = FluStatusViewType.Success + } + } + } + } + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 10 + height: 380 + paddings: 10 + FluStatusView{ + id:status_view + anchors.fill: parent + onErrorClicked:{ + showError("点击重新加载") + } + Rectangle { + anchors.fill: parent + color:FluTheme.primaryColor.dark + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluStatusView{ + anchors.fill: parent + statusMode: FluStatusViewType.Loading + Rectangle{ + anchors.fill: parent + color:FluTheme.primaryColor.dark + } +}' + } + +} diff --git a/example/qml-Qt6/page/T_TabView.qml b/example/qml-Qt6/page/T_TabView.qml new file mode 100644 index 00000000..e50f4de1 --- /dev/null +++ b/example/qml-Qt6/page/T_TabView.qml @@ -0,0 +1,130 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + property var colors : [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green] + + title:"TabView" + + Component{ + id:com_page + Rectangle{ + anchors.fill: parent + color: argument + } + } + + function newTab(){ + tab_view.appendTab("qrc:/example/res/image/favicon.ico","Document "+tab_view.count(),com_page,colors[Math.floor(Math.random() * 8)].dark) + } + + Component.onCompleted: { + newTab() + newTab() + newTab() + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 50 + paddings: 10 + RowLayout{ + spacing: 14 + FluDropDownButton{ + id:btn_tab_width_behavior + Layout.preferredWidth: 140 + text:"Equal" + FluMenuItem{ + text:"Equal" + onClicked: { + btn_tab_width_behavior.text = text + tab_view.tabWidthBehavior = FluTabViewType.Equal + } + } + FluMenuItem{ + text:"SizeToContent" + onClicked: { + btn_tab_width_behavior.text = text + tab_view.tabWidthBehavior = FluTabViewType.SizeToContent + } + } + FluMenuItem{ + text:"Compact" + onClicked: { + btn_tab_width_behavior.text = text + tab_view.tabWidthBehavior = FluTabViewType.Compact + } + } + } + FluDropDownButton{ + id:btn_close_button_visibility + text:"Always" + Layout.preferredWidth: 120 + FluMenuItem{ + text:"Nerver" + onClicked: { + btn_close_button_visibility.text = text + tab_view.closeButtonVisibility = FluTabViewType.Nerver + } + } + FluMenuItem{ + text:"Always" + onClicked: { + btn_close_button_visibility.text = text + tab_view.closeButtonVisibility = FluTabViewType.Always + } + } + FluMenuItem{ + text:"OnHover" + onClicked: { + btn_close_button_visibility.text = text + tab_view.closeButtonVisibility = FluTabViewType.OnHover + } + } + } + } + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 15 + height: 400 + paddings: 10 + FluTabView{ + id:tab_view + onNewPressed:{ + newTab() + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTabView{ + anchors.fill: parent + Component.onCompleted: { + newTab() + newTab() + newTab() + } + Component{ + id:com_page + Rectangle{ + anchors.fill: parent + color: argument + } + } + function newTab(){ + tab_view.appendTab("qrc:/example/res/image/favicon.ico","Document 1",com_page,argument) + } +} +' + } + +} diff --git a/example/qml-Qt6/page/T_TableView.qml b/example/qml-Qt6/page/T_TableView.qml new file mode 100644 index 00000000..ffd6f174 --- /dev/null +++ b/example/qml-Qt6/page/T_TableView.qml @@ -0,0 +1,171 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluContentPage{ + + title:"TableView" + + Component.onCompleted: { + loadData(1,1000) + } + + Component{ + id:com_action + Item{ + RowLayout{ + anchors.centerIn: parent + FluButton{ + text:"删除" + onClicked: { + table_view.closeEditor() + tableModel.removeRow(row) + } + } + FluFilledButton{ + text:"编辑" + onClicked: { + showSuccess(JSON.stringify(tableModel.getRow(row))) + } + } + } + } + } + + function loadData(page,count){ + var numbers = [100, 300, 500, 1000]; + function getRandomAge() { + var randomIndex = Math.floor(Math.random() * numbers.length); + return numbers[randomIndex]; + } + var names = ["孙悟空", "猪八戒", "沙和尚", "唐僧","白骨夫人","金角大王","熊山君","黄风怪","银角大王"]; + function getRandomName(){ + var randomIndex = Math.floor(Math.random() * names.length); + return names[randomIndex]; + } + var nicknames = ["复海大圣","混天大圣","移山大圣","通风大圣","驱神大圣","齐天大圣","平天大圣"] + function getRandomNickname(){ + var randomIndex = Math.floor(Math.random() * nicknames.length); + return nicknames[randomIndex]; + } + var addresses = ["傲来国界花果山水帘洞","傲来国界坎源山脏水洞","大唐国界黑风山黑风洞","大唐国界黄风岭黄风洞","大唐国界骷髅山白骨洞","宝象国界碗子山波月洞","宝象国界平顶山莲花洞","宝象国界压龙山压龙洞","乌鸡国界号山枯松涧火云洞","乌鸡国界衡阳峪黑水河河神府"] + function getRandomAddresses(){ + var randomIndex = Math.floor(Math.random() * addresses.length); + return addresses[randomIndex]; + } + const dataSource = [] + for(var i=0;i element === Number(display)) + selectAll() + } + onCommit: { + display = editText + tableView.closeEditor() + } + } + } + + FluTableView{ + id:table_view + anchors{ + left: parent.left + right: parent.right + top: parent.top + bottom: gagination.top + } + anchors.topMargin: 20 + columnSource:[ + { + title: '姓名', + dataIndex: 'name', + readOnly:true, + }, + { + title: '年龄', + dataIndex: 'age', + editDelegate:com_combobox, + width:100, + minimumWidth:100, + maximumWidth:100 + }, + { + title: '住址', + dataIndex: 'address', + width:200, + minimumWidth:100, + maximumWidth:250 + }, + { + title: '别名', + dataIndex: 'nickname', + width:100, + minimumWidth:80, + maximumWidth:200 + }, + { + title: '长字符串', + dataIndex: 'longstring', + width:200, + minimumWidth:100, + maximumWidth:300 + }, + { + title: '操作', + dataIndex: 'action', + width:160, + minimumWidth:160, + maximumWidth:160 + } + ] + } + + FluPagination{ + id:gagination + anchors{ + bottom: parent.bottom + left: parent.left + } + pageCurrent: 1 + itemCount: 100000 + pageButtonCount: 7 + __itemPerPage: 1000 + onRequestPage: + (page,count)=> { + table_view.closeEditor() + loadData(page,count) + table_view.resetPosition() + } + } + + + +} diff --git a/example/qml-Qt6/page/T_Text.qml b/example/qml-Qt6/page/T_Text.qml new file mode 100644 index 00000000..c5624f62 --- /dev/null +++ b/example/qml-Qt6/page/T_Text.qml @@ -0,0 +1,32 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Text" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 60 + paddings: 10 + + FluCopyableText{ + text: "这是一个可以支持复制的Text" + anchors.verticalCenter: parent.verticalCenter + } + + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluCopyableText{ + text:"这是一个可以支持复制的Text" +}' + } + +} diff --git a/example/qml-Qt6/page/T_TextBox.qml b/example/qml-Qt6/page/T_TextBox.qml new file mode 100644 index 00000000..768fb481 --- /dev/null +++ b/example/qml-Qt6/page/T_TextBox.qml @@ -0,0 +1,191 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + launchMode: FluPageType.SingleInstance + + title:"TextBox" + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + + FluTextBox{ + placeholderText: "单行输入框" + disabled:text_box_switch.checked + cleanEnabled: true + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + + FluToggleSwitch{ + id:text_box_switch + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTextBox{ + placeholderText:"单行输入框" +}' + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + + FluPasswordBox{ + placeholderText: "请输入密码" + disabled:password_box_switch.checked + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + FluToggleSwitch{ + id:password_box_switch + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluPasswordBox{ + placeholderText:"请输入密码" +}' + } + + + FluArea{ + Layout.fillWidth: true + height: 36+multiine_textbox.height + paddings: 10 + Layout.topMargin: 20 + + FluMultilineTextBox{ + id:multiine_textbox + placeholderText: "多行输入框" + disabled:text_box_multi_switch.checked + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + + FluToggleSwitch{ + id:text_box_multi_switch + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluMultilineTextBox{ + placeholderText:"多行输入框" +}' + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + FluAutoSuggestBox{ + placeholderText: "AutoSuggestBox" + items:generateRandomNames(100) + disabled:text_box_suggest_switch.checked + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + FluToggleSwitch{ + id:text_box_suggest_switch + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluAutoSuggestBox{ + placeholderText:"AutoSuggestBox" +}' + } + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + FluSpinBox{ + disabled: spin_box_switch.checked + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + } + FluToggleSwitch{ + id:spin_box_switch + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluSpinBox{ + +}' + } + + function generateRandomNames(numNames) { + const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const names = []; + function generateRandomName() { + const nameLength = Math.floor(Math.random() * 5) + 4; + let name = ''; + for (let i = 0; i < nameLength; i++) { + const letterIndex = Math.floor(Math.random() * 26); + name += alphabet.charAt(letterIndex); + } + return name; + } + for (let i = 0; i < numNames; i++) { + const name = generateRandomName(); + names.push({title:name}); + } + return names; + } + + +} diff --git a/example/qml-Qt6/page/T_Theme.qml b/example/qml-Qt6/page/T_Theme.qml new file mode 100644 index 00000000..a0b73877 --- /dev/null +++ b/example/qml-Qt6/page/T_Theme.qml @@ -0,0 +1,99 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Theme" + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 270 + paddings: 10 + ColumnLayout{ + spacing:0 + anchors{ + left: parent.left + } + RowLayout{ + Layout.topMargin: 10 + Repeater{ + model: [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green] + delegate: FluRectangle{ + width: 42 + height: 42 + radius: [4,4,4,4] + color: mouse_item.containsMouse ? Qt.lighter(modelData.normal,1.1) : modelData.normal + FluIcon { + anchors.centerIn: parent + iconSource: FluentIcons.AcceptMedium + iconSize: 15 + visible: modelData === FluTheme.primaryColor + color: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) + } + MouseArea{ + id:mouse_item + anchors.fill: parent + hoverEnabled: true + onClicked: { + FluTheme.primaryColor = modelData + } + } + } + } + } + FluText{ + text:"夜间模式" + Layout.topMargin: 20 + } + FluToggleSwitch{ + Layout.topMargin: 5 + checked: FluTheme.dark + onClicked: { + if(FluTheme.dark){ + FluTheme.darkMode = FluThemeType.Light + }else{ + FluTheme.darkMode = FluThemeType.Dark + } + } + } + FluText{ + text:"native文本渲染" + Layout.topMargin: 20 + } + FluToggleSwitch{ + Layout.topMargin: 5 + checked: FluTheme.nativeText + onClicked: { + FluTheme.nativeText = !FluTheme.nativeText + } + } + FluText{ + text:"开启动画效果" + Layout.topMargin: 20 + } + FluToggleSwitch{ + Layout.topMargin: 5 + checked: FluTheme.enableAnimation + onClicked: { + FluTheme.enableAnimation = !FluTheme.enableAnimation + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTheme.primaryColor = FluColors.Orange + +FluTheme.dark = true + +FluTheme.nativeText = true' + } + + +} diff --git a/example/qml-Qt6/page/T_TimePicker.qml b/example/qml-Qt6/page/T_TimePicker.qml new file mode 100644 index 00000000..eefce75a --- /dev/null +++ b/example/qml-Qt6/page/T_TimePicker.qml @@ -0,0 +1,79 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"TimePicker" + launchMode: FluPageType.SingleInstance + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 80 + paddings: 10 + + ColumnLayout{ + + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + + FluText{ + text:"hourFormat=FluTimePickerType.H" + } + + FluTimePicker{ + onCurrentChanged: { + showSuccess(current.toLocaleTimeString(Qt.locale("de_DE"))) + } + } + + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTimePicker{ + +}' + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 80 + paddings: 10 + + ColumnLayout{ + + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + + FluText{ + text:"hourFormat=FluTimePickerType.HH" + } + + FluTimePicker{ + hourFormat:FluTimePickerType.HH + onCurrentChanged: { + showSuccess(current.toLocaleTimeString(Qt.locale("de_DE"))) + } + } + + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTimePicker{ + hourFormat:FluTimePickerType.HH +}' + } + +} diff --git a/example/qml-Qt6/page/T_Timeline.qml b/example/qml-Qt6/page/T_Timeline.qml new file mode 100644 index 00000000..3e7ae2b7 --- /dev/null +++ b/example/qml-Qt6/page/T_Timeline.qml @@ -0,0 +1,170 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Timeline" + + Component{ + id:com_dot + Rectangle{ + width: 16 + height: 16 + radius: 8 + border.width: 4 + border.color: FluTheme.dark ? FluColors.Teal.lighter : FluColors.Teal.dark + } + } + + Component{ + id:com_lable + FluText{ + wrapMode: Text.WrapAnywhere + font.bold: true + horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft + text: modelData.lable + color: FluTheme.dark ? FluColors.Teal.lighter : FluColors.Teal.dark + MouseArea{ + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + showSuccess(modelData.lable) + } + } + } + } + + Component{ + id:com_text + FluText{ + wrapMode: Text.WrapAnywhere + horizontalAlignment: isRight ? Qt.AlignRight : Qt.AlignLeft + text: modelData.text + font.bold: true + linkColor: FluTheme.dark ? FluColors.Teal.lighter : FluColors.Teal.dark + onLinkActivated: + (link)=> { + Qt.openUrlExternally(link) + } + onLinkHovered: + (link)=> { + if(link === ""){ + FluTools.restoreOverrideCursor() + }else{ + FluTools.setOverrideCursor(Qt.PointingHandCursor) + } + } + } + } + + ListModel{ + id:list_model + ListElement{ + lable:"2013-09-01" + text:'  考上中国皮城大学,杰斯武器工坊专业' + } + ListElement{ + lable:"2017-07-01" + text:"大学毕业,在寝室打了4年LOL,没想到毕业还要找工作,瞬间蒙蔽,害" + } + ListElement{ + lable:"2017-09-01" + text:"开始找工作,毕业即失业!回农村老家躺平,继承三亩良田" + } + ListElement{ + lable:"2018-02-01" + text:"玩了一年没钱,惨,出去找工作上班" + } + ListElement{ + lable:"2018-03-01" + text:"找到一份Android外包开发岗位,开发了一个Android应用,满满成就感!前端、服务端、Flutter也都懂一丢丢,什么都会什么都不精通,钱途无望" + } + ListElement{ + lable:"2020-06-01" + text:"由于某个项目紧急,临时加入Qt项目组(就因为大学学了点C++),本来是想进去打个酱油,到后面竟然成开发主力,坑啊" + } + ListElement{ + lable:"2022-08-01" + text:"额,被老板卖到甲方公司,走时老板还问我想不想去,我说:'哪里工资高就去哪里',老板:'无语'" + } + ListElement{ + lable:"2023-02-28" + text:"开发FluentUI组件库" + } + ListElement{ + lable:"2023-03-28" + text:'将FluentUI源码开源到github,并发布视频到B站' + lableDelegate:()=>com_lable + textDelegate:()=>com_text + dot:()=>com_dot + } + } + + RowLayout{ + spacing: 20 + Layout.topMargin: 20 + FluTextBox{ + id:text_box + text:"Technical testing 2015-09-01" + } + FluFilledButton{ + text:"Append" + onClicked: { + list_model.append({text:text_box.text}) + } + } + FluFilledButton{ + text:"clear" + onClicked: { + list_model.clear() + } + } + } + + RowLayout{ + Layout.topMargin: 10 + FluText{ + text:"mode:" + } + FluDropDownButton{ + id:btn_mode + Layout.preferredWidth: 100 + text:"Alternate" + FluMenuItem{ + text:"Left" + onClicked: { + btn_mode.text = text + time_line.mode = FluTimelineType.Left + } + } + FluMenuItem{ + text:"Right" + onClicked: { + btn_mode.text = text + time_line.mode = FluTimelineType.Right + } + } + FluMenuItem{ + text:"Alternate" + onClicked: { + btn_mode.text = text + time_line.mode = FluTimelineType.Alternate + } + } + } + } + + FluTimeline{ + id:time_line + Layout.fillWidth: true + Layout.topMargin: 20 + Layout.bottomMargin: 20 + mode: FluTimelineType.Alternate + model:list_model + } + +} diff --git a/example/qml-Qt6/page/T_ToggleSwitch.qml b/example/qml-Qt6/page/T_ToggleSwitch.qml new file mode 100644 index 00000000..0a708f0a --- /dev/null +++ b/example/qml-Qt6/page/T_ToggleSwitch.qml @@ -0,0 +1,51 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"ToggleSwitch" + + FluArea{ + Layout.fillWidth: true + height: 68 + paddings: 10 + Layout.topMargin: 20 + Row{ + spacing: 30 + anchors.verticalCenter: parent.verticalCenter + FluToggleSwitch{ + disabled: toggle_switch.checked + } + FluToggleSwitch{ + disabled: toggle_switch.checked + text:"Right" + } + FluToggleSwitch{ + disabled: toggle_switch.checked + text:"Left" + textRight: false + } + } + FluToggleSwitch{ + id:toggle_switch + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + } + text:"Disabled" + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluToggleSwitch{ + text:"Text" +}' + } + + +} diff --git a/example/qml-Qt6/page/T_Tooltip.qml b/example/qml-Qt6/page/T_Tooltip.qml new file mode 100644 index 00000000..1a05ef80 --- /dev/null +++ b/example/qml-Qt6/page/T_Tooltip.qml @@ -0,0 +1,103 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Tooltip" + + FluText{ + Layout.topMargin: 20 + text:"鼠标悬停不动,弹出Tooltip" + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 68 + paddings: 10 + + Column{ + spacing: 5 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"FluIconButton的text属性自带Tooltip效果" + } + FluIconButton{ + iconSource:FluentIcons.ChromeCloseContrast + iconSize: 15 + text:"删除" + onClicked:{ + showSuccess("点击IconButton") + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluIconButton{ + iconSource:FluentIcons.ChromeCloseContrast + iconSize: 15 + text:"删除" + onClicked:{ + showSuccess("点击IconButton") + } +} +' + } + + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 20 + height: 68 + paddings: 10 + + Column{ + spacing: 5 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + } + FluText{ + text:"给一个Button添加Tooltip效果" + } + FluButton{ + id:button_1 + text:"删除" + onClicked:{ + showSuccess("点击一个Button") + } + FluTooltip{ + visible: button_1.hovered + text:button_1.text + delay: 1000 + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluButton{ + id:button_1 + text:"删除" + FluTooltip{ + visible: button_1.hovered + text:button_1.text + delay: 1000 + } + onClicked:{ + showSuccess("点击一个Button") + } +}' + } + + +} diff --git a/example/qml-Qt6/page/T_Tour.qml b/example/qml-Qt6/page/T_Tour.qml new file mode 100644 index 00000000..65ad8aa1 --- /dev/null +++ b/example/qml-Qt6/page/T_Tour.qml @@ -0,0 +1,80 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage{ + + title:"Tour" + + FluTour{ + id:tour + steps:[ + {title:"Upload File",description: "Put your files here.",target:()=>btn_upload}, + {title:"Save",description: "Save your changes.",target:()=>btn_save}, + {title:"Other Actions",description: "Click to see other actions.",target:()=>btn_more} + ] + } + + FluArea{ + Layout.fillWidth: true + height: 130 + paddings: 10 + Layout.topMargin: 20 + + FluFilledButton{ + anchors{ + top: parent.top + topMargin: 14 + } + text:"Begin Tour" + onClicked: { + tour.open() + } + } + + Row{ + spacing: 20 + anchors{ + top: parent.top + topMargin: 60 + } + FluButton{ + id:btn_upload + text:"Upload" + onClicked: { + showInfo("Upload") + } + } + FluFilledButton{ + id:btn_save + text:"Save" + onClicked: { + showInfo("Save") + } + } + FluIconButton{ + id:btn_more + iconSource: FluentIcons.More + onClicked: { + showInfo("More") + } + } + } + } + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTour{ + id:tour + steps:[ + {title:"Upload File",description: "Put your files here.",target:()=>btn_upload}, + {title:"Save",description: "Save your changes.",target:()=>btn_save}, + {title:"Other Actions",description: "Click to see other actions.",target:()=>btn_more} + ] +}' + } + +} diff --git a/example/qml-Qt6/page/T_TreeView.qml b/example/qml-Qt6/page/T_TreeView.qml new file mode 100644 index 00000000..80556354 --- /dev/null +++ b/example/qml-Qt6/page/T_TreeView.qml @@ -0,0 +1,156 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +FluScrollablePage { + + title:"TreeView" + + function randomName() { + var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"] + return names[Math.floor(Math.random() * names.length)] + } + + function randomCompany() { + var companies = ["阿里巴巴", "腾讯", "百度", "京东", "华为", "小米", "字节跳动", "美团", "滴滴"] + return companies[Math.floor(Math.random() * companies.length)] + } + + function randomDepartment() { + var departments = ["技术部", "销售部", "市场部", "人事部", "财务部", "客服部", "产品部", "设计部", "运营部"] + return departments[Math.floor(Math.random() * departments.length)] + } + + function createEmployee() { + var name = randomName() + return tree_view.createItem(name, false) + } + + function createSubtree(numEmployees) { + var employees = [] + for (var i = 0; i < numEmployees; i++) { + employees.push(createEmployee()) + } + return tree_view.createItem(randomDepartment(), true, employees) + } + + function createOrg(numLevels, numSubtrees, numEmployees) { + if (numLevels === 0) { + return [] + } + var subtrees = [] + for (var i = 0; i < numSubtrees; i++) { + subtrees.push(createSubtree(numEmployees)) + } + return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees)) + } + + FluArea{ + id:layout_actions + Layout.fillWidth: true + Layout.topMargin: 20 + height: 50 + paddings: 10 + RowLayout{ + spacing: 14 + FluDropDownButton{ + id:btn_selection_model + Layout.preferredWidth: 140 + text:"None" + FluMenuItem{ + text:"None" + onClicked: { + btn_selection_model.text = text + tree_view.selectionMode = FluTabViewType.Equal + } + } + FluMenuItem{ + text:"Single" + onClicked: { + btn_selection_model.text = text + tree_view.selectionMode = FluTabViewType.SizeToContent + } + } + FluMenuItem{ + text:"Muiltple" + onClicked: { + btn_selection_model.text = text + tree_view.selectionMode = FluTabViewType.Compact + } + } + } + FluFilledButton{ + text:"获取选中的数据" + onClicked: { + if(tree_view.selectionMode === FluTreeViewType.None){ + showError("当前非选择模式,没有选中的数据") + } + if(tree_view.selectionMode === FluTreeViewType.Single){ + if(!tree_view.signleData()){ + showError("没有选中数据") + return + } + showSuccess(tree_view.signleData().text) + } + if(tree_view.selectionMode === FluTreeViewType.Multiple){ + if(tree_view.multipData().length===0){ + showError("没有选中数据") + return + } + var info = [] + tree_view.multipData().map((value)=>info.push(value.text)) + showSuccess(info.join(",")) + } + } + } + } + } + FluArea{ + Layout.fillWidth: true + Layout.topMargin: 10 + paddings: 10 + height: 400 + FluTreeView{ + id:tree_view + width:240 + anchors{ + top:parent.top + left:parent.left + bottom:parent.bottom + } + onItemClicked: + (model)=>{ + showSuccess(model.text) + } + + Component.onCompleted: { + var org = createOrg(3, 3, 3) + createItem() + updateData(org) + } + } + } + + CodeExpander{ + Layout.fillWidth: true + Layout.topMargin: -1 + code:'FluTreeView{ + id:tree_view + width:240 + height:600 + Component.onCompleted: { + var datas = [] + datas.push(createItem("Node1",false)) + datas.push(createItem("Node2",false)) + datas.push(createItem("Node2",true,[createItem("Node2-1",false),createItem("Node2-2",false)])) + updateData(datas) + } +} +' + } + + +} diff --git a/example/qml-Qt6/page/T_Typography.qml b/example/qml-Qt6/page/T_Typography.qml new file mode 100644 index 00000000..61f3cf43 --- /dev/null +++ b/example/qml-Qt6/page/T_Typography.qml @@ -0,0 +1,84 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import FluentUI + +FluContentPage { + + property real textScale: 1 + + title: "Typography" + rightPadding: 10 + + FluArea{ + anchors{ + top:parent.top + left: parent.left + right: parent.right + bottom: parent.bottom + topMargin: 20 + } + paddings: 10 + ColumnLayout{ + spacing: 0 + scale: textScale + transformOrigin: Item.TopLeft + FluText{ + id:text_Display + text:"Display" + padding: 0 + font: FluTextStyle.Display + } + FluText{ + id:text_TitleLarge + text:"Title Large" + padding: 0 + font: FluTextStyle.TitleLarge + } + FluText{ + id:text_Title + text:"Title" + padding: 0 + font: FluTextStyle.Title + } + FluText{ + id:text_Subtitle + text:"Subtitle" + padding: 0 + font: FluTextStyle.Subtitle + } + FluText{ + id:text_BodyStrong + text:"Body Strong" + padding: 0 + font: FluTextStyle.BodyStrong + } + FluText{ + id:text_Body + text:"Body" + padding: 0 + font: FluTextStyle.Body + } + FluText{ + id:text_Caption + text:"Caption" + padding: 0 + font: FluTextStyle.Caption + } + } + + FluSlider{ + id:slider + orientation: Qt.Vertical + anchors{ + right: parent.right + rightMargin: 45 + top: parent.top + topMargin: 30 + } + onValueChanged:{ + textScale = 1+value/100 + } + } + } +} diff --git a/example/qml-Qt6/page/T_Watermark.qml b/example/qml-Qt6/page/T_Watermark.qml new file mode 100644 index 00000000..3b4aa275 --- /dev/null +++ b/example/qml-Qt6/page/T_Watermark.qml @@ -0,0 +1,132 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI +import "qrc:///example/qml/component" + +FluContentPage{ + + title:"Watermark" + + FluArea{ + anchors.fill: parent + anchors.topMargin: 20 + + ColumnLayout{ + anchors{ + left: parent.left + leftMargin: 14 + } + + RowLayout{ + spacing: 10 + Layout.topMargin: 14 + FluText{ + text:"text:" + Layout.alignment: Qt.AlignVCenter + } + FluTextBox{ + id:text_box + text:"会磨刀的小猪" + } + } + + RowLayout{ + spacing: 10 + FluText{ + text:"textSize:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_text_size + value: 20 + from: 13 + to:50 + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"gapX:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_gap_x + value: 100 + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"gapY:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_gap_y + value: 100 + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"offsetX:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_offset_x + value: 50 + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"offsetY:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_offset_y + value: 50 + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"rotate:" + Layout.alignment: Qt.AlignVCenter + } + FluSlider{ + id:slider_rotate + value: 22 + from: 0 + to:360 + } + } + RowLayout{ + spacing: 10 + FluText{ + text:"textColor:" + Layout.alignment: Qt.AlignVCenter + } + FluColorPicker{ + id:color_picker + Component.onCompleted: { + setColor(Qt.rgba(0,0,0,0.1)) + } + } + } + } + + FluWatermark{ + id:water_mark + anchors.fill: parent + text:text_box.text + textColor: color_picker.colorValue + textSize: slider_text_size.value + rotate: slider_rotate.value + gap:Qt.point(slider_gap_x.value,slider_gap_y.value) + offset: Qt.point(slider_offset_x.value,slider_offset_y.value) + } + } + +} diff --git a/example/qml-Qt6/window/AboutWindow.qml b/example/qml-Qt6/window/AboutWindow.qml new file mode 100644 index 00000000..862923dd --- /dev/null +++ b/example/qml-Qt6/window/AboutWindow.qml @@ -0,0 +1,150 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI +import "qrc:///example/qml/component" + +CustomWindow { + + id:window + title:"关于" + width: 600 + height: 600 + fixSize: true + launchMode: FluWindowType.SingleTask + + ColumnLayout{ + anchors{ + top: parent.top + left: parent.left + right: parent.right + } + + RowLayout{ + Layout.topMargin: 20 + Layout.leftMargin: 15 + spacing: 14 + FluText{ + text:"FluentUI" + font: FluTextStyle.Title + MouseArea{ + anchors.fill: parent + onClicked: { + FluApp.navigate("/") + } + } + } + FluText{ + text:"v%1".arg(appInfo.version) + font: FluTextStyle.Body + Layout.alignment: Qt.AlignBottom + } + } + + RowLayout{ + spacing: 14 + Layout.topMargin: 20 + Layout.leftMargin: 15 + FluText{ + text:"作者:" + } + FluText{ + text:"朱子楚" + Layout.alignment: Qt.AlignBottom + } + } + + RowLayout{ + spacing: 14 + Layout.leftMargin: 15 + FluText{ + text:"GitHub:" + } + FluTextButton{ + id:text_hublink + topPadding:0 + bottomPadding:0 + text:"https://github.com/zhuzichu520/FluentUI" + Layout.alignment: Qt.AlignBottom + onClicked: { + Qt.openUrlExternally(text_hublink.text) + } + } + } + + RowLayout{ + spacing: 14 + Layout.leftMargin: 15 + FluText{ + text:"B站:" + } + FluTextButton{ + topPadding:0 + bottomPadding:0 + text:"https://www.bilibili.com/video/BV1mg4y1M71w/" + Layout.alignment: Qt.AlignBottom + onClicked: { + Qt.openUrlExternally(text) + } + } + } + + RowLayout{ + spacing: 14 + Layout.leftMargin: 15 + FluText{ + id:text_info + text:"如果该项目对你有作用,就请点击上方链接给一个免费的star,或者一键三连,谢谢!" + ColorAnimation { + id: animation + target: text_info + property: "color" + from: "red" + to: "blue" + duration: 1000 + running: true + loops: Animation.Infinite + easing.type: Easing.InOutQuad + } + } + } + + RowLayout{ + spacing: 14 + Layout.topMargin: 20 + Layout.leftMargin: 15 + FluText{ + text:"捐赠:" + } + } + + Item{ + Layout.preferredWidth: parent.width + Layout.preferredHeight: 252 + Row{ + anchors.horizontalCenter: parent.horizontalCenter + spacing: 30 + Image{ + width: 250 + height: 250 + source: "qrc:/example/res/image/qrcode_wx.jpg" + } + Image{ + width: 250 + height: 250 + source: "qrc:/example/res/image/qrcode_zfb.jpg" + } + } + } + + RowLayout{ + spacing: 14 + Layout.leftMargin: 15 + Layout.topMargin: 20 + FluText{ + id:text_desc + text:"个人开发,维护不易,你们的捐赠就是我继续更新的动力!\n有什么问题提Issues,只要时间充足我就会解决的!!" + } + } + } +} diff --git a/example/qml-Qt6/window/HotloadWindow.qml b/example/qml-Qt6/window/HotloadWindow.qml new file mode 100644 index 00000000..31a94400 --- /dev/null +++ b/example/qml-Qt6/window/HotloadWindow.qml @@ -0,0 +1,85 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI +import example +import "qrc:///example/qml/component" + +CustomWindow { + + id:window + title:"热加载" + width: 800 + height: 600 + minimumWidth: 520 + minimumHeight: 200 + launchMode: FluWindowType.SingleTask + FileWatcher{ + id:watcher + onFileChanged: { + loader.reload() + } + } + FluArea{ + anchors.fill: parent + FluRemoteLoader{ + id:loader + anchors.fill: parent + statusMode: FluStatusViewType.Success + lazy: true + errorItem: Item{ + FluText{ + text:loader.itemLodaer().sourceComponent.errorString() + color:"red" + anchors.fill: parent + wrapMode: Text.WrapAnywhere + padding: 20 + verticalAlignment: Qt.AlignVCenter + horizontalAlignment: Qt.AlignHCenter + } + } + } + FluText{ + text:"拖入qml文件" + font.pixelSize: 26 + anchors.centerIn: parent + visible: !loader.itemLodaer().item && loader.statusMode === FluStatusViewType.Success + } + Rectangle{ + radius: 4 + anchors.fill: parent + color: "#33333333" + visible: drop_area.containsDrag + } + DropArea{ + id:drop_area + anchors.fill: parent + onEntered: + (event)=>{ + if(!event.hasUrls){ + event.accepted = false + return + } + if (event.urls.length !== 1) { + event.accepted = false + return + } + var url = event.urls[0].toString() + var fileExtension = url.substring(url.lastIndexOf(".") + 1) + if (fileExtension !== "qml") { + event.accepted = false + return + } + return true + } + onDropped: + (event)=>{ + var path = event.urls[0].toString() + loader.source = path + watcher.path = path + loader.reload() + } + } + } + +} diff --git a/example/qml-Qt6/window/LoginWindow.qml b/example/qml-Qt6/window/LoginWindow.qml new file mode 100644 index 00000000..9f3e25f7 --- /dev/null +++ b/example/qml-Qt6/window/LoginWindow.qml @@ -0,0 +1,63 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import FluentUI +import "qrc:///example/qml/component" + +CustomWindow { + + id:window + title:"登录" + width: 400 + height: 400 + fixSize: true + + onInitArgument: + (argument)=>{ + textbox_uesrname.updateText(argument.username) + textbox_password.focus = true + } + + ColumnLayout{ + anchors{ + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + + FluAutoSuggestBox{ + id:textbox_uesrname + items:[{title:"Admin"},{title:"User"}] + placeholderText: "请输入账号" + Layout.preferredWidth: 260 + Layout.alignment: Qt.AlignHCenter + } + + FluTextBox{ + id:textbox_password + Layout.topMargin: 20 + Layout.preferredWidth: 260 + placeholderText: "请输入密码" + echoMode:TextInput.Password + Layout.alignment: Qt.AlignHCenter + } + + FluFilledButton{ + text:"登录" + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: 20 + onClicked:{ + if(textbox_password.text === ""){ + showError("请随便输入一个密码") + return + } + onResult({password:textbox_password.text}) + window.close() + } + } + + } + + + +} diff --git a/example/qml-Qt6/window/MainWindow.qml b/example/qml-Qt6/window/MainWindow.qml new file mode 100644 index 00000000..be1553d6 --- /dev/null +++ b/example/qml-Qt6/window/MainWindow.qml @@ -0,0 +1,280 @@ +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Layouts +import Qt.labs.platform +import FluentUI +import example +import "qrc:///example/qml/component" +import "qrc:///example/qml/global" + +CustomWindow { + + id:window + title: "FluentUI" + width: 1000 + height: 640 + closeDestory:false + minimumWidth: 520 + minimumHeight: 200 + appBarVisible: false + launchMode: FluWindowType.SingleTask + + closeFunc:function(event){ + dialog_close.open() + event.accepted = false + } + + Component.onCompleted: { + FluTools.setQuitOnLastWindowClosed(false) + tour.open() + } + + SystemTrayIcon { + id:system_tray + visible: true + icon.source: "qrc:/example/res/image/favicon.ico" + tooltip: "FluentUI" + menu: Menu { + MenuItem { + text: "退出" + onTriggered: { + window.deleteWindow() + FluApp.closeApp() + } + } + } + onActivated: + (reason)=>{ + if(reason === SystemTrayIcon.Trigger){ + window.show() + window.raise() + window.requestActivate() + } + } + } + + FluContentDialog{ + id:dialog_close + title:"退出" + message:"确定要退出程序吗?" + negativeText:"最小化" + buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton | FluContentDialogType.PositiveButton + onNegativeClicked:{ + window.hide() + system_tray.showMessage("友情提示","FluentUI已隐藏至托盘,点击托盘可再次激活窗口"); + } + positiveText:"退出" + neutralText:"取消" + onPositiveClicked:{ + window.deleteWindow() + FluApp.closeApp() + } + } + + Flipable{ + id:flipable + anchors.fill: parent + property bool flipped: false + property real flipAngle: 0 + transform: Rotation { + id: rotation + origin.x: flipable.width/2 + origin.y: flipable.height/2 + axis { x: 0; y: 1; z: 0 } + angle: flipable.flipAngle + + } + states: State { + PropertyChanges { target: flipable; flipAngle: 180 } + when: flipable.flipped + } + transitions: Transition { + NumberAnimation { target: flipable; property: "flipAngle"; duration: 1000 ; easing.type: Easing.OutCubic} + } + back: Item{ + anchors.fill: flipable + visible: flipable.flipAngle !== 0 + FluAppBar { + anchors { + top: parent.top + left: parent.left + right: parent.right + } + darkText: lang.dark_mode + showDark: true + z:7 + darkClickListener:(button)=>handleDarkChanged(button) + } + Row{ + z:8 + anchors{ + top: parent.top + left: parent.left + topMargin: FluTools.isMacos() ? 20 : 5 + leftMargin: 5 + } + FluIconButton{ + iconSource: FluentIcons.ChromeBack + width: 30 + height: 30 + iconSize: 13 + onClicked: { + flipable.flipped = false + } + } + FluIconButton{ + iconSource: FluentIcons.Sync + width: 30 + height: 30 + iconSize: 13 + onClicked: { + loader.reload() + } + } + } + + FluRemoteLoader{ + id:loader + lazy: true + anchors.fill: parent + // source: "http://localhost:9000/RemoteComponent.qml" + source: "https://zhu-zichu.gitee.io/RemoteComponent.qml" + } + } + front: Item{ + id:page_front + visible: flipable.flipAngle !== 180 + anchors.fill: flipable + FluAppBar { + id:app_bar_front + anchors { + top: parent.top + left: parent.left + right: parent.right + } + darkText: lang.dark_mode + showDark: true + darkClickListener:(button)=>handleDarkChanged(button) + z:7 + } + FluNavigationView{ + property int clickCount: 0 + id:nav_view + width: parent.width + height: parent.height + z:999 + //Stack模式,每次切换都会将页面压入栈中,随着栈的页面增多,消耗的内存也越多,内存消耗多就会卡顿,这时候就需要按返回将页面pop掉,释放内存。该模式可以配合FluPage中的launchMode属性,设置页面的启动模式 + pageMode: FluNavigationViewType.Stack + //NoStack模式,每次切换都会销毁之前的页面然后创建一个新的页面,只需消耗少量内存(推荐) + // pageMode: FluNavigationViewType.NoStack + items: ItemsOriginal + footerItems:ItemsFooter + topPadding:FluTools.isMacos() ? 20 : 0 + displayMode:MainEvent.displayMode + logo: "qrc:/example/res/image/favicon.ico" + title:"FluentUI" + onLogoClicked:{ + clickCount += 1 + showSuccess("点击%1次".arg(clickCount)) + if(clickCount === 5){ + loader.reload() + flipable.flipped = true + clickCount = 0 + } + } + autoSuggestBox:FluAutoSuggestBox{ + width: 280 + anchors.centerIn: parent + iconSource: FluentIcons.Search + items: ItemsOriginal.getSearchData() + placeholderText: lang.search + onItemClicked: + (data)=>{ + ItemsOriginal.startPageByItem(data) + } + } + Component.onCompleted: { + ItemsOriginal.navigationView = nav_view + ItemsFooter.navigationView = nav_view + setCurrentIndex(0) + } + } + } + } + + Component{ + id:com_reveal + CircularReveal{ + id:reveal + target:window.contentItem + anchors.fill: parent + onAnimationFinished:{ + //动画结束后释放资源 + loader_reveal.sourceComponent = undefined + } + onImageChanged: { + changeDark() + } + } + } + + Loader{ + id:loader_reveal + anchors.fill: parent + } + + function distance(x1,y1,x2,y2){ + return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) + } + + function handleDarkChanged(button){ + if(FluTools.isMacos() || !FluTheme.enableAnimation){ + changeDark() + }else{ + loader_reveal.sourceComponent = com_reveal + var target = window.contentItem + var pos = button.mapToItem(target,0,0) + var mouseX = pos.x + var mouseY = pos.y + var radius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height)) + var reveal = loader_reveal.item + reveal.start(reveal.width*Screen.devicePixelRatio,reveal.height*Screen.devicePixelRatio,Qt.point(mouseX,mouseY),radius) + } + } + + function changeDark(){ + if(FluTheme.dark){ + FluTheme.darkMode = FluThemeType.Light + }else{ + FluTheme.darkMode = FluThemeType.Dark + } + } + + Shortcut { + sequence: "F5" + context: Qt.WindowShortcut + onActivated: { + if(flipable.flipped){ + loader.reload() + } + } + } + + Shortcut { + sequence: "F6" + context: Qt.WindowShortcut + onActivated: { + tour.open() + } + } + + FluTour{ + id:tour + steps:[ + {title:"夜间模式",description: "这里可以切换夜间模式.",target:()=>app_bar_front.darkButton()}, + {title:"隐藏彩蛋",description: "多点几下试试!!",target:()=>nav_view.logoButton()} + ] + } + +} diff --git a/example/qml-Qt6/window/SingleInstanceWindow.qml b/example/qml-Qt6/window/SingleInstanceWindow.qml new file mode 100644 index 00000000..6a765bbc --- /dev/null +++ b/example/qml-Qt6/window/SingleInstanceWindow.qml @@ -0,0 +1,35 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI +import "qrc:///example/qml/component" + +CustomWindow { + + id:window + title:"SingleInstance" + width: 500 + height: 600 + fixSize: true + launchMode: FluWindowType.SingleInstance + + FluTextBox{ + anchors{ + top:parent.top + topMargin:60 + horizontalCenter: parent.horizontalCenter + } + } + + FluText{ + wrapMode: Text.WrapAnywhere + anchors{ + left: parent.left + right: parent.right + leftMargin: 20 + rightMargin: 20 + verticalCenter: parent.verticalCenter + } + text:"我是一个SingleInstance模式的窗口,如果我存在,我会销毁之前的窗口,并创建一个新窗口" + } +} diff --git a/example/qml-Qt6/window/SingleTaskWindow.qml b/example/qml-Qt6/window/SingleTaskWindow.qml new file mode 100644 index 00000000..7a312315 --- /dev/null +++ b/example/qml-Qt6/window/SingleTaskWindow.qml @@ -0,0 +1,21 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI +import "qrc:///example/qml/component" + +CustomWindow { + + id:window + title:"SingleTask" + width: 500 + height: 600 + fixSize: true + launchMode: FluWindowType.SingleTask + + FluText{ + anchors.centerIn: parent + text:"我是一个SingleTask模式的窗口,如果我存在,我就激活窗口" + } + +} diff --git a/example/qml-Qt6/window/StandardWindow.qml b/example/qml-Qt6/window/StandardWindow.qml new file mode 100644 index 00000000..aaee568e --- /dev/null +++ b/example/qml-Qt6/window/StandardWindow.qml @@ -0,0 +1,43 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI +import "qrc:///example/qml/component" + +CustomWindow { + + id:window + title:"Standard" + width: 500 + height: 600 + fixSize: true + launchMode: FluWindowType.Standard + + FluMenuBar { + FluMenu { + title: qsTr("File") + Action { text: qsTr("New...") } + Action { text: qsTr("Open...") } + Action { text: qsTr("Save") } + Action { text: qsTr("Save As...") } + FluMenuSeparator { } + Action { text: qsTr("Quit") } + } + FluMenu { + title: qsTr("Edit") + Action { text: qsTr("Cut") } + Action { text: qsTr("Copy") } + Action { text: qsTr("Paste") } + } + FluMenu { + title: qsTr("Help") + Action { text: qsTr("About") } + } + } + + FluText{ + anchors.centerIn: parent + text:"我是一个Standard模式的窗口,每次我都会创建一个新的窗口" + } + +} diff --git a/example/qml/App.qml b/example/qml/App.qml index f0af5371..08960754 100644 --- a/example/qml/App.qml +++ b/example/qml/App.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Window -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 Window { id: app diff --git a/example/qml/component/CodeExpander.qml b/example/qml/component/CodeExpander.qml index f69c879a..5570c48b 100644 --- a/example/qml/component/CodeExpander.qml +++ b/example/qml/component/CodeExpander.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 FluExpander{ diff --git a/example/qml/component/CustomWindow.qml b/example/qml/component/CustomWindow.qml index 88451d28..626d1a39 100644 --- a/example/qml/component/CustomWindow.qml +++ b/example/qml/component/CustomWindow.qml @@ -1,7 +1,7 @@ -import QtQuick -import QtQuick.Layouts -import FluentUI -import org.wangwenx190.FramelessHelper +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 +import org.wangwenx190.FramelessHelper 1.0 FluWindow { id:window diff --git a/example/qml/global/ItemsFooter.qml b/example/qml/global/ItemsFooter.qml index c6742d06..463b52e2 100644 --- a/example/qml/global/ItemsFooter.qml +++ b/example/qml/global/ItemsFooter.qml @@ -1,7 +1,7 @@ pragma Singleton -import QtQuick -import FluentUI +import QtQuick 2.15 +import FluentUI 1.0 FluObject{ diff --git a/example/qml/global/ItemsOriginal.qml b/example/qml/global/ItemsOriginal.qml index 3f3beb48..5ebe0e96 100644 --- a/example/qml/global/ItemsOriginal.qml +++ b/example/qml/global/ItemsOriginal.qml @@ -1,7 +1,7 @@ pragma Singleton -import QtQuick -import FluentUI +import QtQuick 2.15 +import FluentUI 1.0 FluObject{ diff --git a/example/qml/global/MainEvent.qml b/example/qml/global/MainEvent.qml index 7119ffc6..c31e3a4a 100644 --- a/example/qml/global/MainEvent.qml +++ b/example/qml/global/MainEvent.qml @@ -1,8 +1,8 @@ pragma Singleton -import QtQuick -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 QtObject { property int displayMode : FluNavigationViewType.Auto diff --git a/example/qml/page/T_Acrylic.qml b/example/qml/page/T_Acrylic.qml index ae83a596..e23f239a 100644 --- a/example/qml/page/T_Acrylic.qml +++ b/example/qml/page/T_Acrylic.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Awesome.qml b/example/qml/page/T_Awesome.qml index 182ce910..1804475f 100644 --- a/example/qml/page/T_Awesome.qml +++ b/example/qml/page/T_Awesome.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 FluContentPage { diff --git a/example/qml/page/T_Badge.qml b/example/qml/page/T_Badge.qml index baccc3d7..8ce25806 100644 --- a/example/qml/page/T_Badge.qml +++ b/example/qml/page/T_Badge.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_BreadcrumbBar.qml b/example/qml/page/T_BreadcrumbBar.qml index f6a1ba08..bfe65baf 100644 --- a/example/qml/page/T_BreadcrumbBar.qml +++ b/example/qml/page/T_BreadcrumbBar.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Buttons.qml b/example/qml/page/T_Buttons.qml index 7707333f..699c8318 100644 --- a/example/qml/page/T_Buttons.qml +++ b/example/qml/page/T_Buttons.qml @@ -1,9 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import QtQuick.Controls.Basic -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_CalendarPicker.qml b/example/qml/page/T_CalendarPicker.qml index 4cb67901..c9d10574 100644 --- a/example/qml/page/T_CalendarPicker.qml +++ b/example/qml/page/T_CalendarPicker.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Captcha.qml b/example/qml/page/T_Captcha.qml index 8ac59e75..68466fce 100644 --- a/example/qml/page/T_Captcha.qml +++ b/example/qml/page/T_Captcha.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Carousel.qml b/example/qml/page/T_Carousel.qml index 75cc647c..de27ff74 100644 --- a/example/qml/page/T_Carousel.qml +++ b/example/qml/page/T_Carousel.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Chart.qml b/example/qml/page/T_Chart.qml index 7582b210..53906ba9 100644 --- a/example/qml/page/T_Chart.qml +++ b/example/qml/page/T_Chart.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_CheckBox.qml b/example/qml/page/T_CheckBox.qml index e3c6ea4a..28605536 100644 --- a/example/qml/page/T_CheckBox.qml +++ b/example/qml/page/T_CheckBox.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_ColorPicker.qml b/example/qml/page/T_ColorPicker.qml index 24954589..93375c3a 100644 --- a/example/qml/page/T_ColorPicker.qml +++ b/example/qml/page/T_ColorPicker.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_ComboBox.qml b/example/qml/page/T_ComboBox.qml index 15fba70b..d5463a7c 100644 --- a/example/qml/page/T_ComboBox.qml +++ b/example/qml/page/T_ComboBox.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_DatePicker.qml b/example/qml/page/T_DatePicker.qml index 0fe6c4df..ac978370 100644 --- a/example/qml/page/T_DatePicker.qml +++ b/example/qml/page/T_DatePicker.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Dialog.qml b/example/qml/page/T_Dialog.qml index b1e8b6b5..d4a14699 100644 --- a/example/qml/page/T_Dialog.qml +++ b/example/qml/page/T_Dialog.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Expander.qml b/example/qml/page/T_Expander.qml index 36f390e3..b9af09a3 100644 --- a/example/qml/page/T_Expander.qml +++ b/example/qml/page/T_Expander.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_FlipView.qml b/example/qml/page/T_FlipView.qml index 3baf06c1..843b9ab9 100644 --- a/example/qml/page/T_FlipView.qml +++ b/example/qml/page/T_FlipView.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Home.qml b/example/qml/page/T_Home.qml index c6acc672..52c23211 100644 --- a/example/qml/page/T_Home.qml +++ b/example/qml/page/T_Home.qml @@ -1,9 +1,9 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 import "qrc:///example/qml/global" -import FluentUI +import FluentUI 1.0 FluScrollablePage{ diff --git a/example/qml/page/T_Http.qml b/example/qml/page/T_Http.qml index 58942ade..b5f2123c 100644 --- a/example/qml/page/T_Http.qml +++ b/example/qml/page/T_Http.qml @@ -1,10 +1,10 @@ -import QtQuick -import Qt.labs.platform -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import QtQuick.Dialogs -import FluentUI +import QtQuick 2.15 +import Qt.labs.platform 1.1 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Dialogs 1.3 +import FluentUI 1.0 import "qrc:///example/qml/component" FluContentPage{ diff --git a/example/qml/page/T_Image.qml b/example/qml/page/T_Image.qml index bbeb6dcf..fb63d065 100644 --- a/example/qml/page/T_Image.qml +++ b/example/qml/page/T_Image.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_InfoBar.qml b/example/qml/page/T_InfoBar.qml index 24e3d907..ff5894a1 100644 --- a/example/qml/page/T_InfoBar.qml +++ b/example/qml/page/T_InfoBar.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Menu.qml b/example/qml/page/T_Menu.qml index fde64248..5b2f1808 100644 --- a/example/qml/page/T_Menu.qml +++ b/example/qml/page/T_Menu.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_MultiWindow.qml b/example/qml/page/T_MultiWindow.qml index 070fc4e4..88ff4137 100644 --- a/example/qml/page/T_MultiWindow.qml +++ b/example/qml/page/T_MultiWindow.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Pagination.qml b/example/qml/page/T_Pagination.qml index fa072dc6..838a4c9f 100644 --- a/example/qml/page/T_Pagination.qml +++ b/example/qml/page/T_Pagination.qml @@ -1,9 +1,9 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 import "qrc:///example/qml/component" -import FluentUI +import FluentUI 1.0 FluScrollablePage{ diff --git a/example/qml/page/T_Pivot.qml b/example/qml/page/T_Pivot.qml index 0fe52dfd..bd75554c 100644 --- a/example/qml/page/T_Pivot.qml +++ b/example/qml/page/T_Pivot.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Progress.qml b/example/qml/page/T_Progress.qml index cb4740b5..d5ded7de 100644 --- a/example/qml/page/T_Progress.qml +++ b/example/qml/page/T_Progress.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_QRCode.qml b/example/qml/page/T_QRCode.qml index 24f60f20..956c4d20 100644 --- a/example/qml/page/T_QRCode.qml +++ b/example/qml/page/T_QRCode.qml @@ -1,9 +1,9 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import Qt5Compat.GraphicalEffects +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 +import QtGraphicalEffects 1.15 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_RadioButton.qml b/example/qml/page/T_RadioButton.qml index 07b383b7..85307ab5 100644 --- a/example/qml/page/T_RadioButton.qml +++ b/example/qml/page/T_RadioButton.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_RatingControl.qml b/example/qml/page/T_RatingControl.qml index 4c39d380..05bd99a5 100644 --- a/example/qml/page/T_RatingControl.qml +++ b/example/qml/page/T_RatingControl.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage { diff --git a/example/qml/page/T_Rectangle.qml b/example/qml/page/T_Rectangle.qml index 9cfe42aa..346aeab4 100644 --- a/example/qml/page/T_Rectangle.qml +++ b/example/qml/page/T_Rectangle.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_RemoteLoader.qml b/example/qml/page/T_RemoteLoader.qml index 03dd73cf..c8e11c17 100644 --- a/example/qml/page/T_RemoteLoader.qml +++ b/example/qml/page/T_RemoteLoader.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluPage{ diff --git a/example/qml/page/T_Screenshot.qml b/example/qml/page/T_Screenshot.qml index 1a5cf38f..e146041b 100644 --- a/example/qml/page/T_Screenshot.qml +++ b/example/qml/page/T_Screenshot.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Settings.qml b/example/qml/page/T_Settings.qml index 8c2fcefd..57dadfe3 100644 --- a/example/qml/page/T_Settings.qml +++ b/example/qml/page/T_Settings.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/global" import "qrc:///example/qml/component" diff --git a/example/qml/page/T_Slider.qml b/example/qml/page/T_Slider.qml index 517904a6..138e265a 100644 --- a/example/qml/page/T_Slider.qml +++ b/example/qml/page/T_Slider.qml @@ -1,9 +1,9 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 import "qrc:///example/qml/component" -import FluentUI +import FluentUI 1.0 FluScrollablePage{ diff --git a/example/qml/page/T_StatusView.qml b/example/qml/page/T_StatusView.qml index 3a94578d..d84abc27 100644 --- a/example/qml/page/T_StatusView.qml +++ b/example/qml/page/T_StatusView.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_TabView.qml b/example/qml/page/T_TabView.qml index e50f4de1..dbdb9bcd 100644 --- a/example/qml/page/T_TabView.qml +++ b/example/qml/page/T_TabView.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_TableView.qml b/example/qml/page/T_TableView.qml index ffd6f174..26641d95 100644 --- a/example/qml/page/T_TableView.qml +++ b/example/qml/page/T_TableView.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluContentPage{ diff --git a/example/qml/page/T_Text.qml b/example/qml/page/T_Text.qml index c5624f62..43f43f13 100644 --- a/example/qml/page/T_Text.qml +++ b/example/qml/page/T_Text.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_TextBox.qml b/example/qml/page/T_TextBox.qml index 768fb481..5b717171 100644 --- a/example/qml/page/T_TextBox.qml +++ b/example/qml/page/T_TextBox.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Theme.qml b/example/qml/page/T_Theme.qml index a0b73877..4cd901dc 100644 --- a/example/qml/page/T_Theme.qml +++ b/example/qml/page/T_Theme.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_TimePicker.qml b/example/qml/page/T_TimePicker.qml index eefce75a..92bed2c5 100644 --- a/example/qml/page/T_TimePicker.qml +++ b/example/qml/page/T_TimePicker.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Timeline.qml b/example/qml/page/T_Timeline.qml index 3e7ae2b7..72a33665 100644 --- a/example/qml/page/T_Timeline.qml +++ b/example/qml/page/T_Timeline.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_ToggleSwitch.qml b/example/qml/page/T_ToggleSwitch.qml index 0a708f0a..79122cc3 100644 --- a/example/qml/page/T_ToggleSwitch.qml +++ b/example/qml/page/T_ToggleSwitch.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Tooltip.qml b/example/qml/page/T_Tooltip.qml index 1a05ef80..16e335a8 100644 --- a/example/qml/page/T_Tooltip.qml +++ b/example/qml/page/T_Tooltip.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_Tour.qml b/example/qml/page/T_Tour.qml index 65ad8aa1..74ea324c 100644 --- a/example/qml/page/T_Tour.qml +++ b/example/qml/page/T_Tour.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage{ diff --git a/example/qml/page/T_TreeView.qml b/example/qml/page/T_TreeView.qml index 80556354..c2604fc4 100644 --- a/example/qml/page/T_TreeView.qml +++ b/example/qml/page/T_TreeView.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluScrollablePage { diff --git a/example/qml/page/T_Typography.qml b/example/qml/page/T_Typography.qml index 61f3cf43..854eab56 100644 --- a/example/qml/page/T_Typography.qml +++ b/example/qml/page/T_Typography.qml @@ -1,7 +1,7 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 FluContentPage { diff --git a/example/qml/page/T_Watermark.qml b/example/qml/page/T_Watermark.qml index 3b4aa275..7c352683 100644 --- a/example/qml/page/T_Watermark.qml +++ b/example/qml/page/T_Watermark.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" FluContentPage{ diff --git a/example/qml/window/AboutWindow.qml b/example/qml/window/AboutWindow.qml index 862923dd..33fb6cdb 100644 --- a/example/qml/window/AboutWindow.qml +++ b/example/qml/window/AboutWindow.qml @@ -1,7 +1,7 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 import "qrc:///example/qml/component" CustomWindow { diff --git a/example/qml/window/HotloadWindow.qml b/example/qml/window/HotloadWindow.qml index 31a94400..07e918a0 100644 --- a/example/qml/window/HotloadWindow.qml +++ b/example/qml/window/HotloadWindow.qml @@ -1,8 +1,8 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import example +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 +import example 1.0 import "qrc:///example/qml/component" CustomWindow { diff --git a/example/qml/window/LoginWindow.qml b/example/qml/window/LoginWindow.qml index 9f3e25f7..8ae713ec 100644 --- a/example/qml/window/LoginWindow.qml +++ b/example/qml/window/LoginWindow.qml @@ -1,7 +1,7 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import FluentUI +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 import "qrc:///example/qml/component" CustomWindow { diff --git a/example/qml/window/MainWindow.qml b/example/qml/window/MainWindow.qml index be1553d6..c34e31f7 100644 --- a/example/qml/window/MainWindow.qml +++ b/example/qml/window/MainWindow.qml @@ -1,10 +1,10 @@ -import QtQuick -import QtQuick.Window -import QtQuick.Controls -import QtQuick.Layouts -import Qt.labs.platform -import FluentUI -import example +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import Qt.labs.platform 1.1 +import FluentUI 1.0 +import example 1.0 import "qrc:///example/qml/component" import "qrc:///example/qml/global" diff --git a/example/qml/window/SingleInstanceWindow.qml b/example/qml/window/SingleInstanceWindow.qml index 6a765bbc..bfd95d88 100644 --- a/example/qml/window/SingleInstanceWindow.qml +++ b/example/qml/window/SingleInstanceWindow.qml @@ -1,7 +1,7 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 import "qrc:///example/qml/component" CustomWindow { diff --git a/example/qml/window/SingleTaskWindow.qml b/example/qml/window/SingleTaskWindow.qml index 7a312315..b3354da4 100644 --- a/example/qml/window/SingleTaskWindow.qml +++ b/example/qml/window/SingleTaskWindow.qml @@ -1,7 +1,7 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 import "qrc:///example/qml/component" CustomWindow { diff --git a/example/qml/window/StandardWindow.qml b/example/qml/window/StandardWindow.qml index aaee568e..848dae4d 100644 --- a/example/qml/window/StandardWindow.qml +++ b/example/qml/window/StandardWindow.qml @@ -1,7 +1,7 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 import "qrc:///example/qml/component" CustomWindow { diff --git a/example/resource.qrc b/example/resource.qrc new file mode 100644 index 00000000..252fbb0e --- /dev/null +++ b/example/resource.qrc @@ -0,0 +1,188 @@ + + + res/svg/avatar_1.svg + res/svg/avatar_2.svg + res/svg/avatar_3.svg + res/svg/avatar_4.svg + res/svg/avatar_5.svg + res/svg/avatar_6.svg + res/svg/avatar_7.svg + res/svg/avatar_8.svg + res/svg/avatar_9.svg + res/svg/avatar_10.svg + res/svg/avatar_11.svg + res/svg/avatar_12.svg + res/image/banner_1.jpg + res/image/banner_2.jpg + res/image/banner_3.jpg + res/image/logo_openai.png + res/image/favicon.ico + res/image/bg_home_header.png + res/image/ic_home_github.png + res/image/control/Acrylic.png + res/image/control/AnimatedIcon.png + res/image/control/AnimatedVisualPlayer.png + res/image/control/AnimationInterop.png + res/image/control/AppBarButton.png + res/image/control/AppBarSeparator.png + res/image/control/AppBarToggleButton.png + res/image/control/AutomationProperties.png + res/image/control/AutoSuggestBox.png + res/image/control/Border.png + res/image/control/BreadcrumbBar.png + res/image/control/Button.png + res/image/control/CalendarDatePicker.png + res/image/control/CalendarView.png + res/image/control/Canvas.png + res/image/control/Checkbox.png + res/image/control/Clipboard.png + res/image/control/ColorPaletteResources.png + res/image/control/ColorPicker.png + res/image/control/ComboBox.png + res/image/control/CommandBar.png + res/image/control/CommandBarFlyout.png + res/image/control/CompactSizing.png + res/image/control/ConnectedAnimation.png + res/image/control/ContentDialog.png + res/image/control/CreateMultipleWindows.png + res/image/control/DataGrid.png + res/image/control/DatePicker.png + res/image/control/DropDownButton.png + res/image/control/EasingFunction.png + res/image/control/Expander.png + res/image/control/FilePicker.png + res/image/control/FlipView.png + res/image/control/Flyout.png + res/image/control/Grid.png + res/image/control/GridView.png + res/image/control/HyperlinkButton.png + res/image/control/IconElement.png + res/image/control/Image.png + res/image/control/ImplicitTransition.png + res/image/control/InfoBadge.png + res/image/control/InfoBar.png + res/image/control/InkCanvas.png + res/image/control/InkToolbar.png + res/image/control/InputValidation.png + res/image/control/ItemsRepeater.png + res/image/control/Line.png + res/image/control/ListBox.png + res/image/control/ListView.png + res/image/control/MediaPlayerElement.png + res/image/control/MenuBar.png + res/image/control/MenuFlyout.png + res/image/control/NavigationView.png + res/image/control/NumberBox.png + res/image/control/PageTransition.png + res/image/control/ParallaxView.png + res/image/control/PasswordBox.png + res/image/control/PersonPicture.png + res/image/control/PipsPager.png + res/image/control/Pivot.png + res/image/control/ProgressBar.png + res/image/control/ProgressRing.png + res/image/control/PullToRefresh.png + res/image/control/RadialGradientBrush.png + res/image/control/RadioButton.png + res/image/control/RadioButtons.png + res/image/control/RatingControl.png + res/image/control/RelativePanel.png + res/image/control/RepeatButton.png + res/image/control/RevealFocus.png + res/image/control/RichEditBox.png + res/image/control/RichTextBlock.png + res/image/control/ScrollViewer.png + res/image/control/SemanticZoom.png + res/image/control/Shape.png + res/image/control/Slider.png + res/image/control/Sound.png + res/image/control/SplitButton.png + res/image/control/SplitView.png + res/image/control/StackPanel.png + res/image/control/StandardUICommand.png + res/image/control/SwipeControl.png + res/image/control/TabView.png + res/image/control/TeachingTip.png + res/image/control/TextBlock.png + res/image/control/TextBox.png + res/image/control/ThemeTransition.png + res/image/control/TimePicker.png + res/image/control/TitleBar.png + res/image/control/ToggleButton.png + res/image/control/ToggleSplitButton.png + res/image/control/ToggleSwitch.png + res/image/control/ToolTip.png + res/image/control/TreeView.png + res/image/control/VariableSizedWrapGrid.png + res/image/control/Viewbox.png + res/image/control/WebView.png + res/image/control/XamlUICommand.png + res/svg/home.svg + res/svg/home_dark.svg + res/image/qrcode_wx.jpg + res/image/qrcode_zfb.jpg + qml/App.qml + qml/component/CodeExpander.qml + qml/component/CustomWindow.qml + qml/global/ItemsFooter.qml + qml/global/ItemsOriginal.qml + qml/global/MainEvent.qml + qml/global/qmldir + qml/page/T_Acrylic.qml + qml/page/T_Awesome.qml + qml/page/T_Badge.qml + qml/page/T_BreadcrumbBar.qml + qml/page/T_Buttons.qml + qml/page/T_CalendarPicker.qml + qml/page/T_Captcha.qml + qml/page/T_Carousel.qml + qml/page/T_Chart.qml + qml/page/T_CheckBox.qml + qml/page/T_ColorPicker.qml + qml/page/T_ComboBox.qml + qml/page/T_DatePicker.qml + qml/page/T_Dialog.qml + qml/page/T_Expander.qml + qml/page/T_FlipView.qml + qml/page/T_Home.qml + qml/page/T_Http.qml + qml/page/T_Image.qml + qml/page/T_InfoBar.qml + qml/page/T_Menu.qml + qml/page/T_MultiWindow.qml + qml/page/T_Pagination.qml + qml/page/T_Pivot.qml + qml/page/T_Progress.qml + qml/page/T_QRCode.qml + qml/page/T_RadioButton.qml + qml/page/T_RatingControl.qml + qml/page/T_Rectangle.qml + qml/page/T_RemoteLoader.qml + qml/page/T_Screenshot.qml + qml/page/T_Settings.qml + qml/page/T_Slider.qml + qml/page/T_StatusView.qml + qml/page/T_TableView.qml + qml/page/T_TabView.qml + qml/page/T_Text.qml + qml/page/T_TextBox.qml + qml/page/T_Theme.qml + qml/page/T_Timeline.qml + qml/page/T_TimePicker.qml + qml/page/T_ToggleSwitch.qml + qml/page/T_Tooltip.qml + qml/page/T_Tour.qml + qml/page/T_TreeView.qml + qml/page/T_Typography.qml + qml/page/T_Watermark.qml + qml/window/AboutWindow.qml + qml/window/HotloadWindow.qml + qml/window/LoginWindow.qml + qml/window/MainWindow.qml + qml/window/SingleInstanceWindow.qml + qml/window/SingleTaskWindow.qml + qml/window/StandardWindow.qml + res/image/bg_scenic.png + res/image/image_1.jpg + + diff --git a/example/src/component/CircularReveal.h b/example/src/component/CircularReveal.h index 9262b044..14352ed2 100644 --- a/example/src/component/CircularReveal.h +++ b/example/src/component/CircularReveal.h @@ -12,7 +12,6 @@ class CircularReveal : public QQuickPaintedItem Q_OBJECT Q_PROPERTY_AUTO(QQuickItem*,target) Q_PROPERTY_AUTO(int,radius) - QML_NAMED_ELEMENT(CircularReveal) public: CircularReveal(QQuickItem* parent = nullptr); void paint(QPainter* painter) override; diff --git a/example/src/component/FileWatcher.h b/example/src/component/FileWatcher.h index 5db1df83..d3bb95cc 100644 --- a/example/src/component/FileWatcher.h +++ b/example/src/component/FileWatcher.h @@ -10,7 +10,6 @@ class FileWatcher : public QObject { Q_OBJECT Q_PROPERTY_AUTO(QString,path); - QML_NAMED_ELEMENT(FileWatcher) public: explicit FileWatcher(QObject *parent = nullptr); Q_SIGNAL void fileChanged(); diff --git a/example/src/main.cpp b/example/src/main.cpp index 9aec80a6..a9562905 100644 --- a/example/src/main.cpp +++ b/example/src/main.cpp @@ -9,6 +9,8 @@ #include #include #include "AppInfo.h" +#include "src/component/CircularReveal.h" +#include "src/component/FileWatcher.h" FRAMELESSHELPER_USE_NAMESPACE @@ -38,6 +40,8 @@ FRAMELESSHELPER_USE_NAMESPACE #ifdef FLUENTUI_BUILD_STATIC_LIB engine.addImportPath("qrc:/"); // 让静态资源可以被QML引擎搜索到 #endif + qmlRegisterType("example", 1, 0, "CircularReveal"); + qmlRegisterType("example", 1, 0, "FileWatcher"); appInfo->init(&engine); const QUrl url(QStringLiteral("qrc:/example/qml/App.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, diff --git a/example/src/stdafx.h b/example/src/stdafx.h index 0fe92d6d..a7581723 100644 --- a/example/src/stdafx.h +++ b/example/src/stdafx.h @@ -1,6 +1,6 @@ -#if defined(_MSC_VER) && (_MSC_VER >= 1600) -#pragma execution_character_set("utf-8") -#endif +//#if defined(_MSC_VER) && (_MSC_VER >= 1600) +//#pragma execution_character_set("utf-8") +//#endif #ifndef STDAFX_H #define STDAFX_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bee3c697..931a4cfe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,8 @@ if(APPLE) set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE) endif() -find_package(Qt6 REQUIRED COMPONENTS Core Quick Qml) +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Qml) if(QT_VERSION VERSION_GREATER_EQUAL "6.3") qt_standard_project_setup() @@ -28,25 +29,34 @@ foreach(filepath ${CPP_FILES}) list(APPEND sources_files ${filename}) endforeach(filepath) -#遍历所有qml文件 -file(GLOB_RECURSE QML_PATHS *.qml) -foreach(filepath ${QML_PATHS}) - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) - list(APPEND qml_files ${filename}) -endforeach(filepath) +if(QT_VERSION VERSION_GREATER_EQUAL "6.2") + #删除fluentuiplugin.cpp与fluentuiplugin.h,这些只要Qt5使用,Qt6不需要 + list(REMOVE_ITEM sources_files fluentuiplugin.h fluentuiplugin.cpp) -#遍历所有资源文件 -file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.js) -foreach(filepath ${RES_PATHS}) - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) - list(APPEND resource_files ${filename}) -endforeach(filepath) + #遍历所有qml文件 + file(GLOB_RECURSE QML_PATHS *.qml) + foreach(filepath ${QML_PATHS}) + if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) + list(APPEND qml_files ${filename}) + endif() + endforeach(filepath) -#修改资源文件导出路径 -foreach(filepath IN LISTS qml_files resource_files) - string(REPLACE "imports/FluentUI/" "" filename ${filepath}) - set_source_files_properties(${filepath} PROPERTIES QT_RESOURCE_ALIAS ${filename}) -endforeach() + #遍历所有资源文件 + file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.js) + foreach(filepath ${RES_PATHS}) + if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) + list(APPEND resource_files ${filename}) + endif() + endforeach(filepath) + + #修改资源文件导出路径 + foreach(filepath IN LISTS qml_files resource_files) + string(REPLACE "Qt${QT_VERSION_MAJOR}/imports/FluentUI/" "" filename ${filepath}) + set_source_files_properties(${filepath} PROPERTIES QT_RESOURCE_ALIAS ${filename}) + endforeach() +endif() #添加qml模块 if (FLUENTUI_BUILD_STATIC_LIB) @@ -54,7 +64,6 @@ if (FLUENTUI_BUILD_STATIC_LIB) else() set(LIB_TYPE "SHARED") endif() -qt_add_library(${PROJECT_NAME} ${LIB_TYPE}) if (FLUENTUI_BUILD_STATIC_LIB) set(PLUGIN_TARGET_NAME "") @@ -73,24 +82,38 @@ if(WIN32) ) endif() -qt_add_qml_module(${PROJECT_NAME} - PLUGIN_TARGET ${PLUGIN_TARGET_NAME} - OUTPUT_DIRECTORY ${FLUENTUI_QML_PLUGIN_DIRECTORY} - VERSION 1.0 - URI "FluentUI" - #修改qmltypes文件名称。默认fluentuiplugin.qmltypes,使用默认名称有时候import FluentUI会爆红,所以修改成plugins.qmltypes - TYPEINFO "plugins.qmltypes" - SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} - QML_FILES ${qml_files} - RESOURCES ${resource_files} - RESOURCE_PREFIX "/" -) +if(QT_VERSION VERSION_GREATER_EQUAL "6.2") + qt_add_library(${PROJECT_NAME} ${LIB_TYPE}) + qt_add_qml_module(${PROJECT_NAME} + PLUGIN_TARGET ${PLUGIN_TARGET_NAME} + OUTPUT_DIRECTORY ${FLUENTUI_QML_PLUGIN_DIRECTORY} + VERSION 1.0 + URI "FluentUI" + #修改qmltypes文件名称。默认fluentuiplugin.qmltypes,使用默认名称有时候import FluentUI 1.0会爆红,所以修改成plugins.qmltypes + TYPEINFO "plugins.qmltypes" + SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} + QML_FILES ${qml_files} + RESOURCES ${resource_files} + RESOURCE_PREFIX "/" + ) +else() + include(QmlPlugin) + add_qmlplugin(${PROJECT_NAME} + URI "FluentUI" + VERSION 1.0 + SOURCES ${sources_files} ${FLUENTUI_VERSION_RC_PATH} resource.qrc + QMLFILES ${qml_files} + QMLDIR imports/FluentUI + BINARY_DIR ${FLUENTUI_QML_PLUGIN_DIRECTORY} + LIBTYPE ${LIB_TYPE} + ) +endif() #链接库 target_link_libraries(${PROJECT_NAME} PUBLIC - Qt::CorePrivate - Qt::QuickPrivate - Qt::QmlPrivate + Qt${QT_VERSION_MAJOR}::CorePrivate + Qt${QT_VERSION_MAJOR}::QuickPrivate + Qt${QT_VERSION_MAJOR}::QmlPrivate ZXing ) diff --git a/src/Def.h b/src/Def.h index c40cf066..a77e8fd2 100644 --- a/src/Def.h +++ b/src/Def.h @@ -15,7 +15,6 @@ Q_ENUM_NS(CaptrueMode) QML_NAMED_ELEMENT(FluScreenshotType) } - namespace FluThemeType { Q_NAMESPACE enum DarkMode { diff --git a/src/FluTextStyle.cpp b/src/FluTextStyle.cpp index 4c6a153f..fa35cc84 100644 --- a/src/FluTextStyle.cpp +++ b/src/FluTextStyle.cpp @@ -1,5 +1,16 @@ #include "FluTextStyle.h" +FluTextStyle* FluTextStyle::m_instance = nullptr; + +FluTextStyle *FluTextStyle::getInstance() +{ + if(FluTextStyle::m_instance == nullptr){ + FluTextStyle::m_instance = new FluTextStyle; + } + return FluTextStyle::m_instance; +} + + FluTextStyle::FluTextStyle(QObject *parent) : QObject{parent} { diff --git a/src/FluTextStyle.h b/src/FluTextStyle.h index de10fa4f..7a8524e0 100644 --- a/src/FluTextStyle.h +++ b/src/FluTextStyle.h @@ -10,7 +10,6 @@ class FluTextStyle : public QObject { Q_OBJECT public: - explicit FluTextStyle(QObject *parent = nullptr); Q_PROPERTY_AUTO(QFont,Caption); Q_PROPERTY_AUTO(QFont,Body); Q_PROPERTY_AUTO(QFont,BodyStrong); @@ -20,8 +19,15 @@ public: Q_PROPERTY_AUTO(QFont,Display); QML_NAMED_ELEMENT(FluTextStyle) QML_SINGLETON -signals: - +private: + explicit FluTextStyle(QObject *parent = nullptr); + static FluTextStyle* m_instance; +public: + static FluTextStyle *getInstance(); + static FluTextStyle *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine) + { + return getInstance(); + } }; #endif // FLUTEXTSTYLE_H diff --git a/src/FluTools.cpp b/src/FluTools.cpp index b7876fab..0decf35d 100644 --- a/src/FluTools.cpp +++ b/src/FluTools.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -123,3 +124,7 @@ QString FluTools::getApplicationDirPath(){ QUrl FluTools::getUrlByFilePath(const QString& path){ return QUrl::fromLocalFile(path); } + +QColor FluTools::colorAlpha(const QColor& color,qreal alpha){ + return QColor(color.red(),color.green(),color.blue(),255*alpha); +} diff --git a/src/FluTools.h b/src/FluTools.h index 5d65fa4b..1da83f5a 100644 --- a/src/FluTools.h +++ b/src/FluTools.h @@ -3,6 +3,7 @@ #include #include +#include #include /** @@ -135,6 +136,13 @@ public: */ Q_INVOKABLE QUrl getUrlByFilePath(const QString& path); + /** + * @brief colorAlpha + * @param color + * @param alpha + * @return + */ + Q_INVOKABLE QColor colorAlpha(const QColor&,qreal alpha); }; diff --git a/src/Qt5/imports/FluentUI/Controls/ColorPicker/ColorPicker.qml b/src/Qt5/imports/FluentUI/Controls/ColorPicker/ColorPicker.qml new file mode 100644 index 00000000..cb43e531 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/ColorPicker/ColorPicker.qml @@ -0,0 +1,233 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import "Content" + +Rectangle { + id: colorPicker + property color colorValue: "transparent" + property bool enableAlphaChannel: true + property bool enableDetails: true + property int colorHandleRadius : 8 + property color _changingColorValue : _hsla(hueSlider.value, sbPicker.saturation,sbPicker.brightness, alphaSlider.value) + on_ChangingColorValueChanged: { + colorValue = _changingColorValue + } + + signal colorChanged(color changedColor) + + implicitWidth: picker.implicitWidth + implicitHeight: picker.implicitHeight + color: "#00000000" + clip: true + + RowLayout { + id: picker + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.rightMargin: colorHandleRadius + anchors.bottom: parent.bottom + spacing: 0 + + + SBPicker { + id: sbPicker + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumWidth: 200 + Layout.minimumHeight: 200 + hueColor: { + var v = 1.0-hueSlider.value + if(0.0 <= v && v < 0.16) { + return Qt.rgba(1.0, 0.0, v/0.16, 1.0) + } else if(0.16 <= v && v < 0.33) { + return Qt.rgba(1.0 - (v-0.16)/0.17, 0.0, 1.0, 1.0) + } else if(0.33 <= v && v < 0.5) { + return Qt.rgba(0.0, ((v-0.33)/0.17), 1.0, 1.0) + } else if(0.5 <= v && v < 0.76) { + return Qt.rgba(0.0, 1.0, 1.0 - (v-0.5)/0.26, 1.0) + } else if(0.76 <= v && v < 0.85) { + return Qt.rgba((v-0.76)/0.09, 1.0, 0.0, 1.0) + } else if(0.85 <= v && v <= 1.0) { + return Qt.rgba(1.0, 1.0 - (v-0.85)/0.15, 0.0, 1.0) + } else { + return "red" + } + } + } + + Item { + id: huePicker + width: 12 + Layout.fillHeight: true + Layout.topMargin: colorHandleRadius + Layout.bottomMargin: colorHandleRadius + + Rectangle { + anchors.fill: parent + id: colorBar + gradient: Gradient { + GradientStop { position: 1.0; color: "#FF0000" } + GradientStop { position: 0.85; color: "#FFFF00" } + GradientStop { position: 0.76; color: "#00FF00" } + GradientStop { position: 0.5; color: "#00FFFF" } + GradientStop { position: 0.33; color: "#0000FF" } + GradientStop { position: 0.16; color: "#FF00FF" } + GradientStop { position: 0.0; color: "#FF0000" } + } + } + ColorSlider { + id: hueSlider; anchors.fill: parent + } + } + + Item { + id: alphaPicker + visible: enableAlphaChannel + width: 12 + Layout.leftMargin: 4 + Layout.fillHeight: true + Layout.topMargin: colorHandleRadius + Layout.bottomMargin: colorHandleRadius + Checkerboard { cellSide: 4 } + Rectangle { + anchors.fill: parent + gradient: Gradient { + GradientStop { position: 0.0; color: "#FF000000" } + GradientStop { position: 1.0; color: "#00000000" } + } + } + ColorSlider { + id: alphaSlider; anchors.fill: parent + } + } + + Column { + id: detailColumn + Layout.leftMargin: 4 + Layout.fillHeight: true + Layout.topMargin: colorHandleRadius + Layout.bottomMargin: colorHandleRadius + Layout.alignment: Qt.AlignRight + visible: enableDetails + + PanelBorder { + width: parent.width + height: 30 + visible: enableAlphaChannel + Checkerboard { cellSide: 5 } + Rectangle { + width: parent.width; height: 30 + border.width: 1; border.color: "black" + color: colorPicker.colorValue + } + } + + Item { + width: parent.width + height: 1 + } + + + PanelBorder { + id: colorEditBox + height: 15; width: parent.width + TextInput { + anchors.fill: parent + color: "#AAAAAA" + selectionColor: "#FF7777AA" + font.pixelSize: 11 + maximumLength: 9 + focus: false + text: _fullColorString(colorPicker.colorValue, alphaSlider.value) + selectByMouse: true + } + } + + Item { + width: parent.width + height: 8 + } + + Column { + width: parent.width + spacing: 1 + NumberBox { caption: "H:"; value: hueSlider.value.toFixed(2) } + NumberBox { caption: "S:"; value: sbPicker.saturation.toFixed(2) } + NumberBox { caption: "B:"; value: sbPicker.brightness.toFixed(2) } + } + + Item { + width: parent.width + height: 8 + } + + Column { + width: parent.width + spacing: 1 + NumberBox { + caption: "R:" + value: _getChannelStr(colorPicker.colorValue, 0) + min: 0; max: 255 + } + NumberBox { + caption: "G:" + value: _getChannelStr(colorPicker.colorValue, 1) + min: 0; max: 255 + } + NumberBox { + caption: "B:" + value: _getChannelStr(colorPicker.colorValue, 2) + min: 0; max: 255 + } + } + + Item{ + width: parent.width + height: 1 + } + + NumberBox { + visible: enableAlphaChannel + caption: "A:"; value: Math.ceil(alphaSlider.value*255) + min: 0; max: 255 + } + } + } + + function _hsla(h, s, b, a) { + var lightness = (2 - s)*b + var satHSL = s*b/((lightness <= 1) ? lightness : 2 - lightness) + lightness /= 2 + + var c = Qt.hsla(h, satHSL, lightness, a) + + colorChanged(c) + + return c + } + + function _rgb(rgb, a) { + + var c = Qt.rgba(rgb.r, rgb.g, rgb.b, a) + + colorChanged(c) + + return c + } + + function _fullColorString(clr, a) { + return "#" + ((Math.ceil(a*255) + 256).toString(16).substr(1, 2) + clr.toString().substr(1, 6)).toUpperCase() + } + + function _getChannelStr(clr, channelIdx) { + return parseInt(clr.toString().substr(channelIdx*2 + 1, 2), 16) + } + + function setColor(color) { + var c = Qt.tint(color, "transparent") + alphaSlider.setValue(c.a) + colorPicker.colorValue = c + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml new file mode 100644 index 00000000..302434ec --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml @@ -0,0 +1,16 @@ +import QtQuick 2.15 +Grid { + id: root + property int cellSide: 5 + anchors.fill: parent + rows: height/cellSide; columns: width/cellSide + clip: true + Repeater { + model: root.columns*root.rows + Rectangle { + width: root.cellSide; height: root.cellSide + color: (index%2 == 0) ? "gray" : "white" + } + } +} + diff --git a/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/ColorSlider.qml b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/ColorSlider.qml new file mode 100644 index 00000000..55157ae5 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/ColorSlider.qml @@ -0,0 +1,44 @@ +import QtQuick 2.15 + +Item { + property int cursorHeight: 7 + property real value: (1 - pickerCursor.y/height) + width: 15 + height: 300 + Item { + id: pickerCursor + width: parent.width + Rectangle { + x: -3; y: -height*0.5 + width: parent.width + 4; height: cursorHeight + border.color: "black"; border.width: 1 + color: "transparent" + Rectangle { + anchors.fill: parent; anchors.margins: 2 + border.color: "white"; border.width: 1 + color: "transparent" + } + } + } + MouseArea { + y: -Math.round(cursorHeight/2) + height: parent.height+cursorHeight + anchors.left: parent.left + preventStealing: true + anchors.right: parent.right + function handleMouse(mouse) { + if (mouse.buttons & Qt.LeftButton) { + pickerCursor.y = Math.max(0, Math.min(height, mouse.y)-cursorHeight) + } + } + onPositionChanged:(mouse)=> { + handleMouse(mouse) + } + onPressed:(mouse)=> handleMouse(mouse) + } + + function setValue(val) { + pickerCursor.y = height * (1 - val) + } +} + diff --git a/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/NumberBox.qml b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/NumberBox.qml new file mode 100644 index 00000000..f4afb9db --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/NumberBox.qml @@ -0,0 +1,39 @@ +import QtQuick 2.15 + +Row { + property alias caption: captionBox.text + property alias value: inputBox.text + property alias min: numValidator.bottom + property alias max: numValidator.top + property alias decimals: numValidator.decimals + + width: 80; + height: 15 + spacing: 4 + //anchors.margins: 2 + Text { + id: captionBox + width: 18; height: parent.height + color: "#AAAAAA" + font.pixelSize: 11; font.bold: true + } + PanelBorder { + height: parent.height + TextInput { + id: inputBox + color: "#AAAAAA"; selectionColor: "#FF7777AA" + font.pixelSize: 11 + maximumLength: 10 + focus: false + readOnly: true + selectByMouse: true + validator: DoubleValidator { + id: numValidator + bottom: 0; top: 1; decimals: 2 + notation: DoubleValidator.StandardNotation + } + } + } +} + + diff --git a/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/PanelBorder.qml b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/PanelBorder.qml new file mode 100644 index 00000000..67de5b5c --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/PanelBorder.qml @@ -0,0 +1,16 @@ +import QtQuick 2.15 + +Rectangle { + width : 40; height : 15; radius: 2 + border.width: 1; border.color: "#FF101010" + color: "transparent" + anchors.leftMargin: 1; anchors.topMargin: 3 + clip: true + Rectangle { + anchors.fill: parent; radius: 2 + anchors.leftMargin: -1; anchors.topMargin: -1 + anchors.rightMargin: 0; anchors.bottomMargin: 0 + border.width: 1; border.color: "#FF525255" + color: "transparent" + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/SBPicker.qml b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/SBPicker.qml new file mode 100644 index 00000000..dfe31b52 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/ColorPicker/Content/SBPicker.qml @@ -0,0 +1,62 @@ +import QtQuick 2.15 + +Item { + id: root + property color hueColor : "blue" + property real saturation : pickerCursor.x/(width-2*r) + property real brightness : 1 - pickerCursor.y/(height-2*r) + property int r : colorHandleRadius + + Rectangle { + x : r + y : r + parent.height - 2 * r + rotation: -90 + transformOrigin: Item.TopLeft + width: parent.height - 2 * r + height: parent.width - 2 * r + gradient: Gradient { + GradientStop { position: 0.0; color: "#FFFFFF" } + GradientStop { position: 1.0; color: root.hueColor } + } + } + Rectangle { + x: r + y: r + width: parent.width - 2 * r + height: parent.height - 2 * r + gradient: Gradient { + GradientStop { position: 1.0; color: "#FF000000" } + GradientStop { position: 0.0; color: "#00000000" } + } + } + Item { + id: pickerCursor + Rectangle { + width: r*2; height: r*2 + radius: r + border.color: "black"; border.width: 2 + color: "transparent" + Rectangle { + anchors.fill: parent; anchors.margins: 2; + border.color: "white"; border.width: 2 + radius: width/2 + color: "transparent" + } + } + } + MouseArea { + anchors.fill: parent + x: r + y: r + preventStealing: true + function handleMouse(mouse) { + if (mouse.buttons & Qt.LeftButton) { + pickerCursor.x = Math.max(0,Math.min(mouse.x - r,width-2*r)); + pickerCursor.y = Math.max(0,Math.min(mouse.y - r,height-2*r)); + } + } + onPositionChanged:(mouse)=> handleMouse(mouse) + onPressed:(mouse)=> handleMouse(mouse) + } +} + diff --git a/src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml b/src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml new file mode 100644 index 00000000..c4100d03 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluAcrylic.qml @@ -0,0 +1,40 @@ +import QtQuick 2.15 +import QtGraphicalEffects 1.15 +import FluentUI 1.0 + +FluItem { + id: control + property color tintColor: Qt.rgba(1,1,1,1) + property real tintOpacity: 0.65 + property real luminosity: 0.01 + property real noiseOpacity : 0.066 + property alias target : effect_source.sourceItem + property int blurRadius: 32 + property rect targetRect : Qt.rect(control.x, control.y, control.width, control.height) + ShaderEffectSource { + id: effect_source + anchors.fill: parent + visible: false + sourceRect: control.targetRect + } + FastBlur { + id:fast_blur + anchors.fill: parent + source: effect_source + radius: control.blurRadius + } + Rectangle{ + anchors.fill: parent + color: Qt.rgba(1, 1, 1, luminosity) + } + Rectangle{ + anchors.fill: parent + color: Qt.rgba(tintColor.r, tintColor.g, tintColor.b, tintOpacity) + } + Image{ + anchors.fill: parent + source: "../Image/noise.png" + fillMode: Image.Tile + opacity: control.noiseOpacity + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluAppBar.qml b/src/Qt5/imports/FluentUI/Controls/FluAppBar.qml new file mode 100644 index 00000000..2720bc43 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluAppBar.qml @@ -0,0 +1,166 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Rectangle{ + property string title: "" + property string darkText : "夜间模式" + property string minimizeText : "最小化" + property string restoreText : "向下还原" + property string maximizeText : "最大化" + property string closeText : "关闭" + property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000" + property color minimizeNormalColor: Qt.rgba(0,0,0,0) + property color minimizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06) + property color maximizeNormalColor: Qt.rgba(0,0,0,0) + property color maximizeHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.1) : Qt.rgba(0,0,0,0.06) + property color closeNormalColor: Qt.rgba(0,0,0,0) + property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1) + property bool showDark: false + property bool showClose: true + property bool showMinimize: true + property bool showMaximize: true + property bool titleVisible: true + property url icon + property int iconSize: 20 + property bool isMac: FluTools.isMacos() + property color borerlessColor : FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property var maxClickListener : function(){ + if (d.win.visibility === Window.Maximized) + d.win.visibility = Window.Windowed + else + d.win.visibility = Window.Maximized + } + property var minClickListener: function(){ + d.win.visibility = Window.Minimized + } + property var closeClickListener : function(){ + d.win.close() + } + property var darkClickListener: function(){ + if(FluTheme.dark){ + FluTheme.darkMode = FluThemeType.Light + }else{ + FluTheme.darkMode = FluThemeType.Dark + } + } + id:control + color: Qt.rgba(0,0,0,0) + height: visible ? 30 : 0 + opacity: visible + z: 65535 + Item{ + id:d + property var win: Window.window + property bool isRestore: win && Window.Maximized === win.visibility + property bool resizable: win && !(win.minimumHeight === win.maximumHeight && win.maximumWidth === win.minimumWidth) + } + TapHandler { + onTapped: if (tapCount === 2) btn_maximize.clicked() + gesturePolicy: TapHandler.DragThreshold + } + DragHandler { + target: null + grabPermissions: TapHandler.CanTakeOverFromAnything + onActiveChanged: if (active) { d.win.startSystemMove(); } + } + Row{ + anchors{ + verticalCenter: parent.verticalCenter + left: isMac ? undefined : parent.left + leftMargin: isMac ? undefined : 10 + horizontalCenter: isMac ? parent.horizontalCenter : undefined + } + spacing: 10 + Image{ + width: control.iconSize + height: control.iconSize + visible: status === Image.Ready ? true : false + source: control.icon + anchors.verticalCenter: parent.verticalCenter + } + FluText { + text: title + visible: control.titleVisible + color:control.textColor + anchors.verticalCenter: parent.verticalCenter + } + } + RowLayout{ + anchors.right: parent.right + height: control.height + spacing: 0 + FluToggleSwitch{ + id:btn_dark + Layout.alignment: Qt.AlignVCenter + Layout.rightMargin: 5 + visible: showDark + text:darkText + textColor:control.textColor + checked: FluTheme.dark + textRight: false + clickListener:()=> darkClickListener(btn_dark) + } + FluIconButton{ + id:btn_minimize + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + iconSource : FluentIcons.ChromeMinimize + Layout.alignment: Qt.AlignVCenter + iconSize: 11 + text:minimizeText + radius: 0 + visible: !isMac && showMinimize + iconColor: control.textColor + color: hovered ? minimizeHoverColor : minimizeNormalColor + onClicked: minClickListener() + } + FluIconButton{ + id:btn_maximize + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize + color: hovered ? maximizeHoverColor : maximizeNormalColor + Layout.alignment: Qt.AlignVCenter + visible: d.resizable && !isMac && showMaximize + radius: 0 + iconColor: control.textColor + text:d.isRestore?restoreText:maximizeText + iconSize: 11 + onClicked: maxClickListener() + } + FluIconButton{ + id:btn_close + iconSource : FluentIcons.ChromeClose + Layout.alignment: Qt.AlignVCenter + text:closeText + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + visible: !isMac && showClose + radius: 0 + iconSize: 10 + iconColor: hovered ? Qt.rgba(1,1,1,1) : control.textColor + color:hovered ? closeHoverColor : closeNormalColor + onClicked: closeClickListener() + } + } + + function minimizeButton(){ + return btn_minimize + } + + function maximizeButton(){ + return btn_maximize + } + + function closeButton(){ + return btn_close + } + + function darkButton(){ + return btn_dark + } + +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluArea.qml b/src/Qt5/imports/FluentUI/Controls/FluArea.qml new file mode 100644 index 00000000..3c826d39 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluArea.qml @@ -0,0 +1,27 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Rectangle { + default property alias content: container.data + property int paddings : 0 + property int leftPadding : 0 + property int rightPadding : 0 + property int topPadding : 0 + property int bottomPadding : 0 + radius: 4 + 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) + 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) + border.width: 1 + implicitHeight: height + implicitWidth: width + Item { + id: container + anchors.fill: parent + anchors.leftMargin: Math.max(paddings,leftPadding) + anchors.rightMargin: Math.max(paddings,rightPadding) + anchors.topMargin: Math.max(paddings,topPadding) + anchors.bottomMargin: Math.max(paddings,bottomPadding) + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml b/src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml new file mode 100644 index 00000000..f5b4ea37 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluAutoSuggestBox.qml @@ -0,0 +1,135 @@ +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluTextBox{ + property var items:[] + property string emptyText: "没有找到结果" + property int autoSuggestBoxReplacement: FluentIcons.Search + signal itemClicked(var data) + signal handleClicked + id:control + Component.onCompleted: { + loadData() + } + Item{ + id:d + property bool flagVisible: true + property var window : Window.window + } + onActiveFocusChanged: { + if(!activeFocus){ + control_popup.visible = false + } + } + Popup{ + id:control_popup + y:control.height + focus: false + padding: 0 + enter: Transition { + NumberAnimation { + property: "opacity" + from:0 + to:1 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + contentItem: FluRectangle{ + radius: [4,4,4,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) + ListView{ + id:list_view + anchors.fill: parent + clip: true + boundsBehavior: ListView.StopAtBounds + ScrollBar.vertical: FluScrollBar {} + header: Item{ + width: control.width + height: visible ? 38 : 0 + visible: list_view.count === 0 + FluText{ + text:emptyText + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 10 + } + } + } + delegate:FluControl{ + id:item_control + height: 38 + width: control.width + onClicked:{ + handleClick(modelData) + } + background: Rectangle{ + FluFocusRectangle{ + visible: item_control.activeFocus + radius:4 + } + 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 + leftPadding: 10 + rightPadding: 10 + verticalAlignment : Qt.AlignVCenter + } + } + } + } + background: Item{ + id:container + implicitWidth: control.width + implicitHeight: 38*Math.min(Math.max(list_view.count,1),8) + } + } + onTextChanged: { + loadData() + if(d.flagVisible){ + var pos = control.mapToItem(null, 0, 0) + if(d.window.height>pos.y+control.height+container.height){ + control_popup.y = control.height + } else if(pos.y>container.height){ + control_popup.y = -container.height + } else { + popup.y = d.window.height-(pos.y+container.height) + } + control_popup.visible = true + } + } + function handleClick(modelData){ + control_popup.visible = false + control.itemClicked(modelData) + updateText(modelData.title) + } + function updateText(text){ + d.flagVisible = false + control.text = text + d.flagVisible = true + } + function loadData(){ + var result = [] + if(items==null){ + list_view.model = result + return + } + items.map(function(item){ + if(item.title.indexOf(control.text)!==-1){ + result.push(item) + } + }) + list_view.model = result + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluBadge.qml b/src/Qt5/imports/FluentUI/Controls/FluBadge.qml new file mode 100644 index 00000000..65d17f14 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluBadge.qml @@ -0,0 +1,79 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Rectangle{ + property bool isDot: false + property bool showZero: false + property int count: 0 + property bool topRight: false + id:control + color:Qt.rgba(255/255,77/255,79/255,1) + width: { + if(isDot) + return 10 + if(count<10){ + return 20 + }else if(count<100){ + return 30 + } + return 40 + } + height: { + if(isDot) + return 10 + return 20 + } + radius: { + if(isDot) + return 5 + return 10 + } + border.width: 1 + border.color: Qt.rgba(1,1,1,1) + anchors{ + right: { + if(parent && topRight) + return parent.right + return undefined + } + top: { + if(parent && topRight) + return parent.top + return undefined + } + rightMargin: { + if(parent && topRight){ + if(isDot){ + return -2.5 + } + return -(control.width/2) + } + return 0 + } + topMargin: { + if(parent && topRight){ + if(isDot){ + return -2.5 + } + return -10 + } + return 0 + } + } + visible: { + if(showZero) + return true + return count!==0 + } + Text{ + anchors.centerIn: parent + color: Qt.rgba(1,1,1,1) + visible: !isDot + text:{ + if(count<100) + return count + return count+"+" + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluBreadcrumbBar.qml b/src/Qt5/imports/FluentUI/Controls/FluBreadcrumbBar.qml new file mode 100644 index 00000000..fba338ff --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluBreadcrumbBar.qml @@ -0,0 +1,92 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Item { + property int textSize: 15 + property string separator: "/" + property var items: [] + property int spacing: 5 + signal clickItem(var model) + id:control + implicitWidth: 300 + height: 30 + onItemsChanged: { + list_model.clear() + list_model.append(items) + } + ListModel{ + id:list_model + } + ListView{ + id:list_view + width: parent.width + height: 30 + orientation: ListView.Horizontal + model: list_model + clip: true + spacing : control.spacing + boundsBehavior: ListView.StopAtBounds + remove: Transition { + NumberAnimation { + properties: "opacity" + from: 1 + to: 0 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + add: Transition { + NumberAnimation { + properties: "opacity" + from: 0 + to: 1 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + delegate: Item{ + height: item_layout.height + width: item_layout.width + RowLayout{ + id:item_layout + spacing: list_view.spacing + height: list_view.height + + FluText{ + text:model.title + Layout.alignment: Qt.AlignVCenter + color: { + if(item_mouse.pressed){ + return FluTheme.dark ? Qt.rgba(150/255,150/255,150/235,1) : Qt.rgba(134/255,134/255,134/235,1) + } + if(item_mouse.containsMouse){ + return FluTheme.dark ? Qt.rgba(204/255,204/255,204/235,1) : Qt.rgba(92/255,92/255,92/235,1) + } + return FluTheme.dark ? Qt.rgba(255/255,255/255,255/235,1) : Qt.rgba(26/255,26/255,26/235,1) + } + MouseArea{ + id:item_mouse + anchors.fill: parent + hoverEnabled: true + onClicked: { + control.clickItem(model) + } + } + } + + FluText{ + text:control.separator + font.pixelSize: control.textSize + visible: list_view.count-1 !== index + Layout.alignment: Qt.AlignVCenter + } + } + } + } + function remove(index,count){ + list_model.remove(index,count) + } + function count(){ + return list_model.count + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluButton.qml b/src/Qt5/imports/FluentUI/Controls/FluButton.qml new file mode 100644 index 00000000..c946d0cd --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluButton.qml @@ -0,0 +1,63 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Button { + property bool disabled: false + property string contentDescription: "" + property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) + property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + property color textColor: { + if(FluTheme.dark){ + if(!enabled){ + return Qt.rgba(131/255,131/255,131/255,1) + } + if(pressed){ + return Qt.rgba(162/255,162/255,162/255,1) + } + return Qt.rgba(1,1,1,1) + }else{ + if(!enabled){ + return Qt.rgba(160/255,160/255,160/255,1) + } + if(pressed){ + return Qt.rgba(96/255,96/255,96/255,1) + } + return Qt.rgba(0,0,0,1) + } + } + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() + id: control + enabled: !disabled + horizontalPadding:12 + font:FluTextStyle.Body + focusPolicy:Qt.TabFocus + background: Rectangle{ + implicitWidth: 28 + implicitHeight: 28 + border.color: FluTheme.dark ? "#505050" : "#DFDFDF" + border.width: 1 + radius: 4 + color:{ + if(!enabled){ + return disableColor + } + return hovered ? hoverColor :normalColor + } + FluFocusRectangle{ + visible: control.activeFocus + radius:4 + } + } + contentItem: FluText { + text: control.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font: control.font + color: control.textColor + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluCalendarPicker.qml b/src/Qt5/imports/FluentUI/Controls/FluCalendarPicker.qml new file mode 100644 index 00000000..48026e8b --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluCalendarPicker.qml @@ -0,0 +1,114 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Rectangle { + property color dividerColor: FluTheme.dark ? Qt.rgba(77/255,77/255,77/255,1) : Qt.rgba(239/255,239/255,239/255,1) + property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + property color normalColor: FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(254/255,254/255,254/255,1) + property string text: "请选择日期" + id:control + color: { + if(mouse_area.containsMouse){ + return hoverColor + } + return normalColor + } + height: 30 + width: 120 + radius: 4 + border.width: 1 + border.color: dividerColor + MouseArea{ + id:mouse_area + hoverEnabled: true + anchors.fill: parent + onClicked: { + popup.showPopup() + } + } + Item{ + id:d + property var window : Window.window + } + FluText{ + id:text_date + anchors{ + left: parent.left + right: parent.right + rightMargin: 30 + top: parent.top + bottom: parent.bottom + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text:control.text + } + FluIcon{ + iconSource: FluentIcons.Calendar + iconSize: 14 + iconColor: text_date.color + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 12 + } + } + Menu{ + id:popup + height: container.height + width: container.width + modal: true + dim:false + enter: Transition { + reversible: true + NumberAnimation { + property: "opacity" + from:0 + to:1 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + exit:Transition { + NumberAnimation { + property: "opacity" + from:1 + to:0 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + contentItem: Item{ + clip: true + FluCalendarView{ + id:container + onDateClicked: + (date)=>{ + popup.close() + var year = date.getFullYear() + var month = date.getMonth() + var day = date.getDate() + text_date.text = year+"-"+(month+1)+"-"+day + } + } + } + background: Item{ + FluShadow{ + radius: 5 + } + } + function showPopup() { + var pos = control.mapToItem(null, 0, 0) + if(d.window.height>pos.y+control.height+container.height){ + popup.y = control.height + } else if(pos.y>container.height){ + popup.y = -container.height + } else { + popup.y = d.window.height-(pos.y+container.height) + } + popup.x = -(popup.width-control.width)/2 + popup.open() + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluCalendarView.qml b/src/Qt5/imports/FluentUI/Controls/FluCalendarView.qml new file mode 100644 index 00000000..cfc1fcf1 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluCalendarView.qml @@ -0,0 +1,435 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Item { + property int displayMode: FluCalendarViewType.Month + property var date: new Date() + property var currentDate : new Date() + property var toDay: new Date() + signal dateClicked(var date) + id:control + width: 280 + height: 325 + Component.onCompleted: { + updateMouth(date) + } + Component{ + id:com_week + Item{ + height: 40 + width: 40 + FluText{ + text:name + anchors.centerIn: parent + } + } + } + Component{ + id:com_year + Button{ + id:item_control + property bool isYear: control.toDay.getFullYear() === date.getFullYear() + height: 70 + width: 70 + onClicked:{ + control.date = date + displayMode = FluCalendarViewType.Year + updateYear(date) + } + background: Item{ + Rectangle{ + width: 60 + height: 60 + radius: 4 + anchors.centerIn: parent + color:{ + if(FluTheme.dark){ + if(item_control.hovered){ + return Qt.rgba(1,1,1,0.05) + } + return Qt.rgba(0,0,0,0) + }else{ + if(item_control.hovered){ + return Qt.rgba(0,0,0,0.05) + } + return Qt.rgba(0,0,0,0) + } + } + } + Rectangle{ + id:backgound_selected + anchors.centerIn: parent + width: 50 + height: 50 + radius: 25 + visible: isYear + color: FluTheme.primaryColor.dark + } + FluText{ + text:date.getFullYear() + anchors.centerIn: parent + color: { + if(isYear){ + return "#FFFFFF" + } + if(isDecade){ + return FluTheme.dark ? "#FFFFFF" : "#1A1A1A" + } + return Qt.rgba(150/255,150/255,150/255,1) + } + } + } + contentItem: Item{} + } + } + Component{ + id:com_month + Button{ + id:item_control + property bool isYear: control.date.getFullYear() === date.getFullYear() + property bool isMonth: control.toDay.getFullYear() === date.getFullYear() && control.toDay.getMonth() === date.getMonth() + height: 70 + width: 70 + onClicked:{ + control.date = date + displayMode = FluCalendarViewType.Month + updateMouth(date) + } + background: Item{ + Rectangle{ + width: 60 + height: 60 + radius: 4 + anchors.centerIn: parent + color:{ + if(FluTheme.dark){ + if(item_control.hovered){ + return Qt.rgba(1,1,1,0.05) + } + return Qt.rgba(0,0,0,0) + }else{ + if(item_control.hovered){ + return Qt.rgba(0,0,0,0.05) + } + return Qt.rgba(0,0,0,0) + } + } + } + Rectangle{ + id:backgound_selected + anchors.centerIn: parent + width: 50 + height: 50 + radius: 25 + visible: isMonth + color: FluTheme.primaryColor.dark + } + FluText{ + text:(date.getMonth()+1)+"月" + anchors.centerIn: parent + color: { + if(isMonth){ + return "#FFFFFF" + } + if(isYear){ + return FluTheme.dark ? "#FFFFFF" : "#1A1A1A" + } + return Qt.rgba(150/255,150/255,150/255,1) + } + } + } + contentItem: Item{} + } + } + Component{ + id:com_day + Button{ + id:item_control + property bool isMonth: control.date.getMonth() === date.getMonth() + property bool isDay: control.currentDate.getFullYear() === date.getFullYear() && control.currentDate.getMonth() === date.getMonth() && control.currentDate.getDate() === date.getDate() + property bool isToDay: control.toDay.getFullYear() === date.getFullYear() && control.toDay.getMonth() === date.getMonth() && control.toDay.getDate() === date.getDate() + height: 40 + width: 40 + onClicked: { + currentDate = date + control.dateClicked(date) + } + background: Item{ + Rectangle{ + width: 36 + height: 36 + radius: 4 + anchors.centerIn: parent + color:{ + if(FluTheme.dark){ + if(item_control.hovered){ + return Qt.rgba(1,1,1,0.05) + } + return Qt.rgba(0,0,0,0) + }else{ + if(item_control.hovered){ + return Qt.rgba(0,0,0,0.05) + } + return Qt.rgba(0,0,0,0) + } + } + } + Rectangle{ + id:backgound_today + anchors.centerIn: parent + width: 36 + height: 36 + radius: 18 + color:"#00000000" + visible: isDay + border.color: FluTheme.primaryColor.dark + border.width: 1 + } + Rectangle{ + id:backgound_selected + anchors.centerIn: parent + width: 30 + height: 30 + radius: 15 + visible: isToDay + color: FluTheme.primaryColor.dark + } + FluText{ + text:date.getDate() + anchors.centerIn: parent + color: { + if(isToDay){ + return "#FFFFFF" + } + if(isMonth){ + return FluTheme.dark ? "#FFFFFF" : "#1A1A1A" + } + return Qt.rgba(150/255,150/255,150/255,1) + } + } + } + contentItem: Item{} + } + } + FluArea{ + anchors.fill: parent + radius: 5 + FluShadow{ + radius: 5 + } + Rectangle{ + id:layout_divider + height: 1 + width: parent.width + color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1) + anchors{ + top: parent.top + topMargin: 44 + } + } + Item{ + id:layout_top + anchors{ + left: parent.left + right: parent.right + top: parent.top + bottom: layout_divider.top + } + FluTextButton{ + id:title + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 14 + } + disabled: displayMode === FluCalendarViewType.Decade + onClicked:{ + if(displayMode === FluCalendarViewType.Month){ + displayMode = FluCalendarViewType.Year + updateYear(date) + }else if(displayMode === FluCalendarViewType.Year){ + displayMode = FluCalendarViewType.Decade + updateDecade(date) + } + } + } + FluIconButton{ + id:icon_up + iconSource: FluentIcons.CaretUpSolid8 + iconSize: 10 + anchors{ + verticalCenter: parent.verticalCenter + right: icon_down.left + rightMargin: 14 + } + onClicked: { + var year = date.getFullYear() + var month = date.getMonth() + if(displayMode === FluCalendarViewType.Month){ + var lastMonthYear = year; + var lastMonthMonth = month - 1 + if (month === 0) { + lastMonthYear = year - 1 + lastMonthMonth = 11 + } + date = new Date(lastMonthYear,lastMonthMonth,1) + updateMouth(date) + }else if(displayMode === FluCalendarViewType.Year){ + date = new Date(year-1,month,1) + updateYear(date) + }else if(displayMode === FluCalendarViewType.Decade){ + date = new Date(Math.floor(year / 10) * 10-10,month,1) + updateDecade(date) + } + } + } + FluIconButton{ + id:icon_down + iconSource: FluentIcons.CaretDownSolid8 + iconSize: 10 + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 8 + } + onClicked: { + var year = date.getFullYear() + var month = date.getMonth() + if(displayMode === FluCalendarViewType.Month){ + var nextMonthYear = year + var nextMonth = month + 1 + if (month === 11) { + nextMonthYear = year + 1 + nextMonth = 0 + } + date = new Date(nextMonthYear,nextMonth,1) + updateMouth(date) + }else if(displayMode === FluCalendarViewType.Year){ + date = new Date(year+1,month,1) + updateYear(date) + }else if(displayMode === FluCalendarViewType.Decade){ + date = new Date(Math.floor(year / 10) * 10+10,month,1) + updateDecade(date) + } + } + } + } + ListModel { + id:list_model + } + Item{ + id:layout_bottom + anchors{ + left: parent.left + right: parent.right + top: layout_divider.bottom + bottom: parent.bottom + } + GridView{ + model: list_model + anchors.fill: parent + cellHeight: displayMode === FluCalendarViewType.Month ? 40 : 70 + cellWidth: displayMode === FluCalendarViewType.Month ? 40 : 70 + clip: true + boundsBehavior:Flickable.StopAtBounds + delegate: Loader{ + property var modelData : model + property var name : model.name + property var date : model.date + property var isDecade: { + return model.isDecade + } + sourceComponent: { + if(model.type === 0){ + return com_week + } + if(model.type === 1){ + return com_day + } + if(model.type === 2){ + return com_month + } + if(model.type === 3){ + return com_year + } + return com_day + } + } + } + } + } + function createItemWeek(name){ + return {type:0,date:new Date(),name:name,isDecade:false} + } + function createItemDay(date){ + return {type:1,date:date,name:"",isDecade:false} + } + function createItemMonth(date){ + return {type:2,date:date,name:"",isDecade:false} + } + function createItemYear(date,isDecade){ + return {type:3,date:date,name:"",isDecade:isDecade} + } + function updateDecade(date){ + list_model.clear() + var year = date.getFullYear() + const decadeStart = Math.floor(year / 10) * 10; + for(var i = decadeStart ; i< decadeStart+10 ; i++){ + list_model.append(createItemYear(new Date(i,0,1),true)); + } + for(var j = decadeStart+10 ; j< decadeStart+16 ; j++){ + list_model.append(createItemYear(new Date(j,0,1),false)); + } + title.text = decadeStart+"-"+(decadeStart+10) + } + function updateYear(date){ + list_model.clear() + var year = date.getFullYear() + for(var i = 0 ; i< 12 ; i++){ + list_model.append(createItemMonth(new Date(year,i))); + } + for(var j = 0 ; j< 4 ; j++){ + list_model.append(createItemMonth(new Date(year+1,j))); + } + title.text = year+"年" + } + function updateMouth(date){ + list_model.clear() + list_model.append([createItemWeek("一"),createItemWeek("二"),createItemWeek("三"),createItemWeek("四"),createItemWeek("五"),createItemWeek("六"),createItemWeek("日")]) + var year = date.getFullYear() + var month = date.getMonth() + var day = date.getDate() + var firstDayOfMonth = new Date(year, month, 1) + var dayOfWeek = firstDayOfMonth.getDay() + var headerSize = (dayOfWeek===0?7:dayOfWeek)-1 + if(headerSize!==0){ + var lastMonthYear = year; + var lastMonthMonth = month - 1 + if (month === 0) { + lastMonthYear = year - 1 + lastMonthMonth = 11 + } + var lastMonthDays = new Date(lastMonthYear, lastMonthMonth+1, 0).getDate() + for (var i = headerSize-1; i >= 0; i--) { + list_model.append(createItemDay(new Date(lastMonthYear, lastMonthMonth,lastMonthDays-i))) + } + } + const lastDayOfMonth = new Date(year, month+1, 0).getDate() + for (let day = 1; day <= lastDayOfMonth; day++) { + list_model.append(createItemDay(new Date(year, month,day))) + } + var footerSize = 49-list_model.count + var nextMonthYear = year + var nextMonth = month + 1 + if (month === 11) { + nextMonthYear = year + 1 + nextMonth = 0 + } + const nextDayOfMonth = new Date(nextMonthYear, nextMonth+1, 0).getDate() + for (let j = 1; j <= footerSize; j++) { + list_model.append(createItemDay(new Date(nextMonthYear, nextMonth,j))) + } + title.text = year+"年"+(month+1)+"月" + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluCarousel.qml b/src/Qt5/imports/FluentUI/Controls/FluCarousel.qml new file mode 100644 index 00000000..0296c04c --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluCarousel.qml @@ -0,0 +1,201 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluItem { + property int loopTime: 2000 + property var model + property Component delegate + property bool showIndicator: true + property int indicatorGravity : Qt.AlignBottom | Qt.AlignHCenter + property int indicatorMarginLeft: 0 + property int indicatorMarginRight: 0 + property int indicatorMarginTop: 0 + property int indicatorMarginBottom: 20 + property int indicatorSpacing: 10 + property alias indicatorAnchors: layout_indicator.anchors + property Component indicatorDelegate : com_indicator + id:control + width: 400 + height: 300 + ListModel{ + id:content_model + } + QtObject{ + id:d + property bool flagXChanged: true + function setData(data){ + if(!data){ + return + } + content_model.clear() + content_model.append(data[data.length-1]) + content_model.append(data) + content_model.append(data[0]) + list_view.highlightMoveDuration = 0 + list_view.currentIndex = 1 + list_view.highlightMoveDuration = 250 + timer_run.restart() + } + } + ListView{ + id:list_view + anchors.fill: parent + snapMode: ListView.SnapOneItem + clip: true + boundsBehavior: ListView.StopAtBounds + model:content_model + maximumFlickVelocity: 4 * (list_view.orientation === Qt.Horizontal ? width : height) + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + Component.onCompleted: { + d.setData(control.model) + } + Connections{ + target: control + function onModelChanged(){ + d.setData(control.model) + } + } + orientation : ListView.Horizontal + delegate: Item{ + id:item_control + width: ListView.view.width + height: ListView.view.height + property int displayIndex: { + if(index === 0) + return content_model.count-3 + if(index === content_model.count-1) + return 0 + return index-1 + } + Loader{ + property int displayIndex : item_control.displayIndex + property var model: list_view.model.get(index) + anchors.fill: parent + sourceComponent: { + if(model){ + return control.delegate + } + return undefined + } + } + } + onMovementEnded:{ + currentIndex = list_view.contentX/list_view.width + if(currentIndex === 0){ + currentIndex = list_view.count-2 + }else if(currentIndex === list_view.count-1){ + currentIndex = 1 + } + d.flagXChanged = false + timer_run.restart() + } + onMovementStarted: { + d.flagXChanged = true + timer_run.stop() + } + onContentXChanged: { + if(d.flagXChanged){ + var maxX = Math.min(list_view.width*(currentIndex+1),list_view.count*list_view.width) + var minY = Math.max(0,(list_view.width*(currentIndex-1))) + if(contentX>=maxX){ + contentX = maxX + } + if(contentX<=minY){ + contentX = minY + } + } + } + } + Component{ + id:com_indicator + Rectangle{ + width: 8 + height: 8 + radius: 4 + FluShadow{ + radius: 4 + } + scale: checked ? 1.2 : 1 + color: checked ? FluTheme.primaryColor.dark : Qt.rgba(1,1,1,0.7) + border.width: mouse_item.containsMouse ? 1 : 0 + border.color: FluTheme.primaryColor.dark + MouseArea{ + id:mouse_item + hoverEnabled: true + anchors.fill: parent + onClicked: { + changedIndex(realIndex) + } + } + } + } + Row{ + id:layout_indicator + spacing: control.indicatorSpacing + anchors{ + horizontalCenter:(indicatorGravity & Qt.AlignHCenter) ? parent.horizontalCenter : undefined + verticalCenter: (indicatorGravity & Qt.AlignVCenter) ? parent.verticalCenter : undefined + bottom: (indicatorGravity & Qt.AlignBottom) ? parent.bottom : undefined + top: (indicatorGravity & Qt.AlignTop) ? parent.top : undefined + left: (indicatorGravity & Qt.AlignLeft) ? parent.left : undefined + right: (indicatorGravity & Qt.AlignRight) ? parent.right : undefined + bottomMargin: control.indicatorMarginBottom + leftMargin: control.indicatorMarginBottom + rightMargin: control.indicatorMarginBottom + topMargin: control.indicatorMarginBottom + } + visible: showIndicator + Repeater{ + id:repeater_indicator + model: list_view.count + Loader{ + property int displayIndex: { + if(index === 0) + return list_view.count-3 + if(index === list_view.count-1) + return 0 + return index-1 + } + property int realIndex: index + property bool checked: list_view.currentIndex === index + sourceComponent: { + if(index===0 || index===list_view.count-1) + return undefined + return control.indicatorDelegate + } + } + } + } + Timer{ + id:timer_anim + interval: 250 + onTriggered: { + list_view.highlightMoveDuration = 0 + if(list_view.currentIndex === list_view.count-1){ + list_view.currentIndex = 1 + } + } + } + Timer{ + id:timer_run + interval: control.loopTime + repeat: true + onTriggered: { + list_view.highlightMoveDuration = 250 + list_view.currentIndex = list_view.currentIndex+1 + timer_anim.start() + } + } + + function changedIndex(index){ + d.flagXChanged = true + timer_run.stop() + list_view.currentIndex = index + d.flagXChanged = false + timer_run.restart() + } + +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluChart.qml b/src/Qt5/imports/FluentUI/Controls/FluChart.qml new file mode 100644 index 00000000..7d15aa0b --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluChart.qml @@ -0,0 +1,122 @@ +import QtQuick 2.15 +import "./../JS/Chart.js" as Chart + +Canvas { + id: control + + property var jsChart: undefined + property string chartType + property var chartData + property var chartOptions + property double chartAnimationProgress: 0.1 + property int animationEasingType: Easing.InOutExpo + property double animationDuration: 500 + property var memorizedContext + property var memorizedData + property var memorizedOptions + property alias animationRunning: chartAnimator.running + signal animationFinished() + function animateToNewData() + { + chartAnimationProgress = 0.1; + jsChart.update(); + chartAnimator.restart(); + } + MouseArea { + id: event + anchors.fill: control + hoverEnabled: true + enabled: true + property var handler: undefined + property QtObject mouseEvent: QtObject { + property int left: 0 + property int top: 0 + property int x: 0 + property int y: 0 + property int clientX: 0 + property int clientY: 0 + property string type: "" + property var target + } + function submitEvent(mouse, type) { + mouseEvent.type = type + mouseEvent.clientX = mouse ? mouse.x : 0; + mouseEvent.clientY = mouse ? mouse.y : 0; + mouseEvent.x = mouse ? mouse.x : 0; + mouseEvent.y = mouse ? mouse.y : 0; + mouseEvent.left = 0; + mouseEvent.top = 0; + mouseEvent.target = control; + + if(handler) { + handler(mouseEvent); + } + + control.requestPaint(); + } + onClicked:(mouse)=> { + submitEvent(mouse, "click"); + } + onPositionChanged:(mouse)=> { + submitEvent(mouse, "mousemove"); + } + onExited: { + submitEvent(undefined, "mouseout"); + } + onEntered: { + submitEvent(undefined, "mouseenter"); + } + onPressed:(mouse)=> { + submitEvent(mouse, "mousedown"); + } + onReleased:(mouse)=> { + submitEvent(mouse, "mouseup"); + } + } + PropertyAnimation { + id: chartAnimator + target: control + property: "chartAnimationProgress" + alwaysRunToEnd: true + to: 1 + duration: control.animationDuration + easing.type: control.animationEasingType + onFinished: { + control.animationFinished(); + } + } + onChartAnimationProgressChanged: { + control.requestPaint(); + } + onPaint: { + if(control.getContext('2d') !== null && memorizedContext !== control.getContext('2d') || memorizedData !== control.chartData || memorizedOptions !== control.chartOptions) { + var ctx = control.getContext('2d'); + + jsChart = Chart.build(ctx, { + type: control.chartType, + data: control.chartData, + options: control.chartOptions + }); + + memorizedData = control.chartData ; + memorizedContext = control.getContext('2d'); + memorizedOptions = control.chartOptions; + + control.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;}); + + chartAnimator.start(); + } + + jsChart.draw(chartAnimationProgress); + } + onWidthChanged: { + if(jsChart) { + jsChart.resize(); + } + } + onHeightChanged: { + if(jsChart) { + jsChart.resize(); + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml b/src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml new file mode 100644 index 00000000..6ced72a0 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluCheckBox.qml @@ -0,0 +1,120 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Button { + property bool disabled: false + property string contentDescription: "" + property color borderNormalColor: FluTheme.dark ? Qt.rgba(160/255,160/255,160/255,1) : Qt.rgba(136/255,136/255,136/255,1) + property color bordercheckedColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property color borderHoverColor: FluTheme.dark ? Qt.rgba(167/255,167/255,167/255,1) : Qt.rgba(135/255,135/255,135/255,1) + property color borderDisableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) + property color borderPressedColor: FluTheme.dark ? Qt.rgba(90/255,90/255,90/255,1) : Qt.rgba(191/255,191/255,191/255,1) + property color normalColor: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(247/255,247/255,247/255,1) + property color checkedColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property color hoverColor: FluTheme.dark ? Qt.rgba(72/255,72/255,72/255,1) : Qt.rgba(236/255,236/255,236/255,1) + property color checkedHoverColor: FluTheme.dark ? Qt.darker(checkedColor,1.15) : Qt.lighter(checkedColor,1.15) + property color checkedPreesedColor: FluTheme.dark ? Qt.darker(checkedColor,1.3) : Qt.lighter(checkedColor,1.3) + property color checkedDisableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(253/255,253/255,253/255,1) + property real size: 18 + property alias textColor: btn_text.textColor + property bool textRight: true + property real textSpacing: 6 + property var clickListener : function(){ + checked = !checked + } + id:control + enabled: !disabled + onClicked: clickListener() + onCheckableChanged: { + if(checkable){ + checkable = false + } + } + background: Item{ + FluFocusRectangle{ + radius: 4 + visible: control.activeFocus + } + } + horizontalPadding:2 + verticalPadding: 2 + Accessible.role: Accessible.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 + Rectangle{ + width: control.size + height: control.size + radius: 4 + border.color: { + if(!enabled){ + return borderDisableColor + } + if(checked){ + return bordercheckedColor + } + if(pressed){ + return borderPressedColor + } + if(hovered){ + return borderHoverColor + } + return borderNormalColor + } + border.width: 1 + color: { + if(checked){ + if(!enabled){ + return checkedDisableColor + } + if(pressed){ + return checkedPreesedColor + } + if(hovered){ + return checkedHoverColor + } + return checkedColor + } + if(!enabled){ + return disableColor + } + if(hovered){ + return hoverColor + } + return normalColor + } + Behavior on color { + enabled: FluTheme.enableAnimation + ColorAnimation{ + duration: 83 + } + } + FluIcon { + anchors.centerIn: parent + iconSource: FluentIcons.AcceptMedium + iconSize: 15 + visible: checked + iconColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) + Behavior on visible { + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 83 + } + } + } + } + FluText{ + id:btn_text + text: control.text + Layout.alignment: Qt.AlignVCenter + visible: text !== "" + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluColorPicker.qml b/src/Qt5/imports/FluentUI/Controls/FluColorPicker.qml new file mode 100644 index 00000000..06289074 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluColorPicker.qml @@ -0,0 +1,93 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Button{ + id:control + width: 36 + height: 36 + implicitWidth: width + implicitHeight: height + property alias colorValue: container.colorValue + background: + Rectangle{ + id:layout_color + radius: 5 + color:"#00000000" + border.color: { + if(hovered) + return FluTheme.primaryColor.light + return FluTheme.dark ? Qt.rgba(100/255,100/255,100/255,1) : Qt.rgba(200/255,200/255,200/255,1) + } + border.width: 1 + + Rectangle{ + anchors.fill: parent + anchors.margins: 4 + radius: 5 + color: container.colorValue + } + + } + Item{ + id: d + property var window : Window.window + } + contentItem: Item{} + onClicked: { + popup.showPopup() + } + Menu{ + id:popup + modal: true + dim:false + height: container.height + width: container.width + contentItem: Item{ + clip: true + FluColorView{ + id:container + } + } + background:Item{ + FluShadow{ + radius: 5 + } + } + enter: Transition { + reversible: true + NumberAnimation { + property: "opacity" + from:0 + to:1 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + + exit:Transition { + NumberAnimation { + property: "opacity" + from:1 + to:0 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + function showPopup() { + var pos = control.mapToItem(null, 0, 0) + if(d.window.height>pos.y+control.height+container.height){ + popup.y = control.height + } else if(pos.y>container.height){ + popup.y = -container.height + } else { + popup.y = d.window.height-(pos.y+container.height) + } + popup.x = -(popup.width-control.width)/2 + popup.open() + } + } + function setColor(color){ + container.setColor(color) + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluColorView.qml b/src/Qt5/imports/FluentUI/Controls/FluColorView.qml new file mode 100644 index 00000000..d3b023c2 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluColorView.qml @@ -0,0 +1,24 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 +import "ColorPicker" + +Item { + property alias colorValue: color_picker.colorValue + width: color_picker.width+10 + height: color_picker.height + FluArea{ + anchors.fill: parent + radius: 5 + FluShadow{ + radius: 5 + } + ColorPicker{ + id:color_picker + } + } + function setColor(color) { + color_picker.setColor(color) + } +} + diff --git a/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml b/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml new file mode 100644 index 00000000..bbe3fdfd --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluComboBox.qml @@ -0,0 +1,137 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 +import QtQuick.Templates 2.15 as T + +ComboBox { + id: control + signal commit(string text) + property bool disabled: false + property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) + property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + font: FluTextStyle.Body + leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing) + rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing) + enabled: !disabled + delegate: FluItemDelegate { + width: ListView.view.width + text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData + palette.text: control.palette.text + font: control.font + palette.highlightedText: control.palette.highlightedText + highlighted: control.highlightedIndex === index + hoverEnabled: control.hoverEnabled + } + focusPolicy:Qt.TabFocus + indicator: FluIcon { + x: control.mirrored ? control.padding : control.width - width - control.padding + y: control.topPadding + (control.availableHeight - height) / 2 + width: 28 + iconSource:FluentIcons.ChevronDown + iconSize: 15 + opacity: enabled ? 1 : 0.3 + } + contentItem: T.TextField { + property bool disabled: !control.editable + leftPadding: !control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1 + rightPadding: control.mirrored ? 10 : control.editable && activeFocus ? 3 : 1 + topPadding: 6 - control.padding + bottomPadding: 6 - control.padding + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + selectionColor: FluTools.colorAlpha(FluTheme.primaryColor.lightest,0.6) + selectedTextColor: color + text: control.editable ? control.editText : control.displayText + enabled: control.editable + autoScroll: control.editable + font:control.font + readOnly: control.down + color: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + inputMethodHints: control.inputMethodHints + validator: control.validator + selectByMouse: true + verticalAlignment: Text.AlignVCenter + leftInset:1 + topInset:1 + bottomInset:1 + rightInset:1 + background: FluTextBoxBackground{ + border.width: 0 + inputItem: contentItem + } + Component.onCompleted: { + forceActiveFocus() + } + Keys.onEnterPressed: (event)=> handleCommit(event) + Keys.onReturnPressed:(event)=> handleCommit(event) + function handleCommit(event){ + control.commit(control.editText) + } + } + + background: Rectangle { + implicitWidth: 140 + implicitHeight: 32 + border.color: FluTheme.dark ? "#505050" : "#DFDFDF" + border.width: 1 + visible: !control.flat || control.down + radius: 4 + FluFocusRectangle{ + visible: control.visualFocus + radius:4 + anchors.margins: -2 + } + color:{ + if(disabled){ + return disableColor + } + return hovered ? hoverColor :normalColor + } + } + + popup: T.Popup { + y: control.height + width: control.width + height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin) + topMargin: 6 + bottomMargin: 6 + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: control.delegateModel + currentIndex: control.highlightedIndex + highlightMoveDuration: 0 + T.ScrollIndicator.vertical: ScrollIndicator { } + } + enter: Transition { + NumberAnimation { + property: "opacity" + from:0 + to:1 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + exit:Transition { + NumberAnimation { + property: "opacity" + from:1 + to:0 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + background:Rectangle{ + color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(249/255,249/255,249/255,1) + 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) + border.width: 1 + radius: 5 + FluShadow{ + radius: 5 + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluContentDialog.qml b/src/Qt5/imports/FluentUI/Controls/FluContentDialog.qml new file mode 100644 index 00000000..44ab05ed --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluContentDialog.qml @@ -0,0 +1,129 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +FluPopup { + id: popup + property string title: "Title" + property string message: "Message" + property string neutralText: "Neutral" + property string negativeText: "Negative" + property string positiveText: "Positive" + property int delayTime: 100 + signal neutralClicked + signal negativeClicked + signal positiveClicked + property int buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton + focus: true + implicitWidth: 400 + implicitHeight: text_title.height + text_message.height + layout_actions.height + Rectangle { + id:layout_content + anchors.fill: parent + color: 'transparent' + radius:5 + FluText{ + id:text_title + font: FluTextStyle.TitleLarge + text:title + topPadding: 20 + leftPadding: 20 + rightPadding: 20 + wrapMode: Text.WrapAnywhere + anchors{ + top:parent.top + left: parent.left + right: parent.right + } + } + FluText{ + id:text_message + font: FluTextStyle.Body + wrapMode: Text.WrapAnywhere + text:message + topPadding: 14 + leftPadding: 20 + rightPadding: 20 + bottomPadding: 14 + anchors{ + top:text_title.bottom + left: parent.left + right: parent.right + } + } + Rectangle{ + id:layout_actions + height: 68 + radius: 5 + color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) + anchors{ + top:text_message.bottom + left: parent.left + right: parent.right + } + RowLayout{ + anchors + { + centerIn: parent + margins: spacing + fill: parent + } + spacing: 15 + FluButton{ + id:neutral_btn + Layout.fillWidth: true + Layout.fillHeight: true + visible: popup.buttonFlags&FluContentDialogType.NeutralButton + text: neutralText + onClicked: { + popup.close() + timer_delay.targetFlags = FluContentDialogType.NeutralButton + timer_delay.restart() + } + } + FluButton{ + id:negative_btn + Layout.fillWidth: true + Layout.fillHeight: true + visible: popup.buttonFlags&FluContentDialogType.NegativeButton + text: negativeText + onClicked: { + popup.close() + timer_delay.targetFlags = FluContentDialogType.NegativeButton + timer_delay.restart() + } + } + FluFilledButton{ + id:positive_btn + Layout.fillWidth: true + Layout.fillHeight: true + visible: popup.buttonFlags&FluContentDialogType.PositiveButton + text: positiveText + onClicked: { + popup.close() + timer_delay.targetFlags = FluContentDialogType.PositiveButton + timer_delay.restart() + } + } + } + } + } + Timer{ + property int targetFlags + id:timer_delay + interval: popup.delayTime + onTriggered: { + if(targetFlags === FluContentDialogType.NegativeButton){ + negativeClicked() + } + if(targetFlags === FluContentDialogType.NeutralButton){ + neutralClicked() + } + if(targetFlags === FluContentDialogType.PositiveButton){ + positiveClicked() + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluContentPage.qml b/src/Qt5/imports/FluentUI/Controls/FluContentPage.qml new file mode 100644 index 00000000..05f48a68 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluContentPage.qml @@ -0,0 +1,60 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluPage { + property alias title: text_title.text + default property alias content: container.data + property int leftPadding: 10 + property int topPadding: 0 + property int rightPadding: 10 + property int bottomPadding: 10 + property alias color: status_view.color + property alias statusMode: status_view.statusMode + property alias loadingText: status_view.loadingText + property alias emptyText:status_view.emptyText + property alias errorText:status_view.errorText + property alias errorButtonText:status_view.errorButtonText + property alias loadingItem :status_view.loadingItem + property alias emptyItem : status_view.emptyItem + property alias errorItem :status_view.errorItem + signal errorClicked + + id:control + FluText{ + id:text_title + visible: text !== "" + height: visible ? contentHeight : 0 + font: FluTextStyle.Title + anchors{ + top: parent.top + topMargin: control.topPadding + left: parent.left + right: parent.right + leftMargin: control.leftPadding + rightMargin: control.rightPadding + } + } + FluStatusView{ + id:status_view + color: "#00000000" + statusMode: FluStatusViewType.Success + onErrorClicked: control.errorClicked() + anchors{ + left: parent.left + right: parent.right + top: text_title.bottom + bottom: parent.bottom + leftMargin: control.leftPadding + rightMargin: control.rightPadding + bottomMargin: control.bottomPadding + } + Item{ + clip: true + id:container + anchors.fill: parent + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluControl.qml b/src/Qt5/imports/FluentUI/Controls/FluControl.qml new file mode 100644 index 00000000..c8404b92 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluControl.qml @@ -0,0 +1,27 @@ +import QtQuick 2.15 +import FluentUI 1.0 +import QtQuick.Templates 2.15 as T + +T.Button { + id: control + property string contentDescription: "" + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + padding: 0 + horizontalPadding: 0 + spacing: 0 + contentItem: Item{} + focusPolicy:Qt.TabFocus + background: Item{ + FluFocusRectangle{ + visible: control.activeFocus + radius:8 + } + } + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluCopyableText.qml b/src/Qt5/imports/FluentUI/Controls/FluCopyableText.qml new file mode 100644 index 00000000..b7e6861e --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluCopyableText.qml @@ -0,0 +1,35 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +TextEdit { + property color textColor: FluTheme.dark ? FluColors.White : FluColors.Grey220 + id:control + color: textColor + readOnly: true + activeFocusOnTab: false + activeFocusOnPress: false + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + padding: 0 + leftPadding: 0 + rightPadding: 0 + topPadding: 0 + selectByMouse: true + selectedTextColor: color + bottomPadding: 0 + selectionColor: FluTools.colorAlpha(FluTheme.primaryColor.lightest,0.6) + font:FluTextStyle.Body + onSelectedTextChanged: { + control.forceActiveFocus() + } + MouseArea{ + anchors.fill: parent + cursorShape: Qt.IBeamCursor + acceptedButtons: Qt.RightButton + onClicked: control.echoMode !== TextInput.Password && menu.popup() + } + FluTextBoxMenu{ + id:menu + inputItem: control + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml b/src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml new file mode 100644 index 00000000..d17e12ed --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluDatePicker.qml @@ -0,0 +1,401 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Rectangle { + property color dividerColor: FluTheme.dark ? Qt.rgba(77/255,77/255,77/255,1) : Qt.rgba(239/255,239/255,239/255,1) + property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + property color normalColor: FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(254/255,254/255,254/255,1) + property bool showYear: true + property var current + id:control + color: { + if(mouse_area.containsMouse){ + return hoverColor + } + return normalColor + } + height: 30 + width: 300 + radius: 4 + border.width: 1 + border.color: dividerColor + Item{ + id:d + property var window: Window.window + property bool changeFlag: true + property var rowData: ["","",""] + visible: false + } + MouseArea{ + id:mouse_area + hoverEnabled: true + anchors.fill: parent + onClicked: { + popup.showPopup() + } + } + Rectangle{ + id:divider_1 + width: 1 + x: parent.width/3 + height: parent.height + color: dividerColor + visible: showYear + } + Rectangle{ + id:divider_2 + width: 1 + x: showYear ? parent.width*2/3 : parent.width/2 + height: parent.height + color: dividerColor + } + FluText{ + id:text_year + anchors{ + left: parent.left + right: divider_1.left + top: parent.top + bottom: parent.bottom + } + visible: showYear + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text:"年" + } + FluText{ + id:text_month + anchors{ + left: showYear ? divider_1.right : parent.left + right: divider_2.left + top: parent.top + bottom: parent.bottom + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text:"月" + } + FluText{ + id:text_day + anchors{ + left: divider_2.right + right: parent.right + top: parent.top + bottom: parent.bottom + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text:"日" + } + Menu{ + id:popup + modal: true + width: container.width + height: container.height + dim:false + enter: Transition { + reversible: true + NumberAnimation { + property: "opacity" + from:0 + to:1 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + exit:Transition { + NumberAnimation { + property: "opacity" + from:1 + to:0 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + background:Item{ + FluShadow{ + radius: 4 + } + } + contentItem: Item{ + clip: true + Rectangle{ + id:container + radius: 4 + width: 300 + height: 340 + color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1) + MouseArea{ + anchors.fill: parent + } + FluShadow{ + radius: 4 + } + RowLayout{ + id:layout_content + spacing: 0 + width: parent.width + height: 300 + Component{ + id:list_delegate + Item{ + height:38 + width:getListView().width + function getListView(){ + if(type === 0) + return list_view_1 + if(type === 1) + return list_view_2 + if(type === 2) + return list_view_3 + } + Rectangle{ + anchors.fill: parent + anchors.topMargin: 2 + anchors.bottomMargin: 2 + anchors.leftMargin: 5 + anchors.rightMargin: 5 + color: { + if(getListView().currentIndex === position){ + if(FluTheme.dark){ + return item_mouse.containsMouse ? Qt.darker(FluTheme.primaryColor.lighter,1.1) : FluTheme.primaryColor.lighter + }else{ + return item_mouse.containsMouse ? Qt.lighter(FluTheme.primaryColor.dark,1.1): FluTheme.primaryColor.dark + } + } + if(item_mouse.containsMouse){ + 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) + } + radius: 3 + MouseArea{ + id:item_mouse + anchors.fill: parent + hoverEnabled: true + onClicked: { + getListView().currentIndex = position + if(type === 0){ + text_year.text = model + list_view_2.model = generateMonthArray(1,12) + text_month.text = list_view_2.model[list_view_2.currentIndex] + + list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex]) + text_day.text = list_view_3.model[list_view_3.currentIndex] + } + if(type === 1){ + text_month.text = model + list_view_3.model = generateMonthDaysArray(list_view_1.model[list_view_1.currentIndex],list_view_2.model[list_view_2.currentIndex]) + text_day.text = list_view_3.model[list_view_3.currentIndex] + + } + if(type === 2){ + text_day.text = model + } + } + } + FluText{ + text:model + color: { + if(getListView().currentIndex === position){ + if(FluTheme.dark){ + return Qt.rgba(0,0,0,1) + }else{ + return Qt.rgba(1,1,1,1) + } + }else{ + return FluTheme.dark ? "#FFFFFF" : "#1A1A1A" + } + } + anchors.centerIn: parent + } + } + } + } + ListView{ + id:list_view_1 + width: 100 + height: parent.height + boundsBehavior:Flickable.StopAtBounds + ScrollBar.vertical: FluScrollBar {} + model: generateYearArray(1924,2048) + clip: true + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + visible: showYear + delegate: Loader{ + property var model: modelData + property int type:0 + property int position:index + sourceComponent: list_delegate + } + } + Rectangle{ + width: 1 + height: parent.height + color: dividerColor + } + ListView{ + id:list_view_2 + width: showYear ? 100 : 150 + height: parent.height + clip: true + ScrollBar.vertical: FluScrollBar {} + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + boundsBehavior:Flickable.StopAtBounds + delegate: Loader{ + property var model: modelData + property int type:1 + property int position:index + sourceComponent: list_delegate + } + } + Rectangle{ + width: 1 + height: parent.height + color: dividerColor + } + ListView{ + id:list_view_3 + width: showYear ? 100 : 150 + height: parent.height + clip: true + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + ScrollBar.vertical: FluScrollBar {} + Layout.alignment: Qt.AlignVCenter + boundsBehavior:Flickable.StopAtBounds + delegate: Loader{ + property var model: modelData + property int type:2 + property int position:index + sourceComponent: list_delegate + } + } + } + Rectangle{ + width: parent.width + height: 1 + anchors.top: layout_content.bottom + color: dividerColor + } + Rectangle{ + id:layout_actions + height: 40 + radius: 5 + color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) + anchors{ + bottom:parent.bottom + left: parent.left + right: parent.right + } + Item { + id:divider + width: 1 + height: parent.height + anchors.centerIn: parent + } + FluButton{ + anchors{ + left: parent.left + leftMargin: 20 + rightMargin: 10 + right: divider.left + verticalCenter: parent.verticalCenter + } + text: "取消" + onClicked: { + popup.close() + } + } + FluFilledButton{ + anchors{ + right: parent.right + left: divider.right + rightMargin: 20 + leftMargin: 10 + verticalCenter: parent.verticalCenter + } + text: "确定" + onClicked: { + d.changeFlag = false + popup.close() + const year = text_year.text + const month = text_month.text + const day = text_day.text + const date = new Date() + date.setFullYear(parseInt(year)); + date.setMonth(parseInt(month) - 1); + date.setDate(parseInt(day)); + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + current = date + } + } + } + } + } + y:35 + function showPopup() { + d.changeFlag = true + d.rowData[0] = text_year.text + d.rowData[1] = text_month.text + d.rowData[2] = text_day.text + const now = new Date(); + var year = text_year.text === "年"? now.getFullYear() : Number(text_year.text); + var month = text_month.text === "月"? now.getMonth() + 1 : Number(text_month.text); + var day = text_day.text === "日" ? now.getDate() : Number(text_day.text); + list_view_1.currentIndex = list_view_1.model.indexOf(year) + text_year.text = year + list_view_2.model = generateMonthArray(1,12) + list_view_2.currentIndex = list_view_2.model.indexOf(month) + text_month.text = month + list_view_3.model = generateMonthDaysArray(year,month) + list_view_3.currentIndex = list_view_3.model.indexOf(day) + text_day.text = day + var pos = control.mapToItem(null, 0, 0) + if(d.window.height>pos.y+control.height+container.height){ + popup.y = control.height + } else if(pos.y>container.height){ + popup.y = -container.height + } else { + popup.y = d.window.height-(pos.y+container.height) + } + popup.open() + } + onClosed: { + if(d.changeFlag){ + text_year.text = d.rowData[0] + text_month.text = d.rowData[1] + text_day.text = d.rowData[2] + } + } + } + function generateYearArray(startYear, endYear) { + const yearArray = []; + for (let year = startYear; year <= endYear; year++) { + yearArray.push(year); + } + return yearArray; + } + function generateMonthArray(startMonth, endMonth) { + const monthArray = []; + for (let month = startMonth; month <= endMonth; month++) { + monthArray.push(month); + } + return monthArray; + } + function generateMonthDaysArray(year, month) { + const monthDaysArray = []; + const lastDayOfMonth = new Date(year, month, 0).getDate(); + for (let day = 1; day <= lastDayOfMonth; day++) { + monthDaysArray.push(day); + } + return monthDaysArray; + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluDivider.qml b/src/Qt5/imports/FluentUI/Controls/FluDivider.qml new file mode 100644 index 00000000..34fe3892 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluDivider.qml @@ -0,0 +1,18 @@ +import QtQuick 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Rectangle { + property real spacing + property alias separatorHeight:separator.height + + id:root + color:Qt.rgba(0,0,0,0) + height: spacing*2+separator.height + Rectangle{ + id:separator + color: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) + width:parent.width + anchors.centerIn: parent + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluDropDownButton.qml b/src/Qt5/imports/FluentUI/Controls/FluDropDownButton.qml new file mode 100644 index 00000000..f3838809 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluDropDownButton.qml @@ -0,0 +1,94 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Button { + property bool disabled: false + property string contentDescription: "" + property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) + property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + property color textColor: { + if(FluTheme.dark){ + if(!enabled){ + return Qt.rgba(131/255,131/255,131/255,1) + } + if(pressed){ + return Qt.rgba(162/255,162/255,162/255,1) + } + return Qt.rgba(1,1,1,1) + }else{ + if(!enabled){ + return Qt.rgba(160/255,160/255,160/255,1) + } + if(pressed){ + return Qt.rgba(96/255,96/255,96/255,1) + } + return Qt.rgba(0,0,0,1) + } + } + property var window : Window.window + default property alias contentData: menu.contentData + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() + id: control + rightPadding:35 + enabled: !disabled + focusPolicy:Qt.TabFocus + horizontalPadding:12 + background: Rectangle{ + implicitWidth: 28 + implicitHeight: 28 + border.color: FluTheme.dark ? "#505050" : "#DFDFDF" + border.width: 1 + radius: 4 + FluFocusRectangle{ + visible: control.activeFocus + radius:8 + } + color:{ + if(!enabled){ + return disableColor + } + return hovered ? hoverColor :normalColor + } + FluIcon{ + iconSource:FluentIcons.ChevronDown + iconSize: 15 + anchors{ + right: parent.right + rightMargin: 10 + verticalCenter: parent.verticalCenter + } + iconColor:title.color + } + } + contentItem: FluText { + id:title + text: control.text + verticalAlignment: Text.AlignVCenter + color: control.textColor + } + onClicked: { + if(menu.count !==0){ + var pos = control.mapToItem(null, 0, 0) + var containerHeight = menu.count*36 + if(window.height>pos.y+control.height+containerHeight){ + menu.y = control.height + }else if(pos.y>containerHeight){ + menu.y = -containerHeight + }else{ + menu.y = window.height-(pos.y+containerHeight) + } + menu.open() + } + } + FluMenu{ + id:menu + modal:true + width: control.width + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluExpander.qml b/src/Qt5/imports/FluentUI/Controls/FluExpander.qml new file mode 100644 index 00000000..d36b81e2 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluExpander.qml @@ -0,0 +1,122 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Item { + property string headerText: "Titlte" + property bool expand: false + property int contentHeight : 300 + default property alias content: container.data + id:control + implicitHeight: Math.max((layout_header.height + container.height),layout_header.height) + implicitWidth: 400 + Rectangle{ + id:layout_header + width: parent.width + height: 45 + radius: 4 + 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) + 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) + MouseArea{ + id:control_mouse + anchors.fill: parent + hoverEnabled: true + onClicked: { + expand = !expand + } + } + FluText{ + text: headerText + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 15 + } + } + FluIconButton{ + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 15 + } + color:{ + if(control_mouse.containsMouse || hovered){ + return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(245/255,245/255,245/255,1) + } + return FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0) + } + onClicked: { + expand = !expand + } + contentItem: FluIcon{ + rotation: expand?0:180 + iconSource:FluentIcons.ChevronUp + iconSize: 15 + Behavior on rotation { + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 167 + easing.type: Easing.OutCubic + } + } + } + } + } + Item{ + anchors{ + top: layout_header.bottom + topMargin: -1 + left: layout_header.left + } + width: parent.width + clip: true + visible: contentHeight+container.y !== 0 + height: contentHeight+container.y + Rectangle{ + id:container + width: parent.width + height: parent.height + radius: 4 + color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) + border.color: FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1) + y: -contentHeight + states: [ + State{ + name:"expand" + when: control.expand + PropertyChanges { + target: container + y:0 + } + }, + State{ + name:"collapsed" + when: !control.expand + PropertyChanges { + target: container + y:-contentHeight + } + } + ] + transitions: [ + Transition { + to:"expand" + NumberAnimation { + properties: "y" + duration: FluTheme.enableAnimation ? 167 : 0 + easing.type: Easing.OutCubic + } + }, + Transition { + to:"collapsed" + NumberAnimation { + properties: "y" + duration: FluTheme.enableAnimation ? 167 : 0 + easing.type: Easing.OutCubic + } + } + ] + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluFilledButton.qml b/src/Qt5/imports/FluentUI/Controls/FluFilledButton.qml new file mode 100644 index 00000000..3584e089 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluFilledButton.qml @@ -0,0 +1,56 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Button { + property bool disabled: false + property string contentDescription: "" + property color normalColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property color hoverColor: FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1) + property color disableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) + property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.2) : Qt.lighter(normalColor,1.2) + property color textColor: { + if(FluTheme.dark){ + if(!enabled){ + return Qt.rgba(173/255,173/255,173/255,1) + } + return Qt.rgba(0,0,0,1) + }else{ + return Qt.rgba(1,1,1,1) + } + } + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() + id: control + enabled: !disabled + focusPolicy:Qt.TabFocus + font:FluTextStyle.Body + horizontalPadding:12 + background: Rectangle{ + implicitWidth: 28 + implicitHeight: 28 + radius: 4 + FluFocusRectangle{ + visible: control.visualFocus + radius:4 + } + color:{ + if(!enabled){ + return disableColor + } + if(pressed){ + return pressedColor + } + return hovered ? hoverColor :normalColor + } + } + contentItem: FluText { + text: control.text + font: control.font + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: control.textColor + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluFlipView.qml b/src/Qt5/imports/FluentUI/Controls/FluFlipView.qml new file mode 100644 index 00000000..a8545f2f --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluFlipView.qml @@ -0,0 +1,106 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Item{ + property bool vertical: false + default property alias content : swipe.contentData + property alias currentIndex: swipe.currentIndex + id:control + width: 400 + height: 300 + implicitWidth: width + implicitHeight: height + QtObject{ + id:d + property bool flag: true + } + MouseArea{ + anchors.fill: parent + preventStealing: true + onWheel: + (wheel)=>{ + if(!d.flag) + return + if (wheel.angleDelta.y > 0){ + btn_start.clicked() + }else{ + btn_end.clicked() + } + d.flag = false + timer.restart() + } + } + Timer{ + id:timer + interval: 250 + onTriggered: { + d.flag = true + } + } + SwipeView { + id:swipe + clip: true + interactive: false + orientation:control.vertical ? Qt.Vertical : Qt.Horizontal + anchors.fill: parent + } + Button{ + id:btn_start + height: vertical ? 20 : 40 + width: vertical ? 40 : 20 + anchors{ + left: vertical ? undefined : parent.left + leftMargin: vertical ? undefined : 2 + verticalCenter: vertical ? undefined : parent.verticalCenter + horizontalCenter: !vertical ? undefined : parent.horizontalCenter + top: !vertical ? undefined :parent.top + topMargin: !vertical ? undefined :2 + } + background: Rectangle{ + radius: 4 + color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,0.97) : Qt.rgba(237/255,237/255,237/255,0.97) + } + contentItem:FluIcon{ + iconSource: vertical ? FluentIcons.CaretUpSolid8 : FluentIcons.CaretLeftSolid8 + width: 10 + height: 10 + iconSize: 10 + iconColor: btn_start.hovered ? FluColors.Grey220 : FluColors.Grey120 + anchors.centerIn: parent + } + visible: swipe.currentIndex !==0 + onClicked: { + swipe.currentIndex = Math.max(swipe.currentIndex - 1, 0) + } + } + Button{ + id:btn_end + height: vertical ? 20 : 40 + width: vertical ? 40 : 20 + anchors{ + right: vertical ? undefined : parent.right + rightMargin: vertical ? undefined : 2 + verticalCenter: vertical ? undefined : parent.verticalCenter + horizontalCenter: !vertical ? undefined : parent.horizontalCenter + bottom: !vertical ? undefined :parent.bottom + bottomMargin: !vertical ? undefined :2 + } + background: Rectangle{ + radius: 4 + color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,0.97) : Qt.rgba(237/255,237/255,237/255,0.97) + } + visible: swipe.currentIndex !== swipe.count - 1 + contentItem:FluIcon{ + iconSource: vertical ? FluentIcons.CaretDownSolid8 : FluentIcons.CaretRightSolid8 + width: 10 + height: 10 + iconSize: 10 + iconColor: btn_end.hovered ? FluColors.Grey220 : FluColors.Grey120 + anchors.centerIn: parent + } + onClicked: { + swipe.currentIndex = Math.min(swipe.currentIndex + 1,swipe.count-1) + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluFocusRectangle.qml b/src/Qt5/imports/FluentUI/Controls/FluFocusRectangle.qml new file mode 100644 index 00000000..82dc6903 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluFocusRectangle.qml @@ -0,0 +1,19 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Item { + property int radius: 4 + id:control + anchors.fill: parent + Rectangle{ + width: control.width + height: control.height + anchors.centerIn: parent + color: "#00000000" + border.width: 2 + radius: control.radius + border.color: FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1) + z: 65535 + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluIcon.qml b/src/Qt5/imports/FluentUI/Controls/FluIcon.qml new file mode 100644 index 00000000..3a51b3f2 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluIcon.qml @@ -0,0 +1,19 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Text { + property int iconSource + property int iconSize: 20 + property color iconColor: FluTheme.dark ? "#FFFFFF" : "#000000" + id:control + font.family: "Segoe Fluent Icons" + font.pixelSize: iconSize + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: iconColor + text: (String.fromCharCode(iconSource).toString(16)) + FontLoader{ + source: "../Font/Segoe_Fluent_Icons.ttf" + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluIconButton.qml b/src/Qt5/imports/FluentUI/Controls/FluIconButton.qml new file mode 100644 index 00000000..e0e5efc2 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluIconButton.qml @@ -0,0 +1,140 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Button { + display: Button.IconOnly + property int iconSize: 20 + property int iconSource + property bool disabled: false + property int radius:4 + property string contentDescription: "" + property color hoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03) + property color pressedColor: FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06) + property color normalColor: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0) + property color disableColor: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0) + property Component iconDelegate: com_icon + property color color: { + if(!enabled){ + return disableColor + } + if(pressed){ + return pressedColor + } + return hovered ? hoverColor : normalColor + } + property color iconColor: { + if(FluTheme.dark){ + if(!enabled){ + return Qt.rgba(130/255,130/255,130/255,1) + } + return Qt.rgba(1,1,1,1) + }else{ + if(!enabled){ + return Qt.rgba(161/255,161/255,161/255,1) + } + return Qt.rgba(0,0,0,1) + } + } + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() + id:control + focusPolicy:Qt.TabFocus + padding: 0 + verticalPadding: 8 + horizontalPadding: 8 + enabled: !disabled + background: Rectangle{ + implicitWidth: 30 + implicitHeight: 30 + radius: control.radius + color:control.color + FluFocusRectangle{ + visible: control.activeFocus + } + } + Component{ + id:com_icon + FluIcon { + id:text_icon + font.pixelSize: iconSize + iconSize: control.iconSize + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + iconColor: control.iconColor + iconSource: control.iconSource + } + } + + Component{ + id:com_row + RowLayout{ + Loader{ + sourceComponent: iconDelegate + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + visible: display !== Button.TextOnly + } + FluText{ + text:control.text + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + visible: display !== Button.IconOnly + } + FluTooltip{ + id:tool_tip + visible: { + if(control.text === ""){ + return false + } + if(control.display !== Button.IconOnly){ + return false + } + return hovered + } + text:control.text + delay: 1000 + } + } + } + + Component{ + id:com_column + ColumnLayout{ + Loader{ + sourceComponent: iconDelegate + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + visible: display !== Button.TextOnly + } + FluText{ + text:control.text + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + visible: display !== Button.IconOnly + } + FluTooltip{ + id:tool_tip + visible: { + if(control.text === ""){ + return false + } + if(control.display !== Button.IconOnly){ + return false + } + return hovered + } + text:control.text + delay: 1000 + } + } + } + + contentItem:Loader{ + sourceComponent: { + if(display === Button.TextUnderIcon){ + return com_column + } + return com_row + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluImage.qml b/src/Qt5/imports/FluentUI/Controls/FluImage.qml new file mode 100644 index 00000000..78b02f47 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluImage.qml @@ -0,0 +1,48 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Image { + property string errorButtonText: "重新加载" + property var clickErrorListener : function(){ + image.source = "" + image.source = control.source + } + property Component errorItem : com_error + property Component loadingItem: com_loading + id: control + Loader{ + anchors.fill: parent + sourceComponent: { + if(control.status === Image.Loading){ + return com_loading + }else if(control.status == Image.Error){ + return com_error + }else{ + return undefined + } + } + } + Component{ + id:com_loading + Rectangle{ + color: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03) + FluProgressRing{ + anchors.centerIn: parent + visible: control.status === Image.Loading + } + } + } + Component{ + id:com_error + Rectangle{ + color: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03) + FluFilledButton{ + text: control.errorButtonText + anchors.centerIn: parent + visible: control.status === Image.Error + onClicked: clickErrorListener() + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluInfoBar.qml b/src/Qt5/imports/FluentUI/Controls/FluInfoBar.qml new file mode 100644 index 00000000..f24f627d --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluInfoBar.qml @@ -0,0 +1,210 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluObject { + property var root; + property int layoutY: 75 + id:control + FluObject{ + id:mcontrol + property string const_success: "success"; + property string const_info: "info"; + property string const_warning: "warning"; + property string const_error: "error"; + property int maxWidth: 300; + property var screenLayout: null; + function create(type,text,duration,moremsg){ + if(screenLayout){ + var last = screenLayout.getLastloader(); + if(last.type === type && last.text === text && moremsg === last.moremsg){ + last.restart(); + return; + } + } + initScreenLayout(); + contentComponent.createObject(screenLayout,{ + type:type, + text:text, + duration:duration, + moremsg:moremsg, + }); + } + function createCustom(itemcomponent,duration){ + initScreenLayout(); + if(itemcomponent){ + contentComponent.createObject(screenLayout,{itemcomponent:itemcomponent,duration:duration}); + } + } + function initScreenLayout(){ + if(screenLayout == null){ + screenLayout = screenlayoutComponent.createObject(root); + screenLayout.y = control.layoutY; + screenLayout.z = 100000; + } + } + Component{ + id:screenlayoutComponent + Column{ + spacing: 20 + width: parent.width + move: Transition { + NumberAnimation { + properties: "y" + easing.type: Easing.OutCubic + duration: FluTheme.enableAnimation ? 333 : 0 + } + } + onChildrenChanged: if(children.length === 0) destroy(); + function getLastloader(){ + if(children.length > 0){ + return children[children.length - 1]; + } + return null; + } + } + } + Component{ + id:contentComponent + Item{ + id:content; + property int duration: 1500 + property var itemcomponent + property string type + property string text + property string moremsg + width: parent.width; + height: loader.height; + function close(){ + content.destroy(); + } + function restart(){ + delayTimer.restart(); + } + Timer { + id:delayTimer + interval: duration; running: true; repeat: true + onTriggered: content.close(); + } + Loader{ + id:loader; + x:(parent.width - width) / 2; + property var _super: content; + scale: item ? 1 : 0; + asynchronous: true + Behavior on scale { + enabled: FluTheme.enableAnimation + NumberAnimation { + easing.type: Easing.OutCubic + duration: 167 + } + } + sourceComponent:itemcomponent ? itemcomponent : mcontrol.fluent_sytle; + } + } + } + property Component fluent_sytle: Rectangle{ + width: rowlayout.width + (_super.moremsg ? 25 : 80); + height: rowlayout.height + 20; + color: { + if(FluTheme.dark){ + switch(_super.type){ + case mcontrol.const_success: return Qt.rgba(57/255,61/255,27/255,1); + case mcontrol.const_warning: return Qt.rgba(67/255,53/255,25/255,1); + case mcontrol.const_info: return Qt.rgba(39/255,39/255,39/255,1); + case mcontrol.const_error: return Qt.rgba(68/255,39/255,38/255,1); + } + return Qt.rgba(255,255,255,1) + }else{ + switch(_super.type){ + case mcontrol.const_success: return "#dff6dd"; + case mcontrol.const_warning: return "#fff4ce"; + case mcontrol.const_info: return "#f4f4f4"; + case mcontrol.const_error: return "#fde7e9"; + } + return "#FFFFFF" + } + } + radius: 4 + border.width: 1 + border.color: { + if(FluTheme.dark){ + switch(_super.type){ + case mcontrol.const_success: return Qt.rgba(56/255,61/255,27/255,1); + case mcontrol.const_warning: return Qt.rgba(66/255,53/255,25/255,1); + case mcontrol.const_info: return Qt.rgba(38/255,39/255,39/255,1); + case mcontrol.const_error: return Qt.rgba(67/255,39/255,38/255,1); + } + return "#FFFFFF" + }else{ + switch(_super.type){ + case mcontrol.const_success: return "#d2e8d0"; + case mcontrol.const_warning: return "#f0e6c2"; + case mcontrol.const_info: return "#e6e6e6"; + case mcontrol.const_error: return "#eed9db"; + } + return "#FFFFFF" + } + } + Row{ + id:rowlayout + x:20; + y:(parent.height - height) / 2; + spacing: 10 + + FluIcon{ + iconSource:{ + switch(_super.type){ + case mcontrol.const_success: return FluentIcons.CompletedSolid; + case mcontrol.const_warning: return FluentIcons.InfoSolid; + case mcontrol.const_info: return FluentIcons.InfoSolid; + case mcontrol.const_error: return FluentIcons.StatusErrorFull; + }FluentIcons.StatusErrorFull + return FluentIcons.FA_info_circle + } + iconSize:20 + iconColor: { + if(FluTheme.dark){ + switch(_super.type){ + case mcontrol.const_success: return Qt.rgba(108/255,203/255,95/255,1); + case mcontrol.const_warning: return Qt.rgba(252/255,225/255,0/255,1); + case mcontrol.const_info: return FluTheme.primaryColor.lighter; + case mcontrol.const_error: return Qt.rgba(255/255,153/255,164/255,1); + } + return "#FFFFFF" + }else{ + switch(_super.type){ + case mcontrol.const_success: return "#0f7b0f"; + case mcontrol.const_warning: return "#9d5d00"; + case mcontrol.const_info: return "#0066b4"; + case mcontrol.const_error: return "#c42b1c"; + } + return "#FFFFFF" + } + } + } + + FluText{ + text:_super.text + wrapMode: Text.WrapAnywhere + width: Math.min(implicitWidth,mcontrol.maxWidth) + } + } + } + } + function showSuccess(text,duration=1000,moremsg){ + mcontrol.create(mcontrol.const_success,text,duration,moremsg ? moremsg : ""); + } + function showInfo(text,duration=1000,moremsg){ + mcontrol.create(mcontrol.const_info,text,duration,moremsg ? moremsg : ""); + } + function showWarning(text,duration=1000,moremsg){ + mcontrol.create(mcontrol.const_warning,text,duration,moremsg ? moremsg : ""); + } + function showError(text,duration=1000,moremsg){ + mcontrol.create(mcontrol.const_error,text,duration,moremsg ? moremsg : ""); + } + function showCustom(itemcomponent,duration=1000){ + mcontrol.createCustom(itemcomponent,duration); + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluItem.qml b/src/Qt5/imports/FluentUI/Controls/FluItem.qml new file mode 100644 index 00000000..51074233 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluItem.qml @@ -0,0 +1,57 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtGraphicalEffects 1.15 + +Item{ + property var radius:[0,0,0,0] + default property alias contentItem: container.data + id:control + Item{ + id:container + width: control.width + height: control.height + opacity: 0 + } + onWidthChanged: { + canvas.requestPaint() + } + onHeightChanged: { + canvas.requestPaint() + } + onRadiusChanged: { + canvas.requestPaint() + } + Canvas { + id: canvas + anchors.fill: parent + visible: false + onPaint: { + var ctx = getContext("2d"); + var x = 0; + var y = 0; + var w = control.width; + var h = control.height; + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.save(); + ctx.beginPath(); + ctx.moveTo(x + radius[0], y); + ctx.lineTo(x + w - radius[1], y); + ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1]); + ctx.lineTo(x + w, y + h - radius[2]); + ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2]); + ctx.lineTo(x + radius[3], y + h); + ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3]); + ctx.lineTo(x, y + radius[0]); + ctx.arcTo(x, y, x + radius[0], y, radius[0]); + ctx.closePath(); + ctx.fillStyle = control.color; + ctx.fill(); + ctx.restore(); + } + } + OpacityMask { + anchors.fill: container + source: container + maskSource: canvas + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluItemDelegate.qml b/src/Qt5/imports/FluentUI/Controls/FluItemDelegate.qml new file mode 100644 index 00000000..a852c591 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluItemDelegate.qml @@ -0,0 +1,38 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.ItemDelegate { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 12 + spacing: 8 + + icon.width: 24 + icon.height: 24 + icon.color: control.palette.text + + contentItem: FluText { + text: control.text + font: control.font + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + color:{ + if(FluTheme.dark){ + return Qt.rgba(1,1,1,0.05) + }else{ + return Qt.rgba(0,0,0,0.05) + } + } + visible: control.down || control.highlighted || control.visualFocus + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluMenu.qml b/src/Qt5/imports/FluentUI/Controls/FluMenu.qml new file mode 100644 index 00000000..3485511d --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluMenu.qml @@ -0,0 +1,59 @@ +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.Menu { + property bool enableAnimation: true + id: control + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + margins: 0 + overlap: 1 + spacing: 0 + delegate: FluMenuItem { } + enter: Transition { + NumberAnimation { + property: "opacity" + from:0 + to:1 + duration: FluTheme.enableAnimation && control.enableAnimation ? 83 : 0 + } + } + exit:Transition { + NumberAnimation { + property: "opacity" + from:1 + to:0 + duration: FluTheme.enableAnimation && control.enableAnimation ? 83 : 0 + } + } + contentItem: ListView { + implicitHeight: contentHeight + model: control.contentModel + interactive: Window.window + ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height + : false + clip: true + currentIndex: control.currentIndex + ScrollIndicator.vertical: ScrollIndicator {} + } + background: Rectangle { + implicitWidth: 150 + implicitHeight: 36 + color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(240/255,240/255,240/255,1) + 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) + border.width: 1 + radius: 5 + FluShadow{} + } + T.Overlay.modal: Rectangle { + color: FluTools.colorAlpha(control.palette.shadow, 0.5) + } + T.Overlay.modeless: Rectangle { + color: FluTools.colorAlpha(control.palette.shadow, 0.12) + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluMenuBar.qml b/src/Qt5/imports/FluentUI/Controls/FluMenuBar.qml new file mode 100644 index 00000000..0151af6b --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluMenuBar.qml @@ -0,0 +1,20 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T + +T.MenuBar { + id: control + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding) + delegate: FluMenuBarItem { } + contentItem: Row { + spacing: control.spacing + Repeater { + model: control.contentModel + } + } + background: Item { + implicitHeight: 30 + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml b/src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml new file mode 100644 index 00000000..bc17c4ca --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluMenuBarItem.qml @@ -0,0 +1,69 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.MenuBarItem { + property bool disabled: false + property color textColor: { + if(FluTheme.dark){ + if(disabled){ + return Qt.rgba(131/255,131/255,131/255,1) + } + if(pressed){ + return Qt.rgba(162/255,162/255,162/255,1) + } + return Qt.rgba(1,1,1,1) + }else{ + if(disabled){ + return Qt.rgba(160/255,160/255,160/255,1) + } + if(pressed){ + return Qt.rgba(96/255,96/255,96/255,1) + } + return Qt.rgba(0,0,0,1) + } + } + id: control + enabled: !disabled + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + spacing: 6 + padding: 6 + leftPadding: 12 + rightPadding: 16 + icon.width: 24 + icon.height: 24 + icon.color: control.palette.buttonText + contentItem: FluText { + verticalAlignment: Text.AlignVCenter + text: control.text + color:control.textColor + } + background: Rectangle { + implicitWidth: 30 + implicitHeight: 30 + radius: 3 + color: { + if(FluTheme.dark){ + if(control.highlighted){ + return Qt.rgba(1,1,1,0.06) + } + if(control.hovered){ + return Qt.rgba(1,1,1,0.03) + } + return Qt.rgba(0,0,0,0) + }else{ + if(control.highlighted){ + return Qt.rgba(0,0,0,0.06) + } + if(control.hovered){ + return Qt.rgba(0,0,0,0.03) + } + return Qt.rgba(0,0,0,0) + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluMenuItem.qml b/src/Qt5/imports/FluentUI/Controls/FluMenuItem.qml new file mode 100644 index 00000000..58046db9 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluMenuItem.qml @@ -0,0 +1,115 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.MenuItem { + property Component iconDelegate : com_icon + property int iconSpacing: 5 + property int iconSource + property int iconSize: 16 + property color textColor: { + if(FluTheme.dark){ + if(!enabled){ + return Qt.rgba(131/255,131/255,131/255,1) + } + if(pressed){ + return Qt.rgba(162/255,162/255,162/255,1) + } + return Qt.rgba(1,1,1,1) + }else{ + if(!enabled){ + return Qt.rgba(160/255,160/255,160/255,1) + } + if(pressed){ + return Qt.rgba(96/255,96/255,96/255,1) + } + return Qt.rgba(0,0,0,1) + } + } + id: control + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + padding: 6 + spacing: 6 + icon.width: 24 + icon.height: 24 + icon.color: control.palette.windowText + height: visible ? implicitHeight : 0 + Component{ + id:com_icon + FluIcon{ + id:content_icon + iconSize: control.iconSize + iconSource:control.iconSource + } + } + contentItem: Item{ + Row{ + spacing: control.iconSpacing + readonly property real arrowPadding: control.subMenu && control.arrow ? control.arrow.width + control.spacing : 0 + readonly property real indicatorPadding: control.checkable && control.indicator ? control.indicator.width + control.spacing : 0 + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: (!control.mirrored ? indicatorPadding : arrowPadding)+5 + right: parent.right + rightMargin: (control.mirrored ? indicatorPadding : arrowPadding)+5 + } + Loader{ + id:loader_icon + sourceComponent: iconDelegate + anchors.verticalCenter: parent.verticalCenter + visible: status === Loader.Ready + } + FluText { + id:content_text + text: control.text + color: control.textColor + anchors.verticalCenter: parent.verticalCenter + } + } + } + indicator: FluIcon { + x: control.mirrored ? control.width - width - control.rightPadding : control.leftPadding + y: control.topPadding + (control.availableHeight - height) / 2 + visible: control.checked + iconSource: FluentIcons.CheckMark + } + arrow: FluIcon { + x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding + y: control.topPadding + (control.availableHeight - height) / 2 + visible: control.subMenu + iconSource: FluentIcons.ChevronRightMed + } + background: Item { + implicitWidth: 150 + implicitHeight: 36 + x: 1 + y: 1 + width: control.width - 2 + height: control.height - 2 + Rectangle{ + anchors.fill: parent + anchors.margins: 3 + radius: 4 + color:{ + if(FluTheme.dark){ + if(control.highlighted){ + return Qt.rgba(1,1,1,0.06) + } + return Qt.rgba(0,0,0,0) + }else{ + if(control.highlighted){ + return Qt.rgba(0,0,0,0.06) + } + return Qt.rgba(0,0,0,0) + } + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluMenuSeparator.qml b/src/Qt5/imports/FluentUI/Controls/FluMenuSeparator.qml new file mode 100644 index 00000000..426af36e --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluMenuSeparator.qml @@ -0,0 +1,18 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.MenuSeparator { + id: control + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + padding: 0 + verticalPadding: 0 + contentItem: Rectangle { + implicitWidth: 188 + implicitHeight: 1 + color: FluTheme.dark ? Qt.rgba(60/255,60/255,60/255,1) : Qt.rgba(210/255,210/255,210/255,1) + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluMultilineTextBox.qml b/src/Qt5/imports/FluentUI/Controls/FluMultilineTextBox.qml new file mode 100644 index 00000000..5d9bc200 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluMultilineTextBox.qml @@ -0,0 +1,65 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +TextArea{ + signal commit(string text) + property bool disabled: false + property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + id:control + enabled: !disabled + color: { + if(!enabled){ + return disableColor + } + return normalColor + } + font:FluTextStyle.Body + wrapMode: Text.WrapAnywhere + padding: 8 + leftPadding: padding+2 + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + selectedTextColor: color + selectionColor: FluTools.colorAlpha(FluTheme.primaryColor.lightest,0.6) + placeholderTextColor: { + if(!enabled){ + return placeholderDisableColor + } + if(focus){ + return placeholderFocusColor + } + return placeholderNormalColor + } + selectByMouse: true + width: background.implicitWidth + background: FluTextBoxBackground{ + inputItem: control + implicitWidth: 240 + } + Keys.onEnterPressed: (event)=> d.handleCommit(event) + Keys.onReturnPressed:(event)=> d.handleCommit(event) + QtObject{ + id:d + function handleCommit(event){ + if(event.modifiers & Qt.ControlModifier){ + insert(control.cursorPosition, "\n") + return + } + control.commit(control.text) + } + } + MouseArea{ + anchors.fill: parent + cursorShape: Qt.IBeamCursor + acceptedButtons: Qt.RightButton + onClicked: control.echoMode !== TextInput.Password && menu.popup() + } + FluTextBoxMenu{ + id:menu + inputItem: control + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml b/src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml new file mode 100644 index 00000000..a2ef685a --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluNavigationView.qml @@ -0,0 +1,1222 @@ +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Item { + property url logo + property string title: "" + property FluObject items + property FluObject footerItems + property int displayMode: FluNavigationViewType.Auto + property Component autoSuggestBox + property Component actionItem + property int topPadding: 0 + property int navWidth: 300 + property int pageMode: FluNavigationViewType.Stack + property FluMenu navItemRightMenu + property FluMenu navItemExpanderRightMenu + signal logoClicked + id:control + Item{ + id:d + property bool animDisabled:false + property var stackItems: [] + property int displayMode: control.displayMode + property bool enableNavigationPanel: false + property bool isCompact: d.displayMode === FluNavigationViewType.Compact + property bool isMinimal: d.displayMode === FluNavigationViewType.Minimal + property bool isCompactAndPanel: d.displayMode === FluNavigationViewType.Compact && d.enableNavigationPanel + property bool isCompactAndNotPanel:d.displayMode === FluNavigationViewType.Compact && !d.enableNavigationPanel + property bool isMinimalAndPanel: d.displayMode === FluNavigationViewType.Minimal && d.enableNavigationPanel + onIsCompactAndNotPanelChanged: { + collapseAll() + } + function handleItems(){ + var _idx = 0 + var data = [] + if(items){ + for(var i=0;i children + id:control +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPage.qml b/src/Qt5/imports/FluentUI/Controls/FluPage.qml new file mode 100644 index 00000000..85b95996 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPage.qml @@ -0,0 +1,34 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Item { + property int launchMode: FluPageType.SingleTop + property bool animDisabled: false + property string url : "" + id: control + opacity: visible + visible: false + StackView.onRemoved: destroy() + Behavior on opacity{ + enabled: !animDisabled && FluTheme.enableAnimation + NumberAnimation{ + duration: 167 + } + } + transform: Translate { + y: control.visible ? 0 : 80 + Behavior on y{ + enabled: !animDisabled && FluTheme.enableAnimation + NumberAnimation{ + duration: 167 + easing.type: Easing.OutCubic + } + } + } + Component.onCompleted: { + visible = true + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPagination.qml b/src/Qt5/imports/FluentUI/Controls/FluPagination.qml new file mode 100644 index 00000000..b7391ee6 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPagination.qml @@ -0,0 +1,100 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Item { + signal requestPage(int page,int count) + property string previousText: "<上一页" + property string nextText: "下一页>" + property int pageCurrent: 0 + property int itemCount: 0 + property int pageButtonCount: 5 + property int pageCount: itemCount>0?Math.ceil(itemCount/__itemPerPage):0 + property int __itemPerPage: 10 + property int __pageButtonHalf: Math.floor(pageButtonCount/2)+1 + id: control + implicitHeight: 40 + implicitWidth: content.width + Row{ + id: content + height: control.height + spacing: 10 + padding: 10 + FluToggleButton{ + visible: control.pageCount>1 + disabled: control.pageCurrent<=1 + text:control.previousText + clickListener:function() { + control.calcNewPage(control.pageCurrent-1); + } + } + Row{ + spacing: 5 + FluToggleButton{ + property int pageNumber:1 + visible: control.pageCount>0 + checked: pageNumber === control.pageCurrent + text:String(pageNumber) + clickListener:function() { + control.calcNewPage(pageNumber); + } + } + FluText{ + visible: (control.pageCount>control.pageButtonCount&& + control.pageCurrent>control.__pageButtonHalf) + text: "..." + } + Repeater{ + id: button_repeator + model: (control.pageCount<2)?0:(control.pageCount>=control.pageButtonCount)?(control.pageButtonCount-2):(control.pageCount-2) + delegate:FluToggleButton{ + property int pageNumber: { + return (control.pageCurrent<=control.__pageButtonHalf) + ?(2+index) + :(control.pageCount-control.pageCurrent<=control.pageButtonCount-control.__pageButtonHalf) + ?(control.pageCount-button_repeator.count+index) + :(control.pageCurrent+2+index-control.__pageButtonHalf) + } + text:String(pageNumber) + checked: pageNumber === control.pageCurrent + clickListener:function(){ + control.calcNewPage(pageNumber); + } + } + } + FluText{ + visible: (control.pageCount>control.pageButtonCount&& + control.pageCount-control.pageCurrent>control.pageButtonCount-control.__pageButtonHalf) + text: "..." + } + FluToggleButton{ + property int pageNumber:control.pageCount + visible: control.pageCount>1 + checked: pageNumber === control.pageCurrent + text:String(pageNumber) + clickListener:function(){ + control.calcNewPage(pageNumber); + } + } + } + FluToggleButton{ + visible: control.pageCount>1 + disabled: control.pageCurrent>=control.pageCount + text:control.nextText + clickListener:function() { + control.calcNewPage(control.pageCurrent+1); + } + } + } + function calcNewPage(page) + { + if(!page) + return + let page_num=Number(page) + if(page_num<1||page_num>control.pageCount||page_num===control.pageCurrent) + return + control.pageCurrent=page_num + control.requestPage(page_num,control.__itemPerPage) + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPaneItem.qml b/src/Qt5/imports/FluentUI/Controls/FluPaneItem.qml new file mode 100644 index 00000000..4e3e79c1 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPaneItem.qml @@ -0,0 +1,25 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property var _ext + property string title + property int order : 0 + property int icon + property Component cusIcon + property Component infoBadge + property bool recentlyAdded: false + property bool recentlyUpdated: false + property string desc + property var image + property var parent + property int count: 0 + signal tap + property var tapFunc + property Component menuDelegate + property Component editDelegate + property bool showEdit +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPaneItemEmpty.qml b/src/Qt5/imports/FluentUI/Controls/FluPaneItemEmpty.qml new file mode 100644 index 00000000..92bb64c6 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPaneItemEmpty.qml @@ -0,0 +1,10 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property var _ext + property var parent +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPaneItemExpander.qml b/src/Qt5/imports/FluentUI/Controls/FluPaneItemExpander.qml new file mode 100644 index 00000000..4a700085 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPaneItemExpander.qml @@ -0,0 +1,16 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluObject { + readonly property string key : FluTools.uuid() + property int _idx + property string title + property var icon + property Component cusIcon + property bool isExpand: false + property var parent + property Component menuDelegate + property Component editDelegate + property bool showEdit +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPaneItemHeader.qml b/src/Qt5/imports/FluentUI/Controls/FluPaneItemHeader.qml new file mode 100644 index 00000000..2591cf18 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPaneItemHeader.qml @@ -0,0 +1,10 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property string title + property var parent +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPaneItemSeparator.qml b/src/Qt5/imports/FluentUI/Controls/FluPaneItemSeparator.qml new file mode 100644 index 00000000..7fa94f9a --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPaneItemSeparator.qml @@ -0,0 +1,11 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property var parent + property real spacing + property int size:1 +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPasswordBox.qml b/src/Qt5/imports/FluentUI/Controls/FluPasswordBox.qml new file mode 100644 index 00000000..1d5ed6e5 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPasswordBox.qml @@ -0,0 +1,84 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +TextField{ + signal commit(string text) + property bool disabled: false + property int iconSource: 0 + property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + id:control + enabled: !disabled + color: { + if(!enabled){ + return disableColor + } + return normalColor + } + font:FluTextStyle.Body + padding: 8 + leftPadding: padding+2 + echoMode:btn_reveal.pressed ? TextField.Normal : TextField.Password + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + selectionColor: FluTools.colorAlpha(FluTheme.primaryColor.lightest,0.6) + selectedTextColor: color + placeholderTextColor: { + if(!enabled){ + return placeholderDisableColor + } + if(focus){ + return placeholderFocusColor + } + return placeholderNormalColor + } + selectByMouse: true + rightPadding: icon_end.visible ? 50 : 30 + background: FluTextBoxBackground{ + inputItem: control + implicitWidth: 240 + FluIcon{ + id:icon_end + iconSource: control.iconSource + iconSize: 15 + opacity: 0.5 + visible: control.iconSource != 0 + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 5 + } + } + } + Keys.onEnterPressed: (event)=> d.handleCommit(event) + Keys.onReturnPressed:(event)=> d.handleCommit(event) + QtObject{ + id:d + function handleCommit(event){ + control.commit(control.text) + } + } + FluIconButton{ + id:btn_reveal + iconSource:FluentIcons.RevealPasswordMedium + iconSize: 10 + width: 20 + height: 20 + verticalPadding: 0 + horizontalPadding: 0 + opacity: 0.5 + visible: control.text !== "" + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: icon_end.visible ? 25 : 5 + } + } + FluTextBoxMenu{ + id:menu + inputItem: control + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPivot.qml b/src/Qt5/imports/FluentUI/Controls/FluPivot.qml new file mode 100644 index 00000000..8ddbc7dc --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPivot.qml @@ -0,0 +1,92 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Item { + default property alias content: d.children + property alias currentIndex: nav_list.currentIndex + property color normalColor: FluTheme.dark ? FluColors.Grey120 : FluColors.Grey120 + property color hoverColor: FluTheme.dark ? FluColors.Grey10 : FluColors.Black + id:control + width: 400 + height: 300 + implicitHeight: height + implicitWidth: width + MouseArea{ + anchors.fill: parent + preventStealing: true + } + FluObject{ + id:d + } + ListView{ + id:nav_list + height: 40 + width: control.width + model:d.children + clip: true + spacing: 20 + interactive: false + orientation: ListView.Horizontal + highlightMoveDuration: FluTheme.enableAnimation ? 167 : 0 + highlight: Item{ + clip: true + Rectangle{ + height: 3 + radius: 1.5 + color: FluTheme.primaryColor.dark + width: nav_list.currentItem ? nav_list.currentItem.width : 0 + y:37 + Behavior on width { + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 167 + easing.type: Easing.OutCubic + } + } + } + } + delegate: Button{ + id:item_button + width: item_title.width + height: nav_list.height + background:Item{ + } + contentItem: Item{ + FluText { + id:item_title + font: FluTextStyle.Title + text: modelData.title + anchors.centerIn: parent + color: { + if(item_button.hovered) + return hoverColor + return normalColor + } + } + } + onClicked: { + nav_list.currentIndex = index + } + } + } + Item{ + id:container + anchors{ + top: nav_list.bottom + topMargin: 10 + left: parent.left + right: parent.right + bottom: parent.bottom + } + Repeater{ + model:d.children + Loader{ + property var argument: modelData.argument + anchors.fill: parent + sourceComponent: modelData.contentItem + visible: nav_list.currentIndex === index + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPivotItem.qml b/src/Qt5/imports/FluentUI/Controls/FluPivotItem.qml new file mode 100644 index 00000000..4181d29c --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPivotItem.qml @@ -0,0 +1,9 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +QtObject { + property string title + property Component contentItem + property var argument +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluPopup.qml b/src/Qt5/imports/FluentUI/Controls/FluPopup.qml new file mode 100644 index 00000000..d5a73650 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluPopup.qml @@ -0,0 +1,47 @@ +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: popup + padding: 0 + modal:true + anchors.centerIn: Overlay.overlay + closePolicy: Popup.CloseOnEscape + enter: Transition { + NumberAnimation { + properties: "scale" + from:1.2 + to:1 + duration: FluTheme.enableAnimation ? 83 : 0 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + duration: FluTheme.enableAnimation ? 83 : 0 + from:0 + to:1 + } + } + exit:Transition { + NumberAnimation { + properties: "scale" + from:1 + to:1.2 + duration: FluTheme.enableAnimation ? 83 : 0 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + duration: FluTheme.enableAnimation ? 83 : 0 + from:1 + to:0 + } + } + background: FluRectangle{ + radius: [5,5,5,5] + color: FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(1,1,1,1) + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml b/src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml new file mode 100644 index 00000000..3d325ec3 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluProgressBar.qml @@ -0,0 +1,60 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +ProgressBar{ + property real strokeWidth: 6 + property bool progressVisible: false + property color color: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property color backgroundColor : FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1) + id:control + indeterminate : true + QtObject{ + id:d + property real _radius: strokeWidth/2 + } + background: Rectangle { + implicitWidth: 150 + implicitHeight: control.strokeWidth + color: control.backgroundColor + radius: d._radius + } + contentItem: FluItem { + clip: true + radius: [d._radius,d._radius,d._radius,d._radius] + Rectangle { + id:rect_progress + width: { + if(control.indeterminate){ + return 0.5 * parent.width + } + return control.visualPosition * parent.width + } + height: parent.height + radius: d._radius + color: control.color + PropertyAnimation on x { + running: control.indeterminate && control.visible + from: -rect_progress.width + to:control.width+rect_progress.width + loops: Animation.Infinite + duration: 888 + } + } + } + FluText{ + text:(control.visualPosition * 100).toFixed(0) + "%" + visible: { + if(control.indeterminate){ + return false + } + return control.progressVisible + } + anchors{ + left: parent.left + leftMargin: control.width+5 + verticalCenter: parent.verticalCenter + } + } +} + diff --git a/src/Qt5/imports/FluentUI/Controls/FluProgressRing.qml b/src/Qt5/imports/FluentUI/Controls/FluProgressRing.qml new file mode 100644 index 00000000..c77dd256 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluProgressRing.qml @@ -0,0 +1,74 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Shapes 1.15 +import FluentUI 1.0 + +ProgressBar{ + property real strokeWidth: 6 + property bool progressVisible: false + property color color: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property color backgroundColor : FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1) + id:control + indeterminate : true + clip: true + background: Rectangle { + implicitWidth: 56 + implicitHeight: 56 + radius: control.width/2 + color:"transparent" + border.color: control.backgroundColor + border.width: control.strokeWidth + } + QtObject{ + id:d + property real _radius: control.width/2-control.strokeWidth/2 + property real _progress: control.indeterminate ? 0.3 : control.visualPosition + on_ProgressChanged: { + canvas.requestPaint() + } + } + Connections{ + target: FluTheme + function onDarkChanged(){ + canvas.requestPaint() + } + } + contentItem: Item { + RotationAnimation on rotation { + running: control.indeterminate && control.visible + from: 0 + to:360 + loops: Animation.Infinite + duration: 888 + } + Canvas { + id:canvas + anchors.fill: parent + antialiasing: true + renderTarget: Canvas.Image + onPaint: { + var ctx = canvas.getContext("2d") + ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.save() + ctx.lineWidth = control.strokeWidth + ctx.strokeStyle = control.color + ctx.beginPath() + ctx.arc(width/2, height/2, d._radius ,-0.5 * Math.PI,-0.5 * Math.PI + d._progress * 2 * Math.PI) + ctx.stroke() + ctx.closePath() + ctx.restore() + } + } + } + FluText{ + text:(control.visualPosition * 100).toFixed(0) + "%" + visible: { + if(control.indeterminate){ + return false + } + return control.progressVisible + } + anchors.centerIn: parent + } +} + diff --git a/src/Qt5/imports/FluentUI/Controls/FluQRCode.qml b/src/Qt5/imports/FluentUI/Controls/FluQRCode.qml new file mode 100644 index 00000000..c7a8f287 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluQRCode.qml @@ -0,0 +1,23 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Item{ + property alias text: qrcode.text + property alias color: qrcode.color + property alias bgColor: qrcode.bgColor + property int size: 50 + property int margins: 0 + id:control + width: size + height: size + Rectangle{ + color: bgColor + anchors.fill: parent + } + QRCode{ + id:qrcode + size:control.size-margins + anchors.centerIn: parent + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml b/src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml new file mode 100644 index 00000000..bb5b0f15 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluRadioButton.qml @@ -0,0 +1,98 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Button { + property string contentDescription: "" + property bool disabled: false + property color borderNormalColor: checked ? FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark : FluTheme.dark ? Qt.rgba(161/255,161/255,161/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color borderDisableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(198/255,198/255,198/255,1) + property color normalColor: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(1,1,1,1) + property color hoverColor: checked ? FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(1,1,1,1) : FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(222/255,222/255,222/255,1) + property color disableColor: checked ? FluTheme.dark ? Qt.rgba(159/255,159/255,159/255,1) : Qt.rgba(159/255,159/255,159/255,1) : FluTheme.dark ? Qt.rgba(43/255,43/255,43/255,1) : Qt.rgba(222/255,222/255,222/255,1) + property alias textColor: btn_text.textColor + property real size: 18 + property bool textRight: true + property real textSpacing: 6 + property var clickListener : function(){ + checked = !checked + } + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() + id:control + enabled: !disabled + horizontalPadding:2 + verticalPadding: 2 + background: Item{ + FluFocusRectangle{ + visible: control.activeFocus + } + } + focusPolicy:Qt.TabFocus + font:FluTextStyle.Body + onClicked: clickListener() + onCheckableChanged: { + if(checkable){ + checkable = false + } + } + contentItem: RowLayout{ + spacing: control.textSpacing + layoutDirection:control.textRight ? Qt.LeftToRight : Qt.RightToLeft + Rectangle{ + id:rect_check + width: control.size + height: control.size + radius: size/2 + border.width: { + if(checked&&!enabled){ + return 3 + } + if(pressed){ + if(checked){ + return 4 + } + return 1 + } + if(hovered){ + if(checked){ + return 3 + } + return 1 + } + return checked ? 4 : 1 + } + Behavior on border.width { + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 167 + easing.type: Easing.OutCubic + } + } + border.color: { + if(!enabled){ + return borderDisableColor + } + return borderNormalColor + } + color:{ + if(!enabled){ + return disableColor + } + if(hovered){ + return hoverColor + } + return normalColor + } + } + FluText{ + id:btn_text + text: control.text + Layout.alignment: Qt.AlignVCenter + font: control.font + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluRadioButtons.qml b/src/Qt5/imports/FluentUI/Controls/FluRadioButtons.qml new file mode 100644 index 00000000..84b41a5b --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluRadioButtons.qml @@ -0,0 +1,29 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +ColumnLayout { + default property alias buttons: control.data + property int currentIndex : -1 + id:control + onCurrentIndexChanged: { + for(var i = 0;i{ + d.mouseValue = Number(mouse.x / d.itemSize)+1 + } + onExited: { + d.mouseValue = 0 + } + onClicked: (mouse)=>{ + control.value = Number(mouse.x / d.itemSize)+1 + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluRectangle.qml b/src/Qt5/imports/FluentUI/Controls/FluRectangle.qml new file mode 100644 index 00000000..215f8068 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluRectangle.qml @@ -0,0 +1,71 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtGraphicalEffects 1.15 +import FluentUI 1.0 + +Item{ + property var radius:[0,0,0,0] + property color color : FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) + property bool shadow: true + default property alias contentItem: container.data + id:control + onWidthChanged: { + canvas.requestPaint() + } + onHeightChanged: { + canvas.requestPaint() + } + onRadiusChanged: { + canvas.requestPaint() + } + FluShadow{ + anchors.fill: container + radius: control.radius[0] + visible: { + if(control.radius[0] === control.radius[1] && control.radius[0] === control.radius[2] && control.radius[0] === control.radius[3] && control.shadow){ + return true + } + return false + } + } + Rectangle{ + id:container + width: control.width + height: control.height + opacity: 0 + color:control.color + } + Canvas { + id: canvas + anchors.fill: parent + visible: false + onPaint: { + var ctx = getContext("2d") + var x = 0 + var y = 0 + var w = control.width + var h = control.height + ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.save() + ctx.beginPath(); + ctx.moveTo(x + radius[0], y) + ctx.lineTo(x + w - radius[1], y) + ctx.arcTo(x + w, y, x + w, y + radius[1], radius[1]) + ctx.lineTo(x + w, y + h - radius[2]) + ctx.arcTo(x + w, y + h, x + w - radius[2], y + h, radius[2]) + ctx.lineTo(x + radius[3], y + h) + ctx.arcTo(x, y + h, x, y + h - radius[3], radius[3]) + ctx.lineTo(x, y + radius[0]) + ctx.arcTo(x, y, x + radius[0], y, radius[0]) + ctx.closePath() + ctx.fillStyle = "#000000" + ctx.fill() + ctx.restore() + } + } + OpacityMask { + anchors.fill: container + source: container + maskSource: canvas + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluRemoteLoader.qml b/src/Qt5/imports/FluentUI/Controls/FluRemoteLoader.qml new file mode 100644 index 00000000..0e5c6f53 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluRemoteLoader.qml @@ -0,0 +1,39 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluStatusView { + property url source: "" + property bool lazy: false + color:"transparent" + id:control + onErrorClicked: { + reload() + } + Component.onCompleted: { + if(!lazy){ + loader.source = control.source + } + } + Loader{ + id:loader + anchors.fill: parent + asynchronous: true + onStatusChanged: { + if(status === Loader.Error){ + control.statusMode = FluStatusViewType.Error + }else if(status === Loader.Loading){ + control.statusMode = FluStatusViewType.Loading + }else{ + control.statusMode = FluStatusViewType.Success + } + } + } + function reload(){ + var timestamp = Date.now(); + loader.source = control.source+"?"+timestamp + } + function itemLodaer(){ + return loader + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluScreenshot.qml b/src/Qt5/imports/FluentUI/Controls/FluScreenshot.qml new file mode 100644 index 00000000..22b7d04c --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluScreenshot.qml @@ -0,0 +1,523 @@ +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import Qt.labs.platform 1.1 +import FluentUI 1.0 + +Item{ + id:control + property int captrueMode: FluScreenshotType.Pixmap + property int dotSize: 5 + property int borderSize: 1 + property var saveFolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0] + property color borderColor: FluTheme.primaryColor.dark + signal captrueCompleted(var captrue) + QtObject{ + id:d + property int dotMouseSize: control.dotSize+10 + property int dotMargins: -(control.dotSize-control.borderSize)/2 + property bool enablePosition: false + property int menuMargins: 6 + } + Loader { + id:loader + } + Component{ + id:com_screen + Window{ + property bool isZeroPos: screenshot.start === Qt.point(0,0) && screenshot.end === Qt.point(0,0) + id:window_screen + flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint + x:-1 + y:-1 + width: 1 + height: 1 + visible: true + color: "#00000000" + onVisibleChanged: { + if(!window_screen.visible){ + loader.sourceComponent = undefined + } + } + Component.onCompleted: { + setGeometry(0,0,screenshot_background.width,screenshot_background.height) + } + ScreenshotBackground{ + id:screenshot_background + captureMode:control.captrueMode + saveFolder: { + if(typeof control.saveFolder === 'string'){ + return control.saveFolder + }else{ + return FluTools.toLocalPath(control.saveFolder) + } + } + onCaptrueToPixmapCompleted: + (captrue)=>{ + control.captrueCompleted(captrue) + loader.sourceComponent = undefined + } + onCaptrueToFileCompleted: + (captrue)=>{ + control.captrueCompleted(captrue) + loader.sourceComponent = undefined + } + } + Screenshot{ + id:screenshot + anchors.fill: parent + } + MouseArea{ + anchors.fill: parent + acceptedButtons: Qt.RightButton | Qt.LeftButton + onPressed: + (mouse)=>{ + if(mouse.button === Qt.LeftButton){ + d.enablePosition = true + screenshot.start = Qt.point(mouse.x,mouse.y) + screenshot.end = Qt.point(mouse.x,mouse.y) + } + } + onPositionChanged: + (mouse)=>{ + if(d.enablePosition){ + screenshot.end = Qt.point(mouse.x,mouse.y) + } + } + onReleased: + (mouse)=>{ + if(mouse.button === Qt.LeftButton){ + d.enablePosition = false + screenshot.end = Qt.point(mouse.x,mouse.y) + } + } + onCanceled: + (mouse)=>{ + if(mouse.button === Qt.LeftButton){ + d.enablePosition = false + screenshot.end = Qt.point(mouse.x,mouse.y) + } + } + onClicked: + (mouse)=>{ + if (mouse.button === Qt.RightButton){ + if(isZeroPos){ + loader.sourceComponent = undefined + return + } + screenshot.start = Qt.point(0,0) + screenshot.end = Qt.point(0,0) + } + } + } + Rectangle{ + id:rect_capture + x:Math.min(screenshot.start.x,screenshot.end.x) + y:Math.min(screenshot.start.y,screenshot.end.y) + width: Math.abs(screenshot.end.x - screenshot.start.x) + height: Math.abs(screenshot.end.y - screenshot.start.y) + color:"#00000000" + border.width: control.borderSize + border.color: control.borderColor + MouseArea{ + property point clickPos: Qt.point(0,0) + anchors.fill: parent + cursorShape: Qt.SizeAllCursor + onPressed: + (mouse)=>{ + clickPos = Qt.point(mouse.x, mouse.y) + } + onPositionChanged: + (mouse)=>{ + var delta = Qt.point(mouse.x - clickPos.x,mouse.y - clickPos.y) + var w = Math.abs(screenshot.end.x - screenshot.start.x) + var h = Math.abs(screenshot.end.y - screenshot.start.y) + var x = Math.min(Math.max(rect_capture.x + delta.x,0),window_screen.width-w) + var y =Math.min(Math.max(rect_capture.y + delta.y,0),window_screen.height-h) + screenshot.start = Qt.point(x,y) + screenshot.end = Qt.point(x+w,y+h) + } + } + } + Rectangle{ + id:rect_top_left + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + left: rect_capture.left + leftMargin: d.dotMargins + topMargin: d.dotMargins + top: rect_capture.top + } + } + MouseArea{ + cursorShape: Qt.SizeFDiagCursor + anchors.centerIn: rect_top_left + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + FluTools.setOverrideCursor(cursorShape) + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x+w,y+h) + screenshot.end = Qt.point(x,y) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + screenshot.end = mapToItem(screenshot,Qt.point(mouse.x,mouse.y)) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Rectangle{ + id:rect_top_center + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + horizontalCenter: rect_capture.horizontalCenter + topMargin: d.dotMargins + top: rect_capture.top + } + } + MouseArea{ + cursorShape: Qt.SizeVerCursor + anchors.centerIn: rect_top_center + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + FluTools.setOverrideCursor(cursorShape) + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x+w,y+h) + screenshot.end = Qt.point(x,y) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + var x = rect_capture.x + screenshot.end = Qt.point(x,mapToItem(screenshot,Qt.point(mouse.x,mouse.y)).y) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Rectangle{ + id:rect_top_right + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + right: rect_capture.right + rightMargin: d.dotMargins + topMargin: d.dotMargins + top: rect_capture.top + } + } + MouseArea{ + cursorShape: Qt.SizeBDiagCursor + anchors.centerIn: rect_top_right + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x,y+h) + screenshot.end = Qt.point(x+w,y) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + screenshot.end = mapToItem(screenshot,Qt.point(mouse.x,mouse.y)) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Rectangle{ + id:rect_right_center + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + right: rect_capture.right + rightMargin: d.dotMargins + verticalCenter: rect_capture.verticalCenter + } + } + MouseArea{ + cursorShape: Qt.SizeHorCursor + anchors.centerIn: rect_right_center + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x,y) + screenshot.end = Qt.point(x+w,y+h) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + var y = rect_capture.y + var h = rect_capture.height + screenshot.end = Qt.point(mapToItem(screenshot,Qt.point(mouse.x,mouse.y)).x,y+h) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Rectangle{ + id:rect_right_bottom + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + right: rect_capture.right + rightMargin: d.dotMargins + bottom: rect_capture.bottom + bottomMargin: d.dotMargins + } + } + MouseArea{ + cursorShape: Qt.SizeFDiagCursor + anchors.centerIn: rect_right_bottom + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x,y) + screenshot.end = Qt.point(x+w,y+h) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + screenshot.end = mapToItem(screenshot,Qt.point(mouse.x,mouse.y)) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Rectangle{ + id:rect_bottom_center + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + horizontalCenter: rect_capture.horizontalCenter + bottom: rect_capture.bottom + bottomMargin: d.dotMargins + } + } + MouseArea{ + cursorShape: Qt.SizeVerCursor + anchors.centerIn: rect_bottom_center + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x,y) + screenshot.end = Qt.point(x+w,y+h) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + var x = rect_capture.x + var w = rect_capture.width + screenshot.end = Qt.point(x+w,mapToItem(screenshot,Qt.point(mouse.x,mouse.y)).y) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Rectangle{ + id:rect_bottom_left + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + left: rect_capture.left + leftMargin: d.dotMargins + bottom: rect_capture.bottom + bottomMargin: d.dotMargins + } + } + MouseArea{ + cursorShape: Qt.SizeBDiagCursor + anchors.centerIn: rect_bottom_left + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x+w,y) + screenshot.end = Qt.point(x,y+h) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + screenshot.end = mapToItem(screenshot,Qt.point(mouse.x,mouse.y)) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Rectangle{ + id:rect_left_center + width: control.dotSize + height: control.dotSize + color: control.borderColor + visible: !isZeroPos + anchors{ + left: rect_capture.left + leftMargin: d.dotMargins + verticalCenter: rect_capture.verticalCenter + } + } + MouseArea{ + cursorShape: Qt.SizeHorCursor + anchors.centerIn: rect_left_center + width: d.dotMouseSize + height: d.dotMouseSize + visible: !isZeroPos + onPressed: + (mouse)=> { + var x = rect_capture.x + var y = rect_capture.y + var w = rect_capture.width + var h = rect_capture.height + screenshot.start = Qt.point(x+w,y) + screenshot.end = Qt.point(x,y+h) + } + onReleased: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=> { + var y = rect_capture.y + var h = rect_capture.height + screenshot.end = Qt.point(mapToItem(screenshot,Qt.point(mouse.x,mouse.y)).x,y+h) + } + onCanceled: + (mouse)=> { + FluTools.restoreOverrideCursor() + } + } + Pane{ + width: 100 + height: 40 + visible: { + if(screenshot.start === Qt.point(0,0) && screenshot.end === Qt.point(0,0)){ + return false + } + if(d.enablePosition){ + return false + } + return true + } + x:rect_capture.x + rect_capture.width - width + y:{ + if(rect_capture.y + rect_capture.height + d.menuMargins < screenshot.height-height){ + return rect_capture.y + rect_capture.height + d.menuMargins + }else if(rect_capture.y - height - d.menuMargins > 0){ + return rect_capture.y - height - d.menuMargins + }else{ + screenshot.height - height - d.menuMargins + } + } + RowLayout{ + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + FluIconButton{ + iconSource: FluentIcons.Cancel + iconSize: 18 + iconColor: Qt.rgba(247/255,75/255,77/255,1) + onClicked: { + loader.sourceComponent = undefined + } + } + FluIconButton{ + iconSource: FluentIcons.AcceptMedium + iconColor: FluTheme.primaryColor.dark + onClicked: { + screenshot_background.capture(screenshot.start,screenshot.end) + } + } + } + } + } + } + function open(){ + loader.sourceComponent = com_screen + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluScrollBar.qml b/src/Qt5/imports/FluentUI/Controls/FluScrollBar.qml new file mode 100644 index 00000000..92766a32 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluScrollBar.qml @@ -0,0 +1,85 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.ScrollBar { + id: control + + property color color : FluTheme.dark ? Qt.rgba(159/255,159/255,159/255,1) : Qt.rgba(138/255,138/255,138/255,1) + property color pressedColor: FluTheme.dark ? Qt.darker(color,1.2) : Qt.lighter(color,1.2) + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 2 + visible: control.policy !== T.ScrollBar.AlwaysOff + minimumSize: Math.max(orientation === Qt.Horizontal ? height / width : width / height,0.3) + contentItem: Item { + property bool collapsed: (control.policy === T.ScrollBar.AlwaysOn || (control.active && control.size < 1.0)) + implicitWidth: control.interactive ? 6 : 2 + implicitHeight: control.interactive ? 6 : 2 + + Rectangle{ + id:rect_bar + width: vertical ? 2 : parent.width + height: horizontal ? 2 : parent.height + color:{ + if(control.pressed){ + return control.pressedColor + } + return control .color + } + anchors{ + right: vertical ? parent.right : undefined + bottom: horizontal ? parent.bottom : undefined + } + radius: width / 2 + visible: control.size < 1.0 + } + states: [ + State{ + name:"show" + when: contentItem.collapsed + PropertyChanges { + target: rect_bar + width: vertical ? 6 : parent.width + height: horizontal ? 6 : parent.height + } + } + ,State{ + name:"hide" + when: !contentItem.collapsed + PropertyChanges { + target: rect_bar + width: vertical ? 2 : parent.width + height: horizontal ? 2 : parent.height + } + } + ] + transitions:[ + Transition { + to: "hide" + SequentialAnimation { + PauseAnimation { duration: 450 } + NumberAnimation { + target: rect_bar + properties: vertical ? "width" : "height" + duration: 167 + easing.type: Easing.OutCubic + } + } + } + ,Transition { + to: "show" + NumberAnimation { + target: rect_bar + properties: vertical ? "width" : "height" + duration: 167 + easing.type: Easing.OutCubic + } + } + ] + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluScrollIndicator.qml b/src/Qt5/imports/FluentUI/Controls/FluScrollIndicator.qml new file mode 100644 index 00000000..13e1dcb3 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluScrollIndicator.qml @@ -0,0 +1,48 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T + +T.ScrollIndicator { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 2 + + contentItem: Rectangle { + implicitWidth: 2 + implicitHeight: 2 + + color: control.palette.mid + visible: control.size < 1.0 + opacity: 0.0 + + states: State { + name: "active" + when: control.active + PropertyChanges { + target: control + contentItem.opacity: 0.75 + } + } + + transitions: [ + Transition { + from: "active" + SequentialAnimation { + PauseAnimation { + duration: 450 + } + NumberAnimation { + target: control.contentItem + duration: 200 + property: "opacity" + to: 0.0 + } + } + } + ] + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluScrollablePage.qml b/src/Qt5/imports/FluentUI/Controls/FluScrollablePage.qml new file mode 100644 index 00000000..1f3b949c --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluScrollablePage.qml @@ -0,0 +1,79 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluPage { + property alias title: text_title.text + default property alias content: container.data + property int spacing : 0 + property int leftPadding: 10 + property int topPadding: 0 + property int rightPadding: 10 + property int bottomPadding: 10 + property alias color: status_view.color + property alias statusMode: status_view.statusMode + property alias loadingText: status_view.loadingText + property alias emptyText:status_view.emptyText + property alias errorText:status_view.errorText + property alias errorButtonText:status_view.errorButtonText + property alias loadingItem :status_view.loadingItem + property alias emptyItem : status_view.emptyItem + property alias errorItem :status_view.errorItem + signal errorClicked + id:control + FluText{ + id:text_title + font: FluTextStyle.Title + visible: text !== "" + height: visible ? contentHeight : 0 + padding: 0 + anchors{ + top: parent.top + topMargin: control.topPadding + left: parent.left + right: parent.right + leftMargin: control.leftPadding + rightMargin: control.rightPadding + } + } + FluStatusView{ + id:status_view + color: "#00000000" + statusMode: FluStatusViewType.Success + onErrorClicked: control.errorClicked() + anchors{ + left: parent.left + right: parent.right + top: text_title.bottom + bottom: parent.bottom + bottomMargin: control.bottomPadding + } + Flickable{ + id:flickview + clip: true + anchors.fill: parent + contentWidth: parent.width + contentHeight: container.height + ScrollBar.vertical: FluScrollBar { + anchors.right: flickview.right + anchors.rightMargin: 2 + } + boundsBehavior: Flickable.StopAtBounds + ColumnLayout{ + id:container + spacing: control.spacing + clip: true + anchors{ + left: parent.left + right: parent.right + top: parent.top + leftMargin: control.leftPadding + rightMargin: control.rightPadding + } + width: parent.width + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluShadow.qml b/src/Qt5/imports/FluentUI/Controls/FluShadow.qml new file mode 100644 index 00000000..38f4be88 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluShadow.qml @@ -0,0 +1,66 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Item { + + property color color: FluTheme.dark ? "#FFFFFF" : "#999999" + property int radius: 4 + id:control + anchors.fill: parent + anchors.margins: -4 + Rectangle{ + width: control.width + height: control.height + anchors.centerIn: parent + color: "#00000000" + opacity: 0.02 + border.width: 1 + radius: control.radius + border.color: control.color + } + + Rectangle{ + width: control.width - 2 + height: control.height - 2 + anchors.centerIn: parent + color: "#00000000" + opacity: 0.04 + border.width: 1 + radius: control.radius + border.color: control.color + } + Rectangle{ + width: control.width - 4 + height: control.height - 4 + anchors.centerIn: parent + color: "#00000000" + opacity: 0.06 + border.width: 1 + radius: control.radius + border.color: control.color + } + + Rectangle{ + width: control.width - 6 + height: control.height - 6 + anchors.centerIn: parent + color: "#00000000" + opacity: 0.08 + border.width: 1 + radius: control.radius + border.color: control.color + } + + Rectangle{ + width: control.width - 8 + height: control.height - 8 + anchors.centerIn: parent + opacity: 0.1 + radius: control.radius + color: "#00000000" + border.width: 1 + border.color: control.color + } + +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluSlider.qml b/src/Qt5/imports/FluentUI/Controls/FluSlider.qml new file mode 100644 index 00000000..504b809d --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluSlider.qml @@ -0,0 +1,73 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.Slider { + property bool tooltipEnabled: true + id: control + to:100 + stepSize:1 + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitHandleWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitHandleHeight + topPadding + bottomPadding) + padding: 6 + handle: Rectangle { + x: control.leftPadding + (control.horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height)) + implicitWidth: 24 + implicitHeight: 24 + radius: 12 + color:FluTheme.dark ? Qt.rgba(69/255,69/255,69/255,1) :Qt.rgba(1,1,1,1) + FluShadow{ + radius: 12 + } + Rectangle{ + width: 24 + height: 24 + radius: 12 + color:FluTheme.dark ? FluTheme.primaryColor.lighter :FluTheme.primaryColor.dark + anchors.centerIn: parent + scale: { + if(control.pressed){ + return 4/10 + } + return control.hovered ? 6/10 : 5/10 + } + Behavior on scale { + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 167 + easing.type: Easing.OutCubic + } + } + } + } + background: Item { + x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2) + y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0) + implicitWidth: control.horizontal ? 180 : 6 + implicitHeight: control.horizontal ? 6 : 180 + width: control.horizontal ? control.availableWidth : implicitWidth + height: control.horizontal ? implicitHeight : control.availableHeight + Rectangle{ + anchors.fill: parent + anchors.margins: 1 + radius: 2 + color:FluTheme.dark ? Qt.rgba(162/255,162/255,162/255,1) : Qt.rgba(138/255,138/255,138/255,1) + } + scale: control.horizontal && control.mirrored ? -1 : 1 + Rectangle { + y: control.horizontal ? 0 : control.visualPosition * parent.height + width: control.horizontal ? control.position * parent.width : 6 + height: control.horizontal ? 6 : control.position * parent.height + radius: 3 + color:FluTheme.dark ? FluTheme.primaryColor.lighter :FluTheme.primaryColor.dark + } + } + FluTooltip{ + parent: control.handle + visible: control.tooltipEnabled && control.pressed + text:String(control.value) + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml b/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml new file mode 100644 index 00000000..917e2f66 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluSpinBox.qml @@ -0,0 +1,156 @@ +import QtQuick 2.15 +import QtQuick.Templates 2.15 as T +import FluentUI 1.0 + +T.SpinBox { + id: control + property bool disabled: false + property color normalColor: FluTheme.dark ? Qt.rgba(56/255,56/255,56/255,1) : Qt.rgba(232/255,232/255,232/255,1) + property color hoverColor: FluTheme.dark ? Qt.rgba(64/255,64/255,64/255,1) : Qt.rgba(224/255,224/255,224/255,1) + property color pressedColor: FluTheme.dark ? Qt.rgba(72/255,72/255,72/255,1) : Qt.rgba(216/255,216/255,216/255,1) + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentItem.implicitWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + up.implicitIndicatorHeight, down.implicitIndicatorHeight) + leftPadding: padding + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0)) + rightPadding: padding + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0)) + enabled: !disabled + validator: IntValidator { + locale: control.locale.name + bottom: Math.min(control.from, control.to) + top: Math.max(control.from, control.to) + } + + contentItem: TextInput { + property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + z: 2 + text: control.displayText + clip: width < implicitWidth + padding: 6 + font: control.font + color: { + if(!enabled){ + return disableColor + } + return normalColor + } + selectionColor: FluTools.colorAlpha(FluTheme.primaryColor.lightest,0.6) + selectedTextColor: color + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + readOnly: !control.editable + validator: control.validator + inputMethodHints: control.inputMethodHints + Rectangle{ + width: parent.width + height: contentItem.activeFocus ? 3 : 1 + anchors.bottom: parent.bottom + visible: contentItem.enabled + color: { + if(FluTheme.dark){ + contentItem.activeFocus ? FluTheme.primaryColor.lighter : Qt.rgba(166/255,166/255,166/255,1) + }else{ + return contentItem.activeFocus ? FluTheme.primaryColor.dark : Qt.rgba(183/255,183/255,183/255,1) + } + } + Behavior on height{ + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 83 + easing.type: Easing.OutCubic + } + } + } + } + + up.indicator: FluItem { + x: control.mirrored ? 0 : control.width - width + height: control.height + implicitWidth: 32 + implicitHeight: 32 + radius: [0,4,4,0] + Rectangle{ + anchors.fill: parent + color: { + if(control.up.pressed){ + return control.pressedColor + } + if(control.up.hovered){ + return control.hoverColor + } + return control.normalColor + } + } + Rectangle { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: parent.width / 3 + height: 2 + color: enabled ? FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1) : FluColors.Grey90 + } + Rectangle { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: 2 + height: parent.width / 3 + color: enabled ? FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1) : FluColors.Grey90 + } + } + + + down.indicator: FluItem { + x: control.mirrored ? parent.width - width : 0 + height: control.height + implicitWidth: 32 + implicitHeight: 32 + radius: [4,0,0,4] + Rectangle{ + anchors.fill: parent + color: { + if(control.down.pressed){ + return control.pressedColor + } + if(control.down.hovered){ + return control.hoverColor + } + return normalColor + } + } + Rectangle { + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: parent.width / 3 + height: 2 + color: enabled ? FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1) : FluColors.Grey90 + } + } + + background: Rectangle { + implicitWidth: 136 + radius: 4 + border.width: 1 + border.color: { + if(contentItem.disabled){ + return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(237/255,237/255,237/255,1) + } + return FluTheme.dark ? Qt.rgba(76/255,76/255,76/255,1) : Qt.rgba(240/255,240/255,240/255,1) + } + color: { + if(contentItem.disabled){ + return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + } + if(contentItem.activeFocus){ + return FluTheme.dark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1) + } + if(contentItem.hovered){ + return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + } + return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1) + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluStatusView.qml b/src/Qt5/imports/FluentUI/Controls/FluStatusView.qml new file mode 100644 index 00000000..6fac6d3d --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluStatusView.qml @@ -0,0 +1,116 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Item{ + id:control + default property alias content: container.data + property int statusMode: FluStatusViewType.Loading + property string loadingText:"正在加载..." + property string emptyText: "空空如也" + property string errorText: "页面出错了.." + property string errorButtonText: "重新加载" + 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) + signal errorClicked + property Component loadingItem : com_loading + property Component emptyItem : com_empty + property Component errorItem : com_error + + Item{ + id:container + anchors.fill: parent + visible: statusMode===FluStatusViewType.Success + } + Loader{ + id:loader + anchors.fill: parent + visible: statusMode!==FluStatusViewType.Success + sourceComponent: { + if(statusMode === FluStatusViewType.Loading){ + return loadingItem + } + if(statusMode === FluStatusViewType.Empty){ + return emptyItem + } + if(statusMode === FluStatusViewType.Error){ + return errorItem + } + return undefined + } + } + Component{ + id:com_loading + FluArea{ + paddings: 0 + border.width: 0 + radius: 0 + color:control.color + ColumnLayout{ + anchors.centerIn: parent + FluProgressRing{ + indeterminate: true + Layout.alignment: Qt.AlignHCenter + } + FluText{ + text:control.loadingText + Layout.alignment: Qt.AlignHCenter + } + } + } + } + Component { + id:com_empty + FluArea{ + paddings: 0 + border.width: 0 + radius: 0 + color:control.color + ColumnLayout{ + anchors.centerIn: parent + FluText{ + text:control.emptyText + font: FluTextStyle.BodyStrong + Layout.alignment: Qt.AlignHCenter + } + } + } + } + Component{ + id:com_error + FluArea{ + paddings: 0 + border.width: 0 + radius: 0 + color:control.color + ColumnLayout{ + anchors.centerIn: parent + FluText{ + text:control.errorText + font: FluTextStyle.BodyStrong + Layout.alignment: Qt.AlignHCenter + } + FluFilledButton{ + id:btn_error + Layout.alignment: Qt.AlignHCenter + text:control.errorButtonText + onClicked:{ + control.errorClicked() + } + } + } + } + } + function showSuccessView(){ + statusMode = FluStatusViewType.Success + } + function showLoadingView(){ + statusMode = FluStatusViewType.Loading + } + function showEmptyView(){ + statusMode = FluStatusViewType.Empty + } + function showErrorView(){ + statusMode = FluStatusViewType.Error + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTabView.qml b/src/Qt5/imports/FluentUI/Controls/FluTabView.qml new file mode 100644 index 00000000..7554a390 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTabView.qml @@ -0,0 +1,307 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import FluentUI 1.0 + +Item { + property int tabWidthBehavior : FluTabViewType.Equal + property int closeButtonVisibility : FluTabViewType.Always + property int itemWidth: 146 + property bool addButtonVisibility: true + signal newPressed + id:control + implicitHeight: height + implicitWidth: width + anchors.fill: { + if(parent) + return parent + return undefined + } + QtObject { + id: d + property int dragIndex: -1 + property bool dragBehavior: false + property bool itemPress: false + property int maxEqualWidth: 240 + } + MouseArea{ + anchors.fill: parent + preventStealing: true + } + ListModel{ + id:tab_model + } + FluIconButton{ + id:btn_new + visible: addButtonVisibility + width: 34 + height: 34 + x:Math.min(tab_nav.contentWidth,tab_nav.width) + anchors.top: parent.top + iconSource: FluentIcons.Add + onClicked: { + newPressed() + } + } + ListView{ + id:tab_nav + height: 34 + orientation: ListView.Horizontal + anchors{ + top: parent.top + left: parent.left + right: parent.right + rightMargin: 34 + } + interactive: false + model: tab_model + move: Transition { + NumberAnimation { properties: "x"; duration: 100; easing.type: Easing.OutCubic } + NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.OutCubic } + } + moveDisplaced: Transition { + NumberAnimation { properties: "x"; duration: 300; easing.type: Easing.OutCubic} + NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.OutCubic } + } + clip: true + ScrollBar.horizontal: ScrollBar{ + id: scroll_nav + policy: ScrollBar.AlwaysOff + } + delegate: Item{ + width: item_layout.width + height: item_container.height + z: item_mouse_drag.pressed ? 1000 : 1 + Item{ + id:item_layout + width: item_container.width + height: item_container.height + FluItem{ + id:item_container + property real timestamp: new Date().getTime() + height: tab_nav.height + width: { + if(tabWidthBehavior === FluTabViewType.Equal){ + return Math.max(Math.min(d.maxEqualWidth,tab_nav.width/tab_nav.count),41 + item_btn_close.width) + } + if(tabWidthBehavior === FluTabViewType.SizeToContent){ + return itemWidth + } + if(tabWidthBehavior === FluTabViewType.Compact){ + return item_mouse_hove.containsMouse || item_btn_close.hovered || tab_nav.currentIndex === index ? itemWidth : 41 + item_btn_close.width + } + return Math.max(Math.min(d.maxEqualWidth,tab_nav.width/tab_nav.count),41 + item_btn_close.width) + } + radius: [6,6,0,0] + Behavior on x { enabled: d.dragBehavior; NumberAnimation { duration: 200 } } + Behavior on y { enabled: d.dragBehavior; NumberAnimation { duration: 200 } } + MouseArea{ + id:item_mouse_hove + anchors.fill: parent + hoverEnabled: true + } + FluTooltip{ + visible: item_mouse_hove.containsMouse + text:item_text.text + delay: 1000 + } + MouseArea{ + id:item_mouse_drag + anchors.fill: parent + drag.target: item_container + drag.axis: Drag.XAxis + onWheel: (wheel)=>{ + if (wheel.angleDelta.y > 0) scroll_nav.decrease() + else scroll_nav.increase() + } + onPressed: { + d.itemPress = true + item_container.timestamp = new Date().getTime(); + d.dragBehavior = false; + var pos = tab_nav.mapFromItem(item_container, 0, 0) + d.dragIndex = model.index + item_container.parent = tab_nav + item_container.x = pos.x + item_container.y = pos.y + } + onReleased: { + d.itemPress = false + timer.stop() + var timeDiff = new Date().getTime() - item_container.timestamp + if (timeDiff < 300) { + tab_nav.currentIndex = index + } + d.dragIndex = -1; + var pos = tab_nav.mapToItem(item_layout, item_container.x, item_container.y) + item_container.parent = item_layout; + item_container.x = pos.x; + item_container.y = pos.y; + d.dragBehavior = true; + item_container.x = 0; + item_container.y = 0; + } + onPositionChanged: { + var pos = tab_nav.mapFromItem(item_container, 0, 0) + updatePosition(pos) + if(pos.x<0){ + timer.isIncrease = false + timer.restart() + }else if(pos.x>tab_nav.width-itemWidth){ + timer.isIncrease = true + timer.restart() + }else{ + timer.stop() + } + } + Timer{ + id:timer + property bool isIncrease: true + interval: 10 + repeat: true + onTriggered: { + if(isIncrease){ + if(tab_nav.contentX>=tab_nav.contentWidth-tab_nav.width){ + return + } + tab_nav.contentX = tab_nav.contentX+2 + }else{ + if(tab_nav.contentX<=0){ + return + } + tab_nav.contentX = tab_nav.contentX-2 + } + item_mouse_drag.updatePosition(tab_nav.mapFromItem(item_container, 0, 0)) + } + } + function updatePosition(pos){ + var idx = tab_nav.indexAt(pos.x+tab_nav.contentX+1, pos.y) + var firstIdx = tab_nav.indexAt(tab_nav.contentX+1, pos.y) + var lastIdx = tab_nav.indexAt(tab_nav.width+tab_nav.contentX-1, pos.y) + if(lastIdx === -1){ + lastIdx = tab_nav.count-1 + } + if (idx!==-1 && idx >= firstIdx && idx <= lastIdx && d.dragIndex !== idx) { + tab_model.move(d.dragIndex, idx, 1) + d.dragIndex = idx; + } + } + } + Rectangle{ + anchors.fill: parent + color: { + if(FluTheme.dark){ + if(item_mouse_hove.containsMouse || item_btn_close.hovered){ + return Qt.rgba(1,1,1,0.03) + } + if(tab_nav.currentIndex === index){ + return Qt.rgba(1,1,1,0.06) + } + return Qt.rgba(0,0,0,0) + }else{ + if(item_mouse_hove.containsMouse || item_btn_close.hovered){ + return Qt.rgba(0,0,0,0.03) + } + if(tab_nav.currentIndex === index){ + return Qt.rgba(0,0,0,0.06) + } + return Qt.rgba(0,0,0,0) + } + } + } + RowLayout{ + spacing: 0 + height: parent.height + Image{ + source:model.icon + Layout.leftMargin: 10 + Layout.preferredWidth: 14 + Layout.preferredHeight: 14 + Layout.alignment: Qt.AlignVCenter + } + FluText{ + id:item_text + text: model.text + Layout.leftMargin: 10 + visible: { + if(tabWidthBehavior === FluTabViewType.Equal){ + return true + } + if(tabWidthBehavior === FluTabViewType.SizeToContent){ + return true + } + if(tabWidthBehavior === FluTabViewType.Compact){ + return item_mouse_hove.containsMouse || item_btn_close.hovered || tab_nav.currentIndex === index + } + return false + } + Layout.preferredWidth: visible?item_container.width - 41 - item_btn_close.width:0 + elide: Text.ElideRight + Layout.alignment: Qt.AlignVCenter + } + } + FluIconButton{ + id:item_btn_close + iconSource: FluentIcons.ChromeClose + iconSize: 10 + width: visible ? 24 : 0 + height: 24 + visible: { + if(closeButtonVisibility === FluTabViewType.Nerver) + return false + if(closeButtonVisibility === FluTabViewType.OnHover) + return item_mouse_hove.containsMouse || item_btn_close.hovered + return true + } + anchors{ + right: parent.right + rightMargin: 5 + verticalCenter: parent.verticalCenter + } + onClicked: { + tab_model.remove(index) + } + } + FluDivider{ + width: 1 + height: 16 + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + } + } + } + } + } + } + Item{ + id:container + anchors{ + top: tab_nav.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + Repeater{ + model:tab_model + Loader{ + property var argument: model.argument + anchors.fill: parent + sourceComponent: model.page + visible: tab_nav.currentIndex === index + } + } + } + function createTab(icon,text,page,argument={}){ + return {icon:icon,text:text,page:page,argument:argument} + } + function appendTab(icon,text,page,argument){ + tab_model.append(createTab(icon,text,page,argument)) + } + function setTabList(list){ + tab_model.clear() + tab_model.append(list) + } + function count(){ + return tab_nav.count + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTableModelColumn.qml b/src/Qt5/imports/FluentUI/Controls/FluTableModelColumn.qml new file mode 100644 index 00000000..b3a1fd01 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTableModelColumn.qml @@ -0,0 +1,5 @@ +import Qt.labs.qmlmodels 1.0 + +TableModelColumn{ + +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTableView.qml b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml new file mode 100644 index 00000000..6be63d77 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTableView.qml @@ -0,0 +1,531 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import Qt.labs.qmlmodels 1.0 +import FluentUI 1.0 + +Rectangle { + property var columnSource + property var dataSource + property color selectionColor: FluTools.colorAlpha(FluTheme.primaryColor.lightest,0.6) + property color hoverButtonColor: FluTools.colorAlpha(selectionColor,0.2) + property color pressedButtonColor: FluTools.colorAlpha(selectionColor,0.4) + id:control + color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1) + onColumnSourceChanged: { + if(columnSource.length!==0){ + var com_column = Qt.createComponent("FluTableModelColumn.qml") + if (com_column.status === Component.Ready) { + var columns= [] + var header_rows = {} + columnSource.forEach(function(item){ + var column = com_column.createObject(table_model,{display:item.dataIndex}); + columns.push(column) + header_rows[item.dataIndex] = item.title + }) + table_model.columns = columns + header_model.columns = columns + d.header_rows = [header_rows] + } + } + } + QtObject{ + id:d + property int defaultItemWidth: 100 + property int defaultItemHeight: 42 + property var header_rows:[] + property bool selectionFlag: true + function obtEditDelegate(column,row){ + var display = table_model.data(table_model.index(row,column),"display") + var cellItem = table_view.itemAtCell(column, row) + var cellPosition = cellItem.mapToItem(scroll_table, 0, 0) + item_loader.column = column + item_loader.row = row + item_loader.x = table_view.contentX + cellPosition.x + item_loader.y = table_view.contentY + cellPosition.y + item_loader.width = table_view.columnWidthProvider(column) + item_loader.height = table_view.rowHeightProvider(row) + item_loader.display = display + var obj =columnSource[column].editDelegate + if(obj){ + return obj + } + if(columnSource[column].editMultiline === true){ + return com_edit_multiline + } + return com_edit + } + } + onDataSourceChanged: { + table_model.clear() + dataSource.forEach(function(item){ + table_model.appendRow(item) + }) + } + TableModel { + id:table_model + } + Component{ + id:com_edit + FluTextBox{ + text: display + readOnly: true === columnSource[column].readOnly + Component.onCompleted: { + forceActiveFocus() + selectAll() + } + onCommit: { + if(!readOnly){ + display = text + } + tableView.closeEditor() + } + } + } + Component{ + id:com_edit_multiline + Item{ + anchors.fill: parent + ScrollView{ + id:item_scroll + clip: true + anchors.fill: parent + ScrollBar.vertical: FluScrollBar{ + parent: item_scroll + x: item_scroll.mirrored ? 0 : item_scroll.width - width + y: item_scroll.topPadding + height: item_scroll.availableHeight + active: item_scroll.ScrollBar.horizontal.active + } + FluMultilineTextBox { + id:text_box + text: display + readOnly: true === columnSource[column].readOnly + verticalAlignment: TextInput.AlignVCenter + Component.onCompleted: { + forceActiveFocus() + selectAll() + } + rightPadding: 24 + onCommit: { + if(!readOnly){ + display = text + } + tableView.closeEditor() + } + } + } + FluIconButton{ + iconSource:FluentIcons.ChromeClose + iconSize: 10 + width: 20 + height: 20 + visible: { + if(text_box.readOnly) + return false + return text_box.text !== "" + } + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 5 + } + onClicked:{ + text_box.text = "" + } + } + } + } + Component{ + id:com_text + FluText { + id:item_text + text: itemData + anchors.fill: parent + anchors.margins: 10 + elide: Text.ElideRight + wrapMode: Text.WrapAnywhere + verticalAlignment: Text.AlignVCenter + HoverHandler{ + id: hover_handler + } + FluTooltip{ + text: item_text.text + delay: 500 + visible: item_text.contentWidth < item_text.implicitWidth && item_text.contentHeight < item_text.implicitHeight && hover_handler.hovered + } + } + } + ScrollView{ + id:scroll_table + anchors.left: header_vertical.right + anchors.top: header_horizontal.bottom + anchors.right: parent.right + anchors.bottom: parent.bottom + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + ScrollBar.vertical.policy: ScrollBar.AlwaysOff + TableView { + id:table_view + ListModel{ + id:model_columns + } + boundsBehavior: Flickable.StopAtBounds + ScrollBar.horizontal: FluScrollBar{ + id:scroll_bar_h + } + ScrollBar.vertical: FluScrollBar{ + id:scroll_bar_v + } + columnWidthProvider: function(column) { + var w = columnSource[column].width + if(!w){ + w = columnSource[column].minimumWidth + } + if(!w){ + w = d.defaultItemWidth + } + if(column === item_loader.column){ + item_loader.width = w + } + if(column === item_loader.column-1){ + let cellItem = table_view.itemAtCell(item_loader.column, item_loader.row) + if(cellItem){ + let cellPosition = cellItem.mapToItem(scroll_table, 0, 0) + item_loader.x = table_view.contentX + cellPosition.x + } + } + return w + } + rowHeightProvider: function(row) { + if(row>=table_model.rowCount){ + return 0 + } + var h = table_model.getRow(row).height + if(!h){ + h = table_model.getRow(row).minimumHeight + } + if(!h){ + return d.defaultItemHeight + } + if(row === item_loader.row){ + item_loader.height = h + } + if(row === item_loader.row-1){ + let cellItem = table_view.itemAtCell(item_loader.column, item_loader.row) + if(cellItem){ + let cellPosition = cellItem.mapToItem(scroll_table, 0, 0) + item_loader.y = table_view.contentY + cellPosition.y + } + } + return h + } + model: table_model + clip: true + delegate: Rectangle { + id:item_table + property var position: Qt.point(column,row) + color: (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06)) + implicitHeight: 40 + implicitWidth: { + var w = columnSource[column].width + if(!w){ + w = columnSource[column].minimumWidth + } + if(!w){ + w = d.defaultItemWidth + } + return w + } + Rectangle{ + anchors.fill: parent + visible: !item_loader.sourceComponent + color: "#00000000" + } + MouseArea{ + anchors.fill: parent + acceptedButtons: Qt.LeftButton + onPressed:{ + closeEditor() + table_view.interactive = false + } + onCanceled: { + table_view.interactive = true + } + onReleased: { + table_view.interactive = true + } + onDoubleClicked:{ + if(display instanceof Component){ + return + } + item_loader.sourceComponent = d.obtEditDelegate(column,row) + } + onClicked: + (event)=>{ + item_loader.sourceComponent = undefined + d.selectionFlag = !d.selectionFlag + event.accepted = true + } + } + Loader{ + property var itemData: display + property var tableView: table_view + property var tableModel: table_model + property var position: item_table.position + property int row: position.y + property int column: position.x + anchors.fill: parent + sourceComponent: { + if(itemData instanceof Component){ + return itemData + } + return com_text + } + } + } + } + Loader{ + id:item_loader + z:2 + property var display + property int column + property int row + property var tableView: control + sourceComponent: undefined + onDisplayChanged: { + var obj = table_model.getRow(row) + obj[columnSource[column].dataIndex] = display + table_model.setRow(row,obj) + } + } + } + Component{ + id:com_handle + Item {} + } + TableView { + id: header_horizontal + model: TableModel{ + id:header_model + rows: d.header_rows + } + syncDirection: Qt.Horizontal + anchors.left: scroll_table.left + anchors.top: parent.top + implicitWidth: syncView ? syncView.width : 0 + implicitHeight: Math.max(1, contentHeight) + syncView: table_view + boundsBehavior: Flickable.StopAtBounds + clip: true + delegate: Rectangle { + id:column_item_control + readonly property real cellPadding: 8 + property bool canceled: false + readonly property var obj : columnSource[column] + implicitWidth: column_text.implicitWidth + (cellPadding * 2) + implicitHeight: Math.max(36, column_text.implicitHeight + (cellPadding * 2)) + color:{ + d.selectionFlag + if(column_item_control_mouse.pressed){ + return control.pressedButtonColor + } + return column_item_control_mouse.containsMouse&&!canceled ? control.hoverButtonColor : FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1) + } + border.color: FluTheme.dark ? "#252525" : "#e4e4e4" + FluText { + id: column_text + text: model.display + width: parent.width + height: parent.height + font.bold:{ + d.selectionFlag + return true + } + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + MouseArea{ + id:column_item_control_mouse + anchors.fill: parent + anchors.rightMargin: 6 + hoverEnabled: true + onCanceled: { + column_item_control.canceled = true + } + onContainsMouseChanged: { + if(!containsMouse){ + column_item_control.canceled = false + } + } + onClicked: + (event)=>{ + closeEditor() + d.selectionFlag = !d.selectionFlag + } + } + MouseArea{ + property point clickPos: "0,0" + height: parent.height + width: 6 + anchors.right: parent.right + acceptedButtons: Qt.LeftButton + hoverEnabled: true + visible: !(obj.width === obj.minimumWidth && obj.width === obj.maximumWidth && obj.width) + cursorShape: Qt.SplitHCursor + onPressed : + (mouse)=>{ + header_horizontal.interactive = false + FluTools.setOverrideCursor(Qt.SplitHCursor) + clickPos = Qt.point(mouse.x, mouse.y) + } + onReleased:{ + header_horizontal.interactive = true + FluTools.restoreOverrideCursor() + } + onCanceled: { + header_horizontal.interactive = true + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=>{ + if(!pressed){ + return + } + var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y) + var minimumWidth = obj.minimumWidth + var maximumWidth = obj.maximumWidth + var w = obj.width + if(!w){ + w = d.defaultItemWidth + } + if(!minimumWidth){ + minimumWidth = d.defaultItemWidth + } + if(!maximumWidth){ + maximumWidth = 65535 + } + obj.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth) + table_view.forceLayout() + } + } + } + } + TableView { + id: header_vertical + boundsBehavior: Flickable.StopAtBounds + anchors.top: scroll_table.top + anchors.left: parent.left + implicitWidth: Math.max(1, contentWidth) + implicitHeight: syncView ? syncView.height : 0 + syncDirection: Qt.Vertical + syncView: table_view + clip: true + model: TableModel{ + TableModelColumn {} + rows: { + if(dataSource) + return dataSource + return [] + } + } + delegate: Rectangle{ + id:item_control + readonly property real cellPadding: 8 + property bool canceled: false + implicitWidth: Math.max(30, row_text.implicitWidth + (cellPadding * 2)) + implicitHeight: row_text.implicitHeight + (cellPadding * 2) + color: { + d.selectionFlag + if(item_control_mouse.pressed){ + return control.pressedButtonColor + } + return item_control_mouse.containsMouse&&!canceled ? control.hoverButtonColor : FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1) + } + border.color: FluTheme.dark ? "#252525" : "#e4e4e4" + FluText{ + id:row_text + anchors.centerIn: parent + text: row + 1 + font.bold:{ + d.selectionFlag + return true + } + } + MouseArea{ + id:item_control_mouse + anchors.fill: parent + anchors.bottomMargin: 6 + hoverEnabled: true + onCanceled: { + item_control.canceled = true + } + onContainsMouseChanged: { + if(!containsMouse){ + item_control.canceled = false + } + } + onClicked: + (event)=>{ + closeEditor() + d.selectionFlag = !d.selectionFlag + } + } + MouseArea{ + property point clickPos: "0,0" + height: 6 + width: parent.width + anchors.bottom: parent.bottom + acceptedButtons: Qt.LeftButton + cursorShape: Qt.SplitVCursor + visible: { + var obj = table_model.getRow(row) + return !(obj.height === obj.minimumHeight && obj.height === obj.maximumHeight && obj.height) + } + onPressed : + (mouse)=>{ + header_vertical.interactive = false + FluTools.setOverrideCursor(Qt.SplitVCursor) + clickPos = Qt.point(mouse.x, mouse.y) + } + onReleased:{ + header_vertical.interactive = true + FluTools.restoreOverrideCursor() + } + onCanceled: { + header_vertical.interactive = true + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=>{ + if(!pressed){ + return + } + var obj = table_model.getRow(row) + var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y) + var minimumHeight = obj.minimumHeight + var maximumHeight = obj.maximumHeight + var h = obj.height + if(!h){ + h = d.defaultItemHeight + } + if(!minimumHeight){ + minimumHeight = d.defaultItemHeight + } + if(!maximumHeight){ + maximumHeight = 65535 + } + obj.height = Math.min(Math.max(minimumHeight, h + delta.y),maximumHeight) + table_model.setRow(row,obj) + table_view.forceLayout() + } + } + } + } + function closeEditor(){ + item_loader.sourceComponent = null + } + function resetPosition(){ + scroll_bar_h.position = 0 + scroll_bar_v.position = 0 + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluText.qml b/src/Qt5/imports/FluentUI/Controls/FluText.qml new file mode 100644 index 00000000..414f1e06 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluText.qml @@ -0,0 +1,11 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Text { + property color textColor: FluTheme.dark ? FluColors.White : FluColors.Grey220 + id:text + color: textColor + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + font: FluTextStyle.Body +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTextBox.qml b/src/Qt5/imports/FluentUI/Controls/FluTextBox.qml new file mode 100644 index 00000000..e2b28bc8 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTextBox.qml @@ -0,0 +1,101 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +TextField{ + signal commit(string text) + property bool disabled: false + property int iconSource: 0 + property color normalColor: FluTheme.dark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property color placeholderNormalColor: FluTheme.dark ? Qt.rgba(210/255,210/255,210/255,1) : Qt.rgba(96/255,96/255,96/255,1) + property color placeholderFocusColor: FluTheme.dark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1) + property color placeholderDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + property int iconRightMargin: icon_end.visible ? 25 : 5 + property bool cleanEnabled: true + id:control + padding: 8 + leftPadding: padding+2 + enabled: !disabled + color: { + if(!enabled){ + return disableColor + } + return normalColor + } + font:FluTextStyle.Body + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + selectionColor:FluTools.colorAlpha(FluTheme.primaryColor.lightest,0.6) + selectedTextColor: color + placeholderTextColor: { + if(!enabled){ + return placeholderDisableColor + } + if(focus){ + return placeholderFocusColor + } + return placeholderNormalColor + } + selectByMouse: true + rightPadding: icon_end.visible ? 50 : 30 + background: FluTextBoxBackground{ + inputItem: control + implicitWidth: 240 + FluIcon{ + id:icon_end + iconSource: control.iconSource + iconSize: 15 + opacity: 0.5 + visible: control.iconSource != 0 + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 5 + } + } + } + Keys.onEnterPressed: (event)=> d.handleCommit(event) + Keys.onReturnPressed:(event)=> d.handleCommit(event) + QtObject{ + id:d + function handleCommit(event){ + control.commit(control.text) + } + } + MouseArea{ + anchors.fill: parent + cursorShape: Qt.IBeamCursor + acceptedButtons: Qt.RightButton + onClicked: control.echoMode !== TextInput.Password && menu.popup() + } + FluIconButton{ + iconSource:FluentIcons.ChromeClose + iconSize: 10 + width: 20 + height: 20 + verticalPadding: 0 + horizontalPadding: 0 + visible: { + if(control.cleanEnabled === false){ + return false + } + if(control.readOnly) + return false + return control.text !== "" + } + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: control.iconRightMargin + } + contentDescription:"清空" + onClicked:{ + control.text = "" + } + } + FluTextBoxMenu{ + id:menu + inputItem: control + } +} + diff --git a/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml b/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml new file mode 100644 index 00000000..64d0698a --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTextBoxBackground.qml @@ -0,0 +1,57 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtGraphicalEffects 1.15 +import FluentUI 1.0 + +Rectangle{ + property Item inputItem + id:content + radius: 4 + layer.enabled: true + color: { + if(inputItem.disabled){ + return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) + } + if(inputItem.activeFocus){ + return FluTheme.dark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1) + } + if(inputItem.hovered){ + return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + } + return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1) + } + layer.effect:OpacityMask { + maskSource: Rectangle { + width: content.width + height: content.height + radius: 4 + } + } + border.width: 1 + border.color: { + if(inputItem.disabled){ + return FluTheme.dark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(237/255,237/255,237/255,1) + } + return FluTheme.dark ? Qt.rgba(76/255,76/255,76/255,1) : Qt.rgba(240/255,240/255,240/255,1) + } + Rectangle{ + width: parent.width + height: inputItem.activeFocus ? 3 : 1 + anchors.bottom: parent.bottom + visible: !inputItem.disabled + color: { + if(FluTheme.dark){ + inputItem.activeFocus ? FluTheme.primaryColor.lighter : Qt.rgba(166/255,166/255,166/255,1) + }else{ + return inputItem.activeFocus ? FluTheme.primaryColor.dark : Qt.rgba(183/255,183/255,183/255,1) + } + } + Behavior on height{ + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 83 + easing.type: Easing.OutCubic + } + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTextBoxMenu.qml b/src/Qt5/imports/FluentUI/Controls/FluTextBoxMenu.qml new file mode 100644 index 00000000..6d5eedd8 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTextBoxMenu.qml @@ -0,0 +1,51 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +FluMenu{ + property string cutText : "剪切" + property string copyText : "复制" + property string pasteText : "粘贴" + property string selectAllText : "全选" + property var inputItem + id:menu + enableAnimation: false + width: 120 + onVisibleChanged: { + inputItem.forceActiveFocus() + } + Connections{ + target: inputItem + function onTextChanged() { + menu.close() + } + } + FluMenuItem{ + text: cutText + visible: inputItem.selectedText !== "" && !inputItem.readOnly + onClicked: { + inputItem.cut() + } + } + FluMenuItem{ + text: copyText + visible: inputItem.selectedText !== "" + onClicked: { + inputItem.copy() + } + } + FluMenuItem{ + text: pasteText + visible: inputItem.canPaste + onClicked: { + inputItem.paste() + } + } + FluMenuItem{ + text: selectAllText + visible: inputItem.text !== "" + onClicked: { + inputItem.selectAll() + } + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTextButton.qml b/src/Qt5/imports/FluentUI/Controls/FluTextButton.qml new file mode 100644 index 00000000..e61bdf39 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTextButton.qml @@ -0,0 +1,64 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Button { + property bool disabled: false + property string contentDescription: "" + property color normalColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property color hoverColor: FluTheme.dark ? Qt.darker(normalColor,1.15) : Qt.lighter(normalColor,1.15) + property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.3) : Qt.lighter(normalColor,1.3) + property color disableColor: FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) + property color backgroundHoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03) + property color backgroundPressedColor: FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06) + property color backgroundNormalColor: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0) + property color backgroundDisableColor: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0) + property bool textBold: true + property color textColor: { + if(!enabled){ + return disableColor + } + if(pressed){ + return pressedColor + } + return hovered ? hoverColor :normalColor + } + id: control + horizontalPadding:6 + enabled: !disabled + font:FluTextStyle.Body + background: Rectangle{ + implicitWidth: 28 + implicitHeight: 28 + radius: 4 + color: { + if(!enabled){ + return backgroundDisableColor + } + if(pressed){ + return backgroundPressedColor + } + if(hovered){ + return backgroundHoverColor + } + return backgroundNormalColor + } + FluFocusRectangle{ + visible: control.visualFocus + radius:8 + } + } + focusPolicy:Qt.TabFocus + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() + contentItem: FluText { + id:btn_text + text: control.text + font: control.font + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: control.textColor + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTimePicker.qml b/src/Qt5/imports/FluentUI/Controls/FluTimePicker.qml new file mode 100644 index 00000000..208db934 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTimePicker.qml @@ -0,0 +1,400 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import FluentUI 1.0 + +Rectangle { + property color dividerColor: FluTheme.dark ? Qt.rgba(77/255,77/255,77/255,1) : Qt.rgba(239/255,239/255,239/255,1) + property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) + property color normalColor: FluTheme.dark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(254/255,254/255,254/255,1) + property int hourFormat: FluTimePickerType.H + property int isH: hourFormat === FluTimePickerType.H + property var current + id:control + color: { + if(mouse_area.containsMouse){ + return hoverColor + } + return normalColor + } + height: 30 + width: 300 + radius: 4 + border.width: 1 + border.color: dividerColor + Item{ + id:d + property var window: Window.window + property bool changeFlag: true + property var rowData: ["","",""] + visible: false + } + MouseArea{ + id:mouse_area + hoverEnabled: true + anchors.fill: parent + onClicked: { + popup.showPopup() + } + } + Rectangle{ + id:divider_1 + width: 1 + x: isH ? parent.width/3 : parent.width/2 + height: parent.height + color: dividerColor + } + Rectangle{ + id:divider_2 + width: 1 + x:parent.width*2/3 + height: parent.height + color: dividerColor + visible: isH + } + FluText{ + id:text_hour + anchors{ + left: parent.left + right: divider_1.left + top: parent.top + bottom: parent.bottom + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text:"时" + } + FluText{ + id:text_minute + anchors{ + left: divider_1.right + right: isH ? divider_2.left : parent.right + top: parent.top + bottom: parent.bottom + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text:"分" + } + FluText{ + id:text_ampm + visible: isH + anchors{ + left: divider_2.right + right: parent.right + top: parent.top + bottom: parent.bottom + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + text:"AM/PM" + } + Menu{ + id:popup + width: container.width + height: container.height + modal: true + dim:false + enter: Transition { + reversible: true + NumberAnimation { + property: "opacity" + from:0 + to:1 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + exit:Transition { + NumberAnimation { + property: "opacity" + from:1 + to:0 + duration: FluTheme.enableAnimation ? 83 : 0 + } + } + background:Item{ + FluShadow{ + radius: 4 + } + } + contentItem: Item{ + clip: true + Rectangle{ + id:container + height: 340 + width: 300 + radius: 4 + color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1) + MouseArea{ + anchors.fill: parent + } + RowLayout{ + id:layout_content + spacing: 0 + width: parent.width + height: 300 + Component{ + id:list_delegate + Item{ + height:38 + width:getListView().width + function getListView(){ + if(type === 0) + return list_view_1 + if(type === 1) + return list_view_2 + if(type === 2) + return list_view_3 + } + Rectangle{ + anchors.fill: parent + anchors.topMargin: 2 + anchors.bottomMargin: 2 + anchors.leftMargin: 5 + anchors.rightMargin: 5 + color: { + if(getListView().currentIndex === position){ + if(FluTheme.dark){ + return item_mouse.containsMouse ? Qt.darker(FluTheme.primaryColor.lighter,1.1) : FluTheme.primaryColor.lighter + }else{ + return item_mouse.containsMouse ? Qt.lighter(FluTheme.primaryColor.dark,1.1): FluTheme.primaryColor.dark + } + } + if(item_mouse.containsMouse){ + 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) + } + radius: 3 + MouseArea{ + id:item_mouse + anchors.fill: parent + hoverEnabled: true + onClicked: { + getListView().currentIndex = position + if(type === 0){ + text_hour.text = model + } + if(type === 1){ + text_minute.text = model + } + if(type === 2){ + text_ampm.text = model + } + } + } + FluText{ + text:model + color: { + if(getListView().currentIndex === position){ + if(FluTheme.dark){ + return Qt.rgba(0,0,0,1) + }else{ + return Qt.rgba(1,1,1,1) + } + }else{ + return FluTheme.dark ? "#FFFFFF" : "#1A1A1A" + } + } + anchors.centerIn: parent + } + } + } + } + ListView{ + id:list_view_1 + width: isH ? 100 : 150 + height: parent.height + boundsBehavior:Flickable.StopAtBounds + ScrollBar.vertical: FluScrollBar {} + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + model: isH ? generateArray(1,12) : generateArray(0,23) + clip: true + delegate: Loader{ + property var model: modelData + property int type:0 + property int position:index + sourceComponent: list_delegate + } + } + Rectangle{ + width: 1 + height: parent.height + color: dividerColor + } + ListView{ + id:list_view_2 + width: isH ? 100 : 150 + height: parent.height + model: generateArray(0,59) + clip: true + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + ScrollBar.vertical: FluScrollBar {} + boundsBehavior:Flickable.StopAtBounds + delegate: Loader{ + property var model: modelData + property int type:1 + property int position:index + sourceComponent: list_delegate + } + } + Rectangle{ + width: 1 + height: parent.height + color: dividerColor + visible: isH + } + ListView{ + id:list_view_3 + width: 100 + height: 76 + model: ["上午","下午"] + clip: true + visible: isH + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + ScrollBar.vertical: FluScrollBar {} + Layout.alignment: Qt.AlignVCenter + boundsBehavior:Flickable.StopAtBounds + delegate: Loader{ + property var model: modelData + property int type:2 + property int position:index + sourceComponent: list_delegate + } + } + } + Rectangle{ + width: parent.width + height: 1 + anchors.top: layout_content.bottom + color: dividerColor + } + Rectangle{ + id:layout_actions + height: 40 + radius: 5 + color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) + anchors{ + bottom:parent.bottom + left: parent.left + right: parent.right + } + Item { + id:divider + width: 1 + height: parent.height + anchors.centerIn: parent + } + FluButton{ + anchors{ + left: parent.left + leftMargin: 20 + rightMargin: 10 + right: divider.left + verticalCenter: parent.verticalCenter + } + text: "取消" + onClicked: { + popup.close() + } + } + FluFilledButton{ + anchors{ + right: parent.right + left: divider.right + rightMargin: 20 + leftMargin: 10 + verticalCenter: parent.verticalCenter + } + text: "确定" + onClicked: { + d.changeFlag = false + popup.close() + const hours = text_hour.text + const minutes = text_minute.text + const period = text_ampm.text + const date = new Date() + var hours24 = parseInt(hours); + if(control.hourFormat === FluTimePickerType.H){ + if (hours === "12") { + hours24 = (period === "上午") ? 0 : 12; + } else { + hours24 = (period === "上午") ? hours24 : hours24 + 12; + } + } + date.setHours(hours24); + date.setMinutes(parseInt(minutes)); + date.setSeconds(0); + current = date + } + } + } + } + } + y:35 + function showPopup() { + d.changeFlag = true + d.rowData[0] = text_hour.text + d.rowData[1] = text_minute.text + d.rowData[2] = text_ampm.text + + var now = new Date(); + + var hour + var ampm; + if(isH){ + hour = now.getHours(); + if(hour>12){ + ampm = "下午" + hour = hour-12 + }else{ + ampm = "上午" + } + }else{ + hour = now.getHours(); + } + hour = text_hour.text === "时"? hour.toString().padStart(2, '0') : text_hour.text + var minute = text_minute.text === "分"? now.getMinutes().toString().padStart(2, '0') : text_minute.text + ampm = text_ampm.text === "AM/PM"?ampm:text_ampm.text + list_view_1.currentIndex = list_view_1.model.indexOf(hour); + list_view_2.currentIndex = list_view_2.model.indexOf(minute); + list_view_3.currentIndex = list_view_3.model.indexOf(ampm); + + text_hour.text = hour + text_minute.text = minute + if(isH){ + text_ampm.text = ampm + } + var pos = control.mapToItem(null, 0, 0) + if(d.window.height>pos.y+control.height+container.height){ + popup.y = control.height + } else if(pos.y>container.height){ + popup.y = -container.height + } else { + popup.y = d.window.height-(pos.y+container.height) + } + popup.open() + } + onClosed: { + if(d.changeFlag){ + text_hour.text = d.rowData[0] + text_minute.text = d.rowData[1] + text_ampm.text = d.rowData[2] + } + } + } + function generateArray(start, n) { + var arr = []; + for (var i = start; i <= n; i++) { + arr.push(i.toString().padStart(2, '0')); + } + return arr; + } +} diff --git a/src/Qt5/imports/FluentUI/Controls/FluTimeline.qml b/src/Qt5/imports/FluentUI/Controls/FluTimeline.qml new file mode 100644 index 00000000..8d0863a6 --- /dev/null +++ b/src/Qt5/imports/FluentUI/Controls/FluTimeline.qml @@ -0,0 +1,294 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 + +Item{ + property int mode: FluTimelineType.Left + property alias model: repeater.model + property color lineColor: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1) + id:control + implicitWidth: 380 + implicitHeight: layout_column.height + QtObject{ + id:d + property bool isLeft: control.mode === FluTimelineType.Left + property bool isRight: control.mode === FluTimelineType.Right + property bool isAlternate: control.mode === FluTimelineType.Alternate + property bool hasLable: { + for(var i=0;i 0) { + const curr = stack.pop(); + result.unshift(curr); + if (curr.items) { + for(var i=0 ; i 0) { + const curr = stack.pop(); + if (curr.items) { + for(var i=0 ; i 0) { + const curr = stack.pop(); + if(curr.multipSelected){ + result.push(curr) + } + + for(var i=0 ; igp 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%0A|xtMb)(B7--Xm2F6 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�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 z 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

m`f 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`I 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%0A8TuF$PW8~*o|99)+yH2ieQ z!bBi-;a%Zdx_#jiz7ekc-y6iQ;Uf{yu3(r_OpYrt1MxkAsPpWME0^LlIR2T2D{#Q0 zfSXa}1=tk2X`ZC*&O4y|u%TR&7;Uf=C2 zM8WG!_>EV^T54(=ykH)zR$?8{tM;`+(df|H_J*OJ4qssz6<}4zbkLRn83N( zYW5=yloI0&BD3|Nzh`lCsWa@#$s5|Yq;6<>PH7%XouB+wZrwj-L z_|9jPn*)9AwMED3?#2@?(XV{dv4~-^6`+^%T>ZBOewNEaZ|BsvIpV~ex99y|%Pv=$p7u~&Y zsAj?5;S~?gT=e+b<@fI&eCU3|+MK?NuUoSJ^9OsP^$&E!Di6_ORG^Q{R?Of>a4V` zHFK~SyU}FDvdBnL|LHw1-aLQt9WNbR_|Wk1nPtoF*wz!3FG?HM@s#l07u-U)Mvt9R3>=a2Ls>*+ccTX)BfIrXJV_X`^rUb(b3 zy6DPfv#wm*TD|ltMVx=#lb7uH>K)5sJ8u8@V+$^R_2s8;Tx4~g@_1+LKK;o@=N#OZ zI6i&H&9kvw{aqW6&zyblk$E&bMS#rTvAGrinZ{hn6rza^NJa8bFMa;OLxFp|2R{1L zhQxPGOM0JE?^bVCulT`>;!!wiU-T$&v1EhK&u=l(DC(*&K!Z9oan_o0$YqE|yud4i zFvgO@d_sDQ6nk!XDYj#7&Frh6+P?jZ*UYY+zjJ!a^8V1!fd^NveBi)PsBc;FKWpbg zDZX`HZSCBxebctitr5%TUbV8RW%aR<*~eBlH?BNpI9#^mviQthpFI+re&n+|XP(%x z*jYBRdVBYpd$#xVTz2=Go~^4!#J=9`^XuyuZ13sazM#Ht!S?Y(Eo+X?9l2_4YwMb; zX3smmrWvbf!z%uQtzti0MUA)9VaL#h)N3RS(h#*(1nbAtE|S5p>GbxQRTf9*`dhww ze8%y<-V=kD+_Ph5b+MuS`Kz}-wtw2tiKj0eJiNNiQqeJcL-&F!m(^7*y~?x;>v!g{ z`CEVV@>AE(cQ|kJhGRSK_{8H25AT|H-9K*LHG13P#L2eRM+Td>Zd%q~5!-&#$bwt8 z0mx)wEo_Y+VOXhB7z9u!}h9ME7onfRB76N-}dRD z{Nn22y=Qi8xp&84Wl>Sp@V-y3Td;S2Lz&rVubsPR;nIVP8d31OtYQ8>twCZ@-25;h)xC zS4db_!i@M$yI8wJ+4J!(D45hJOzJG;c$hqB({m$#nfQ0H_OEQKU9>NSl#xO| zGB>nyTiv{^hfnmEwE{8c7bpfLyMyCT$E!Mbwa;dFdf!dUhxaY4(eSiUHkDY~zjkQt zT}QWWSkq*!ZEi1jwYe=mU=xf(F)d`{n6R#T;kclw?*EeJ;DW%o$^KRRVl3Y?|)*S0pVziHLQH!jPh4YW@c(;3#gcGC4_>{D)( zV;Uw><-QN0Fr@pctUXVX(PoWw&RLh;`~R3C1(|p1GDbm~Hm_gO2a!b9q+nHW!Veiy zNC+rkYX6L)z5q~gCOO-#OdL07VxRW<&BYgQ!C>ykees;CGh*1CG(1}Q&WR+d;}wV}3E4T@L2YF$`S zj`XHah~KA)`o8!C(w!ph=|fV8&XYe?P*yr%(=~2TvekkI?GvV>5(i@cnf$G3Lzz1v z+`GuZ(#{Kt!}poAF+o9kK z!u%psZK ze0fTYp_XYOX-BZXIcTz$LvFE@ctV!Mu-qO|LXPBJj*xPvQqw|B@bY2JwTdO=DWOE{ z9;+$X%%5%v8B6r1rMP|gJy%mL)l`glO?{XlI zJ09w)c4j>^s!66>J&u>rKvF-~i(GAG>I2o!zW68M1wb2%sUn*X@vAA@0j)e=;B#4h zL@w*Xr$pQR+#M2rC49Zk<#U`Wn3{Gt)}f!{wdKM?KSRH%(s+a5aLX)PIj~gcor|3`uMEeDIyKy5t#}1*bv;=;T%5I=NR87 z3>TA)sCSU^OC}Bv9WqcSIa)Z65uRm+D#QBVp`pZK%9c4OKTl((zX@wd^3@dA(0U;w z8oi(a@Fim1MSlfob>qOjZb(UOlQqSeSON5rp$N(e(cC^nI^=7w{mZMLKQ_dVPyPiu zRc`6au@;>`Q8ed-;T?)28M=c|1_Tk>gp9-f{s7GUNnk0l#3Pi+W4_SV#RrJvB} z`SiQSOHX)f&|Cb+Vk(GQqPLmc@O$wB*>q%F4>3wtCr=SZ9$v%pJQDPC>_l`veeZiz zGEbNAgC_;!TckKF3a|}kds2jTo`kU?EW<0Kl;pq4H=P*csFG{JGma^mLFXAFu*Kgj zoDrTw`?}Zz7z^l%dInh6|;&%vKp-<(9bnXfG zDXaVh_+pNVz(-LOBEbPH^o%01#-WfA#AynT4df9~_#|;zLv`H8bjpWY$a4+&kmyZ`^H;FaJnA_=WZrL(PF= z*_>xKdmP?UXPw*L<|%Kig$rUZNBokw`e3QkS=Etzn-9LAqQZ~BBx>4P{2(20*JJS7 zR5R&6atjI$-LF3UwUYj7aZtR@9IS4v4vhb#yrb5IK%qvDx8LokDnW@xtEajX(18C; zXThs9plE0lS8!O_{5qi(m>t3&6n?M)k?esy5`iN^2?mAKs?-Ep1mV~ZTX|lZ;!?O z(|yEpEAcXWuvVrQr@{y+npjV<+q`1`z`*_$%?ZKWw`FOpCRLUNZ=iQ+S`t+E_L*DEQJ`qS&R^IaF??qw-hlT__iyDeI7MzZ6pHoFghhKSMwG2=O^l2N2RY853H%0 zvps%#0UfP=;FV5l06@(JcR|P}rwCU0*$sYwzzG_*hp4L?Duv*9CItwD6<0zvp^m+ek7TAI=YrUv? zS?}Or@3QKPT9wCXZO#gO5yx%5o-%JwU3qz3x38?nC*Q2`U%D`?e^09T{JuZ1csIz* zKLSpmtO8WY`w-TU0269-WF`*4#f~Dy;gG$ig*a9Ul8Cxo19g$70wC>IE~}4a%fev8F8o*qE|~w z74BhKQc{ls?!+z1NQ4Tr`l`ZL%zjJaxQk`{7o*MLwaDTMWU-2h4#IGs3fi zP{yZLBa2-0B9#yUx5k|^4UvW{a2*?j0v?cdkc@BiBYfppT!WSZWKw~y$yFaYdS_cq zb7Es+KkY8A8Q|MbQ-DPXM~K(cuIH|`gal}Fh}RPeqB8cUf7Vct8nkiI1reN0iuRR}$6T|ZQn zV7N|io;&kOF{0D78|XSiUPsWG*yOH6r2Eo0q#jD#m*;jn%};)=cI7oI%}$paXD$xP)t*uYruwcOrPj5Ap>PM39sXP9re)Kl^`_jZ!4Xtmb zzDfdBCb{&PTbAhGle~n*_{7m&Sf4?ofFkrUO})>u`NQcn^;+~r{Y0W>yqtLc6DVo-=#9!-{e!ghg zvPII*-L?J_I#2rOJn5rzgV5h8{k+6(FG>2k`}(?*K020u-YF*Eu-L+`fI-I5d2CG`IYj{24w7u`2FhZd5HZhPtwdo&$&EC0sGqWnQM12Pex=lJ z79oAAKf+m}9%t&0?DE@hn!Rw|G5-0_Mr<{&`OV~KXs2do0--3ey@;8577m+>LsE9TqOIG1Luf0rK5zE-Y}bW^+^|dbPSaD2xK7Ddv>2E7RPj zvVzozCgeZm=5lcJQioR#Lvo1Xev?;ra8ZDFMv4a;eMLpS#-R2s>j(O`6pVLlKK1xF zwhdq1-hTD)_OCyFYI6thPsHVKAE}Oxl#4^+%i>V^NVIyS!%RwRPB+z*!%2#6S`>mJ0tG(iVUaz_ZMK~hv zV()L?`8s7VF$?tDJ732=?g;L|?{r@^{pS6xv5&ru0)74#iUzt!EwKA21535{w|G9m zlA-*TTE-3ZIC~kjT*Ge27+W2y&`o5H=p_?p7}C`pRG2A{_BM8Ym8hew08vz?1f7&D zyiihDzG`cr*2!~oQ;HhHVP|c?O8H)@W_!fD{6U{b-Qt;@c$=pSr(4EvaMlD$wOiC3 z{vcfG?_rs`JN%`A8o7mjs_3k*ak8{AvpfCH>W0n=%I$*2cKC&0^m9#p zN0|SNHxAd=&ZY)^^e$=!8{E)|$|=M0@Vj_*LTzN|r1B`Yh_|rPDQXN~wo#iTU~cIm z{fLXWgw}*F3vbIW@z$)w7fh;4^W~{F2LDJcAKD0HqKlDL`6%?BH#0fmN#RA*IQ=$W z$aMq6+VFMbxlkD9;6MmA5*(<8lv9O}DXbpq3Ia$Ii4_R+Xm7(MAa-hrMc%h4oUvhS zQ>H8tW>P0 zIBkDTJ-}*%aY+Q1-x)Q6ok-x1o~BP}lx}ADLP#C42IveWK#=B28l^k9zK5Hf=r=We zKl`0)g_8fG9w0pm^0po@%gSg{Af5_0WT@OT6!8!pxxU1RKyK(>=tZN%?(ov))H|M2 zn%JKh@2K9*)VKNwG4%SWewT`(X6zdOq#noP`HnnWbbH($wbiHWym4?)9gs=5#(a

+2*WmXTC^G?K(*0EbHUj%Fi(!pKr-4aBd}@0KQ%y-MJt!)a zAW)^f1GRF2N5G&{#b+XUtlXRqQs5^teBg)@PS7c~%^^7=txS|;SyubrOWaJ0pouJT zGvckD6D$zF_92vFP9RYxVCxotiOkA|G4(w3BlOJ^CdnydW^&=YJ}IDURT9jK>GubG z^3UEyPCb`cTJG!$*~h=~0V*rY4AlCkkLo=k)egi;QdsCT@FZ~0XN9jKE8}k{vL376 z!Pp*DaMB1KCn4k{(LsBg|Eymm8px|WX;o=5SYTEJ%11fkb@Bpo#Om%k+M6@4P0WNg z5j@`S_xHQsAoO*17y1guXWSfRbNXm(8mTd?84Xa?^ZinVd*E)ik zV@w2Na~(7z5I5L{VY)03dKSZnZ{T67>1CXy>sQD3>PIH(i5%x)#_A}%I>2d;F*O|$ zh6oBXUMH|%q!vg&W?=eN7Mq+HH3*~B3P_s@mnb?UicP~CRpZ<)g9c3G%Mpf#=o7-1 z&TUVFXI4sAKz(KjPe>P!v9a6>#PHHBjPd1S8fa2K@KBEg_@F9UL~{tCac-9=6>+^3 z+{mE@0UR|FLsq=nPo~r+KBLbHA07>P>=`4QjPW>)i%*9(J+~Hlz20JCUlwi#%RWfweT( zARAo4s6|mqqMBQ`B1)Vs6V3S8D1FMK33f$n z%qz%q=0|F(ipm0r&MYnW1l@&IHQ~J6!n{IcpIT~jz`T>^v@gL4UCP6~h3;UvyVUCO zgq(#{wUIn0uDiok1vY0Mzc=457W=7FmAq4qs&*=&D#lsFAK4&#kZWoQ;$bfnjsRXs zR^h@J?P8{RJC|ot=Jw6xS2B+$@h;kS*EtZbY!p*$2RFQsiZf-(iT39@15af;T!W>LeVyiFdETkY5rtA;dGkS<+ z@VcMnjCwJnW{a*<#b)`iXLl+qaNhTP7;E(2EBFC^%{HXHhiO}RH^y($+MbIO)WME@ zzv~mEUWc&CY;GKf_Cvq10#fFl_ofDfPAwUjRI~T9O@ge8Tn7kZnYnhE0-?;e6G@o3 z+r-QgG&6iYQoD)@*z%b8cUU^9Ga9(Rtq(7~gQV1&Fq+4GolMMQaGd3ppho$ojgy&# za#zu28fQimDb90~rrUeho%MEVBW2EA1Mm{f8%gIk!ef1kn5p9&_f5>>F(vGkC3>ee zK-z~Qg{0CV5+kUD)D4UT(Gj5^K6CNOGn}5AB*RlYLQ`{DWM*iZVm{eyiVbXnX|jPC zAx1FDovv(^WUr0up`O&J_^vRYMqlqX>+l7e>a3sZzNyZ-@-EPQo^y^G6(IZioO5+W zOouGpXM-FSCSN;`8Ru@}>35y081pDCdd8owSErPI?+> zwEw@Ja+%6lG7o{3!YSb&fQyOOEYuXO#HVr;3m%q`Fy-*zPDQXN>G{Q&4-i=+fMTJ} zWg@j9%-K?k;$qSaR5SRMge1v9vBxCfz)OiVHoU+x!_Q1aB37B7O_NN5r*G3>sL5AI z^=emr^5}@)?+fUj9!r*2&-IjgQMa;j*`eFcEL(X0sl#=_`aD^d3;{Qc3jSJW`|XcD zvuVrM9=~-ZI(%l0r-t80o+pRDytHaXOK5g9JUg=DW7qGT zR~;VSHqdf;uf=C^1;Vb{^=p?`EIhuVzGeNjpL*f1vu(bPIsfLd1-GjF-jX5rBT@Msa~`uFEXI%_LKHX=La?c?$Z@~pNSZmOO?&}FaPIZ(TN z<@y$vPb%nMd}&Yfrbe19CN&-I+BB=O^eXSw%f4PJ{+qM9C#WuQFk^7oos(~F-_zT+ z)H^CxZ7&E`*Ow{z%GX-vmt2)EO3vEu(9o_1Z>77$YzVrHx!tR$`Ado=zmC1sw`Sya zBiN#|L;cL69YsNd^rcWgA|>V+DjeMX9)vY48_I&gy3jWsF0ClHh+;5jMx(e4aeE}Q za|?epye9TRf%mcC=7SnN8arHWSxD8kUH49`}zaIRwz8^>z2G z$dl^#topptcb$B5C_HlVxnHVdx8ACb{p#71BXlMjZ@uV+HLiO5jd$_VL%hxrKdvut zRyU%0(ay@c<}zicHIXto7Zi2%l$Kudx!;^T`J2yOLf>6`+Pi93)RP6<@L93$$;d4C z>+qf!#kR2i*zHlj7pc?Ng1(fwTxllP0V&OA@Q-9^g-E5*RE2!5 z4wL>=RIelt0|S!l71Q}ZA8{YzUs~2zNW~S=By?#=LK;z5>&{$h_bz67QTK5>&M292 z#8I2!%|sqK$G|s?I2QR$v`kiZ@wiCms;R^))zb~pisYLW>wiiNjrhp8OY`wMobvkG z1A7oPPWGKq8#OH;vxh)79I!4Gs2kjl8JmrWyW@x_ct&_#_$lTtjfZU^7}!G$Kbvf@ zi8$cPX>F;OqoG1sX=(2$6cr$7yF;NA7j{Pr3%ctFAkLbd!b0B~!6D%b=w|c-5R8dl zswk!5fGHn$!jUZPS=s|*w8l+xGay6y%&5a$QRxA4NDH7}j3QvOBC$8^RfoL<>m|x9 z;wzg!b8Kea;{CTiyqe%9ZZ`i#lJm^!V@iQpbkx`Wz)<3@ut_$gT~r_cc1g{$o8&ol zH!Z6vNrue$4>!w_c*N%ULzC zG3-WA;6nAag$M^krOb^@8yZbPEBpf**Eer8sAn#DNp`vqec~HiS3Pq3!DaQd7yU6m z{!PC!CVM){#c4<7YTJTEGjeifELvbYu*0{1{`~#E9S7q4wn?Ar&lsx}j}!ZW!z>@y z)${lHcN|dB^(^01HsT5XtI0RqVTbhxKd>UBQ(=yJLKIF|OG>OK&I%{g9I01DmL&2~ z<+{)sVLIfJZGbg>e=>;!OQG0E>3wQx)n zeM81VCdo1Dclxf5b`#_ExqZyQ6Weo{Z0#sfNLU^WkWC*BB5 zZ@p72vC>Mcxc{oPW$MGUT;xIJqBr7wbj#vbkaoi;2xs46ySfWf^E$|WCwP1iW0e?@ zr}{yRHKX0Za&i(MhkXMMOXme-=E@EHs1YTF5McV$ntjR`g7mKwZkBGSojp9azJFK! zw2qpE0+F!zOsp|8 zT11RzpZ_fTH2Vx5mRS$WgB7(Ez0tNC7A<;U_Q$U6y{vj+dpTSGv z!*dL)@(?P+K|36XP&QPZS)eSb4&rvjDAGAs;}cw0J(vwJS>#9$K<7vmJOwZ^m}c!C zSO&3PAuhvI1toC@Ff-N@4moV2bOgwFs$}sLUPBJ-2padDqv?}@sloI)@TmOODK+`? zXRjUB(xBcf8h-iwb#p}DP$e*?e}*4ys)CHJ#){#vXsfo>)#R1tB_A{Amu93!*x9Z35TpghXDyRW*_Vr+P45w}( zF5|k9k!zp%xtcr`8SoH>6b(j{h%(8Nk}K!Lj!&O{JO-@Ta&cpkx2V`}Xp>A2djqT3Fw@igx~bVV=iQ;o|U0oA=&*ntWw*8m?fNoUf+W3As~ zUSc8KA2LOPB2yh^GZAfJt5a1z$H8u-9iS!Hv#z?JA$MN4ryZ-K7>y#Wj$~BiywvivZfVBy*lX;|PIrlO zu6ynmqH;>(A%|&o6aN|AzW4H#?d>Zs-@84^rnzy?;VZk3{BbiaT(W_;M9US|e?5v! za&cM%Lmd7!Bx78^YUi# zVj5j!7~6#?(+#Lj{%Pt9glVFJ#Mh7)Ho*lBZ48DBd0Z>$XF9rezqsi;yNMWa za!MDY(dcC-?wAj+nBm(7W*_LzwZTua$XQ-cdEoX(*MdDL$(01VT@`XEuXj3CqvmfL zr`BXdZ5Ak!p%8(b%s3enH>e-?J1wD-**Es|U*hjLal_5iJrNUVE{~k0r*?m5(~G;i zIwH^(aq3DJ=ifRwuzgNtB(cO;?((c`%gGJ9yt8Hxx|iL&ZC1&5!Sa~Z7)(W=u4XeR zdW>i_&yGo>iMSHzQHC!K{CkK?kmiXkV#`sNUqM2P;=abV_}q%NP)W#xn6KTa6HqMQ z{(iahl-+vLT;wdHHzBn|Ov{+72DtYR^YPKFiqMG1Ssn=TotX{IBI3tbu61}u1yX4R zv9Qcb1*-|SKjvFSLOUyMYqOvhHiELaqJ}^Vm+6+c*D1#hCU=E&Puw1HIjv{y_On)} zD`Jl)w}+4{JP~(#4RP=v<8cbq5r3wuVkLhZ-XtT+E@#MaqZoE4W4o;$SETr7G^Ibo zz{*Q^Q%x@MMng#cHYFicV~O}d<+lftF->uv+zL%MZh>y%O;M0;fB%^i-<6!4glV6^ASq1$MCy-1W>G~!PHZe7R7RVL zXr{B@b9EJ%De|2)(Y*3R!w`tjKye_XkYoP^RsJ5uj8tj-kJmi{t z@0{R{!&h9?*A9PXcQ_HRn7+0%-<>BuQL}uY`mAu#uq2h$^aLYo!l6Fos(3_Eq-JS3 zG+>WLTm1z{UT7~E-nebebYpLyL4E|eD+(f&(L#sM(Btr$^F7sFk>K>6=91pE(|jhY zuW6{hys5U*%8G=Va>}L+&#TOL=J%}|sCDHA2RF~~%v!RcwP(|uwqiN_R;evN$E@U` zeo*`L(!wIiRFGTbEpvyfk;ivP@_5E_8%BsAGW=5Ysa-?L zDCtS8HkiARbOnj@OmlE0R15EL^J)XqF_2CH%nDV9OC~0hAt?qjB-m_c1x93UQ6C|! zBCdwqpLlTXC$E?_)I*g(WKZb85LehM%tXS}3rG{4GL8IF$~V75`Nj>5xycF~0}Z3* z>63Yj653)~i}4#~9r@%sLu_b&XzW*1b);uVFr}=zVOYtRKqGS{=o>U@TnU36)dQXc zWS3+;9z(<}=K8MSN*bCO6gwj~{~9RXa1q)FjdtZCo?6I(1Er(WH~bkITTM!Qt+izd)9Yv%=7!;4j!L$0mk9 zpyZ5ZC!}YnmE;%7>iWadaJav&Y%#KSEq(Z!#d3L>CHZAb*|d#^y1EW+oJRdn7=_{X z$H7%isM4m#1sa(ROSiX^x@Qa+RRM*f0JDf|3`YiGVjxJW-k;_-m;7^hTCLMrJ1uutNEnU_i;T-) zxC)E|pHVxrwSsZtRL0JJz!R8odX6zv5k*h+4gAPebW8<6D3-wkttaA7^`%tk(X0ko z^I0!pN&pQgn8$Fotb@e*5m#uaJqU;V3Q-EQ4OX}!Rpp@>t$sT__QEfCqFcagVCU1aau!a7-9om`e%(b(zZ z)-~#_B>1Sl*l9h;=!R5TfFV9Yy}NwmXqG$la-)=1E=hxAKsNAWobaRR2)vvq4+*3f zR_6j0W773Qh&?wc0dySypXGbcJY`!QF!r+FY69(0XAcThYwr?9LbUPphzsE2k|lSfHeB|g&Tn8%O~YFbT(+pN zfZp2Jw0v)@XU)7>(XzrvT|*Vofo4y+Yy4UD!Hsif4;F-!IM7Q<3#-T8igM%1!K&!M z+BR3X((SDETT6qrPP^adukERJMQS`H<(@$OG_B-(n^?PcqdiL_Y!C`-?GlERaUl7-dv&HsX3L5Kz=(ix>1!;N* z&)7>a)zZ!LauVJT`3(y68cd7NC#|Ex_|vLIRe82NW1iwdg{+=^J?g5&^XeL?0g?2& zEV8_E@uwC`YYaOiQIslRrIo7dz^jEZ8@;UUK96L@f92Jk9o zlLj&>q*4_0&luzvfuiUF%7jNxnRxo)s+`kbdSs)aLzvw ztGRglp6=q3GQZVa==2r;W8K`a+LGt9I4hj_vQ#>=&f3!5SDsf&5r-aM?(HMuw(6A^ z?;ey*sEnolyfkDUK7RPnHFvMdEd~P+ysWFJuDLl{Ca!(rOD`R;gsqfcPFb2)oa0-! z^T5t^K5J>Q)ru)@?65a1s($j3=-NxRxAh(FEJ6A7^12Rp&9=PkszF_=+!ddi>sv5?rrn&2LRSI5C;!p!h>tX_pWl@) zhFunm8VC$TdTzY^wySqVm9Q%>Z___4bIh2xbivFrgVC_^r57ISGUw*myjVKY#TXpS z8YOVAEN~deMgi3a=|*wHXCF&To5A1+xxGF`gu)nl0wp&Js-Bx`l$05+%3!(4;c}S1 zICTBcZKCJ4+r+Zl-f~w&T`#M|u= zC<#(w?gP+fz$}Gp+Z_>!S8!6k?(r$ID4IN#Z9cKm#^zO{YB%R5(mWY3JYW!qXyq84)wEJ<^&xj*>xFH!7aT^zG|izSjgI(Jp~}OaQUOXwT;C`@>wOmM4F&1mvSJuL98&I z)GV%hLK|9=saP51B(eMBOh#iu!k%1Z_*8#EWnF!QjAEsE^S`{48E?;ui5Qs#Gg&@_ zSxmSB_jDMFNo+8&qy@>FVMR{vu85M5!sRw7hcwSyyp~MAVuL4Oba;cI5IC5e+&PPv zY369Lkx4OW?oF@hqh;r6NQe^4vOre4l<#E&w9;1y_e|Y~P4gS!YD=cDOp9TZYJwqT z9^I!i=jTX?#LT)>v6@Q`D9g%r*CI=4}9mfV>kavpAN(sgrh+}Z~fh23W> zuP_zm*34SlT)%dtF3(v}wvqB-dO{WDXWEu@`TDlrI7j^!cU4Tw0n`cZT1W5aekgJ9 z*GC2Ne?3MXoWOycEYT;>A!iDRLExr&+TE$LOXM(xHGu9f3K9h~(KINXG|L~u7>u)E z<|D!!M8@bJ;XS6}n((X?ciU^{4bQCT-W;*G9i_QN4Gl%5wf@MZUE!It=GEEUZd?7l znM0AzRkJ$nCZE&kGu58jRWUR?ug>l^oczcy=FI-pJ@@=-_MBh5bJ}fdTpI0PP-Y6) z?EzE1ud2l#UD`-Z;QF-14wK*E@SAeoCC#VS+1%27Lpv)gcMh>n!zg}%(|(P&anJPf zwzdvmO-=8%j{bd(zM6o$kUv@E3e@@+~AMU>Q z_sM^zhNAwqE9TqqU*%9=r`sQ84FrsZ5r6Bkx%6d=@Lj;5rgQZA|3g)s*bSGD6Q$uaHGgLohwaj@6;7+)4N0RUCwL zPy-A1!8?WQcqmPUHN^6220aR|$Av1G>Y!^RM7$#dieRx z42ZexHoE1xhi}@_Z#G-0WJa;Y9khhZ)99{CQ~9^Hdo=ClW$Sd(Gr*6a>uhlo;wdm4~=y*n#9=YjK z^xBd`sfcNGL3975H$C!|El4X|efj0C1uNIgZ8eEa^ERwq;Ml!y`->kt6pY>b(8otc zKK8&}(?f?JeD;kk&p&W5IPIc^q72Cu^?jk8GvO1nAD}EajF&}*qiiwu+-4*3p!&bu z;Z0J+srcMsIBfWP#y2gK{;wlyQNP_G2Ibrw^{ECq>_AOX>G)(h^_(UqWK?!52EiG` zS8|I{kuFQby|JK5-X7}H4u9AUzd-S?lLXLn+MzVRH-L6ODiL1>zX9^jFaZ~UHddbE9KyRm7`#x~LDYpSX!u{Zi-Yh88C>R+`YzORelL=oR_zTP$Sople13y>?V z_R3q-U*DE4(c8Jx_+#Brm!8*i`dcagsXjY>x~IiqDlmyNJ$ZS>rVTe;)E6v}TG!63 zaz^TGWr4iu_pK~RSMu#?Z|^BuqrT=GzHXPpnX1$KTPZm($u4{@FD%%BHF{fvd7lR> z@F`SC7dS(wxj@xR3~?YHnh`?A*Z_aXEmkO1$T5J7c-)W>K zpBT|hrYlv2cwFN)jDC8WHh9(2T4z%kyFEsVWnyA@i%+Ed#<5X@N$3_R zwJtrWvWNKN#8e@aPqWa2?+zhaeLc9$`(QsJ8IydC2#>>+kZA(~WE;g?0#&exM4C!n zxy&@C98=JSVV-czn5(N1;I+ZlsDa@VnDmgAoFpCEFq|9{gQ`7P53?2h2$G+jvcN20 z7M{)PS-Q2ebL-NcyhJw*T>hu@6>%nI5FkY$nJ@KkanxCEw7P?K_`}Kt&K!r$<|r&P zn!+G_ZmY4}nH)t$Y3uJdQ*)bt4?m-*7|XM|ip;(eu$X!IGE%+g%lUaZ5m$-NT;#Im zB`~GBe$xoB=vY4(jSjBwATUTDXLbUe8Gm%a19L15wcfDXRBUuqx?)n{i)p`N+Jv z0iC)qJ9`Fa+lOc(5(D+!z$_446@AWlvaDR4VVG92@*OFoEAe8QKA?zYUZE^2p!E$b zPZ6^SrnQ@z*?}dmVef^#l?i^c5zQ=y)KhB5ai@7*Izu0W?TIPT8Qd3D$t~mY?V^MB`)yI|C zEJ-ObPyJj$SWMM$Mwz(-af|RTR>*X-=m(aTnr@xvvUy@#Fmt?4A--fljk^R z*EN#B?*l60rnE2&DBRRFRq6{%pvMh|@-d_$YK1TUDB%gQ6HLl)2nv5=i8|DmXzPx` z<=gEcYhujXIelQqqmT*+07bWMQ)8Ufm6=z3g>#VJFad<*2mRlsNDPs@6mfz)_@BvEsW zg%>qZf3kj(dygHNU$sF;*?254$7K^15T}WEWZ$4Lnv&t>ItR-rKIQf#00v0z8sS0m z2MAwl7&K$Et~j$Y`3}29dY8V32tM!c~lJl8mVnq0zxAC^n>hn)--li9MDlKilf!7I&*jy z{myF1-cP?T(tj3mp@GAcLppE>ULnYG6EwkBs~4~{>m1Mnd4OdoXz4)7Kt~H%zL4dp z#fpptR`6#mQ$ZVY3)$G5hm0v6D-8=QG%^lfn>ct9%AyLmsqw^ycpiZE%bqO<2i-js}a4u2<0)}W> za_NFd)OKf|&+WFA8I9f$5R~3r34gR|r2USZ-VsXkyM{ztJqEcSOc`@sPfP`XW<1 z{Exr@t{S8c)s|Njz|8~aOM)p5rrse0n78M-;F{1R!;a8wXo<&+DMXVlPXWXtjV5Er z)ffk-8zX-Zo;ZVh1Q3qlA;pBTm?wXP;zYQfAYQP(L~Lq@y$nC#5K{ z+8lrLunC?@I?j|c$oLS6W8{fAQ{==MPGvqTJP}Gl(7Ag9JHjO3X4W7fQMS|KuoCt` z&u}sL9=(Q%J~GnyX5t%-0pjGCm?GxQ!$SSj*V43E)TA=5ej{o{0v0if#7m>$P)-TOO<0eFj?aP03m?ytSG{KUlx{b&$Aah9n9^SV9*fDgwbT5^h9#k z5+>;$Q~ynRnbxvA4^#E}3w)@v`&5l@D}uCb+> zI^qzFSRUXFAoen0KBAj;Ak+MX}&Y@oIOa}oA9`SEe1vnUgIl#E1&+E#0!S>T~-Fi z0$>CH<*S8Np07zK=r+D0d>M!W>LAO|d2-g8LbzV!T5P$~Pg@YQ;CilGEOM0~NH| zWX`)uSm#7fI)9WwkBKWMmX#x)G^EjyQDJfg6CW6V&5qJ=$Auw+GM)$zLYE2_fF9*l z4C#nhHayouGUMo>ILB&G^CCL}&n?C^Y)v>JJq9wuc#lhfJbR z6gvW}fE9c9p9oe!_K91%iyL;+Z*OB0TOW$fXmAmgR33qO z!5y}~9k;%$2xG77t#EospsY=xsynUd7ogkE(9lo?%@u&Pbc}&ETQu-<>Gm}PZfYhb z&dkK~DdyXgv9|9$Cli0C$w_C&dapEW9FpH-O3pDyhDmcY6v2N6?qMN%e>ZsLNUhkFs%_Px(8m^5PS zf^+2+JJ&9Fzcrq?=2M%4DJ=P9AUKa{d0#M?1Qr5H5~Z}c4Y0XSc^6Q9bk1lp?kO@w zsJDs&laP?80sO?20bGf>=t;01l;R-*-O+{iJA7gNMh@o->-lJQ$FuQHA9$WA&v>?T zASx`e>1XEhsm?xJWH9TQf9J6RoP`8Uk3`1r%Qz7}z?fK!3|En)l}?(_GewAsW$?aW zJHdid4_#9p*rX{D(iSn|*RUt1iZv$giK$_QY`{8??JiH)6d$1903{Y24><_hmZ|ld zHe-5Eo=3mMQE)mO0Z;=_b7#^fwkM`KF?n!dz1uQMwel-ly{z%zLd9_Kbr6Ay>GC zdf55|)>mB@L*6TFOR%p9Q+QE{Ez$(=-$Xe;%4IJ0{u*hCXjiE4%AsTq?yyOWp=zJi zYZhbhB2q_R6F-kqBMePJ14tf35vyn=g`)a81w%>k;^HDpGF}L=TxwDme2`gxFWfq{ zS^wa0G#R;mkP&@wILg!@aoGOw;3$K?J`b8Pksq1b$`~fFBj+)S2@J`FQ#;0hoHx}l z5J+4Y-7o+iv*<<^4|ra@)O+FBzZ2gvnHPhf*njB}87C8s4>F=`YMy;I#Wm82h5kKd zrVy1k1;P*K;C3%q@|d_^rZ@&h`Z6}ml*d5srkUGC)1fJ#b#>6Ru7X_?euyl(5V<1B z6^axY0rKPRqi`8I?a=ZHVw*Q0{gWkZiz?ibz@uWqQ3dX|6q5uKXAZP(aHI0U(<4fm zMOkRNnQ6^_I+mNVf**`0ZgNFdRZXk5N9XUKr~XveqE)YhLE>A|Y|2Vja@nwwt0bO# z*r3=Pcio_je?%>uclmJ8?|e!6QjU}pA4fDUEI=6IPsu__tpl@sDc@MpF)KRzmIF(Q z#gMK+`}cMEh2qMVns3c7LNt4;YtAm0B#WPWl?uWP!rsdA_PHMIy_iJ75XnW#0Gc+UJ=C(P1$$V~68iJclfoTy8h zczz!AaVol{Y&=a+F=Z+K{a|8>SYZmPq^Tncu8e;V?coQ~C{NTFzu);3XJFzIzu)NZB*mbHZ7;#}65soJwdc#>7&gN%seO_;XcUZ^#PJPTD=&EsMm|IWi| z19*c^51$z_bg&~z@IpnSlJH05M;u>j6`%BZ_&{@zvSgi1g#$3_FR6hQO~C`;h0KIQ;})l z?F>NfVEHr=h{c5Cv`UX#%*p!+e1iyUcc#CB?%u!+*L^C zz}qquDaao;*~@8`GTj$mq|_N-ip*@NSrW`uG;8#0U)+zZg=PNYr;4pfunfBQ09TGM z9?z8=C5IiT)O4=Tbx@qAUJ{*QjTEa_i%;&(kGKL>ZO3#(hFZJ^@ddM|%)sChZD>ws z;Xn{n93!l27s-*tUyuCi2eMA{$^bTKsS&VTH5z4(Rx6d-kzVQ{`uaAieYzm zBa3lrO~|KYz3x*I&UQqjgbkFmgE>?OC_qtH9ZeJa!QW~AX*~L>C4kIQ_2l6X2SO5t zGJO`9nj^J>gn$&Z3(n4=q=S5r{Ex4Q5=%U%Z%yu&DyeZ}Fi}kgQR&3jJXMA2t2C>k zTk(}$ruNaX)bg{_?3(-)+GE`HWRzWrvri%YnH(kKu=GrFw79s;B^Gr*huO7RPESYL zJW8}t$c*&qP4j}WKp8{IOjttz?RVIr2f-|dhsv*@Z|=7C+GF~9Q5{(gOz>uraeZ{( zS)nJn(^^^PZ?*o*_irghS-^r_Z<-4&HfUzRK~MC++VVH@z{*+|wl@&7$d-~^taUvV zzhceWJAVrgEKQHdmWX|*qo5&eGH!8D7M=lE(1IoN?qjzC2oTlRu|AO(%_wANOr|$ zl0%~`{2}oN@rLckm_{)PK~BW~X=hBzEI)QlsS}TIkS=yOz1G{Ma2YPpe{7QAr#PAk z-;YRlCKsuP#NaWmdi>s5nExhvyI#g(XVM-gNV}cF_$lXVjf!zJfk+whkJ8b(HFbb^ zHJ*Py3GS3R|c^!*mSmf~<<36mvv4nl4d_=aOuN=i^ z%D6{s^2krb$7w3num2c12-!?>NK}W5+~qz@U~!YPuuL{5Un}+G+Rf^Kl=o;!h1+di z_~7D9M@>nL8!H_0F%l_xGs<&PzRRg$iDXWBprW{}f+Gq2lbkj=V5-OS9i>Hvr_TzK zm~54x&>a)%>Ymv$1&9fPs!5f5ut(-@rXVOSXjbOLPz*x z3>AID!#p!Wg(||ndxQ%3z$9=2(Pbc=_!yHGSd0}h`Eh=Qc{{Nf8}8|*f@vgP?3^Jg zabj@jkFl)y(!~W7jm2+_rKO*Vt&I~#`Vi&-@%kTN4ulUoO6Pp1AT!EticmmOBC&HU z4vlkn7J`DzI5hH(#Kce>8uNq8kSJ3@)<;>$5M%-fi&$|E2W+K4>jkX88i&I)`8Zo@&+EI zpJIsrVh8EFc??w=O~>h{#Av3RBtN1u(ki}Dh&+of)OX<}UL3qF9#Kn=@hCGfruTxA z8u|t8iL6iQkhGYVNe8rtQJqoNF(6?eY<__VdSSU8WSc6=;3ML4AZiUkL8vK1o~R+n zV%w1i;}PKt!t+>_D9?ze7m@8i)~%|}szQ_N4@Zj9wQK4|);Ir2*W8c) zyOzCP`u^`)Yb!f@s}t_3g|SM1w7?&#C~;4lv#!V2=b1hf$T3^nH!qJ3Hm_bhTYXD= zO5Ca^(D%CH`3;`RPUBl^m#rG;9eL?5>aQP|dFSmnP214A@9>eX8^>OIGS=2p5^8y; z5)1R$+L2aoaglG`6|7cGacxZ{t5w6x+uXQt!NVWBqxVm`8Ne9PUo&>!@2Yz{D{EWj zUpF7S{?v??6~R2GtuT!0*g3ZOn-3kka@Sg~1DW0xv;K%0*E*}N^fcthUEaq{BF&UX|kJ>1Qo& zo@?img1TCa5Xv13B~U)kD@;dB*9lJ8B2z0t;y2IYM;fiKR)Tm?atmjp%`jHq+R`v?vNc{oSCmtf z_#!_)+3i}@*1pn}?9R_;5-q7{fTN3G>l{X|(Bqn=Q;Q{}5sMT(fIXThH*RtS4NQ*QtI%-rlq7ocA)eJ&GAV)P4&?GijH2!}goaX1vXqm^Meh9cg^&T% z7ie`|wq>XE$Z2*7lL--(N#&=JY`N|24;!P)*QYKawH@ls zY#VQt9=__(#)XfsPOiC=wSzWjVMy8pxurMJA>M0@7!2FJr`aic5xtH&bK171_P`Av zS+MiVtB_yFg=$}g6~(K+we>4vUt(nS8^_Yu3w%Xu{$=|;>Th>!YuXg8;%%{)>97E- zLi-E2wZJQiK!Ya$u@Dpyx9rWE2_V@Nw9Xt@j+DXxl4izIAI8B%Im9^!XapjZpTdK526una_lMBnuh5XUtF9nvOYC-|;3 zew@g9X_1v0-vmL74U}5_Q-C4ULm zpQCw|g~Vna=r1MA1haxMj=dN`tm@p1c}z2}9Te2wfn;CA&mi@1hFu{=E2CK|3uRXS z-eoN;cgkM zJr!xSUQD0MiKCi-!J|TPMx>`>+A)^Y`GUs9YO*Isi9xxbafz|cO7=89Cal*78d;XD z=l{vbB#car(Zq=V?Zzf!Y`kog^xtl528=Di)=j3dApwqtLzc zk$^AYJ-oND>ke^y0jh5Oz#5qZhc2-JkSqWQxs53NnhITn?8`wDuUj81l zl|ps@HD+s^&6bKq=&byo+2U-#yYIdPn=MXY|E{xzY>(K9e;e3BtuFCvwEiFZR!qhR zpUB2mhv+i}YYHZv3sLOd&x-Oaa4(iocR^5=G*jmE-!nW%12K^)kqqM)9V? zH_N4_96gRDhZ0?oR0_*0Bax0A7Q}f$ycxpY|4%C5B^Aqp1JFwZwV)_C=;j6SqmU~Q zL-TG;YOkG$<^O9#7NxZMn?V*!*rhX66X)%JsN*DVE9qx=G4?;yaVorNg3T6}vL;~r zzXxpT;`4tIK6RYU)+ht53A45PZ%P}9Dsn{wF#m_hrNWjUPw7=YRFXKxgf5c4K2&{6 zik%|W_XSbDpXqGV1?pQ25Q8|GH^lzCXy|2zFAhK4b*4*_0zx-Nq){hMO(>atB6s+f6Ss*51Ysac-8I|u7XWXOTEv-0YGAy*)9?anviUea+zvr z`(Zz}!hyVpYBiyQLpECRB(BtIKgc5;xjAa9EjmU@Hu~71A zy+(xi^|`mUi$k$Szdzvf)T_@`tZz|cWG!OSRK)d3loEO-Wi^RA9jlM|6w~BX{9|xD zf=*6aE$!{QdG5-GjttjGn<8l8NZB2p@=-?iO}mwoaug)+1{7%I62|3?W+#zvtnh|h`S`xGT0RA_4!HyE~J}1D>SZdpM7Tw1oo0>%V48-R+)z?olba)ZYQRJy|+nnzIkG(g6lcTKj#_Q<2XZk*-@4I`Z z=f2NOI>{V4n4C;*LPA0afdrCp<{%9i2uDCg6e1{yB1;4>kV99;1qBaQR~KE`UBy+| zzq`I3yRR#m=`Q}?-&0lHJ;?-;KzR3kKZ|j?y1MGAr+&}x`Q1l4lnmKynrc5XUZi_` z{=P0MLX4AEJK4x-I+zn~fg9kYb^j>3%}vX{e2>??+{OqicXBIk>PIxK7dL;7m-dOb zY0~ZRTJ(Y#OgAKJN^QE&#UlRsluf$_>ilW5%WrjtgRzE+w%wp=3I}Q6hEVrvoZH78 z=I-VmL476WqlGnd0Q#3vF6Q`BWJCK#%%t%D2F6qFTmB!Ui9=VyVj$Ncm)?7Hi`zw@{8Av8f%`A>0*xuC8|&uwLGJ!I~~O0d#Ih9`gZ|oLO?J(Vxc;s+_uaxift}WDeGLQZX!=FU(uHC zdHT+Ly$kj|vS!UA`xameAHSa@S3Z4mRG9QychXnQ^13v6EP;^A1CE8UQxxt3}^qJ}_=kMg!>r?2

aV29BS)l3^&77_7Es$2nU^gM&1X6XD)ojZPceR58BompQMZ5s%Ntc1@ zM96OmMLAKZFU@ZmF#k;F$agRS#;em4^P@?#y`p7$3iSz~uT8?4zslqWNl-8p~7 zqNKI6Yu$al7LVB!bYYP@{q=pZ-UhAH=02|>)>rR8% zowd3rFc7rb(}lI?0_2<^ZY<&A!n43cGSa*olq-1NJ!Wy!(Fhw~;5X_eq~r0J2_3gjkx%2P8{pH0qjV_bJZ1&l)xl-?da43Lvy4zAS;k4iI@|_D8-udzk zb|-XXOYO4M;=L>C>sRbuT+<%31gop9={HV+W50RFEehF6Abe3^dx-l4_l5Tiy60v; zzsHMlPIv#iTfTEcB6P&CSr41}=wNdp_|*rv4}vnQf%zHM!dEGnAS>CVVyksgNpEjw zC6x#U> zqszeOtE;OlQr_S)e&gwuBjePrvu)K?^Kw_M?hu7TY5tAM$Kz@L`pPT$e7^7+e^0ux z@+YU12}CHIv}}vzj3qtCiB2|aVTIp|u1}A0&r$y2NtMOoPz9OrO!gG!^`y#vBv^-; zl>>`LDpAS&-UWU+t){z^OqB}oPiUHpv^HYUqzbilu>f{eyHvA9Rcka`b*2162}fYk zk1?BJ@0n0;&RAti`;Q{|{+E@d`1IOavYo$W8L@LDxB^)*|bZwcCaQ zRI+pTWAV{78G>**1<~HkwzbH0ZMb2yZRzk}EH*f_q-{Q4q@z`;M!^!BWNPh{o>Q|d z{=w?fJ*K{c9IBkBFcIBnM{n5B<;nEK=>^eNhDNkk zbPp=!#A{jN(Iji~l2=ng`5BHRZiZiTw1AYTqZYTQ=xEMTn~p2lNpe<_xRIQdGyGqA z?1Ym@*Ojpcki&lr8*=a!tp&}#f;$4c_!Gbkmx# zhh5pO%EvIqplIMO{~PI#kMI_M!ZT~sBfTKtKYoS5Xfzb#eCzhk1#`4EhgCFK^wzMY z>ik^Qsym+f$G?04y56t9dT2p$jUn97JG!#9ZG5!1A#AwW9B=GPt~~mI%QCw2)0ZDQ zdj5h{UjASzCEaV(>y6R}X#+~n&ANSzwBFIZkE|yMZ8;Dsd)00V1t^Li$ow z4C9R-{lMiK?s4hcQsEmdTC+CZQD5sFe`%{NYQw+W!8vmd=Cn?Sjo0clJm1hfeDfdw z_OWYo3l4qt*V5#FX14FXVs%&7>MM3{&-CrTZdXfa-8FYFUv~Gk>p~a*>H1=R-=RbM zFJRiEiw+(ZD`x-zy-NTs55YLPWE3cC|c zemRw{2$R5D=*vVN(Bd^@sV;IU)+~;^gmhMJ77xP4>Z4IPJ%1DIFRbX7h-p(*Bb}sw z30;=uTtOyq$I52Qa#ChD&%DXZSs=fmm_PK}C%3GuzxM7&RtleyJ_~XiaPTj>98y0l z9supy;?ix;9A2{Yj<0SP*e>L`El>XT&=Vh7c+H9ieyuYQNa9*o2)6isILHvUx@N_Z z=Pud))jO8b)&iU{D_Q!bUJzs8vL#r)eLf?s)6AO1II3DDyIHltmcUxhnk}U^PI9XK zU&#NMF*!bm4=4T-GXIz+b|&>qKl3AYA8vO_6KuR671N94v}mj$LLau0w_$tr}{K1ym#e{ae@<6(${;|DMZdAN}0( z8~6X_0I!I7yteWX6HGypuqDx*sDm4 zufn;)j6{bP(D=OW2;KT=>4*E~?^;}!yNbr#|C^UEe&^=9*3v^sP`v(+tV^o&#)=zP zH_1k&c1cNOg($)7&3-Z@aj>uhE@@cU7o)c(q$|+9^1I5WnCak1O_yMs1il2T5-~ALO?md-xbyG+`jOd{kkRrd(gp~y486&yORp;auzA6u=M|v; z8dkNFfS!o-X@6dV#_}82G_`c(k`t(?ju1$ff?Rc?5Al`k zqMm59XHizSm5v(vY{9hq_)&K{Xrm)x8x?7jS{tL$#>Qx*iSKA&M^V@;aIS&Au_OFi zK8iFIIQfq9xoD$cbr@5fxn#62+!ylJ!jm4#)P(RQnw-;-GCDjB9{h6{lO1zX(cW-h z7}r3~t@Yya{z%0&g}Lr<*v;Q>vg^d4H`5)7cGY^lbzPANJ_U~6M!a8ruVTw^udrNw zpTZ?{RPC$AKQT}56m4vZ$e-$rPyB3>es{tJQ?D&d^wxRp#)YdqnTGa6qN6_JUA55Y z@Me1x3$%i$S&)Fw(r#L?+EZKK87IcyU6BGoTT<>}CFG65cZ*#{hs9zPUN;(xQKQA;;G_8V9pO84 zET5vk4h$k3!-%iG?TE*!glCEis(cPdmGCOc6x3HaoHcwszC9y6Q{{BjR28#T_z{0m z0D%`aV#IuDL{%FrC2;U*VIxhAO{GitE}JT5qv6<$Y2wB1VmJF8m(hsz7;*eibZA_pO;|4rJu?v77$R&uV$uiO|AqLVX zuP3cfR`?+pLh-NX;n%l7wxmoHCkzJ_Tb(3&0~hOFls$elyQn+HQ0}QW`_HeN-x;x5 zZYJcL{6^FB!ld11^~asgl!gBXTPWpzy*OZV8QXI6XEkcAHNrxTjeo50Wp|1;L&~k& zN=G`bur<4ocICpXh~aypZ}vwz=hub0{dkVF^!aAtxV_2ijQgNzNjJMwL0hrkrV*;` z4y(y+)9Cm*7lyS3Q|Y>cG65(&AfkJP)jUu=vX{XMc{Ac0KFRsOdOpYJphd zRjwKT%E{;Cb>!P=9T8}PHI zrfrfJ6$$Wc*W&vpgZQoY2&^Z8u?#jCf8QmvPKC#(Ixn6%v@|7zEu*P41Dd|_-eBP= z!9^6q0Ge=2Kdv7K2S{=4s0B6#DR&2V0B}@e6w1|3+TEb{C=HLv<@gP}guq8XdUWFyT~<4^u4C#vRi$@CycX?Bi#Ot+qshnVXuLI%ZiRf+ zCU9+uWLq^(rCRy%)?@<5VRm70rKKj~NVMW|d$Nrmr`wXPIA>3^>BlK-Y-(lu1tVF~ z@-C}Um$e1bOsS-yTuP_1%9G+7@3ebmyLXoed7i?3 zRfBbtRyBlE@tG7fF!j3*bp-g_rMI6qcE|QXoqi8R=5(wdse|Co!ksJ1ITdcYpyR69 z6fVfB52fZ_wE5YwwadS~oph#kpSkO*e(XV$vmWhSXeiWx5& z1};4K(Z|=(mpwmTwrurpFYMnxhrX@-Jp6dflA)6;GmRleifS6oV9k&V$WIqeo`}Got^?vhX-0zhhhnEY*;O(E*gKr(sRm z<&08~BI1*PpRj+*mQo;`ypvVm3oHj^Ln%e5h~Xnsdg)}b&>r_9Pi$+e`s|7`mV0^`$tC( ztnU(!na#Uidi17s&CP3X{>-;`nX8hm@nEo}xyirz!5#hmJ0INaZ*FP{1{2uoLnhU5 zMuX9y`r*CnI=e17FrthJbUMb5>sKNm+Y3HQd{9m&C)rl z^b{8woF?JvhTWROyN|7qUXlLv^;q$%sbjoD`uo-T{6x#f7Ky`OsRc(Z8;e)sL%dVC zs(3g5#mW4{gf=gohglth2RUyLxjw{sA3==wv*kz=)>w=*LpcUZLu46*w=ysbTZPG0 zVf-kYQ7NPgXux+gD``P!RNF)&!7zza_>IE5`~n;l@=%EWaI#IssE(|UVgM#cGvyRt zfIk||k9#j|+5DwX+}=NX)7<#Ny$`IYUpY3%yT3lwlj})^8#_D}zoVwJe_m$wz4d#; zR`0UyHy%y~+t`Rk4#`CA^LzHh6jYeWrzl~gLG_Erk4>}W(IS)Pc z;>DN$^yj}lu=dENj;e4+?avmD&%I!{t+6o_T5a6$ZI?B5F6e6NnAh6Y^fPbJs!5JsI()12 zhV*aJUw-%U0(VXA-0?=UO`IVANZKEbQj$`rKKoHQVwA?Msj1dg!(svZxZ-yjMurkN zN=hp)*r0}m05}lZCtHTS=}cNkC&{A(HjPyR@zdy2L^ZHz9&Z!Yi%~`VOcG6#plyTk z9L^@zCBW^9z)rv%&M_AFE!0a%gFcY5c|(4eroUgdLf&;Jul<*=-m*~WUl#b}@1&o8 zMm7NtbZNBJt{RVBwk2a!DiI;E#I(m zPSpnZT-&Ob^$XpCzLWsAgpQCB_CtCY+1xmH79U4w<&V&lRmkd(!^$#;;+a{`N`O^~ zv|vbV1&P5HVT@Sj!3dQAt<-CE-6_7p>>?W$2-5TqHcb!q8yWQhY1%n3aPly1mKl?5 zypfk8O#~PoLaYf3p(0zeCzeSDwVEo;(uO^Qx!o&UTN*x9+n7l{%RCHlOnM7XRNExZ zw4Ohp8S)21ZSyjzA^+4@YmwzpBUrN5^jK!rW!o;F?aI35ede)G>{}FUAE~b&X%F_) zg=R+^ds@b?86Li7yk+*>IAtX%0j=q=^s;Ba`NG=KkKFUYd7d_x4W%dHR-M1~>dTf{ zs%bhctt)ruX76fzq+#VC5+t5wE`w*&osl+I;mK-EUO2i@GtWPi%FJsE1^rXc7hgc0 zhK6@&&2E#`Rjt)Hv%_0%SyeyU77VtH)(>9MXshYGA@vBEJcz7=5B(bPp zgR#CRR&5KUJbJ6y7$P2lg<}zoUyM*A&rbS3H%B~1+j@3ILV9_K-23xJcfdFk6zt3gVdK9l$qy{@2FXS0GIrWT}9qQ>A|xOl#s1~Opk7`#UC zRs}S_flFO)FzK8b=XqB*>$HMS&|1al+yzUU1;HQ~3{_U_L8M~wx|@uSDs!kOWVN+6 z#R3NYUvwsuS#Q$nOqjD#`y;EtS!H(UnxnyiwrIfcT9w~zF(#Kef?d zHVImx<$@MnwZ&Cq`YoG;RwweMk;ofZ!d56_$wLrn zAuJ|(?)5mzQZFI`G>QilIHE;U9WTQ&@#~?OM$3!V-UhKYWDQ&6L-9MM-`{F9`l)!{ z=3RTQzO)t(_Q08t&~ou$Vl?rf^y812jo~$a)reJkBMN?_5e-~B08K&ZZc9+N3F1kHxpSVC$TLe znn3v!sWc?f<27*~&ai*ji6E8WYM`aEq)&shPO0jyVUmY8!YDRXw27E>vMWT-EEEOh}rHkX>3ld$)M3{fHFY0 z>T0`5!wVXn)|hG^92yZCv_?-nTN^WaTS7HyU$ryV(mOX<9dK0(K%pvws5ORrTkAqL zjoD=j4|KJpeBz)Eo893L8auajnqB&)JzIxclHrY)?^xAs3&d=x2(NXA!bYtr)6&_L z&>0;39o|&S*oO5>Yi!PF`@E5%fFrf1BR%W-ofpQ<0cRBmtU>E)j@8T_S(pU*&35VU@*ZSHQ4k{0qddx2WzRqh4qs;JGwX&hmD zL6u)*B3Th_rv=~ax$?0qZ+>EHmKeQv_=c_H*Dp?@D?-}8?YSe%FMQ~SyGYzP|KS_P zW?y>880na2G!uRT-k!~xJnLl7L}x<3w2)yKS;E&Yhm5j>?vMuXPrEtgclylkxPAWK z)(bw?=Zd(DAt>GAz}F9WTLUJK#TRi^>)c(l=Ee0spOc>tf4U_&Cvr1yy=%uGZf@Mr z=&DKk&Bnjxm){@iuQ8gVjqQ%y?YAB3tI9OgLL;bzrx|s*ogC-GMy2+0L}}FjX#iWI zFvrnm1Tf~HPvkXuxhsg2r_@CC|2PC!1+SI3B<*PUltjIT)8bWS5tOn%ySo|$@<(|L zT#d`s+1ulho-FQ`p4;?|i!9ZFl*{h!9~`XtA^&OqG5(3yjAjJ;f4wGPGCA!w{T}Hr zcV$;+bs4{>##|lr`^@W~di;SQF@35v(Q;Ful+@g&5j>H3*At$05Ek$P% z%@MjA5GN2844gZXwugE{()_|b(ij*D5F}n}=U)=<|@HHwhA_HZ3h zK$5=gAb~N;d(*qUfH(;m^cu5dI*9x$8Rv=Jd*nDe!gGrDk!?C;=MkPE6fX{uNrsFw z;yzQdr8iPepyl(C-j<}v7Kta_EEEQ}yOZ(AEtOqC(1|8bk+Il0{`A*q#IMm2lpiHV z_^WhI%&AGNa%df0!t9mI_EZo;EpZm{D`(3(<1L}88h16Bh@|W2&T4lJ|6LkL4y@om zu>ObZB@KIw@@PDejtITwRmgK0#4?SaumWwk5uB~f>BCcwLloGfi!2tI z-f5o>$;2w4b@}P@Q$WLvlT!+4rh`N_$Dui_3b9Fyue_anxALB3d|2Ht(jOzcrZQRx}0pkK*NMuK`GZp8-B5g9}Lq_Q8ND;c=HOO7ljY%1n&uc?nZO~sFx zoYDH4+vTRRt#P4E5J&bta)H2I@W|egLf&cF{Vl!GV6z%b`fu&FI18X8V}CN+?4I15 zy_b#$b-D9Ddd-rm!W8X`JPl^NE(q_#d&xHmMMzU9w9{@mWVy1!4~vBBF?gB&M> zHLpE-?NWPkiDsgrD9F$E|LLb+8Z<&8^qKv&k^Z|r`MK5iNq>0l-aze0gdaWlg`fNv zfBWti7CAz8vmZ$>#BVZQ<8r9+y|6Et4nyx(LRlNtncy{K6}fB?G<5F z(<9L4f8g1Fk&08>7v1``U-6pT34Rp8cJ)Vn%dj9~p6#@}9I-OpI3ng}vR#~HUtn~J zs>vWy)Pw3l01>nKBhsIQT$EXml|*X!qEuQyf+2#NNZ1u+MNgqxd|SM)-WL#F@s8Bh zjd+Du0>1jbxWyp~#WtO zysKI?i<&ul{5SOtjRBUKa%~ynt%^md3%m@omCX}j;2&)*#p-veWNmC^&CDG*tl+Y8 z;t5b!W>Y|1k)sIGY@N>OsAj!3QoU(c_m(>!|JL@II&%nX<=prLemiZ@;M$f(&L3?g&dQdNKD-UB_CzIg1;i@Rsau`cGfzfk^dT62wiXsF(c z)~{|hTUeit`YZPxAjwLBS0}5?bT#*36>7|`S^+jkH#$_EBFkONG}>P&gO2}SK=UN<@3RgT!x%h0t)Tf*?uQ74mRZ^m`ijvc)B<1;~* zU&7#)>`A-%==?fcZ&I)0&1z+vGQKlxVGX%FK?|ce#~tCno!qP>jy!~X&l0pudwG+r$(kQ`> z@GEvCaG&a+ti1O-S6SP8`&+{LFX>Gte!JNbj0PPhyuJn27j+Fzkx&_+~+&#AQ2a5|o^ZCSvB|ktd9(p;JDdvOM zdl9!B`C^;N(yvOEARVkC7-OzV+n0)ZE^_8Z#nnt^1s^U~T!K_Vg!%t8Xux6~{ZS-PX76DcRBurs+P2X!LtpI*ZQl~oF}N^V?nqN2izoU|eL z;H?;u6>va_HpqxMIhS6^lLuh%H2t&sJgRuLp=e!rvEWv(Ac*-WX?!DLg|1yh_qt&88fs%K#|@x^Sq97PD$-!>&C$SM_QG zDX)wFXX#Dye$o8#fo|)`WE5G{G=$UkARXj8(aqDLPU;0NK!YIEKJ}VDa6og&U$Mp-7hD;(6nq;GC6B`BmY4L?edNb zvCT7eH8#%$&P2d!4J4dj5TmVw_DDnEzQU>2$5QJZV!+l=g`= z5O>jYCmK2_8mUET#n$C~30*kri`5pVE z;9o0zb!(7&$Lud5(vxHpZ~{)tgkl6BzCVpcqLdXxE+8EX3xiWdG2SplR9PvjJgA2; zkEPwhciv9!QMrwCD3@SetBS6CZgFuhv$Al4rub*o#=`$*U`KM#{tb?yd59*G9>LrQy?6Vg4we3KJy9Wxw!%M&!*!kXKR*UQF(dQa9(tX4K2bhR99 zIZzWIg%^Zc+D;s|Vr2FVDG#qI4Ns4maJ%^lL{OLOH_7pH%MjeO)O#e3Bh8jn?@T;<^^! zwzYp?+nq}(4lJH}3Z3&P6s+?CGGJZM*|A}`PS0{+%LB@(t}Gilm!rYeAq(sqkk|QC zDn7XVjxu`glY2nPUCEHR zI6@>{a>ksm2it0UPzDf&QpBqPzSK{HvN4@IAQ%mQa{c;G4qHR6+Ma0r_N({x5A3~a zdqWiTxzMBeunQ#GU-)gP&Xw?61JX;VQB9P|p#KG=ml&c_&u7t-C%ze^68Y7bI}1Vv zWR(+NT*vHMIIV6iyfx%@l2|~r$!SLJFu2huL_pLvS#4W(?%ZOtcGtSX);SlCq*5an z&%wOwx_@sr*EcmZn$76H8;-Wd9mBaWS_T(5H3ycGbSW2BnjpNB`#2_NuWIYN>F}LH zLw6p&sjqF-?4-ES8?|kDbj%mw(m$s2vyQ(T&PCt(RZ?$9+AFt8*D1D z`{-W+798a60nUSp0$X7k17^!=ClnGAX34opS_U+GI?px)UIuA!I884CT+w2!Nn@px zbjWlLH7twr;uxxcq0u>(aLi0NH0YoptPGAU91Vs#9My?*I^^(q?gKY;-Phy{r!%Q) zM@J|;JUSAs&l!@2zU-2v+3{?)TOT*fsgKN`KN1dgD)%KjXLlyOuKPV+`9^1JsK#@^ z*Bq>G4VZNfLvME3vh0d%w#yJV3<(EnL8iMXFd9+IWMJk$?vMBb9$VYMoY_6DV3*^7 zt=$)BvEP^;aQDofGtg%9)ZmJ~x)I+?nvV+HZ7p z2HoAtO@=0;E7dz3-IDFmRcQ@|?(7SVox;T|D0}3BE)aE^1C{_-W!B%JpX7pwnUc){ za?4wpoG7eJwtF`ww0FQy34AF0A?T94j<#R`h;fJR4}>4VsaqVKAzE)w@fEihlmqLX zFV#_K#`rU6*p&iEN$Y03iMTe;cr_h~c~vqfpJQxITl!(Lbadi5?4Ht0+{phV8?&+< z)a^6v-I?W)Xo!x{{7TFHBsblZ=xVG%c`_f8$4gAAW5#WAZ8p}^B7{-nw92h(xQ9NC)bYv_x4o19bMfWkM^WW+$(SUR~S*4N;( zR*?-Az(71uUZ2;<_FY<|N@|)Yhb!wi6%t~e7=yaE>61oL)*36#vt?z&l;2II&m@1! zWV@4mtSYAxO0NeEK=G9n**V5zOHUN?>T~H=*&8GKF=$Sh2lK}2I7I1lJmUl8Bmjl! zmSX@ZM1)1F$?k+imJtZq)~HssqX=oeF3$7Gq28>?U^VFUjoH<|_%qL4e;Y3zy!^YX z+IvMoYtrgdopX}-{JTZ#Jocz{>HVu#e{{JmVmH<#+Y%kyI<&ADc+RcK zw<1PcvYrNj5pMv)Ql!{N$in1-@aR+&F z6c8gpKQXPxD}J=_us0gf-A1k-UbC_gfJMEF4rF;@FE@tTxVoPuLV)QfK( z@`RkWU+B6DPhO%8VQ+F|Ck4c7RDZr4^F6?KJH<50myi$!KnqS)X*6&y`X~q2v2r5toqkRrsPN=ZqK%d0i@~HE6`0;!gM*f+<}gZ!dfwUI=rs zlk_~2lTiH!COde;lCak02!~6GE7qEQo2?cTmGc~63}>kivUaOpRQ?7jAHj|s{pBIu zIu9Rav4~%B7>!?X9uLrYEhIa+`Ve5ku2l6=_|d*c2!We0LFdzsKvj+LY3I|jT3XrN z84_*9>=V#IXP-2CIXwfqwiRwmW`Y94Cq-OQ%}<)VTrNYN{P79r(`*vA-pXF!X{Y?F zJo!oX3MWn;SsJ*h@&%lDQF_^FQ?H!)%y2Kw98s>PH+5<j+41QONu>6{%Di zLALMYLw#%dtzEMRP&>?ec?$({n4TF8kL?{Lhlb;>m)0VwqVO45{y_wJc~ zWReRLT9~}TM3ocD-SDv4CJ;G+drkNv3FUqn$ zbVXU}gk(f!1=uZ1Rs9E*kXe>7)-FdKpz1%a1ACI|3!+~ToX7GPIJ7M=Rd~qpO!SI} zXN1`*6vs4Z>~yYu0s>`gYFIE@8He~!`IAY%^ocXZqg!-6wHBkd(X*)RmsUO1WHa_y zzqMjyE#sPNtac-!mXRlTD zDy}ZP#_+VtpG=@o5gA7+a4_tTM*RHGr{f`wbo!_m*VXn^n{@WLtN81a0!buF>G0Va z)-ayFwx+%T{VCFR6fqBmdH=KoO}uK*Vm8mimDXU5$LMeG?2pmZUGYfRCcSK)cD10` z-+dXPvK;3}K4l*EinXA!aC(vJi&SDT9kL&kaW;f3mlC<~vWP?CR9a??k{#wuc~dDh zLK+cmmg;1NTIr{O2HW>kax0V1kv^HM=5~#@VFjBU4%gI3ZqImIbAvS7;xf2&(g2c6 z&fk@5oIk5K9PSw$6(?YVxs|9bEbv5#%gx}w73|=HDs^vM%gpn0+Q#?f26xkN1|9!m z!=Bl>UFWwtlWpN}YZ9JDs;tW-;CjTVujj608M;ba6ym>%lE zMCx6{;ZYG*CJbuwQjWlKYj!~w3Jd+o8HqTB*M>(up5o_3sfDA28k?MX z;NDbD$gx_ge4g16_*}GmL3X59{A5i{;Re4b{Jij>(N`7rcx0c<#97AqJ<9Nk;gnLr zZIhbuoMBluokU7tm5MQ`hk2uv<`6KG6R<&G81fK50)owS9mCC;5~hWH?Q4f9QM~`c zxk(B!(A;Bdoi&`tU{WdsUv*u;zqI4$&_a z9I(XED1r?Cv0d56E#+9BWp!T?`8{c0LWQ4UW1bjJq&-zfmv(CVLiR?`c!W@@TXw=| z5+9kqW6@gWq%B)uadFrE=z+Cmx-7*`Zr#E6~Ml-dHAw8i4!6m3qen%y3I};c-!NRUX-gDWXDwltd(UpRQ z&JkFPq3ZqLdh3JdKfI`?mYSBLS>)>~yE}J)&fWcAPhFBsEuiO7E;{({CIxeEXKaMa}H*n>ve>wdP3oicLm>3Xp%RdEqsY>gK!XP zzh4l3$er+8=G{2ZQ!7T#J&<#@KoVA#5RkcWazn^>ARyE5nEG!XI!idGNRTEdLu^28 zw)Y2@C-c!LqZ|_iapBx!^goM?XaM3x>zSf-C9R&1njRl`w~%H*E$se9{rqq?Cz4r;L3(?x1&Kp1SDH*fh z7p@3F^55oe8%;5YpE+avzZ~8V)%L`0f9~hktbSKITJ?P(UWjNAjh zY}3`tDVZ!jt85@+q(nAwlyksXaH*W$3$>f2G%9&MWd&UNX^y{Wx&pqe`DFe3Aaw^Q z+(=datN980Ksw!T=O?Pm8D6FS043uYvjdft?&5(*&RZ)mvl26R7nXCR2H=R|NmYHj2ffqRa@)A8&I(p3_#Bn2$a4&~<9UyD9nD^N z>m0#vyD#!Ie=`9J{*JSPsy_ z5>TZFzA|so6g)0z3m#;$)KfLolfRq;=rHGI!Q#KSIDhxsh1>@>`U?e2X9Fp#&m?)duz;cOTG zA7>5WF?0^vjZWV0o;Hy8?fnC>2psOIz3KgeG5F?x4;Uw6?<0(X#!&F3|F%G$COf>B znEZZ1S@Fl+@ZT58wi7SemmCVx0|<&p+Mv$NoqtEhYF*>Fo1S&aa3IM=5^k9;-nEd&FCxah{u zT~q-=V4y9SlsxY#50!E#BX!Z|Zd_D`WO2fs^jY|WZ_iMt?cSB>>-QeR6WL|&r65u~ z37)csP<-^8|u*=}|bI32K>AAa002 zrBzxU$Vux+ET@XKEOA|*SNa6VX)$hZzh;-3wmOwZw6?)!z(4v`PO@q0@M$L}yq;g8 znwtJ!nrgDWQExIFvWEH^qP_J#@pV?`{~_{wY5OS!8!dv7>w&1$TQvrq&Y-zfb%{Ns z^>thp>BUGGXHK*?TVrzgtdXQIi{yK7%+gzr!(MWB?~VLZxthuJ7*JF{VTon$6*%t3 z8@khTR<#%$hUS=NW30J3R7Om{+|IGMbnmKxrMOS?mA0pP7Adv%TgW~)WlO_nm8zS zQ_Y665^krs(6tMUc4Ko4xRyI5$Xac&upiRi84A3f;pKuX!+m*X0ZuB~qOr7RR;+oN z47@=00-S~Hj|wDeyf+*H&Qk*ItbjF{_q6(;ACNQP)UY~380|C}d43Ob1Uxb`kf?%3 zgwN}LsoRfQGs{swl4XbiI!gEnDg^ga?Idawq;cD+4wn;|Na!;f#t+nn3#Gi8G>EQ1 zO<kE-BO)byu=o)aof^`t!}qbJ!j)~@w9u#tJx!O&5~(rPY&eLSrP04QTz0x+ubHe!2$uFg4Umj*O+U}w|#KK1K<0{f84O+JNK_^S+(yxK_gH{A%jJK;R8Ddc7E+IZ0=WM z?suRXQ@N5DCeLgKNZFNVPHnjmP%PJ*qs}x+a%2ov0;O#p3K!;geD%%Smwx=VT^W;^ zN_hF}VnIuG*Vw=n8%CW56IJSSsmj0bXTkr$fBWpZ^rD^f zQTiHHz5G?4m}_v3w{v`!x1*-`Yiga@I=*|(EV@}8bvS$b$&xT<>e>W_?#9=K%8 zqt&C56bkB~ssV}=4g1qEpDXE1wMQ(zjupMx`UP8;4lliUenad0JItN( z%mZ!Srs3w+rE@ynHLao6gNvhc;^Q~2YKYF=I${YIF*_NZ@%k_d$_6_)+02C}wR78jIb9M-3j6KV2hUUib`tWmtW}y8{zsAkd4;?~GCg z>dW)_n)?2D?R<}LRDB}$C$Kp*|H*p?|#LfS}O-Kf*Y0K%%HraPyX*+7%7CnCA%$_K6)p+#+3v13+E zlb63nU17v-mk>yE*(Rf5%=1by^>=Z3aa$llxAip$dxgF1z!wP=w+YKtI2WH04o72jYgb+I zVDVsG7Y!JT3Wtl&sMmnwe*iT(soq%{QPqdIPvce9?M`?{TwdP&_yU&A%JaYg$jUE? z-7t&NKSqyP%@v{^v{14gln__BM82xT*;sKy>?Sl-U=*K`9^58&%M~EnW3<Wr2uZ&mT%s!&VO=(M>UbA_9$ z!|3MvJ!5@yy(u!B=(sL_%RB)sB6+QVo)!*Y(5w|T0&2h+#cDxkGMLc(GiptaB=SF9 zXJ~3k74DS@oRmWyeK!?rk*ic3^{0~!na#VdAE4>wmOgUdZQZ%fG%5+J`zC}+=ZhHK zl6Q#OyaA#Waa0-1a_u8!@l;3?ff2Awy6J?QiYfckCfyh4^~3#PN6JAb3KM~p&+TpX zZvXs^i;cymqcI0!;o2H1uaU3K`H-qISWeSAHk$mtO`Y20teKMEd<7 z)^(kSCc$7aN*|UuIs}yE2ij*cf1w>g1fxk{1yhwuXS6RWBnY?5gx0TYYiV;TQBc`Q z>~;0b)JEFqi~2)7!JEEw*GgM)ySnjZuC@Fz>8;NXA6clYuH;fuRK35*?#H(q>CEh9 z7QM-k`p}ENXJ6H!o{>H&egD4}h11n2CyUzqpeLwd$ob(}SwVeR&S1~ex|Vi5y>FQb zGoVm^C`t=bn*hov`i@(d7FON76RM-6TqTy4St%blA(t8~?>=zrbehK!SM0vDf7z$* zKTO+iYAv~NPHe*hG^W~1KrQ?QM8G^)O~+c)B;CmTpe2sV7Pa(}UXP1NE`CK@LomFU znmWbYEv%j!1ai8ZS{yc!UIr}~MW4z24b?xTWd14F{0j&(z|rK&Dd`GFyRm`>%?l2LdXuH+}w?|2%% zlgq0Dl3uPEd>FM*PpT+}ouf4PnGT-QK&BI_bP?RN>`eiKa;dJeh{sQ;JHX;_SfrfA z;jHFaK`gmiI1Mnx0FR1sR4!h9CAn-o&(WSL4I|=0fjahzV}@F>5=y!C3{OD)Q4brE>+}!8F_QDCXQ0{wRgWI1l@;)5?$qv7 zT?Wh>o<}MP4KF0C*Mrxiig8Y7rhWQfsu8DU_%w+6jP5-M-O3Q|Pi<9y+ReXVNQ-WPJx`1%q(MTM+C8m!`T}*=~0nTewREe@kn$d8@fAuAjZ9c(=1B*A}NZ?TLv2(?L#esZIycIvU zp>-GgG3khSt8oK*IZ64fTur z;`G@t))&tPng3%lwbGcx$`DvyVm_?|tT#i`TsH{U2@1&CXqQ;fSj$ zuzdJygF|ySEnAq?*$v)h8@DX$;FlV+=|2rEYZ~fp4-ZgrT&`Z>3|KLR>#JGUL2D@3&+~q#c_MuO?B9XFDC%IIC}j-d%<_Vpp!Pr2l>qG*(eHE zWue=oje-s}@Tg2T{nNh+t5YqGTr7;4crM|N%6rRt4RwjrzuI0n7O$u6S{#!~6WHflq=BD!Mkp6HEgx}|4K0>NF6^dfu-xf#k^VxSq%6&B zf5z`B6beO7l~GCfL`m2a&y1GtaMK+&k~5*9a`cxLS;x@;YP%UaQ|K23aiXFH4I~uO za)drvhZAaPMD3F36HS#mMrw=s+L4Yh9pzk(bO$7vCPz9)=L-4ZYvaWYL_deFI{NsR zmdE2Ozx?DQ!&mI4ULCS@q2o;3o;kckZHz*n2DK%V@~o*pN~K5e>1~$@an60Pt0{#Gyuo%nI}? z{e{n4!mgyRaLm`1Ncw~qWD+F2=wn1kJeHs!Ndk?3Zh?WsfpOZ@CRfvSDeKLrtw{2i@2=Hq8XIp(Z3ePMNM50Un2DwE8uhW1!&p6<6i-kt?5k!OJa&1kB6h2F1(S`=_ow`aM0ojDVkVm z7J$X8I0I*0Gp=NFhFBpiV|Qc96*J(}8IaZ_w+mvZUS578@p@(bX{bqn((b0Cu2kU{ z9-qg>K#oO76T}JjnsNGD{DQs3M+Ye}?x~N3nq6Xs*1+GHE`A>O%WJ`~y{*!2+y%j0 zO&9aXqB&zp5YAOcQkukbox3+2?Lon4w=h}MdAv2*o@lriUxdlVTm(OOJw=@`>8??J z5Hq+%{X$oH=>9s~PnR{~sz|sOw^R(wc8K_jfyg(S;4zJQniO`FO#lzpeV>ke7(;xe zrmiQdo~H+pzJ>qTn|etDDbaIToMW;Mb*`*5-|!cX9Ng5~yXoMFcCLD)r(S=P->1LR zf0+C_UBb7A-P#WIno?C*P)#4}dI+7P39GCM2}(^L#{0`U@r;wvz0$w=rqM#TVfKb= z=LnateeB--jcZ$0T$!8vusS#Kv61{nHeWW&!d9AxcE|ku#-7}jD_WXX?i>5~mx~{n zbM1!N25B=*A9v6jZp@DqR;$w&kJ4>)Gs!v-7W0^W2pp3-XK%uCV0s$xI1O2Pn5!Lr zb3I|TTjon^ZTl#$+Zvsh_#>A=8E~sk%h`{ z{6Ch5oMg|EB=)S5SfhwH#Wg~%d&5vBGqj<*IH45F#g6%R{$9OD=Ya*0^@C7#S9y~v zT=C!Sp^T?K%3mm67;W%mLiT83+?sLMN2T$Ic#NHp9>#C>aK_ybEv&TKqx|C$!WZg6 zHVTNhaU*1%OcCFc$r02o$d-1seVQ!y>6zmXg10Ids-922gEBsuO@&l#*kC9Tl*+=# z+Pd_kBxOuOdgusO@ljK%xhKqD(tF{&lqx%==3Us!UlQ(VPMY~>RpEM7k$BWGe-_%i~fxh=9gcBNPPmZYjqVIE4=vce2<4 z)-#0D=b`ICYLTs4$_mJ`xoYWw1WEF35%M!UI+!11)$Y~9}pLmX4%jV4ISu_UZ zqEg7kbd$<7&}jU^3OTsqiQ*G-aK#E7FhH%qPk5wLlRM>4#V3^8Vd3lncD@Ykyp8); zZi=^JGLVo-2c#}}gBl92p-;uXCVSeLJBJ*`@V&|ZWS?EROCEJ^S6bwOI%33+wAC}(jE1=l?CwbGjCZH1U9F+m@X%1Sp~Y|3X^mP#PkrsOx{CV+ zlg3nK(FgZ03ydxr2{g|S+@Eb~&VJ0m*UZcEU#ray^|s75#pf?b&QBO^W@AHcX;Wh@ z|196M(0|G+C6}susGkB90=e&>`icI3)XUG>HZX5?k2BfJdilk>nj2bsl8&C-yjg7) z)&Q`(q4lCxysciVGZ?zEts7hG#lz1`WC zO)d33(jPo?h6bIB&=?|U>NzlvzbUb~yL(IG1|EIc2X}Q0Sz>{;T`yE=wQU!*HZ1Cj zSciJ|4W05TabKmXMX#$g8e~llsnMVaJceulOH&;>6A$AXY1NDk$1^FW8BUiMLVT)A z%Q!iq31e!^Q0?UHyq?v#A>ph(F18S4rq z7wsBr+`RSDj!XY`{o-8sLK|*R>7)gxi?zY`o^k!_xWv^Yz^q-+Qq&7IMbtgfg?2)gAr)!sdv;*&8!~K&H`t z=$khT4BYTd;`z*rg7vE9I^ac7Y^^1X>+Wg;@oZNXM>aX6VhrNIJ`^Pc)uU)dvc=8f z5ttw!FbY;i%}Sq1+4)6Qg00UVS-~77Q<%!&rFV`kz2njWO`bL5$TQvqE``qWOpybw z%C=Iiws4K=ArWuyTr)SL;dwG{EV=EOOHA;Jd`GrETzaSUMb;(+Oby-c<-ZJdnJ0~o zAe%D?fM=3Da>h=aGua`_E*iPB_B5B+lW8v^q2fjYY>Ney2O>I)SUL zsi~#^S3o>L5+~~no{<%A#=v3L0#Am-=z+olX4lyDaRu;I7+Dn)GhczlUq zcS>B{qV4&6mQ>cd#i^$?w~gmY#V;Nf78}tc6b($ML}wxCRa%N*96Z@jlmi4rhuqIl_nX4+ z*+awwX8c#U*~x$^(z&$gWHT<@Z1z~K9{O?mlitBb>{IcB+ z20Mj(={b@v3Y^Md6mmEkft<*G4O-s$?wau+f&7@M(G%HOjvsFziGp#fQ zX81kNIrq*Ch%N8i`+0x=-{Sk^TW!nTVs{tY$Qo~_A~XQK+CY!}K_0NpJSy4Z!jO1*!tO$0uqwoocrKjv zfl1g?EHn3=xAW}n1q*MV-8nBkecsMkq4|&+dD&EJbQA zDQKQj#roj!nrSIw)52SDPhYs_?CpgM@t$<3>)fpctF1p&iB}htq?A3m?`-vI)~Bj@ z3LH&av+pcgG&sg6v&udIE)Q#%f}xXi6r8DIC1|OUu}bQt;gy*L*eDV%ghuP&L(0h{ ztdwIfSd*0+6<5Qm;a`(r5BIkx_c;<9+snH#9_Vxp4PsWrD7Q%(%1;=r!u`-CZ58& zSZ^(5{g$%Jht{)9eSIraKh#>e)OrQi6UP|%_udl&Jd-ABu1SBfZhy#=A|N~=kUJ`|<3Tts2^a9RoId$RK>kLpT*T~7;0 zEDmBV+-Q^oH83Cu97PEmfQK+WM1!M`0|gH1t8!fBu&)+b*eLbkb%_Z&2lx{h8WQA8 zpuc~AeIp8Q)a}-&hXfFTT}RfYna~I!0<|MP$dpz)vTGBAUD{$+>m}%ph-e}|fzW_A zQ|}$TpA~2&UIW-Syb?@3q(YmktC2jAGh>Y=!4zSF=TUot-2(zXV7>h=*lr5z1R4RK zgyJ%U2Jl+E;CcW{ij4sgzdcwBC`$zD2~)vNS-m|xypi&vCjSSNAN^7$pty}dZ(?8_ z_vNwf#NVM06$y?*5#l6~jskZ9I}miZ3Pcc{HU`9SH%_8e2C*Pz;C6q4eSyeR69piS;c(jbKg4$Efhh z+3b&&Mm!5}@kZLYzr%LbtGT-+k}5{=`3ndTxOqgMQ!* za=DR8=46@&vo`k_v>$9glC}=;wnu0&{F6KIU2<7!6SJC;teTY~()$$n+zgEtAjEe} ze|EJL?oYy^X8*6af-x(p)_q&Se1Y?Zv&Jf)w1>QXubi}EUU*$n&8EEy- z^F9%WX^yL)BYjEffWmOxoAiF=`yn{)dwrYUwrN5{0Qqa^MLUecR_X}k(QNybwUs)& zjtmx6swn(`SFi}@weJf`HCdt(0#6Z4D?~pPO>jVeI3huWvTcuA;Y9my>oH-(g>Q)D zF|mxq3}Z?-Jik+XoA^1-M6J$kjn-m@*qosvn;Dw7V{>Mx5u^sbM%x-kXENCRfwglG z4@Yd&aI@WR&6?n-qZl}TUt}T$N5am?J%9p_f_T&l$YT2t%t?UcbD$W8#c;rrJbQ9s zab3khoF_0O2@#C7V54;tfxA!zEQ;uAiAh?rcdZJ3LZdBz#A>NCot}j&!?i&oI4MD) zS_c=&a8J?!3lChfHa)h~+I;E2!U1^1N*{ZSmEuv;c5aV6s7rGH;a$59@1NWy$QsUO zt40nOwr*jWIC8*96`QS}ws2j`lTI?3lXaCRIB&%#ux!!br}%_*6@If*;g{xexZb)) zH*L{6?zAPlO||T2);+Y^X=0|sme5xI8a}0}VpL+{sEVp7;d8H*sK?G;&YDZE&COXp zdu;Ow)BN7O=bL)XPfMHMi~C%E_|BvvLBcfLS`3q%Hj{anj=jla}xF(k5p{aTB64leN)&Az3^hxinHp20MAxGBopJIXX-im4^MOVG%8gErRHC(y$XKQhQC z*vnZg+)cGX@X*6L2%)xN-c}+ao<1iwG{L5L5lawYVSLzd2t_7X3OcnV;X0i1#32W6 zI45A103}fSD=qU@O0_;9x|dnb=W%*#nbOCTJz?3X42MN3Gb@|dPk2K$J{bgDZiatg z?*!}EiR@WVZ%@l&x!Oe;EN?l?{rs@CiwXD#_n_6+3;6I#%lR>!j$Ntr_X?7~&P`CN z{dLMaW~Ib$0{cvSYM{Smv44g>xxi=V#KZDnFMm&NhTH}42-hqg>|yp}2mL>c_#pE- z_LXZ%006a#vD5@WAW-dX%;>L&=>tM5=Ey|O#M)Q^#i3IPh#0{eae$i|C7|UC#&MPi z|AJ70-zjKy>=wa60y&i0(C8<17A%oXb5I^b0|Aa8YnIr^Io+`rOLEi=(7z-Ad8EX;ichmN3sKwv z;;;#m9AmNdiAaJC=OrJO2q5qY=ae#n-Two`K4EIKPc8bEb!4$j62vQzJ%~7?SE4A< zdKV;$R`3nreg%t|70lDjbMVHn!g(DKKrleR$v@(_<2=zC=mw-6P5$U_!+#=xF!IKK zI7X2hR7&DvBk{T9PMHc!h|n86SXAOrRymY;rG@A$j@NJxM-S|u71OgaI<;FDP3YJ} zV|m*2)w7u z5lW);ur6Ue!V?w`9{fy3_KLI~QzJ97(t2bb`^|cJ!-Rul`!9R2dYHk(J$UTwHDi*> z6Wv2xI(a%vED6c6rk9RG8uuoqfICbx}GOC-3aynRDk> zj15vrw)3*bDE|8n|80{wKIKmkO^G2AayD@3$xJ@*pjT)4@Uy!@R z5HEKHw4m=FX;OZgRIR0$dcHBtPGWNP3-htQ>Ju50s5K1h8EU!A4z#*ED_vca2Mp;K z@1*c|QFtjm#BvX?yb!xTApxLf-Smq~>=6>@%DVZxX;OXvOyAP<4hG!~1bNnk>Xy}C zn`r2wVh6(Z^KPL%hiR>^!egDqVh^R4!o^=9kIxt~Fu9YT2ZI(LSW3Vb5}>aUmM93k z2)h8&Ag%*}0#IAE0I$Q=t-eL4!j1YB6$lIXfo1g67U-;Wm@*3Kp<$$*kMTOB@DLH+K9(3X6{`Z z7MwMs&>}(w4pKtkMa@LP$75QFq|uB>a!WEtY($JRjyG9hDq&~8AOS}XC!<*hTTT3 z7|6}rRwtoBeAFEWd>ulyfJL(;A_|r|wgd+U1pvqBs&*Fzn8K{YdDh0abow#!e3tR1 z4T|)B%(@M0Y`lMUXhR_*$pHS;L~Kg!IuTe~dtMKjWT;^M7srKd7vuoV$N6XvZ(#R% z295kX-OIKMY_Rr$0b;uek`cA7_DN;`Mkg^GEk?!L&U#!p zC_m%(mx-%~S{etfsGk+3K|e{ zI)CtnK@7jbLEp#Fe8CO?xG8iM!xDiw2vpu3#sa&0z@h^esn&k+z@hiypMCf8Tv~2ognTl>x0nIN|K2M2>gQa3cT3wEXl;B}8IqX> zSr5F{0?Z&8(Z zxYb1na1xV%Bz12cQh{bOu3B+!Sysy=!lei^a@3$3qX$i@nwgYPTUC-1qe;%}0xEJ= zH!aJg_n>=83iVzM?cqB`paG`NBU^|OS(MyvfmuYn${X2h*yNtwqOy`T+HP4<#53d& z36@VXYPF+=$cH+%Cc>*C55^S*OAuEePa%l3&$BPv9QdQF*jd61m)O>tNRTBdV1o#G zVFRXT`)2epf>$y?6A@%g>#R_8PBR8YXac}LY3!5Xn>~F%7}xmMu49?DtDCMaY8$j^ zlr1Dgnlq;_E=yNvV?o$b`YMf?c@YtLnMNo=_Mlj;BE4*J`k!6_o*v41%;3u?g6N}% zL3VJk;P(Qegz{MmXkIjmEEvRZzKhD;u>FvwZd4Hb*=el95ht`=PYcy)@4pL?LYpF!ti2$i|YoxNP# zg5w~t2BxzK(mW^XbS(`1c9UGnkcGze)V73$_B4jby+WiKB5nZHLB`BG?(rMt4|McX zSH5tDWw2JxtVuD3I%S~3H6Of3;o;ytn$OC;^+CFL@L6X#g&I>d5TyxA$($6X)9Dh; z{I}T5PSSSk?5pbBEoAiG7I>=NtHe^Ro2QTM=_MS4UmdujS&H6zS8FsF0#>r`vD^^TnB>52YHgS&*qD6$T*dlcLxv6R z6>ilCnx*7nA!?hhC@)TJ3<&GfH#P0uLwzW--CE;O~n_=TDW6|s+AS$`(&JyIP?0mMFoEGb?=W)6U(j#!gL4eN( zJzFOc<^|eI5R_!MhO6}9dX6GRkTwz&GFh9lo?zZaB(jexhHWoeg3&c0J{B}H8XuZO zzNqXE8YLHH4Re!eOjB2~01B?XMmz*d(&%1XXHuxKEcGQ|IxYt~P;Qts&y6sZ;? zE|-NkKes-^#|`b_q;TuEWKj1(byt4qKmav?aQ_&ahhu5oM#XE8^1VUCuBzm8{;t|k zZKu3lc@@9RTZ&A0;ed<<`@XTZJUXcRX4dQ2bjoXcR!o_kB=>NV25Ez&nNMVj6y7Rj zCz&R}bw~==jgumls*NE3p-qiwr(OvC4MwX(CJS;v@pd_6%rbqr&Vf6lxX8~D^g7ts zSUYAdmQh^_Vj+S--=rZCGP;p7cw%HkngV&fE^83$iGmbOuEAaL)VNtj<0RrbE5cQl z2L=8llVCUU@gcmrbf=v@!sgjD6>7(`NAkUf#* ziI?DGnu$~|gtyS13&JsJ*KKg7El<~hEpuqc9zvbNVso%>Dp-IB2?{tS*8>KG9(KWv zWV2M-jjonvJ5Eb#)AOvb9F;3A>u@G5B?7X%O3OM|oH7|Gt9%&D~}UQBi9p=-hwfb(_tQ zK#9=F6&%>Iz&`R6#o<8Kk-z!29K0>m1@G(l(r|`qN*YyptK;vqWFM$Px&}?AVTdH5Z4}VDJKlO zd0Fh^BT(+d*{jnh*evhJ&BF)!hjzxonoQquiR{G0alV;rkagc>%w{Q=0oHU*)T#YL z{jE>?hXkl~iJjMA52DY#m12^Ck0Le@)lM@~=7jvdojdooL8r&%OYIGoD7-)u;6Ef0qpEm=*!$;vfM2WA&J@FR}6V)Kd11>FwuQ z7#u?y{SS^9Te-#7EB0&u&i!I@+h<$N_qK}t2CF8ZU$_~6w3b1ZJ`fsV0)k8v3|82Y6c0{$03=kV zN(mAR5OqNq1MLp78rbI~lx;$rjo!5JnI)hwNs)Dp&`JuHqQL-G#!AwFp(~G*SSj}a z9xEkm7|&Yfa5kCUVm9IJU=4=~Y3VMbXY~ZXB_>EKvt5Xj5LJ#w-;mRknV1=`R`>%x zT`*Ka%taz_$SF(%Se!O9yO=kblgxSM7uK0ovyp6Hb^=?@!p_qQBKRi}eHYV0hIp%p zA-b(UUErHk>`o&2I)DPJcv~*T7^eO z79=n@Pl%_jH(G5a)>fkD;MM7qZMZ+a+e{sw)?3cs=LhS$|M;0!vXU7c5MNLmjL+LU`^a89hL^I&0 z1ne+mRZ|I>T8_gB+=Ji{5onJVY9N`Q5n_qnuP5*kFxrrF-uEiP;CFLi*{A~&WHL$p ziaA$-$T#AIA(I$pEcwPntR&5(C~wrdsx-9c21Z2&qBItrGqtC?5A+3K58)roaNoOY zgs!2cd^}KDjc{Q06^? zlorAu34TsKZ%f-~9J}43l_BN{cz0!o#tUg9Br3y|iJz895Q+oF4D3ht4C$~lgqvF4 zaq&U^X=_mwpoH#e(;qa+N5bRtglu?3-y%^w_;kdHDlLtabDwEmhv&qTtkI+;01^an z2>&amv`{E6oNd>3Knpf@&~&U-_=Qt)O8P<&FaSL)GV>WXLg8)Dx(M@}=t(x8c3aNJ znrMFz4M@;kSVGz;jTKKiLz}=Tm7ow|x0ea?2OfuZDQ9x)-U#g+~r7%IO8KdpQroJ_y zO_wmtAO%8(c^QhgQ_O-lAnpDS>=YPi5yiH%{t#bqEK%A7Yx_TAv1nytb4rt&+E{$h z(fe2v=KU1A`uV7US^Y!C3+uV=fbwf+>LIoaOggFv^;dWXhA}t~dCMV{u!WT_AlV5} z!2x9fD+yI#gtqW@3qe34w3s8zykjv~^pg@~Y7(Ii4=u$D4u?tt+>o>`XJ<(qI|35fyoI zb`Ae#gKX9RF!(=xNT7SE!PVSU8R-Vj`mE!zNfDJ(ScMgg_d4NW=T0K7DM#bTfc zq}&6B)+o})I+>6PmkGBZT>$MJ59zXGC6R+n2G?fefl{X0d8cB>x?Dz62gcc%|7KtMaARBk(*kfN!1%csMi6IR$nXuxu~`QLQIb z`&UK?R3yRNLh~cr28L)zj<7bCY~=|8hn5US0Ki=6LQ z>|+~6gjsKZTsD)TUwKUdWFmB(5D=1s-!Ku=^~2;8C-4{Au@-nEI$wz!2As=a-zBmb zpblwvJ#?+8gG{rNhm91xE-8~1XUC0;PMi?IQ4|slm~IPaX@L;4`~cC}RXOgb|5}D+~v+?A(;H3sdwxd}Cr%sro4w%BP%dx!gI_zk9&QU3*{7L&F@} z3P$gK>BSM6UcsTAEzQ(em!A+n4k%Rr@kYVS&d*=R`PmazJy7E~LKp>n9CRyU8^QgG z^AOzo;k>{POIHSV5OS0NOB_9aB;z^KY|3|n5dTWD;h-TE@FxHU#97b6R=o(Nv@Hbc zd2K}dRiHl?@98O$$m7R1Y}l0#q35>DScUlk29r)1fg9=)IUUs=4~;=P1r^=Q6qyAB7Dt2pJ({%Brcw=GV;Wn!6bm+S?*W1 zdhhs%>L)5S>z z2{u4Ak&!TEofL@1J;*W}7gRgH6nnWxSy(l98Ci7mmT{hmK~@b}bBlZ;BXr`j`+BX~!1{=g zCRu1*2>z-&IDdvm(WEoHgNjPbiH3E+kJirf^~Y&u_V5j8ZV}Qe*r_6MS#{(YLoWPZ z@5%c({2Y5SE$epd%MRRs*pnb>0#`|7W-u=^zarm7 zkUolipu;H&wZzXSq77)Lpu3lp!8HSx{O-vEqaZ`5k6aSq zZE047D7s|#jFfj{S%2RoO($Ph%p@v@R2gEHbMsfb1xn>k(trUG{{4oGi*pT7xmm5a zosm-O5uEJTH7C?7*wY8<%#2dN7HrNgP8=YS`G)kKP}j%L;A^?teUPiOk0>xIhdxLd z9Oc_DAU0Hqj}dX4Yk;3ZE%OQT@rm|}nriZk3vvtaafb%_`*0FPh-g`Sf+8d&M4?X` z73b^4#`Ufk5-pR?a~qKyH8xsrijQ!YE8P-Iy_RQ0j)+R^Y0NI*j_8Jld21ze#FD`H zj412-5*JBia3G9dSggM?EG$e3S)V-(Q9(YP+_fH=EBYD=MrHU&6)OMcqx#2cNGFoR#DQ2}$BDz|zXm43&m1JK$a*16!S)ZhOE5+x!sIdQdJT*5 zH>&zhpOC8$jSE%{?-APFFD%;EN$nMo6wtrEAXz$CG5(R43PSsZSjvW0Dk3Ff?SKWP z8LoplF0AL^sK9Q4FlW4-Bwn4w9vXj%i(KI=b8(YLPB*2j&I|6V3rLJqi#j{?j^S3S z6S$WX^Rs$*ck)*zKlH?goQ%~26Vn4#p*bV-4HNc{V_CzNqml;3rkWU%;v>O8<2?o)oQAi|+ zR=Co!bnnwU$a+tr!jR*)ZHvRhn;afa8$zu~fAVn3Pl!D!9^{Lmkn3B(905j$D$G4V zizdb+eF)*g-U_LJHYQ*s9YGsW11%w)po4%c$fHN@!wmb|;EEiin@VHMZ z>TN707~mkmfQ91T_13)m@{oJEvG_)d3o>;g0mS%=Zb0oQX#-dZxvy2`8N|il1%PaV ztOH-5#LI4LR{tG_%!nYO$4n5}Du@Hb7#Fly2ZKEdmLvf%|{r`n1_$^x+~c ziH_8>A}xCUJX|kcboBrQ!=sh)aCOB`Na-nN8|4}=FUZ!?C=T=Y(#jWFxrJn>D~@@e zT_=NCAe%lNvc^C{8nX;?acG)WxH^f=N*^C(v)Rd29qyxKM_O@fE74WUO_=X2P!ocE zLmOgh$8n1t*$~^#K8{#AaFqVgehBI>OnLf=7u(@56q*LAPK>|Q7FYowA{+%&cgRY? z^}$QPU7)of14B-A(rd9STC|A@2vB@2HM}BNgCzzax-EzVLP)hC?%3^tXd;v|T%%O0 zQY+6`%t31FRy34g9E+08gX}A;ku#rB`uT8;u-Ad!GKVc%)cln7mRfoJJGK5NrL0lr zY%%%x;my_$^cevBQtDv$Bvj4VG5&#gvs$Hw5Nw=BJcD>D8AZ0|Z3H5E>)J z%xyFdc?e`Dn90n6453fLZ)AZH?cHV?X}?KU+ukSddmp+$e-qp?9o3ByH?%(CsrK>{>gfQSq-?nNLBH9c=8CrrF5>0kO9_e91=aAJWT0=^qlR+trFs!rfAUt`IFxOMDZf!A^s7 zyPZ~tra#pEsLrRLdL5Br+i7<9XnKFu&=1CKZ({bMAY>mA;t;JioIKUUf=nUQ7Kq$N zN{oCETm`g4=I^ zgvygZSCA0EOW4joh)7!@^%4aP-ZcxbEoofSRaZBizqg0vP{17+6R=k?_$e~oB}Y;- zP{)H-k#GaWjfoy{3Uv3^xwJ6Kr-k=I@<72}0_}s=>WSB-8bWnxTzgxPwh+Rk4<|@& z9dEhgBbhkFfH*l=6-i< zD+VcTId*vt1S~&+ ze|-6kd5^I&@{C3MFIk%(dlV9+ys>Ctax#Fm$CzrKJ@y@hQ61fa`*c5h^zxkE<)xF8 zJ=|S-Waka-<3b|e7iSHovQT07`EmLa|ojCqZN=&u~eJ~S0_z}PuE zFj~RsAyUKv_XYhO7s}r_&l^yo9tsr_dB-J4%>r|^;YiJh@8_Kl|JF&mg&$2{i)(_W zh?T&GWD=%{@KupnST8N4BxYL7B6ADzt=Ka+P?Q=6I0eYuK<=~MMhXxbZiXt`_FX2~ zYxHmQj%`&r^dz2Z-&=pRr#k4o4o?03J|dP!M(8&?g0F3#2($zIY!szUck*Z(-Whs7 zjJD0CZPKQR1%+%Ee%v(1b+6*_r9 z=EbO01@Sgg>4QQ7@b&F+G6Vx5BLV>q)?G5G9g~XK`;Ev87Bf&C;IB0P1^2DQ#RpSf z*#9g6C;@U?$4tB!B>+LWs3`N^5{R`0TVD*vVz>(l!Nt@Qs5_!bAMd4+gXnA}{(Hf& z2(=ivU2>P0+?u6ZMti3AAD9B}p%=HZ!<1@YU4U07DaM29283A#d&j4w1`RNePZD2n zb_&bTPuc&-U_j5ln9u>b z(OZ_*=Eg`nc?IY}kFvh76|%tTdkpBG>WPt~E^&9Xq`rTclQU%YNeIk}#Dqf{dzMy2_l9QTlWe9 zr8H1g>e9>5#GrPB92a&cgA&`=$_Sf&TZuCnUHGkJ=Q5JXli~-7hJ`!?QG;MZAop4r zOvDM>FXN`+5cI~<`?17C0V1GnP^)DRmoh1=k;byphnq;X&5e!3!%V<%_EICsAWBkw zLOV^+*tJAzFj<*KA~8TN(Z*0kh#EFf2j{=7gc1UeFEK(k2h4AV+7Y-7ji^btY#5I zVXyQO&dhbNlZvH@GX;VB)ZHE2s6iH@5h3@c`4WQWAK9hPN;G$ zpi>;P3qB4OS%F_UKpQ%;p!_#73sOCvhnk}quK;(61W)t z@}FIEpR6XJeNfq%q&K00Ba9`lgz?6jf8(P2>ZJdP)+utJbI79GYOE+KwAD(fE+#SK z8`8|RLN8;#JO0|({?=wfkg2KbA67~os5q4@|7N_Sl9G3z>m9`Z#n`je{kiCARvs#@X)Wj}c{ROdMs?Xz^t2zx~?Z^vF+8-kD6^Pg_1RUx5hG>!u(JI5}qM3tW@)F6x zRFvC)z>vZRnuWw{s67zdAdOD8p?-p3W^F3c2wQ%q=8j-q+*r$>Sz zuzm2d4Y~d|7c(F_9ak|yzas{o*p{gTY9f|KM82c{#9<8}!*5TS+w#Xh;Q(!HRewy= zsk8O3(09ixrHul6Bi|vhb{iwm2+9pDf8iSF2!`LKKr7f<3DkqPyrC3C-C~$Wb;PRU zHPep|_R@JNbzVb`Os_fluPu5`&@U)4}fN z*lm;%RSHE3#I)k#8q6v1-N zEQU=k%a5!p>hul{%R8Nl)*UIw(zwmD($i;c9tY*-mqagHgT{!x-LV^CCr@r1ncJic zA2`qP(-Zvaw9LUYOy|oYhx1~GvIH{0XY$ub84s{%(|cuLhcDsFau_ceUv`1)b{qM! zD|?uEk1xBC^PpIYLGfogaZ7=Ru>i*57!Ph8DND)u=SW#b&c8~^;A4hsj*_wyyg?Cn zjxV!Jn5a8n<`_58IKC`$I4^c6OBi3#H2xYXqY*9O%QB`)w1qFrnMm#uUv^=Ji80EG z6+1DmqKCy(__CYBc_kAe`-Pl$Che#1<$`UNtI7FJ4(HvlERQ7TJ)jJ>c2dUJCr^1g zDWk1R=pSz=d&ozS^F9ve{h;h7pG3~%K4u>B8d45)xF*=497e9E?~56S-Q+9C_0gof z5zBIi_RAff)yd&}C;nY_Xu2A@8a0DT3#%%sD<;)w`cza^R#X+#lvb3-XnIeZrWsmV zGP$N&Gqkw6xN1gmQA}=eNky@y-?ZA|@*2&6!iw_hp~WS&(+a9a6jxQlT^eJI!9Xse z*N{u-O{LYE0!>X-K~Zs8LDf`E#UxG5IZ(m6g`i zKy?%ANPDN178aLdUGPJ-rlLwHOu{F0x%aIqt160W3v0S)umj;Fn#?NOLh<#qh!I3O?_&_9z)Cze7F$1vI88LDE+V27b;P@2fpv991Z zodQuc-@||VZ@GY!E`T#d@L9zaiPnjBiw=qo!T)`t{h}9`9gGHOqXGUKp)`mo1>Z>( z++PjH&lDh0YY8GfrKN5$}64EM}{&my=o z7rsm2u44GLAKXz3rE*gD0C*bKRt81xL9Uo?io>UEsKgT!-}+Kzr~E zoi!S0VHNyF$BT{@-b0TINFP_iG0w$Os11L^*1?Q~PkcVM16y54?h@KX@4)$jvkR|u zJcDCH-vL|l=VOI!tbpg%!c%HU>+v}_1L<>VE%==FZ-8&6fic5=DumCD`)nrk2DTNi zE`+zKg=f*ZeQ)36I8GyP9|6~QhP!ayO(fTMTsv(;`vlHh% zzLl_MJ9-29P93!?1?myz0KN%*7aS*C12}59QcL-FErK&M$(vWed7J_FpL@6_?XwEU zNtgu{&7{Zb88x0;aFSy5vFvioQ#KK?ZOJ7tAoxToC6c# zKb^xdR|Z_ExhlST?&`_!XI=}xqP&uQrR2)|D;KZaxq9&GvG0d}Kj!<%S7X0l=Rk{* z8kgFRzkwr1I$aF(%TA36J#Obf%g4`tXkkK6_^?j;Y`5hAaekKHSuo_3=1-( zY0w2YI6d*N!Pu@svBqoJQbsfJ`{p6;Q>58mt+QRX`|ICpRlHI7{3(CWC95}VY;c)k zXb}HmXb_#>DB@U-Q^tXj@Abp;oLl!kIqf}s2hr{wDjF`9D!Jjg zMx{Z42XdwJ$b#z0ATQKZlp8$^Zg^6rlnpH|Dyt|jG6op}@Qkz4+b(Z8h>XSvgC2hu zDT5tFS+!J*Lz!YF@esQIt7k8i)| zKJ7O&upy2e1p_K-VBHxw@60u@EOSut;H}rvzGK{mW8!W@@hANT4T<vSzRUb?sGd{^A+8KPt_Cbtb@o*9U#Jq;u%!*AIPDS=H3Q8)D48n$n#w4_cu9VPossSmKs$eY%~>+_Yr{ZO*~g-QK65iF5s8`$a4BV`69 zjCG(++{xf9mBXZ$NMs_BArMcxiG9Rg-<%w=ZBq8t%J^q;x5z(RGIccjzKDDd9%FKO=o8^6R zLBN8-qS__fmTXCH+Hn1;*Sb$$<9GV>bidz>bB29$;)%W^w)uYdMa<#IuT_g(Vn2R) z@ywrUySg23F3(81CL0=LdgOtSq&K>zJpc6Y&!)cOny~Sk^|z}0e|zZmvCU2C*XQ|6 zG_ZySX(dp;QIzUA7jzn$g~W~#wd*WH{lotiYSPtUz}YBLcD7I6p%oRNMZ?&ZPAV+~ z{ZiArwq|lgRcTF~jqU;UOEM&OHN+c?Nl5n+=wSjL{?F<1pHaZ?-HHa+mArEJqQ!~H zdiseMejhRUhxAWBI5H|{$JQBh%lhs=lf2^PEkSqh7B^f{onB^1UoXE}yz*3+;R_DU zlV6O9`d9BL-`6&0mJi69>Mi^7qtkCM4x0YN`>)K;e0it*(~}RMo2q)E`^r=LUe~^} z#;+N9HZXs{?LCn(XBQqA-RsWsm!lr6c`s^jO23OY`VDwXHEG!KfP;aDhff??b*E&X zP80uS{)2bzmgt>F&zD_mb^FQenULkV?aiTMZf!gN z^&>7BGtVvTf7WB)(W}p0e`HFuWbA~aFGr499~v;e??ts&P({)Szc}-h#e<%mGO2LZ z%Cm+KRs{J!3CGQ zyBMokWN^2weThK?B%lq2J9~S?iDg$ekDWOAqtqvskNM=(I^V=E|o2eSXP(q0!w?I^TL)rzxu_IP;b4>}OR>m(oQu zQipuLEjiQk%E&5IbaYw^G#Th>iG_FC{jwOi?q zPcFRmz()frpL_Mi16BPCRZZK@ZQi!%+P^%~pDKKHPw8UmyZsi;_U(1`NTBxYoV#3T z^pV~t4h3c%^Z9xA`uQy(nFE%Tdtcl(f5w=Pa_b&nxZ&*S&r_=te(mwnusuWjPicHk zx$5*%#rd@*w7-tI@sp9{RS z@O=NciOaSee>`sd^dQsDHO0q6uBK^qO9G-Ne3rDh_u@z&_fHCXJTZB~(4WusU%Sz4 zy6#;+v*-G+bA8o=1G}wyDri!iGCWx|>!HL`+3$?sb1Suf?yFy4{@kS?HS&`cT}~zC z^)#g!w*-60-yX64P+0yDZo`zi)2cJ)-+E%HY>sYv`t#B$-+g@atI&0;YmXQkyh{uX z-i09i8(`Z0kHzTwiuw*J$;SGZ3_x~x;onJQ?Bt-3h(VyYD=aQXH;_8)$KHlm`;B5_ zh*)##;*n>=-Z-2F+v&wFfL?pMe?t*kN~=H^TS- z)_iGa?0afI>A{e5qgQ7s_qtx1_p#LN@wdXCR_;8o`?F=+8$Ss=v*!!-&1*4xCcnPL z{nuxEGErHNcr|XGH+%QG!2y-($$dgTc~RZCd|5AXx5LgGeynbObxMz<4Oh|+N{qRS zb}LJNnml`U&PMP2-%|Ii?XtbN{Fm-;o($oZ1oi&Bv+K?w6_KAP({BE}tP{{4kr|7OR`-L*fyBF|Lo43>mHj>`;l1_x{(_{-+wIow$;CqB&{IRq^=4{=fbF`J;Y{A3W75 zEc4FZ@{2iVj3aN1efsOm!S5zizWCEA`INXp-&8d0m+jfL@6+-vlg4~6h_(LEQz{1` zw)jeP!oy{+ z3TvZn8~-U;^geaB*S0$_ZOGd#VWNU>kDHpZO{rdc%A+<<_rg!3^L-yQ_RVkjdH#Dl zHP_R;pS*HuRo@vS@?u`w`OKCd%<7rDx?TucKPIn!)bQ}P&L4QEa^<(ofa50d55B&Br0Lq`UY#`V%#v5OzGV&H`QE_b0k>aB zzc$OW&*=BRC>tctdR%rk;K+hfpKFi4pUN!# zJ`(92!?o+I{~J|sus+5mCL{l-r_OS)^WwJ4vw)il5K ziK#WiJkD-)W*QbY|1@`UW|#3t-nm@x_KeqhPKp|H!#g)zYz*%0uU-{+%1OC&Zh>L+ zZbQ2J%?S@L7}lrLCxc$^Cf}R(#mX1XRU1a?8=md!`r!|^`q#gIC~QL4Q4{+8GOGWg zt_y-{3Q8UyUq5X32P?Byymfe6{znDM@`$7AyNk>RzA9+x_f~jdSczwqTDxRtX3^ro z6L;rZW(KF;7+L$m!6j*fOhZ0$UoY)hGXK`3M$zi@2Y&uA(^7tU-Fv(L^~>x?XXB0Y z+0w^feOR7wbymQx@7KQH<4SD${_VeAC_1=>eM{rCa@PATZ!{iH&mZTro|WW;3=$~S zcR;DW{X+%(Y)7Q&|5w1le90^Kpnz{A3OL#r|39RI%f5Sfi0ijUzh2X;e!3`i!?T;T z6?=c&cJh|-%?~8s?yxqEEb}w$ef!9y<5Rx6b>+sagYW+9Y2C%UZ~QcM*hqQQkcM>6 z=6$)3p8Rcs=aLyGO{U&YT^Ors9ea12Dq&67h|HRw(>#vtJT(94{9lsh<@E~qWo_NS z$A>aIySb}w#n#mqf41Y5sh8e8b^E>9Ohu+4JuIZh2S16nu3k2}^Bb>P#NSjt({*6D zW%$lm>#LWS#vPbAe%%od3m%tt zpEkT)^?u-QuP+rR+AF57~f43(3hsVB-i}CDyt1)(1xc2vB zFJzyOczySd&sXo+p0@e;2Y$T=eZA;z2E%uEMMoD6RcHKBQ;r!1| z;Q?p&K9CS3-+w;w^E2a@eOdGH0MAVg+-XAtmqK*#mQDX}sui0lobo;1!11~ zctN7W?Hu|aZ3Ya~WVwyb207j)l5Ns#63XnNjgI08G+9(%&rBWqT-D}BlD6tDbzQLv zQkm_Yoik=c@xqLsqF?{PIATXY*31n#l?9u{yV%!e3^3(7ziPU%V#m^DF>mkxTB*6P zeW~xP_j9)gT-!Z;Nzt-_&lTo>cl*dEt%t2Yp8CG)uHgrJkNah#JnrsIm#}v>aFYf# z9NAUnzcAv3?q7snH%l)lKXdXkHi%q7hjb#ddgcFiM2TIgBNf)suGGK|G^lOX2QVzT zwy`hVV>>!u!HTM8t@h|yu=SA@z2^>44w1+wZya_rsE4fRb96>zb}`X3DS zR}A%+4D|=an&Tl~?}#W=JhV7XeMQ=%^0DyOfB5b2=X2_oe>!Gp(XNGlhWa)C7c7O2 zI}QwIQ;vP!`<0Y07bmYPj4A38Gdl6OyJp|H%&6^`HyFP^Jw)R;A;CU?Mla`^*A&hV zq-mP1A>WTUwDsp<7vino79DEo68VVKv~q&PW!B=SKl!xf?%>6P zmk!-|^7N_oCNAPg+*7~4=oURM@59Zz-}E~^Z^g$^-}{w4^v01rqHVK3y}jb_+|0s7 ztsh@FSvSaAmOuLLgk2B4vi!%z1AQ%Dl&m@ED)L-<^{ua0hK&AhbjBW6-xi4>N(Nm;zP9NS_daChg z&f}uz)_&W4Rkvjy*X?-K+{L-l_tK{8pZkm*^|EYw T-|Wu*C93JG*3SoP9%lXz9{#lZ literal 0 HcmV?d00001 diff --git a/src/Qt6/imports/FluentUI/Image/noise.png b/src/Qt6/imports/FluentUI/Image/noise.png new file mode 100644 index 0000000000000000000000000000000000000000..a78e829655892f964e38dcf2a103bd3b1b204240 GIT binary patch literal 271829 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≪|l91Nqibm%C%ACQTkcUCh^RDo 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μ5A6s-g-O>5ly|3YP>ce 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

    fBW4YJH@r`qhDVYQ#nX)Npi2_^-Od`9| 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≺5d{xNP@m~ZaKqNg4jtA!L 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

    i^~&EAF^UFc`9Xd=;kU16aaV!O%|Q2gD?xXRS0 z9M)}ta`q#ROjL?cB-AR$)S3RaQUq-G3JKYE-6J=5IIYKC(6Gu{s8Cw(G>BWFXMOOq z#Z8R(kw4eFLcMesl%JM;T&&p}ipJ7CPpvAGXa`}2?_N6Dnw}orWPzbnRwTbPftEKA zhH;rXAWCk_0d7iK2a)vYBT|>)eP*20OX5sUv}zsEczn}rIeI4QnSIjZlJvWOvM7wc zM50Jrd?V?&X{$bkq_i_a>C43SO+LLTw|j#2lUlAUlsm1wYtj2E)zgMr)kTFzxYoW zc~NH1%6Rg0BPMK-l>eWtK2S56o$8L4$y@&{3;(lh1kA(%Lr=TIe@kM3Zp<+w9AD zN%OOOciE@k2-7w({8)P*rC*xKcg4e%3JS9_S5At0<4M3JgiKDDz{ZGxm8t9v-a(J5 z`zA3JqpIHq>)sOsa;>_5q|LGQuHW=}o+YP@9%s|E8q~W8i~dzjBkpNRPX7K6^7XmVa#OYM zpE?PXOGkhSY-{4*8{my_nQQ&s1^hj}eGE)!H48y-z#^!x$QyWha{6p?JWroO4p%h~ z1FCMLYOUf}PKfNQq4FQl(Y%WVnbcOnbs`#_CP zw%kU_B=&7^mTX>p3J+7$_0!mY_1-4^^v8&9hf8=v{Gn3qJ% z31h~+@Z9L~DQnNPTVA-0f6H=PL||syCu@H?faD3j9{D6=-^Y)1ZN1NX*1#ppEsQu@ zar)vXO_m2 zgXGb|jD%D2Rof(D91#|h8;NMI<4~B(s*Hh$G|O{dfM+stL!MFdQ?waL5X;E8w!457bU(n4RmTOR^)!GH(ms zP|f`HZO2~|T!ZnUdfdZlP5AikR#JEs^#LtvbCmBca%IqWb^md+aH+H8^X?H0XUdnn%x;?*z zy)M|`7t{f+$!)(WGr2Pm0Aa}3U=0lib#lMv{LS6oWkg+k{1DvQUNlsv;fTuj-L*4- zL0oZv>gA`6z)OSgh0$=*GUNLGBXC`>vLfB3kQ&f?gipmsubq_ykP{!g{Q=%BG>mA$ zF4A<<B0Bifkc!sG~k(Z+<*fPg6I4HBf;(O zzn}RD9FzYt@6cUbDa`K^h(??Ubq-ee3b(v&!@w^pA`rf4e@n)hB;n?6m7& zkZy5ILE))fQ`3i;^ho``|I88k>Ur(p>MjkHzPU z9gd9I0%9hcVMUaLvZ4jTvi~doN~4@t)wVC-)-Nm;`MP^amvH_@7zS$loZLh%h<S zCK%u0L%bdsSi$0~*3WMj-=wWZ;GYIM#c=;+imITSInhv&NA67Mp>0)a8dpGVEN~4I z`Yf=d9#xO#eDaZVYNygT&Jup(kMkh?;0FndoM6kN^glIv`t4g!s`10LgVo4O-g{5y zFP%^@EeeIdwM}$U)+C-_A(W{z7k3qxpScL)UY`Wr(WY4MQQ!8@h$i8PbGle~@NAbR!9S)D{Od-Xt#&?S9?W`p)B_8XTQ z&vY+MkCs!slJP23bCL4ZZ0#i(+Z0soiF-9KMegz$uzB=8jp9JIMwg!^=}Pj;?%Y^= z`tye`c4?UBbO-asU98i1kaFnd_K+tm4(}K%fl#H_?n%1kixpEnckCdY>m!X6 z3+mTYVb?bHnz|nhe3=jPofY=t6TaeP^3`bft>esaka}$FJoIN(SW?yP*BT!q%BgmA z4N|Nh_n_C*y<%y*c%?119E$t~pUch&b43W*3vwZykjTv{qIli1#@sWsk=jVDgU?98 zE%~vC8?ZtFWzuT4(kL*dfl>hh$NxZ}z-o43cw88)5$ z^mntR?^dlS$Y<0uUvN2Cm7DM3ZQ$E)GN@0(9Is0#t=|!MtF!);&>lDQOlfNKQ)Y(L zhb)lv2zQjUpw}CjkM;3YG*P#h#1Hkr$@RU1mq87^7Hn?TZ`p90AYFoRDD?nj3hy;z zHvmytiLox3Deo(cFGFx^2)Ew17?Xl?_C}_P|rA$D?i(w@Z=LZes01 zzETo?)X%6hlH1AvyKVhs;M<7U7@_g&t~s^Lj--OLMY~Mp3MBV8^ivot#PcAjk|w8R zJn}(67Z1g#Z>5O4%W<}B1wy6O;Dl~}5zc@FH)8q|z+DrVAAQHb^Y$nQ?HzXg-BP{e zRrKTLs7S60tVf9@)_k{fAi@7fXyo`NDzoom_nl?w#PX8Zo$!U&g`pWGP3p;?JzXY* zPLQS+dsm1?@>c>_umAacGa9^#V2o?K4Tn)2#P;4i`YFsJSJnzT+kfjHIeb^pC#%H< z;GcfZkoH>{zmsdYZ`w~olkvnrxpO>Y3|lf$-R|i5iOg&j7*RQWC}O>5}fQ?^%{c=T(Q< z=-caCe)!DOC0;R6aVr7GZBWvlvL>DN^67h%Q5+#@68B;yZKHJFW3!pt$YI+qU3X1x z!7JE$*fzKbSVK+0XRWCH9|s|EZYA~UqkO~)SEZhunzc4yzz!Bt!OB^K*YgtT1 z;I3-5P|VE&C>Nf5w3sCifzL2LIQ5+QlWT6scKMSK1{V9pN{ zyh0ifx|MkgYTqGNil2VMHU_AZ9<13!MGfa_`F)s5M)SYWB5Fc+SAg+W)z;$+BM@Qw zF2mO}ZrYmIyfyYA_|RgoJ=0=XiRke7g<+n+r}=ET7G@toJaaN%D^dv6oPlu~dN88O z)%`I}d__Bo3iXqmtvf~&^_v{cTg4O zHOqP`6!9hK#f5&ukuNHt{>-kqJl?iQ zLM(P%m%n(IpB12c4lmjf)e{qh>lH{?jo$D+<3!sVHnM9|W}J#(6-1jzd^+o2eg?-G zeAL~D5s{W9<$T65>wju>y9n0q3oH2X;vsir z0Kx#XP*cK9Stn>X)rDOUIE5%s1)(Z9B7JR8-pjBjsl0)aMeo+@Te zrz)Ci_fuscI#vnq)dt%MkOmLqKT!z%^}Be{JAeHttsdH5w~Vs7-T7ib-}Uzr$PF1Z zoBU(4`6 z5HnkST|_dQF;zwm2qOFDA6OT&q?m`fFo`r$nvyCBII*M-di__8hbn4YBVw&(t@ql= z^H!nRW4&@?%?*pB#o>+7F1-0SkM7oCrAM`Om<7FCJ!x}{GzMn|DZ=YE!PoS|#@K#4 zay*0|4NNHaqHRn5#2*=#*pjbE$DiQ8jt~w?PP^j@-ILcEQ|Igtwn5Ko)cxSEQF0x% zBhh1e<_ZY^{hBfWBN=Vce(c;#uAr;Ht*Q%ETjeWwD_b%Ut)v8h21trV6nR zepM;*ogrFwnK`igN2}2(J^8qhN0a4?#E0Xiq8H|ri`>Sgn8(IGj<)UmvWu|AQL*ip z64T;iJIL)vi)|9*fPd~gfByMac8#Yg+&QFSMh(c!h1V~uc@M4(*|YE^JJ(s-pOJRz zZ{35108dCK!DCvA@1d$^7Tna0^eABP>DAU?GnGH8pF_g#xs)&FHiX?9UKVZ(hu1B?$k5B5$kgB!Nz@C%UTibXxQO6} z!hCtJ3R67gU4-BNl6@8R-aKVdE71jdjg=ztB#K|jlF_ew=x1D!!H%eRsG3$5S|`QF zT}maQvA+9ENLZrT^UH*%7V+Nvy7I}4BIJsZ*5xj}(fM#rYB2%r!I6~qokQ3sb@Exl zO}+AJevpKrIAN~3mXT*NU-824Ii^P z4+OKQ=vc>R(1_9b@JmJhFkU59+g)h@NHvI!m0o{ky#>=AY?(H8Gu?w}I?U23^%hq3 zL?G|3fSd3y-)FuY))^A^TL#zPcD2&SN(&i4TMC+Ftbz`&=&=Tb|NaoVN|P+?2VLA~ zny>!sQ1`zHqQIT`-*NzQOzyI3j*tjr!Uhs&ZzgH8{k(ydvL0h-O61mXVm}m%cnmb7 zcb;!bBfaRPgLd1H;>BXEL66sbT&UXx#wx!wv_6*PnZtT!{>md>R`^Kv{Bw^tlLOw; zm~Yt^8_3KBIPx)Kn-9u={nk!s247}m#!Ft(9bAzi4Mf=t*8i z7n7vkKeF#fRybuo0e|ERYHo;Ro2NFPG#AA_lWeh}x{GKW%EQEqO-WCH-!?1{vih|@ zbOK`+Tkaf~9b6)m`GrnRf{8xVHq=6JaQ?C8p;-ak&$FrPaMKvZadK<#>-S3t({j%q z%3LytbyqW_e2r`B& zVB7t4d{Zot8*!5OP9k5EMyX6Q^s4JigM_g$^RJfH^8&XL{p+GbLO`_b;={#Tr>zvO z0@fzwe=dfm&E2jY(l%_RuVwFBCMZ9p{Pi8FB|~d8V{Hqp5p-7uke;Q@jjDT{| zPqxZeLny5!W1TmS0aOU9PwOocGM|*Q5He=}D#U(o6yUjk+q9HC3+oJW?fWVuZd0-n z6s(DQ91aSp$PkHBejZz`%q7$pooN==FVZR_t_p-by%NHgSXz$hji#b9tmQh`Hmk-{ z0Y81!B0`(UwXUN&15e3Mbk?Q^>k_gmKwMKzaamCMzvnY9%8IaqNw#{c{x{nmG?QtS z#f0KS%SWi&i!TgDak2)r>G+ble!sg*-{QuN_dRyfNiIVK+D3G)DPZcXQSGrEa5H1= zyJh~hr893z6o7GpCV{C89t04(6tc|rfqdozfdXaK6ChMn_@7L>_5c;640Z*&%YR6D zv+EkC_zgUrfjP&=!bB@;!pLIPuaKqNIZ1!G;xyUJT;xj5!dc$lB>W`(TNtRXv!vSV z%7I;k@cfi0I9A2io^{`8{dMa@V2Gs_oVtCvMKRhBu8DK4ViNzPi1pi*hREFWqmk

    {F)tTsH8tJ;L}2-?hX-=Z43o_h<&^W6s$BdOSG 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 literal 0 HcmV?d00001 diff --git a/src/Qt6/imports/FluentUI/JS/Chart.js b/src/Qt6/imports/FluentUI/JS/Chart.js new file mode 100644 index 00000000..b3e9a0dd --- /dev/null +++ b/src/Qt6/imports/FluentUI/JS/Chart.js @@ -0,0 +1,20782 @@ +/*! + * Chart.js v2.9.3 + * https://www.chartjs.org + * (c) 2019 Chart.js Contributors + * Released under the MIT License + */ + + /*! + * adaptions by Elypson (Michael A. Voelkel) to get it working for QML: + * 1) changed overall library structure with UMD and global function build + * 2) animations are triggered via QML animator + * 3) tooltips do not use DOM events but QML events that are injected via bindEvents now + * 4) many smaller modifications because Chart.js relied on and used the DOM that is not available in QML in the same way + * 5) some fixes that occured in QML like setting dashed line to solid + * 6) personal customization, where we assumed that it leads to better looks + * + * also note that modifications are inspired by Shuirna (github.com/shuirna) and their changes were inspired by Julien Wintz + * + * (c) 2020 ChartJs2QML contributors (starting with Elypson, Michael A. Voelkel, https://github.com/Elypson) + * those customizations are also licensed under MIT for all matters and purposes + */ + +function UMD(global, factory) { +typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : +typeof define === 'function' && define.amd ? define(factory) : +(global = global || self, global.Chart = factory()); +}; + +function Chart (item, config) { 'use strict'; + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function commonjsRequire () { + throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); +} + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +function getCjsExportFromNamespace (n) { + return n && n['default'] || n; +} + +var colorName = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; + +var conversions = createCommonjsModule(function (module) { +/* MIT license */ + + +// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) + +var reverseKeywords = {}; +for (var key in colorName) { + if (colorName.hasOwnProperty(key)) { + reverseKeywords[colorName[key]] = key; + } +} + +var convert = module.exports = { + rgb: {channels: 3, labels: 'rgb'}, + hsl: {channels: 3, labels: 'hsl'}, + hsv: {channels: 3, labels: 'hsv'}, + hwb: {channels: 3, labels: 'hwb'}, + cmyk: {channels: 4, labels: 'cmyk'}, + xyz: {channels: 3, labels: 'xyz'}, + lab: {channels: 3, labels: 'lab'}, + lch: {channels: 3, labels: 'lch'}, + hex: {channels: 1, labels: ['hex']}, + keyword: {channels: 1, labels: ['keyword']}, + ansi16: {channels: 1, labels: ['ansi16']}, + ansi256: {channels: 1, labels: ['ansi256']}, + hcg: {channels: 3, labels: ['h', 'c', 'g']}, + apple: {channels: 3, labels: ['r16', 'g16', 'b16']}, + gray: {channels: 1, labels: ['gray']} +}; + +// hide .channels and .labels properties +for (var model in convert) { + if (convert.hasOwnProperty(model)) { + if (!('channels' in convert[model])) { + throw new Error('missing channels property: ' + model); + } + + if (!('labels' in convert[model])) { + throw new Error('missing channel labels property: ' + model); + } + + if (convert[model].labels.length !== convert[model].channels) { + throw new Error('channel and label counts mismatch: ' + model); + } + + var channels = convert[model].channels; + var labels = convert[model].labels; + delete convert[model].channels; + delete convert[model].labels; + Object.defineProperty(convert[model], 'channels', {value: channels}); + Object.defineProperty(convert[model], 'labels', {value: labels}); + } +} + +convert.rgb.hsl = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var min = Math.min(r, g, b); + var max = Math.max(r, g, b); + var delta = max - min; + var h; + var s; + var l; + + if (max === min) { + h = 0; + } else if (r === max) { + h = (g - b) / delta; + } else if (g === max) { + h = 2 + (b - r) / delta; + } else if (b === max) { + h = 4 + (r - g) / delta; + } + + h = Math.min(h * 60, 360); + + if (h < 0) { + h += 360; + } + + l = (min + max) / 2; + + if (max === min) { + s = 0; + } else if (l <= 0.5) { + s = delta / (max + min); + } else { + s = delta / (2 - max - min); + } + + return [h, s * 100, l * 100]; +}; + +convert.rgb.hsv = function (rgb) { + var rdif; + var gdif; + var bdif; + var h; + var s; + + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var v = Math.max(r, g, b); + var diff = v - Math.min(r, g, b); + var diffc = function (c) { + return (v - c) / 6 / diff + 1 / 2; + }; + + if (diff === 0) { + h = s = 0; + } else { + s = diff / v; + rdif = diffc(r); + gdif = diffc(g); + bdif = diffc(b); + + if (r === v) { + h = bdif - gdif; + } else if (g === v) { + h = (1 / 3) + rdif - bdif; + } else if (b === v) { + h = (2 / 3) + gdif - rdif; + } + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + } + + return [ + h * 360, + s * 100, + v * 100 + ]; +}; + +convert.rgb.hwb = function (rgb) { + var r = rgb[0]; + var g = rgb[1]; + var b = rgb[2]; + var h = convert.rgb.hsl(rgb)[0]; + var w = 1 / 255 * Math.min(r, Math.min(g, b)); + + b = 1 - 1 / 255 * Math.max(r, Math.max(g, b)); + + return [h, w * 100, b * 100]; +}; + +convert.rgb.cmyk = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var c; + var m; + var y; + var k; + + k = Math.min(1 - r, 1 - g, 1 - b); + c = (1 - r - k) / (1 - k) || 0; + m = (1 - g - k) / (1 - k) || 0; + y = (1 - b - k) / (1 - k) || 0; + + return [c * 100, m * 100, y * 100, k * 100]; +}; + +/** + * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + * */ +function comparativeDistance(x, y) { + return ( + Math.pow(x[0] - y[0], 2) + + Math.pow(x[1] - y[1], 2) + + Math.pow(x[2] - y[2], 2) + ); +} + +convert.rgb.keyword = function (rgb) { + var reversed = reverseKeywords[rgb]; + if (reversed) { + return reversed; + } + + var currentClosestDistance = Infinity; + var currentClosestKeyword; + + for (var keyword in colorName) { + if (colorName.hasOwnProperty(keyword)) { + var value = colorName[keyword]; + + // Compute comparative distance + var distance = comparativeDistance(rgb, value); + + // Check if its less, if so set as closest + if (distance < currentClosestDistance) { + currentClosestDistance = distance; + currentClosestKeyword = keyword; + } + } + } + + return currentClosestKeyword; +}; + +convert.keyword.rgb = function (keyword) { + return colorName[keyword]; +}; + +convert.rgb.xyz = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + + // assume sRGB + r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); + g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); + b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); + + var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); + + return [x * 100, y * 100, z * 100]; +}; + +convert.rgb.lab = function (rgb) { + var xyz = convert.rgb.xyz(rgb); + var x = xyz[0]; + var y = xyz[1]; + var z = xyz[2]; + var l; + var a; + var b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.hsl.rgb = function (hsl) { + var h = hsl[0] / 360; + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var t1; + var t2; + var t3; + var rgb; + var val; + + if (s === 0) { + val = l * 255; + return [val, val, val]; + } + + if (l < 0.5) { + t2 = l * (1 + s); + } else { + t2 = l + s - l * s; + } + + t1 = 2 * l - t2; + + rgb = [0, 0, 0]; + for (var i = 0; i < 3; i++) { + t3 = h + 1 / 3 * -(i - 1); + if (t3 < 0) { + t3++; + } + if (t3 > 1) { + t3--; + } + + if (6 * t3 < 1) { + val = t1 + (t2 - t1) * 6 * t3; + } else if (2 * t3 < 1) { + val = t2; + } else if (3 * t3 < 2) { + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + } else { + val = t1; + } + + rgb[i] = val * 255; + } + + return rgb; +}; + +convert.hsl.hsv = function (hsl) { + var h = hsl[0]; + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var smin = s; + var lmin = Math.max(l, 0.01); + var sv; + var v; + + l *= 2; + s *= (l <= 1) ? l : 2 - l; + smin *= lmin <= 1 ? lmin : 2 - lmin; + v = (l + s) / 2; + sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s); + + return [h, sv * 100, v * 100]; +}; + +convert.hsv.rgb = function (hsv) { + var h = hsv[0] / 60; + var s = hsv[1] / 100; + var v = hsv[2] / 100; + var hi = Math.floor(h) % 6; + + var f = h - Math.floor(h); + var p = 255 * v * (1 - s); + var q = 255 * v * (1 - (s * f)); + var t = 255 * v * (1 - (s * (1 - f))); + v *= 255; + + switch (hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } +}; + +convert.hsv.hsl = function (hsv) { + var h = hsv[0]; + var s = hsv[1] / 100; + var v = hsv[2] / 100; + var vmin = Math.max(v, 0.01); + var lmin; + var sl; + var l; + + l = (2 - s) * v; + lmin = (2 - s) * vmin; + sl = s * vmin; + sl /= (lmin <= 1) ? lmin : 2 - lmin; + sl = sl || 0; + l /= 2; + + return [h, sl * 100, l * 100]; +}; + +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +convert.hwb.rgb = function (hwb) { + var h = hwb[0] / 360; + var wh = hwb[1] / 100; + var bl = hwb[2] / 100; + var ratio = wh + bl; + var i; + var v; + var f; + var n; + + // wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } + + i = Math.floor(6 * h); + v = 1 - bl; + f = 6 * h - i; + + if ((i & 0x01) !== 0) { + f = 1 - f; + } + + n = wh + f * (v - wh); // linear interpolation + + var r; + var g; + var b; + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } + + return [r * 255, g * 255, b * 255]; +}; + +convert.cmyk.rgb = function (cmyk) { + var c = cmyk[0] / 100; + var m = cmyk[1] / 100; + var y = cmyk[2] / 100; + var k = cmyk[3] / 100; + var r; + var g; + var b; + + r = 1 - Math.min(1, c * (1 - k) + k); + g = 1 - Math.min(1, m * (1 - k) + k); + b = 1 - Math.min(1, y * (1 - k) + k); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.rgb = function (xyz) { + var x = xyz[0] / 100; + var y = xyz[1] / 100; + var z = xyz[2] / 100; + var r; + var g; + var b; + + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); + + // assume sRGB + r = r > 0.0031308 + ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) + : r * 12.92; + + g = g > 0.0031308 + ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) + : g * 12.92; + + b = b > 0.0031308 + ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) + : b * 12.92; + + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); + + return [r * 255, g * 255, b * 255]; +}; + +convert.xyz.lab = function (xyz) { + var x = xyz[0]; + var y = xyz[1]; + var z = xyz[2]; + var l; + var a; + var b; + + x /= 95.047; + y /= 100; + z /= 108.883; + + x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116); + + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); + + return [l, a, b]; +}; + +convert.lab.xyz = function (lab) { + var l = lab[0]; + var a = lab[1]; + var b = lab[2]; + var x; + var y; + var z; + + y = (l + 16) / 116; + x = a / 500 + y; + z = y - b / 200; + + var y2 = Math.pow(y, 3); + var x2 = Math.pow(x, 3); + var z2 = Math.pow(z, 3); + y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787; + x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787; + z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787; + + x *= 95.047; + y *= 100; + z *= 108.883; + + return [x, y, z]; +}; + +convert.lab.lch = function (lab) { + var l = lab[0]; + var a = lab[1]; + var b = lab[2]; + var hr; + var h; + var c; + + hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + + if (h < 0) { + h += 360; + } + + c = Math.sqrt(a * a + b * b); + + return [l, c, h]; +}; + +convert.lch.lab = function (lch) { + var l = lch[0]; + var c = lch[1]; + var h = lch[2]; + var a; + var b; + var hr; + + hr = h / 360 * 2 * Math.PI; + a = c * Math.cos(hr); + b = c * Math.sin(hr); + + return [l, a, b]; +}; + +convert.rgb.ansi16 = function (args) { + var r = args[0]; + var g = args[1]; + var b = args[2]; + var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization + + value = Math.round(value / 50); + + if (value === 0) { + return 30; + } + + var ansi = 30 + + ((Math.round(b / 255) << 2) + | (Math.round(g / 255) << 1) + | Math.round(r / 255)); + + if (value === 2) { + ansi += 60; + } + + return ansi; +}; + +convert.hsv.ansi16 = function (args) { + // optimization here; we already know the value and don't need to get + // it converted for us. + return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]); +}; + +convert.rgb.ansi256 = function (args) { + var r = args[0]; + var g = args[1]; + var b = args[2]; + + // we use the extended greyscale palette here, with the exception of + // black and white. normal palette only has 4 greyscale shades. + if (r === g && g === b) { + if (r < 8) { + return 16; + } + + if (r > 248) { + return 231; + } + + return Math.round(((r - 8) / 247) * 24) + 232; + } + + var ansi = 16 + + (36 * Math.round(r / 255 * 5)) + + (6 * Math.round(g / 255 * 5)) + + Math.round(b / 255 * 5); + + return ansi; +}; + +convert.ansi16.rgb = function (args) { + var color = args % 10; + + // handle greyscale + if (color === 0 || color === 7) { + if (args > 50) { + color += 3.5; + } + + color = color / 10.5 * 255; + + return [color, color, color]; + } + + var mult = (~~(args > 50) + 1) * 0.5; + var r = ((color & 1) * mult) * 255; + var g = (((color >> 1) & 1) * mult) * 255; + var b = (((color >> 2) & 1) * mult) * 255; + + return [r, g, b]; +}; + +convert.ansi256.rgb = function (args) { + // handle greyscale + if (args >= 232) { + var c = (args - 232) * 10 + 8; + return [c, c, c]; + } + + args -= 16; + + var rem; + var r = Math.floor(args / 36) / 5 * 255; + var g = Math.floor((rem = args % 36) / 6) / 5 * 255; + var b = (rem % 6) / 5 * 255; + + return [r, g, b]; +}; + +convert.rgb.hex = function (args) { + var integer = ((Math.round(args[0]) & 0xFF) << 16) + + ((Math.round(args[1]) & 0xFF) << 8) + + (Math.round(args[2]) & 0xFF); + + var string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.hex.rgb = function (args) { + var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i); + if (!match) { + return [0, 0, 0]; + } + + var colorString = match[0]; + + if (match[0].length === 3) { + colorString = colorString.split('').map(function (char) { + return char + char; + }).join(''); + } + + var integer = parseInt(colorString, 16); + var r = (integer >> 16) & 0xFF; + var g = (integer >> 8) & 0xFF; + var b = integer & 0xFF; + + return [r, g, b]; +}; + +convert.rgb.hcg = function (rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var max = Math.max(Math.max(r, g), b); + var min = Math.min(Math.min(r, g), b); + var chroma = (max - min); + var grayscale; + var hue; + + if (chroma < 1) { + grayscale = min / (1 - chroma); + } else { + grayscale = 0; + } + + if (chroma <= 0) { + hue = 0; + } else + if (max === r) { + hue = ((g - b) / chroma) % 6; + } else + if (max === g) { + hue = 2 + (b - r) / chroma; + } else { + hue = 4 + (r - g) / chroma + 4; + } + + hue /= 6; + hue %= 1; + + return [hue * 360, chroma * 100, grayscale * 100]; +}; + +convert.hsl.hcg = function (hsl) { + var s = hsl[1] / 100; + var l = hsl[2] / 100; + var c = 1; + var f = 0; + + if (l < 0.5) { + c = 2.0 * s * l; + } else { + c = 2.0 * s * (1.0 - l); + } + + if (c < 1.0) { + f = (l - 0.5 * c) / (1.0 - c); + } + + return [hsl[0], c * 100, f * 100]; +}; + +convert.hsv.hcg = function (hsv) { + var s = hsv[1] / 100; + var v = hsv[2] / 100; + + var c = s * v; + var f = 0; + + if (c < 1.0) { + f = (v - c) / (1 - c); + } + + return [hsv[0], c * 100, f * 100]; +}; + +convert.hcg.rgb = function (hcg) { + var h = hcg[0] / 360; + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + if (c === 0.0) { + return [g * 255, g * 255, g * 255]; + } + + var pure = [0, 0, 0]; + var hi = (h % 1) * 6; + var v = hi % 1; + var w = 1 - v; + var mg = 0; + + switch (Math.floor(hi)) { + case 0: + pure[0] = 1; pure[1] = v; pure[2] = 0; break; + case 1: + pure[0] = w; pure[1] = 1; pure[2] = 0; break; + case 2: + pure[0] = 0; pure[1] = 1; pure[2] = v; break; + case 3: + pure[0] = 0; pure[1] = w; pure[2] = 1; break; + case 4: + pure[0] = v; pure[1] = 0; pure[2] = 1; break; + default: + pure[0] = 1; pure[1] = 0; pure[2] = w; + } + + mg = (1.0 - c) * g; + + return [ + (c * pure[0] + mg) * 255, + (c * pure[1] + mg) * 255, + (c * pure[2] + mg) * 255 + ]; +}; + +convert.hcg.hsv = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + var v = c + g * (1.0 - c); + var f = 0; + + if (v > 0.0) { + f = c / v; + } + + return [hcg[0], f * 100, v * 100]; +}; + +convert.hcg.hsl = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + + var l = g * (1.0 - c) + 0.5 * c; + var s = 0; + + if (l > 0.0 && l < 0.5) { + s = c / (2 * l); + } else + if (l >= 0.5 && l < 1.0) { + s = c / (2 * (1 - l)); + } + + return [hcg[0], s * 100, l * 100]; +}; + +convert.hcg.hwb = function (hcg) { + var c = hcg[1] / 100; + var g = hcg[2] / 100; + var v = c + g * (1.0 - c); + return [hcg[0], (v - c) * 100, (1 - v) * 100]; +}; + +convert.hwb.hcg = function (hwb) { + var w = hwb[1] / 100; + var b = hwb[2] / 100; + var v = 1 - b; + var c = v - w; + var g = 0; + + if (c < 1) { + g = (v - c) / (1 - c); + } + + return [hwb[0], c * 100, g * 100]; +}; + +convert.apple.rgb = function (apple) { + return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255]; +}; + +convert.rgb.apple = function (rgb) { + return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535]; +}; + +convert.gray.rgb = function (args) { + return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255]; +}; + +convert.gray.hsl = convert.gray.hsv = function (args) { + return [0, 0, args[0]]; +}; + +convert.gray.hwb = function (gray) { + return [0, 100, gray[0]]; +}; + +convert.gray.cmyk = function (gray) { + return [0, 0, 0, gray[0]]; +}; + +convert.gray.lab = function (gray) { + return [gray[0], 0, 0]; +}; + +convert.gray.hex = function (gray) { + var val = Math.round(gray[0] / 100 * 255) & 0xFF; + var integer = (val << 16) + (val << 8) + val; + + var string = integer.toString(16).toUpperCase(); + return '000000'.substring(string.length) + string; +}; + +convert.rgb.gray = function (rgb) { + var val = (rgb[0] + rgb[1] + rgb[2]) / 3; + return [val / 255 * 100]; +}; +}); +var conversions_1 = conversions.rgb; +var conversions_2 = conversions.hsl; +var conversions_3 = conversions.hsv; +var conversions_4 = conversions.hwb; +var conversions_5 = conversions.cmyk; +var conversions_6 = conversions.xyz; +var conversions_7 = conversions.lab; +var conversions_8 = conversions.lch; +var conversions_9 = conversions.hex; +var conversions_10 = conversions.keyword; +var conversions_11 = conversions.ansi16; +var conversions_12 = conversions.ansi256; +var conversions_13 = conversions.hcg; +var conversions_14 = conversions.apple; +var conversions_15 = conversions.gray; + +/* + this function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. +*/ + +function buildGraph() { + var graph = {}; + // https://jsperf.com/object-keys-vs-for-in-with-closure/3 + var models = Object.keys(conversions); + + for (var len = models.length, i = 0; i < len; i++) { + graph[models[i]] = { + // http://jsperf.com/1-vs-infinity + // micro-opt, but this is simple. + distance: -1, + parent: null + }; + } + + return graph; +} + +// https://en.wikipedia.org/wiki/Breadth-first_search +function deriveBFS(fromModel) { + var graph = buildGraph(); + var queue = [fromModel]; // unshift -> queue -> pop + + graph[fromModel].distance = 0; + + while (queue.length) { + var current = queue.pop(); + var adjacents = Object.keys(conversions[current]); + + for (var len = adjacents.length, i = 0; i < len; i++) { + var adjacent = adjacents[i]; + var node = graph[adjacent]; + + if (node.distance === -1) { + node.distance = graph[current].distance + 1; + node.parent = current; + queue.unshift(adjacent); + } + } + } + + return graph; +} + +function link(from, to) { + return function (args) { + return to(from(args)); + }; +} + +function wrapConversion(toModel, graph) { + var path = [graph[toModel].parent, toModel]; + var fn = conversions[graph[toModel].parent][toModel]; + + var cur = graph[toModel].parent; + while (graph[cur].parent) { + path.unshift(graph[cur].parent); + fn = link(conversions[graph[cur].parent][cur], fn); + cur = graph[cur].parent; + } + + fn.conversion = path; + return fn; +} + +var route = function (fromModel) { + var graph = deriveBFS(fromModel); + var conversion = {}; + + var models = Object.keys(graph); + for (var len = models.length, i = 0; i < len; i++) { + var toModel = models[i]; + var node = graph[toModel]; + + if (node.parent === null) { + // no possible conversion, or this node is the source model. + continue; + } + + conversion[toModel] = wrapConversion(toModel, graph); + } + + return conversion; +}; + +var convert = {}; + +var models = Object.keys(conversions); + +function wrapRaw(fn) { + var wrappedFn = function (args) { + if (args === undefined || args === null) { + return args; + } + + if (arguments.length > 1) { + args = Array.prototype.slice.call(arguments); + } + + return fn(args); + }; + + // preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +function wrapRounded(fn) { + var wrappedFn = function (args) { + if (args === undefined || args === null) { + return args; + } + + if (arguments.length > 1) { + args = Array.prototype.slice.call(arguments); + } + + var result = fn(args); + + // we're assuming the result is an array here. + // see notice in conversions.js; don't use box types + // in conversion functions. + if (typeof result === 'object') { + for (var len = result.length, i = 0; i < len; i++) { + result[i] = Math.round(result[i]); + } + } + + return result; + }; + + // preserve .conversion property if there is one + if ('conversion' in fn) { + wrappedFn.conversion = fn.conversion; + } + + return wrappedFn; +} + +models.forEach(function (fromModel) { + convert[fromModel] = {}; + + Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels}); + Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels}); + + var routes = route(fromModel); + var routeModels = Object.keys(routes); + + routeModels.forEach(function (toModel) { + var fn = routes[toModel]; + + convert[fromModel][toModel] = wrapRounded(fn); + convert[fromModel][toModel].raw = wrapRaw(fn); + }); +}); + +var colorConvert = convert; + +var colorName$1 = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; + +/* MIT license */ + + +var colorString = { + getRgba: getRgba, + getHsla: getHsla, + getRgb: getRgb, + getHsl: getHsl, + getHwb: getHwb, + getAlpha: getAlpha, + + hexString: hexString, + rgbString: rgbString, + rgbaString: rgbaString, + percentString: percentString, + percentaString: percentaString, + hslString: hslString, + hslaString: hslaString, + hwbString: hwbString, + keyword: keyword +}; + +function getRgba(string) { + if (!string) { + return; + } + var abbr = /^#([a-fA-F0-9]{3,4})$/i, + hex = /^#([a-fA-F0-9]{6}([a-fA-F0-9]{2})?)$/i, + rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, + per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, + keyword = /(\w+)/; + + var rgb = [0, 0, 0], + a = 1, + match = string.match(abbr), + hexAlpha = ""; + if (match) { + match = match[1]; + hexAlpha = match[3]; + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match[i] + match[i], 16); + } + if (hexAlpha) { + a = Math.round((parseInt(hexAlpha + hexAlpha, 16) / 255) * 100) / 100; + } + } + else if (match = string.match(hex)) { + hexAlpha = match[2]; + match = match[1]; + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16); + } + if (hexAlpha) { + a = Math.round((parseInt(hexAlpha, 16) / 255) * 100) / 100; + } + } + else if (match = string.match(rgba)) { + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match[i + 1]); + } + a = parseFloat(match[4]); + } + else if (match = string.match(per)) { + for (var i = 0; i < rgb.length; i++) { + rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); + } + a = parseFloat(match[4]); + } + else if (match = string.match(keyword)) { + if (match[1] == "transparent") { + return [0, 0, 0, 0]; + } + rgb = colorName$1[match[1]]; + if (!rgb) { + return; + } + } + + for (var i = 0; i < rgb.length; i++) { + rgb[i] = scale(rgb[i], 0, 255); + } + if (!a && a != 0) { + a = 1; + } + else { + a = scale(a, 0, 1); + } + rgb[3] = a; + return rgb; +} + +function getHsla(string) { + if (!string) { + return; + } + var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; + var match = string.match(hsl); + if (match) { + var alpha = parseFloat(match[4]); + var h = scale(parseInt(match[1]), 0, 360), + s = scale(parseFloat(match[2]), 0, 100), + l = scale(parseFloat(match[3]), 0, 100), + a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, s, l, a]; + } +} + +function getHwb(string) { + if (!string) { + return; + } + var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; + var match = string.match(hwb); + if (match) { + var alpha = parseFloat(match[4]); + var h = scale(parseInt(match[1]), 0, 360), + w = scale(parseFloat(match[2]), 0, 100), + b = scale(parseFloat(match[3]), 0, 100), + a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, w, b, a]; + } +} + +function getRgb(string) { + var rgba = getRgba(string); + return rgba && rgba.slice(0, 3); +} + +function getHsl(string) { + var hsla = getHsla(string); + return hsla && hsla.slice(0, 3); +} + +function getAlpha(string) { + var vals = getRgba(string); + if (vals) { + return vals[3]; + } + else if (vals = getHsla(string)) { + return vals[3]; + } + else if (vals = getHwb(string)) { + return vals[3]; + } +} + +// generators +function hexString(rgba, a) { + var a = (a !== undefined && rgba.length === 3) ? a : rgba[3]; + return "#" + hexDouble(rgba[0]) + + hexDouble(rgba[1]) + + hexDouble(rgba[2]) + + ( + (a >= 0 && a < 1) + ? hexDouble(Math.round(a * 255)) + : "" + ); +} + +function rgbString(rgba, alpha) { + if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { + return rgbaString(rgba, alpha); + } + return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")"; +} + +function rgbaString(rgba, alpha) { + if (alpha === undefined) { + alpha = (rgba[3] !== undefined ? rgba[3] : 1); + } + return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + + ", " + alpha + ")"; +} + +function percentString(rgba, alpha) { + if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { + return percentaString(rgba, alpha); + } + var r = Math.round(rgba[0]/255 * 100), + g = Math.round(rgba[1]/255 * 100), + b = Math.round(rgba[2]/255 * 100); + + return "rgb(" + r + "%, " + g + "%, " + b + "%)"; +} + +function percentaString(rgba, alpha) { + var r = Math.round(rgba[0]/255 * 100), + g = Math.round(rgba[1]/255 * 100), + b = Math.round(rgba[2]/255 * 100); + return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")"; +} + +function hslString(hsla, alpha) { + if (alpha < 1 || (hsla[3] && hsla[3] < 1)) { + return hslaString(hsla, alpha); + } + return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)"; +} + +function hslaString(hsla, alpha) { + if (alpha === undefined) { + alpha = (hsla[3] !== undefined ? hsla[3] : 1); + } + return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + + alpha + ")"; +} + +// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax +// (hwb have alpha optional & 1 is default value) +function hwbString(hwb, alpha) { + if (alpha === undefined) { + alpha = (hwb[3] !== undefined ? hwb[3] : 1); + } + return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%" + + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")"; +} + +// helpers +function scale(num, min, max) { + return Math.min(Math.max(min, num), max); +} + +function hexDouble(num) { + var str = num.toString(16).toUpperCase(); + return (str.length < 2) ? "0" + str : str; +} + +//create a list of reverse color names +var reverseNames = {}; +for (var name in colorName$1) { + reverseNames[colorName$1[name]] = name; +} + +function keyword(rgb) { + return reverseNames[rgb.slice(0, 3)]; +} + +var Color = function (obj) { + if (obj instanceof Color) { + return obj; + } + if (!(this instanceof Color)) { + return new Color(obj); + } + + this.valid = false; + this.values = { + rgb: [0, 0, 0], + hsl: [0, 0, 0], + hsv: [0, 0, 0], + hwb: [0, 0, 0], + cmyk: [0, 0, 0, 0], + alpha: 1 + }; + + // parse Color() argument + var vals; + if (typeof obj === 'string') { + vals = colorString.getRgba(obj); + if (vals) { + this.setValues('rgb', vals); + } else if (vals = colorString.getHsla(obj)) { + this.setValues('hsl', vals); + } else if (vals = colorString.getHwb(obj)) { + this.setValues('hwb', vals); + } + } else if (typeof obj === 'object') { + vals = obj; + if (vals.r !== undefined || vals.red !== undefined) { + this.setValues('rgb', vals); + } else if (vals.l !== undefined || vals.lightness !== undefined) { + this.setValues('hsl', vals); + } else if (vals.v !== undefined || vals.value !== undefined) { + this.setValues('hsv', vals); + } else if (vals.w !== undefined || vals.whiteness !== undefined) { + this.setValues('hwb', vals); + } else if (vals.c !== undefined || vals.cyan !== undefined) { + this.setValues('cmyk', vals); + } + } +}; + +Color.prototype = { + isValid: function () { + return this.valid; + }, + rgb: function () { + return this.setSpace('rgb', arguments); + }, + hsl: function () { + return this.setSpace('hsl', arguments); + }, + hsv: function () { + return this.setSpace('hsv', arguments); + }, + hwb: function () { + return this.setSpace('hwb', arguments); + }, + cmyk: function () { + return this.setSpace('cmyk', arguments); + }, + + rgbArray: function () { + return this.values.rgb; + }, + hslArray: function () { + return this.values.hsl; + }, + hsvArray: function () { + return this.values.hsv; + }, + hwbArray: function () { + var values = this.values; + if (values.alpha !== 1) { + return values.hwb.concat([values.alpha]); + } + return values.hwb; + }, + cmykArray: function () { + return this.values.cmyk; + }, + rgbaArray: function () { + var values = this.values; + return values.rgb.concat([values.alpha]); + }, + hslaArray: function () { + var values = this.values; + return values.hsl.concat([values.alpha]); + }, + alpha: function (val) { + if (val === undefined) { + return this.values.alpha; + } + this.setValues('alpha', val); + return this; + }, + + red: function (val) { + return this.setChannel('rgb', 0, val); + }, + green: function (val) { + return this.setChannel('rgb', 1, val); + }, + blue: function (val) { + return this.setChannel('rgb', 2, val); + }, + hue: function (val) { + if (val) { + val %= 360; + val = val < 0 ? 360 + val : val; + } + return this.setChannel('hsl', 0, val); + }, + saturation: function (val) { + return this.setChannel('hsl', 1, val); + }, + lightness: function (val) { + return this.setChannel('hsl', 2, val); + }, + saturationv: function (val) { + return this.setChannel('hsv', 1, val); + }, + whiteness: function (val) { + return this.setChannel('hwb', 1, val); + }, + blackness: function (val) { + return this.setChannel('hwb', 2, val); + }, + value: function (val) { + return this.setChannel('hsv', 2, val); + }, + cyan: function (val) { + return this.setChannel('cmyk', 0, val); + }, + magenta: function (val) { + return this.setChannel('cmyk', 1, val); + }, + yellow: function (val) { + return this.setChannel('cmyk', 2, val); + }, + black: function (val) { + return this.setChannel('cmyk', 3, val); + }, + + hexString: function () { + return colorString.hexString(this.values.rgb); + }, + rgbString: function () { + return colorString.rgbString(this.values.rgb, this.values.alpha); + }, + rgbaString: function () { + return colorString.rgbaString(this.values.rgb, this.values.alpha); + }, + percentString: function () { + return colorString.percentString(this.values.rgb, this.values.alpha); + }, + hslString: function () { + return colorString.hslString(this.values.hsl, this.values.alpha); + }, + hslaString: function () { + return colorString.hslaString(this.values.hsl, this.values.alpha); + }, + hwbString: function () { + return colorString.hwbString(this.values.hwb, this.values.alpha); + }, + keyword: function () { + return colorString.keyword(this.values.rgb, this.values.alpha); + }, + + rgbNumber: function () { + var rgb = this.values.rgb; + return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; + }, + + luminosity: function () { + // http://www.w3.org/TR/WCAG20/#relativeluminancedef + var rgb = this.values.rgb; + var lum = []; + for (var i = 0; i < rgb.length; i++) { + var chan = rgb[i] / 255; + lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); + } + return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; + }, + + contrast: function (color2) { + // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + var lum1 = this.luminosity(); + var lum2 = color2.luminosity(); + if (lum1 > lum2) { + return (lum1 + 0.05) / (lum2 + 0.05); + } + return (lum2 + 0.05) / (lum1 + 0.05); + }, + + level: function (color2) { + var contrastRatio = this.contrast(color2); + if (contrastRatio >= 7.1) { + return 'AAA'; + } + + return (contrastRatio >= 4.5) ? 'AA' : ''; + }, + + dark: function () { + // YIQ equation from http://24ways.org/2010/calculating-color-contrast + var rgb = this.values.rgb; + var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; + return yiq < 128; + }, + + light: function () { + return !this.dark(); + }, + + negate: function () { + var rgb = []; + for (var i = 0; i < 3; i++) { + rgb[i] = 255 - this.values.rgb[i]; + } + this.setValues('rgb', rgb); + return this; + }, + + lighten: function (ratio) { + var hsl = this.values.hsl; + hsl[2] += hsl[2] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + darken: function (ratio) { + var hsl = this.values.hsl; + hsl[2] -= hsl[2] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + saturate: function (ratio) { + var hsl = this.values.hsl; + hsl[1] += hsl[1] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + desaturate: function (ratio) { + var hsl = this.values.hsl; + hsl[1] -= hsl[1] * ratio; + this.setValues('hsl', hsl); + return this; + }, + + whiten: function (ratio) { + var hwb = this.values.hwb; + hwb[1] += hwb[1] * ratio; + this.setValues('hwb', hwb); + return this; + }, + + blacken: function (ratio) { + var hwb = this.values.hwb; + hwb[2] += hwb[2] * ratio; + this.setValues('hwb', hwb); + return this; + }, + + greyscale: function () { + var rgb = this.values.rgb; + // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale + var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; + this.setValues('rgb', [val, val, val]); + return this; + }, + + clearer: function (ratio) { + var alpha = this.values.alpha; + this.setValues('alpha', alpha - (alpha * ratio)); + return this; + }, + + opaquer: function (ratio) { + var alpha = this.values.alpha; + this.setValues('alpha', alpha + (alpha * ratio)); + return this; + }, + + rotate: function (degrees) { + var hsl = this.values.hsl; + var hue = (hsl[0] + degrees) % 360; + hsl[0] = hue < 0 ? 360 + hue : hue; + this.setValues('hsl', hsl); + return this; + }, + + /** + * Ported from sass implementation in C + * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 + */ + mix: function (mixinColor, weight) { + var color1 = this; + var color2 = mixinColor; + var p = weight === undefined ? 0.5 : weight; + + var w = 2 * p - 1; + var a = color1.alpha() - color2.alpha(); + + var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + return this + .rgb( + w1 * color1.red() + w2 * color2.red(), + w1 * color1.green() + w2 * color2.green(), + w1 * color1.blue() + w2 * color2.blue() + ) + .alpha(color1.alpha() * p + color2.alpha() * (1 - p)); + }, + + toJSON: function () { + return this.rgb(); + }, + + clone: function () { + // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify, + // making the final build way to big to embed in Chart.js. So let's do it manually, + // assuming that values to clone are 1 dimension arrays containing only numbers, + // except 'alpha' which is a number. + var result = new Color(); + var source = this.values; + var target = result.values; + var value, type; + + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + value = source[prop]; + type = ({}).toString.call(value); + if (type === '[object Array]') { + target[prop] = value.slice(0); + } else if (type === '[object Number]') { + target[prop] = value; + } else { + console.error('unexpected color value:', value); + } + } + } + + return result; + } +}; + +Color.prototype.spaces = { + rgb: ['red', 'green', 'blue'], + hsl: ['hue', 'saturation', 'lightness'], + hsv: ['hue', 'saturation', 'value'], + hwb: ['hue', 'whiteness', 'blackness'], + cmyk: ['cyan', 'magenta', 'yellow', 'black'] +}; + +Color.prototype.maxes = { + rgb: [255, 255, 255], + hsl: [360, 100, 100], + hsv: [360, 100, 100], + hwb: [360, 100, 100], + cmyk: [100, 100, 100, 100] +}; + +Color.prototype.getValues = function (space) { + var values = this.values; + var vals = {}; + + for (var i = 0; i < space.length; i++) { + vals[space.charAt(i)] = values[space][i]; + } + + if (values.alpha !== 1) { + vals.a = values.alpha; + } + + // {r: 255, g: 255, b: 255, a: 0.4} + return vals; +}; + +Color.prototype.setValues = function (space, vals) { + var values = this.values; + var spaces = this.spaces; + var maxes = this.maxes; + var alpha = 1; + var i; + + this.valid = true; + + if (space === 'alpha') { + alpha = vals; + } else if (vals.length) { + // [10, 10, 10] + values[space] = vals.slice(0, space.length); + alpha = vals[space.length]; + } else if (vals[space.charAt(0)] !== undefined) { + // {r: 10, g: 10, b: 10} + for (i = 0; i < space.length; i++) { + values[space][i] = vals[space.charAt(i)]; + } + + alpha = vals.a; + } else if (vals[spaces[space][0]] !== undefined) { + // {red: 10, green: 10, blue: 10} + var chans = spaces[space]; + + for (i = 0; i < space.length; i++) { + values[space][i] = vals[chans[i]]; + } + + alpha = vals.alpha; + } + + values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha))); + + if (space === 'alpha') { + return false; + } + + var capped; + + // cap values of the space prior converting all values + for (i = 0; i < space.length; i++) { + capped = Math.max(0, Math.min(maxes[space][i], values[space][i])); + values[space][i] = Math.round(capped); + } + + // convert to all the other color spaces + for (var sname in spaces) { + if (sname !== space) { + values[sname] = colorConvert[space][sname](values[space]); + } + } + + return true; +}; + +Color.prototype.setSpace = function (space, args) { + var vals = args[0]; + + if (vals === undefined) { + // color.rgb() + return this.getValues(space); + } + + // color.rgb(10, 10, 10) + if (typeof vals === 'number') { + vals = Array.prototype.slice.call(args); + } + + this.setValues(space, vals); + return this; +}; + +Color.prototype.setChannel = function (space, index, val) { + var svalues = this.values[space]; + if (val === undefined) { + // color.red() + return svalues[index]; + } else if (val === svalues[index]) { + // color.red(color.red()) + return this; + } + + // color.red(100) + svalues[index] = val; + this.setValues(space, svalues); + + return this; +}; + +if (typeof window !== 'undefined') { +// window.Color = Color; +} + +var chartjsColor = Color; + +/** + * @namespace Chart.helpers + */ +var helpers = { + /** + * An empty function that can be used, for example, for optional callback. + */ + noop: function() {}, + + /** + * Returns a unique id, sequentially generated from a global variable. + * @returns {number} + * @function + */ + uid: (function() { + var id = 0; + return function() { + return id++; + }; + }()), + + /** + * Returns true if `value` is neither null nor undefined, else returns false. + * @param {*} value - The value to test. + * @returns {boolean} + * @since 2.7.0 + */ + isNullOrUndef: function(value) { + return value === null || typeof value === 'undefined'; + }, + + /** + * Returns true if `value` is an array (including typed arrays), else returns false. + * @param {*} value - The value to test. + * @returns {boolean} + * @function + */ + isArray: function(value) { + if (Array.isArray && Array.isArray(value)) { + return true; + } + var type = Object.prototype.toString.call(value); + if (type.substr(0, 7) === '[object' && type.substr(-6) === 'Array]') { + return true; + } + return false; + }, + + /** + * Returns true if `value` is an object (excluding null), else returns false. + * @param {*} value - The value to test. + * @returns {boolean} + * @since 2.7.0 + */ + isObject: function(value) { + return value !== null && Object.prototype.toString.call(value) === '[object Object]'; + }, + + /** + * Returns true if `value` is a finite number, else returns false + * @param {*} value - The value to test. + * @returns {boolean} + */ + isFinite: function(value) { + return (typeof value === 'number' || value instanceof Number) && isFinite(value); + }, + + /** + * Returns `value` if defined, else returns `defaultValue`. + * @param {*} value - The value to return if defined. + * @param {*} defaultValue - The value to return if `value` is undefined. + * @returns {*} + */ + valueOrDefault: function(value, defaultValue) { + return typeof value === 'undefined' ? defaultValue : value; + }, + + /** + * Returns value at the given `index` in array if defined, else returns `defaultValue`. + * @param {Array} value - The array to lookup for value at `index`. + * @param {number} index - The index in `value` to lookup for value. + * @param {*} defaultValue - The value to return if `value[index]` is undefined. + * @returns {*} + */ + valueAtIndexOrDefault: function(value, index, defaultValue) { + return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue); + }, + + /** + * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the + * value returned by `fn`. If `fn` is not a function, this method returns undefined. + * @param {function} fn - The function to call. + * @param {Array|undefined|null} args - The arguments with which `fn` should be called. + * @param {object} [thisArg] - The value of `this` provided for the call to `fn`. + * @returns {*} + */ + callback: function(fn, args, thisArg) { + if (fn && typeof fn.call === 'function') { + return fn.apply(thisArg, args); + } + }, + + /** + * Note(SB) for performance sake, this method should only be used when loopable type + * is unknown or in none intensive code (not called often and small loopable). Else + * it's preferable to use a regular for() loop and save extra function calls. + * @param {object|Array} loopable - The object or array to be iterated. + * @param {function} fn - The function to call for each item. + * @param {object} [thisArg] - The value of `this` provided for the call to `fn`. + * @param {boolean} [reverse] - If true, iterates backward on the loopable. + */ + each: function(loopable, fn, thisArg, reverse) { + var i, len, keys; + if (helpers.isArray(loopable)) { + len = loopable.length; + if (reverse) { + for (i = len - 1; i >= 0; i--) { + fn.call(thisArg, loopable[i], i); + } + } else { + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[i], i); + } + } + } else if (helpers.isObject(loopable)) { + keys = Object.keys(loopable); + len = keys.length; + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[keys[i]], keys[i]); + } + } + }, + + /** + * Returns true if the `a0` and `a1` arrays have the same content, else returns false. + * @see https://stackoverflow.com/a/14853974 + * @param {Array} a0 - The array to compare + * @param {Array} a1 - The array to compare + * @returns {boolean} + */ + arrayEquals: function(a0, a1) { + var i, ilen, v0, v1; + + if (!a0 || !a1 || a0.length !== a1.length) { + return false; + } + + for (i = 0, ilen = a0.length; i < ilen; ++i) { + v0 = a0[i]; + v1 = a1[i]; + + if (v0 instanceof Array && v1 instanceof Array) { + if (!helpers.arrayEquals(v0, v1)) { + return false; + } + } else if (v0 !== v1) { + // NOTE: two different object instances will never be equal: {x:20} != {x:20} + return false; + } + } + + return true; + }, + + /** + * Returns a deep copy of `source` without keeping references on objects and arrays. + * @param {*} source - The value to clone. + * @returns {*} + */ + clone: function(source) { + if (helpers.isArray(source)) { + return source.map(helpers.clone); + } + + if (helpers.isObject(source)) { + var target = {}; + var keys = Object.keys(source); + var klen = keys.length; + var k = 0; + + for (; k < klen; ++k) { + target[keys[k]] = helpers.clone(source[keys[k]]); + } + + return target; + } + + return source; + }, + + /** + * The default merger when Chart.helpers.merge is called without merger option. + * Note(SB): also used by mergeConfig and mergeScaleConfig as fallback. + * @private + */ + _merger: function(key, target, source, options) { + var tval = target[key]; + var sval = source[key]; + + if (helpers.isObject(tval) && helpers.isObject(sval)) { + helpers.merge(tval, sval, options); + } else { + target[key] = helpers.clone(sval); + } + }, + + /** + * Merges source[key] in target[key] only if target[key] is undefined. + * @private + */ + _mergerIf: function(key, target, source) { + var tval = target[key]; + var sval = source[key]; + + if (helpers.isObject(tval) && helpers.isObject(sval)) { + helpers.mergeIf(tval, sval); + } else if (!target.hasOwnProperty(key)) { + target[key] = helpers.clone(sval); + } + }, + + /** + * Recursively deep copies `source` properties into `target` with the given `options`. + * IMPORTANT: `target` is not cloned and will be updated with `source` properties. + * @param {object} target - The target object in which all sources are merged into. + * @param {object|object[]} source - Object(s) to merge into `target`. + * @param {object} [options] - Merging options: + * @param {function} [options.merger] - The merge method (key, target, source, options) + * @returns {object} The `target` object. + */ + merge: function(target, source, options) { + var sources = helpers.isArray(source) ? source : [source]; + var ilen = sources.length; + var merge, i, keys, klen, k; + + if (!helpers.isObject(target)) { + return target; + } + + options = options || {}; + merge = options.merger || helpers._merger; + + for (i = 0; i < ilen; ++i) { + source = sources[i]; + if (!helpers.isObject(source)) { + continue; + } + + keys = Object.keys(source); + for (k = 0, klen = keys.length; k < klen; ++k) { + merge(keys[k], target, source, options); + } + } + + return target; + }, + + /** + * Recursively deep copies `source` properties into `target` *only* if not defined in target. + * IMPORTANT: `target` is not cloned and will be updated with `source` properties. + * @param {object} target - The target object in which all sources are merged into. + * @param {object|object[]} source - Object(s) to merge into `target`. + * @returns {object} The `target` object. + */ + mergeIf: function(target, source) { + return helpers.merge(target, source, {merger: helpers._mergerIf}); + }, + + /** + * Applies the contents of two or more objects together into the first object. + * @param {object} target - The target object in which all objects are merged into. + * @param {object} arg1 - Object containing additional properties to merge in target. + * @param {object} argN - Additional objects containing properties to merge in target. + * @returns {object} The `target` object. + */ + extend: Object.assign || function(target) { + return helpers.merge(target, [].slice.call(arguments, 1), { + merger: function(key, dst, src) { + dst[key] = src[key]; + } + }); + }, + + /** + * Basic javascript inheritance based on the model created in Backbone.js + */ + inherits: function(extensions) { + var me = this; + var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() { + return me.apply(this, arguments); + }; + + var Surrogate = function() { + this.constructor = ChartElement; + }; + + Surrogate.prototype = me.prototype; + ChartElement.prototype = new Surrogate(); + ChartElement.extend = helpers.inherits; + + if (extensions) { + helpers.extend(ChartElement.prototype, extensions); + } + + ChartElement.__super__ = me.prototype; + return ChartElement; + }, + + _deprecated: function(scope, value, previous, current) { + if (value !== undefined) { + console.warn(scope + ': "' + previous + + '" is deprecated. Please use "' + current + '" instead'); + } + } +}; + +var helpers_core = helpers; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.callback instead. + * @function Chart.helpers.callCallback + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ +helpers.callCallback = helpers.callback; + +/** + * Provided for backward compatibility, use Array.prototype.indexOf instead. + * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+ + * @function Chart.helpers.indexOf + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.indexOf = function(array, item, fromIndex) { + return Array.prototype.indexOf.call(array, item, fromIndex); +}; + +/** + * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead. + * @function Chart.helpers.getValueOrDefault + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.getValueOrDefault = helpers.valueOrDefault; + +/** + * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead. + * @function Chart.helpers.getValueAtIndexOrDefault + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault; + +/** + * Easing functions adapted from Robert Penner's easing equations. + * @namespace Chart.helpers.easingEffects + * @see http://www.robertpenner.com/easing/ + */ +var effects = { + linear: function(t) { + return t; + }, + + easeInQuad: function(t) { + return t * t; + }, + + easeOutQuad: function(t) { + return -t * (t - 2); + }, + + easeInOutQuad: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t; + } + return -0.5 * ((--t) * (t - 2) - 1); + }, + + easeInCubic: function(t) { + return t * t * t; + }, + + easeOutCubic: function(t) { + return (t = t - 1) * t * t + 1; + }, + + easeInOutCubic: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t; + } + return 0.5 * ((t -= 2) * t * t + 2); + }, + + easeInQuart: function(t) { + return t * t * t * t; + }, + + easeOutQuart: function(t) { + return -((t = t - 1) * t * t * t - 1); + }, + + easeInOutQuart: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t * t; + } + return -0.5 * ((t -= 2) * t * t * t - 2); + }, + + easeInQuint: function(t) { + return t * t * t * t * t; + }, + + easeOutQuint: function(t) { + return (t = t - 1) * t * t * t * t + 1; + }, + + easeInOutQuint: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t * t * t; + } + return 0.5 * ((t -= 2) * t * t * t * t + 2); + }, + + easeInSine: function(t) { + return -Math.cos(t * (Math.PI / 2)) + 1; + }, + + easeOutSine: function(t) { + return Math.sin(t * (Math.PI / 2)); + }, + + easeInOutSine: function(t) { + return -0.5 * (Math.cos(Math.PI * t) - 1); + }, + + easeInExpo: function(t) { + return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1)); + }, + + easeOutExpo: function(t) { + return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1; + }, + + easeInOutExpo: function(t) { + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if ((t /= 0.5) < 1) { + return 0.5 * Math.pow(2, 10 * (t - 1)); + } + return 0.5 * (-Math.pow(2, -10 * --t) + 2); + }, + + easeInCirc: function(t) { + if (t >= 1) { + return t; + } + return -(Math.sqrt(1 - t * t) - 1); + }, + + easeOutCirc: function(t) { + return Math.sqrt(1 - (t = t - 1) * t); + }, + + easeInOutCirc: function(t) { + if ((t /= 0.5) < 1) { + return -0.5 * (Math.sqrt(1 - t * t) - 1); + } + return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1); + }, + + easeInElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if (!p) { + p = 0.3; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); + }, + + easeOutElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if (!p) { + p = 0.3; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1; + }, + + easeInOutElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if ((t /= 0.5) === 2) { + return 1; + } + if (!p) { + p = 0.45; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + if (t < 1) { + return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); + } + return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1; + }, + easeInBack: function(t) { + var s = 1.70158; + return t * t * ((s + 1) * t - s); + }, + + easeOutBack: function(t) { + var s = 1.70158; + return (t = t - 1) * t * ((s + 1) * t + s) + 1; + }, + + easeInOutBack: function(t) { + var s = 1.70158; + if ((t /= 0.5) < 1) { + return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s)); + } + return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); + }, + + easeInBounce: function(t) { + return 1 - effects.easeOutBounce(1 - t); + }, + + easeOutBounce: function(t) { + if (t < (1 / 2.75)) { + return 7.5625 * t * t; + } + if (t < (2 / 2.75)) { + return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75; + } + if (t < (2.5 / 2.75)) { + return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375; + } + return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375; + }, + + easeInOutBounce: function(t) { + if (t < 0.5) { + return effects.easeInBounce(t * 2) * 0.5; + } + return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5; + } +}; + +var helpers_easing = { + effects: effects +}; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.easing.effects instead. + * @function Chart.helpers.easingEffects + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers_core.easingEffects = effects; + +var PI = Math.PI; +var RAD_PER_DEG = PI / 180; +var DOUBLE_PI = PI * 2; +var HALF_PI = PI / 2; +var QUARTER_PI = PI / 4; +var TWO_THIRDS_PI = PI * 2 / 3; + +/** + * @namespace Chart.helpers.canvas + */ +var exports$1 = { + /** + * Clears the entire canvas associated to the given `chart`. + * @param {Chart} chart - The chart for which to clear the canvas. + */ + clear: function(chart) { + chart.ctx.clearRect(0, 0, chart.width, chart.height); + }, + + /** + * Creates a "path" for a rectangle with rounded corners at position (x, y) with a + * given size (width, height) and the same `radius` for all corners. + * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context. + * @param {number} x - The x axis of the coordinate for the rectangle starting point. + * @param {number} y - The y axis of the coordinate for the rectangle starting point. + * @param {number} width - The rectangle's width. + * @param {number} height - The rectangle's height. + * @param {number} radius - The rounded amount (in pixels) for the four corners. + * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object? + */ + roundedRect: function(ctx, x, y, width, height, radius) { + if (radius) { + var r = Math.min(radius, height / 2, width / 2); + var left = x + r; + var top = y + r; + var right = x + width - r; + var bottom = y + height - r; + + ctx.moveTo(x, top); + if (left < right && top < bottom) { + ctx.arc(left, top, r, -PI, -HALF_PI); + ctx.arc(right, top, r, -HALF_PI, 0); + ctx.arc(right, bottom, r, 0, HALF_PI); + ctx.arc(left, bottom, r, HALF_PI, PI); + } else if (left < right) { + ctx.moveTo(left, y); + ctx.arc(right, top, r, -HALF_PI, HALF_PI); + ctx.arc(left, top, r, HALF_PI, PI + HALF_PI); + } else if (top < bottom) { + ctx.arc(left, top, r, -PI, 0); + ctx.arc(left, bottom, r, 0, PI); + } else { + ctx.arc(left, top, r, -PI, PI); + } + ctx.closePath(); + ctx.moveTo(x, y); + } else { + ctx.rect(x, y, width, height); + } + }, + + drawPoint: function(ctx, style, radius, x, y, rotation) { + var type, xOffset, yOffset, size, cornerRadius; + var rad = (rotation || 0) * RAD_PER_DEG; + + if (style && typeof style === 'object') { + type = style.toString(); + if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { + ctx.save(); + ctx.translate(x, y); + ctx.rotate(rad); + ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height); + ctx.restore(); + return; + } + } + + if (isNaN(radius) || radius <= 0) { + return; + } + + ctx.beginPath(); + + switch (style) { + // Default includes circle + default: + ctx.arc(x, y, radius, 0, DOUBLE_PI); + ctx.closePath(); + break; + case 'triangle': + ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); + rad += TWO_THIRDS_PI; + ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); + rad += TWO_THIRDS_PI; + ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius); + ctx.closePath(); + break; + case 'rectRounded': + // NOTE: the rounded rect implementation changed to use `arc` instead of + // `quadraticCurveTo` since it generates better results when rect is + // almost a circle. 0.516 (instead of 0.5) produces results with visually + // closer proportion to the previous impl and it is inscribed in the + // circle with `radius`. For more details, see the following PRs: + // https://github.com/chartjs/Chart.js/issues/5597 + // https://github.com/chartjs/Chart.js/issues/5858 + cornerRadius = radius * 0.516; + size = radius - cornerRadius; + xOffset = Math.cos(rad + QUARTER_PI) * size; + yOffset = Math.sin(rad + QUARTER_PI) * size; + ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI); + ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad); + ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI); + ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI); + ctx.closePath(); + break; + case 'rect': + if (!rotation) { + size = Math.SQRT1_2 * radius; + ctx.rect(x - size, y - size, 2 * size, 2 * size); + break; + } + rad += QUARTER_PI; + /* falls through */ + case 'rectRot': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + yOffset, y - xOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.lineTo(x - yOffset, y + xOffset); + ctx.closePath(); + break; + case 'crossRot': + rad += QUARTER_PI; + /* falls through */ + case 'cross': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x + yOffset, y - xOffset); + ctx.lineTo(x - yOffset, y + xOffset); + break; + case 'star': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x + yOffset, y - xOffset); + ctx.lineTo(x - yOffset, y + xOffset); + rad += QUARTER_PI; + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x + yOffset, y - xOffset); + ctx.lineTo(x - yOffset, y + xOffset); + break; + case 'line': + xOffset = Math.cos(rad) * radius; + yOffset = Math.sin(rad) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + break; + case 'dash': + ctx.moveTo(x, y); + ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius); + break; + } + + ctx.fill(); + ctx.stroke(); + }, + + /** + * Returns true if the point is inside the rectangle + * @param {object} point - The point to test + * @param {object} area - The rectangle + * @returns {boolean} + * @private + */ + _isPointInArea: function(point, area) { + var epsilon = 1e-6; // 1e-6 is margin in pixels for accumulated error. + + return point.x > area.left - epsilon && point.x < area.right + epsilon && + point.y > area.top - epsilon && point.y < area.bottom + epsilon; + }, + + clipArea: function(ctx, area) { + ctx.save(); + ctx.beginPath(); + ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top); + ctx.clip(); + }, + + unclipArea: function(ctx) { + ctx.restore(); + }, + + lineTo: function(ctx, previous, target, flip) { + var stepped = target.steppedLine; + if (stepped) { + if (stepped === 'middle') { + var midpoint = (previous.x + target.x) / 2.0; + ctx.lineTo(midpoint, flip ? target.y : previous.y); + ctx.lineTo(midpoint, flip ? previous.y : target.y); + } else if ((stepped === 'after' && !flip) || (stepped !== 'after' && flip)) { + ctx.lineTo(previous.x, target.y); + } else { + ctx.lineTo(target.x, previous.y); + } + ctx.lineTo(target.x, target.y); + return; + } + + if (!target.tension) { + ctx.lineTo(target.x, target.y); + return; + } + + ctx.bezierCurveTo( + flip ? previous.controlPointPreviousX : previous.controlPointNextX, + flip ? previous.controlPointPreviousY : previous.controlPointNextY, + flip ? target.controlPointNextX : target.controlPointPreviousX, + flip ? target.controlPointNextY : target.controlPointPreviousY, + target.x, + target.y); + } +}; + +var helpers_canvas = exports$1; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.canvas.clear instead. + * @namespace Chart.helpers.clear + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers_core.clear = exports$1.clear; + +/** + * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead. + * @namespace Chart.helpers.drawRoundedRectangle + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers_core.drawRoundedRectangle = function(ctx) { + ctx.beginPath(); + exports$1.roundedRect.apply(exports$1, arguments); +}; + +var defaults = { + /** + * @private + */ + _set: function(scope, values) { + return helpers_core.merge(this[scope] || (this[scope] = {}), values); + } +}; + +// TODO(v3): remove 'global' from namespace. all default are global and +// there's inconsistency around which options are under 'global' +defaults._set('global', { + defaultColor: 'rgba(0,0,0,0.1)', + defaultFontColor: '#666', + defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + defaultFontSize: 12, + defaultFontStyle: 'normal', + defaultLineHeight: 1.2, + showLines: true +}); + +var core_defaults = defaults; + +var valueOrDefault = helpers_core.valueOrDefault; + +/** + * Converts the given font object into a CSS font string. + * @param {object} font - A font object. + * @return {string} The CSS font string. See https://developer.mozilla.org/en-US/docs/Web/CSS/font + * @private + */ +function toFontString(font) { + if (!font || helpers_core.isNullOrUndef(font.size) || helpers_core.isNullOrUndef(font.family)) { + return null; + } + + return (font.style ? font.style + ' ' : '') + + (font.weight ? font.weight + ' ' : '') + + font.size + 'px ' + + font.family; +} + +/** + * @alias Chart.helpers.options + * @namespace + */ +var helpers_options = { + /** + * Converts the given line height `value` in pixels for a specific font `size`. + * @param {number|string} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em'). + * @param {number} size - The font size (in pixels) used to resolve relative `value`. + * @returns {number} The effective line height in pixels (size * 1.2 if value is invalid). + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height + * @since 2.7.0 + */ + toLineHeight: function(value, size) { + var matches = ('' + value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/); + if (!matches || matches[1] === 'normal') { + return size * 1.2; + } + + value = +matches[2]; + + switch (matches[3]) { + case 'px': + return value; + case '%': + value /= 100; + break; + } + + return size * value; + }, + + /** + * Converts the given value into a padding object with pre-computed width/height. + * @param {number|object} value - If a number, set the value to all TRBL component, + * else, if and object, use defined properties and sets undefined ones to 0. + * @returns {object} The padding values (top, right, bottom, left, width, height) + * @since 2.7.0 + */ + toPadding: function(value) { + var t, r, b, l; + + if (helpers_core.isObject(value)) { + t = +value.top || 0; + r = +value.right || 0; + b = +value.bottom || 0; + l = +value.left || 0; + } else { + t = r = b = l = +value || 0; + } + + return { + top: t, + right: r, + bottom: b, + left: l, + height: t + b, + width: l + r + }; + }, + + /** + * Parses font options and returns the font object. + * @param {object} options - A object that contains font options to be parsed. + * @return {object} The font object. + * @todo Support font.* options and renamed to toFont(). + * @private + */ + _parseFont: function(options) { + var globalDefaults = core_defaults.global; + var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize); + var font = { + family: valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily), + lineHeight: helpers_core.options.toLineHeight(valueOrDefault(options.lineHeight, globalDefaults.defaultLineHeight), size), + size: size, + style: valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle), + weight: null, + string: '' + }; + + font.string = toFontString(font); + return font; + }, + + /** + * Evaluates the given `inputs` sequentially and returns the first defined value. + * @param {Array} inputs - An array of values, falling back to the last value. + * @param {object} [context] - If defined and the current value is a function, the value + * is called with `context` as first argument and the result becomes the new input. + * @param {number} [index] - If defined and the current value is an array, the value + * at `index` become the new input. + * @param {object} [info] - object to return information about resolution in + * @param {boolean} [info.cacheable] - Will be set to `false` if option is not cacheable. + * @since 2.7.0 + */ + resolve: function(inputs, context, index, info) { + var cacheable = true; + var i, ilen, value; + + for (i = 0, ilen = inputs.length; i < ilen; ++i) { + value = inputs[i]; + if (value === undefined) { + continue; + } + if (context !== undefined && typeof value === 'function') { + value = value(context); + cacheable = false; + } + if (index !== undefined && helpers_core.isArray(value)) { + value = value[index]; + cacheable = false; + } + if (value !== undefined) { + if (info && !cacheable) { + info.cacheable = false; + } + return value; + } + } + } +}; + +/** + * @alias Chart.helpers.math + * @namespace + */ +var exports$2 = { + /** + * Returns an array of factors sorted from 1 to sqrt(value) + * @private + */ + _factorize: function(value) { + var result = []; + var sqrt = Math.sqrt(value); + var i; + + for (i = 1; i < sqrt; i++) { + if (value % i === 0) { + result.push(i); + result.push(value / i); + } + } + if (sqrt === (sqrt | 0)) { // if value is a square number + result.push(sqrt); + } + + result.sort(function(a, b) { + return a - b; + }).pop(); + return result; + }, + + log10: Math.log10 || function(x) { + var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10. + // Check for whole powers of 10, + // which due to floating point rounding error should be corrected. + var powerOf10 = Math.round(exponent); + var isPowerOf10 = x === Math.pow(10, powerOf10); + + return isPowerOf10 ? powerOf10 : exponent; + } +}; + +var helpers_math = exports$2; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.math.log10 instead. + * @namespace Chart.helpers.log10 + * @deprecated since version 2.9.0 + * @todo remove at version 3 + * @private + */ +helpers_core.log10 = exports$2.log10; + +var getRtlAdapter = function(rectX, width) { + return { + x: function(x) { + return rectX + rectX + width - x; + }, + setWidth: function(w) { + width = w; + }, + textAlign: function(align) { + if (align === 'center') { + return align; + } + return align === 'right' ? 'left' : 'right'; + }, + xPlus: function(x, value) { + return x - value; + }, + leftForLtr: function(x, itemWidth) { + return x - itemWidth; + }, + }; +}; + +var getLtrAdapter = function() { + return { + x: function(x) { + return x; + }, + setWidth: function(w) { // eslint-disable-line no-unused-vars + }, + textAlign: function(align) { + return align; + }, + xPlus: function(x, value) { + return x + value; + }, + leftForLtr: function(x, _itemWidth) { // eslint-disable-line no-unused-vars + return x; + }, + }; +}; + +var getAdapter = function(rtl, rectX, width) { + return rtl ? getRtlAdapter(rectX, width) : getLtrAdapter(); +}; + +var overrideTextDirection = function(ctx, direction) { + var style, original; + if (direction === 'ltr' || direction === 'rtl') { + style = ctx.canvas.style; + original = [ + style.getPropertyValue('direction'), + style.getPropertyPriority('direction'), + ]; + + style.setProperty('direction', direction, 'important'); + ctx.prevTextDirection = original; + } +}; + +var restoreTextDirection = function(ctx) { + var original = ctx.prevTextDirection; + if (original !== undefined) { + delete ctx.prevTextDirection; + ctx.canvas.style.setProperty('direction', original[0], original[1]); + } +}; + +var helpers_rtl = { + getRtlAdapter: getAdapter, + overrideTextDirection: overrideTextDirection, + restoreTextDirection: restoreTextDirection, +}; + +var helpers$1 = helpers_core; +var easing = helpers_easing; +var canvas = helpers_canvas; +var options = helpers_options; +var math = helpers_math; +var rtl = helpers_rtl; +helpers$1.easing = easing; +helpers$1.canvas = canvas; +helpers$1.options = options; +helpers$1.math = math; +helpers$1.rtl = rtl; + +function interpolate(start, view, model, ease) { + var keys = Object.keys(model); + var i, ilen, key, actual, origin, target, type, c0, c1; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + + target = model[key]; + + // if a value is added to the model after pivot() has been called, the view + // doesn't contain it, so let's initialize the view to the target value. + if (!view.hasOwnProperty(key)) { + view[key] = target; + } + + actual = view[key]; + + if (actual === target || key[0] === '_') { + continue; + } + + if (!start.hasOwnProperty(key)) { + start[key] = actual; + } + + origin = start[key]; + + type = typeof target; + + if (type === typeof origin) { + if (type === 'string') { + c0 = chartjsColor(origin); + if (c0.valid) { + c1 = chartjsColor(target); + if (c1.valid) { + view[key] = c1.mix(c0, ease).rgbString(); + continue; + } + } + } else if (helpers$1.isFinite(origin) && helpers$1.isFinite(target)) { + view[key] = origin + (target - origin) * ease; + continue; + } + } + + view[key] = target; + } +} + +var Element = function(configuration) { + helpers$1.extend(this, configuration); + this.initialize.apply(this, arguments); +}; + +helpers$1.extend(Element.prototype, { + _type: undefined, + + initialize: function() { + this.hidden = false; + }, + + pivot: function() { + var me = this; + if (!me._view) { + me._view = helpers$1.extend({}, me._model); + } + me._start = {}; + return me; + }, + + transition: function(ease) { + var me = this; + var model = me._model; + var start = me._start; + var view = me._view; + + // No animation -> No Transition + if (!model || ease === 1) { + me._view = helpers$1.extend({}, model); + me._start = null; + return me; + } + + if (!view) { + view = me._view = {}; + } + + if (!start) { + start = me._start = {}; + } + + interpolate(start, view, model, ease); + + return me; + }, + + tooltipPosition: function() { + return { + x: this._model.x, + y: this._model.y + }; + }, + + hasValue: function() { + return helpers$1.isNumber(this._model.x) && helpers$1.isNumber(this._model.y); + } +}); + +Element.extend = helpers$1.inherits; + +var core_element = Element; + +var exports$3 = core_element.extend({ + chart: null, // the animation associated chart instance + currentStep: 0, // the current animation step + numSteps: 60, // default number of steps + easing: '', // the easing to use for this animation + render: null, // render function used by the animation service + + onAnimationProgress: null, // user specified callback to fire on each step of the animation + onAnimationComplete: null, // user specified callback to fire when the animation finishes +}); + +var core_animation = exports$3; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.Animation instead + * @prop Chart.Animation#animationObject + * @deprecated since version 2.6.0 + * @todo remove at version 3 + */ +Object.defineProperty(exports$3.prototype, 'animationObject', { + get: function() { + return this; + } +}); + +/** + * Provided for backward compatibility, use Chart.Animation#chart instead + * @prop Chart.Animation#chartInstance + * @deprecated since version 2.6.0 + * @todo remove at version 3 + */ +Object.defineProperty(exports$3.prototype, 'chartInstance', { + get: function() { + return this.chart; + }, + set: function(value) { + this.chart = value; + } +}); + +core_defaults._set('global', { + animation: { + duration: 1000, + easing: 'easeOutQuart', + onProgress: helpers$1.noop, + onComplete: helpers$1.noop + } +}); + +var core_animations = { + animations: [], + request: null, + + /** + * @param {Chart} chart - The chart to animate. + * @param {Chart.Animation} animation - The animation that we will animate. + * @param {number} duration - The animation duration in ms. + * @param {boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions + */ + addAnimation: function(chart, animation, duration, lazy) { + var animations = this.animations; + var i, ilen; + + animation.chart = chart; + animation.startTime = Date.now(); + animation.duration = duration; + + if (!lazy) { + chart.animating = true; + } + + for (i = 0, ilen = animations.length; i < ilen; ++i) { + if (animations[i].chart === chart) { + animations[i] = animation; + return; + } + } + + animations.push(animation); + + // If there are no animations queued, manually kickstart a digest, for lack of a better word + if (animations.length === 1) { + this.requestAnimationFrame(); + } + }, + + cancelAnimation: function(chart) { + var index = helpers$1.findIndex(this.animations, function(animation) { + return animation.chart === chart; + }); + + if (index !== -1) { + this.animations.splice(index, 1); + chart.animating = false; + } + }, + + requestAnimationFrame: function() { + var me = this; + if (me.request === null) { + return; + // TBD: animation should work somehow; what is startDigest? + + // Skip animation frame requests until the active one is executed. + // This can happen when processing mouse events, e.g. 'mousemove' + // and 'mouseout' events will trigger multiple renders. + me.request = helpers$1.requestAnimFrame.call(undefined, function() { + me.request = null; + me.startDigest(); + }); + } + }, + + /** + * @private + */ + startDigest: function() { + var me = this; + + me.advance(); + + // Do we have more stuff to animate? + if (me.animations.length > 0) { + me.requestAnimationFrame(); + } + }, + + /** + * @private + */ + advance: function() { + var animations = this.animations; + var animation, chart, numSteps, nextStep; + var i = 0; + + // 1 animation per chart, so we are looping charts here + while (i < animations.length) { + animation = animations[i]; + chart = animation.chart; + numSteps = animation.numSteps; + + // Make sure that currentStep starts at 1 + // https://github.com/chartjs/Chart.js/issues/6104 + nextStep = Math.floor((Date.now() - animation.startTime) / animation.duration * numSteps) + 1; + animation.currentStep = Math.min(nextStep, numSteps); + + helpers$1.callback(animation.render, [chart, animation], chart); + helpers$1.callback(animation.onAnimationProgress, [animation], chart); + + if (animation.currentStep >= numSteps) { + helpers$1.callback(animation.onAnimationComplete, [animation], chart); + chart.animating = false; + animations.splice(i, 1); + } else { + ++i; + } + } + } +}; + +var resolve = helpers$1.options.resolve; + +var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift']; + +/** + * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice', + * 'unshift') and notify the listener AFTER the array has been altered. Listeners are + * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments. + */ +function listenArrayEvents(array, listener) { + if (array._chartjs) { + array._chartjs.listeners.push(listener); + return; + } + + Object.defineProperty(array, '_chartjs', { + configurable: true, + enumerable: false, + value: { + listeners: [listener] + } + }); + + arrayEvents.forEach(function(key) { + var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1); + var base = array[key]; + + Object.defineProperty(array, key, { + configurable: true, + enumerable: false, + value: function() { + var args = Array.prototype.slice.call(arguments); + var res = base.apply(this, args); + + helpers$1.each(array._chartjs.listeners, function(object) { + if (typeof object[method] === 'function') { + object[method].apply(object, args); + } + }); + + return res; + } + }); + }); +} + +/** + * Removes the given array event listener and cleanup extra attached properties (such as + * the _chartjs stub and overridden methods) if array doesn't have any more listeners. + */ +function unlistenArrayEvents(array, listener) { + var stub = array._chartjs; + if (!stub) { + return; + } + + var listeners = stub.listeners; + var index = listeners.indexOf(listener); + if (index !== -1) { + listeners.splice(index, 1); + } + + if (listeners.length > 0) { + return; + } + + arrayEvents.forEach(function(key) { + delete array[key]; + }); + + delete array._chartjs; +} + +// Base class for all dataset controllers (line, bar, etc) +var DatasetController = function(chart, datasetIndex) { + this.initialize(chart, datasetIndex); +}; + +helpers$1.extend(DatasetController.prototype, { + + /** + * Element type used to generate a meta dataset (e.g. Chart.element.Line). + * @type {Chart.core.element} + */ + datasetElementType: null, + + /** + * Element type used to generate a meta data (e.g. Chart.element.Point). + * @type {Chart.core.element} + */ + dataElementType: null, + + /** + * Dataset element option keys to be resolved in _resolveDatasetElementOptions. + * A derived controller may override this to resolve controller-specific options. + * The keys defined here are for backward compatibility for legend styles. + * @private + */ + _datasetElementOptions: [ + 'backgroundColor', + 'borderCapStyle', + 'borderColor', + 'borderDash', + 'borderDashOffset', + 'borderJoinStyle', + 'borderWidth' + ], + + /** + * Data element option keys to be resolved in _resolveDataElementOptions. + * A derived controller may override this to resolve controller-specific options. + * The keys defined here are for backward compatibility for legend styles. + * @private + */ + _dataElementOptions: [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'pointStyle' + ], + + initialize: function(chart, datasetIndex) { + var me = this; + me.chart = chart; + me.index = datasetIndex; + me.linkScales(); + me.addElements(); + me._type = me.getMeta().type; + }, + + updateIndex: function(datasetIndex) { + this.index = datasetIndex; + }, + + linkScales: function() { + var me = this; + var meta = me.getMeta(); + var chart = me.chart; + var scales = chart.scales; + var dataset = me.getDataset(); + var scalesOpts = chart.options.scales; + + if (meta.xAxisID === null || !(meta.xAxisID in scales) || dataset.xAxisID) { + meta.xAxisID = dataset.xAxisID || scalesOpts.xAxes[0].id; + } + if (meta.yAxisID === null || !(meta.yAxisID in scales) || dataset.yAxisID) { + meta.yAxisID = dataset.yAxisID || scalesOpts.yAxes[0].id; + } + }, + + getDataset: function() { + return this.chart.data.datasets[this.index]; + }, + + getMeta: function() { + return this.chart.getDatasetMeta(this.index); + }, + + getScaleForId: function(scaleID) { + return this.chart.scales[scaleID]; + }, + + /** + * @private + */ + _getValueScaleId: function() { + return this.getMeta().yAxisID; + }, + + /** + * @private + */ + _getIndexScaleId: function() { + return this.getMeta().xAxisID; + }, + + /** + * @private + */ + _getValueScale: function() { + return this.getScaleForId(this._getValueScaleId()); + }, + + /** + * @private + */ + _getIndexScale: function() { + return this.getScaleForId(this._getIndexScaleId()); + }, + + reset: function() { + this._update(true); + }, + + /** + * @private + */ + destroy: function() { + if (this._data) { + unlistenArrayEvents(this._data, this); + } + }, + + createMetaDataset: function() { + var me = this; + var type = me.datasetElementType; + return type && new type({ + _chart: me.chart, + _datasetIndex: me.index + }); + }, + + createMetaData: function(index) { + var me = this; + var type = me.dataElementType; + return type && new type({ + _chart: me.chart, + _datasetIndex: me.index, + _index: index + }); + }, + + addElements: function() { + var me = this; + var meta = me.getMeta(); + var data = me.getDataset().data || []; + var metaData = meta.data; + var i, ilen; + + for (i = 0, ilen = data.length; i < ilen; ++i) { + metaData[i] = metaData[i] || me.createMetaData(i); + } + + meta.dataset = meta.dataset || me.createMetaDataset(); + }, + + addElementAndReset: function(index) { + var element = this.createMetaData(index); + this.getMeta().data.splice(index, 0, element); + this.updateElement(element, index, true); + }, + + buildOrUpdateElements: function() { + var me = this; + var dataset = me.getDataset(); + var data = dataset.data || (dataset.data = []); + + // In order to correctly handle data addition/deletion animation (an thus simulate + // real-time charts), we need to monitor these data modifications and synchronize + // the internal meta data accordingly. + if (me._data !== data) { + if (me._data) { + // This case happens when the user replaced the data array instance. + unlistenArrayEvents(me._data, me); + } + + if (data && Object.isExtensible(data)) { + listenArrayEvents(data, me); + } + me._data = data; + } + + // Re-sync meta data in case the user replaced the data array or if we missed + // any updates and so make sure that we handle number of datapoints changing. + me.resyncElements(); + }, + + /** + * Returns the merged user-supplied and default dataset-level options + * @private + */ + _configure: function() { + var me = this; + me._config = helpers$1.merge({}, [ + me.chart.options.datasets[me._type], + me.getDataset(), + ], { + merger: function(key, target, source) { + if (key !== '_meta' && key !== 'data') { + helpers$1._merger(key, target, source); + } + } + }); + }, + + _update: function(reset) { + var me = this; + me._configure(); + me._cachedDataOpts = null; + me.update(reset); + }, + + update: helpers$1.noop, + + transition: function(easingValue) { + var meta = this.getMeta(); + var elements = meta.data || []; + var ilen = elements.length; + var i = 0; + + for (; i < ilen; ++i) { + elements[i].transition(easingValue); + } + + if (meta.dataset) { + meta.dataset.transition(easingValue); + } + }, + + draw: function() { + var meta = this.getMeta(); + var elements = meta.data || []; + var ilen = elements.length; + var i = 0; + + if (meta.dataset) { + meta.dataset.draw(); + } + + for (; i < ilen; ++i) { + elements[i].draw(); + } + }, + + /** + * Returns a set of predefined style properties that should be used to represent the dataset + * or the data if the index is specified + * @param {number} index - data index + * @return {IStyleInterface} style object + */ + getStyle: function(index) { + var me = this; + var meta = me.getMeta(); + var dataset = meta.dataset; + var style; + + me._configure(); + if (dataset && index === undefined) { + style = me._resolveDatasetElementOptions(dataset || {}); + } else { + index = index || 0; + style = me._resolveDataElementOptions(meta.data[index] || {}, index); + } + + if (style.fill === false || style.fill === null) { + style.backgroundColor = style.borderColor; + } + + return style; + }, + + /** + * @private + */ + _resolveDatasetElementOptions: function(element, hover) { + var me = this; + var chart = me.chart; + var datasetOpts = me._config; + var custom = element.custom || {}; + var options = chart.options.elements[me.datasetElementType.prototype._type] || {}; + var elementOptions = me._datasetElementOptions; + var values = {}; + var i, ilen, key, readKey; + + // Scriptable options + var context = { + chart: chart, + dataset: me.getDataset(), + datasetIndex: me.index, + hover: hover + }; + + for (i = 0, ilen = elementOptions.length; i < ilen; ++i) { + key = elementOptions[i]; + readKey = hover ? 'hover' + key.charAt(0).toUpperCase() + key.slice(1) : key; + values[key] = resolve([ + custom[readKey], + datasetOpts[readKey], + options[readKey] + ], context); + } + + return values; + }, + + /** + * @private + */ + _resolveDataElementOptions: function(element, index) { + var me = this; + var custom = element && element.custom; + var cached = me._cachedDataOpts; + if (cached && !custom) { + return cached; + } + var chart = me.chart; + var datasetOpts = me._config; + var options = chart.options.elements[me.dataElementType.prototype._type] || {}; + var elementOptions = me._dataElementOptions; + var values = {}; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: me.getDataset(), + datasetIndex: me.index + }; + + // `resolve` sets cacheable to `false` if any option is indexed or scripted + var info = {cacheable: !custom}; + + var keys, i, ilen, key; + + custom = custom || {}; + + if (helpers$1.isArray(elementOptions)) { + for (i = 0, ilen = elementOptions.length; i < ilen; ++i) { + key = elementOptions[i]; + values[key] = resolve([ + custom[key], + datasetOpts[key], + options[key] + ], context, index, info); + } + } else { + keys = Object.keys(elementOptions); + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve([ + custom[key], + datasetOpts[elementOptions[key]], + datasetOpts[key], + options[key] + ], context, index, info); + } + } + + if (info.cacheable) { + me._cachedDataOpts = Object.freeze(values); + } + + return values; + }, + + removeHoverStyle: function(element) { + helpers$1.merge(element._model, element.$previousStyle || {}); + delete element.$previousStyle; + }, + + setHoverStyle: function(element) { + var dataset = this.chart.data.datasets[element._datasetIndex]; + var index = element._index; + var custom = element.custom || {}; + var model = element._model; + var getHoverColor = helpers$1.getHoverColor; + + element.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth + }; + + model.backgroundColor = resolve([custom.hoverBackgroundColor, dataset.hoverBackgroundColor, getHoverColor(model.backgroundColor)], undefined, index); + model.borderColor = resolve([custom.hoverBorderColor, dataset.hoverBorderColor, getHoverColor(model.borderColor)], undefined, index); + model.borderWidth = resolve([custom.hoverBorderWidth, dataset.hoverBorderWidth, model.borderWidth], undefined, index); + }, + + /** + * @private + */ + _removeDatasetHoverStyle: function() { + var element = this.getMeta().dataset; + + if (element) { + this.removeHoverStyle(element); + } + }, + + /** + * @private + */ + _setDatasetHoverStyle: function() { + var element = this.getMeta().dataset; + var prev = {}; + var i, ilen, key, keys, hoverOptions, model; + + if (!element) { + return; + } + + model = element._model; + hoverOptions = this._resolveDatasetElementOptions(element, true); + + keys = Object.keys(hoverOptions); + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + prev[key] = model[key]; + model[key] = hoverOptions[key]; + } + + element.$previousStyle = prev; + }, + + /** + * @private + */ + resyncElements: function() { + var me = this; + var meta = me.getMeta(); + var data = me.getDataset().data; + var numMeta = meta.data.length; + var numData = data.length; + + if (numData < numMeta) { + meta.data.splice(numData, numMeta - numData); + } else if (numData > numMeta) { + me.insertElements(numMeta, numData - numMeta); + } + }, + + /** + * @private + */ + insertElements: function(start, count) { + for (var i = 0; i < count; ++i) { + this.addElementAndReset(start + i); + } + }, + + /** + * @private + */ + onDataPush: function() { + var count = arguments.length; + this.insertElements(this.getDataset().data.length - count, count); + }, + + /** + * @private + */ + onDataPop: function() { + this.getMeta().data.pop(); + }, + + /** + * @private + */ + onDataShift: function() { + this.getMeta().data.shift(); + }, + + /** + * @private + */ + onDataSplice: function(start, count) { + this.getMeta().data.splice(start, count); + this.insertElements(start, arguments.length - 2); + }, + + /** + * @private + */ + onDataUnshift: function() { + this.insertElements(0, arguments.length); + } +}); + +DatasetController.extend = helpers$1.inherits; + +var core_datasetController = DatasetController; + +var TAU = Math.PI * 2; + +core_defaults._set('global', { + elements: { + arc: { + backgroundColor: core_defaults.global.defaultColor, + borderColor: '#fff', + borderWidth: 2, + borderAlign: 'center' + } + } +}); + +function clipArc(ctx, arc) { + var startAngle = arc.startAngle; + var endAngle = arc.endAngle; + var pixelMargin = arc.pixelMargin; + var angleMargin = pixelMargin / arc.outerRadius; + var x = arc.x; + var y = arc.y; + + // Draw an inner border by cliping the arc and drawing a double-width border + // Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders + ctx.beginPath(); + ctx.arc(x, y, arc.outerRadius, startAngle - angleMargin, endAngle + angleMargin); + if (arc.innerRadius > pixelMargin) { + angleMargin = pixelMargin / arc.innerRadius; + ctx.arc(x, y, arc.innerRadius - pixelMargin, endAngle + angleMargin, startAngle - angleMargin, true); + } else { + ctx.arc(x, y, pixelMargin, endAngle + Math.PI / 2, startAngle - Math.PI / 2); + } + ctx.closePath(); + ctx.clip(); +} + +function drawFullCircleBorders(ctx, vm, arc, inner) { + var endAngle = arc.endAngle; + var i; + + if (inner) { + arc.endAngle = arc.startAngle + TAU; + clipArc(ctx, arc); + arc.endAngle = endAngle; + if (arc.endAngle === arc.startAngle && arc.fullCircles) { + arc.endAngle += TAU; + arc.fullCircles--; + } + } + + ctx.beginPath(); + ctx.arc(arc.x, arc.y, arc.innerRadius, arc.startAngle + TAU, arc.startAngle, true); + for (i = 0; i < arc.fullCircles; ++i) { + ctx.stroke(); + } + + ctx.beginPath(); + ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.startAngle + TAU); + for (i = 0; i < arc.fullCircles; ++i) { + ctx.stroke(); + } +} + +function drawBorder(ctx, vm, arc) { + var inner = vm.borderAlign === 'inner'; + + if (inner) { + ctx.lineWidth = vm.borderWidth * 2; + ctx.lineJoin = 'round'; + } else { + ctx.lineWidth = vm.borderWidth; + ctx.lineJoin = 'bevel'; + } + + if (arc.fullCircles) { + drawFullCircleBorders(ctx, vm, arc, inner); + } + + if (inner) { + clipArc(ctx, arc); + } + + ctx.beginPath(); + ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.endAngle); + ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true); + ctx.closePath(); + ctx.stroke(); +} + +var element_arc = core_element.extend({ + _type: 'arc', + + inLabelRange: function(mouseX) { + var vm = this._view; + + if (vm) { + return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2)); + } + return false; + }, + + inRange: function(chartX, chartY) { + var vm = this._view; + + if (vm) { + var pointRelativePosition = helpers$1.getAngleFromPoint(vm, {x: chartX, y: chartY}); + var angle = pointRelativePosition.angle; + var distance = pointRelativePosition.distance; + + // Sanitise angle range + var startAngle = vm.startAngle; + var endAngle = vm.endAngle; + while (endAngle < startAngle) { + endAngle += TAU; + } + while (angle > endAngle) { + angle -= TAU; + } + while (angle < startAngle) { + angle += TAU; + } + + // Check if within the range of the open/close angle + var betweenAngles = (angle >= startAngle && angle <= endAngle); + var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius); + + return (betweenAngles && withinRadius); + } + return false; + }, + + getCenterPoint: function() { + var vm = this._view; + var halfAngle = (vm.startAngle + vm.endAngle) / 2; + var halfRadius = (vm.innerRadius + vm.outerRadius) / 2; + return { + x: vm.x + Math.cos(halfAngle) * halfRadius, + y: vm.y + Math.sin(halfAngle) * halfRadius + }; + }, + + getArea: function() { + var vm = this._view; + return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2)); + }, + + tooltipPosition: function() { + var vm = this._view; + var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2); + var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius; + + return { + x: vm.x + (Math.cos(centreAngle) * rangeFromCentre), + y: vm.y + (Math.sin(centreAngle) * rangeFromCentre) + }; + }, + + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; + var pixelMargin = (vm.borderAlign === 'inner') ? 0.33 : 0; + var arc = { + x: vm.x, + y: vm.y, + innerRadius: vm.innerRadius, + outerRadius: Math.max(vm.outerRadius - pixelMargin, 0), + pixelMargin: pixelMargin, + startAngle: vm.startAngle, + endAngle: vm.endAngle, + fullCircles: Math.floor(vm.circumference / TAU) + }; + var i; + + ctx.save(); + + ctx.fillStyle = vm.backgroundColor; + ctx.strokeStyle = vm.borderColor; + + if (arc.fullCircles) { + arc.endAngle = arc.startAngle + TAU; + ctx.beginPath(); + ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle); + ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true); + ctx.closePath(); + for (i = 0; i < arc.fullCircles; ++i) { + ctx.fill(); + } + arc.endAngle = arc.startAngle + vm.circumference % TAU; + } + + ctx.beginPath(); + ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle); + ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true); + ctx.closePath(); + ctx.fill(); + + if (vm.borderWidth) { + drawBorder(ctx, vm, arc); + } + + ctx.restore(); + } +}); + +var valueOrDefault$1 = helpers$1.valueOrDefault; + +var defaultColor = core_defaults.global.defaultColor; + +core_defaults._set('global', { + elements: { + line: { + tension: 0.4, + backgroundColor: defaultColor, + borderWidth: 3, + borderColor: defaultColor, + borderCapStyle: 'butt', + borderDash: [], + borderDashOffset: 0.0, + borderJoinStyle: 'miter', + capBezierPoints: true, + fill: true, // do we fill in the area between the line and its base axis + } + } +}); + +var element_line = core_element.extend({ + _type: 'line', + + draw: function() { + var me = this; + var vm = me._view; + var ctx = me._chart.ctx; + var spanGaps = vm.spanGaps; + var points = me._children.slice(); // clone array + var globalDefaults = core_defaults.global; + var globalOptionLineElements = globalDefaults.elements.line; + var lastDrawnIndex = -1; + var closePath = me._loop; + var index, previous, currentVM; + + if (!points.length) { + return; + } + + if (me._loop) { + for (index = 0; index < points.length; ++index) { + previous = helpers$1.previousItem(points, index); + // If the line has an open path, shift the point array + if (!points[index]._view.skip && previous._view.skip) { + points = points.slice(index).concat(points.slice(0, index)); + closePath = spanGaps; + break; + } + } + // If the line has a close path, add the first point again + if (closePath) { + points.push(points[0]); + } + } + + ctx.save(); + + // Stroke Line Options + ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle; + + // IE 9 and 10 do not support line dash + if (ctx.setLineDash) { + ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash); + } + + // line dash fix for QML + if(ctx.getLineDash && ctx.getLineDash().length === 0) { + ctx.setLineDash([99999]); + } + + ctx.lineDashOffset = valueOrDefault$1(vm.borderDashOffset, globalOptionLineElements.borderDashOffset); + ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle; + ctx.lineWidth = valueOrDefault$1(vm.borderWidth, globalOptionLineElements.borderWidth); + ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor; + + // Stroke Line + ctx.beginPath(); + + // First point moves to it's starting position no matter what + currentVM = points[0]._view; + if (!currentVM.skip) { + ctx.moveTo(currentVM.x, currentVM.y); + lastDrawnIndex = 0; + } + + for (index = 1; index < points.length; ++index) { + currentVM = points[index]._view; + previous = lastDrawnIndex === -1 ? helpers$1.previousItem(points, index) : points[lastDrawnIndex]; + + if (!currentVM.skip) { + if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) { + // There was a gap and this is the first point after the gap + ctx.moveTo(currentVM.x, currentVM.y); + } else { + // Line to next point + helpers$1.canvas.lineTo(ctx, previous._view, currentVM); + } + lastDrawnIndex = index; + } + } + + if (closePath) { + ctx.closePath(); + } + + ctx.stroke(); + ctx.restore(); + } +}); + +var valueOrDefault$2 = helpers$1.valueOrDefault; + +var defaultColor$1 = core_defaults.global.defaultColor; + +core_defaults._set('global', { + elements: { + point: { + radius: 3, + pointStyle: 'circle', + backgroundColor: defaultColor$1, + borderColor: defaultColor$1, + borderWidth: 1, + // Hover + hitRadius: 1, + hoverRadius: 4, + hoverBorderWidth: 1 + } + } +}); + +function xRange(mouseX) { + var vm = this._view; + return vm ? (Math.abs(mouseX - vm.x) < vm.radius + vm.hitRadius) : false; +} + +function yRange(mouseY) { + var vm = this._view; + return vm ? (Math.abs(mouseY - vm.y) < vm.radius + vm.hitRadius) : false; +} + +var element_point = core_element.extend({ + _type: 'point', + + inRange: function(mouseX, mouseY) { + var vm = this._view; + return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false; + }, + + inLabelRange: xRange, + inXRange: xRange, + inYRange: yRange, + + getCenterPoint: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y + }; + }, + + getArea: function() { + return Math.PI * Math.pow(this._view.radius, 2); + }, + + tooltipPosition: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y, + padding: vm.radius + vm.borderWidth + }; + }, + + draw: function(chartArea) { + var vm = this._view; + var ctx = this._chart.ctx; + var pointStyle = vm.pointStyle; + var rotation = vm.rotation; + var radius = vm.radius; + var x = vm.x; + var y = vm.y; + var globalDefaults = core_defaults.global; + var defaultColor = globalDefaults.defaultColor; // eslint-disable-line no-shadow + + if (vm.skip) { + return; + } + + // Clipping for Points. + if (chartArea === undefined || helpers$1.canvas._isPointInArea(vm, chartArea)) { + ctx.strokeStyle = vm.borderColor || defaultColor; + ctx.lineWidth = valueOrDefault$2(vm.borderWidth, globalDefaults.elements.point.borderWidth); + ctx.fillStyle = vm.backgroundColor || defaultColor; + helpers$1.canvas.drawPoint(ctx, pointStyle, radius, x, y, rotation); + } + } +}); + +var defaultColor$2 = core_defaults.global.defaultColor; + +core_defaults._set('global', { + elements: { + rectangle: { + backgroundColor: defaultColor$2, + borderColor: defaultColor$2, + borderSkipped: 'bottom', + borderWidth: 0 + } + } +}); + +function isVertical(vm) { + return vm && vm.width !== undefined; +} + +/** + * Helper function to get the bounds of the bar regardless of the orientation + * @param bar {Chart.Element.Rectangle} the bar + * @return {Bounds} bounds of the bar + * @private + */ +function getBarBounds(vm) { + var x1, x2, y1, y2, half; + + if (isVertical(vm)) { + half = vm.width / 2; + x1 = vm.x - half; + x2 = vm.x + half; + y1 = Math.min(vm.y, vm.base); + y2 = Math.max(vm.y, vm.base); + } else { + half = vm.height / 2; + x1 = Math.min(vm.x, vm.base); + x2 = Math.max(vm.x, vm.base); + y1 = vm.y - half; + y2 = vm.y + half; + } + + return { + left: x1, + top: y1, + right: x2, + bottom: y2 + }; +} + +function swap(orig, v1, v2) { + return orig === v1 ? v2 : orig === v2 ? v1 : orig; +} + +function parseBorderSkipped(vm) { + var edge = vm.borderSkipped; + var res = {}; + + if (!edge) { + return res; + } + + if (vm.horizontal) { + if (vm.base > vm.x) { + edge = swap(edge, 'left', 'right'); + } + } else if (vm.base < vm.y) { + edge = swap(edge, 'bottom', 'top'); + } + + res[edge] = true; + return res; +} + +function parseBorderWidth(vm, maxW, maxH) { + var value = vm.borderWidth; + var skip = parseBorderSkipped(vm); + var t, r, b, l; + + if (helpers$1.isObject(value)) { + t = +value.top || 0; + r = +value.right || 0; + b = +value.bottom || 0; + l = +value.left || 0; + } else { + t = r = b = l = +value || 0; + } + + return { + t: skip.top || (t < 0) ? 0 : t > maxH ? maxH : t, + r: skip.right || (r < 0) ? 0 : r > maxW ? maxW : r, + b: skip.bottom || (b < 0) ? 0 : b > maxH ? maxH : b, + l: skip.left || (l < 0) ? 0 : l > maxW ? maxW : l + }; +} + +function boundingRects(vm) { + var bounds = getBarBounds(vm); + var width = bounds.right - bounds.left; + var height = bounds.bottom - bounds.top; + var border = parseBorderWidth(vm, width / 2, height / 2); + + return { + outer: { + x: bounds.left, + y: bounds.top, + w: width, + h: height + }, + inner: { + x: bounds.left + border.l, + y: bounds.top + border.t, + w: width - border.l - border.r, + h: height - border.t - border.b + } + }; +} + +function inRange(vm, x, y) { + var skipX = x === null; + var skipY = y === null; + var bounds = !vm || (skipX && skipY) ? false : getBarBounds(vm); + + return bounds + && (skipX || x >= bounds.left && x <= bounds.right) + && (skipY || y >= bounds.top && y <= bounds.bottom); +} + +var element_rectangle = core_element.extend({ + _type: 'rectangle', + + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; + var rects = boundingRects(vm); + var outer = rects.outer; + var inner = rects.inner; + + ctx.save(); + + if (outer.w !== inner.w || outer.h !== inner.h) { + ctx.beginPath(); + ctx.strokeStyle = vm.borderColor; + ctx.strokeRect(inner.x, inner.y, inner.w, inner.h); + ctx.fill('evenodd'); + } + + ctx.fillStyle = vm.backgroundColor; + ctx.fillRect(inner.x, inner.y, inner.w, inner.h); + + ctx.restore(); + }, + + height: function() { + var vm = this._view; + return vm.base - vm.y; + }, + + inRange: function(mouseX, mouseY) { + return inRange(this._view, mouseX, mouseY); + }, + + inLabelRange: function(mouseX, mouseY) { + var vm = this._view; + return isVertical(vm) + ? inRange(vm, mouseX, null) + : inRange(vm, null, mouseY); + }, + + inXRange: function(mouseX) { + return inRange(this._view, mouseX, null); + }, + + inYRange: function(mouseY) { + return inRange(this._view, null, mouseY); + }, + + getCenterPoint: function() { + var vm = this._view; + var x, y; + if (isVertical(vm)) { + x = vm.x; + y = (vm.y + vm.base) / 2; + } else { + x = (vm.x + vm.base) / 2; + y = vm.y; + } + + return {x: x, y: y}; + }, + + getArea: function() { + var vm = this._view; + + return isVertical(vm) + ? vm.width * Math.abs(vm.y - vm.base) + : vm.height * Math.abs(vm.x - vm.base); + }, + + tooltipPosition: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y + }; + } +}); + +var elements = {}; +var Arc = element_arc; +var Line = element_line; +var Point = element_point; +var Rectangle = element_rectangle; +elements.Arc = Arc; +elements.Line = Line; +elements.Point = Point; +elements.Rectangle = Rectangle; + +var deprecated = helpers$1._deprecated; +var valueOrDefault$3 = helpers$1.valueOrDefault; + +core_defaults._set('bar', { + hover: { + mode: 'label' + }, + + scales: { + xAxes: [{ + type: 'category', + offset: true, + gridLines: { + offsetGridLines: true + } + }], + + yAxes: [{ + type: 'linear' + }] + } +}); + +core_defaults._set('global', { + datasets: { + bar: { + categoryPercentage: 0.8, + barPercentage: 0.9 + } + } +}); + +/** + * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap. + * @private + */ +function computeMinSampleSize(scale, pixels) { + var min = scale._length; + var prev, curr, i, ilen; + + for (i = 1, ilen = pixels.length; i < ilen; ++i) { + min = Math.min(min, Math.abs(pixels[i] - pixels[i - 1])); + } + + for (i = 0, ilen = scale.getTicks().length; i < ilen; ++i) { + curr = scale.getPixelForTick(i); + min = i > 0 ? Math.min(min, Math.abs(curr - prev)) : min; + prev = curr; + } + + return min; +} + +/** + * Computes an "ideal" category based on the absolute bar thickness or, if undefined or null, + * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This + * mode currently always generates bars equally sized (until we introduce scriptable options?). + * @private + */ +function computeFitCategoryTraits(index, ruler, options) { + var thickness = options.barThickness; + var count = ruler.stackCount; + var curr = ruler.pixels[index]; + var min = helpers$1.isNullOrUndef(thickness) + ? computeMinSampleSize(ruler.scale, ruler.pixels) + : -1; + var size, ratio; + + if (helpers$1.isNullOrUndef(thickness)) { + size = min * options.categoryPercentage; + ratio = options.barPercentage; + } else { + // When bar thickness is enforced, category and bar percentages are ignored. + // Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%') + // and deprecate barPercentage since this value is ignored when thickness is absolute. + size = thickness * count; + ratio = 1; + } + + return { + chunk: size / count, + ratio: ratio, + start: curr - (size / 2) + }; +} + +/** + * Computes an "optimal" category that globally arranges bars side by side (no gap when + * percentage options are 1), based on the previous and following categories. This mode + * generates bars with different widths when data are not evenly spaced. + * @private + */ +function computeFlexCategoryTraits(index, ruler, options) { + var pixels = ruler.pixels; + var curr = pixels[index]; + var prev = index > 0 ? pixels[index - 1] : null; + var next = index < pixels.length - 1 ? pixels[index + 1] : null; + var percent = options.categoryPercentage; + var start, size; + + if (prev === null) { + // first data: its size is double based on the next point or, + // if it's also the last data, we use the scale size. + prev = curr - (next === null ? ruler.end - ruler.start : next - curr); + } + + if (next === null) { + // last data: its size is also double based on the previous point. + next = curr + curr - prev; + } + + start = curr - (curr - Math.min(prev, next)) / 2 * percent; + size = Math.abs(next - prev) / 2 * percent; + + return { + chunk: size / ruler.stackCount, + ratio: options.barPercentage, + start: start + }; +} + +var controller_bar = core_datasetController.extend({ + + dataElementType: elements.Rectangle, + + /** + * @private + */ + _dataElementOptions: [ + 'backgroundColor', + 'borderColor', + 'borderSkipped', + 'borderWidth', + 'barPercentage', + 'barThickness', + 'categoryPercentage', + 'maxBarThickness', + 'minBarLength' + ], + + initialize: function() { + var me = this; + var meta, scaleOpts; + + core_datasetController.prototype.initialize.apply(me, arguments); + + meta = me.getMeta(); + meta.stack = me.getDataset().stack; + meta.bar = true; + + scaleOpts = me._getIndexScale().options; + deprecated('bar chart', scaleOpts.barPercentage, 'scales.[x/y]Axes.barPercentage', 'dataset.barPercentage'); + deprecated('bar chart', scaleOpts.barThickness, 'scales.[x/y]Axes.barThickness', 'dataset.barThickness'); + deprecated('bar chart', scaleOpts.categoryPercentage, 'scales.[x/y]Axes.categoryPercentage', 'dataset.categoryPercentage'); + deprecated('bar chart', me._getValueScale().options.minBarLength, 'scales.[x/y]Axes.minBarLength', 'dataset.minBarLength'); + deprecated('bar chart', scaleOpts.maxBarThickness, 'scales.[x/y]Axes.maxBarThickness', 'dataset.maxBarThickness'); + }, + + update: function(reset) { + var me = this; + var rects = me.getMeta().data; + var i, ilen; + + me._ruler = me.getRuler(); + + for (i = 0, ilen = rects.length; i < ilen; ++i) { + me.updateElement(rects[i], i, reset); + } + }, + + updateElement: function(rectangle, index, reset) { + var me = this; + var meta = me.getMeta(); + var dataset = me.getDataset(); + var options = me._resolveDataElementOptions(rectangle, index); + + rectangle._xScale = me.getScaleForId(meta.xAxisID); + rectangle._yScale = me.getScaleForId(meta.yAxisID); + rectangle._datasetIndex = me.index; + rectangle._index = index; + rectangle._model = { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderSkipped: options.borderSkipped, + borderWidth: options.borderWidth, + datasetLabel: dataset.label, + label: me.chart.data.labels[index] + }; + + if (helpers$1.isArray(dataset.data[index])) { + rectangle._model.borderSkipped = null; + } + + me._updateElementGeometry(rectangle, index, reset, options); + + rectangle.pivot(); + }, + + /** + * @private + */ + _updateElementGeometry: function(rectangle, index, reset, options) { + var me = this; + var model = rectangle._model; + var vscale = me._getValueScale(); + var base = vscale.getBasePixel(); + var horizontal = vscale.isHorizontal(); + var ruler = me._ruler || me.getRuler(); + var vpixels = me.calculateBarValuePixels(me.index, index, options); + var ipixels = me.calculateBarIndexPixels(me.index, index, ruler, options); + + model.horizontal = horizontal; + model.base = reset ? base : vpixels.base; + model.x = horizontal ? reset ? base : vpixels.head : ipixels.center; + model.y = horizontal ? ipixels.center : reset ? base : vpixels.head; + model.height = horizontal ? ipixels.size : undefined; + model.width = horizontal ? undefined : ipixels.size; + }, + + /** + * Returns the stacks based on groups and bar visibility. + * @param {number} [last] - The dataset index + * @returns {string[]} The list of stack IDs + * @private + */ + _getStacks: function(last) { + var me = this; + var scale = me._getIndexScale(); + var metasets = scale._getMatchingVisibleMetas(me._type); + var stacked = scale.options.stacked; + var ilen = metasets.length; + var stacks = []; + var i, meta; + + for (i = 0; i < ilen; ++i) { + meta = metasets[i]; + // stacked | meta.stack + // | found | not found | undefined + // false | x | x | x + // true | | x | + // undefined | | x | x + if (stacked === false || stacks.indexOf(meta.stack) === -1 || + (stacked === undefined && meta.stack === undefined)) { + stacks.push(meta.stack); + } + if (meta.index === last) { + break; + } + } + + return stacks; + }, + + /** + * Returns the effective number of stacks based on groups and bar visibility. + * @private + */ + getStackCount: function() { + return this._getStacks().length; + }, + + /** + * Returns the stack index for the given dataset based on groups and bar visibility. + * @param {number} [datasetIndex] - The dataset index + * @param {string} [name] - The stack name to find + * @returns {number} The stack index + * @private + */ + getStackIndex: function(datasetIndex, name) { + var stacks = this._getStacks(datasetIndex); + var index = (name !== undefined) + ? stacks.indexOf(name) + : -1; // indexOf returns -1 if element is not present + + return (index === -1) + ? stacks.length - 1 + : index; + }, + + /** + * @private + */ + getRuler: function() { + var me = this; + var scale = me._getIndexScale(); + var pixels = []; + var i, ilen; + + for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) { + pixels.push(scale.getPixelForValue(null, i, me.index)); + } + + return { + pixels: pixels, + start: scale._startPixel, + end: scale._endPixel, + stackCount: me.getStackCount(), + scale: scale + }; + }, + + /** + * Note: pixel values are not clamped to the scale area. + * @private + */ + calculateBarValuePixels: function(datasetIndex, index, options) { + var me = this; + var chart = me.chart; + var scale = me._getValueScale(); + var isHorizontal = scale.isHorizontal(); + var datasets = chart.data.datasets; + var metasets = scale._getMatchingVisibleMetas(me._type); + var value = scale._parseValue(datasets[datasetIndex].data[index]); + var minBarLength = options.minBarLength; + var stacked = scale.options.stacked; + var stack = me.getMeta().stack; + var start = value.start === undefined ? 0 : value.max >= 0 && value.min >= 0 ? value.min : value.max; + var length = value.start === undefined ? value.end : value.max >= 0 && value.min >= 0 ? value.max - value.min : value.min - value.max; + var ilen = metasets.length; + var i, imeta, ivalue, base, head, size, stackLength; + + if (stacked || (stacked === undefined && stack !== undefined)) { + for (i = 0; i < ilen; ++i) { + imeta = metasets[i]; + + if (imeta.index === datasetIndex) { + break; + } + + if (imeta.stack === stack) { + stackLength = scale._parseValue(datasets[imeta.index].data[index]); + ivalue = stackLength.start === undefined ? stackLength.end : stackLength.min >= 0 && stackLength.max >= 0 ? stackLength.max : stackLength.min; + + if ((value.min < 0 && ivalue < 0) || (value.max >= 0 && ivalue > 0)) { + start += ivalue; + } + } + } + } + + base = scale.getPixelForValue(start); + head = scale.getPixelForValue(start + length); + size = head - base; + + if (minBarLength !== undefined && Math.abs(size) < minBarLength) { + size = minBarLength; + if (length >= 0 && !isHorizontal || length < 0 && isHorizontal) { + head = base - minBarLength; + } else { + head = base + minBarLength; + } + } + + return { + size: size, + base: base, + head: head, + center: head + size / 2 + }; + }, + + /** + * @private + */ + calculateBarIndexPixels: function(datasetIndex, index, ruler, options) { + var me = this; + var range = options.barThickness === 'flex' + ? computeFlexCategoryTraits(index, ruler, options) + : computeFitCategoryTraits(index, ruler, options); + + var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack); + var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2); + var size = Math.min( + valueOrDefault$3(options.maxBarThickness, Infinity), + range.chunk * range.ratio); + + return { + base: center - size / 2, + head: center + size / 2, + center: center, + size: size + }; + }, + + draw: function() { + var me = this; + var chart = me.chart; + var scale = me._getValueScale(); + var rects = me.getMeta().data; + var dataset = me.getDataset(); + var ilen = rects.length; + var i = 0; + + helpers$1.canvas.clipArea(chart.ctx, chart.chartArea); + + for (; i < ilen; ++i) { + var val = scale._parseValue(dataset.data[i]); + if (!isNaN(val.min) && !isNaN(val.max)) { + rects[i].draw(); + } + } + + helpers$1.canvas.unclipArea(chart.ctx); + }, + + /** + * @private + */ + _resolveDataElementOptions: function() { + var me = this; + var values = helpers$1.extend({}, core_datasetController.prototype._resolveDataElementOptions.apply(me, arguments)); + var indexOpts = me._getIndexScale().options; + var valueOpts = me._getValueScale().options; + + values.barPercentage = valueOrDefault$3(indexOpts.barPercentage, values.barPercentage); + values.barThickness = valueOrDefault$3(indexOpts.barThickness, values.barThickness); + values.categoryPercentage = valueOrDefault$3(indexOpts.categoryPercentage, values.categoryPercentage); + values.maxBarThickness = valueOrDefault$3(indexOpts.maxBarThickness, values.maxBarThickness); + values.minBarLength = valueOrDefault$3(valueOpts.minBarLength, values.minBarLength); + + return values; + } + +}); + +var valueOrDefault$4 = helpers$1.valueOrDefault; +var resolve$1 = helpers$1.options.resolve; + +core_defaults._set('bubble', { + hover: { + mode: 'single' + }, + + scales: { + xAxes: [{ + type: 'linear', // bubble should probably use a linear scale by default + position: 'bottom', + id: 'x-axis-0' // need an ID so datasets can reference the scale + }], + yAxes: [{ + type: 'linear', + position: 'left', + id: 'y-axis-0' + }] + }, + + tooltips: { + callbacks: { + title: function() { + // Title doesn't make sense for scatter since we format the data as a point + return ''; + }, + label: function(item, data) { + var datasetLabel = data.datasets[item.datasetIndex].label || ''; + var dataPoint = data.datasets[item.datasetIndex].data[item.index]; + return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')'; + } + } + } +}); + +var controller_bubble = core_datasetController.extend({ + /** + * @protected + */ + dataElementType: elements.Point, + + /** + * @private + */ + _dataElementOptions: [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'hoverBackgroundColor', + 'hoverBorderColor', + 'hoverBorderWidth', + 'hoverRadius', + 'hitRadius', + 'pointStyle', + 'rotation' + ], + + /** + * @protected + */ + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var points = meta.data; + + // Update Points + helpers$1.each(points, function(point, index) { + me.updateElement(point, index, reset); + }); + }, + + /** + * @protected + */ + updateElement: function(point, index, reset) { + var me = this; + var meta = me.getMeta(); + var custom = point.custom || {}; + var xScale = me.getScaleForId(meta.xAxisID); + var yScale = me.getScaleForId(meta.yAxisID); + var options = me._resolveDataElementOptions(point, index); + var data = me.getDataset().data[index]; + var dsIndex = me.index; + + var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex); + var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex); + + point._xScale = xScale; + point._yScale = yScale; + point._options = options; + point._datasetIndex = dsIndex; + point._index = index; + point._model = { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + hitRadius: options.hitRadius, + pointStyle: options.pointStyle, + rotation: options.rotation, + radius: reset ? 0 : options.radius, + skip: custom.skip || isNaN(x) || isNaN(y), + x: x, + y: y, + }; + + point.pivot(); + }, + + /** + * @protected + */ + setHoverStyle: function(point) { + var model = point._model; + var options = point._options; + var getHoverColor = helpers$1.getHoverColor; + + point.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + radius: model.radius + }; + + model.backgroundColor = valueOrDefault$4(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault$4(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$4(options.hoverBorderWidth, options.borderWidth); + model.radius = options.radius + options.hoverRadius; + }, + + /** + * @private + */ + _resolveDataElementOptions: function(point, index) { + var me = this; + var chart = me.chart; + var dataset = me.getDataset(); + var custom = point.custom || {}; + var data = dataset.data[index] || {}; + var values = core_datasetController.prototype._resolveDataElementOptions.apply(me, arguments); + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + // In case values were cached (and thus frozen), we need to clone the values + if (me._cachedDataOpts === values) { + values = helpers$1.extend({}, values); + } + + // Custom radius resolution + values.radius = resolve$1([ + custom.radius, + data.r, + me._config.radius, + chart.options.elements.point.radius + ], context, index); + + return values; + } +}); + +var valueOrDefault$5 = helpers$1.valueOrDefault; + +var PI$1 = Math.PI; +var DOUBLE_PI$1 = PI$1 * 2; +var HALF_PI$1 = PI$1 / 2; + +core_defaults._set('doughnut', { + animation: { + // Boolean - Whether we animate the rotation of the Doughnut + animateRotate: true, + // Boolean - Whether we animate scaling the Doughnut from the centre + animateScale: false + }, + hover: { + mode: 'single' + }, + legendCallback: function(chart) { + var list = document.createElement('ul'); + var data = chart.data; + var datasets = data.datasets; + var labels = data.labels; + var i, ilen, listItem, listItemSpan; + + list.setAttribute('class', chart.id + '-legend'); + if (datasets.length) { + for (i = 0, ilen = datasets[0].data.length; i < ilen; ++i) { + listItem = list.appendChild(document.createElement('li')); + listItemSpan = listItem.appendChild(document.createElement('span')); + listItemSpan.style.backgroundColor = datasets[0].backgroundColor[i]; + if (labels[i]) { + listItem.appendChild(document.createTextNode(labels[i])); + } + } + } + + return list.outerHTML; + }, + legend: { + labels: { + generateLabels: function(chart) { + var data = chart.data; + if (data.labels.length && data.datasets.length) { + return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); + var style = meta.controller.getStyle(i); + + return { + text: label, + fillStyle: style.backgroundColor, + strokeStyle: style.borderColor, + lineWidth: style.borderWidth, + hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden, + + // Extra data used for toggling the correct item + index: i + }; + }); + } + return []; + } + }, + + onClick: function(e, legendItem) { + var index = legendItem.index; + var chart = this.chart; + var i, ilen, meta; + + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + // toggle visibility of index if exists + if (meta.data[index]) { + meta.data[index].hidden = !meta.data[index].hidden; + } + } + + chart.update(); + } + }, + + // The percentage of the chart that we cut out of the middle. + cutoutPercentage: 50, + + // The rotation of the chart, where the first data arc begins. + rotation: -HALF_PI$1, + + // The total circumference of the chart. + circumference: DOUBLE_PI$1, + + // Need to override these to give a nice default + tooltips: { + callbacks: { + title: function() { + return ''; + }, + label: function(tooltipItem, data) { + var dataLabel = data.labels[tooltipItem.index]; + var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; + + if (helpers$1.isArray(dataLabel)) { + // show value on first line of multiline label + // need to clone because we are changing the value + dataLabel = dataLabel.slice(); + dataLabel[0] += value; + } else { + dataLabel += value; + } + + return dataLabel; + } + } + } +}); + +var controller_doughnut = core_datasetController.extend({ + + dataElementType: elements.Arc, + + linkScales: helpers$1.noop, + + /** + * @private + */ + _dataElementOptions: [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'borderAlign', + 'hoverBackgroundColor', + 'hoverBorderColor', + 'hoverBorderWidth', + ], + + // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly + getRingIndex: function(datasetIndex) { + var ringIndex = 0; + + for (var j = 0; j < datasetIndex; ++j) { + if (this.chart.isDatasetVisible(j)) { + ++ringIndex; + } + } + + return ringIndex; + }, + + update: function(reset) { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var ratioX = 1; + var ratioY = 1; + var offsetX = 0; + var offsetY = 0; + var meta = me.getMeta(); + var arcs = meta.data; + var cutout = opts.cutoutPercentage / 100 || 0; + var circumference = opts.circumference; + var chartWeight = me._getRingWeight(me.index); + var maxWidth, maxHeight, i, ilen; + + // If the chart's circumference isn't a full circle, calculate size as a ratio of the width/height of the arc + if (circumference < DOUBLE_PI$1) { + var startAngle = opts.rotation % DOUBLE_PI$1; + startAngle += startAngle >= PI$1 ? -DOUBLE_PI$1 : startAngle < -PI$1 ? DOUBLE_PI$1 : 0; + var endAngle = startAngle + circumference; + var startX = Math.cos(startAngle); + var startY = Math.sin(startAngle); + var endX = Math.cos(endAngle); + var endY = Math.sin(endAngle); + var contains0 = (startAngle <= 0 && endAngle >= 0) || endAngle >= DOUBLE_PI$1; + var contains90 = (startAngle <= HALF_PI$1 && endAngle >= HALF_PI$1) || endAngle >= DOUBLE_PI$1 + HALF_PI$1; + var contains180 = startAngle === -PI$1 || endAngle >= PI$1; + var contains270 = (startAngle <= -HALF_PI$1 && endAngle >= -HALF_PI$1) || endAngle >= PI$1 + HALF_PI$1; + var minX = contains180 ? -1 : Math.min(startX, startX * cutout, endX, endX * cutout); + var minY = contains270 ? -1 : Math.min(startY, startY * cutout, endY, endY * cutout); + var maxX = contains0 ? 1 : Math.max(startX, startX * cutout, endX, endX * cutout); + var maxY = contains90 ? 1 : Math.max(startY, startY * cutout, endY, endY * cutout); + ratioX = (maxX - minX) / 2; + ratioY = (maxY - minY) / 2; + offsetX = -(maxX + minX) / 2; + offsetY = -(maxY + minY) / 2; + } + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + arcs[i]._options = me._resolveDataElementOptions(arcs[i], i); + } + + chart.borderWidth = me.getMaxBorderWidth(); + maxWidth = (chartArea.right - chartArea.left - chart.borderWidth) / ratioX; + maxHeight = (chartArea.bottom - chartArea.top - chart.borderWidth) / ratioY; + chart.outerRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0); + chart.innerRadius = Math.max(chart.outerRadius * cutout, 0); + chart.radiusLength = (chart.outerRadius - chart.innerRadius) / (me._getVisibleDatasetWeightTotal() || 1); + chart.offsetX = offsetX * chart.outerRadius; + chart.offsetY = offsetY * chart.outerRadius; + + meta.total = me.calculateTotal(); + + me.outerRadius = chart.outerRadius - chart.radiusLength * me._getRingWeightOffset(me.index); + me.innerRadius = Math.max(me.outerRadius - chart.radiusLength * chartWeight, 0); + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + me.updateElement(arcs[i], i, reset); + } + }, + + updateElement: function(arc, index, reset) { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var animationOpts = opts.animation; + var centerX = (chartArea.left + chartArea.right) / 2; + var centerY = (chartArea.top + chartArea.bottom) / 2; + var startAngle = opts.rotation; // non reset case handled later + var endAngle = opts.rotation; // non reset case handled later + var dataset = me.getDataset(); + var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / DOUBLE_PI$1); + var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius; + var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius; + var options = arc._options || {}; + + helpers$1.extend(arc, { + // Utility + _datasetIndex: me.index, + _index: index, + + // Desired view properties + _model: { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + borderAlign: options.borderAlign, + x: centerX + chart.offsetX, + y: centerY + chart.offsetY, + startAngle: startAngle, + endAngle: endAngle, + circumference: circumference, + outerRadius: outerRadius, + innerRadius: innerRadius, + label: helpers$1.valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index]) + } + }); + + var model = arc._model; + + // Set correct angles if not resetting + if (!reset || !animationOpts.animateRotate) { + if (index === 0) { + model.startAngle = opts.rotation; + } else { + model.startAngle = me.getMeta().data[index - 1]._model.endAngle; + } + + model.endAngle = model.startAngle + model.circumference; + } + + arc.pivot(); + }, + + calculateTotal: function() { + var dataset = this.getDataset(); + var meta = this.getMeta(); + var total = 0; + var value; + + helpers$1.each(meta.data, function(element, index) { + value = dataset.data[index]; + if (!isNaN(value) && !element.hidden) { + total += Math.abs(value); + } + }); + + /* if (total === 0) { + total = NaN; + }*/ + + return total; + }, + + calculateCircumference: function(value) { + var total = this.getMeta().total; + if (total > 0 && !isNaN(value)) { + return DOUBLE_PI$1 * (Math.abs(value) / total); + } + return 0; + }, + + // gets the max border or hover width to properly scale pie charts + getMaxBorderWidth: function(arcs) { + var me = this; + var max = 0; + var chart = me.chart; + var i, ilen, meta, arc, controller, options, borderWidth, hoverWidth; + + if (!arcs) { + // Find the outmost visible dataset + for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) { + if (chart.isDatasetVisible(i)) { + meta = chart.getDatasetMeta(i); + arcs = meta.data; + if (i !== me.index) { + controller = meta.controller; + } + break; + } + } + } + + if (!arcs) { + return 0; + } + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + arc = arcs[i]; + if (controller) { + controller._configure(); + options = controller._resolveDataElementOptions(arc, i); + } else { + options = arc._options; + } + if (options.borderAlign !== 'inner') { + borderWidth = options.borderWidth; + hoverWidth = options.hoverBorderWidth; + + max = borderWidth > max ? borderWidth : max; + max = hoverWidth > max ? hoverWidth : max; + } + } + return max; + }, + + /** + * @protected + */ + setHoverStyle: function(arc) { + var model = arc._model; + var options = arc._options; + var getHoverColor = helpers$1.getHoverColor; + + arc.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + }; + + model.backgroundColor = valueOrDefault$5(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault$5(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$5(options.hoverBorderWidth, options.borderWidth); + }, + + /** + * Get radius length offset of the dataset in relation to the visible datasets weights. This allows determining the inner and outer radius correctly + * @private + */ + _getRingWeightOffset: function(datasetIndex) { + var ringWeightOffset = 0; + + for (var i = 0; i < datasetIndex; ++i) { + if (this.chart.isDatasetVisible(i)) { + ringWeightOffset += this._getRingWeight(i); + } + } + + return ringWeightOffset; + }, + + /** + * @private + */ + _getRingWeight: function(dataSetIndex) { + return Math.max(valueOrDefault$5(this.chart.data.datasets[dataSetIndex].weight, 1), 0); + }, + + /** + * Returns the sum of all visibile data set weights. This value can be 0. + * @private + */ + _getVisibleDatasetWeightTotal: function() { + return this._getRingWeightOffset(this.chart.data.datasets.length); + } +}); + +core_defaults._set('horizontalBar', { + hover: { + mode: 'index', + axis: 'y' + }, + + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom' + }], + + yAxes: [{ + type: 'category', + position: 'left', + offset: true, + gridLines: { + offsetGridLines: true + } + }] + }, + + elements: { + rectangle: { + borderSkipped: 'left' + } + }, + + tooltips: { + mode: 'index', + axis: 'y' + } +}); + +core_defaults._set('global', { + datasets: { + horizontalBar: { + categoryPercentage: 0.8, + barPercentage: 0.9 + } + } +}); + +var controller_horizontalBar = controller_bar.extend({ + /** + * @private + */ + _getValueScaleId: function() { + return this.getMeta().xAxisID; + }, + + /** + * @private + */ + _getIndexScaleId: function() { + return this.getMeta().yAxisID; + } +}); + +var valueOrDefault$6 = helpers$1.valueOrDefault; +var resolve$2 = helpers$1.options.resolve; +var isPointInArea = helpers$1.canvas._isPointInArea; + +core_defaults._set('line', { + showLines: true, + spanGaps: false, + + hover: { + mode: 'label' + }, + + scales: { + xAxes: [{ + type: 'category', + id: 'x-axis-0' + }], + yAxes: [{ + type: 'linear', + id: 'y-axis-0' + }] + } +}); + +function scaleClip(scale, halfBorderWidth) { + var tickOpts = scale && scale.options.ticks || {}; + var reverse = tickOpts.reverse; + var min = tickOpts.min === undefined ? halfBorderWidth : 0; + var max = tickOpts.max === undefined ? halfBorderWidth : 0; + return { + start: reverse ? max : min, + end: reverse ? min : max + }; +} + +function defaultClip(xScale, yScale, borderWidth) { + var halfBorderWidth = borderWidth / 2; + var x = scaleClip(xScale, halfBorderWidth); + var y = scaleClip(yScale, halfBorderWidth); + + return { + top: y.end, + right: x.end, + bottom: y.start, + left: x.start + }; +} + +function toClip(value) { + var t, r, b, l; + + if (helpers$1.isObject(value)) { + t = value.top; + r = value.right; + b = value.bottom; + l = value.left; + } else { + t = r = b = l = value; + } + + return { + top: t, + right: r, + bottom: b, + left: l + }; +} + + +var controller_line = core_datasetController.extend({ + + datasetElementType: elements.Line, + + dataElementType: elements.Point, + + /** + * @private + */ + _datasetElementOptions: [ + 'backgroundColor', + 'borderCapStyle', + 'borderColor', + 'borderDash', + 'borderDashOffset', + 'borderJoinStyle', + 'borderWidth', + 'cubicInterpolationMode', + 'fill' + ], + + /** + * @private + */ + _dataElementOptions: { + backgroundColor: 'pointBackgroundColor', + borderColor: 'pointBorderColor', + borderWidth: 'pointBorderWidth', + hitRadius: 'pointHitRadius', + hoverBackgroundColor: 'pointHoverBackgroundColor', + hoverBorderColor: 'pointHoverBorderColor', + hoverBorderWidth: 'pointHoverBorderWidth', + hoverRadius: 'pointHoverRadius', + pointStyle: 'pointStyle', + radius: 'pointRadius', + rotation: 'pointRotation' + }, + + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var line = meta.dataset; + var points = meta.data || []; + var options = me.chart.options; + var config = me._config; + var showLine = me._showLine = valueOrDefault$6(config.showLine, options.showLines); + var i, ilen; + + me._xScale = me.getScaleForId(meta.xAxisID); + me._yScale = me.getScaleForId(meta.yAxisID); + + // Update Line + if (showLine) { + // Compatibility: If the properties are defined with only the old name, use those values + if (config.tension !== undefined && config.lineTension === undefined) { + config.lineTension = config.tension; + } + + // Utility + line._scale = me._yScale; + line._datasetIndex = me.index; + // Data + line._children = points; + // Model + line._model = me._resolveDatasetElementOptions(line); + + line.pivot(); + } + + // Update Points + for (i = 0, ilen = points.length; i < ilen; ++i) { + me.updateElement(points[i], i, reset); + } + + if (showLine && line._model.tension !== 0) { + me.updateBezierControlPoints(); + } + + // Now pivot the point for animation + for (i = 0, ilen = points.length; i < ilen; ++i) { + points[i].pivot(); + } + }, + + updateElement: function(point, index, reset) { + var me = this; + var meta = me.getMeta(); + var custom = point.custom || {}; + var dataset = me.getDataset(); + var datasetIndex = me.index; + var value = dataset.data[index]; + var xScale = me._xScale; + var yScale = me._yScale; + var lineModel = meta.dataset._model; + var x, y; + + var options = me._resolveDataElementOptions(point, index); + + x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex); + y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex); + + // Utility + point._xScale = xScale; + point._yScale = yScale; + point._options = options; + point._datasetIndex = datasetIndex; + point._index = index; + + // Desired view properties + point._model = { + x: x, + y: y, + skip: custom.skip || isNaN(x) || isNaN(y), + // Appearance + radius: options.radius, + pointStyle: options.pointStyle, + rotation: options.rotation, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + tension: valueOrDefault$6(custom.tension, lineModel ? lineModel.tension : 0), + steppedLine: lineModel ? lineModel.steppedLine : false, + // Tooltip + hitRadius: options.hitRadius + }; + }, + + /** + * @private + */ + _resolveDatasetElementOptions: function(element) { + var me = this; + var config = me._config; + var custom = element.custom || {}; + var options = me.chart.options; + var lineOptions = options.elements.line; + var values = core_datasetController.prototype._resolveDatasetElementOptions.apply(me, arguments); + + // The default behavior of lines is to break at null values, according + // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158 + // This option gives lines the ability to span gaps + values.spanGaps = valueOrDefault$6(config.spanGaps, options.spanGaps); + values.tension = valueOrDefault$6(config.lineTension, lineOptions.tension); + values.steppedLine = resolve$2([custom.steppedLine, config.steppedLine, lineOptions.stepped]); + values.clip = toClip(valueOrDefault$6(config.clip, defaultClip(me._xScale, me._yScale, values.borderWidth))); + + return values; + }, + + calculatePointY: function(value, index, datasetIndex) { + var me = this; + var chart = me.chart; + var yScale = me._yScale; + var sumPos = 0; + var sumNeg = 0; + var i, ds, dsMeta, stackedRightValue, rightValue, metasets, ilen; + + if (yScale.options.stacked) { + rightValue = +yScale.getRightValue(value); + metasets = chart._getSortedVisibleDatasetMetas(); + ilen = metasets.length; + + for (i = 0; i < ilen; ++i) { + dsMeta = metasets[i]; + if (dsMeta.index === datasetIndex) { + break; + } + + ds = chart.data.datasets[dsMeta.index]; + if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id) { + stackedRightValue = +yScale.getRightValue(ds.data[index]); + if (stackedRightValue < 0) { + sumNeg += stackedRightValue || 0; + } else { + sumPos += stackedRightValue || 0; + } + } + } + + if (rightValue < 0) { + return yScale.getPixelForValue(sumNeg + rightValue); + } + return yScale.getPixelForValue(sumPos + rightValue); + } + return yScale.getPixelForValue(value); + }, + + updateBezierControlPoints: function() { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var lineModel = meta.dataset._model; + var area = chart.chartArea; + var points = meta.data || []; + var i, ilen, model, controlPoints; + + // Only consider points that are drawn in case the spanGaps option is used + if (lineModel.spanGaps) { + points = points.filter(function(pt) { + return !pt._model.skip; + }); + } + + function capControlPoint(pt, min, max) { + return Math.max(Math.min(pt, max), min); + } + + if (lineModel.cubicInterpolationMode === 'monotone') { + helpers$1.splineCurveMonotone(points); + } else { + for (i = 0, ilen = points.length; i < ilen; ++i) { + model = points[i]._model; + controlPoints = helpers$1.splineCurve( + helpers$1.previousItem(points, i)._model, + model, + helpers$1.nextItem(points, i)._model, + lineModel.tension + ); + model.controlPointPreviousX = controlPoints.previous.x; + model.controlPointPreviousY = controlPoints.previous.y; + model.controlPointNextX = controlPoints.next.x; + model.controlPointNextY = controlPoints.next.y; + } + } + + if (chart.options.elements.line.capBezierPoints) { + for (i = 0, ilen = points.length; i < ilen; ++i) { + model = points[i]._model; + if (isPointInArea(model, area)) { + if (i > 0 && isPointInArea(points[i - 1]._model, area)) { + model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right); + model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom); + } + if (i < points.length - 1 && isPointInArea(points[i + 1]._model, area)) { + model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right); + model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom); + } + } + } + } + }, + + draw: function() { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var points = meta.data || []; + var area = chart.chartArea; + var canvas = chart.canvas; + var i = 0; + var ilen = points.length; + var clip; + + if (me._showLine) { + clip = meta.dataset._model.clip; + + helpers$1.canvas.clipArea(chart.ctx, { + left: clip.left === false ? 0 : area.left - clip.left, + right: clip.right === false ? canvas.width : area.right + clip.right, + top: clip.top === false ? 0 : area.top - clip.top, + bottom: clip.bottom === false ? canvas.height : area.bottom + clip.bottom + }); + + meta.dataset.draw(); + + helpers$1.canvas.unclipArea(chart.ctx); + } + + // Draw the points + for (; i < ilen; ++i) { + points[i].draw(area); + } + }, + + /** + * @protected + */ + setHoverStyle: function(point) { + var model = point._model; + var options = point._options; + var getHoverColor = helpers$1.getHoverColor; + + point.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + radius: model.radius + }; + + model.backgroundColor = valueOrDefault$6(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = "rgba(255,0,0,1.)";//valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = 1;//valueOrDefault$6(options.hoverBorderWidth, options.borderWidth); + model.radius = 2;//valueOrDefault$6(options.hoverRadius, options.radius); + }, +}); + +var resolve$3 = helpers$1.options.resolve; + +core_defaults._set('polarArea', { + scale: { + type: 'radialLinear', + angleLines: { + display: false + }, + gridLines: { + circular: true + }, + pointLabels: { + display: false + }, + ticks: { + beginAtZero: true + } + }, + + // Boolean - Whether to animate the rotation of the chart + animation: { + animateRotate: true, + animateScale: true + }, + + startAngle: -0.5 * Math.PI, + legendCallback: function(chart) { + var list = document.createElement('ul'); + var data = chart.data; + var datasets = data.datasets; + var labels = data.labels; + var i, ilen, listItem, listItemSpan; + + list.setAttribute('class', chart.id + '-legend'); + if (datasets.length) { + for (i = 0, ilen = datasets[0].data.length; i < ilen; ++i) { + listItem = list.appendChild(document.createElement('li')); + listItemSpan = listItem.appendChild(document.createElement('span')); + listItemSpan.style.backgroundColor = datasets[0].backgroundColor[i]; + if (labels[i]) { + listItem.appendChild(document.createTextNode(labels[i])); + } + } + } + + return list.outerHTML; + }, + legend: { + labels: { + generateLabels: function(chart) { + var data = chart.data; + if (data.labels.length && data.datasets.length) { + return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); + var style = meta.controller.getStyle(i); + + return { + text: label, + fillStyle: style.backgroundColor, + strokeStyle: style.borderColor, + lineWidth: style.borderWidth, + hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden, + + // Extra data used for toggling the correct item + index: i + }; + }); + } + return []; + } + }, + + onClick: function(e, legendItem) { + var index = legendItem.index; + var chart = this.chart; + var i, ilen, meta; + + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + meta.data[index].hidden = !meta.data[index].hidden; + } + + chart.update(); + } + }, + + // Need to override these to give a nice default + tooltips: { + callbacks: { + title: function() { + return ''; + }, + label: function(item, data) { + return data.labels[item.index] + ': ' + item.yLabel; + } + } + } +}); + +var controller_polarArea = core_datasetController.extend({ + + dataElementType: elements.Arc, + + linkScales: helpers$1.noop, + + /** + * @private + */ + _dataElementOptions: [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'borderAlign', + 'hoverBackgroundColor', + 'hoverBorderColor', + 'hoverBorderWidth', + ], + + /** + * @private + */ + _getIndexScaleId: function() { + return this.chart.scale.id; + }, + + /** + * @private + */ + _getValueScaleId: function() { + return this.chart.scale.id; + }, + + update: function(reset) { + var me = this; + var dataset = me.getDataset(); + var meta = me.getMeta(); + var start = me.chart.options.startAngle || 0; + var starts = me._starts = []; + var angles = me._angles = []; + var arcs = meta.data; + var i, ilen, angle; + + me._updateRadius(); + + meta.count = me.countVisibleElements(); + + for (i = 0, ilen = dataset.data.length; i < ilen; i++) { + starts[i] = start; + angle = me._computeAngle(i); + angles[i] = angle; + start += angle; + } + + for (i = 0, ilen = arcs.length; i < ilen; ++i) { + arcs[i]._options = me._resolveDataElementOptions(arcs[i], i); + me.updateElement(arcs[i], i, reset); + } + }, + + /** + * @private + */ + _updateRadius: function() { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); + + chart.outerRadius = Math.max(minSize / 2, 0); + chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0); + chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); + + me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index); + me.innerRadius = me.outerRadius - chart.radiusLength; + }, + + updateElement: function(arc, index, reset) { + var me = this; + var chart = me.chart; + var dataset = me.getDataset(); + var opts = chart.options; + var animationOpts = opts.animation; + var scale = chart.scale; + var labels = chart.data.labels; + + var centerX = scale.xCenter; + var centerY = scale.yCenter; + + // var negHalfPI = -0.5 * Math.PI; + var datasetStartAngle = opts.startAngle; + var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); + var startAngle = me._starts[index]; + var endAngle = startAngle + (arc.hidden ? 0 : me._angles[index]); + + var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); + var options = arc._options || {}; + + helpers$1.extend(arc, { + // Utility + _datasetIndex: me.index, + _index: index, + _scale: scale, + + // Desired view properties + _model: { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + borderAlign: options.borderAlign, + x: centerX, + y: centerY, + innerRadius: 0, + outerRadius: reset ? resetRadius : distance, + startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle, + endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle, + label: helpers$1.valueAtIndexOrDefault(labels, index, labels[index]) + } + }); + + arc.pivot(); + }, + + countVisibleElements: function() { + var dataset = this.getDataset(); + var meta = this.getMeta(); + var count = 0; + + helpers$1.each(meta.data, function(element, index) { + if (!isNaN(dataset.data[index]) && !element.hidden) { + count++; + } + }); + + return count; + }, + + /** + * @protected + */ + setHoverStyle: function(arc) { + var model = arc._model; + var options = arc._options; + var getHoverColor = helpers$1.getHoverColor; + var valueOrDefault = helpers$1.valueOrDefault; + + arc.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + }; + + model.backgroundColor = valueOrDefault(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault(options.hoverBorderWidth, options.borderWidth); + }, + + /** + * @private + */ + _computeAngle: function(index) { + var me = this; + var count = this.getMeta().count; + var dataset = me.getDataset(); + var meta = me.getMeta(); + + if (isNaN(dataset.data[index]) || meta.data[index].hidden) { + return 0; + } + + // Scriptable options + var context = { + chart: me.chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; + + return resolve$3([ + me.chart.options.elements.arc.angle, + (2 * Math.PI) / count + ], context, index); + } +}); + +core_defaults._set('pie', helpers$1.clone(core_defaults.doughnut)); +core_defaults._set('pie', { + cutoutPercentage: 0 +}); + +// Pie charts are Doughnut chart with different defaults +var controller_pie = controller_doughnut; + +var valueOrDefault$7 = helpers$1.valueOrDefault; + +core_defaults._set('radar', { + spanGaps: false, + scale: { + type: 'radialLinear' + }, + elements: { + line: { + fill: 'start', + tension: 0 // no bezier in radar + } + } +}); + +var controller_radar = core_datasetController.extend({ + datasetElementType: elements.Line, + + dataElementType: elements.Point, + + linkScales: helpers$1.noop, + + /** + * @private + */ + _datasetElementOptions: [ + 'backgroundColor', + 'borderWidth', + 'borderColor', + 'borderCapStyle', + 'borderDash', + 'borderDashOffset', + 'borderJoinStyle', + 'fill' + ], + + /** + * @private + */ + _dataElementOptions: { + backgroundColor: 'pointBackgroundColor', + borderColor: 'pointBorderColor', + borderWidth: 'pointBorderWidth', + hitRadius: 'pointHitRadius', + hoverBackgroundColor: 'pointHoverBackgroundColor', + hoverBorderColor: 'pointHoverBorderColor', + hoverBorderWidth: 'pointHoverBorderWidth', + hoverRadius: 'pointHoverRadius', + pointStyle: 'pointStyle', + radius: 'pointRadius', + rotation: 'pointRotation' + }, + + /** + * @private + */ + _getIndexScaleId: function() { + return this.chart.scale.id; + }, + + /** + * @private + */ + _getValueScaleId: function() { + return this.chart.scale.id; + }, + + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var line = meta.dataset; + var points = meta.data || []; + var scale = me.chart.scale; + var config = me._config; + var i, ilen; + + // Compatibility: If the properties are defined with only the old name, use those values + if (config.tension !== undefined && config.lineTension === undefined) { + config.lineTension = config.tension; + } + + // Utility + line._scale = scale; + line._datasetIndex = me.index; + // Data + line._children = points; + line._loop = true; + // Model + line._model = me._resolveDatasetElementOptions(line); + + line.pivot(); + + // Update Points + for (i = 0, ilen = points.length; i < ilen; ++i) { + me.updateElement(points[i], i, reset); + } + + // Update bezier control points + me.updateBezierControlPoints(); + + // Now pivot the point for animation + for (i = 0, ilen = points.length; i < ilen; ++i) { + points[i].pivot(); + } + }, + + updateElement: function(point, index, reset) { + var me = this; + var custom = point.custom || {}; + var dataset = me.getDataset(); + var scale = me.chart.scale; + var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]); + var options = me._resolveDataElementOptions(point, index); + var lineModel = me.getMeta().dataset._model; + var x = reset ? scale.xCenter : pointPosition.x; + var y = reset ? scale.yCenter : pointPosition.y; + + // Utility + point._scale = scale; + point._options = options; + point._datasetIndex = me.index; + point._index = index; + + // Desired view properties + point._model = { + x: x, // value not used in dataset scale, but we want a consistent API between scales + y: y, + skip: custom.skip || isNaN(x) || isNaN(y), + // Appearance + radius: options.radius, + pointStyle: options.pointStyle, + rotation: options.rotation, + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + tension: valueOrDefault$7(custom.tension, lineModel ? lineModel.tension : 0), + + // Tooltip + hitRadius: options.hitRadius + }; + }, + + /** + * @private + */ + _resolveDatasetElementOptions: function() { + var me = this; + var config = me._config; + var options = me.chart.options; + var values = core_datasetController.prototype._resolveDatasetElementOptions.apply(me, arguments); + + values.spanGaps = valueOrDefault$7(config.spanGaps, options.spanGaps); + values.tension = valueOrDefault$7(config.lineTension, options.elements.line.tension); + + return values; + }, + + updateBezierControlPoints: function() { + var me = this; + var meta = me.getMeta(); + var area = me.chart.chartArea; + var points = meta.data || []; + var i, ilen, model, controlPoints; + + // Only consider points that are drawn in case the spanGaps option is used + if (meta.dataset._model.spanGaps) { + points = points.filter(function(pt) { + return !pt._model.skip; + }); + } + + function capControlPoint(pt, min, max) { + return Math.max(Math.min(pt, max), min); + } + + for (i = 0, ilen = points.length; i < ilen; ++i) { + model = points[i]._model; + controlPoints = helpers$1.splineCurve( + helpers$1.previousItem(points, i, true)._model, + model, + helpers$1.nextItem(points, i, true)._model, + model.tension + ); + + // Prevent the bezier going outside of the bounds of the graph + model.controlPointPreviousX = capControlPoint(controlPoints.previous.x, area.left, area.right); + model.controlPointPreviousY = capControlPoint(controlPoints.previous.y, area.top, area.bottom); + model.controlPointNextX = capControlPoint(controlPoints.next.x, area.left, area.right); + model.controlPointNextY = capControlPoint(controlPoints.next.y, area.top, area.bottom); + } + }, + + setHoverStyle: function(point) { + var model = point._model; + var options = point._options; + var getHoverColor = helpers$1.getHoverColor; + + point.$previousStyle = { + backgroundColor: model.backgroundColor, + borderColor: model.borderColor, + borderWidth: model.borderWidth, + radius: model.radius + }; + + model.backgroundColor = valueOrDefault$7(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); + model.borderColor = valueOrDefault$7(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$7(options.hoverBorderWidth, options.borderWidth); + model.radius = valueOrDefault$7(options.hoverRadius, options.radius); + } +}); + +core_defaults._set('scatter', { + hover: { + mode: 'single' + }, + + scales: { + xAxes: [{ + id: 'x-axis-1', // need an ID so datasets can reference the scale + type: 'linear', // scatter should not use a category axis + position: 'bottom' + }], + yAxes: [{ + id: 'y-axis-1', + type: 'linear', + position: 'left' + }] + }, + + tooltips: { + callbacks: { + title: function() { + return ''; // doesn't make sense for scatter since data are formatted as a point + }, + label: function(item) { + return '(' + item.xLabel + ', ' + item.yLabel + ')'; + } + } + } +}); + +core_defaults._set('global', { + datasets: { + scatter: { + showLine: false + } + } +}); + +// Scatter charts use line controllers +var controller_scatter = controller_line; + +// NOTE export a map in which the key represents the controller type, not +// the class, and so must be CamelCase in order to be correctly retrieved +// by the controller in core.controller.js (`controllers[meta.type]`). + +var controllers = { + bar: controller_bar, + bubble: controller_bubble, + doughnut: controller_doughnut, + horizontalBar: controller_horizontalBar, + line: controller_line, + polarArea: controller_polarArea, + pie: controller_pie, + radar: controller_radar, + scatter: controller_scatter +}; + +/** + * Helper function to get relative position for an event + * @param {Event|IEvent} event - The event to get the position for + * @param {Chart} chart - The chart + * @returns {object} the event position + */ +function getRelativePosition(e, chart) { + if (e.native) { + return { + x: e.x, + y: e.y + }; + } + + return helpers$1.getRelativePosition(e, chart); +} + +/** + * Helper function to traverse all of the visible elements in the chart + * @param {Chart} chart - the chart + * @param {function} handler - the callback to execute for each visible item + */ +function parseVisibleItems(chart, handler) { + var metasets = chart._getSortedVisibleDatasetMetas(); + var metadata, i, j, ilen, jlen, element; + + for (i = 0, ilen = metasets.length; i < ilen; ++i) { + metadata = metasets[i].data; + for (j = 0, jlen = metadata.length; j < jlen; ++j) { + element = metadata[j]; + if (!element._view.skip) { + handler(element); + } + } + } +} + +/** + * Helper function to get the items that intersect the event position + * @param {ChartElement[]} items - elements to filter + * @param {object} position - the point to be nearest to + * @return {ChartElement[]} the nearest items + */ +function getIntersectItems(chart, position) { + var elements = []; + + parseVisibleItems(chart, function(element) { + if (element.inRange(position.x, position.y)) { + elements.push(element); + } + }); + + return elements; +} + +/** + * Helper function to get the items nearest to the event position considering all visible items in teh chart + * @param {Chart} chart - the chart to look at elements from + * @param {object} position - the point to be nearest to + * @param {boolean} intersect - if true, only consider items that intersect the position + * @param {function} distanceMetric - function to provide the distance between points + * @return {ChartElement[]} the nearest items + */ +function getNearestItems(chart, position, intersect, distanceMetric) { + var minDistance = Number.POSITIVE_INFINITY; + var nearestItems = []; + + parseVisibleItems(chart, function(element) { + if (intersect && !element.inRange(position.x, position.y)) { + return; + } + + var center = element.getCenterPoint(); + var distance = distanceMetric(position, center); + if (distance < minDistance) { + nearestItems = [element]; + minDistance = distance; + } else if (distance === minDistance) { + // Can have multiple items at the same distance in which case we sort by size + nearestItems.push(element); + } + }); + + return nearestItems; +} + +/** + * Get a distance metric function for two points based on the + * axis mode setting + * @param {string} axis - the axis mode. x|y|xy + */ +function getDistanceMetricForAxis(axis) { + var useX = axis.indexOf('x') !== -1; + var useY = axis.indexOf('y') !== -1; + + return function(pt1, pt2) { + var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0; + var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0; + return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); + }; +} + +function indexMode(chart, e, options) { + var position = getRelativePosition(e, chart); + // Default axis for index mode is 'x' to match old behaviour + options.axis = options.axis || 'x'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); + var elements = []; + + if (!items.length) { + return []; + } + + chart._getSortedVisibleDatasetMetas().forEach(function(meta) { + var element = meta.data[items[0]._index]; + + // don't count items that are skipped (null data) + if (element && !element._view.skip) { + elements.push(element); + } + }); + + return elements; +} + +/** + * @interface IInteractionOptions + */ +/** + * If true, only consider items that intersect the point + * @name IInterfaceOptions#boolean + * @type Boolean + */ + +/** + * Contains interaction related functions + * @namespace Chart.Interaction + */ +var core_interaction = { + // Helper function for different modes + modes: { + single: function(chart, e) { + var position = getRelativePosition(e, chart); + var elements = []; + + parseVisibleItems(chart, function(element) { + if (element.inRange(position.x, position.y)) { + elements.push(element); + return elements; + } + }); + + return elements.slice(0, 1); + }, + + /** + * @function Chart.Interaction.modes.label + * @deprecated since version 2.4.0 + * @todo remove at version 3 + * @private + */ + label: indexMode, + + /** + * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something + * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item + * @function Chart.Interaction.modes.index + * @since v2.4.0 + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use during interaction + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + index: indexMode, + + /** + * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something + * If the options.intersect is false, we find the nearest item and return the items in that dataset + * @function Chart.Interaction.modes.dataset + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use during interaction + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + dataset: function(chart, e, options) { + var position = getRelativePosition(e, chart); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); + + if (items.length > 0) { + items = chart.getDatasetMeta(items[0]._datasetIndex).data; + } + + return items; + }, + + /** + * @function Chart.Interaction.modes.x-axis + * @deprecated since version 2.4.0. Use index mode and intersect == true + * @todo remove at version 3 + * @private + */ + 'x-axis': function(chart, e) { + return indexMode(chart, e, {intersect: false}); + }, + + /** + * Point mode returns all elements that hit test based on the event position + * of the event + * @function Chart.Interaction.modes.intersect + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + point: function(chart, e) { + var position = getRelativePosition(e, chart); + return getIntersectItems(chart, position); + }, + + /** + * nearest mode returns the element closest to the point + * @function Chart.Interaction.modes.intersect + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + nearest: function(chart, e, options) { + var position = getRelativePosition(e, chart); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + return getNearestItems(chart, position, options.intersect, distanceMetric); + }, + + /** + * x mode returns the elements that hit-test at the current x coordinate + * @function Chart.Interaction.modes.x + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + x: function(chart, e, options) { + var position = getRelativePosition(e, chart); + var items = []; + var intersectsItem = false; + + parseVisibleItems(chart, function(element) { + if (element.inXRange(position.x)) { + items.push(element); + } + + if (element.inRange(position.x, position.y)) { + intersectsItem = true; + } + }); + + // If we want to trigger on an intersect and we don't have any items + // that intersect the position, return nothing + if (options.intersect && !intersectsItem) { + items = []; + } + return items; + }, + + /** + * y mode returns the elements that hit-test at the current y coordinate + * @function Chart.Interaction.modes.y + * @param {Chart} chart - the chart we are returning items from + * @param {Event} e - the event we are find things at + * @param {IInteractionOptions} options - options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + y: function(chart, e, options) { + var position = getRelativePosition(e, chart); + var items = []; + var intersectsItem = false; + + parseVisibleItems(chart, function(element) { + if (element.inYRange(position.y)) { + items.push(element); + } + + if (element.inRange(position.x, position.y)) { + intersectsItem = true; + } + }); + + // If we want to trigger on an intersect and we don't have any items + // that intersect the position, return nothing + if (options.intersect && !intersectsItem) { + items = []; + } + return items; + } + } +}; + +var extend = helpers$1.extend; + +function filterByPosition(array, position) { + return helpers$1.where(array, function(v) { + return v.pos === position; + }); +} + +function sortByWeight(array, reverse) { + return array.sort(function(a, b) { + var v0 = reverse ? b : a; + var v1 = reverse ? a : b; + return v0.weight === v1.weight ? + v0.index - v1.index : + v0.weight - v1.weight; + }); +} + +function wrapBoxes(boxes) { + var layoutBoxes = []; + var i, ilen, box; + + for (i = 0, ilen = (boxes || []).length; i < ilen; ++i) { + box = boxes[i]; + layoutBoxes.push({ + index: i, + box: box, + pos: box.position, + horizontal: box.isHorizontal(), + weight: box.weight + }); + } + return layoutBoxes; +} + +function setLayoutDims(layouts, params) { + var i, ilen, layout; + for (i = 0, ilen = layouts.length; i < ilen; ++i) { + layout = layouts[i]; + // store width used instead of chartArea.w in fitBoxes + layout.width = layout.horizontal + ? layout.box.fullWidth && params.availableWidth + : params.vBoxMaxWidth; + // store height used instead of chartArea.h in fitBoxes + layout.height = layout.horizontal && params.hBoxMaxHeight; + } +} + +function buildLayoutBoxes(boxes) { + var layoutBoxes = wrapBoxes(boxes); + var left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true); + var right = sortByWeight(filterByPosition(layoutBoxes, 'right')); + var top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true); + var bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom')); + + return { + leftAndTop: left.concat(top), + rightAndBottom: right.concat(bottom), + chartArea: filterByPosition(layoutBoxes, 'chartArea'), + vertical: left.concat(right), + horizontal: top.concat(bottom) + }; +} + +function getCombinedMax(maxPadding, chartArea, a, b) { + return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]); +} + +function updateDims(chartArea, params, layout) { + var box = layout.box; + var maxPadding = chartArea.maxPadding; + var newWidth, newHeight; + + if (layout.size) { + // this layout was already counted for, lets first reduce old size + chartArea[layout.pos] -= layout.size; + } + layout.size = layout.horizontal ? box.height : box.width; + chartArea[layout.pos] += layout.size; + + if (box.getPadding) { + var boxPadding = box.getPadding(); + maxPadding.top = Math.max(maxPadding.top, boxPadding.top); + maxPadding.left = Math.max(maxPadding.left, boxPadding.left); + maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom); + maxPadding.right = Math.max(maxPadding.right, boxPadding.right); + } + + newWidth = params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right'); + newHeight = params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom'); + + if (newWidth !== chartArea.w || newHeight !== chartArea.h) { + chartArea.w = newWidth; + chartArea.h = newHeight; + + // return true if chart area changed in layout's direction + return layout.horizontal ? newWidth !== chartArea.w : newHeight !== chartArea.h; + } +} + +function handleMaxPadding(chartArea) { + var maxPadding = chartArea.maxPadding; + + function updatePos(pos) { + var change = Math.max(maxPadding[pos] - chartArea[pos], 0); + chartArea[pos] += change; + return change; + } + chartArea.y += updatePos('top'); + chartArea.x += updatePos('left'); + updatePos('right'); + updatePos('bottom'); +} + +function getMargins(horizontal, chartArea) { + var maxPadding = chartArea.maxPadding; + + function marginForPositions(positions) { + var margin = {left: 0, top: 0, right: 0, bottom: 0}; + positions.forEach(function(pos) { + margin[pos] = Math.max(chartArea[pos], maxPadding[pos]); + }); + return margin; + } + + return horizontal + ? marginForPositions(['left', 'right']) + : marginForPositions(['top', 'bottom']); +} + +function fitBoxes(boxes, chartArea, params) { + var refitBoxes = []; + var i, ilen, layout, box, refit, changed; + + for (i = 0, ilen = boxes.length; i < ilen; ++i) { + layout = boxes[i]; + box = layout.box; + + box.update( + layout.width || chartArea.w, + layout.height || chartArea.h, + getMargins(layout.horizontal, chartArea) + ); + if (updateDims(chartArea, params, layout)) { + changed = true; + if (refitBoxes.length) { + // Dimensions changed and there were non full width boxes before this + // -> we have to refit those + refit = true; + } + } + if (!box.fullWidth) { // fullWidth boxes don't need to be re-fitted in any case + refitBoxes.push(layout); + } + } + + return refit ? fitBoxes(refitBoxes, chartArea, params) || changed : changed; +} + +function placeBoxes(boxes, chartArea, params) { + var userPadding = params.padding; + var x = chartArea.x; + var y = chartArea.y; + var i, ilen, layout, box; + + for (i = 0, ilen = boxes.length; i < ilen; ++i) { + layout = boxes[i]; + box = layout.box; + if (layout.horizontal) { + box.left = box.fullWidth ? userPadding.left : chartArea.left; + box.right = box.fullWidth ? params.outerWidth - userPadding.right : chartArea.left + chartArea.w; + box.top = y; + box.bottom = y + box.height; + box.width = box.right - box.left; + y = box.bottom; + } else { + box.left = x; + box.right = x + box.width; + box.top = chartArea.top; + box.bottom = chartArea.top + chartArea.h; + box.height = box.bottom - box.top; + x = box.right; + } + } + + chartArea.x = x; + chartArea.y = y; +} + +core_defaults._set('global', { + layout: { + padding: { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } +}); + +/** + * @interface ILayoutItem + * @prop {string} position - The position of the item in the chart layout. Possible values are + * 'left', 'top', 'right', 'bottom', and 'chartArea' + * @prop {number} weight - The weight used to sort the item. Higher weights are further away from the chart area + * @prop {boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down + * @prop {function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom) + * @prop {function} update - Takes two parameters: width and height. Returns size of item + * @prop {function} getPadding - Returns an object with padding on the edges + * @prop {number} width - Width of item. Must be valid after update() + * @prop {number} height - Height of item. Must be valid after update() + * @prop {number} left - Left edge of the item. Set by layout system and cannot be used in update + * @prop {number} top - Top edge of the item. Set by layout system and cannot be used in update + * @prop {number} right - Right edge of the item. Set by layout system and cannot be used in update + * @prop {number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update + */ + +// The layout service is very self explanatory. It's responsible for the layout within a chart. +// Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need +// It is this service's responsibility of carrying out that layout. +var core_layouts = { + defaults: {}, + + /** + * Register a box to a chart. + * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title. + * @param {Chart} chart - the chart to use + * @param {ILayoutItem} item - the item to add to be layed out + */ + addBox: function(chart, item) { + if (!chart.boxes) { + chart.boxes = []; + } + + // initialize item with default values + item.fullWidth = item.fullWidth || false; + item.position = item.position || 'top'; + item.weight = item.weight || 0; + item._layers = item._layers || function() { + return [{ + z: 0, + draw: function() { + item.draw.apply(item, arguments); + } + }]; + }; + + chart.boxes.push(item); + }, + + /** + * Remove a layoutItem from a chart + * @param {Chart} chart - the chart to remove the box from + * @param {ILayoutItem} layoutItem - the item to remove from the layout + */ + removeBox: function(chart, layoutItem) { + var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1; + if (index !== -1) { + chart.boxes.splice(index, 1); + } + }, + + /** + * Sets (or updates) options on the given `item`. + * @param {Chart} chart - the chart in which the item lives (or will be added to) + * @param {ILayoutItem} item - the item to configure with the given options + * @param {object} options - the new item options. + */ + configure: function(chart, item, options) { + var props = ['fullWidth', 'position', 'weight']; + var ilen = props.length; + var i = 0; + var prop; + + for (; i < ilen; ++i) { + prop = props[i]; + if (options.hasOwnProperty(prop)) { + item[prop] = options[prop]; + } + } + }, + + /** + * Fits boxes of the given chart into the given size by having each box measure itself + * then running a fitting algorithm + * @param {Chart} chart - the chart + * @param {number} width - the width to fit into + * @param {number} height - the height to fit into + */ + update: function(chart, width, height) { + if (!chart) { + return; + } + + var layoutOptions = chart.options.layout || {}; + var padding = helpers$1.options.toPadding(layoutOptions.padding); + + var availableWidth = width - padding.width; + var availableHeight = height - padding.height; + var boxes = buildLayoutBoxes(chart.boxes); + var verticalBoxes = boxes.vertical; + var horizontalBoxes = boxes.horizontal; + + // Essentially we now have any number of boxes on each of the 4 sides. + // Our canvas looks like the following. + // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and + // B1 is the bottom axis + // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays + // These locations are single-box locations only, when trying to register a chartArea location that is already taken, + // an error will be thrown. + // + // |----------------------------------------------------| + // | T1 (Full Width) | + // |----------------------------------------------------| + // | | | T2 | | + // | |----|-------------------------------------|----| + // | | | C1 | | C2 | | + // | | |----| |----| | + // | | | | | + // | L1 | L2 | ChartArea (C0) | R1 | + // | | | | | + // | | |----| |----| | + // | | | C3 | | C4 | | + // | |----|-------------------------------------|----| + // | | | B1 | | + // |----------------------------------------------------| + // | B2 (Full Width) | + // |----------------------------------------------------| + // + + var params = Object.freeze({ + outerWidth: width, + outerHeight: height, + padding: padding, + availableWidth: availableWidth, + vBoxMaxWidth: availableWidth / 2 / verticalBoxes.length, + hBoxMaxHeight: availableHeight / 2 + }); + var chartArea = extend({ + maxPadding: extend({}, padding), + w: availableWidth, + h: availableHeight, + x: padding.left, + y: padding.top + }, padding); + + setLayoutDims(verticalBoxes.concat(horizontalBoxes), params); + + // First fit vertical boxes + fitBoxes(verticalBoxes, chartArea, params); + + // Then fit horizontal boxes + if (fitBoxes(horizontalBoxes, chartArea, params)) { + // if the area changed, re-fit vertical boxes + fitBoxes(verticalBoxes, chartArea, params); + } + + handleMaxPadding(chartArea); + + // Finally place the boxes to correct coordinates + placeBoxes(boxes.leftAndTop, chartArea, params); + + // Move to opposite side of chart + chartArea.x += chartArea.w; + chartArea.y += chartArea.h; + + placeBoxes(boxes.rightAndBottom, chartArea, params); + + chart.chartArea = { + left: chartArea.left, + top: chartArea.top, + right: chartArea.left + chartArea.w, + bottom: chartArea.top + chartArea.h + }; + + // Finally update boxes in chartArea (radial scale for example) + helpers$1.each(boxes.chartArea, function(layout) { + var box = layout.box; + extend(box, chart.chartArea); + box.update(chartArea.w, chartArea.h); + }); + } +}; + +/** + * Platform fallback implementation (minimal). + * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939 + */ + +var platform_basic = { + acquireContext: function(item) { + if (item && item.canvas) { + // Support for any object associated to a canvas (including a context2d) + item = item.canvas; + } + + return item && item.getContext('2d') || null; + } +}; + +var platform_dom = "/*\n * DOM element rendering detection\n * https://davidwalsh.name/detect-node-insertion\n */\n@keyframes chartjs-render-animation {\n\tfrom { opacity: 0.99; }\n\tto { opacity: 1; }\n}\n\n.chartjs-render-monitor {\n\tanimation: chartjs-render-animation 0.001s;\n}\n\n/*\n * DOM element resizing detection\n * https://github.com/marcj/css-element-queries\n */\n.chartjs-size-monitor,\n.chartjs-size-monitor-expand,\n.chartjs-size-monitor-shrink {\n\tposition: absolute;\n\tdirection: ltr;\n\tleft: 0;\n\ttop: 0;\n\tright: 0;\n\tbottom: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n\tvisibility: hidden;\n\tz-index: -1;\n}\n\n.chartjs-size-monitor-expand > div {\n\tposition: absolute;\n\twidth: 1000000px;\n\theight: 1000000px;\n\tleft: 0;\n\ttop: 0;\n}\n\n.chartjs-size-monitor-shrink > div {\n\tposition: absolute;\n\twidth: 200%;\n\theight: 200%;\n\tleft: 0;\n\ttop: 0;\n}\n"; + +var platform_dom$1 = /*#__PURE__*/Object.freeze({ +__proto__: null, +'default': platform_dom +}); + +var stylesheet = getCjsExportFromNamespace(platform_dom$1); + +var EXPANDO_KEY = '$chartjs'; +var CSS_PREFIX = 'chartjs-'; +var CSS_SIZE_MONITOR = CSS_PREFIX + 'size-monitor'; +var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor'; +var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation'; +var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart']; + +/** + * DOM event types -> Chart.js event types. + * Note: only events with different types are mapped. + * @see https://developer.mozilla.org/en-US/docs/Web/Events + */ +var EVENT_TYPES = { + touchstart: 'mousedown', + touchmove: 'mousemove', + touchend: 'mouseup', + pointerenter: 'mouseenter', + pointerdown: 'mousedown', + pointermove: 'mousemove', + pointerup: 'mouseup', + pointerleave: 'mouseout', + pointerout: 'mouseout' +}; + +/** + * The "used" size is the final value of a dimension property after all calculations have + * been performed. This method uses the computed style of `element` but returns undefined + * if the computed style is not expressed in pixels. That can happen in some cases where + * `element` has a size relative to its parent and this last one is not yet displayed, + * for example because of `display: none` on a parent node. + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value + * @returns {number} Size in pixels or undefined if unknown. + */ +function readUsedSize(element, property) { + var value = helpers$1.getStyle(element, property); + var matches = value && value.match(/^(\d+)(\.\d+)?px$/); + return matches ? Number(matches[1]) : undefined; +} + +/** + * Initializes the canvas style and render size without modifying the canvas display size, + * since responsiveness is handled by the controller.resize() method. The config is used + * to determine the aspect ratio to apply in case no explicit height has been specified. + */ +function initCanvas(canvas, config) { + var style = canvas.style; + + // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it + // returns null or '' if no explicit value has been set to the canvas attribute. + var renderHeight = canvas.getAttribute('height'); + var renderWidth = canvas.getAttribute('width'); + + // Chart.js modifies some canvas values that we want to restore on destroy + canvas[EXPANDO_KEY] = { + initial: { + height: renderHeight, + width: renderWidth, + style: { + display: style.display, + height: style.height, + width: style.width + } + } + }; + + // Force canvas to display as block to avoid extra space caused by inline + // elements, which would interfere with the responsive resize process. + // https://github.com/chartjs/Chart.js/issues/2538 + style.display = style.display || 'block'; + + if (renderWidth === null || renderWidth === '') { + var displayWidth = readUsedSize(canvas, 'width'); + if (displayWidth !== undefined) { + canvas.width = displayWidth; + } + } + + if (renderHeight === null || renderHeight === '') { + if (canvas.style.height === '') { + // If no explicit render height and style height, let's apply the aspect ratio, + // which one can be specified by the user but also by charts as default option + // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2. + canvas.height = canvas.width / (config.options.aspectRatio || 2); + } else { + var displayHeight = readUsedSize(canvas, 'height'); + if (displayWidth !== undefined) { + canvas.height = displayHeight; + } + } + } + + return canvas; +} + +/** + * Detects support for options object argument in addEventListener. + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support + * @private + */ +var supportsEventListenerOptions = (function() { + var supports = false; + try { + var options = Object.defineProperty({}, 'passive', { + // eslint-disable-next-line getter-return + get: function() { + supports = true; + } + }); + window.addEventListener('e', null, options); + } catch (e) { + // continue regardless of error + } + return supports; +}()); + +// Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events. +// https://github.com/chartjs/Chart.js/issues/4287 +var eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false; + +function addListener(node, type, listener) { + node.addEventListener(type, listener, eventListenerOptions); +} + +function removeListener(node, type, listener) { + node.removeEventListener(type, listener, eventListenerOptions); +} + +function createEvent(type, chart, x, y, nativeEvent) { + return { + type: type, + chart: chart, + native: nativeEvent || null, + x: x !== undefined ? x : null, + y: y !== undefined ? y : null, + }; +} + +function fromNativeEvent(event, chart) { + var type = EVENT_TYPES[event.type] || event.type; + var pos = helpers$1.getRelativePosition(event, chart); + return createEvent(type, chart, pos.x, pos.y, event); +} + +function throttled(fn, thisArg) { + var ticking = false; + var args = []; + + return function() { + args = Array.prototype.slice.call(arguments); + thisArg = thisArg || this; + + if (!ticking) { + ticking = true; + helpers$1.requestAnimFrame.call(window, function() { + ticking = false; + fn.apply(thisArg, args); + }); + } + }; +} + +function createDiv(cls) { + var el = document.createElement('div'); + el.className = cls || ''; + return el; +} + +// Implementation based on https://github.com/marcj/css-element-queries +function createResizer(handler) { + var maxSize = 1000000; + + // NOTE(SB) Don't use innerHTML because it could be considered unsafe. + // https://github.com/chartjs/Chart.js/issues/5902 + var resizer = createDiv(CSS_SIZE_MONITOR); + var expand = createDiv(CSS_SIZE_MONITOR + '-expand'); + var shrink = createDiv(CSS_SIZE_MONITOR + '-shrink'); + + expand.appendChild(createDiv()); + shrink.appendChild(createDiv()); + + resizer.appendChild(expand); + resizer.appendChild(shrink); + resizer._reset = function() { + expand.scrollLeft = maxSize; + expand.scrollTop = maxSize; + shrink.scrollLeft = maxSize; + shrink.scrollTop = maxSize; + }; + + var onScroll = function() { + resizer._reset(); + handler(); + }; + + addListener(expand, 'scroll', onScroll.bind(expand, 'expand')); + addListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink')); + + return resizer; +} + +// https://davidwalsh.name/detect-node-insertion +function watchForRender(node, handler) { + var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); + var proxy = expando.renderProxy = function(e) { + if (e.animationName === CSS_RENDER_ANIMATION) { + handler(); + } + }; + + helpers$1.each(ANIMATION_START_EVENTS, function(type) { + addListener(node, type, proxy); + }); + + // #4737: Chrome might skip the CSS animation when the CSS_RENDER_MONITOR class + // is removed then added back immediately (same animation frame?). Accessing the + // `offsetParent` property will force a reflow and re-evaluate the CSS animation. + // https://gist.github.com/paulirish/5d52fb081b3570c81e3a#box-metrics + // https://github.com/chartjs/Chart.js/issues/4737 + expando.reflow = !!node.offsetParent; + + node.classList.add(CSS_RENDER_MONITOR); +} + +function unwatchForRender(node) { + var expando = node[EXPANDO_KEY] || {}; + var proxy = expando.renderProxy; + + if (proxy) { + helpers$1.each(ANIMATION_START_EVENTS, function(type) { + removeListener(node, type, proxy); + }); + + delete expando.renderProxy; + } + + node.classList.remove(CSS_RENDER_MONITOR); +} + +function addResizeListener(node, listener, chart) { + var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); + + // Let's keep track of this added resizer and thus avoid DOM query when removing it. + var resizer = expando.resizer = createResizer(throttled(function() { + if (expando.resizer) { + var container = chart.options.maintainAspectRatio && node.parentNode; + var w = container ? container.clientWidth : 0; + listener(createEvent('resize', chart)); + if (container && container.clientWidth < w && chart.canvas) { + // If the container size shrank during chart resize, let's assume + // scrollbar appeared. So we resize again with the scrollbar visible - + // effectively making chart smaller and the scrollbar hidden again. + // Because we are inside `throttled`, and currently `ticking`, scroll + // events are ignored during this whole 2 resize process. + // If we assumed wrong and something else happened, we are resizing + // twice in a frame (potential performance issue) + listener(createEvent('resize', chart)); + } + } + })); + + // The resizer needs to be attached to the node parent, so we first need to be + // sure that `node` is attached to the DOM before injecting the resizer element. + watchForRender(node, function() { + if (expando.resizer) { + var container = node.parentNode; + if (container && container !== resizer.parentNode) { + container.insertBefore(resizer, container.firstChild); + } + + // The container size might have changed, let's reset the resizer state. + resizer._reset(); + } + }); +} + +function removeResizeListener(node) { + var expando = node[EXPANDO_KEY] || {}; + var resizer = expando.resizer; + + delete expando.resizer; + unwatchForRender(node); + + if (resizer && resizer.parentNode) { + resizer.parentNode.removeChild(resizer); + } +} + +/** + * Injects CSS styles inline if the styles are not already present. + * @param {HTMLDocument|ShadowRoot} rootNode - the node to contain the