From a587443ea7dfb79313af1090b52b9617eff7bbfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E5=AD=90=E6=A5=9A=5Czhuzi?= Date: Mon, 18 Mar 2024 17:07:44 +0800 Subject: [PATCH] update --- CMakeLists.txt | 1 + example/CMakeLists.txt | 107 +- example/README.md | 18 + example/example_en_US.ts | 536 +- example/example_zh_CN.ts | 526 +- example/qml-Qt6/App.qml | 59 - example/qml-Qt6/chart/T_BarChart.qml | 132 - example/qml-Qt6/chart/T_BubbleChart.qml | 74 - example/qml-Qt6/chart/T_LineChart.qml | 45 - example/qml-Qt6/chart/T_PieChart.qml | 93 - example/qml-Qt6/chart/T_PolarAreaChart.qml | 57 - example/qml-Qt6/chart/T_RadarChart.qml | 74 - example/qml-Qt6/chart/T_ScatterChart.qml | 123 - example/qml-Qt6/component/CodeExpander.qml | 144 - example/qml-Qt6/global/ItemsFooter.qml | 33 - example/qml-Qt6/global/ItemsOriginal.qml | 532 - example/qml-Qt6/global/qmldir | 2 - example/qml-Qt6/page/T_3D.qml | 117 - example/qml-Qt6/page/T_Acrylic.qml | 115 - example/qml-Qt6/page/T_Awesome.qml | 71 - example/qml-Qt6/page/T_Badge.qml | 131 - example/qml-Qt6/page/T_BreadcrumbBar.qml | 93 - example/qml-Qt6/page/T_Buttons.qml | 438 - example/qml-Qt6/page/T_CalendarPicker.qml | 37 - example/qml-Qt6/page/T_Captcha.qml | 60 - example/qml-Qt6/page/T_Carousel.qml | 147 - example/qml-Qt6/page/T_CheckBox.qml | 114 - example/qml-Qt6/page/T_Clip.qml | 106 - example/qml-Qt6/page/T_ColorPicker.qml | 43 - example/qml-Qt6/page/T_ComboBox.qml | 104 - example/qml-Qt6/page/T_DatePicker.qml | 75 - example/qml-Qt6/page/T_Dialog.qml | 232 - example/qml-Qt6/page/T_Expander.qml | 110 - example/qml-Qt6/page/T_FlipView.qml | 117 - example/qml-Qt6/page/T_Home.qml | 294 - example/qml-Qt6/page/T_Image.qml | 48 - example/qml-Qt6/page/T_InfoBar.qml | 72 - example/qml-Qt6/page/T_Menu.qml | 171 - example/qml-Qt6/page/T_MultiWindow.qml | 186 - example/qml-Qt6/page/T_Network.qml | 560 - example/qml-Qt6/page/T_Pagination.qml | 49 - example/qml-Qt6/page/T_Pivot.qml | 82 - example/qml-Qt6/page/T_Progress.qml | 103 - example/qml-Qt6/page/T_QRCode.qml | 102 - example/qml-Qt6/page/T_RadioButton.qml | 101 - example/qml-Qt6/page/T_RatingControl.qml | 35 - example/qml-Qt6/page/T_Rectangle.qml | 74 - example/qml-Qt6/page/T_RemoteLoader.qml | 14 - example/qml-Qt6/page/T_Settings.qml | 205 - example/qml-Qt6/page/T_ShortcutPicker.qml | 30 - example/qml-Qt6/page/T_Slider.qml | 59 - example/qml-Qt6/page/T_SplitLayout.qml | 84 - example/qml-Qt6/page/T_StaggeredLayout.qml | 58 - example/qml-Qt6/page/T_StatusLayout.qml | 90 - example/qml-Qt6/page/T_TabView.qml | 129 - example/qml-Qt6/page/T_TableView.qml | 589 - example/qml-Qt6/page/T_Text.qml | 32 - example/qml-Qt6/page/T_TextBox.qml | 203 - example/qml-Qt6/page/T_Theme.qml | 136 - example/qml-Qt6/page/T_TimePicker.qml | 92 - example/qml-Qt6/page/T_Timeline.qml | 171 - 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 | 131 - example/qml-Qt6/page/T_Typography.qml | 84 - example/qml-Qt6/page/T_Watermark.qml | 131 - .../qml-Qt6/viewmodel/SettingsViewModel.qml | 14 - .../qml-Qt6/viewmodel/TextBoxViewModel.qml | 8 - example/qml-Qt6/window/AboutWindow.qml | 165 - example/qml-Qt6/window/CrashWindow.qml | 79 - .../qml-Qt6/window/FluentInitalizrWindow.qml | 113 - example/qml-Qt6/window/HotloadWindow.qml | 97 - example/qml-Qt6/window/LoginWindow.qml | 59 - example/qml-Qt6/window/MainWindow.qml | 395 - example/qml-Qt6/window/PageWindow.qml | 25 - .../qml-Qt6/window/SingleInstanceWindow.qml | 35 - example/qml-Qt6/window/SingleTaskWindow.qml | 21 - example/qml-Qt6/window/StandardWindow.qml | 43 - example/qml/window/MainWindow.qml | 1 + example/res/template/src/CMakeLists.txt.in | 13 +- example/res/template/src/README.md.in | 18 + src/CMakeLists.txt | 8 +- src/FluTheme.cpp | 16 - src/FluentUI/Controls/FluAcrylic.qml | 41 + src/FluentUI/Controls/FluAppBar.qml | 347 + src/FluentUI/Controls/FluArea.qml | 28 + src/FluentUI/Controls/FluAutoSuggestBox.qml | 139 + src/FluentUI/Controls/FluBadge.qml | 79 + src/FluentUI/Controls/FluBreadcrumbBar.qml | 92 + src/FluentUI/Controls/FluButton.qml | 65 + src/FluentUI/Controls/FluCalendarPicker.qml | 661 + src/FluentUI/Controls/FluCarousel.qml | 206 + src/FluentUI/Controls/FluChart.qml | 117 + src/FluentUI/Controls/FluCheckBox.qml | 138 + src/FluentUI/Controls/FluClip.qml | 20 + src/FluentUI/Controls/FluColorPicker.qml | 589 + src/FluentUI/Controls/FluComboBox.qml | 146 + src/FluentUI/Controls/FluContentDialog.qml | 163 + src/FluentUI/Controls/FluContentPage.qml | 60 + src/FluentUI/Controls/FluControl.qml | 28 + src/FluentUI/Controls/FluCopyableText.qml | 35 + src/FluentUI/Controls/FluDatePicker.qml | 415 + src/FluentUI/Controls/FluDivider.qml | 34 + src/FluentUI/Controls/FluDropDownButton.qml | 96 + src/FluentUI/Controls/FluExpander.qml | 133 + src/FluentUI/Controls/FluFilledButton.qml | 72 + src/FluentUI/Controls/FluFlipView.qml | 107 + src/FluentUI/Controls/FluFocusRectangle.qml | 19 + src/FluentUI/Controls/FluIcon.qml | 19 + src/FluentUI/Controls/FluIconButton.qml | 130 + src/FluentUI/Controls/FluImage.qml | 48 + src/FluentUI/Controls/FluImageButton.qml | 18 + src/FluentUI/Controls/FluInfoBar.qml | 252 + src/FluentUI/Controls/FluItemDelegate.qml | 39 + src/FluentUI/Controls/FluLoader.qml | 5 + src/FluentUI/Controls/FluLoadingButton.qml | 41 + src/FluentUI/Controls/FluMenu.qml | 59 + src/FluentUI/Controls/FluMenuBar.qml | 21 + src/FluentUI/Controls/FluMenuBarItem.qml | 61 + src/FluentUI/Controls/FluMenuItem.qml | 111 + src/FluentUI/Controls/FluMenuSeparator.qml | 19 + src/FluentUI/Controls/FluMultilineTextBox.qml | 82 + src/FluentUI/Controls/FluNavigationView.qml | 1344 + src/FluentUI/Controls/FluObject.qml | 8 + src/FluentUI/Controls/FluPage.qml | 43 + src/FluentUI/Controls/FluPagination.qml | 100 + src/FluentUI/Controls/FluPaneItem.qml | 25 + src/FluentUI/Controls/FluPaneItemEmpty.qml | 11 + src/FluentUI/Controls/FluPaneItemExpander.qml | 18 + src/FluentUI/Controls/FluPaneItemHeader.qml | 11 + .../Controls/FluPaneItemSeparator.qml | 12 + src/FluentUI/Controls/FluPasswordBox.qml | 73 + src/FluentUI/Controls/FluPivot.qml | 95 + src/FluentUI/Controls/FluPivotItem.qml | 9 + src/FluentUI/Controls/FluPopup.qml | 54 + src/FluentUI/Controls/FluProgressBar.qml | 69 + src/FluentUI/Controls/FluProgressButton.qml | 136 + src/FluentUI/Controls/FluProgressRing.qml | 93 + src/FluentUI/Controls/FluQRCode.qml | 23 + src/FluentUI/Controls/FluRadioButton.qml | 94 + src/FluentUI/Controls/FluRadioButtons.qml | 33 + src/FluentUI/Controls/FluRangeSlider.qml | 118 + src/FluentUI/Controls/FluRatingControl.qml | 54 + src/FluentUI/Controls/FluRemoteLoader.qml | 39 + src/FluentUI/Controls/FluScrollBar.qml | 187 + src/FluentUI/Controls/FluScrollIndicator.qml | 49 + src/FluentUI/Controls/FluScrollablePage.qml | 79 + src/FluentUI/Controls/FluShadow.qml | 24 + src/FluentUI/Controls/FluShortcutPicker.qml | 235 + src/FluentUI/Controls/FluSlider.qml | 75 + src/FluentUI/Controls/FluSpinBox.qml | 160 + src/FluentUI/Controls/FluSplitLayout.qml | 30 + src/FluentUI/Controls/FluStaggeredLayout.qml | 68 + src/FluentUI/Controls/FluStatusLayout.qml | 116 + src/FluentUI/Controls/FluTabView.qml | 299 + src/FluentUI/Controls/FluTableView.qml | 849 + src/FluentUI/Controls/FluText.qml | 11 + src/FluentUI/Controls/FluTextBox.qml | 119 + .../Controls/FluTextBoxBackground.qml | 56 + src/FluentUI/Controls/FluTextBoxMenu.qml | 104 + src/FluentUI/Controls/FluTextButton.qml | 65 + src/FluentUI/Controls/FluTimePicker.qml | 429 + src/FluentUI/Controls/FluTimeline.qml | 309 + src/FluentUI/Controls/FluToggleButton.qml | 124 + src/FluentUI/Controls/FluToggleSwitch.qml | 121 + src/FluentUI/Controls/FluTooltip.qml | 30 + src/FluentUI/Controls/FluTour.qml | 250 + src/FluentUI/Controls/FluTreeView.qml | 440 + src/FluentUI/Controls/FluWindow.qml | 320 + src/FluentUI/Controls/FluWindowDialog.qml | 33 + src/FluentUI/Font/Segoe_Fluent_Icons.ttf | Bin 0 -> 408752 bytes src/FluentUI/Image/btn_close_hovered.png | Bin 0 -> 10314 bytes src/FluentUI/Image/btn_close_normal.png | Bin 0 -> 10096 bytes src/FluentUI/Image/btn_close_pushed.png | Bin 0 -> 10276 bytes src/FluentUI/Image/btn_max_hovered.png | Bin 0 -> 10301 bytes src/FluentUI/Image/btn_max_normal.png | Bin 0 -> 10128 bytes src/FluentUI/Image/btn_max_pushed.png | Bin 0 -> 10412 bytes src/FluentUI/Image/btn_min_hovered.png | Bin 0 -> 10143 bytes src/FluentUI/Image/btn_min_normal.png | Bin 0 -> 10083 bytes src/FluentUI/Image/btn_min_pushed.png | Bin 0 -> 10260 bytes src/FluentUI/Image/noise.png | Bin 0 -> 271829 bytes src/FluentUI/JS/Chart.js | 20822 ++++++++++++++++ src/FluentUI/fluentui_qml_module_dir_map.qrc | 6 + src/FluentUI/fluentuiplugin.lib | Bin 0 -> 142822 bytes src/FluentUI/plugins.qmltypes | 2748 ++ src/FluentUI/qmldir | 94 + src/Qt5/imports/FluentUI/Controls/FluArea.qml | 4 +- .../imports/FluentUI/Controls/FluWindow.qml | 4 +- src/Qt6/imports/FluentUI/Controls/FluArea.qml | 4 +- .../imports/FluentUI/Controls/FluWindow.qml | 4 +- src/fluentui_en_US.ts | 241 + src/fluentui_zh_CN.ts | 241 + 193 files changed, 36086 insertions(+), 9986 deletions(-) create mode 100644 example/README.md delete mode 100644 example/qml-Qt6/App.qml delete mode 100644 example/qml-Qt6/chart/T_BarChart.qml delete mode 100644 example/qml-Qt6/chart/T_BubbleChart.qml delete mode 100644 example/qml-Qt6/chart/T_LineChart.qml delete mode 100644 example/qml-Qt6/chart/T_PieChart.qml delete mode 100644 example/qml-Qt6/chart/T_PolarAreaChart.qml delete mode 100644 example/qml-Qt6/chart/T_RadarChart.qml delete mode 100644 example/qml-Qt6/chart/T_ScatterChart.qml delete mode 100644 example/qml-Qt6/component/CodeExpander.qml delete mode 100644 example/qml-Qt6/global/ItemsFooter.qml delete mode 100644 example/qml-Qt6/global/ItemsOriginal.qml delete mode 100644 example/qml-Qt6/global/qmldir delete mode 100644 example/qml-Qt6/page/T_3D.qml delete mode 100644 example/qml-Qt6/page/T_Acrylic.qml delete mode 100644 example/qml-Qt6/page/T_Awesome.qml delete mode 100644 example/qml-Qt6/page/T_Badge.qml delete mode 100644 example/qml-Qt6/page/T_BreadcrumbBar.qml delete mode 100644 example/qml-Qt6/page/T_Buttons.qml delete mode 100644 example/qml-Qt6/page/T_CalendarPicker.qml delete mode 100644 example/qml-Qt6/page/T_Captcha.qml delete mode 100644 example/qml-Qt6/page/T_Carousel.qml delete mode 100644 example/qml-Qt6/page/T_CheckBox.qml delete mode 100644 example/qml-Qt6/page/T_Clip.qml delete mode 100644 example/qml-Qt6/page/T_ColorPicker.qml delete mode 100644 example/qml-Qt6/page/T_ComboBox.qml delete mode 100644 example/qml-Qt6/page/T_DatePicker.qml delete mode 100644 example/qml-Qt6/page/T_Dialog.qml delete mode 100644 example/qml-Qt6/page/T_Expander.qml delete mode 100644 example/qml-Qt6/page/T_FlipView.qml delete mode 100644 example/qml-Qt6/page/T_Home.qml delete mode 100644 example/qml-Qt6/page/T_Image.qml delete mode 100644 example/qml-Qt6/page/T_InfoBar.qml delete mode 100644 example/qml-Qt6/page/T_Menu.qml delete mode 100644 example/qml-Qt6/page/T_MultiWindow.qml delete mode 100644 example/qml-Qt6/page/T_Network.qml delete mode 100644 example/qml-Qt6/page/T_Pagination.qml delete mode 100644 example/qml-Qt6/page/T_Pivot.qml delete mode 100644 example/qml-Qt6/page/T_Progress.qml delete mode 100644 example/qml-Qt6/page/T_QRCode.qml delete mode 100644 example/qml-Qt6/page/T_RadioButton.qml delete mode 100644 example/qml-Qt6/page/T_RatingControl.qml delete mode 100644 example/qml-Qt6/page/T_Rectangle.qml delete mode 100644 example/qml-Qt6/page/T_RemoteLoader.qml delete mode 100644 example/qml-Qt6/page/T_Settings.qml delete mode 100644 example/qml-Qt6/page/T_ShortcutPicker.qml delete mode 100644 example/qml-Qt6/page/T_Slider.qml delete mode 100644 example/qml-Qt6/page/T_SplitLayout.qml delete mode 100644 example/qml-Qt6/page/T_StaggeredLayout.qml delete mode 100644 example/qml-Qt6/page/T_StatusLayout.qml delete mode 100644 example/qml-Qt6/page/T_TabView.qml delete mode 100644 example/qml-Qt6/page/T_TableView.qml delete mode 100644 example/qml-Qt6/page/T_Text.qml delete mode 100644 example/qml-Qt6/page/T_TextBox.qml delete mode 100644 example/qml-Qt6/page/T_Theme.qml delete mode 100644 example/qml-Qt6/page/T_TimePicker.qml delete mode 100644 example/qml-Qt6/page/T_Timeline.qml delete mode 100644 example/qml-Qt6/page/T_ToggleSwitch.qml delete mode 100644 example/qml-Qt6/page/T_Tooltip.qml delete mode 100644 example/qml-Qt6/page/T_Tour.qml delete mode 100644 example/qml-Qt6/page/T_TreeView.qml delete mode 100644 example/qml-Qt6/page/T_Typography.qml delete mode 100644 example/qml-Qt6/page/T_Watermark.qml delete mode 100644 example/qml-Qt6/viewmodel/SettingsViewModel.qml delete mode 100644 example/qml-Qt6/viewmodel/TextBoxViewModel.qml delete mode 100644 example/qml-Qt6/window/AboutWindow.qml delete mode 100644 example/qml-Qt6/window/CrashWindow.qml delete mode 100644 example/qml-Qt6/window/FluentInitalizrWindow.qml delete mode 100644 example/qml-Qt6/window/HotloadWindow.qml delete mode 100644 example/qml-Qt6/window/LoginWindow.qml delete mode 100644 example/qml-Qt6/window/MainWindow.qml delete mode 100644 example/qml-Qt6/window/PageWindow.qml delete mode 100644 example/qml-Qt6/window/SingleInstanceWindow.qml delete mode 100644 example/qml-Qt6/window/SingleTaskWindow.qml delete mode 100644 example/qml-Qt6/window/StandardWindow.qml create mode 100644 example/res/template/src/README.md.in create mode 100644 src/FluentUI/Controls/FluAcrylic.qml create mode 100644 src/FluentUI/Controls/FluAppBar.qml create mode 100644 src/FluentUI/Controls/FluArea.qml create mode 100644 src/FluentUI/Controls/FluAutoSuggestBox.qml create mode 100644 src/FluentUI/Controls/FluBadge.qml create mode 100644 src/FluentUI/Controls/FluBreadcrumbBar.qml create mode 100644 src/FluentUI/Controls/FluButton.qml create mode 100644 src/FluentUI/Controls/FluCalendarPicker.qml create mode 100644 src/FluentUI/Controls/FluCarousel.qml create mode 100644 src/FluentUI/Controls/FluChart.qml create mode 100644 src/FluentUI/Controls/FluCheckBox.qml create mode 100644 src/FluentUI/Controls/FluClip.qml create mode 100644 src/FluentUI/Controls/FluColorPicker.qml create mode 100644 src/FluentUI/Controls/FluComboBox.qml create mode 100644 src/FluentUI/Controls/FluContentDialog.qml create mode 100644 src/FluentUI/Controls/FluContentPage.qml create mode 100644 src/FluentUI/Controls/FluControl.qml create mode 100644 src/FluentUI/Controls/FluCopyableText.qml create mode 100644 src/FluentUI/Controls/FluDatePicker.qml create mode 100644 src/FluentUI/Controls/FluDivider.qml create mode 100644 src/FluentUI/Controls/FluDropDownButton.qml create mode 100644 src/FluentUI/Controls/FluExpander.qml create mode 100644 src/FluentUI/Controls/FluFilledButton.qml create mode 100644 src/FluentUI/Controls/FluFlipView.qml create mode 100644 src/FluentUI/Controls/FluFocusRectangle.qml create mode 100644 src/FluentUI/Controls/FluIcon.qml create mode 100644 src/FluentUI/Controls/FluIconButton.qml create mode 100644 src/FluentUI/Controls/FluImage.qml create mode 100644 src/FluentUI/Controls/FluImageButton.qml create mode 100644 src/FluentUI/Controls/FluInfoBar.qml create mode 100644 src/FluentUI/Controls/FluItemDelegate.qml create mode 100644 src/FluentUI/Controls/FluLoader.qml create mode 100644 src/FluentUI/Controls/FluLoadingButton.qml create mode 100644 src/FluentUI/Controls/FluMenu.qml create mode 100644 src/FluentUI/Controls/FluMenuBar.qml create mode 100644 src/FluentUI/Controls/FluMenuBarItem.qml create mode 100644 src/FluentUI/Controls/FluMenuItem.qml create mode 100644 src/FluentUI/Controls/FluMenuSeparator.qml create mode 100644 src/FluentUI/Controls/FluMultilineTextBox.qml create mode 100644 src/FluentUI/Controls/FluNavigationView.qml create mode 100644 src/FluentUI/Controls/FluObject.qml create mode 100644 src/FluentUI/Controls/FluPage.qml create mode 100644 src/FluentUI/Controls/FluPagination.qml create mode 100644 src/FluentUI/Controls/FluPaneItem.qml create mode 100644 src/FluentUI/Controls/FluPaneItemEmpty.qml create mode 100644 src/FluentUI/Controls/FluPaneItemExpander.qml create mode 100644 src/FluentUI/Controls/FluPaneItemHeader.qml create mode 100644 src/FluentUI/Controls/FluPaneItemSeparator.qml create mode 100644 src/FluentUI/Controls/FluPasswordBox.qml create mode 100644 src/FluentUI/Controls/FluPivot.qml create mode 100644 src/FluentUI/Controls/FluPivotItem.qml create mode 100644 src/FluentUI/Controls/FluPopup.qml create mode 100644 src/FluentUI/Controls/FluProgressBar.qml create mode 100644 src/FluentUI/Controls/FluProgressButton.qml create mode 100644 src/FluentUI/Controls/FluProgressRing.qml create mode 100644 src/FluentUI/Controls/FluQRCode.qml create mode 100644 src/FluentUI/Controls/FluRadioButton.qml create mode 100644 src/FluentUI/Controls/FluRadioButtons.qml create mode 100644 src/FluentUI/Controls/FluRangeSlider.qml create mode 100644 src/FluentUI/Controls/FluRatingControl.qml create mode 100644 src/FluentUI/Controls/FluRemoteLoader.qml create mode 100644 src/FluentUI/Controls/FluScrollBar.qml create mode 100644 src/FluentUI/Controls/FluScrollIndicator.qml create mode 100644 src/FluentUI/Controls/FluScrollablePage.qml create mode 100644 src/FluentUI/Controls/FluShadow.qml create mode 100644 src/FluentUI/Controls/FluShortcutPicker.qml create mode 100644 src/FluentUI/Controls/FluSlider.qml create mode 100644 src/FluentUI/Controls/FluSpinBox.qml create mode 100644 src/FluentUI/Controls/FluSplitLayout.qml create mode 100644 src/FluentUI/Controls/FluStaggeredLayout.qml create mode 100644 src/FluentUI/Controls/FluStatusLayout.qml create mode 100644 src/FluentUI/Controls/FluTabView.qml create mode 100644 src/FluentUI/Controls/FluTableView.qml create mode 100644 src/FluentUI/Controls/FluText.qml create mode 100644 src/FluentUI/Controls/FluTextBox.qml create mode 100644 src/FluentUI/Controls/FluTextBoxBackground.qml create mode 100644 src/FluentUI/Controls/FluTextBoxMenu.qml create mode 100644 src/FluentUI/Controls/FluTextButton.qml create mode 100644 src/FluentUI/Controls/FluTimePicker.qml create mode 100644 src/FluentUI/Controls/FluTimeline.qml create mode 100644 src/FluentUI/Controls/FluToggleButton.qml create mode 100644 src/FluentUI/Controls/FluToggleSwitch.qml create mode 100644 src/FluentUI/Controls/FluTooltip.qml create mode 100644 src/FluentUI/Controls/FluTour.qml create mode 100644 src/FluentUI/Controls/FluTreeView.qml create mode 100644 src/FluentUI/Controls/FluWindow.qml create mode 100644 src/FluentUI/Controls/FluWindowDialog.qml create mode 100644 src/FluentUI/Font/Segoe_Fluent_Icons.ttf create mode 100644 src/FluentUI/Image/btn_close_hovered.png create mode 100644 src/FluentUI/Image/btn_close_normal.png create mode 100644 src/FluentUI/Image/btn_close_pushed.png create mode 100644 src/FluentUI/Image/btn_max_hovered.png create mode 100644 src/FluentUI/Image/btn_max_normal.png create mode 100644 src/FluentUI/Image/btn_max_pushed.png create mode 100644 src/FluentUI/Image/btn_min_hovered.png create mode 100644 src/FluentUI/Image/btn_min_normal.png create mode 100644 src/FluentUI/Image/btn_min_pushed.png create mode 100644 src/FluentUI/Image/noise.png create mode 100644 src/FluentUI/JS/Chart.js create mode 100644 src/FluentUI/fluentui_qml_module_dir_map.qrc create mode 100644 src/FluentUI/fluentuiplugin.lib create mode 100644 src/FluentUI/plugins.qmltypes create mode 100644 src/FluentUI/qmldir create mode 100644 src/fluentui_en_US.ts create mode 100644 src/fluentui_zh_CN.ts diff --git a/CMakeLists.txt b/CMakeLists.txt index f0402239..9d416420 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/.cmake/) include(GetGitRevisionDescription) option(FLUENTUI_BUILD_EXAMPLES "Build FluentUI demo applications." ON) +set(FLUENTUI_BUILD_STATIC_LIB OFF) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index e0528d8f..866312d7 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -4,6 +4,10 @@ project(example VERSION 1.0 LANGUAGES CXX) #配置通用编译 set(CMAKE_CXX_STANDARD 17) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) #判断FluentUI库类型 @@ -24,19 +28,11 @@ endif() 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() -else() - set(CMAKE_AUTOMOC ON) - set(CMAKE_AUTORCC ON) - set(CMAKE_AUTOUIC ON) -endif() - -#国际化 +#添加国际化脚本 find_program(QT_LUPDATE NAMES lupdate) find_program(QT_LRELEASE NAMES lrelease) file(GLOB TS_FILE_PATHS ${CMAKE_CURRENT_LIST_DIR}/ *.ts) -add_custom_target(UpdateTranslations +add_custom_target(Script-UpdateTranslations COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} COMMAND ${QT_LUPDATE} ${CMAKE_CURRENT_LIST_DIR} -ts ${PROJECT_NAME}_zh_CN.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} COMMAND ${QT_LRELEASE} ${PROJECT_NAME}_en_US.ts WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} @@ -64,30 +60,6 @@ if(WIN32) list(APPEND sources_files "src/app_dmp.h") endif() -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 "qml-Qt6") - string(REPLACE "qml-Qt6" "qml" filealias ${filename}) - set_source_files_properties(${filename} PROPERTIES QT_RESOURCE_ALIAS ${filealias}) - if(${filename} MATCHES "qmldir") - list(APPEND resource_files ${filename}) - else() - list(APPEND qml_files ${filename}) - endif() - endif() - endforeach(filepath) - - #遍历所有资源文件 - file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.in) - foreach(filepath ${RES_PATHS}) - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath}) - list(APPEND resource_files ${filename}) - endforeach(filepath) -endif() - #如果是Windows平台,则生成rc文件,还有inno setup脚本文件 set(EXAMPLE_VERSION_RC_PATH "") if(WIN32) @@ -103,21 +75,26 @@ configure_file( endif() #添加可执行文件 -if (WIN32) - add_executable(${PROJECT_NAME} +list(APPEND sources_files ${PROJECT_NAME}.qrc) +if(WIN32) + list(APPEND sources_files ${EXAMPLE_VERSION_RC_PATH}) +endif() +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_executable(${PROJECT_NAME} + MANUAL_FINALIZATION ${sources_files} - ${EXAMPLE_VERSION_RC_PATH} ) -else () +else() add_executable(${PROJECT_NAME} ${sources_files} ) -endif () - -add_dependencies(${PROJECT_NAME} UpdateTranslations) +endif() +add_dependencies(${PROJECT_NAME} Script-UpdateTranslations) #复制程序运行所需要的动态库 if(WIN32) + message("-----------------------------") + message(${CMAKE_CXX_COMPILER_ID}) if(MSVC) if(CMAKE_SIZEOF_VOID_P EQUAL 4) file(GLOB_RECURSE 3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/msvc/x86/*.dll) @@ -134,23 +111,6 @@ endif() file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/source/) file(COPY ${CMAKE_SOURCE_DIR}/src/ DESTINATION ${APPLICATION_DIR_PATH}/source/) -if(QT_VERSION VERSION_GREATER_EQUAL "6.2") - #如果是Qt6.2以上,则使用qt_add_qml_module添加资源文件 - qt_add_qml_module(${PROJECT_NAME} - URI ${PROJECT_NAME} - VERSION 1.0 - QML_FILES ${qml_files} - RESOURCES ${resource_files} - RESOURCE_PREFIX "/" - ) -else() - #如果是Qt6.2以下,则使用qrc添加资源文件 - target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} - ) -target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}.qrc) -endif() - #导入component头文件,不然通过QML_NAMED_ELEMENT生成的c++类会找不到头文件报错 target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/component @@ -186,9 +146,28 @@ target_link_libraries(${PROJECT_NAME} PRIVATE fluentuiplugin ) -#安装 -install(TARGETS ${PROJECT_NAME} - BUNDLE DESTINATION . - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +#添加部署脚本 +if (CMAKE_BUILD_TYPE MATCHES "Release") + if (APPLE) + find_program(QT_DEPLOY_QT NAMES macdeployqt) + add_custom_target(Script-DeployRelease + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist + COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME} -qmldir=${CMAKE_CURRENT_LIST_DIR} + COMMENT "MacOs Deploying Qt Dependencies After Build........." + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + endif() + if(WIN32) + find_program(QT_DEPLOY_QT NAMES windeployqt) + add_custom_target(Script-DeployRelease + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist + COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe -qmldir=${CMAKE_CURRENT_LIST_DIR} + COMMENT "Windows Deploying Qt Dependencies After Build........." + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) +endif() +endif() diff --git a/example/README.md b/example/README.md new file mode 100644 index 00000000..2ac81422 --- /dev/null +++ b/example/README.md @@ -0,0 +1,18 @@ +# FluentUI 脚手架开发说明 + +## 代码说明 + +文件编码格式请用utf-8不带bom,代码中最好不要含有中文(包括注释),中文可能会改变文件格式导致编译失败,还会出现乱码,显示中文请用国际化,c++中用tr函数,qml中用qsTr函数 + +### 脚本说明 + +1. **Script-UpdateTranslations** + + 用于更新ts与qm文件,当你的代码添加了tr或者qsTr函数后,执行这个脚本会更新ts文件,然后编写翻译后,再执行这个脚本,qm文件会更新生效 + +2. **Script-DeployRelease** + + 执行Qt的windeployqt或macdeployqt命令,这个脚本只在windows与macos才有,linux不支持 + + + diff --git a/example/example_en_US.ts b/example/example_en_US.ts index a354efb0..f39856a6 100644 --- a/example/example_en_US.ts +++ b/example/example_en_US.ts @@ -5,13 +5,11 @@ CodeExpander - Source - The Copy is Successful @@ -20,25 +18,21 @@ CrashWindow - Friendly Reminder - We apologize for the inconvenience caused by an unexpected error - Report Logs - Restart Program @@ -48,38 +42,31 @@ - - FluentUI Initalizr - Name - Create In - Browse - Cancel - Create @@ -88,13 +75,11 @@ HotloadWindow - Hot Loader - Drag in a qml file @@ -126,13 +111,11 @@ ItemsFooter - About - Settings @@ -141,463 +124,386 @@ ItemsOriginal - Home - PaneItemExpander Disabled - Basic Input - Buttons - A control that responds to user input and raisesa Click event. - Text - Image - Slider - A control that lets the user select from a rangeof values by moving a Thumb control along atrack. - CheckBox - A control that a user can select or clear. - RadioButton - ToggleSwitch - PaneItem Disabled - Form - TextBox - TimePicker - DatePicker - CalendarPicker - ColorPicker - ShortcutPicker - Surface - InfoBar - An inline message to display app-wide statuschange information. - Progress - RatingControl - Badge - Rectangle - Clip - Carousel - Expander - Watermark - Layout - StaggeredLayout - SplitLayout - StatusLayout - Popus - Dialog - ComboBox - Tooltip - Menu - Navigation - Pivot - Presents information from different sources in a tabbed view. - BreadcrumbBar - TabView - A control that displays a collection of tabs thatcan be used to display several documents. - TreeView - TableView - The TableView control provides a flexible way to display a collection of data in rows and columns - Pagination - MultiWindow - FlipView - Presents a collection of items that the user canflip through, one item at a time. - Theming - Acrylic - Theme - Typography - Awesome - Chart - Bar Chart - Line Chart - Pie Chart - Polar Area Chart - Bubble Chart - Scatter Chart - Radar Chart - Other - QRCode - Tour - Timeline - Captcha - Network - Remote Loader - Hot Loader - 3D - Test Crash @@ -607,26 +513,21 @@ - - Login - Please enter the account - Please enter your password - Please feel free to enter a password @@ -634,126 +535,104 @@ MainWindow - - + Dark Mode - - - - + + Quit - - + Are you sure you want to exit the program? - - + Minimize - - + Friendly Reminder - - + FluentUI is hidden from the tray, click on the tray to activate the window again - - - - + + Cancel - - + Open in Separate Window - - + Click Time - - + Search - - + Finish - - + Next - - + Previous - - + Here you can switch to night mode. - - + Hide Easter eggs - - + Try a few more clicks!! - - + Upgrade Tips - - + FluentUI is currently up to date - - + -- The current app version - - + Now go and download the new version? @@ -762,20 +641,17 @@ Updated content: - - + OK - - + The current version is already the latest - - + The network is abnormal @@ -784,13 +660,11 @@ Updated content: SingleInstanceWindow - SingleInstance - I'm a SingleInstance window, and if I exist, I'll destroy the previous window and create a new one @@ -799,13 +673,11 @@ Updated content: SingleTaskWindow - SingleTask - I'm a SingleTask mode window, and if I exist, I activate the window @@ -814,79 +686,66 @@ Updated content: StandardWindow - File - New... - Open... - Save - Save As... - Quit - Edit - Cut - Copy - Paste - Help - About - I'm a Standard mode window, and every time I create a new window @@ -895,7 +754,6 @@ Updated content: T_Acrylic - Acrylic @@ -904,25 +762,21 @@ Updated content: T_Awesome - Awesome - Please enter a keyword - Search - You Copied @@ -931,13 +785,11 @@ Updated content: T_Badge - Badge - It usually appears in the upper right corner of the notification icon or avatar to display the number of messages that need to be processed @@ -946,7 +798,6 @@ Updated content: T_BarChart - Bar Chart @@ -955,13 +806,11 @@ Updated content: T_BreadcrumbBar - BreadcurmbBar - Reset sample @@ -970,7 +819,6 @@ Updated content: T_BubbleChart - Bubble Chart @@ -979,19 +827,16 @@ Updated content: T_Buttons - Buttons - Support the Tab key to switch focus, and the Space key to perform click events - Text Button @@ -1004,164 +849,131 @@ Updated content: - - - - - - - - Disabled - Standard Button - Click StandardButton - Filled Button - Click FilledButton - Toggle Button - Progress Button - Loading Button - Loading - Click IconButton - IconOnly - Button.IconOnly - TextOnly - Button.TextOnly - TextBesideIcon - Button.TextBesideIcon - TextUnderIcon - Button.TextUnderIcon - DropDownButton - Menu_1 - Menu_2 - Menu_3 - Menu_4 - Radio Button_1 - Radio Button_2 - Radio Button_3 @@ -1170,7 +982,6 @@ Updated content: T_CalendarPicker - CalendarPicker @@ -1179,37 +990,31 @@ Updated content: T_Captcha - Captcha - Refresh - Ignore Case - Please enter a verification code - The verification code is correct - Error validation, please re-enter @@ -1218,13 +1023,11 @@ Updated content: T_Carousel - Carousel - Carousel map, support infinite carousel, infinite swipe, and components implemented with ListView @@ -1233,45 +1036,37 @@ Updated content: T_CheckBox - CheckBox - A 2-state CheckBox - Right - Left - - Disabled - A 3-state CheckBox - Three State @@ -1280,13 +1075,11 @@ Updated content: T_Clip - Clip - Use with images (this component will have no effect under software rendering) @@ -1295,61 +1088,51 @@ Updated content: T_ColorPicker - ColorPicker - Click to Select a Color - > - Cancel - OK - Color Picker - Edit Color - Red - Green - Blue - Opacity @@ -1358,7 +1141,6 @@ Updated content: T_ComboBox - ComboBox @@ -1367,44 +1149,16 @@ Updated content: T_DatePicker - TimePicker - showYear=true - - - Year - - - - - Month - - - - - Day - - - - - Cancel - - - - - OK - - - showYear=false @@ -1413,13 +1167,11 @@ Updated content: T_Dialog - Dialog - Show Double Button Dialog @@ -1427,25 +1179,18 @@ Updated content: - - - Friendly Reminder - - Are you sure you want to opt out? - - Cancel @@ -1453,9 +1198,6 @@ Updated content: - - - Click the Cancel Button @@ -1464,10 +1206,6 @@ Updated content: - - - - OK @@ -1475,63 +1213,51 @@ Updated content: - - - Click the OK Button - Show Triple Button Dialog - Minimize - Click Minimize - Custom Content Dialog - Custom Content Dialog2 - Data is loading, please wait... - Unload - Test the InfoBar level on top of the Popup - Line Chart @@ -1540,25 +1266,21 @@ Updated content: T_Expander - Expander - Open a radio box - Open a sliding text box - Permit me to observe: the late emperor was taken from us before he could finish his life`s work, the restoration of Han. Today, the empire is still divided in three, and our very survival is threatened. Yet still the officials at court and the soldiers throughout the realm remain loyal to you, your majesty. Because they remember the late emperor, all of them, and they wish to repay his kindness in service to you. This is the moment to extend your divine influence, to honour the memory of the late Emperor and strengthen the morale of your officers. It is not time to listen to bad advice, or close your ears to the suggestions of loyal men. The court and the administration are as one. Both must be judged by one standard. Those who are loyal and good must get what they deserve, but so must the evil-doers who break the law. This will demonstrate the justice of your rule. There cannot be one law for the court and another for the administration. Counselors and attendants like Guo Youzhi, Fei Yi, and Dong Yun are all reliable men, loyal of purpose and pure in motive. The late Emperor selected them for office so that they would serve you after his death.These are the men who should be consulted on all palace affairs. Xiang Chong has proved himself a fine general in battle, and the late Emperor believed in him. That is why the assembly has recommended him for overall command. It will keep the troops happy if he is consulted on all military matters. @@ -1574,19 +1296,16 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_FlipView - FlipView - Horizontal FlipView - Vertical FlipView @@ -1595,25 +1314,21 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Home - FluentUI GitHub - The latest FluentUI controls and styles for your applications. - FluentUI Initalizr - FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options. @@ -1622,13 +1337,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Image - Image - The image failed to load, please reload @@ -1637,57 +1350,47 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_InfoBar - InfoBar - Info - - This is an InfoBar in the Info Style - Warning - This is an InfoBar in the Warning Style - This is an InfoBar in the Error Style - This is an InfoBar in the Success Style - InfoBar that needs to be turned off manually - Manual shutdown is supported @@ -1696,7 +1399,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_LineChart - Line Chart @@ -1706,56 +1408,42 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - Menu - - File - - New... - - Open... - - Save - - Quit - - Search @@ -1763,87 +1451,69 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - Disable - Check - - Save As... - - Doc - - PDF - Show Menu Popup - MenuBar - Edit - Cut - Copy - Paste - Help - About @@ -1852,13 +1522,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_MultiWindow - MultiWindow - <font color='red'>Standard</font> mode window,a new window is created every time @@ -1868,41 +1536,31 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - - - Create Window - <font color='red'>SingleTask</font> mode window,If a window exists, this activates the window - <font color='red'>SingleInstance</font> mode window,If the window exists, destroy the window and create a new window - Create the window without carrying any parameters - Create a window with the parameter username: zhuzichu - Login Window Returned Password - > @@ -1911,7 +1569,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Network - Network @@ -1920,7 +1577,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Pagination - Pagination @@ -1929,7 +1585,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_PieChart - Pie Chart @@ -1938,55 +1593,46 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Pivot - Pivot - All - All emails go here. - Unread - Unread emails go here. - Flagged - Flagged emails go here. - Urgent - Urgent emails go here. @@ -1995,7 +1641,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_PolarAreaChart - Polar Area Chart @@ -2004,7 +1649,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Progress - Progress @@ -2013,7 +1657,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_QRCode - QRCode @@ -2022,7 +1665,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_RadarChart - Radar Chart @@ -2031,45 +1673,37 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_RadioButton - RadioButton - Right - Left - - Disabled - Radio Button_1 - Radio Button_2 - Radio Button_3 @@ -2078,7 +1712,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_RatingControl - RatingControl @@ -2087,7 +1720,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Rectangle - Rectangle @@ -2096,7 +1728,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_ScatterChart - Scatter Chart @@ -2105,115 +1736,96 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Settings - Settings - Current Version - Check for Updates - Use System AppBar - Fits AppBar Windows - Friendly Reminder - This action requires a restart of the program to take effect, is it restarted? - Cancel - OK - Dark Mode - System - Light - Dark - Navigation View Display Mode - Open - Compact - Minimal - Auto - Language @@ -2222,7 +1834,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_ShortcutPicker - ShortcutPicker @@ -2231,7 +1842,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Slider - Slider @@ -2240,7 +1850,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_SplitLayout - SplitLayout @@ -2249,7 +1858,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_StaggeredLayout - StaggeredLayout @@ -2258,31 +1866,26 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_StatusLayout - StatusLayout - Loading... - Empty - The page went wrong... - Reload @@ -2291,13 +1894,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TabView - TabView - Document @@ -2306,123 +1907,102 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TableView - TableView - Modify the column name - Cancel - OK - Search - - Name - Delete - Edit - Select All - Age - Clear All - Avatar - Address - Nickname - Long String - Options - <Previous - Next> - Delete Selection - Add a row of Data @@ -2431,13 +2011,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Text - Text - This is a text that can be copied @@ -2446,13 +2024,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TextBox - TextBox - Single-line Input Box @@ -2462,29 +2038,21 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - - - Disabled - Please enter your password - Multi-line Input Box - AutoSuggestBox @@ -2493,37 +2061,31 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Theme - Theme - Theme colors - Customize the Theme Color - Dark Mode - Native Text - Open Animation @@ -2532,67 +2094,52 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TimePicker - TimePicker - hourFormat=FluTimePickerType.H - - AM - - PM - - Hour - - Minute - - Cancel - - OK - hourFormat=FluTimePickerType.HH @@ -2601,19 +2148,16 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Timeline - Timeline - Append - clear @@ -2622,25 +2166,21 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_ToggleSwitch - ToggleSwitch - Right - Left - Disabled @@ -2649,45 +2189,37 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Tooltip - Tooltip - Hover over Tultip and it pops up - Text properties of FluIconButton support the Tooltip pop-up window by default - - Delete - Click IconButton - Add a Tooltip pop-up to a Button - Click Button @@ -2696,13 +2228,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Tour - Upload File - Put your files here. @@ -2710,53 +2240,42 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - Save - Save your changes. - Other Actions - Click to see other actions. - Begin Tour - - Upload - More - Tour @@ -2765,19 +2284,16 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TreeView - TreeView - Total %1 data, %2 data currently displayed - A total of %1 data items are selected @@ -2786,7 +2302,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Typography - Typography @@ -2795,7 +2310,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Watermark - Watermark diff --git a/example/example_zh_CN.ts b/example/example_zh_CN.ts index 4f8ebdb6..a9c0ee7d 100644 --- a/example/example_zh_CN.ts +++ b/example/example_zh_CN.ts @@ -5,13 +5,11 @@ CodeExpander - Source 源码 - The Copy is Successful 复制成功 @@ -20,25 +18,21 @@ CrashWindow - Friendly Reminder 友情提示 - We apologize for the inconvenience caused by an unexpected error 对于意外错误给您带来的不便,我们深表歉意 - Report Logs 上报日志 - Restart Program 重启程序 @@ -48,38 +42,31 @@ - - FluentUI Initalizr FluentUI脚手架 - Name 名称 - Create In 创建路径 - Browse 浏览 - Cancel 取消 - Create 创建 @@ -88,13 +75,11 @@ HotloadWindow - Hot Loader 热加载 - Drag in a qml file 拖入qml文件 @@ -126,13 +111,11 @@ ItemsFooter - About 关于 - Settings 设置 @@ -141,463 +124,386 @@ ItemsOriginal - Home 首页 - PaneItemExpander Disabled PaneItemExpander 已禁用 - Basic Input 基本输入 - Buttons 按钮 - A control that responds to user input and raisesa Click event. 响应用户输入并引发 Click 事件的控件。 - Text 文本 - Image 图像 - Slider 滑块 - A control that lets the user select from a rangeof values by moving a Thumb control along atrack. 一个控件,允许用户通过沿轨道移动 Thumb 控件从一系列值中进行选择。 - CheckBox 复选框 - A control that a user can select or clear. 用户可以选择或清除的控件。 - RadioButton 单选按钮 - ToggleSwitch 切换开关 - PaneItem Disabled PaneItem 已禁用 - Form 表单 - TextBox 文本框 - TimePicker 时间选择器 - DatePicker 日期选择器 - CalendarPicker 日历选择器 - ColorPicker 颜色选择器 - ShortcutPicker 快捷键选择器 - Surface 表面 - InfoBar 信息栏 - An inline message to display app-wide statuschange information. 用于显示应用范围状态更改信息的内联消息。 - Progress 进度条 - RatingControl 评级控制 - Badge 徽章 - Rectangle 矩形 - Clip 裁剪 - Carousel 轮播图 - Expander 展开 - Watermark 水印 - Layout 布局 - StaggeredLayout 瀑布流布局 - SplitLayout 拆分布局 - StatusLayout 状态布局 - Popus 弹窗 - Dialog 弹窗 - ComboBox 组合框 - Tooltip 工具提示 - Menu 菜单 - Navigation 导航 - Pivot 轴转 - Presents information from different sources in a tabbed view. 在选项卡式视图中显示来自不同源的信息。 - BreadcrumbBar 面包屑 - TabView 选项卡 - A control that displays a collection of tabs thatcan be used to display several documents. 一个控件,用于显示可用于显示多个文档的选项卡集合。 - TreeView - TableView 表格 - The TableView control provides a flexible way to display a collection of data in rows and columns TableView 控件提供了一种以行和列形式显示数据集合的灵活方法 - Pagination 分页 - MultiWindow 多窗口 - FlipView 翻转视图 - Presents a collection of items that the user canflip through, one item at a time. 显示用户可以翻阅的项集合,一次翻阅一个项。 - Theming 主题 - Acrylic 亚克力 - Theme 主题 - Typography 字体 - Awesome 图标 - Chart 图表 - Bar Chart 条形图 - Line Chart 线型图 - Pie Chart 饼图 - Polar Area Chart 极坐标区域图 - Bubble Chart 气泡图 - Scatter Chart 散点图 - Radar Chart 雷达图 - Other 其他 - QRCode 二维码 - Tour 游览 - Timeline 时间轴 - Captcha 验证码 - Network 网络 - Remote Loader 远程加载 - Hot Loader 热加载 - 3D 3D - Test Crash 测试崩溃 @@ -607,26 +513,21 @@ - - Login 登录 - Please enter the account 请输入账号 - Please enter your password 请输入密码 - Please feel free to enter a password 请随意输入一个密码 @@ -634,126 +535,104 @@ MainWindow - - + Dark Mode 夜间模式 - - - - + + Quit 退出 - - + Are you sure you want to exit the program? 您确定要退出程序吗 - - + Minimize 最小化 - - + Friendly Reminder 友情提示 - - + FluentUI is hidden from the tray, click on the tray to activate the window again FluentUI 在托盘中处于隐藏状态,单击托盘以再次激活窗口 - - - - + + Cancel 取消 - - + Open in Separate Window 在独立窗口中打开 - - + Click Time 点击次数 - - + Search 搜索 - - + Finish 完成 - - + Next 下一步 - - + Previous 上一步 - - + Here you can switch to night mode. 在这里,您可以切换到夜间模式。 - - + Hide Easter eggs 隐藏彩蛋 - - + Try a few more clicks!! 再试几下!! - - + Upgrade Tips 升级提示 - - + FluentUI is currently up to date FluentUI 目前最新版本 - - + -- The current app version -- 当前应用版本 - - + Now go and download the new version? @@ -766,20 +645,17 @@ Updated content: - - + OK 确定 - - + The current version is already the latest 当前版本已经是最新版本 - - + The network is abnormal 网络异常 @@ -788,13 +664,11 @@ Updated content: SingleInstanceWindow - SingleInstance - I'm a SingleInstance window, and if I exist, I'll destroy the previous window and create a new one 我是一个SingleInstance模式的窗口,如果我存在,我会销毁之前的窗口,并创建一个新窗口 @@ -803,13 +677,11 @@ Updated content: SingleTaskWindow - SingleTask - I'm a SingleTask mode window, and if I exist, I activate the window 我是一个SingleTask模式的窗口,如果我存在,我就激活窗口 @@ -818,79 +690,66 @@ Updated content: StandardWindow - File 文件 - New... 新建... - Open... 打开... - Save 保存 - Save As... 另存为... - Quit 退出 - Edit 编辑 - Cut 剪切 - Copy 复制 - Paste 粘贴 - Help 帮助 - About 关于 - I'm a Standard mode window, and every time I create a new window 我是一个Standard模式的窗口,每次我都会创建一个新的窗口 @@ -899,7 +758,6 @@ Updated content: T_Acrylic - Acrylic 亚克力 @@ -908,25 +766,21 @@ Updated content: T_Awesome - Awesome 图标 - Please enter a keyword 请输入关键字 - Search 搜索 - You Copied 您复制 @@ -935,13 +789,11 @@ Updated content: T_Badge - Badge 徽章 - It usually appears in the upper right corner of the notification icon or avatar to display the number of messages that need to be processed 一般出现在通知图标或头像的右上角,用于显示需要处理的消息条数 @@ -950,7 +802,6 @@ Updated content: T_BarChart - Bar Chart 条形图 @@ -959,13 +810,11 @@ Updated content: T_BreadcrumbBar - BreadcurmbBar 面包屑 - Reset sample 重置 @@ -974,7 +823,6 @@ Updated content: T_BubbleChart - Bubble Chart 气泡图 @@ -983,19 +831,16 @@ Updated content: T_Buttons - Buttons 按钮 - Support the Tab key to switch focus, and the Space key to perform click events 支持Tab键切换焦点,空格键执行点击事件 - Text Button 文本按钮 @@ -1008,164 +853,131 @@ Updated content: - - - - - - - - Disabled 禁用 - Standard Button 标准按钮 - Click StandardButton 点击标准按钮 - Filled Button 填充按钮 - Click FilledButton 点击填充按钮 - Toggle Button 开关按钮 - Progress Button 进度按钮 - Loading Button 加载按钮 - Loading 正在加载 - Click IconButton 点击图标按钮 - IconOnly - Button.IconOnly - TextOnly - Button.TextOnly - TextBesideIcon - Button.TextBesideIcon - TextUnderIcon - Button.TextUnderIcon - DropDownButton 下拉按钮 - Menu_1 - Menu_2 - Menu_3 - Menu_4 - Radio Button_1 - Radio Button_2 - Radio Button_3 @@ -1174,7 +986,6 @@ Updated content: T_CalendarPicker - CalendarPicker 日历选择器 @@ -1183,37 +994,31 @@ Updated content: T_Captcha - Captcha 验证码 - Refresh 刷新 - Ignore Case 忽略大小写 - Please enter a verification code 请输入验证码 - The verification code is correct 验证码错误 - Error validation, please re-enter 错误验证,请重新输入 @@ -1222,13 +1027,11 @@ Updated content: T_Carousel - Carousel 轮播图 - Carousel map, support infinite carousel, infinite swipe, and components implemented with ListView 轮播图,支持无限轮播,无限滑动,用ListView实现的组件 @@ -1237,45 +1040,37 @@ Updated content: T_CheckBox - CheckBox 复选框 - A 2-state CheckBox - Right - Left - - Disabled 禁用 - A 3-state CheckBox - Three State @@ -1284,13 +1079,11 @@ Updated content: T_Clip - Clip 裁剪 - Use with images (this component will have no effect under software rendering) 配合图片使用(software渲染下该组件将没有效果) @@ -1299,61 +1092,51 @@ Updated content: T_ColorPicker - ColorPicker 颜色选择器 - Click to Select a Color - > 点击选中颜色 - > - Cancel 取消 - OK 确定 - Color Picker 颜色选择器 - Edit Color 编辑颜色 - Red 红色 - Green 绿色 - Blue 蓝色 - Opacity 透明度 @@ -1362,7 +1145,6 @@ Updated content: T_ComboBox - ComboBox 组合框 @@ -1371,44 +1153,36 @@ Updated content: T_DatePicker - TimePicker 时间选择器 - showYear=true - Year - + - Month - + - Day - + - Cancel - 取消 + 取消 - OK - 确定 + 确定 - showYear=false @@ -1417,13 +1191,11 @@ Updated content: T_Dialog - Dialog 弹窗 - Show Double Button Dialog 显示双按钮对话框 @@ -1431,25 +1203,18 @@ Updated content: - - - Friendly Reminder 友情提示 - - Are you sure you want to opt out? 您确定要退出吗? - - Cancel 取消 @@ -1457,9 +1222,6 @@ Updated content: - - - Click the Cancel Button 单击取消按钮 @@ -1468,10 +1230,6 @@ Updated content: - - - - OK 确定 @@ -1479,63 +1237,51 @@ Updated content: - - - Click the OK Button 单击确定按钮 - Show Triple Button Dialog 显示三个按钮对话框 - Minimize 最小化 - Click Minimize 单击最小化 - Custom Content Dialog 自定义对话框内容 - Custom Content Dialog2 自定义对话框内容2 - Data is loading, please wait... 正在加载,请稍等... - Unload 取消加载 - Test the InfoBar level on top of the Popup 测试InfoBar层级在Popup之上 - Line Chart 线型图 @@ -1544,25 +1290,21 @@ Updated content: T_Expander - Expander 展开 - Open a radio box 打开一个单选框 - Open a sliding text box 打开一个滑动文本框 - Permit me to observe: the late emperor was taken from us before he could finish his life`s work, the restoration of Han. Today, the empire is still divided in three, and our very survival is threatened. Yet still the officials at court and the soldiers throughout the realm remain loyal to you, your majesty. Because they remember the late emperor, all of them, and they wish to repay his kindness in service to you. This is the moment to extend your divine influence, to honour the memory of the late Emperor and strengthen the morale of your officers. It is not time to listen to bad advice, or close your ears to the suggestions of loyal men. The court and the administration are as one. Both must be judged by one standard. Those who are loyal and good must get what they deserve, but so must the evil-doers who break the law. This will demonstrate the justice of your rule. There cannot be one law for the court and another for the administration. Counselors and attendants like Guo Youzhi, Fei Yi, and Dong Yun are all reliable men, loyal of purpose and pure in motive. The late Emperor selected them for office so that they would serve you after his death.These are the men who should be consulted on all palace affairs. Xiang Chong has proved himself a fine general in battle, and the late Emperor believed in him. That is why the assembly has recommended him for overall command. It will keep the troops happy if he is consulted on all military matters. @@ -1586,19 +1328,16 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_FlipView - FlipView 翻转视图 - Horizontal FlipView 水平方向的翻转视图 - Vertical FlipView 垂直方向的翻转视图 @@ -1607,25 +1346,21 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Home - FluentUI GitHub FluentUI GitHub - The latest FluentUI controls and styles for your applications. 最新的 FluentUI 控件和样式 - FluentUI Initalizr FluentUI脚手架 - FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options. FluentUI 脚手架是一个快速创建项目工具,可帮助您创建和自定义具有各种选项的 Fluent UI 项目 @@ -1634,7 +1369,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Image - Image 图像 @@ -1644,7 +1378,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - The image failed to load, please reload 图片加载失败,请重新加载 @@ -1653,57 +1386,47 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_InfoBar - InfoBar 信息栏 - Info - - This is an InfoBar in the Info Style 这是一个Info样式的信息栏 - Warning - This is an InfoBar in the Warning Style 这是一个Warning样式的信息栏 - This is an InfoBar in the Error Style 这是一个Error样式的信息栏 - This is an InfoBar in the Success Style 这是一个Success样式的信息栏 - InfoBar that needs to be turned off manually 需要手动关闭的信息栏 - Manual shutdown is supported 支持手动关闭 @@ -1716,7 +1439,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_LineChart - Line Chart 线型图 @@ -1726,56 +1448,42 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - Menu 菜单 - - File 文件 - - New... 新建... - - Open... 打开... - - Save 保存 - - Quit 退出 - - Search 搜索 @@ -1783,87 +1491,69 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - Disable 不可操作 - Check 复选 - - Save As... 另存为... - - Doc DOC - - PDF PDF - Show Menu Popup 打开菜单弹框 - MenuBar 菜单栏 - Edit 编辑 - Cut 剪切 - Copy 复制 - Paste 粘贴 - Help 帮助 - About 关于 @@ -1872,13 +1562,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_MultiWindow - MultiWindow 多窗口 - <font color='red'>Standard</font> mode window,a new window is created every time <font color='red'>Standard</font> 模式窗口,每次都会创建新窗口 @@ -1888,41 +1576,31 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - - - Create Window 创建窗口 - <font color='red'>SingleTask</font> mode window,If a window exists, this activates the window <font color='red'>SingleTask</font> 模式窗口,如果窗口存在,这激活该窗口 - <font color='red'>SingleInstance</font> mode window,If the window exists, destroy the window and create a new window <font color='red'>SingleInstance</font> 模式窗口,如果窗口存在,则销毁窗口,然后新建窗口 - Create the window without carrying any parameters 创建一个窗口,不携带任何参数 - Create a window with the parameter username: zhuzichu 创建一个窗口,并携带参数用户名:zhuzichu - Login Window Returned Password - > 登录窗口返回过来的密码 - > @@ -1931,7 +1609,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Network - Network 网络 @@ -1940,7 +1617,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Pagination - Pagination 分页 @@ -1957,7 +1633,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_PieChart - Pie Chart Doughnut and Pie Chart 饼图 @@ -1967,55 +1642,46 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Pivot - Pivot 轴转 - All 所有 - All emails go here. 所有电子邮件都在这里 - Unread 未读 - Unread emails go here. 未读电子邮件都在这里 - Flagged 标记 - Flagged emails go here. 标记电子邮件都在这里 - Urgent 紧急 - Urgent emails go here. 紧急电子邮件都在这里 @@ -2024,7 +1690,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_PolarAreaChart - Polar Area Chart PolarArea Chart 极坐标区域图 @@ -2034,7 +1699,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Progress - Progress 进度条 @@ -2043,7 +1707,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_QRCode - QRCode 二维码 @@ -2052,7 +1715,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_RadarChart - Radar Chart 雷达图 @@ -2061,45 +1723,37 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_RadioButton - RadioButton 单选按钮 - Right - Left - - Disabled 禁用 - Radio Button_1 - Radio Button_2 - Radio Button_3 @@ -2108,7 +1762,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_RatingControl - RatingControl 评级控制 @@ -2117,7 +1770,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Rectangle - Rectangle 矩形 @@ -2126,7 +1778,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_ScatterChart - Scatter Chart 散点图 @@ -2135,115 +1786,96 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Settings - Settings 设置 - Current Version 当前版本 - Check for Updates 检查更新 - Use System AppBar 使用系统应用栏 - Fits AppBar Windows 沉浸式应用栏 - Friendly Reminder 友情提示 - This action requires a restart of the program to take effect, is it restarted? 此操作需要重启程序才能生效,是否重新启动? - Cancel 取消 - OK 确定 - Dark Mode 夜间模式 - System 跟随系统 - Light 浅色 - Dark 深色 - Navigation View Display Mode 导航视图 - Open 开放 - Compact 紧凑 - Minimal 极简 - Auto 自动 - Language 语言 @@ -2252,7 +1884,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_ShortcutPicker - ShortcutPicker 快捷键选择器 @@ -2281,7 +1912,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Slider - Slider 滑块 @@ -2290,7 +1920,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_SplitLayout - SplitLayout 拆分布局 @@ -2299,7 +1928,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_StaggeredLayout - StaggeredLayout 瀑布流布局 @@ -2308,31 +1936,26 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_StatusLayout - StatusLayout 状态布局 - Loading... 正在加载... - Empty 空空如也 - The page went wrong... 页面出错了... - Reload 重新加载 @@ -2341,13 +1964,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TabView - TabView 选项卡 - Document 文档 @@ -2356,123 +1977,102 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TableView - TableView 表格 - Modify the column name 修改列名 - Cancel 取消 - OK 确定 - Search 搜索 - - Name 名称 - Delete 删除 - Edit 编辑 - Select All 全选 - Age 年龄 - Clear All 清除所有 - Avatar 头像 - Address 地址 - Nickname 昵称 - Long String 长字符串 - Options 操作 - <Previous <上一页 - Next> 下一页> - Delete Selection 删除选中 - Add a row of Data 添加一行数据 @@ -2481,13 +2081,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Text - Text 文本 - This is a text that can be copied 这是一个可以复制的文本 @@ -2496,13 +2094,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TextBox - TextBox 文本框 - Single-line Input Box 单行输入框 @@ -2512,29 +2108,21 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - - - Disabled 禁用 - Please enter your password 请输入您的密码 - Multi-line Input Box 多行输入框 - AutoSuggestBox 自动建议框 @@ -2543,37 +2131,31 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Theme - Theme 主题 - Theme colors 主题颜色 - Customize the Theme Color 自定义主题颜色 - Dark Mode 夜间模式 - Native Text Native文本 - Open Animation 开启动画 @@ -2582,67 +2164,52 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TimePicker - TimePicker 时间选择器 - hourFormat=FluTimePickerType.H - - AM 上午 - - PM 下午 - - Hour - - Minute - - Cancel 取消 - - OK 确定 - hourFormat=FluTimePickerType.HH @@ -2651,19 +2218,16 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Timeline - Timeline 时间轴 - Append 追加 - clear 清空 @@ -2672,25 +2236,21 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_ToggleSwitch - ToggleSwitch 切换开关 - Right - Left - Disabled 禁用 @@ -2699,45 +2259,37 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Tooltip - Tooltip 工具提示 - Hover over Tultip and it pops up 鼠标悬停不动,弹出Tooltip - Text properties of FluIconButton support the Tooltip pop-up window by default FluIconButton的text属性自带Tooltip效果 - - Delete 删除 - Click IconButton 点击图标按钮 - Add a Tooltip pop-up to a Button 给一个Button添加Tooltip效果 - Click Button 点击按钮 @@ -2758,13 +2310,11 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - Upload File 上传文件 - Put your files here. 把你的文件放在这里 @@ -2772,53 +2322,42 @@ My only desire is to be permitted to drive out the traitors and restore the Han. - - - Save 保存 - Save your changes. 保存更改 - Other Actions 其他操作 - Click to see other actions. 点击查看其他操作 - Begin Tour 开始游览 - - Upload 上传 - More 更多 - Tour 游览 @@ -2827,19 +2366,16 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_TreeView - TreeView - Total %1 data, %2 data currently displayed 共计%1条数据,当前显示的%2条数据 - A total of %1 data items are selected 共计选中%1条数据 @@ -2848,7 +2384,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Typography - Typography 字体 @@ -2857,7 +2392,6 @@ My only desire is to be permitted to drive out the traitors and restore the Han. T_Watermark - Watermark 水印 diff --git a/example/qml-Qt6/App.qml b/example/qml-Qt6/App.qml deleted file mode 100644 index 93f293fb..00000000 --- a/example/qml-Qt6/App.qml +++ /dev/null @@ -1,59 +0,0 @@ -import QtQuick -import QtQuick.Window -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI - -Item { - id: app - - Connections{ - target: FluTheme - function onDarkModeChanged(){ - SettingsHelper.saveDarkMode(FluTheme.darkMode) - } - } - - Connections{ - target: FluApp - function onUseSystemAppBarChanged(){ - SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar) - } - } - - Connections{ - target: TranslateHelper - function onCurrentChanged(){ - SettingsHelper.saveLanguage(TranslateHelper.current) - } - } - - Component.onCompleted: { - FluNetwork.openLog = false - FluNetwork.setInterceptor(function(param){ - param.addHeader("Token","000000000000000000000") - }) - FluApp.init(app,Qt.locale(TranslateHelper.current)) - FluApp.windowIcon = "qrc:/example/res/image/favicon.ico" - FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar() - FluTheme.darkMode = SettingsHelper.getDarkMode() - 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", - "/crash":"qrc:/example/qml/window/CrashWindow.qml", - "/singleTaskWindow":"qrc:/example/qml/window/SingleTaskWindow.qml", - "/standardWindow":"qrc:/example/qml/window/StandardWindow.qml", - "/singleInstanceWindow":"qrc:/example/qml/window/SingleInstanceWindow.qml", - "/pageWindow":"qrc:/example/qml/window/PageWindow.qml" - } - var args = Qt.application.arguments - if(args.length>=2 && args[1].startsWith("-crashed=")){ - FluApp.navigate("/crash",{crashFilePath:args[1].replace("-crashed=","")}) - }else{ - FluApp.navigate("/") - } - } -} diff --git a/example/qml-Qt6/chart/T_BarChart.qml b/example/qml-Qt6/chart/T_BarChart.qml deleted file mode 100644 index 859724c0..00000000 --- a/example/qml-Qt6/chart/T_BarChart.qml +++ /dev/null @@ -1,132 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Bar Chart") - - 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: 'My First Dataset', - data: [65, 59, 80, 81, 56, 55, 40], - backgroundColor: [ - 'rgba(255, 99, 132, 0.2)', - 'rgba(255, 159, 64, 0.2)', - 'rgba(255, 205, 86, 0.2)', - 'rgba(75, 192, 192, 0.2)', - 'rgba(54, 162, 235, 0.2)', - 'rgba(153, 102, 255, 0.2)', - 'rgba(201, 203, 207, 0.2)' - ], - borderColor: [ - 'rgb(255, 99, 132)', - 'rgb(255, 159, 64)', - 'rgb(255, 205, 86)', - 'rgb(75, 192, 192)', - 'rgb(54, 162, 235)', - 'rgb(153, 102, 255)', - 'rgb(201, 203, 207)' - ], - borderWidth: 1 - }] - } - } - - 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: 'horizontalBar' - chartData: { return { - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], - datasets: [{ - label: 'My First Dataset', - data: [65, 59, 80, 81, 56, 55, 40], - backgroundColor: [ - 'rgba(255, 99, 132, 0.2)', - 'rgba(255, 159, 64, 0.2)', - 'rgba(255, 205, 86, 0.2)', - 'rgba(75, 192, 192, 0.2)', - 'rgba(54, 162, 235, 0.2)', - 'rgba(153, 102, 255, 0.2)', - 'rgba(201, 203, 207, 0.2)' - ], - borderColor: [ - 'rgb(255, 99, 132)', - 'rgb(255, 159, 64)', - 'rgb(255, 205, 86)', - 'rgb(75, 192, 192)', - 'rgb(54, 162, 235)', - 'rgb(153, 102, 255)', - 'rgb(201, 203, 207)' - ], - borderWidth: 1 - }] - } - } - - chartOptions: { return { - maintainAspectRatio: false, - title: { - display: true, - text: 'Chart.js HorizontalBar Chart - Stacked' - }, - tooltips: { - mode: 'index', - intersect: false - }, - responsive: true, - scales: { - xAxes: [{ - stacked: true, - }], - yAxes: [{ - stacked: true - }] - } - } - } - } - } - -} diff --git a/example/qml-Qt6/chart/T_BubbleChart.qml b/example/qml-Qt6/chart/T_BubbleChart.qml deleted file mode 100644 index c5500f40..00000000 --- a/example/qml-Qt6/chart/T_BubbleChart.qml +++ /dev/null @@ -1,74 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Bubble Chart") - - function randomScalingFactor() { - return Math.random().toFixed(1); - } - - FluArea{ - height: 370 - width: 500 - paddings: 10 - Layout.topMargin: 20 - FluChart{ - anchors.fill: parent - chartType: 'bubble' - chartData: { - return { - datasets: [{ - label: 'First Dataset', - data: [{ - x: 20, - y: 30, - r: 15 - }, { - x: 12, - y: 70, - r: 20 - }, { - x: 11, - y: 28, - r: 8 - }, { - x: 9, - y: 28, - r: 10 - }, { - x: 43, - y: 7, - r: 14 - }, { - x: 22, - y: 22, - r: 12 - }, { - x: 40, - y: 10, - r: 10 - }], - backgroundColor: 'rgb(255, 99, 132)' - }] - }} - chartOptions: {return { - maintainAspectRatio: false, - responsive: true, - hoverMode: 'nearest', - intersect: true, - title: { - display: true, - text: 'Chart.js Bubble Chart - Multi Axis' - } - } - } - } - } - -} diff --git a/example/qml-Qt6/chart/T_LineChart.qml b/example/qml-Qt6/chart/T_LineChart.qml deleted file mode 100644 index cf9e0340..00000000 --- a/example/qml-Qt6/chart/T_LineChart.qml +++ /dev/null @@ -1,45 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Line Chart") - - 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: 'My First Dataset', - data: [65, 59, 80, 81, 56, 55, 40], - fill: false, - borderColor: 'rgb(75, 192, 192)', - tension: 0.1 - }] - } - } - chartOptions: { return { - maintainAspectRatio: false, - title: { - display: true, - text: 'Chart.js Line Chart - Stacked' - }, - tooltips: { - mode: 'index', - intersect: false - } - } - } - } - } -} diff --git a/example/qml-Qt6/chart/T_PieChart.qml b/example/qml-Qt6/chart/T_PieChart.qml deleted file mode 100644 index 5d6b6345..00000000 --- a/example/qml-Qt6/chart/T_PieChart.qml +++ /dev/null @@ -1,93 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Pie Chart") - - FluArea{ - width: 500 - height: 370 - paddings: 10 - Layout.topMargin: 20 - FluChart{ - anchors.fill: parent - chartType: "doughnut" - chartData: { return { - labels: [ - 'Red', - 'Blue', - 'Yellow' - ], - datasets: [{ - label: 'My First Dataset', - data: [300, 50, 100], - backgroundColor: [ - 'rgb(255, 99, 132)', - 'rgb(54, 162, 235)', - 'rgb(255, 205, 86)' - ], - hoverOffset: 4 - }] - } - } - chartOptions: { return { - maintainAspectRatio: false, - title: { - display: true, - text: 'Chart.js Doughnut Chart - Stacked' - }, - tooltips: { - mode: 'index', - intersect: false - } - } - } - } - } - - FluArea{ - width: 500 - height: 370 - paddings: 10 - Layout.topMargin: 20 - FluChart{ - anchors.fill: parent - chartType: "pie" - chartData: { return { - labels: [ - 'Red', - 'Blue', - 'Yellow' - ], - datasets: [{ - label: 'My First Dataset', - data: [300, 50, 100], - backgroundColor: [ - 'rgb(255, 99, 132)', - 'rgb(54, 162, 235)', - 'rgb(255, 205, 86)' - ], - hoverOffset: 4 - }] - } - } - chartOptions: { return { - maintainAspectRatio: false, - title: { - display: true, - text: 'Chart.js Pie Chart - Stacked' - }, - tooltips: { - mode: 'index', - intersect: false - } - } - } - } - } -} diff --git a/example/qml-Qt6/chart/T_PolarAreaChart.qml b/example/qml-Qt6/chart/T_PolarAreaChart.qml deleted file mode 100644 index 6e86529d..00000000 --- a/example/qml-Qt6/chart/T_PolarAreaChart.qml +++ /dev/null @@ -1,57 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Polar Area Chart") - - FluArea{ - width: 500 - height: 370 - paddings: 10 - Layout.topMargin: 20 - FluChart{ - anchors.fill: parent - chartType: 'polarArea' - chartData: { return { - labels: [ - 'Red', - 'Green', - 'Yellow', - 'Grey', - 'Blue' - ], - datasets: [{ - label: 'My First Dataset', - data: [11, 16, 7, 3, 14], - backgroundColor: [ - 'rgb(255, 99, 132)', - 'rgb(75, 192, 192)', - 'rgb(255, 205, 86)', - 'rgb(201, 203, 207)', - 'rgb(54, 162, 235)' - ] - }] - } - } - - chartOptions: { return { - maintainAspectRatio: false, - title: { - display: true, - text: 'Chart.js PolarArea Chart - Stacked' - }, - tooltips: { - mode: 'index', - intersect: false - } - } - } - } - } - -} diff --git a/example/qml-Qt6/chart/T_RadarChart.qml b/example/qml-Qt6/chart/T_RadarChart.qml deleted file mode 100644 index 76b49925..00000000 --- a/example/qml-Qt6/chart/T_RadarChart.qml +++ /dev/null @@ -1,74 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Radar Chart") - - FluArea{ - width: 500 - height: 370 - paddings: 10 - Layout.topMargin: 20 - FluChart{ - anchors.fill: parent - chartType: 'radar' - chartData: { return { - labels: [ - 'Eating', - 'Drinking', - 'Sleeping', - 'Designing', - 'Coding', - 'Cycling', - 'Running' - ], - datasets: - [{ - label: 'My First Dataset', - data: [65, 59, 90, 81, 56, 55, 40], - fill: true, - backgroundColor: 'rgba(255, 99, 132, 0.2)', - borderColor: 'rgb(255, 99, 132)', - pointBackgroundColor: 'rgb(255, 99, 132)', - pointBorderColor: '#fff', - pointHoverBackgroundColor: '#fff', - pointHoverBorderColor: 'rgb(255, 99, 132)' - }, { - label: 'My Second Dataset', - data: [28, 48, 40, 19, 96, 27, 100], - fill: true, - backgroundColor: 'rgba(54, 162, 235, 0.2)', - borderColor: 'rgb(54, 162, 235)', - pointBackgroundColor: 'rgb(54, 162, 235)', - pointBorderColor: '#fff', - pointHoverBackgroundColor: '#fff', - pointHoverBorderColor: 'rgb(54, 162, 235)' - }] - } - } - chartOptions: { return { - maintainAspectRatio: false, - title: { - display: true, - text: 'Chart.js Radar Chart - Stacked' - }, - tooltips: { - mode: 'index', - intersect: false - }, - elements: { - line: { - borderWidth: 3 - } - } - } - } - } - } - -} diff --git a/example/qml-Qt6/chart/T_ScatterChart.qml b/example/qml-Qt6/chart/T_ScatterChart.qml deleted file mode 100644 index 2e0778c6..00000000 --- a/example/qml-Qt6/chart/T_ScatterChart.qml +++ /dev/null @@ -1,123 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Scatter 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 - }, - }], - } - } - } - } - } - -} diff --git a/example/qml-Qt6/component/CodeExpander.qml b/example/qml-Qt6/component/CodeExpander.qml deleted file mode 100644 index 52d0291d..00000000 --- a/example/qml-Qt6/component/CodeExpander.qml +++ /dev/null @@ -1,144 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI - -FluExpander{ - - id:control - property string code: "" - headerText: qsTr("Source") - contentHeight:content.height - focus: false - - FluCopyableText{ - id:content - width:parent.width - text:highlightQmlCode(code) - textFormat: FluMultilineTextBox.RichText - padding: 10 - topPadding: 10 - leftPadding: 10 - rightPadding: 10 - bottomPadding: 10 - } - - FluIconButton{ - iconSource:FluentIcons.Copy - anchors{ - right: parent.right - top: parent.top - rightMargin: 5 - topMargin: 5 - } - onClicked:{ - FluTools.clipText(FluTools.html2PlantText(content.text)) - showSuccess(qsTr("The Copy is Successful")) - } - } - - 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) { - 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", - "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", - "FluStatusLayout", - "FluRatingControl", - "FluPasswordBox", - "FluBreadcrumbBar", - "FluCopyableText", - "FluAcrylic", - "FluRemoteLoader", - "FluMenuBar", - "FluPagination", - "FluRadioButtons", - "FluImage", - "FluSpinBox", - "FluWatermark", - "FluTour", - "FluQRCode", - "FluTimeline", - "FluChart", - "FluRangeSlider", - "FluStaggeredLayout", - "FluProgressButton", - "FluLoadingButton", - "FluClip", - "FluNetwork", - "FluShortcutPicker" - ]; - 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/global/ItemsFooter.qml b/example/qml-Qt6/global/ItemsFooter.qml deleted file mode 100644 index 85d466f8..00000000 --- a/example/qml-Qt6/global/ItemsFooter.qml +++ /dev/null @@ -1,33 +0,0 @@ -pragma Singleton - -import QtQuick -import FluentUI - -FluObject{ - - property var navigationView - property var paneItemMenu - - id:footer_items - - FluPaneItemSeparator{} - - FluPaneItem{ - title:qsTr("About") - icon:FluentIcons.Contact - onTapListener:function(){ - FluApp.navigate("/about") - } - } - - FluPaneItem{ - title:qsTr("Settings") - menuDelegate: paneItemMenu - icon:FluentIcons.Settings - url:"qrc:/example/qml/page/T_Settings.qml" - onTap:{ - navigationView.push(url) - } - } - -} diff --git a/example/qml-Qt6/global/ItemsOriginal.qml b/example/qml-Qt6/global/ItemsOriginal.qml deleted file mode 100644 index 13137a8b..00000000 --- a/example/qml-Qt6/global/ItemsOriginal.qml +++ /dev/null @@ -1,532 +0,0 @@ -pragma Singleton - -import QtQuick -import FluentUI - -FluObject{ - - property var navigationView - property var paneItemMenu - - function rename(item, newName){ - if(newName && newName.trim().length>0){ - item.title = newName; - } - } - - FluPaneItem{ - id:item_home - count: 9 - title: qsTr("Home") - menuDelegate: paneItemMenu - infoBadge: FluBadge{ - count: item_home.count - } - icon: FluentIcons.Home - url: "qrc:/example/qml/page/T_Home.qml" - onTap: { - if(navigationView.getCurrentUrl()){ - item_home.count = 0 - } - navigationView.push(url) - } - } - - FluPaneItemExpander{ - title: qsTr("PaneItemExpander Disabled") - iconVisible: false - disabled: true - } - - FluPaneItemExpander{ - id: item_expander_basic_input - title: qsTr("Basic Input") - icon: FluentIcons.CheckboxComposite - FluPaneItem{ - id: item_buttons - count: 99 - infoBadge: FluBadge{ - count: item_buttons.count - } - title: qsTr("Buttons") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/Button.png",recentlyUpdated:true,desc:qsTr("A control that responds to user input and raisesa Click event.")}) - url: "qrc:/example/qml/page/T_Buttons.qml" - onTap: { - item_buttons.count = 0 - navigationView.push(url) - } - } - FluPaneItem{ - id: item_text - title: qsTr("Text") - menuDelegate: paneItemMenu - count: 5 - infoBadge: FluBadge{ - count: item_text.count - color: Qt.rgba(82/255,196/255,26/255,1) - } - url: "qrc:/example/qml/page/T_Text.qml" - onTap: { - item_text.count = 0 - navigationView.push(url) - } - } - FluPaneItem{ - title: qsTr("Image") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Image.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Slider") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/Slider.png",recentlyUpdated:true,desc:qsTr("A control that lets the user select from a rangeof values by moving a Thumb control along atrack.")}) - url: "qrc:/example/qml/page/T_Slider.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("CheckBox") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/Checkbox.png",recentlyUpdated:true,desc:qsTr("A control that a user can select or clear.")}) - url: "qrc:/example/qml/page/T_CheckBox.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("RadioButton") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_RadioButton.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("ToggleSwitch") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_ToggleSwitch.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("PaneItem Disabled") - disabled: true - icon: FluentIcons.Error - } - } - - FluPaneItemExpander{ - title: qsTr("Form") - icon: FluentIcons.GridView - FluPaneItem { - title: qsTr("TextBox") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_TextBox.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("TimePicker") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_TimePicker.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("DatePicker") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_DatePicker.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("CalendarPicker") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_CalendarPicker.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("ColorPicker") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_ColorPicker.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("ShortcutPicker") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_ShortcutPicker.qml" - onTap: { navigationView.push(url) } - } - } - - FluPaneItemExpander{ - title: qsTr("Surface") - icon: FluentIcons.SurfaceHub - FluPaneItem{ - title: qsTr("InfoBar") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/InfoBar.png",recentlyUpdated:true,desc:qsTr("An inline message to display app-wide statuschange information.")}) - url: "qrc:/example/qml/page/T_InfoBar.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Progress") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Progress.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("RatingControl") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_RatingControl.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Badge") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Badge.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Rectangle") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Rectangle.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Clip") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Clip.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Carousel") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Carousel.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Expander") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Expander.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Watermark") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Watermark.qml" - onTap: { navigationView.push(url) } - } - } - - FluPaneItemExpander{ - title: qsTr("Layout") - icon: FluentIcons.DockLeft - FluPaneItem { - title: qsTr("StaggeredLayout") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_StaggeredLayout.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("SplitLayout") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_SplitLayout.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("StatusLayout") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_StatusLayout.qml" - onTap: { navigationView.push(url) } - } - } - - FluPaneItemExpander{ - title: qsTr("Popus") - icon: FluentIcons.ButtonMenu - FluPaneItem{ - title: qsTr("Dialog") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Dialog.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - id: item_combobox - title: qsTr("ComboBox") - menuDelegate: paneItemMenu - count: 9 - infoBadge:FluBadge{ - count: item_combobox.count - color: Qt.rgba(250/255,173/255,20/255,1) - } - url: "qrc:/example/qml/page/T_ComboBox.qml" - onTap: { - item_combobox.count = 0 - navigationView.push("qrc:/example/qml/page/T_ComboBox.qml") - } - } - FluPaneItem{ - title: qsTr("Tooltip") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Tooltip.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Menu") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Menu.qml" - onTap: { navigationView.push(url) } - } - } - - FluPaneItemExpander{ - title: qsTr("Navigation") - icon: FluentIcons.AllApps - FluPaneItem{ - title: qsTr("Pivot") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/Pivot.png",order:3,recentlyAdded:true,desc:qsTr("Presents information from different sources in a tabbed view.")}) - url: "qrc:/example/qml/page/T_Pivot.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("BreadcrumbBar") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_BreadcrumbBar.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("TabView") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/TabView.png",order:1,recentlyAdded:true,desc:qsTr("A control that displays a collection of tabs thatcan be used to display several documents.")}) - url: "qrc:/example/qml/page/T_TabView.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("TreeView") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_TreeView.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("TableView") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/DataGrid.png",order:4,recentlyAdded:true,desc:qsTr("The TableView control provides a flexible way to display a collection of data in rows and columns")}) - url: "qrc:/example/qml/page/T_TableView.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Pagination") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Pagination.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("MultiWindow") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_MultiWindow.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("FlipView") - menuDelegate: paneItemMenu - extra: ({image:"qrc:/example/res/image/control/FlipView.png",order:2,recentlyAdded:true,desc:qsTr("Presents a collection of items that the user canflip through, one item at a time.")}) - url: "qrc:/example/qml/page/T_FlipView.qml" - onTap: { navigationView.push(url) } - } - } - - FluPaneItemExpander{ - title: qsTr("Theming") - icon:FluentIcons.Brightness - FluPaneItem{ - title: qsTr("Acrylic") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Acrylic.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Theme") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Theme.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Typography") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Typography.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Awesome") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Awesome.qml" - onTap: { navigationView.push(url) } - } - } - - FluPaneItemExpander{ - title: qsTr("Chart") - icon: FluentIcons.AreaChart - FluPaneItem{ - title: qsTr("Bar Chart") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/chart/T_BarChart.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Line Chart") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/chart/T_LineChart.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Pie Chart") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/chart/T_PieChart.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Polar Area Chart") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/chart/T_PolarAreaChart.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Bubble Chart") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/chart/T_BubbleChart.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Scatter Chart") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/chart/T_ScatterChart.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Radar Chart") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/chart/T_RadarChart.qml" - onTap: { navigationView.push(url) } - } - } - - FluPaneItemSeparator{ - spacing:10 - size:1 - } - - FluPaneItemExpander{ - title: qsTr("Other") - icon: FluentIcons.Shop - FluPaneItem{ - title: qsTr("QRCode") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_QRCode.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Tour") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Tour.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Timeline") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Timeline.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Captcha") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Captcha.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Network") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_Network.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - id: item_other - title: qsTr("Remote Loader") - menuDelegate: paneItemMenu - count: 99 - infoBadge:FluBadge{ - count: item_other.count - color: Qt.rgba(82/255,196/255,26/255,1) - } - url: "qrc:/example/qml/page/T_RemoteLoader.qml" - onTap: { - item_other.count = 0 - navigationView.push("qrc:/example/qml/page/T_RemoteLoader.qml") - } - } - FluPaneItem{ - title: qsTr("Hot Loader") - onTapListener: function(){ - FluApp.navigate("/hotload") - } - } - FluPaneItem{ - title: qsTr("3D") - menuDelegate: paneItemMenu - url: "qrc:/example/qml/page/T_3D.qml" - onTap: { navigationView.push(url) } - } - FluPaneItem{ - title: qsTr("Test Crash") - visible: FluTools.isWin() - onTapListener: function(){ - AppInfo.testCrash() - } - } - } - - function getRecentlyAddedData(){ - var arr = [] - var items = navigationView.getItems(); - 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/qmldir b/example/qml-Qt6/global/qmldir deleted file mode 100644 index eb6bfeaf..00000000 --- a/example/qml-Qt6/global/qmldir +++ /dev/null @@ -1,2 +0,0 @@ -singleton ItemsOriginal 1.0 ItemsOriginal.qml -singleton ItemsFooter 1.0 ItemsFooter.qml diff --git a/example/qml-Qt6/page/T_3D.qml b/example/qml-Qt6/page/T_3D.qml deleted file mode 100644 index d4b38536..00000000 --- a/example/qml-Qt6/page/T_3D.qml +++ /dev/null @@ -1,117 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Window -import FluentUI -import Qt3D.Core -import Qt3D.Render -import Qt3D.Input -import Qt3D.Extras -import QtQuick.Scene3D -import QtQuick.Dialogs -import Qt.labs.platform -import "../component" - -FluContentPage{ - - id:root - title:"3D" - - Scene3D{ - id:scene_3d - anchors.fill: parent - focus: true - aspects: ["input", "logic"] - cameraAspectRatioMode: Scene3D.AutomaticAspectRatio - Entity { - Camera { - id: camera - projectionType: CameraLens.PerspectiveProjection - fieldOfView: 22.5 - aspectRatio: scene_3d.width / scene_3d.height - nearPlane: 1 - farPlane: 1000.0 - viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) - upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) - position: Qt.vector3d( 0.0, 0.0, 15.0 ) - } - FirstPersonCameraController { - linearSpeed: 100 - lookSpeed: 50 - camera: camera - } - components: [ - RenderSettings{ - activeFrameGraph: ForwardRenderer{ - clearColor: Qt.rgba(0,0,0,0); - camera: camera - } - }, - InputSettings{} - ] - Mesh { - id: mesh - source: "https://zhu-zichu.gitee.io/test.obj" - } - PhongMaterial { - id: material - ambient: color_picker.current - } - Transform{ - id:transform - scale: 1.0 - translation: Qt.vector3d(0, 0, 0) - rotation: fromEulerAngles(0, 0, 0) - property real hAngle:0.0 - NumberAnimation on hAngle{ - from:0 - to:360.0 - duration: 5000 - loops: Animation.Infinite - } - matrix:{ - var m=Qt.matrix4x4(); - m.rotate(hAngle,Qt.vector3d(0,1,0)); - m.translate(Qt.vector3d(0,0,0)); - return m; - } - } - Entity { - id: entity - components: [mesh, material,transform] - } - } - } - ColumnLayout{ - RowLayout{ - spacing: 10 - Layout.topMargin: 20 - FluText{ - text:"tintColor:" - Layout.alignment: Qt.AlignVCenter - } - FluColorPicker{ - id:color_picker - current: "gray" - } - } - - FluButton{ - text:"选择obj资源" - onClicked: { - file_dialog.open() - } - } - } - - FileDialog { - id: file_dialog - nameFilters: ["Obj files (*.obj)"] - folder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation) - onAccepted: { - var fileUrl = file_dialog.currentFile - mesh.source = fileUrl - } - } - -} diff --git a/example/qml-Qt6/page/T_Acrylic.qml b/example/qml-Qt6/page/T_Acrylic.qml deleted file mode 100644 index eb1e0801..00000000 --- a/example/qml-Qt6/page/T_Acrylic.qml +++ /dev/null @@ -1,115 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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 - FluClip{ - width: 1920/4 - height: 1200/4 - radius:[8,8,8,8] - 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.current - 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 - preventStealing: true - 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 deleted file mode 100644 index d8e660f5..00000000 --- a/example/qml-Qt6/page/T_Awesome.qml +++ /dev/null @@ -1,71 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI - -FluContentPage { - - title: qsTr("Awesome") - - FluTextBox{ - id:text_box - placeholderText: qsTr("Please enter a keyword") - anchors{ - topMargin: 20 - top:parent.top - } - } - - FluFilledButton{ - text: qsTr("Search") - anchors{ - left: text_box.right - verticalCenter: text_box.verticalCenter - leftMargin: 14 - } - onClicked: { - grid_view.model = FluTheme.awesomeList(text_box.text) - } - } - GridView{ - id:grid_view - cellWidth: 80 - cellHeight: 80 - clip: true - boundsBehavior: GridView.StopAtBounds - model:FluTheme.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(qsTr("You Copied ")+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 deleted file mode 100644 index 4a536a3c..00000000 --- a/example/qml-Qt6/page/T_Badge.qml +++ /dev/null @@ -1,131 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Badge") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 120 - paddings: 10 - - Column{ - spacing: 15 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - right: parent.right - } - FluText{ - wrapMode: Text.WrapAnywhere - width: parent.width - text: qsTr("It usually appears in the upper right corner of the notification icon or avatar to display the number of messages that need to be processed") - } - 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 deleted file mode 100644 index 51cc829d..00000000 --- a/example/qml-Qt6/page/T_BreadcrumbBar.qml +++ /dev/null @@ -1,93 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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: qsTr("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)=>{ - 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 deleted file mode 100644 index 7806e81c..00000000 --- a/example/qml-Qt6/page/T_Buttons.qml +++ /dev/null @@ -1,438 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import QtQuick.Controls.Basic -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Buttons") - - FluText{ - Layout.topMargin: 20 - text: qsTr("Support the Tab key to switch focus, and the Space key to perform click events") - } - - FluArea{ - Layout.fillWidth: true - height: 68 - paddings: 10 - Layout.topMargin: 20 - - FluTextButton{ - disabled: text_button_switch.checked - text: qsTr("Text Button") - onClicked: { - showInfo("点击Text Button") - } - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - } - FluToggleSwitch{ - id: text_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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: qsTr("Standard Button") - onClicked: { - showInfo(qsTr("Click StandardButton")) - } - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - } - FluToggleSwitch{ - id: button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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: qsTr("Filled Button") - onClicked: { - showWarning(qsTr("Click FilledButton")) - } - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - } - FluToggleSwitch{ - id: filled_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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: qsTr("Toggle Button") - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - } - FluToggleSwitch{ - id: toggle_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("Disabled") - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluToggleButton{ - text:"Toggle Button" - onClicked: { - checked = !checked - } -}' - } - - Timer{ - id: timer_progress - interval: 200 - onTriggered: { - btn_progress.progress = (btn_progress.progress + 0.1).toFixed(1) - if(btn_progress.progress==1){ - timer_progress.stop() - }else{ - timer_progress.start() - } - } - } - - FluArea{ - Layout.fillWidth: true - height: 68 - Layout.topMargin: 20 - paddings: 10 - - FluProgressButton{ - id: btn_progress - disabled: progress_button_switch.checked - text: qsTr("Progress Button") - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - onClicked: { - btn_progress.progress = 0 - timer_progress.restart() - } - } - FluToggleSwitch{ - id: progress_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("Disabled") - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluProgressButton{ - text:"Progress Button" - onClicked: { - - } -}' - } - - FluArea{ - Layout.fillWidth: true - height: 68 - Layout.topMargin: 20 - paddings: 10 - - FluLoadingButton{ - id: btn_loading - loading: loading_button_switch.checked - text: qsTr("Loading Button") - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - onClicked: { - - } - } - FluToggleSwitch{ - id: loading_button_switch - checked: true - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("Loading") - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluLoadingButton{ - text:"Loading Button" - onClicked: { - - } -}' - } - - - 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(qsTr("Click IconButton")) - } - } - FluIconButton{ - iconSource: FluentIcons.ChromeCloseContrast - disabled: icon_button_switch.checked - iconSize: 15 - text: qsTr("IconOnly") - display: Button.IconOnly - onClicked:{ - showSuccess(qsTr("Button.IconOnly")) - } - } - FluIconButton{ - iconSource: FluentIcons.ChromeCloseContrast - disabled: icon_button_switch.checked - iconSize: 15 - text: qsTr("TextOnly") - display: Button.TextOnly - onClicked:{ - showSuccess(qsTr("Button.TextOnly")) - } - } - FluIconButton{ - iconSource: FluentIcons.ChromeCloseContrast - disabled: icon_button_switch.checked - iconSize: 15 - text: qsTr("TextBesideIcon") - display: Button.TextBesideIcon - onClicked:{ - showSuccess(qsTr("Button.TextBesideIcon")) - } - } - FluIconButton{ - iconSource: FluentIcons.ChromeCloseContrast - disabled: icon_button_switch.checked - iconSize: 15 - text: qsTr("TextUnderIcon") - display: Button.TextUnderIcon - onClicked:{ - showSuccess(qsTr("Button.TextUnderIcon")) - } - } - } - FluToggleSwitch{ - id: icon_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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: qsTr("DropDownButton") - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluMenuItem{ - text: qsTr("Menu_1") - } - FluMenuItem{ - text: qsTr("Menu_2") - } - FluMenuItem{ - text: qsTr("Menu_3") - } - FluMenuItem{ - text: qsTr("Menu_4") - onClicked: { - - } - } - } - FluToggleSwitch{ - id: drop_down_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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: qsTr("Radio Button_1") - } - FluRadioButton{ - disabled:radio_button_switch.checked - text: qsTr("Radio Button_2") - } - FluRadioButton{ - disabled:radio_button_switch.checked - text: qsTr("Radio Button_3") - } - } - FluToggleSwitch{ - id: radio_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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 deleted file mode 100644 index 1b28b644..00000000 --- a/example/qml-Qt6/page/T_CalendarPicker.qml +++ /dev/null @@ -1,37 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("CalendarPicker") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 80 - paddings: 10 - ColumnLayout{ - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluCalendarPicker{ - onAccepted:{ - showSuccess(current.toLocaleString()) - } - } - } - } - 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 deleted file mode 100644 index 20f7275c..00000000 --- a/example/qml-Qt6/page/T_Captcha.qml +++ /dev/null @@ -1,60 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Captcha") - - FluCaptcha{ - id: captcha - Layout.topMargin: 20 - ignoreCase:switch_case.checked - MouseArea{ - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - captcha.refresh() - } - } - } - - FluButton{ - text: qsTr("Refresh") - Layout.topMargin: 20 - onClicked: { - captcha.refresh() - } - } - - FluToggleSwitch{ - id: switch_case - text: qsTr("Ignore Case") - checked: true - Layout.topMargin: 10 - } - - RowLayout{ - spacing: 10 - Layout.topMargin: 10 - FluTextBox{ - id:text_box - placeholderText: qsTr("Please enter a verification code") - Layout.preferredWidth: 240 - } - FluButton{ - text:"verify" - onClicked: { - var success = captcha.verify(text_box.text) - if(success){ - showSuccess(qsTr("The verification code is correct")) - }else{ - showError(qsTr("Error validation, please re-enter")) - } - } - } - } -} diff --git a/example/qml-Qt6/page/T_Carousel.qml b/example/qml-Qt6/page/T_Carousel.qml deleted file mode 100644 index 401584f8..00000000 --- a/example/qml-Qt6/page/T_Carousel.qml +++ /dev/null @@ -1,147 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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: qsTr("Carousel map, support infinite carousel, infinite swipe, and components implemented with ListView") - } - Item{ - width: 400 - height: 300 - FluShadow{ - radius: 8 - } - FluCarousel{ - anchors.fill: parent - 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 - } - Item{ - width: 400 - height: 300 - FluShadow{ - radius: 8 - } - FluCarousel{ - anchors.fill: parent - 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_CheckBox.qml b/example/qml-Qt6/page/T_CheckBox.qml deleted file mode 100644 index 602270d4..00000000 --- a/example/qml-Qt6/page/T_CheckBox.qml +++ /dev/null @@ -1,114 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("CheckBox") - - FluArea{ - Layout.fillWidth: true - height: 72 - paddings: 10 - Layout.topMargin: 20 - - FluText{ - text: qsTr("A 2-state CheckBox") - } - - Row{ - spacing: 30 - anchors{ - top: parent.top - topMargin: 30 - } - FluCheckBox{ - disabled: check_box_switch_two.checked - } - FluCheckBox{ - disabled: check_box_switch_two.checked - text: qsTr("Right") - } - FluCheckBox{ - disabled: check_box_switch_two.checked - text: qsTr("Left") - textRight: false - } - } - FluToggleSwitch{ - id:check_box_switch_two - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("Disabled") - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluCheckBox{ - text:"Text" -}' - } - - FluArea{ - Layout.fillWidth: true - height: 72 - paddings: 10 - Layout.topMargin: 20 - - FluText{ - text: qsTr("A 3-state CheckBox") - } - - Row{ - spacing: 30 - anchors{ - top: parent.top - topMargin: 30 - } - FluCheckBox{ - property int count: 1 - text: qsTr("Three State") - disabled: check_box_switch_three.checked - clickListener: function(){ - var flag = count%3 - if(flag === 0){ - checked = false - indeterminate = false - } - if(flag === 1){ - checked = true - indeterminate = false - } - if(flag === 2){ - checked = true - indeterminate = true - } - count++ - } - } - } - FluToggleSwitch{ - id: check_box_switch_three - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("Disabled") - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluCheckBox{ - text:"Text" - indeterminate:true -}' - } - -} diff --git a/example/qml-Qt6/page/T_Clip.qml b/example/qml-Qt6/page/T_Clip.qml deleted file mode 100644 index 37d5f31e..00000000 --- a/example/qml-Qt6/page/T_Clip.qml +++ /dev/null @@ -1,106 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Clip") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 380 - paddings: 10 - - Column{ - spacing: 15 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluText{ - text: qsTr("Use with images (this component will have no effect under software rendering)") - Layout.topMargin: 20 - } - RowLayout{ - spacing: 14 - FluClip{ - 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) - } - } - FluClip{ - 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" - } - } - FluClip{ - 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" - } - } - FluClip{ - 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" - } - } - } - FluClip{ - width: 1920/5 - height: 1200/5 - radius: [8,8,8,8] - 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:'FluClip{ - 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_ColorPicker.qml b/example/qml-Qt6/page/T_ColorPicker.qml deleted file mode 100644 index ac8571b0..00000000 --- a/example/qml-Qt6/page/T_ColorPicker.qml +++ /dev/null @@ -1,43 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("ColorPicker") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 60 - paddings: 10 - RowLayout{ - FluText{ - text: qsTr("Click to Select a Color - >") - Layout.alignment: Qt.AlignVCenter - } - FluColorPicker{ - cancelText: qsTr("Cancel") - okText: qsTr("OK") - titleText: qsTr("Color Picker") - editText: qsTr("Edit Color") - redText: qsTr("Red") - greenText: qsTr("Green") - blueText: qsTr("Blue") - opacityText: qsTr("Opacity") - } - } - } - 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 deleted file mode 100644 index 02bd3b1c..00000000 --- a/example/qml-Qt6/page/T_ComboBox.qml +++ /dev/null @@ -1,104 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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: 5 - Layout.topMargin: 20 - Column{ - spacing: 5 - anchors.verticalCenter: parent.verticalCenter - FluText{ - text: "disabled=true" - x:10 - } - FluComboBox { - disabled: true - model: ListModel { - id: model_2 - 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 - model: ListModel { - id: model_3 - ListElement { text: "Banana" } - ListElement { text: "Apple" } - ListElement { text: "Coconut" } - } - onAccepted: { - if (find(editText) === -1) - model_3.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 deleted file mode 100644 index fa4e342f..00000000 --- a/example/qml-Qt6/page/T_DatePicker.qml +++ /dev/null @@ -1,75 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("TimePicker") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 80 - paddings: 10 - ColumnLayout{ - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluText{ - text: qsTr("showYear=true") - } - FluDatePicker{ - current: new Date() - onAccepted: { - 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: qsTr("showYear=false") - } - FluDatePicker{ - showYear: false - yearText: qsTr("Year") - monthText: qsTr("Month") - dayText: qsTr("Day") - cancelText: qsTr("Cancel") - okText: qsTr("OK") - onAccepted: { - 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 deleted file mode 100644 index 23bef093..00000000 --- a/example/qml-Qt6/page/T_Dialog.qml +++ /dev/null @@ -1,232 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Dialog") - - FluArea{ - Layout.fillWidth: true - height: 68 - paddings: 10 - Layout.topMargin: 20 - FluButton{ - anchors.verticalCenter: parent.verticalCenter - text: qsTr("Show Double Button Dialog") - onClicked: { - double_btn_dialog.open() - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluContentDialog{ - id:dialog - title: qsTr("Friendly Reminder") - message: qsTr("Are you sure you want to opt out?") - negativeText: qsTr("Cancel") - buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton - onNegativeClicked:{ - showSuccess(qsTr("Click the Cancel Button")) - } - positiveText: qsTr("OK") - onPositiveClicked:{ - showSuccess(qsTr("Click the OK Button")) - } - } - dialog.open()' - } - - FluContentDialog{ - id:double_btn_dialog - title: qsTr("Friendly Reminder") - message: qsTr("Are you sure you want to opt out?") - buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton - negativeText: qsTr("Cancel") - onNegativeClicked: { - showSuccess(qsTr("Click the Cancel Button")) - } - positiveText: qsTr("OK") - onPositiveClicked:{ - showSuccess(qsTr("Click the OK Button")) - } - } - - FluArea{ - Layout.fillWidth: true - height: 68 - paddings: 10 - Layout.topMargin: 20 - FluButton{ - anchors.verticalCenter: parent.verticalCenter - text: qsTr("Show Triple Button Dialog") - onClicked: { - triple_btn_dialog.open() - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluContentDialog{ - id: dialog - title: qsTr("Friendly Reminder") - message: qsTr("Are you sure you want to opt out?") - negativeText: qsTr("Cancel") - buttonFlags: FluContentDialogType.NeutralButton | FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton - negativeText: qsTr("Cancel") - onNegativeClicked: { - showSuccess(qsTr("Click the Cancel Button")) - } - positiveText: qsTr("OK") - onPositiveClicked: { - showSuccess(qsTr("Click the OK Button")) - } - neutralText: qsTr("Minimize") - onNeutralClicked: { - showSuccess(qsTr("Click Minimize")) - } - } - dialog.open()' - } - - FluContentDialog{ - id: triple_btn_dialog - title: qsTr("Friendly Reminder") - message: qsTr("Are you sure you want to opt out?") - buttonFlags: FluContentDialogType.NeutralButton | FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton - negativeText: qsTr("Cancel") - onNegativeClicked: { - showSuccess(qsTr("Click the Cancel Button")) - } - positiveText: qsTr("OK") - onPositiveClicked: { - showSuccess(qsTr("Click the OK Button")) - } - neutralText: qsTr("Minimize") - onNeutralClicked: { - showSuccess(qsTr("Click Minimize")) - } - } - - FluArea{ - Layout.fillWidth: true - height: 100 - paddings: 10 - Layout.topMargin: 20 - FluButton{ - anchors.top: parent.top - anchors.topMargin: 5 - text: qsTr("Custom Content Dialog") - onClicked: { - custom_btn_dialog.open() - } - } - FluButton{ - anchors.top: parent.top - anchors.topMargin: 48 - text: qsTr("Custom Content Dialog2") - onClicked: { - custom_btn_dialog2.open() - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluContentDialog{ - id: dialog - title: qsTr("Friendly Reminder") - message: qsTr("Data is loading, please wait...") - negativeText: qsTr("Unload") - contentDelegate: Component{ - Item{ - width: parent.width - height: 80 - FluProgressRing{ - anchors.centerIn: parent - } - } - } - onNegativeClicked: { - showSuccess(qsTr("Click the Cancel Button")) - } - positiveText :qsTr("OK") - onPositiveClicked: { - showSuccess(qsTr("Click the OK Button")) - } - } - dialog.open()' - } - - FluContentDialog{ - id: custom_btn_dialog - title: qsTr("Friendly Reminder") - message: qsTr("Data is loading, please wait...") - negativeText: qsTr("Unload") - contentDelegate: Component{ - Item{ - implicitWidth: parent.width - implicitHeight: 80 - FluProgressRing{ - anchors.centerIn: parent - } - } - } - onNegativeClicked: { - showSuccess(qsTr("Click the Cancel Button")) - } - positiveText: qsTr("OK") - onPositiveClickListener: function(){ - showError(qsTr("Test the InfoBar level on top of the Popup")) - } - } - - FluContentDialog{ - id:custom_btn_dialog2 - title: qsTr("Line Chart") - contentDelegate: Component{ - Item{ - implicitWidth: parent.width - implicitHeight: 300 - FluChart{ - anchors.fill: parent - chartType: 'line' - chartData: { return { - labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], - datasets: [{ - label: 'My First Dataset', - data: [65, 59, 80, 81, 56, 55, 40], - fill: false, - borderColor: 'rgb(75, 192, 192)', - tension: 0.1 - }] - } - } - chartOptions: { return { - maintainAspectRatio: false, - title: { - display: true, - text: 'Chart.js Line Chart - Stacked' - }, - tooltips: { - mode: 'index', - intersect: false - } - } - } - } - } - } - buttonFlags: FluContentDialogType.PositiveButton - positiveText: qsTr("OK") - onPositiveClicked: { - showSuccess(qsTr("Click the OK Button")) - } - } -} diff --git a/example/qml-Qt6/page/T_Expander.qml b/example/qml-Qt6/page/T_Expander.qml deleted file mode 100644 index 602f67c9..00000000 --- a/example/qml-Qt6/page/T_Expander.qml +++ /dev/null @@ -1,110 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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: qsTr("Open a radio box") - 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: qsTr("Open a sliding text box") - Item{ - anchors.fill: parent - Flickable{ - id:scrollview - width: parent.width - height: parent.height - contentWidth: width - boundsBehavior: Flickable.StopAtBounds - contentHeight: text_info.height - ScrollBar.vertical: FluScrollBar {} - FluText{ - id:text_info - width: scrollview.width - wrapMode: Text.WrapAnywhere - padding: 14 - text: qsTr("Permit me to observe: the late emperor was taken from us before he could finish his life`s work, the restoration of Han. Today, the empire is still divided in three, and our very survival is threatened. Yet still the officials at court and the soldiers throughout the realm remain loyal to you, your majesty. Because they remember the late emperor, all of them, and they wish to repay his kindness in service to you. This is the moment to extend your divine influence, to honour the memory of the late Emperor and strengthen the morale of your officers. It is not time to listen to bad advice, or close your ears to the suggestions of loyal men. -The court and the administration are as one. Both must be judged by one standard. Those who are loyal and good must get what they deserve, but so must the evil-doers who break the law. This will demonstrate the justice of your rule. There cannot be one law for the court and another for the administration. -Counselors and attendants like Guo Youzhi, Fei Yi, and Dong Yun are all reliable men, loyal of purpose and pure in motive. The late Emperor selected them for office so that they would serve you after his death.These are the men who should be consulted on all palace affairs. Xiang Chong has proved himself a fine general in battle, and the late Emperor believed in him. That is why the assembly has recommended him for overall command. It will keep the troops happy if he is consulted on all military matters. -Xiang Chong has proved himself a fine general in battle, and the late Emperor believed in him. That is why the assembly has recommended him for overall command. It will keep the troops happy if he is consulted on all military matters. -The emperors of the Western Han chose their courtiers wisely, and their dynasty flourished. The emperors of the Eastern Han chose poorly, and they doomed the empire to ruin. Whenever the late Emperor discussed this problem with me, he lamented the failings of Emperors Huan and Ling. Advisors like Guo Youzhi, Fei Yi, Chen Zhen, Zhang Yi, and Jiang Wan – these are all men of great integrity and devotion. I encourage you to trust them, your majesty, if the house of Han is to rise again. -I begin as a common man, farming in my fields in Nanyang, doing what I could to survive in an age of chaos. I never had any interest in making a name for myself as a noble. The late Emperor was not ashamed to visit my cottage and seek my advice. Grateful for his regard, I responded to his appeal and threw myself into his service. Now twenty-one years has passed, the late Emperor always appreciated my caution and, in his final days, entrusted me with his cause. -Since that moment, I have been tormented day and night by the fear that I might let him down. That is why I crossed the Lu river at the height of summer, and entered the wastelands beyond. Now the south has been subdued, and our forces are fully armed.I should lead our soldiers to conquer the northern heartland and attempt to remove the hateful traitors, restore the house of Han, and return it to the former capital.This the way I mean to honor my debt to the late Emperor and fulfill my duty to you. Guo Youzhi, Fei Yi, and Dong Yun are the ones who should be making policy decisions and recommendations. -My only desire is to be permitted to drive out the traitors and restore the Han. If I should let you down, punish my offense and report it to the spirit of the late Emperor. If those three advisors should fail in their duties, then they should be punished for their negligence.Your Majesty, consider your course of action carefully. Seek out good advice, and never forget the late Emperor. I depart now on a long expedition, and I will be forever grateful if you heed my advice. Blinded by my own tears, I know not what I write.") - } - } - } - } - } - } - - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluExpander{ - headerText: qsTr("Open a radio box") - 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: qsTr("Permit me to observe: the late emperor was taken from us before he could finish his life`s work...") - } - } - } -}' - } - - -} diff --git a/example/qml-Qt6/page/T_FlipView.qml b/example/qml-Qt6/page/T_FlipView.qml deleted file mode 100644 index 4d75df9e..00000000 --- a/example/qml-Qt6/page/T_FlipView.qml +++ /dev/null @@ -1,117 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("FlipView") - - FluArea{ - Layout.fillWidth: true - height: 340 - paddings: 10 - Layout.topMargin: 20 - ColumnLayout{ - anchors.verticalCenter: parent.verticalCenter - FluText{ - text: qsTr("Horizontal 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: qsTr("Vertical 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 deleted file mode 100644 index 3437c4ea..00000000 --- a/example/qml-Qt6/page/T_Home.qml +++ /dev/null @@ -1,294 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../global" -import "../window" - - -FluScrollablePage{ - - launchMode: FluPageType.SingleTask - animDisabled: true - - FluentInitalizrWindow{ - id:fluent_initalizr - } - - ListModel{ - id: model_header - ListElement{ - icon: "qrc:/example/res/image/ic_home_github.png" - title: qsTr("FluentUI GitHub") - desc: qsTr("The latest FluentUI controls and styles for your applications.") - url: "https://github.com/zhuzichu520/FluentUI" - clicked: function(model){ - Qt.openUrlExternally(model.url) - } - } - ListElement{ - icon: "qrc:/example/res/image/favicon.ico" - title: qsTr("FluentUI Initalizr") - desc: qsTr("FluentUI Initializr is a Tool that helps you create and customize Fluent UI projects with various options.") - url: "https://github.com/zhuzichu520/FluentUI" - clicked: function(model){ - fluent_initalizr.showDialog() - } - } - } - Item{ - Layout.fillWidth: true - Layout.preferredHeight: 320 - Image { - id: bg - fillMode:Image.PreserveAspectCrop - anchors.fill: parent - verticalAlignment: Qt.AlignTop - sourceSize: Qt.size(960,640) - 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 - } - } - Component{ - id:com_grallery - Item{ - id: control - width: 220 - height: 240 - FluShadow{ - radius:5 - anchors.fill: item_content - } - FluClip{ - id:item_content - radius: [5,5,5,5] - 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: 5 - color:FluTheme.itemHoverColor - visible: item_mouse.containsMouse - } - Rectangle{ - anchors.fill: parent - radius: 5 - color:Qt.rgba(0,0,0,0.0) - visible: !item_mouse.containsMouse - } - 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: { - model.clicked(model) - } - } - } - } - } - - 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: com_grallery - } - } - - Component{ - id:com_item - Item{ - property string desc: modelData.extra.desc - width: 320 - height: 120 - FluArea{ - radius: 8 - width: 300 - height: 100 - anchors.centerIn: parent - Rectangle{ - anchors.fill: parent - radius: 8 - color:{ - if(item_mouse.containsMouse){ - return FluTheme.itemHoverColor - } - return FluTheme.itemNormalColor - } - } - Image{ - id:item_icon - height: 40 - width: 40 - source: modelData.extra.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: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 - 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_Image.qml b/example/qml-Qt6/page/T_Image.qml deleted file mode 100644 index be2745ea..00000000 --- a/example/qml-Qt6/page/T_Image.qml +++ /dev/null @@ -1,48 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Image") - - FluArea{ - Layout.fillWidth: true - height: 260 - paddings: 10 - Layout.topMargin: 20 - Column{ - spacing: 15 - anchors{ - verticalCenter: parent.verticalCenter - left:parent.left - } - FluImage{ - width: 384 - height: 240 - source: "https://gitee.com/zhu-zichu/zhu-zichu/raw/74f075efe2f8d3c3bb7ba3c2259e403450e4050b/image/banner_4.jpg" - onStatusChanged:{ - if(status === Image.Error){ - showError(qsTr("The image failed to load, please reload")) - } - } - clickErrorListener: function(){ - source = "https://gitee.com/zhu-zichu/zhu-zichu/raw/74f075efe2f8d3c3bb7ba3c2259e403450e4050b/image/banner_1.jpg" - } - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluImage{ - width: 400 - height: 300 - source: "https://gitee.com/zhu-zichu/zhu-zichu/raw/74f075efe2f8d3c3bb7ba3c2259e403450e4050b/image/banner_1.jpg" -}' - } - -} diff --git a/example/qml-Qt6/page/T_InfoBar.qml b/example/qml-Qt6/page/T_InfoBar.qml deleted file mode 100644 index 89406e2e..00000000 --- a/example/qml-Qt6/page/T_InfoBar.qml +++ /dev/null @@ -1,72 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("InfoBar") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 270 - paddings: 10 - ColumnLayout{ - spacing: 14 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluButton{ - text: qsTr("Info") - onClicked: { - showInfo(qsTr("This is an InfoBar in the Info Style")) - } - } - FluButton{ - text: qsTr("Warning") - onClicked: { - showWarning(qsTr("This is an InfoBar in the Warning Style")) - } - } - FluButton{ - text:"Error" - onClicked: { - showError(qsTr("This is an InfoBar in the Error Style")) - } - } - FluButton{ - text:"Success" - onClicked: { - showSuccess(qsTr("This is an InfoBar in the Success Style")) - } - } - FluButton{ - text: qsTr("InfoBar that needs to be turned off manually") - onClicked: { - showInfo(qsTr("This is an InfoBar in the Info Style"),0,qsTr("Manual shutdown is supported")) - } - } - FluButton{ - text:"Loading" - onClicked: { - showLoading() - } - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'showInfo(qsTr("This is an InfoBar in the Info Style")) - -showWarning(qsTr("This is an InfoBar in the Warning Style")) - -showError(qsTr("This is an InfoBar in the Error Style")) - -showSuccess(qsTr("This is an InfoBar in the Success Style"))' - } -} diff --git a/example/qml-Qt6/page/T_Menu.qml b/example/qml-Qt6/page/T_Menu.qml deleted file mode 100644 index 56b5ef09..00000000 --- a/example/qml-Qt6/page/T_Menu.qml +++ /dev/null @@ -1,171 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Menu") - - FluMenu { - id:menu - title: qsTr("File") - Action { text: qsTr("New...")} - Action { text: qsTr("Open...") } - Action { text: qsTr("Save") } - FluMenuSeparator { } - FluMenuItem{ - text: qsTr("Quit") - onTriggered: { - showError("Quit") - } - } - FluMenuItem{ - text: qsTr("Search") - iconSource: FluentIcons.Zoom - iconSpacing: 3 - onTriggered: { - showError(qsTr("Search")) - } - } - Action { - text: qsTr("Disable") - enabled:false - onTriggered: { - showError(qsTr("Disable")) - } - } - FluMenuSeparator { } - Action { text: qsTr("Check");checkable: true;checked: true} - FluMenu{ - title: qsTr("Save As...") - Action { text: qsTr("Doc") } - Action { text: qsTr("PDF") } - } - } - - - FluArea{ - Layout.fillWidth: true - height: 100 - paddings: 10 - Layout.topMargin: 20 - Column{ - id: layout_column - spacing: 15 - anchors{ - verticalCenter: parent.verticalCenter - left:parent.left - } - - FluText{ - text: qsTr("Menu") - } - - FluButton{ - text: qsTr("Show Menu Popup") - Layout.topMargin: 20 - onClicked:{ - menu.popup() - } - } - - - } - } - - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluMenu{ - id:menu - FluMenuItem:{ - text:"删除" - onClicked: { - showError("删除") - } - } - FluMenuItem:{ - text:"修改" - onClicked: { - showInfo("修改") - } - } -} -menu.popup() -' - } - - - FluArea{ - Layout.fillWidth: true - height: 100 - paddings: 10 - Layout.topMargin: 20 - Column{ - spacing: 15 - anchors{ - verticalCenter: parent.verticalCenter - left:parent.left - } - - FluText{ - text: qsTr("MenuBar") - } - - FluMenuBar { - id:menu_bar - FluMenu { - title: qsTr("File") - Action { text: qsTr("New...") } - Action { text: qsTr("Open...") } - Action { text: qsTr("Save") } - FluMenuSeparator { } - Action { text: qsTr("Quit") } - Action { - text: qsTr("Disable") - enabled:false - } - FluMenu{ - title: qsTr("Save As...") - Action { text: qsTr("Doc") } - Action { text: qsTr("PDF") } - } - } - FluMenu { - title: qsTr("Edit") - Action { text: qsTr("Cut") } - Action { text: qsTr("Copy") } - Action { text: qsTr("Paste") } - } - FluMenu { - title: qsTr("Help") - Action { text: qsTr("About") } - } - } - - } - } - - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluMenuBar{ - id:menu - FluMenu:{ - title:"File" - Action { text: qsTr("New...") } - } - FluMenu:{ - title:"Edit" - Action { text: qsTr("Cut") } - Action { text: qsTr("Copy") } - Action { text: qsTr("Paste") } - } -} -menu.popup() -' - } -} diff --git a/example/qml-Qt6/page/T_MultiWindow.qml b/example/qml-Qt6/page/T_MultiWindow.qml deleted file mode 100644 index 1f21a789..00000000 --- a/example/qml-Qt6/page/T_MultiWindow.qml +++ /dev/null @@ -1,186 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - property string password: "" - property var loginPageRegister: registerForWindowResult("/login") - - title: qsTr("MultiWindow") - - Connections{ - target: loginPageRegister - function onResult(data) - { - password = data.password - } - } - - FluArea{ - Layout.fillWidth: true - height: 86 - paddings: 10 - Layout.topMargin: 20 - Column{ - spacing: 15 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluText{ - text: qsTr("Standard mode window,a new window is created every time") - } - FluButton{ - text: qsTr("Create Window") - 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: qsTr("SingleTask mode window,If a window exists, this activates the window") - textFormat: Text.RichText - } - FluButton{ - text: qsTr("Create Window") - 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: qsTr("SingleInstance mode window,If the window exists, destroy the window and create a new window") - } - FluButton{ - text: qsTr("Create Window") - 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: qsTr("Create the window without carrying any parameters") - } - FluButton{ - text: qsTr("Create Window") - onClicked: { - FluApp.navigate("/about") - } - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluButton{ - text: qsTr("Create Window") - 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: qsTr("Create a window with the parameter username: zhuzichu") - } - FluButton{ - text: qsTr("Create Window") - onClicked: { - loginPageRegister.launch({username:"zhuzichu"}) - } - } - FluText{ - text:qsTr("Login Window Returned Password - >")+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: qsTr("Create Window") - onClicked: { - loginPageRegister.launch({username:"zhuzichu"}) - } -} -' - } - -} diff --git a/example/qml-Qt6/page/T_Network.qml b/example/qml-Qt6/page/T_Network.qml deleted file mode 100644 index f4313c92..00000000 --- a/example/qml-Qt6/page/T_Network.qml +++ /dev/null @@ -1,560 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import Qt.labs.platform -import "../component" - -FluContentPage{ - - id:root - title: qsTr("Network") - - FluNetworkCallable{ - id:callable - onStart: { - showLoading() - } - onFinish: { - hideLoading() - } - onError: - (status,errorString,result)=>{ - console.debug(status+";"+errorString+";"+result) - } - onCache: - (result)=>{ - text_info.text = result - } - onSuccess: - (result)=>{ - text_info.text = result - } - } - - Flickable{ - id:layout_flick - width: 200 - clip: true - anchors{ - top: parent.top - topMargin: 20 - bottom: parent.bottom - left: parent.left - } - boundsBehavior: Flickable.StopAtBounds - 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: { - text_info.text = "" - FluNetwork.get("https://httpbingo.org/get") - .addQuery("name","孙悟空") - .addQuery("age",500) - .addQuery("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Head" - onClicked: { - text_info.text = "" - FluNetwork.head("https://httpbingo.org/head") - .addQuery("name","孙悟空") - .addQuery("age",500) - .addQuery("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Post Body" - onClicked: { - text_info.text = "" - FluNetwork.postBody("https://httpbingo.org/post") - .setBody("花果山水帘洞美猴王齐天大圣孙悟空") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Post Form" - onClicked: { - text_info.text = "" - FluNetwork.postForm("https://httpbingo.org/post") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Post JSON" - onClicked: { - text_info.text = "" - FluNetwork.postJson("https://httpbingo.org/post") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Post JSON Array" - onClicked: { - text_info.text = "" - FluNetwork.postJsonArray("https://httpbingo.org/post") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Put Body" - onClicked: { - text_info.text = "" - FluNetwork.putBody("https://httpbingo.org/put") - .setBody("花果山水帘洞美猴王齐天大圣孙悟空") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Put Form" - onClicked: { - text_info.text = "" - FluNetwork.putForm("https://httpbingo.org/put") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Put JSON" - onClicked: { - text_info.text = "" - FluNetwork.putJson("https://httpbingo.org/put") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Put JSON Array" - onClicked: { - text_info.text = "" - FluNetwork.putJsonArray("https://httpbingo.org/put") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Patch Body" - onClicked: { - text_info.text = "" - FluNetwork.patchBody("https://httpbingo.org/patch") - .setBody("花果山水帘洞美猴王齐天大圣孙悟空") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Patch Form" - onClicked: { - text_info.text = "" - FluNetwork.patchForm("https://httpbingo.org/patch") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Patch JSON" - onClicked: { - text_info.text = "" - FluNetwork.patchJson("https://httpbingo.org/patch") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Patch JSON Array" - onClicked: { - text_info.text = "" - FluNetwork.patchJsonArray("https://httpbingo.org/patch") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Delete Body" - onClicked: { - text_info.text = "" - FluNetwork.deleteBody("https://httpbingo.org/delete") - .setBody("花果山水帘洞美猴王齐天大圣孙悟空") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Delete Form" - onClicked: { - text_info.text = "" - FluNetwork.deleteForm("https://httpbingo.org/delete") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Delete JSON" - onClicked: { - text_info.text = "" - FluNetwork.deleteJson("https://httpbingo.org/delete") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Delete JSON Array" - onClicked: { - text_info.text = "" - FluNetwork.deleteJsonArray("https://httpbingo.org/delete") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Open Log" - onClicked: { - text_info.text = "" - FluNetwork.postJson("https://httpbingo.org/post") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .openLog(true) - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Custom Header" - onClicked: { - text_info.text = "" - FluNetwork.postJson("https://httpbingo.org/post") - .addHeader("os","PC") - .addHeader("version","1.0.0") - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "RequestFailedReadCache" - onClicked: { - text_info.text = "" - FluNetwork.postJson("https://httpbingo.org/post") - .setCacheMode(FluNetworkType.RequestFailedReadCache) - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .add("cacheMode","RequestFailedReadCache") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "IfNoneCacheRequest" - onClicked: { - text_info.text = "" - FluNetwork.postJson("https://httpbingo.org/post") - .setCacheMode(FluNetworkType.IfNoneCacheRequest) - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .add("cacheMode","IfNoneCacheRequest") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "FirstCacheThenRequest" - onClicked: { - text_info.text = "" - FluNetwork.postJson("https://httpbingo.org/post") - .setCacheMode(FluNetworkType.FirstCacheThenRequest) - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .add("cacheMode","FirstCacheThenRequest") - .bind(root) - .go(callable) - } - } - FluButton{ - implicitWidth: parent.width - implicitHeight: 36 - text: "Timeout And Retry" - onClicked: { - text_info.text = "" - FluNetwork.postJson("https://httpbingo.org/post") - .setTimeout(5000) - .setRetry(3) - .add("name","孙悟空") - .add("age",500) - .add("address","花果山水帘洞") - .add("timeout","5000") - .add("retry","3") - .bind(root) - .go(callable) - } - } - FluProgressButton{ - id:btn_upload - implicitWidth: parent.width - implicitHeight: 36 - text: "Upload File" - onClicked: { - file_dialog.open() - } - } - FluProgressButton{ - id:btn_download - implicitWidth: parent.width - implicitHeight: 36 - text: "Download File" - onClicked: { - folder_dialog.showDialog(function(path){ - FluNetwork.get("http://vjs.zencdn.net/v/oceans.mp4") - .toDownload(path) - .bind(root) - .go(callable_download_file) - }) - } - } - FluProgressButton{ - id:btn_download_breakpoint - implicitWidth: parent.width - implicitHeight: 36 - text: "Breakpoint Download File" - onClicked: { - folder_dialog.showDialog(function(path){ - FluNetwork.get("http://vjs.zencdn.net/v/oceans.mp4") - .toDownload(path,true) - .bind(root) - .go(callable_breakpoint_download_file) - }) - } - } - } - } - - FluNetworkCallable{ - id:callable_upload_file - onStart: { - btn_upload.disabled = true - } - onFinish: { - btn_upload.disabled = false - } - onError: - (status,errorString,result)=>{ - btn_upload.progress = 0 - text_info.text = result - console.debug(status+";"+errorString+";"+result) - } - onSuccess: - (result)=>{ - text_info.text = result - } - onUploadProgress: - (sent,total)=>{ - btn_upload.progress = sent/total - } - } - - FluNetworkCallable{ - id:callable_download_file - onStart: { - btn_download.progress = 0 - btn_download.disabled = true - } - onFinish: { - btn_download.disabled = false - } - onError: - (status,errorString,result)=>{ - btn_download.progress = 0 - showError(errorString) - console.debug(status+";"+errorString+";"+result) - } - onSuccess: - (result)=>{ - showSuccess(result) - } - onDownloadProgress: - (recv,total)=>{ - btn_download.progress = recv/total - } - } - - FluNetworkCallable{ - id:callable_breakpoint_download_file - onStart: { - btn_download_breakpoint.progress = 0 - btn_download_breakpoint.disabled = true - } - onFinish: { - btn_download_breakpoint.disabled = false - } - onError: - (status,errorString,result)=>{ - btn_download_breakpoint.progress = 0 - showError(errorString) - console.debug(status+";"+errorString+";"+result) - } - onSuccess: - (result)=>{ - showSuccess(result) - } - onDownloadProgress: - (recv,total)=>{ - btn_download_breakpoint.progress = recv/total - } - } - - FileDialog { - id: file_dialog - onAccepted: { - FluNetwork.postForm("https://httpbingo.org/post") - .setRetry(1)//只请求一次 - .add("accessToken","12345678") - .addFile("file",FluTools.toLocalPath(file_dialog.currentFile)) - .bind(root) - .go(callable_upload_file) - } - } - - FileDialog { - property var onSelectListener - id: folder_dialog - folder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0] - currentFile: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]+"/oceans.mp4" - fileMode: FileDialog.SaveFile - onAccepted: { - folder_dialog.onSelectListener(FluTools.toLocalPath(folder_dialog.currentFile)) - } - function showDialog(listener){ - folder_dialog.onSelectListener = listener - folder_dialog.open() - } - } - - FluArea{ - anchors{ - top: layout_flick.top - bottom: layout_flick.bottom - left: layout_flick.right - right: parent.right - leftMargin: 8 - } - Flickable{ - clip: true - id:scrollview - boundsBehavior:Flickable.StopAtBounds - 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 - } - } - } -} diff --git a/example/qml-Qt6/page/T_Pagination.qml b/example/qml-Qt6/page/T_Pagination.qml deleted file mode 100644 index f2e85c11..00000000 --- a/example/qml-Qt6/page/T_Pagination.qml +++ /dev/null @@ -1,49 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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 deleted file mode 100644 index b52a4928..00000000 --- a/example/qml-Qt6/page/T_Pivot.qml +++ /dev/null @@ -1,82 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Pivot") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 400 - paddings: 10 - - - - FluPivot{ - anchors.fill: parent - currentIndex: 2 - - FluPivotItem{ - title: qsTr("All") - contentItem:FluText{ - text: qsTr("All emails go here.") - } - } - FluPivotItem{ - title: qsTr("Unread") - contentItem: FluText{ - text: qsTr("Unread emails go here.") - } - } - FluPivotItem{ - title: qsTr("Flagged") - contentItem: FluText{ - text: qsTr("Flagged emails go here.") - } - } - FluPivotItem{ - title: qsTr("Urgent") - contentItem: FluText{ - text: qsTr("Urgent emails go here.") - } - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluPivot{ - anchors.fill: parent - FluPivotItem:{ - text: qsTr("All") - contentItem: FluText{ - text: qsTr("All emails go here.") - } - } - FluPivotItem:{ - text: qsTr("Unread") - contentItem: FluText{ - text: qsTr("Unread emails go here.") - } - } - FluPivotItem:{ - text: qsTr("Flagged") - contentItem: FluText{ - text: qsTr("Flagged emails go here.") - } - } - FluPivotItem:{ - text: qsTr("Urgent") - contentItem: FluText{ - text: qsTr("Urgent emails go here.") - } - } -} -' - } -} diff --git a/example/qml-Qt6/page/T_Progress.qml b/example/qml-Qt6/page/T_Progress.qml deleted file mode 100644 index ecbfb488..00000000 --- a/example/qml-Qt6/page/T_Progress.qml +++ /dev/null @@ -1,103 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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 deleted file mode 100644 index 9ed3ced0..00000000 --- a/example/qml-Qt6/page/T_QRCode.qml +++ /dev/null @@ -1,102 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("QRCode") - - FluQRCode{ - id:qrcode - Layout.topMargin: 20 - size:slider_size.value - text:text_box.text - color:color_picker.current - bgColor: bgcolor_picker.current - 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:"会磨刀的小猪" - Layout.preferredWidth: 240 - } - } - - RowLayout{ - spacing: 10 - Layout.topMargin: 10 - FluText{ - text:"color:" - Layout.alignment: Qt.AlignVCenter - } - FluColorPicker{ - id:color_picker - current: Qt.rgba(0,0,0,1) - } - } - - RowLayout{ - spacing: 10 - Layout.topMargin: 10 - FluText{ - text:"bgColor:" - Layout.alignment: Qt.AlignVCenter - } - FluColorPicker{ - id:bgcolor_picker - current: 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 deleted file mode 100644 index eae17351..00000000 --- a/example/qml-Qt6/page/T_RadioButton.qml +++ /dev/null @@ -1,101 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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: qsTr("Right") - } - FluRadioButton{ - disabled: radio_button_switch.checked - text: qsTr("Left") - textRight: false - } - } - FluToggleSwitch{ - id: radio_button_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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: qsTr("Radio Button_1") - } - FluRadioButton{ - disabled: radio_button_switch2.checked - text: qsTr("Radio Button_2") - } - FluRadioButton{ - disabled: radio_button_switch2.checked - text: qsTr("Radio Button_3") - } - } - FluToggleSwitch{ - id: radio_button_switch2 - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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 deleted file mode 100644 index 3a20e844..00000000 --- a/example/qml-Qt6/page/T_RatingControl.qml +++ /dev/null @@ -1,35 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage { - - title: qsTr("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 deleted file mode 100644 index 9426e66f..00000000 --- a/example/qml-Qt6/page/T_Rectangle.qml +++ /dev/null @@ -1,74 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Rectangle") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 80 - paddings: 10 - - Column{ - spacing: 15 - anchors{ - left: parent.left - verticalCenter: parent.verticalCenter - } - 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] - } - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluRectangle{ - radius: [25,25,25,25] - width: 50 - height: 50 -}' - } -} diff --git a/example/qml-Qt6/page/T_RemoteLoader.qml b/example/qml-Qt6/page/T_RemoteLoader.qml deleted file mode 100644 index 8a1d077e..00000000 --- a/example/qml-Qt6/page/T_RemoteLoader.qml +++ /dev/null @@ -1,14 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../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_Settings.qml b/example/qml-Qt6/page/T_Settings.qml deleted file mode 100644 index c9f9e8a9..00000000 --- a/example/qml-Qt6/page/T_Settings.qml +++ /dev/null @@ -1,205 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../global" -import "../component" -import "../viewmodel" - -FluScrollablePage{ - - title: qsTr("Settings") - - SettingsViewModel{ - id:viewmodel_settings - } - - FluEvent{ - id:event_checkupdate_finish - name: "checkUpdateFinish" - onTriggered: { - btn_checkupdate.loading = false - } - } - - Component.onCompleted: { - FluEventBus.registerEvent(event_checkupdate_finish) - } - - Component.onDestruction: { - FluEventBus.unRegisterEvent(event_checkupdate_finish) - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 60 - paddings: 10 - Row{ - spacing: 20 - anchors.verticalCenter: parent.verticalCenter - FluText{ - text: "%1 v%2".arg(qsTr("Current Version")).arg(AppInfo.version) - font: FluTextStyle.Body - anchors.verticalCenter: parent.verticalCenter - } - FluLoadingButton{ - id: btn_checkupdate - text: qsTr("Check for Updates") - anchors.verticalCenter: parent.verticalCenter - onClicked: { - loading = true - FluEventBus.post("checkUpdate") - } - } - } - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 50 - paddings: 10 - FluCheckBox{ - text: qsTr("Use System AppBar") - checked: FluApp.useSystemAppBar - anchors.verticalCenter: parent.verticalCenter - onClicked: { - FluApp.useSystemAppBar = !FluApp.useSystemAppBar - dialog_restart.open() - } - } - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 50 - paddings: 10 - FluCheckBox{ - text:qsTr("Fits AppBar Windows") - checked: window.fitsAppBarWindows - anchors.verticalCenter: parent.verticalCenter - onClicked: { - window.fitsAppBarWindows = !window.fitsAppBarWindows - } - } - } - - FluContentDialog{ - id: dialog_restart - title: qsTr("Friendly Reminder") - message: qsTr("This action requires a restart of the program to take effect, is it restarted?") - buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton - negativeText: qsTr("Cancel") - positiveText: qsTr("OK") - onPositiveClicked: { - FluApp.exit(931) - } - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 128 - paddings: 10 - - ColumnLayout{ - spacing: 5 - anchors{ - top: parent.top - left: parent.left - } - FluText{ - text: qsTr("Dark Mode") - font: FluTextStyle.BodyStrong - Layout.bottomMargin: 4 - } - Repeater{ - model: [{title:qsTr("System"),mode:FluThemeType.System},{title:qsTr("Light"),mode:FluThemeType.Light},{title:qsTr("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:qsTr("Navigation View Display Mode") - font: FluTextStyle.BodyStrong - Layout.bottomMargin: 4 - } - Repeater{ - model: [{title:qsTr("Open"),mode:FluNavigationViewType.Open},{title:qsTr("Compact"),mode:FluNavigationViewType.Compact},{title:qsTr("Minimal"),mode:FluNavigationViewType.Minimal},{title:qsTr("Auto"),mode:FluNavigationViewType.Auto}] - delegate: FluRadioButton{ - checked : viewmodel_settings.displayMode===modelData.mode - text:modelData.title - clickListener:function(){ - viewmodel_settings.displayMode = modelData.mode - } - } - } - } - } - - ListModel{ - id:model_language - ListElement{ - name:"en" - } - ListElement{ - name:"zh" - } - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 80 - paddings: 10 - - ColumnLayout{ - spacing: 10 - anchors{ - top: parent.top - left: parent.left - } - FluText{ - text:qsTr("Language") - font: FluTextStyle.BodyStrong - Layout.bottomMargin: 4 - } - Flow{ - spacing: 5 - Repeater{ - model: TranslateHelper.languages - delegate: FluRadioButton{ - checked: TranslateHelper.current === modelData - text:modelData - clickListener:function(){ - TranslateHelper.current = modelData - dialog_restart.open() - } - } - } - } - } - } -} diff --git a/example/qml-Qt6/page/T_ShortcutPicker.qml b/example/qml-Qt6/page/T_ShortcutPicker.qml deleted file mode 100644 index b2f51448..00000000 --- a/example/qml-Qt6/page/T_ShortcutPicker.qml +++ /dev/null @@ -1,30 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("ShortcutPicker") - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 100 - paddings: 10 - FluShortcutPicker{ - anchors.verticalCenter: parent.verticalCenter - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluShortcutPicker{ - -}' - } - -} - diff --git a/example/qml-Qt6/page/T_Slider.qml b/example/qml-Qt6/page/T_Slider.qml deleted file mode 100644 index 2a46b2c7..00000000 --- a/example/qml-Qt6/page/T_Slider.qml +++ /dev/null @@ -1,59 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Slider") - - FluArea{ - Layout.fillWidth: true - Layout.preferredHeight: 200 - Layout.topMargin: 20 - paddings: 10 - - Row{ - spacing: 30 - FluSlider{ - } - FluSlider{ - orientation: Qt.Vertical - anchors.verticalCenter: parent.verticalCenter - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluSlider{ - value:50 -}' - } - - - FluArea{ - Layout.fillWidth: true - Layout.preferredHeight: 200 - Layout.topMargin: 20 - paddings: 10 - Row{ - spacing: 30 - FluRangeSlider{ - } - FluRangeSlider{ - orientation: Qt.Vertical - anchors.verticalCenter: parent.verticalCenter - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluRangeSlider{ - orientation: Qt.Vertical -}' - } -} diff --git a/example/qml-Qt6/page/T_SplitLayout.qml b/example/qml-Qt6/page/T_SplitLayout.qml deleted file mode 100644 index 303d6181..00000000 --- a/example/qml-Qt6/page/T_SplitLayout.qml +++ /dev/null @@ -1,84 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluContentPage{ - - title: qsTr("SplitLayout") - - RowLayout{ - id:layout_dropdown - anchors{ - top: parent.top - topMargin: 20 - } - FluText{ - text:"orientation:" - } - FluDropDownButton{ - id:btn_orientation - Layout.preferredWidth: 120 - text:"Horizontal" - FluMenuItem{ - text:"Horizontal" - onClicked: { - btn_orientation.text = text - split_layout.orientation = Qt.Horizontal - } - } - FluMenuItem{ - text:"Vertical" - onClicked: { - btn_orientation.text = text - split_layout.orientation = Qt.Vertical - } - } - } - } - FluSplitLayout { - id:split_layout - anchors{ - top: layout_dropdown.bottom - left: parent.left - right: parent.right - bottom: parent.bottom - topMargin: 8 - } - orientation: Qt.Horizontal - Item { - clip: true - implicitWidth: 200 - implicitHeight: 200 - SplitView.maximumWidth: 400 - SplitView.maximumHeight: 400 - FluText { - text: "Page 1" - anchors.centerIn: parent - } - } - Item { - clip: true - id: centerItem - SplitView.minimumWidth: 50 - SplitView.minimumHeight: 50 - SplitView.fillWidth: true - SplitView.fillHeight: true - FluText { - text: "Page 2" - anchors.centerIn: parent - } - } - Item { - clip: true - implicitWidth: 200 - implicitHeight: 200 - FluText { - text: "Page 3" - anchors.centerIn: parent - } - } - } -} diff --git a/example/qml-Qt6/page/T_StaggeredLayout.qml b/example/qml-Qt6/page/T_StaggeredLayout.qml deleted file mode 100644 index 4594f9c6..00000000 --- a/example/qml-Qt6/page/T_StaggeredLayout.qml +++ /dev/null @@ -1,58 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI 1.0 -import "../component" - -FluContentPage{ - - title: qsTr("StaggeredLayout") - - property var colors : [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green] - - ListModel{ - id:list_model - Component.onCompleted: { - for(var i=0;i<=100;i++){ - var item = {} - item.color = colors[rand(0,7)] - item.height = rand(100,300) - append(item) - } - } - - } - - Flickable{ - id: scroll - anchors.fill: parent - anchors.topMargin: 20 - boundsBehavior:Flickable.StopAtBounds - contentHeight: staggered_view.implicitHeight - clip: true - ScrollBar.vertical: FluScrollBar {} - FluStaggeredLayout{ - id:staggered_view - width: parent.width - itemWidth: 160 - model:list_model - delegate: Rectangle{ - height: model.height - color:model.color.normal - FluText{ - color:"#FFFFFF" - text:model.index - font.bold: true - font.pixelSize: 18 - anchors.centerIn: parent - } - } - } - } - - function rand(minNum, maxNum){ - return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10); - } - -} diff --git a/example/qml-Qt6/page/T_StatusLayout.qml b/example/qml-Qt6/page/T_StatusLayout.qml deleted file mode 100644 index a2742461..00000000 --- a/example/qml-Qt6/page/T_StatusLayout.qml +++ /dev/null @@ -1,90 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("StatusLayout") - - 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 = FluStatusLayoutType.Loading - } - } - FluMenuItem{ - text:"Empty" - onClicked: { - btn_status_mode.text = text - status_view.statusMode = FluStatusLayoutType.Empty - } - } - FluMenuItem{ - text:"Error" - onClicked: { - btn_status_mode.text = text - status_view.statusMode = FluStatusLayoutType.Error - } - } - FluMenuItem{ - text:"Success" - onClicked: { - btn_status_mode.text = text - status_view.statusMode = FluStatusLayoutType.Success - } - } - } - } - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 10 - height: 380 - paddings: 10 - FluStatusLayout{ - id:status_view - anchors.fill: parent - loadingText: qsTr("Loading...") - emptyText: qsTr("Empty") - errorText: qsTr("The page went wrong...") - errorButtonText: qsTr("Reload") - onErrorClicked:{ - showError("Click Reload") - } - Rectangle { - anchors.fill: parent - color:FluTheme.primaryColor - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluStatusLayout{ - anchors.fill: parent - statusMode: FluStatusLayoutType.Loading - Rectangle{ - anchors.fill: parent - color:FluTheme.primaryColor - } -}' - } - -} diff --git a/example/qml-Qt6/page/T_TabView.qml b/example/qml-Qt6/page/T_TabView.qml deleted file mode 100644 index 76bed115..00000000 --- a/example/qml-Qt6/page/T_TabView.qml +++ /dev/null @@ -1,129 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - property var colors : [FluColors.Yellow,FluColors.Orange,FluColors.Red,FluColors.Magenta,FluColors.Purple,FluColors.Blue,FluColors.Teal,FluColors.Green] - - title: qsTr("TabView") - - Component{ - id:com_page - Rectangle{ - anchors.fill: parent - color: argument.normal - } - } - - function newTab(){ - tab_view.appendTab("qrc:/example/res/image/favicon.ico",qsTr("Document ")+tab_view.count(),com_page,colors[Math.floor(Math.random() * 8)]) - } - - 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:"Never" - onClicked: { - btn_close_button_visibility.text = text - tab_view.closeButtonVisibility = FluTabViewType.Never - } - } - 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 deleted file mode 100644 index 00b1c4d3..00000000 --- a/example/qml-Qt6/page/T_TableView.qml +++ /dev/null @@ -1,589 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluContentPage{ - - id:root - title: qsTr("TableView") - signal checkBoxChanged - - property var dataSource : [] - property int sortType: 0 - property bool seletedAll: true - property string nameKeyword: "" - - onNameKeywordChanged: { - table_view.filter(function(item){ - if(item.name.includes(nameKeyword)){ - return true - } - return false - }) - } - - Component.onCompleted: { - loadData(1,1000) - } - - onCheckBoxChanged: { - for(var i =0;i< table_view.rows ;i++){ - if(false === table_view.getRow(i).checkbox.options.checked){ - root.seletedAll = false - return - } - } - root.seletedAll = true - } - - onSortTypeChanged: { - table_view.closeEditor() - if(sortType === 0){ - table_view.sort() - }else if(sortType === 1){ - table_view.sort( - (l, r) =>{ - var lage = Number(l.age) - var rage = Number(r.age) - if(lage === rage){ - return l._key>r._key - } - return lage>rage - }); - }else if(sortType === 2){ - table_view.sort( - (l, r) => { - var lage = Number(l.age) - var rage = Number(r.age) - if(lage === rage){ - return l._key>r._key - } - return lage element === display) - selectAll() - } - onCommit: { - editTextChaged(editText) - tableView.closeEditor() - } - } - } - - Component{ - id:com_avatar - Item{ - FluClip{ - anchors.centerIn: parent - width: 40 - height: 40 - radius: [20,20,20,20] - Image{ - anchors.fill: parent - source: { - if(options && options.avatar){ - return options.avatar - } - return "" - } - sourceSize: Qt.size(80,80) - } - } - } - } - - Component{ - id:com_column_update_title - Item{ - FluText{ - id:text_title - text: { - if(options.title){ - return options.title - } - return "" - } - anchors.fill: parent - verticalAlignment: Qt.AlignVCenter - horizontalAlignment: Qt.AlignHCenter - elide: Text.ElideRight - } - MouseArea{ - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - custom_update_dialog.showDialog(options.title,function(text){ - itemModel.display = table_view.customItem(com_column_update_title,{"title":text}) - }) - } - } - } - } - - Component{ - id:com_column_sort_age - Item{ - FluText{ - text: qsTr("Age") - anchors.centerIn: parent - } - ColumnLayout{ - spacing: 0 - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - rightMargin: 4 - } - FluIconButton{ - Layout.preferredWidth: 20 - Layout.preferredHeight: 15 - iconSize: 12 - verticalPadding:0 - horizontalPadding:0 - iconSource: FluentIcons.ChevronUp - iconColor: { - if(1 === root.sortType){ - return FluTheme.primaryColor - } - return FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1) - } - onClicked: { - if(root.sortType === 1){ - root.sortType = 0 - return - } - root.sortType = 1 - } - } - FluIconButton{ - Layout.preferredWidth: 20 - Layout.preferredHeight: 15 - iconSize: 12 - verticalPadding:0 - horizontalPadding:0 - iconSource: FluentIcons.ChevronDown - iconColor: { - if(2 === root.sortType){ - return FluTheme.primaryColor - } - return FluTheme.dark ? Qt.rgba(1,1,1,1) : Qt.rgba(0,0,0,1) - } - onClicked: { - if(root.sortType === 2){ - root.sortType = 0 - return - } - root.sortType = 2 - } - } - } - } - } - - FluArea{ - id:layout_controls - anchors{ - left: parent.left - right: parent.right - top: parent.top - topMargin: 20 - } - height: 60 - - Row{ - spacing: 5 - anchors{ - left: parent.left - leftMargin: 10 - verticalCenter: parent.verticalCenter - } - - FluButton{ - text: qsTr("Clear All") - onClicked: { - table_view.dataSource = [] - } - } - - FluButton{ - text: qsTr("Delete Selection") - onClicked: { - var data = [] - var rows = [] - for (var i = 0; i < table_view.rows; i++) { - var item = table_view.getRow(i); - rows.push(item) - if (!item.checkbox.options.checked) { - data.push(item); - } - } - var sourceModel = table_view.sourceModel; - for (i = 0; i < sourceModel.rowCount; i++) { - var sourceItem = sourceModel.getRow(i); - const foundItem = rows.find(item=> item._key === sourceItem._key) - if (!foundItem) { - data.push(sourceItem); - } - } - table_view.dataSource = data - } - } - - FluButton{ - text: qsTr("Add a row of Data") - onClicked: { - table_view.appendRow(genTestObject()) - } - } - - } - } - - FluTableView{ - id:table_view - anchors{ - left: parent.left - right: parent.right - top: layout_controls.bottom - bottom: gagination.top - } - anchors.topMargin: 5 - onRowsChanged: { - root.checkBoxChanged() - } - columnSource:[ - { - title: table_view.customItem(com_column_checbox,{checked:true}), - dataIndex: 'checkbox', - width:100, - minimumWidth:100, - maximumWidth:100 - }, - { - title: table_view.customItem(com_column_update_title,{title:qsTr("Avatar")}), - dataIndex: 'avatar', - width:100 - }, - { - title: table_view.customItem(com_column_filter_name,{title:qsTr("Name")}), - dataIndex: 'name', - readOnly:true - }, - { - title: table_view.customItem(com_column_sort_age,{sort:0}), - dataIndex: 'age', - editDelegate:com_combobox, - width:100, - minimumWidth:100, - maximumWidth:100 - }, - { - title: qsTr("Address"), - dataIndex: 'address', - width:200, - minimumWidth:100, - maximumWidth:250 - }, - { - title: qsTr("Nickname"), - dataIndex: 'nickname', - width:100, - minimumWidth:80, - maximumWidth:200 - }, - { - title: qsTr("Long String"), - dataIndex: 'longstring', - width:200, - minimumWidth:100, - maximumWidth:300 - }, - { - title: qsTr("Options"), - 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 - previousText: qsTr("") - onRequestPage: - (page,count)=> { - table_view.closeEditor() - loadData(page,count) - table_view.resetPosition() - } - } - - function genTestObject(){ - var ages = ["100", "300", "500", "1000"]; - function getRandomAge() { - var randomIndex = Math.floor(Math.random() * ages.length); - return ages[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]; - } - var avatars = ["qrc:/example/res/svg/avatar_1.svg", "qrc:/example/res/svg/avatar_2.svg", "qrc:/example/res/svg/avatar_3.svg", "qrc:/example/res/svg/avatar_4.svg","qrc:/example/res/svg/avatar_5.svg","qrc:/example/res/svg/avatar_6.svg","qrc:/example/res/svg/avatar_7.svg","qrc:/example/res/svg/avatar_8.svg","qrc:/example/res/svg/avatar_9.svg","qrc:/example/res/svg/avatar_10.svg","qrc:/example/res/svg/avatar_11.svg","qrc:/example/res/svg/avatar_12.svg"]; - function getAvatar(){ - var randomIndex = Math.floor(Math.random() * avatars.length); - return avatars[randomIndex]; - } - return { - checkbox: table_view.customItem(com_checbox,{checked:root.seletedAll}), - avatar:table_view.customItem(com_avatar,{avatar:getAvatar()}), - name: getRandomName(), - age:getRandomAge(), - address: getRandomAddresses(), - nickname: getRandomNickname(), - longstring:"你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好", - action: table_view.customItem(com_action), - _minimumHeight:50, - _key:FluTools.uuid() - } - } - function loadData(page,count){ - root.seletedAll = true - const dataSource = [] - for(var i=0;i { - 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:"2021-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" - Layout.preferredWidth: 240 - } - FluFilledButton{ - text: qsTr("Append") - onClicked: { - list_model.append({text:text_box.text}) - } - } - FluFilledButton{ - text: qsTr("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 deleted file mode 100644 index 9220ff9f..00000000 --- a/example/qml-Qt6/page/T_ToggleSwitch.qml +++ /dev/null @@ -1,51 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("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: qsTr("Right") - } - FluToggleSwitch{ - disabled: toggle_switch.checked - text: qsTr("Left") - textRight: false - } - } - FluToggleSwitch{ - id: toggle_switch - anchors{ - right: parent.right - verticalCenter: parent.verticalCenter - } - text: qsTr("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 deleted file mode 100644 index 4d1b8ed8..00000000 --- a/example/qml-Qt6/page/T_Tooltip.qml +++ /dev/null @@ -1,103 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Tooltip") - - FluText{ - Layout.topMargin: 20 - text: qsTr("Hover over Tultip and it pops up") - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 68 - paddings: 10 - - Column{ - spacing: 5 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluText{ - text: qsTr("Text properties of FluIconButton support the Tooltip pop-up window by default") - } - FluIconButton{ - iconSource:FluentIcons.ChromeCloseContrast - iconSize: 15 - text: qsTr("Delete") - onClicked:{ - showSuccess(qsTr("Click IconButton")) - } - } - } - } - CodeExpander{ - Layout.fillWidth: true - Layout.topMargin: -1 - code:'FluIconButton{ - iconSource:FluentIcons.ChromeCloseContrast - iconSize: 15 - text: qsTr("Delete") - onClicked:{ - showSuccess(qsTr("Click IconButton")) - } -} -' - } - - FluArea{ - Layout.fillWidth: true - Layout.topMargin: 20 - height: 68 - paddings: 10 - - Column{ - spacing: 5 - anchors{ - verticalCenter: parent.verticalCenter - left: parent.left - } - FluText{ - text: qsTr("Add a Tooltip pop-up to a Button") - } - FluButton{ - id:button_1 - text: qsTr("Delete") - onClicked:{ - showSuccess(qsTr("Click 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: qsTr("Delete") - FluTooltip{ - visible: button_1.hovered - text:button_1.text - delay: 1000 - } - onClicked:{ - showSuccess(qsTr("Click Button")) - } -}' - } - - -} diff --git a/example/qml-Qt6/page/T_Tour.qml b/example/qml-Qt6/page/T_Tour.qml deleted file mode 100644 index 830f58c5..00000000 --- a/example/qml-Qt6/page/T_Tour.qml +++ /dev/null @@ -1,80 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluScrollablePage{ - - title: qsTr("Tour") - - FluTour{ - id:tour - steps:[ - {title:qsTr("Upload File"),description: qsTr("Put your files here."),target:()=>btn_upload}, - {title:qsTr("Save"),description: qsTr("Save your changes."),target:()=>btn_save}, - {title:qsTr("Other Actions"),description: qsTr("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: qsTr("Begin Tour") - onClicked: { - tour.open() - } - } - - Row{ - spacing: 20 - anchors{ - top: parent.top - topMargin: 60 - } - FluButton{ - id: btn_upload - text: qsTr("Upload") - onClicked: { - showInfo(qsTr("Upload")) - } - } - FluFilledButton{ - id: btn_save - text: qsTr("Save") - onClicked: { - showInfo(qsTr("Save")) - } - } - FluIconButton{ - id: btn_more - iconSource: FluentIcons.More - onClicked: { - showInfo(qsTr("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 deleted file mode 100644 index 02e09ac8..00000000 --- a/example/qml-Qt6/page/T_TreeView.qml +++ /dev/null @@ -1,131 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Window -import QtQuick.Controls -import FluentUI -import "../component" - -FluContentPage { - - title: qsTr("TreeView") - - function treeData(){ - const dig = (path = '0', level = 4) => { - const list = []; - for (let i = 0; i < 6; i += 1) { - const key = `${path}-${i}`; - const treeNode = { - title: key, - key, - }; - if (level > 0) { - treeNode.children = dig(key, level - 1); - } - list.push(treeNode); - } - return list; - }; - return dig(); - } - - Column{ - id: layout_column - spacing: 12 - width: 300 - anchors{ - topMargin: 20 - top:parent.top - left: parent.left - leftMargin: 10 - bottom:parent.bottom - bottomMargin: 20 - } - - FluText{ - text: qsTr("Total %1 data, %2 data currently displayed").arg(tree_view.count()).arg(tree_view.visibleCount()) - } - - FluText{ - text: qsTr("A total of %1 data items are selected").arg(tree_view.selectionModel().length) - } - - RowLayout{ - spacing: 10 - FluText{ - text: "cellHeight:" - Layout.alignment: Qt.AlignVCenter - } - FluSlider{ - id: slider_cell_height - value: 30 - from: 30 - to:100 - } - } - RowLayout{ - spacing: 10 - FluText{ - text: "depthPadding:" - Layout.alignment: Qt.AlignVCenter - } - FluSlider{ - id: slider_depth_padding - value: 30 - from: 30 - to:100 - } - } - FluToggleSwitch{ - id: switch_showline - text:"showLine" - checked: false - } - FluToggleSwitch{ - id: switch_draggable - text:"draggable" - checked: false - } - FluToggleSwitch{ - id: switch_checkable - text:"checkable" - checked: false - } - FluButton{ - text: "all expand" - onClicked: { - tree_view.allExpand() - } - } - FluButton{ - text: "all collapse" - onClicked: { - tree_view.allCollapse() - } - } - } - FluArea{ - anchors{ - left: layout_column.right - top: parent.top - bottom: parent.bottom - right: parent.right - rightMargin: 5 - topMargin: 5 - bottomMargin: 5 - } - FluShadow{} - FluTreeView{ - id:tree_view - anchors.fill: parent - cellHeight: slider_cell_height.value - draggable:switch_draggable.checked - showLine: switch_showline.checked - checkable:switch_checkable.checked - depthPadding: slider_depth_padding.value - Component.onCompleted: { - var data = treeData() - dataSource = data - } - } - } -} diff --git a/example/qml-Qt6/page/T_Typography.qml b/example/qml-Qt6/page/T_Typography.qml deleted file mode 100644 index 7d3fd445..00000000 --- a/example/qml-Qt6/page/T_Typography.qml +++ /dev/null @@ -1,84 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import FluentUI - -FluContentPage { - - property real textScale: 1 - - title: qsTr("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 deleted file mode 100644 index a383b4a7..00000000 --- a/example/qml-Qt6/page/T_Watermark.qml +++ /dev/null @@ -1,131 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Window -import FluentUI -import "../component" - -FluContentPage{ - - title: qsTr("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: "会磨刀的小猪" - Layout.preferredWidth: 240 - } - } - - 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 - current: Qt.rgba(0,0,0,0.1) - } - } - } - - FluWatermark{ - id: water_mark - anchors.fill: parent - text:text_box.text - textColor: color_picker.current - 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/viewmodel/SettingsViewModel.qml b/example/qml-Qt6/viewmodel/SettingsViewModel.qml deleted file mode 100644 index 6a8bf031..00000000 --- a/example/qml-Qt6/viewmodel/SettingsViewModel.qml +++ /dev/null @@ -1,14 +0,0 @@ -import QtQuick -import FluentUI - -FluViewModel{ - - objectName: "SettingsViewModel" - scope: FluViewModelType.Application - property int displayMode - - onInitData: { - displayMode = FluNavigationViewType.Auto - } - -} diff --git a/example/qml-Qt6/viewmodel/TextBoxViewModel.qml b/example/qml-Qt6/viewmodel/TextBoxViewModel.qml deleted file mode 100644 index e06ae30f..00000000 --- a/example/qml-Qt6/viewmodel/TextBoxViewModel.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick -import FluentUI - -FluViewModel { - objectName: "TextBoxView" - property string text1 - property string text2 -} diff --git a/example/qml-Qt6/window/AboutWindow.qml b/example/qml-Qt6/window/AboutWindow.qml deleted file mode 100644 index 2cd6166b..00000000 --- a/example/qml-Qt6/window/AboutWindow.qml +++ /dev/null @@ -1,165 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import "../component" - -FluWindow { - - id:window - title:"关于" - width: 600 - height: 580 - fixSize: true - launchMode: FluWindowType.SingleTask - - ColumnLayout{ - anchors{ - top: parent.top - left: parent.left - right: parent.right - } - spacing: 5 - - RowLayout{ - Layout.topMargin: 15 - 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.leftMargin: 15 - FluText{ - text:"作者:" - } - FluText{ - text:"朱子楚" - Layout.alignment: Qt.AlignBottom - } - } - - RowLayout{ - spacing: 14 - Layout.leftMargin: 15 - FluText{ - text:"微信号:" - } - FluText{ - text:"FluentUI" - Layout.alignment: Qt.AlignBottom - } - FluText{ - text:"(有啥问题可能不会马上回,但发了红包必须立马回......)" - } - } - - 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/CrashWindow.qml b/example/qml-Qt6/window/CrashWindow.qml deleted file mode 100644 index e5d4443d..00000000 --- a/example/qml-Qt6/window/CrashWindow.qml +++ /dev/null @@ -1,79 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import Qt.labs.platform -import "../component" - -FluWindow { - - id:window - title: qsTr("Friendly Reminder") - width: 300 - height: 400 - fixSize: true - showMinimize: false - - property string crashFilePath - - Component.onCompleted: { - window.stayTop = true - } - - onInitArgument: - (argument)=>{ - crashFilePath = argument.crashFilePath - } - - Image{ - width: 540/2 - height: 285/2 - anchors{ - horizontalCenter: parent.horizontalCenter - top: parent.top - topMargin: 40 - } - source: "qrc:/example/res/image/ic_crash.png" - } - - FluText{ - id:text_info - anchors{ - top: parent.top - topMargin: 240 - left: parent.left - right: parent.right - leftMargin: 10 - rightMargin: 10 - } - wrapMode: Text.WrapAnywhere - text: qsTr("We apologize for the inconvenience caused by an unexpected error") - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - - RowLayout{ - anchors{ - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom - bottomMargin: 20 - } - FluButton{ - text: qsTr("Report Logs") - onClicked: { - FluTools.showFileInFolder(crashFilePath) - } - } - Item{ - width: 30 - height: 1 - } - FluFilledButton{ - text: qsTr("Restart Program") - onClicked: { - FluApp.exit(931) - } - } - } - -} diff --git a/example/qml-Qt6/window/FluentInitalizrWindow.qml b/example/qml-Qt6/window/FluentInitalizrWindow.qml deleted file mode 100644 index e679ba88..00000000 --- a/example/qml-Qt6/window/FluentInitalizrWindow.qml +++ /dev/null @@ -1,113 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import Qt.labs.platform -import "../component" - -FluWindowDialog { - - id:window - title:qsTr("FluentUI Initalizr") - width: 600 - height: 400 - - contentDelegate:Component{ - Item{ - Connections{ - target: InitalizrHelper - function onError(message){ - showError(message) - } - function onSuccess(path){ - FluTools.showFileInFolder(path+"/CMakeLists.txt") - window.close() - } - } - - FluText{ - id:text_title - text:qsTr("FluentUI Initalizr") - font: FluTextStyle.Title - anchors{ - left: parent.left - top: parent.top - leftMargin: 20 - topMargin: 20 - } - } - - Column{ - spacing: 14 - anchors{ - left: parent.left - top: text_title.bottom - leftMargin: 20 - topMargin: 20 - } - FluTextBox{ - id:text_box_name - width: 180 - placeholderText: qsTr("Name") - focus: true - } - Row{ - spacing: 8 - FluTextBox{ - id:text_box_path - width: 300 - placeholderText: qsTr("Create In") - anchors.verticalCenter: parent.verticalCenter - } - FluButton{ - text:qsTr("Browse") - anchors.verticalCenter: parent.verticalCenter - onClicked: { - folder_dialog.open() - } - } - } - } - - FolderDialog{ - id:folder_dialog - onAccepted: { - text_box_path.text = FluTools.toLocalPath(currentFolder) - } - } - - Rectangle{ - id:layout_actions - width: parent.width - height: 60 - anchors.bottom: parent.bottom - color: FluTheme.backgroundColor - Row{ - height: parent.height - spacing: 20 - anchors{ - right: parent.right - rightMargin: 20 - } - FluButton{ - text:qsTr("Cancel") - width: 120 - anchors.verticalCenter: parent.verticalCenter - onClicked: { - window.close() - } - } - FluFilledButton{ - text:qsTr("Create") - width: 120 - anchors.verticalCenter: parent.verticalCenter - onClicked: { - InitalizrHelper.generate(text_box_name.text,text_box_path.text) - } - } - } - } - } - } - -} diff --git a/example/qml-Qt6/window/HotloadWindow.qml b/example/qml-Qt6/window/HotloadWindow.qml deleted file mode 100644 index 7ae6be9d..00000000 --- a/example/qml-Qt6/window/HotloadWindow.qml +++ /dev/null @@ -1,97 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import example -import "../component" - -FluWindow { - - id:window - title: qsTr("Hot Loader") - 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: FluStatusLayoutType.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: qsTr("Drag in a qml file") - font.pixelSize: 26 - anchors.centerIn: parent - visible: !loader.itemLodaer().item && loader.statusMode === FluStatusLayoutType.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 - } - var url = getUrlByEvent(event) - if(url === ""){ - event.accepted = false - return - } - var fileExtension = url.substring(url.lastIndexOf(".") + 1) - if (fileExtension !== "qml") { - event.accepted = false - return - } - return true - } - onDropped: - (event)=>{ - var url = getUrlByEvent(event) - if(url !== ""){ - loader.source = url - watcher.path = url - loader.reload() - } - } - } - } - - function getUrlByEvent(event){ - var url = "" - if (event.urls.length === 0) { - url = "file:///"+event.getDataAsString("text/plain") - }else{ - url = event.urls[0].toString() - } - return url - } - -} diff --git a/example/qml-Qt6/window/LoginWindow.qml b/example/qml-Qt6/window/LoginWindow.qml deleted file mode 100644 index 23f95972..00000000 --- a/example/qml-Qt6/window/LoginWindow.qml +++ /dev/null @@ -1,59 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import FluentUI -import "../component" - -FluWindow { - - id: window - title: qsTr("Login") - width: 400 - height: 400 - fixSize: true - modality: Qt.ApplicationModal - 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: qsTr("Please enter the account") - Layout.preferredWidth: 260 - Layout.alignment: Qt.AlignHCenter - } - - FluTextBox{ - id: textbox_password - Layout.topMargin: 20 - Layout.preferredWidth: 260 - placeholderText: qsTr("Please enter your password") - echoMode:TextInput.Password - Layout.alignment: Qt.AlignHCenter - } - - FluFilledButton{ - text: qsTr("Login") - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: 20 - onClicked:{ - if(textbox_password.text === ""){ - showError(qsTr("Please feel free to enter a password")) - return - } - onResult({password:textbox_password.text}) - window.close() - } - } - } -} diff --git a/example/qml-Qt6/window/MainWindow.qml b/example/qml-Qt6/window/MainWindow.qml deleted file mode 100644 index 5675b006..00000000 --- a/example/qml-Qt6/window/MainWindow.qml +++ /dev/null @@ -1,395 +0,0 @@ -import QtQuick -import QtQuick.Window -import QtQuick.Controls -import QtQuick.Layouts -import Qt.labs.platform -import FluentUI -import example -import "../component" -import "../global" -import "../viewmodel" - -FluWindow { - - id:window - title: "FluentUI" - width: 1000 - height: 680 - minimumWidth: 520 - minimumHeight: 200 - launchMode: FluWindowType.SingleTask - fitsAppBarWindows: true - appBar: FluAppBar { - height: 30 - showDark: true - darkClickListener:(button)=>handleDarkChanged(button) - closeClickListener: ()=>{dialog_close.open()} - z:7 - } - - SettingsViewModel{ - id:viewmodel_settings - } - - FluEvent{ - id:event_checkupdate - name: "checkUpdate" - onTriggered: { - checkUpdate(false) - } - } - - onFirstVisible: { - timer_tour_delay.restart() - } - - Timer{ - id:timer_tour_delay - interval: 200 - onTriggered: { - tour.open() - } - } - - Component.onCompleted: { - checkUpdate(true) - FluEventBus.registerEvent(event_checkupdate) - } - - Component.onDestruction: { - FluEventBus.unRegisterEvent(event_checkupdate) - } - - SystemTrayIcon { - id:system_tray - visible: true - icon.source: "qrc:/example/res/image/favicon.ico" - tooltip: "FluentUI" - menu: Menu { - MenuItem { - text: "退出" - onTriggered: { - FluApp.exit() - } - } - } - onActivated: - (reason)=>{ - if(reason === SystemTrayIcon.Trigger){ - window.show() - window.raise() - window.requestActivate() - } - } - } - - Timer{ - id: timer_window_hide_delay - interval: 150 - onTriggered: { - window.hide() - } - } - - FluContentDialog{ - id: dialog_close - title: qsTr("Quit") - message: qsTr("Are you sure you want to exit the program?") - negativeText: qsTr("Minimize") - buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton | FluContentDialogType.PositiveButton - onNegativeClicked: { - system_tray.showMessage(qsTr("Friendly Reminder"),qsTr("FluentUI is hidden from the tray, click on the tray to activate the window again")); - timer_window_hide_delay.restart() - } - positiveText: qsTr("Quit") - neutralText: qsTr("Cancel") - onPositiveClicked:{ - FluApp.exit(0) - } - } - - Component{ - id: nav_item_right_menu - FluMenu{ - width: 186 - FluMenuItem{ - text: qsTr("Open in Separate Window") - font.pixelSize: 12 - onClicked: { - FluApp.navigate("/pageWindow",{title:modelData.title,url:modelData.url}) - } - } - } - } - - 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 - Row{ - id:layout_back_buttons - 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() - } - } - Component.onCompleted: { - appBar.setHitTestVisible(layout_back_buttons) - } - } - FluRemoteLoader{ - id:loader - lazy: true - anchors.fill: parent - source: "https://zhu-zichu.gitee.io/Qt_168_LieflatPage.qml" - } - } - front: Item{ - id:page_front - visible: flipable.flipAngle !== 180 - anchors.fill: flipable - FluNavigationView{ - property int clickCount: 0 - id:nav_view - width: parent.width - height: parent.height - z:999 - //Stack模式,每次切换都会将页面压入栈中,随着栈的页面增多,消耗的内存也越多,内存消耗多就会卡顿,这时候就需要按返回将页面pop掉,释放内存。该模式可以配合FluPage中的launchMode属性,设置页面的启动模式 - // pageMode: FluNavigationViewType.Stack - //NoStack模式,每次切换都会销毁之前的页面然后创建一个新的页面,只需消耗少量内存,可以配合FluViewModel保存页面数据(推荐) - pageMode: FluNavigationViewType.NoStack - items: ItemsOriginal - footerItems:ItemsFooter - topPadding:{ - if(window.useSystemAppBar){ - return 0 - } - return FluTools.isMacos() ? 20 : 0 - } - displayMode:viewmodel_settings.displayMode - logo: "qrc:/example/res/image/favicon.ico" - title:"FluentUI" - onLogoClicked:{ - clickCount += 1 - showSuccess("%1:%2".arg(qsTr("Click Time")).arg(clickCount)) - if(clickCount === 5){ - loader.reload() - flipable.flipped = true - clickCount = 0 - } - } - autoSuggestBox:FluAutoSuggestBox{ - iconSource: FluentIcons.Search - items: ItemsOriginal.getSearchData() - placeholderText: qsTr("Search") - onItemClicked: - (data)=>{ - ItemsOriginal.startPageByItem(data) - } - } - Component.onCompleted: { - ItemsOriginal.navigationView = nav_view - ItemsOriginal.paneItemMenu = nav_item_right_menu - ItemsFooter.navigationView = nav_view - ItemsFooter.paneItemMenu = nav_item_right_menu - appBar.setHitTestVisible(nav_view.buttonMenu) - appBar.setHitTestVisible(nav_view.buttonBack) - appBar.setHitTestVisible(nav_view.imageLogo) - setCurrentIndex(0) - } - } - } - } - - Component{ - id:com_reveal - CircularReveal{ - id:reveal - target:window.contentItem - anchors.fill: parent - onAnimationFinished:{ - //动画结束后释放资源 - loader_reveal.sourceComponent = undefined - } - onImageChanged: { - changeDark() - } - } - } - - FluLoader{ - 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(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){ - changeDark() - }else{ - if(loader_reveal.sourceComponent){ - return - } - 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 - finishText: qsTr("Finish") - nextText: qsTr("Next") - previousText: qsTr("Previous") - steps:{ - var data = [] - if(!window.useSystemAppBar){ - data.push({title:qsTr("Dark Mode"),description: qsTr("Here you can switch to night mode."),target:()=>appBar.buttonDark}) - } - data.push({title:qsTr("Hide Easter eggs"),description: qsTr("Try a few more clicks!!"),target:()=>nav_view.imageLogo}) - return data - } - } - - FpsItem{ - id:fps_item - } - - FluText{ - text: "fps %1".arg(fps_item.fps) - opacity: 0.3 - anchors{ - bottom: parent.bottom - right: parent.right - bottomMargin: 5 - rightMargin: 5 - } - } - - FluContentDialog{ - property string newVerson - property string body - id: dialog_update - title: qsTr("Upgrade Tips") - message:qsTr("FluentUI is currently up to date ")+ newVerson +qsTr(" -- The current app version") +AppInfo.version+qsTr(" \nNow go and download the new version?\n\nUpdated content: \n")+body - buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton - negativeText: qsTr("Cancel") - positiveText: qsTr("OK") - onPositiveClicked:{ - Qt.openUrlExternally("https://github.com/zhuzichu520/FluentUI/releases/latest") - } - } - - FluNetworkCallable{ - id:callable - property bool silent: true - onStart: { - console.debug("satrt check update...") - } - onFinish: { - console.debug("check update finish") - FluEventBus.post("checkUpdateFinish"); - } - onSuccess: - (result)=>{ - var data = JSON.parse(result) - console.debug("current version "+AppInfo.version) - console.debug("new version "+data.tag_name) - if(data.tag_name !== AppInfo.version){ - dialog_update.newVerson = data.tag_name - dialog_update.body = data.body - dialog_update.open() - }else{ - if(!silent){ - showInfo(qsTr("The current version is already the latest")) - } - } - } - onError: - (status,errorString)=>{ - if(!silent){ - showError(qsTr("The network is abnormal")) - } - console.debug(status+";"+errorString) - } - } - - function checkUpdate(silent){ - callable.silent = silent - FluNetwork.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest") - .go(callable) - } -} diff --git a/example/qml-Qt6/window/PageWindow.qml b/example/qml-Qt6/window/PageWindow.qml deleted file mode 100644 index b4057e1e..00000000 --- a/example/qml-Qt6/window/PageWindow.qml +++ /dev/null @@ -1,25 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import example -import "../component" - -FluWindow { - - id:window - width: 800 - height: 600 - minimumWidth: 520 - minimumHeight: 200 - launchMode: FluWindowType.SingleInstance - onInitArgument: - (arg)=>{ - window.title = arg.title - loader.setSource( arg.url,{animDisabled:true}) - } - FluLoader{ - id: loader - anchors.fill: parent - } -} diff --git a/example/qml-Qt6/window/SingleInstanceWindow.qml b/example/qml-Qt6/window/SingleInstanceWindow.qml deleted file mode 100644 index aca0d519..00000000 --- a/example/qml-Qt6/window/SingleInstanceWindow.qml +++ /dev/null @@ -1,35 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import "../component" - -FluWindow { - - id: window - title: qsTr("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: qsTr("I'm a SingleInstance window, and if I exist, I'll destroy the previous window and create a new one") - } -} diff --git a/example/qml-Qt6/window/SingleTaskWindow.qml b/example/qml-Qt6/window/SingleTaskWindow.qml deleted file mode 100644 index a43cc042..00000000 --- a/example/qml-Qt6/window/SingleTaskWindow.qml +++ /dev/null @@ -1,21 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import "../component" - -FluWindow { - - id: window - title: qsTr("SingleTask") - width: 500 - height: 600 - fixSize: true - launchMode: FluWindowType.SingleTask - - FluText{ - anchors.centerIn: parent - text: qsTr("I'm a SingleTask mode window, and if I exist, I activate the window") - } - -} diff --git a/example/qml-Qt6/window/StandardWindow.qml b/example/qml-Qt6/window/StandardWindow.qml deleted file mode 100644 index 13e60a8a..00000000 --- a/example/qml-Qt6/window/StandardWindow.qml +++ /dev/null @@ -1,43 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import FluentUI -import "../component" - -FluWindow { - - 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: qsTr("I'm a Standard mode window, and every time I create a new window") - } - -} diff --git a/example/qml/window/MainWindow.qml b/example/qml/window/MainWindow.qml index 4b49563a..ed85f702 100644 --- a/example/qml/window/MainWindow.qml +++ b/example/qml/window/MainWindow.qml @@ -2,6 +2,7 @@ import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 +import QtQml 2.15 import Qt.labs.platform 1.1 import FluentUI 1.0 import example 1.0 diff --git a/example/res/template/src/CMakeLists.txt.in b/example/res/template/src/CMakeLists.txt.in index 6d1d3717..34946eaa 100644 --- a/example/res/template/src/CMakeLists.txt.in +++ b/example/res/template/src/CMakeLists.txt.in @@ -84,9 +84,9 @@ if (CMAKE_BUILD_TYPE MATCHES "Release") add_custom_target(Script-DeployRelease COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist - COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/%1 -qmldir=${CMAKE_CURRENT_LIST_DIR} - COMMENT "Deploying Qt Dependencies After Build........." - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/README.md + COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME} -qmldir=${CMAKE_CURRENT_LIST_DIR} + COMMENT "MacOs Deploying Qt Dependencies After Build........." + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif() @@ -95,10 +95,11 @@ if (CMAKE_BUILD_TYPE MATCHES "Release") add_custom_target(Script-DeployRelease COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/dist COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ${CMAKE_SOURCE_DIR}/dist - COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/%1.exe -qmldir=${CMAKE_CURRENT_LIST_DIR} - COMMENT "Deploying Qt Dependencies After Build........." - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/README.md + COMMAND ${QT_DEPLOY_QT} ${CMAKE_SOURCE_DIR}/dist/${PROJECT_NAME}.exe -qmldir=${CMAKE_CURRENT_LIST_DIR} + COMMENT "Windows Deploying Qt Dependencies After Build........." + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif() endif() + diff --git a/example/res/template/src/README.md.in b/example/res/template/src/README.md.in new file mode 100644 index 00000000..2ac81422 --- /dev/null +++ b/example/res/template/src/README.md.in @@ -0,0 +1,18 @@ +# FluentUI 脚手架开发说明 + +## 代码说明 + +文件编码格式请用utf-8不带bom,代码中最好不要含有中文(包括注释),中文可能会改变文件格式导致编译失败,还会出现乱码,显示中文请用国际化,c++中用tr函数,qml中用qsTr函数 + +### 脚本说明 + +1. **Script-UpdateTranslations** + + 用于更新ts与qm文件,当你的代码添加了tr或者qsTr函数后,执行这个脚本会更新ts文件,然后编写翻译后,再执行这个脚本,qm文件会更新生效 + +2. **Script-DeployRelease** + + 执行Qt的windeployqt或macdeployqt命令,这个脚本只在windows与macos才有,linux不支持 + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f153f419..7a50f9b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) #设置版本号 -add_definitions(-DFLUENTUI_VERSION=1,7,2,0) +add_definitions(-DFLUENTUI_VERSION=1,7,3,0) if (FLUENTUI_BUILD_STATIC_LIB) add_definitions(-DFLUENTUI_BUILD_STATIC_LIB) @@ -170,9 +170,9 @@ endif() #链接库 target_link_libraries(${PROJECT_NAME} PUBLIC - Qt${QT_VERSION_MAJOR}::CorePrivate - Qt${QT_VERSION_MAJOR}::QuickPrivate - Qt${QT_VERSION_MAJOR}::QmlPrivate + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Quick + Qt${QT_VERSION_MAJOR}::Qml ) #安装 diff --git a/src/FluTheme.cpp b/src/FluTheme.cpp index 065c43c1..d41b568e 100644 --- a/src/FluTheme.cpp +++ b/src/FluTheme.cpp @@ -1,14 +1,7 @@ #include "FluTheme.h" #include -#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) -#include -#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))) -#include -#include -#else #include -#endif #include "Def.h" #include "FluColors.h" @@ -71,18 +64,9 @@ QJsonArray FluTheme::awesomeList(const QString& keyword){ } bool FluTheme::systemDark(){ -#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) - return (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark); -#elif ((QT_VERSION >= QT_VERSION_CHECK(6, 2, 1))) - if (const QPlatformTheme * const theme = QGuiApplicationPrivate::platformTheme()) { - return (theme->appearance() == QPlatformTheme::Appearance::Dark); - } - return false; -#else QPalette palette = qApp->palette(); QColor color = palette.color(QPalette::Window).rgb(); return !(color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 > 255 / 2); -#endif } bool FluTheme::dark(){ diff --git a/src/FluentUI/Controls/FluAcrylic.qml b/src/FluentUI/Controls/FluAcrylic.qml new file mode 100644 index 00000000..035fe423 --- /dev/null +++ b/src/FluentUI/Controls/FluAcrylic.qml @@ -0,0 +1,41 @@ +import QtQuick +import Qt5Compat.GraphicalEffects +import FluentUI + +Item { + 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.02 + 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/FluentUI/Controls/FluAppBar.qml b/src/FluentUI/Controls/FluAppBar.qml new file mode 100644 index 00000000..8a62854b --- /dev/null +++ b/src/FluentUI/Controls/FluAppBar.qml @@ -0,0 +1,347 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Window +import QtQuick.Layouts +import FluentUI + +Rectangle{ + property string title: "" + property string darkText : qsTr("Dark") + property string lightText : qsTr("Light") + property string minimizeText : qsTr("Minimize") + property string restoreText : qsTr("Restore") + property string maximizeText : qsTr("Maximize") + property string closeText : qsTr("Close") + property string stayTopText : qsTr("Sticky on Top") + property string stayTopCancelText : qsTr("Sticky on Top cancelled") + property color textColor: FluTheme.dark ? "#FFFFFF" : "#000000" + property color minimizeNormalColor: FluTheme.itemNormalColor + property color minimizeHoverColor: FluTheme.itemHoverColor + property color minimizePressColor: FluTheme.itemPressColor + property color maximizeNormalColor: FluTheme.itemNormalColor + property color maximizeHoverColor: FluTheme.itemHoverColor + property color maximizePressColor: FluTheme.itemPressColor + property color closeNormalColor: Qt.rgba(0,0,0,0) + property color closeHoverColor: Qt.rgba(251/255,115/255,115/255,1) + property color closePressColor: Qt.rgba(251/255,115/255,115/255,0.8) + property bool showDark: false + property bool showClose: true + property bool showMinimize: true + property bool showMaximize: true + property bool showStayTop: true + property bool titleVisible: true + property url icon + property int iconSize: 20 + property bool isMac: FluTools.isMacos() + property color borerlessColor : FluTheme.primaryColor + property bool systemMoveEnable: true + property var maxClickListener : function(){ + if(FluTools.isMacos()){ + if (d.win.visibility === Window.FullScreen) + d.win.showNormal() + else + d.win.showFullScreen() + }else{ + if (d.win.visibility === Window.Maximized) + d.win.showNormal() + else + d.win.showMaximized() + d.hoverMaxBtn = false + } + } + property var minClickListener: function(){ + if(d.win.transientParent != null){ + d.win.transientParent.showMinimized() + }else{ + d.win.showMinimized() + } + } + property var closeClickListener : function(){ + d.win.close() + } + property var stayTopClickListener: function(){ + if(d.win instanceof FluWindow){ + d.win.stayTop = !d.win.stayTop + } + } + property var darkClickListener: function(){ + if(FluTheme.dark){ + FluTheme.darkMode = FluThemeType.Light + }else{ + FluTheme.darkMode = FluThemeType.Dark + } + } + property var systemMenuListener: function(){ + if(d.win instanceof FluWindow){ + d.win.showSystemMenu() + } + } + property alias buttonStayTop: btn_stay_top + property alias buttonMinimize: btn_minimize + property alias buttonMaximize: btn_maximize + property alias buttonClose: btn_close + property alias buttonDark: btn_dark + id:control + color: Qt.rgba(0,0,0,0) + height: visible ? 30 : 0 + opacity: visible + z: 65535 + Item{ + id:d + property var hitTestList: [] + property bool hoverMaxBtn: false + property var win: Window.window + property bool stayTop: { + if(d.win instanceof FluWindow){ + return d.win.stayTop + } + return false + } + property bool isRestore: win && Window.Maximized === win.visibility + property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth) + function containsPointToItem(point,item){ + var pos = item.mapToGlobal(0,0) + var rect = Qt.rect(pos.x,pos.y,item.width,item.height) + if(point.x>rect.x && point.x<(rect.x+rect.width) && point.y>rect.y && point.y<(rect.y+rect.height)){ + return true + } + return false + } + } + MouseArea{ + id:mouse_app_bar + anchors.fill: parent + onPositionChanged: + (mouse)=>{ + if(systemMoveEnable){ + d.win.startSystemMove() + } + } + onDoubleClicked: + (mouse)=>{ + if(systemMoveEnable && d.resizable && Qt.LeftButton){ + btn_maximize.clicked() + } + } + acceptedButtons: Qt.LeftButton|Qt.RightButton + onClicked: + (mouse)=>{ + if (systemMoveEnable && mouse.button === Qt.RightButton){ + control.systemMenuListener() + } + } + } + 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 + } + } + + Component{ + id:com_mac_buttons + RowLayout{ + FluImageButton{ + Layout.preferredHeight: 12 + Layout.preferredWidth: 12 + normalImage: "../Image/btn_close_normal.png" + hoveredImage: "../Image/btn_close_hovered.png" + pushedImage: "../Image/btn_close_pushed.png" + visible: showClose + onClicked: closeClickListener() + } + FluImageButton{ + Layout.preferredHeight: 12 + Layout.preferredWidth: 12 + normalImage: "../Image/btn_min_normal.png" + hoveredImage: "../Image/btn_min_hovered.png" + pushedImage: "../Image/btn_min_pushed.png" + onClicked: minClickListener() + visible: showMinimize + } + FluImageButton{ + Layout.preferredHeight: 12 + Layout.preferredWidth: 12 + normalImage: "../Image/btn_max_normal.png" + hoveredImage: "../Image/btn_max_hovered.png" + pushedImage: "../Image/btn_max_pushed.png" + onClicked: maxClickListener() + visible: d.resizable && showMaximize + } + } + } + + FluLoader{ + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 10 + } + sourceComponent: isMac ? com_mac_buttons : undefined + } + + RowLayout{ + id:layout_row + anchors.right: parent.right + height: control.height + spacing: 0 + Component.onCompleted: { + setHitTestVisible(layout_row) + } + FluIconButton{ + id:btn_dark + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + padding: 0 + verticalPadding: 0 + horizontalPadding: 0 + rightPadding: 2 + iconSource: FluTheme.dark ? FluentIcons.Brightness : FluentIcons.QuietHours + Layout.alignment: Qt.AlignVCenter + iconSize: 15 + visible: showDark + text: FluTheme.dark ? control.lightText : control.darkText + radius: 0 + iconColor:control.textColor + onClicked:()=> darkClickListener(btn_dark) + } + FluIconButton{ + id:btn_stay_top + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + padding: 0 + verticalPadding: 0 + horizontalPadding: 0 + iconSource : FluentIcons.Pinned + Layout.alignment: Qt.AlignVCenter + iconSize: 14 + visible: { + if(!(d.win instanceof FluWindow)){ + return false + } + return showStayTop + } + text:d.stayTop ? control.stayTopCancelText : control.stayTopText + radius: 0 + iconColor: d.stayTop ? FluTheme.primaryColor : control.textColor + onClicked: stayTopClickListener() + } + FluIconButton{ + id:btn_minimize + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + padding: 0 + verticalPadding: 0 + horizontalPadding: 0 + iconSource : FluentIcons.ChromeMinimize + Layout.alignment: Qt.AlignVCenter + iconSize: 11 + text:minimizeText + radius: 0 + visible: !isMac && showMinimize + iconColor: control.textColor + color: { + if(pressed){ + return minimizePressColor + } + return hovered ? minimizeHoverColor : minimizeNormalColor + } + onClicked: minClickListener() + } + FluIconButton{ + id:btn_maximize + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + padding: 0 + verticalPadding: 0 + horizontalPadding: 0 + iconSource : d.isRestore ? FluentIcons.ChromeRestore : FluentIcons.ChromeMaximize + color: { + if(down){ + return maximizePressColor + } + if(FluTools.isWindows11OrGreater()){ + return d.hoverMaxBtn ? maximizeHoverColor : maximizeNormalColor + } + return 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 + Layout.preferredWidth: 40 + Layout.preferredHeight: 30 + padding: 0 + verticalPadding: 0 + horizontalPadding: 0 + iconSource : FluentIcons.ChromeClose + Layout.alignment: Qt.AlignVCenter + text:closeText + visible: !isMac && showClose + radius: 0 + iconSize: 10 + iconColor: hovered ? Qt.rgba(1,1,1,1) : control.textColor + color:{ + if(pressed){ + return closePressColor + } + return hovered ? closeHoverColor : closeNormalColor + } + onClicked: closeClickListener() + } + } + function _maximizeButtonHover(){ + var hover = false + if(btn_maximize.visible && FluTools.isWindows11OrGreater() && d.resizable){ + if(d.containsPointToItem(FluTools.cursorPos(),btn_maximize)){ + hover = true + }else{ + if(btn_maximize.down){ + btn_maximize.down = false + } + } + } + d.hoverMaxBtn = hover + return hover; + } + function _appBarHover(){ + var cursorPos = FluTools.cursorPos() + for(var i =0 ;i< d.hitTestList.length; i++){ + var item = d.hitTestList[i] + if(item.visible){ + if(d.containsPointToItem(cursorPos,item)){ + return false + } + } + } + if(d.containsPointToItem(cursorPos,control)){ + return true + } + return false + } + function setHitTestVisible(id){ + d.hitTestList.push(id) + } +} diff --git a/src/FluentUI/Controls/FluArea.qml b/src/FluentUI/Controls/FluArea.qml new file mode 100644 index 00000000..81a08036 --- /dev/null +++ b/src/FluentUI/Controls/FluArea.qml @@ -0,0 +1,28 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Window +import FluentUI + +Rectangle { + default property alias contentData : layout_content.data + property int paddings : 0 + property int leftPadding : 0 + property int rightPadding : 0 + property int topPadding : 0 + property int bottomPadding : 0 + id:control + 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: layout_content + 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/FluentUI/Controls/FluAutoSuggestBox.qml b/src/FluentUI/Controls/FluAutoSuggestBox.qml new file mode 100644 index 00000000..0aaa8e03 --- /dev/null +++ b/src/FluentUI/Controls/FluAutoSuggestBox.qml @@ -0,0 +1,139 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +FluTextBox{ + property var items:[] + property string emptyText: qsTr("No results found") + property int autoSuggestBoxReplacement: FluentIcons.Search + property var filter: function(item){ + if(item.title.indexOf(control.text)!==-1){ + return true + } + return false + } + signal itemClicked(var data) + id:control + Component.onCompleted: { + d.loadData() + } + Item{ + id:d + property bool flagVisible: true + property var window : Window.window + function handleClick(modelData){ + control_popup.visible = false + control.itemClicked(modelData) + d.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(control.filter(item)){ + result.push(item) + } + }) + list_view.model = result + } + } + 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:{ + d.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: { + d.loadData() + if(d.flagVisible){ + var pos = control.mapToItem(null, 0, 0) + if(d.window.height>pos.y+control.height+container.implicitHeight){ + control_popup.y = control.height + } else if(pos.y>container.implicitHeight){ + control_popup.y = -container.implicitHeight + } else { + control_popup.y = d.window.height-(pos.y+container.implicitHeight) + } + control_popup.visible = true + } + } +} diff --git a/src/FluentUI/Controls/FluBadge.qml b/src/FluentUI/Controls/FluBadge.qml new file mode 100644 index 00000000..d265891a --- /dev/null +++ b/src/FluentUI/Controls/FluBadge.qml @@ -0,0 +1,79 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +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 + } + FluText{ + anchors.centerIn: parent + color: Qt.rgba(1,1,1,1) + visible: !isDot + text:{ + if(count<100) + return count + return count+"+" + } + } +} diff --git a/src/FluentUI/Controls/FluBreadcrumbBar.qml b/src/FluentUI/Controls/FluBreadcrumbBar.qml new file mode 100644 index 00000000..02d1e3a2 --- /dev/null +++ b/src/FluentUI/Controls/FluBreadcrumbBar.qml @@ -0,0 +1,92 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +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 : 1 + } + } + add: Transition { + NumberAnimation { + properties: "opacity" + from: 0 + to: 1 + duration: FluTheme.enableAnimation ? 83 : 1 + } + } + 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/FluentUI/Controls/FluButton.qml b/src/FluentUI/Controls/FluButton.qml new file mode 100644 index 00000000..dffe4d61 --- /dev/null +++ b/src/FluentUI/Controls/FluButton.qml @@ -0,0 +1,65 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +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(246/255,246/255,246/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/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 + verticalPadding: 0 + 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/FluentUI/Controls/FluCalendarPicker.qml b/src/FluentUI/Controls/FluCalendarPicker.qml new file mode 100644 index 00000000..dbd9d503 --- /dev/null +++ b/src/FluentUI/Controls/FluCalendarPicker.qml @@ -0,0 +1,661 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI + +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: qsTr("Pick a date") + property date from: new Date(1924, 0, 1) + property date to: new Date(2124, 11, 31) + property var current + signal accepted() + 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() + } + } + CalendarModel { + id:calender_model + from: control.from + to: control.to + } + Item{ + id:d + property var window : Window.window + property date displayDate: { + if(control.current){ + return control.current + } + return new Date() + } + property date toDay : new Date() + property int pageIndex: 0 + signal nextButton + signal previousButton + property point yearRing : Qt.point(0,0) + } + 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:{ + if(control.current){ + return control.current.toLocaleDateString(FluApp.locale,"yyyy/M/d") + } + return 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 + Overlay.modal: Item {} + 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 + FluArea{ + id:container + width: 300 + height: 360 + ColumnLayout { + anchors.fill: parent + spacing: 0 + Item{ + Layout.fillWidth: true + Layout.preferredHeight: 50 + RowLayout{ + anchors.fill: parent + spacing: 10 + Item{ + Layout.leftMargin: parent.spacing + Layout.fillWidth: true + Layout.fillHeight: true + FluTextButton{ + width: parent.width + anchors.centerIn: parent + contentItem: FluText { + text: d.displayDate.toLocaleString(FluApp.locale, "MMMM yyyy") + verticalAlignment: Text.AlignVCenter + } + visible: d.pageIndex === 0 + onClicked: { + d.pageIndex = 1 + } + } + FluTextButton{ + width: parent.width + anchors.centerIn: parent + contentItem: FluText { + text: d.displayDate.toLocaleString(FluApp.locale, "yyyy") + verticalAlignment: Text.AlignVCenter + } + visible: d.pageIndex === 1 + onClicked: { + d.pageIndex = 2 + } + } + FluTextButton{ + width: parent.width + anchors.centerIn: parent + contentItem: FluText { + text: "%1-%2".arg(d.yearRing.x).arg(d.yearRing.y) + verticalAlignment: Text.AlignVCenter + textColor: FluTheme.fontTertiaryColor + } + visible: d.pageIndex === 2 + } + } + FluIconButton{ + id:icon_up + iconSource: FluentIcons.CaretUpSolid8 + iconSize: 10 + onClicked: { + d.previousButton() + } + } + FluIconButton{ + id:icon_down + iconSource: FluentIcons.CaretDownSolid8 + iconSize: 10 + Layout.rightMargin: parent.spacing + onClicked: { + d.nextButton() + } + } + } + FluDivider{ + width: parent.width + height: 1 + anchors.bottom: parent.bottom + } + } + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + StackView{ + id:stack_view + anchors.fill: parent + initialItem: com_page_one + replaceEnter : Transition{ + OpacityAnimator{ + from: 0 + to: 1 + duration: 88 + } + ScaleAnimator{ + from: 0.5 + to: 1 + duration: 167 + easing.type: Easing.OutCubic + } + } + replaceExit : Transition{ + OpacityAnimator{ + from: 1 + to: 0 + duration: 88 + } + ScaleAnimator{ + from: 1.0 + to: 0.5 + duration: 167 + easing.type: Easing.OutCubic + } + } + } + Connections{ + target: d + function onPageIndexChanged(){ + if(d.pageIndex === 0){ + stack_view.replace(com_page_one) + } + if(d.pageIndex === 1){ + stack_view.replace(com_page_two) + } + if(d.pageIndex === 2){ + stack_view.replace(com_page_three) + } + } + } + Component{ + id:com_page_three + GridView{ + id:grid_view + cellHeight: 75 + cellWidth: 75 + clip: true + boundsBehavior: GridView.StopAtBounds + ScrollBar.vertical: FluScrollBar {} + model: { + var fromYear = calender_model.from.getFullYear() + var toYear = calender_model.to.getFullYear() + return toYear-fromYear+1 + } + highlightRangeMode: GridView.StrictlyEnforceRange + onCurrentIndexChanged:{ + var year = currentIndex + calender_model.from.getFullYear() + var start = Math.ceil(year / 10) * 10 + var end = start+10 + d.yearRing = Qt.point(start,end) + } + highlightMoveDuration: 100 + Component.onCompleted: { + grid_view.highlightMoveDuration = 0 + currentIndex = d.displayDate.getFullYear()-calender_model.from.getFullYear() + timer_delay.restart() + } + Connections{ + target: d + function onNextButton(){ + grid_view.currentIndex = Math.min(grid_view.currentIndex+16,grid_view.count-1) + } + function onPreviousButton(){ + grid_view.currentIndex = Math.max(grid_view.currentIndex-16,0) + } + } + Timer{ + id:timer_delay + interval: 100 + onTriggered: { + grid_view.highlightMoveDuration = 100 + } + } + currentIndex: -1 + delegate: Item{ + property int year : calender_model.from.getFullYear()+modelData + property bool toYear: year === d.toDay.getFullYear() + implicitHeight: 75 + implicitWidth: 75 + FluControl{ + id:control_delegate + width: 60 + height: 60 + anchors.centerIn: parent + Rectangle{ + width: 48 + height: 48 + radius: width/2 + color: { + if(toYear){ + if(control_delegate.pressed){ + return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.2) : Qt.lighter(FluTheme.primaryColor,1.2) + } + if(control_delegate.hovered){ + return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.1) : Qt.lighter(FluTheme.primaryColor,1.1) + } + return FluTheme.primaryColor + }else{ + if(control_delegate.pressed){ + return FluTheme.itemPressColor + } + if(control_delegate.hovered){ + return FluTheme.itemHoverColor + } + return FluColors.Transparent + } + } + anchors.centerIn: parent + } + + FluText{ + text: year + anchors.centerIn: parent + opacity: { + if(year >= d.yearRing.x && year <= d.yearRing.y){ + return 1 + } + if(control_delegate.hovered){ + return 1 + } + return 0.3 + } + color: { + if(toYear){ + return FluColors.White + } + if(control_delegate.pressed){ + return FluTheme.dark ? FluColors.Grey100 : FluColors.Grey100 + } + if(control_delegate.hovered){ + return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120 + } + return FluTheme.dark ? FluColors.White : FluColors.Grey220 + } + } + onClicked: { + d.displayDate = new Date(year,0,1) + d.pageIndex = 1 + } + } + } + } + } + Component{ + id:com_page_two + + ListView{ + id:listview + ScrollBar.vertical: FluScrollBar {} + highlightRangeMode: ListView.StrictlyEnforceRange + clip: true + boundsBehavior: ListView.StopAtBounds + spacing: 0 + highlightMoveDuration: 100 + model: { + var fromYear = calender_model.from.getFullYear() + var toYear = calender_model.to.getFullYear() + var yearsArray = [] + for (var i = fromYear; i <= toYear; i++) { + yearsArray.push(i) + } + return yearsArray + } + currentIndex: -1 + onCurrentIndexChanged:{ + var year = model[currentIndex] + var month = d.displayDate.getMonth() + d.displayDate = new Date(year,month,1) + } + Connections{ + target: d + function onNextButton(){ + listview.currentIndex = Math.min(listview.currentIndex+1,listview.count-1) + } + function onPreviousButton(){ + listview.currentIndex = Math.max(listview.currentIndex-1,0) + } + } + Component.onCompleted: { + listview.highlightMoveDuration = 0 + currentIndex = model.indexOf(d.displayDate.getFullYear()) + timer_delay.restart() + } + Timer{ + id:timer_delay + interval: 100 + onTriggered: { + listview.highlightMoveDuration = 100 + } + } + delegate: Item{ + id:layout_congrol + property int year : modelData + width: listview.width + height: 75*3 + GridView{ + anchors.fill: parent + cellHeight: 75 + cellWidth: 75 + clip: true + interactive: false + boundsBehavior: GridView.StopAtBounds + model: 12 + delegate: Item{ + property int month : modelData + property bool toMonth: layout_congrol.year === d.toDay.getFullYear() && month === d.toDay.getMonth() + implicitHeight: 75 + implicitWidth: 75 + FluControl{ + id:control_delegate + width: 60 + height: 60 + anchors.centerIn: parent + Rectangle{ + width: 48 + height: 48 + radius: width/2 + color: { + if(toMonth){ + if(control_delegate.pressed){ + return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.2) : Qt.lighter(FluTheme.primaryColor,1.2) + } + if(control_delegate.hovered){ + return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.1) : Qt.lighter(FluTheme.primaryColor,1.1) + } + return FluTheme.primaryColor + }else{ + if(control_delegate.pressed){ + return FluTheme.itemPressColor + } + if(control_delegate.hovered){ + return FluTheme.itemHoverColor + } + return FluColors.Transparent + } + } + anchors.centerIn: parent + } + FluText{ + text: new Date(layout_congrol.year,month).toLocaleString(FluApp.locale, "MMMM") + anchors.centerIn: parent + opacity: { + if(layout_congrol.year === d.displayDate.getFullYear()){ + return 1 + } + if(control_delegate.hovered){ + return 1 + } + return 0.3 + } + color: { + if(toMonth){ + return FluColors.White + } + if(control_delegate.pressed){ + return FluTheme.dark ? FluColors.Grey100 : FluColors.Grey100 + } + if(control_delegate.hovered){ + return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120 + } + return FluTheme.dark ? FluColors.White : FluColors.Grey220 + } + } + onClicked: { + d.displayDate = new Date(layout_congrol.year,month) + d.pageIndex = 0 + } + } + } + } + } + } + } + Component{ + id:com_page_one + ColumnLayout { + DayOfWeekRow { + id: dayOfWeekRow + locale: FluApp.locale + font.bold: false + delegate: Label { + text: model.shortName + font: dayOfWeekRow.font + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + Layout.column: 1 + Layout.fillWidth: true + } + ListView{ + id:listview + property bool isCompleted: false + Layout.fillWidth: true + Layout.fillHeight: true + highlightRangeMode: ListView.StrictlyEnforceRange + clip: true + boundsBehavior: ListView.StopAtBounds + spacing: 0 + highlightMoveDuration: 100 + currentIndex: -1 + ScrollBar.vertical: FluScrollBar {} + onCurrentIndexChanged:{ + if(isCompleted){ + var month = calender_model.monthAt(currentIndex) + var year = calender_model.yearAt(currentIndex) + d.displayDate = new Date(year,month,1) + } + } + Component.onCompleted: { + listview.model = calender_model + listview.highlightMoveDuration = 0 + currentIndex = calender_model.indexOf(d.displayDate) + timer_delay.restart() + isCompleted = true + } + Timer{ + id:timer_delay + interval: 100 + onTriggered: { + listview.highlightMoveDuration = 100 + } + } + Connections{ + target: d + function onNextButton(){ + listview.currentIndex = Math.min(listview.currentIndex+1,listview.count-1) + } + function onPreviousButton(){ + listview.currentIndex = Math.max(listview.currentIndex-1,0) + } + } + delegate: MonthGrid { + id: grid + width: listview.width + height: listview.height + month: model.month + year: model.year + spacing: 0 + locale: FluApp.locale + delegate: FluControl { + required property bool today + required property int year + required property int month + required property int day + required property int visibleMonth + id: control_delegate + visibleMonth: grid.month + implicitHeight: 40 + implicitWidth: 40 + Rectangle{ + width: 34 + height: 34 + radius: width/2 + color: { + if(today){ + if(control_delegate.pressed){ + return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.2) : Qt.lighter(FluTheme.primaryColor,1.2) + } + if(control_delegate.hovered){ + return FluTheme.dark ? Qt.darker(FluTheme.primaryColor,1.1) : Qt.lighter(FluTheme.primaryColor,1.1) + } + return FluTheme.primaryColor + }else{ + if(control_delegate.pressed){ + return FluTheme.itemPressColor + } + if(control_delegate.hovered){ + return FluTheme.itemHoverColor + } + return FluColors.Transparent + } + } + anchors.centerIn: parent + } + Rectangle{ + width: 40 + height: 40 + border.width: 1 + anchors.centerIn: parent + radius: width/2 + border.color: FluTheme.primaryColor + color: FluColors.Transparent + visible: { + if(control.current){ + var y = control.current.getFullYear() + var m = control.current.getMonth() + var d = control.current.getDate() + if(y === year && m === month && d === day){ + return true + } + return false + } + return false + } + } + FluText{ + text: day + opacity: { + if(month === grid.month){ + return 1 + } + if(control_delegate.hovered){ + return 1 + } + return 0.3 + } + anchors.centerIn: parent + color: { + if(today){ + return FluColors.White + } + if(control_delegate.pressed){ + return FluTheme.dark ? FluColors.Grey100 : FluColors.Grey100 + } + if(control_delegate.hovered){ + return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120 + } + return FluTheme.dark ? FluColors.White : FluColors.Grey220 + } + } + onClicked: { + control.current = new Date(year,month,day) + control.accepted() + popup.close() + } + } + background: Item { + x: grid.leftPadding + y: grid.topPadding + width: grid.availableWidth + height: grid.availableHeight + } + } + } + } + } + } + } + } + } + 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/FluentUI/Controls/FluCarousel.qml b/src/FluentUI/Controls/FluCarousel.qml new file mode 100644 index 00000000..844b8d9d --- /dev/null +++ b/src/FluentUI/Controls/FluCarousel.qml @@ -0,0 +1,206 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +Item { + property bool autoPlay: true + 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 + property bool isAnimEnable: control.autoPlay && list_view.count>3 + 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 + if(d.isAnimEnable){ + 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) + } + interactive: list_view.count>3 + 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 + } + FluLoader{ + 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 : Qt.rgba(1,1,1,0.7) + border.width: mouse_item.containsMouse ? 1 : 0 + border.color: FluTheme.primaryColor + 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 + FluLoader{ + 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: d.isAnimEnable + 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 + if(d.isAnimEnable){ + timer_run.restart() + } + } +} diff --git a/src/FluentUI/Controls/FluChart.qml b/src/FluentUI/Controls/FluChart.qml new file mode 100644 index 00000000..ebc70b15 --- /dev/null +++ b/src/FluentUI/Controls/FluChart.qml @@ -0,0 +1,117 @@ +import QtQuick +import "./../JS/Chart.js" as Chart + +Canvas { + id: control + property string chartType + property var chartData + property var chartOptions + property double chartAnimationProgress: 0.1 + property int animationEasingType: Easing.InOutExpo + property double animationDuration: 300 + property alias animationRunning: chartAnimator.running + signal animationFinished() + function animateToNewData() + { + chartAnimationProgress = 0.1; + d.jsChart.update(); + chartAnimator.restart(); + } + QtObject{ + id:d + property var jsChart: undefined + property var memorizedContext + property var memorizedData + property var memorizedOptions + } + 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 && d.memorizedContext !== control.getContext('2d') || d.memorizedData !== control.chartData || d.memorizedOptions !== control.chartOptions) { + var ctx = control.getContext('2d'); + d.jsChart = Chart.build(ctx, {type: control.chartType,data: control.chartData,options: control.chartOptions}); + d.memorizedData = control.chartData ; + d.memorizedContext = control.getContext('2d'); + d.memorizedOptions = control.chartOptions; + d.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;}); + chartAnimator.start(); + } + d.jsChart.draw(chartAnimationProgress); + } + onWidthChanged: { + if(d.jsChart) { + d.jsChart.resize(); + } + } + onHeightChanged: { + if(d.jsChart) { + d.jsChart.resize(); + } + } +} diff --git a/src/FluentUI/Controls/FluCheckBox.qml b/src/FluentUI/Controls/FluCheckBox.qml new file mode 100644 index 00000000..47c95ee1 --- /dev/null +++ b/src/FluentUI/Controls/FluCheckBox.qml @@ -0,0 +1,138 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +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.primaryColor + 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.primaryColor + 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 bool enableAnimation: FluTheme.enableAnimation + property var clickListener : function(){ + checked = !checked + } + property bool indeterminate : false + id:control + enabled: !disabled + onClicked: clickListener() + onCheckableChanged: { + if(checkable){ + checkable = false + } + } + background: Item{ + FluFocusRectangle{ + radius: 4 + visible: control.activeFocus + } + } + horizontalPadding:0 + verticalPadding: 0 + padding: 0 + 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: control.enableAnimation + ColorAnimation{ + duration: 83 + } + } + + FluIcon { + anchors.centerIn: parent + iconSource: FluentIcons.CheckboxIndeterminate + iconSize: 14 + visible: indeterminate + iconColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) + Behavior on visible { + enabled: control.enableAnimation + NumberAnimation{ + duration: 83 + } + } + } + + FluIcon { + anchors.centerIn: parent + iconSource: FluentIcons.AcceptMedium + iconSize: 14 + visible: checked && !indeterminate + iconColor: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) + Behavior on visible { + enabled: control.enableAnimation + NumberAnimation{ + duration: 83 + } + } + } + } + FluText{ + id:btn_text + text: control.text + Layout.alignment: Qt.AlignVCenter + visible: text !== "" + } + } +} diff --git a/src/FluentUI/Controls/FluClip.qml b/src/FluentUI/Controls/FluClip.qml new file mode 100644 index 00000000..486b9365 --- /dev/null +++ b/src/FluentUI/Controls/FluClip.qml @@ -0,0 +1,20 @@ +import QtQuick +import QtQuick.Controls +import Qt5Compat.GraphicalEffects +import FluentUI + +FluRectangle { + id:control + color: "#00000000" + layer.enabled: !FluTools.isSoftware() + layer.textureSize: Qt.size(control.width*2*Math.ceil(Screen.devicePixelRatio),control.height*2*Math.ceil(Screen.devicePixelRatio)) + layer.effect: OpacityMask{ + maskSource: ShaderEffectSource{ + sourceItem: FluRectangle{ + radius: control.radius + width: control.width + height: control.height + } + } + } +} diff --git a/src/FluentUI/Controls/FluColorPicker.qml b/src/FluentUI/Controls/FluColorPicker.qml new file mode 100644 index 00000000..72728a56 --- /dev/null +++ b/src/FluentUI/Controls/FluColorPicker.qml @@ -0,0 +1,589 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI + +Button{ + id:control + width: 36 + height: 36 + implicitWidth: width + implicitHeight: height + property color current : Qt.rgba(1,1,1,1) + signal accepted() + property int colorHandleRadius: 8 + property string cancelText: "取消" + property string okText: "确定" + property string titleText: "颜色选择器" + property string editText: "编辑颜色" + property string redText: "红色" + property string greenText: "绿色" + property string blueText: "蓝色" + property string opacityText: "透明度" + background: + Rectangle{ + id:layout_color + radius: 5 + color:"#00000000" + border.color: { + if(hovered) + return FluTheme.primaryColor + 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: control.current + } + } + contentItem: Item{} + onClicked: { + color_dialog.open() + } + FluPopup{ + id:color_dialog + implicitWidth: 326 + implicitHeight: 560 + closePolicy: Popup.CloseOnEscape + Rectangle{ + id:layout_actions + width: parent.width + height: 60 + radius: 5 + z:999 + anchors.bottom: parent.bottom + color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) + RowLayout{ + anchors + { + centerIn: parent + margins: spacing + fill: parent + } + spacing: 10 + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + FluButton{ + text: control.cancelText + width: parent.width + anchors.centerIn: parent + onClicked: { + color_dialog.close() + } + } + } + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + FluFilledButton{ + text: control.okText + width: parent.width + anchors.centerIn: parent + onClicked: { + current = layout_color_hue.colorValue + control.accepted() + color_dialog.close() + } + } + } + } + } + contentItem: Flickable{ + implicitWidth: parent.width + implicitHeight: Math.min(layout_content.height,560,color_dialog.height) + boundsBehavior:Flickable.StopAtBounds + contentHeight: layout_content.height + 70 + contentWidth: width + clip: true + ScrollBar.vertical: FluScrollBar {} + Item{ + id: layout_content + width: parent.width + height: childrenRect.height + FluText{ + id: text_titile + font: FluTextStyle.Subtitle + text: control.titleText + anchors{ + left: parent.left + top: parent.top + leftMargin: 20 + topMargin: 20 + } + } + Item{ + id: layout_sb + width: 200 + height: 200 + anchors{ + left: parent.left + top: text_titile.bottom + leftMargin: 12 + } + FluClip{ + id: layout_color_hue + property color colorValue + property real xPercent: pickerCursor.x/width + property real yPercent: pickerCursor.y/height + property real blackPercent: blackCursor.x/(layout_black.width-12) + property real opacityPercent: opacityCursor.x/(layout_opacity.width-12) + property color opacityColor:{ + var c = blackColor + c = Qt.rgba(c.r,c.g,c.b,opacityPercent) + return c + } + onOpacityColorChanged: { + layout_color_hue.colorValue = opacityColor + updateColorText(opacityColor) + } + function updateColorText(color){ + text_box_r.text = String(Math.floor(color.r*255)) + text_box_g.text = String(Math.floor(color.g*255)) + text_box_b.text = String(Math.floor(color.b*255)) + text_box_a.text = String(Math.floor(color.a*100)) + var colorString = color.toString().slice(1) + if(color.a===1){ + colorString = "FF"+colorString + } + text_box_color.text = colorString.toUpperCase() + } + property color blackColor: { + var c = whiteColor + c = Qt.rgba(c.r*blackPercent,c.g*blackPercent,c.b*blackPercent,1) + return c + } + property color hueColor: { + var v = 1.0-xPercent + var c + if(0.0 <= v && v < 0.16) { + c = Qt.rgba(1.0, 0.0, v/0.16, 1.0) + } else if(0.16 <= v && v < 0.33) { + c = Qt.rgba(1.0 - (v-0.16)/0.17, 0.0, 1.0, 1.0) + } else if(0.33 <= v && v < 0.5) { + c = Qt.rgba(0.0, ((v-0.33)/0.17), 1.0, 1.0) + } else if(0.5 <= v && v < 0.76) { + c = Qt.rgba(0.0, 1.0, 1.0 - (v-0.5)/0.26, 1.0) + } else if(0.76 <= v && v < 0.85) { + c = Qt.rgba((v-0.76)/0.09, 1.0, 0.0, 1.0) + } else if(0.85 <= v && v <= 1.0) { + c = Qt.rgba(1.0, 1.0 - (v-0.85)/0.15, 0.0, 1.0) + } else { + c = Qt.rgba(1.0,0.0,0.0,1.0) + } + return c + } + property color whiteColor: { + var c = hueColor + c = Qt.rgba((1-c.r)*yPercent+c.r,(1-c.g)*yPercent+c.g,(1-c.b)*yPercent+c.b,1.0) + return c + } + function updateColor(){ + var r = Number(text_box_r.text)/255 + var g = Number(text_box_g.text)/255 + var b = Number(text_box_b.text)/255 + var opacityPercent = Number(text_box_a.text)/100 + var blackPercent = Math.max(r,g,b) + r = r/blackPercent + g = g/blackPercent + b = b/blackPercent + var yPercent = Math.min(r,g,b) + if(r === g && r === b){ + r = 1 + b = 1 + g = 1 + }else{ + r = (yPercent-r)/(yPercent-1) + g = (yPercent-g)/(yPercent-1) + b = (yPercent-b)/(yPercent-1) + } + var xPercent + if (r === 1.0 && g === 0.0 && b <= 1.0) { + if(b===0.0){ + xPercent = 0 + }else{ + xPercent = 1.0 - b * 0.16 + } + } else if (r <= 1.0 && g === 0.0 && b === 1.0) { + xPercent = 1.0 - (1.0 - r) * 0.17 - 0.16 + } else if (r === 0.0 && g <= 1.0 && b === 1.0) { + xPercent = 1.0 - (g * 0.17 + 0.33) + } else if (r === 0.0 && g === 1.0 && b <= 1.0) { + xPercent = 1.0 - (1.0 - b) * 0.26 - 0.5 + } else if (r <= 1.0 && g === 1.0 && b === 0.0) { + xPercent = 1.0 - (r * 0.09 + 0.76) + } else if (r === 1.0 && g <= 1.0 && b === 0.0) { + xPercent = 1.0 - (1.0 - g) * 0.15 - 0.85 + } else { + xPercent = 0 + } + pickerCursor.x = xPercent * width + pickerCursor.y = yPercent * height + blackCursor.x = blackPercent * (layout_black.width-12) + opacityCursor.x = opacityPercent * (layout_opacity.width-12) + } + radius: [4,4,4,4] + x: colorHandleRadius + y: colorHandleRadius + width: parent.width - 2 * colorHandleRadius + height: parent.height - 2 * colorHandleRadius + Rectangle { + anchors.fill: parent + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { position: 0.0; color: "#FF0000" } + GradientStop { position: 0.16; color: "#FFFF00" } + GradientStop { position: 0.33; color: "#00FF00" } + GradientStop { position: 0.5; color: "#00FFFF" } + GradientStop { position: 0.76; color: "#0000FF" } + GradientStop { position: 0.85; color: "#FF00FF" } + GradientStop { position: 1.0; color: "#FF0000" } + } + } + Rectangle { + anchors.fill: parent + gradient: Gradient { + GradientStop { position: 1.0; color: "#FFFFFFFF" } + GradientStop { position: 0.0; color: "#00000000" } + } + } + Rectangle{ + radius: 4 + anchors.fill: parent + border.width: 1 + border.color: FluTheme.dividerColor + color:"#00000000" + } + } + Item { + id: pickerCursor + Rectangle { + width: colorHandleRadius*2; height: colorHandleRadius*2 + radius: colorHandleRadius + 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: colorHandleRadius + y: colorHandleRadius + preventStealing: true + function handleMouse(mouse) { + if (mouse.buttons & Qt.LeftButton) { + pickerCursor.x = Math.max(0,Math.min(mouse.x - colorHandleRadius,width-2*colorHandleRadius)); + pickerCursor.y = Math.max(0,Math.min(mouse.y - colorHandleRadius,height-2*colorHandleRadius)); + } + } + onPositionChanged:(mouse)=> handleMouse(mouse) + onPressed:(mouse)=> handleMouse(mouse) + } + } + FluClip{ + width: 40 + height: 200 + anchors{ + top: layout_sb.top + bottom: layout_sb.bottom + left: layout_sb.right + topMargin: colorHandleRadius + bottomMargin: colorHandleRadius + leftMargin: 4 + } + radius: [4,4,4,4] + Grid { + padding: 0 + id:target_grid_color + anchors.fill: parent + rows: height/5+1 + columns: width/5+1 + Repeater { + model: (target_grid_color.columns-1)*(target_grid_color.rows-1) + Rectangle { + width: 6 + height: 6 + color: (model.index%2 == 0) ? "gray" : "white" + } + } + } + Rectangle{ + anchors.fill: parent + color:layout_color_hue.colorValue + radius: 4 + border.width: 1 + border.color: FluTheme.dividerColor + } + } + + Column{ + id:layout_slider_bar + spacing: 8 + anchors{ + left: parent.left + leftMargin: 18 + right: parent.right + rightMargin: 18 + top: layout_sb.bottom + topMargin: 10 + } + Rectangle{ + id:layout_black + radius: 6 + height: 12 + width:parent.width + gradient: Gradient { + orientation:Gradient.Horizontal + GradientStop { position: 0.0; color: "#FF000000" } + GradientStop { position: 1.0; color: layout_color_hue.hueColor } + } + Item { + id:blackCursor + x:layout_black.width-12 + Rectangle { + width: 12 + height: 12 + radius: 6 + 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 + preventStealing: true + function handleMouse(mouse) { + if (mouse.buttons & Qt.LeftButton) { + blackCursor.x = Math.max(0,Math.min(mouse.x - 6,width-2*6)); + blackCursor.y = 0 + } + } + onPositionChanged:(mouse)=> handleMouse(mouse) + onPressed:(mouse)=> handleMouse(mouse) + } + + } + FluClip{ + id:layout_opacity + height: 12 + width:parent.width + radius: [6,6,6,6] + Grid { + id:grid_opacity + anchors.fill: parent + rows: height/4 + columns: width/4+1 + clip: true + Repeater { + model: grid_opacity.columns*grid_opacity.rows + Rectangle { + width: 4 + height: 4 + color: (model.index%2 == 0) ? "gray" : "white" + } + } + } + MouseArea{ + anchors.fill: parent + onClicked: { + console.debug(grid_opacity.columns,grid_opacity.rows) + } + } + Rectangle{ + anchors.fill: parent + gradient: Gradient { + orientation:Gradient.Horizontal + GradientStop { position: 0.0; color: "#00000000" } + GradientStop { position: 1.0; color: layout_color_hue.blackColor } + } + } + Item { + id:opacityCursor + x:layout_opacity.width-12 + Rectangle { + width: 12 + height: 12 + radius: 6 + 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 { + id:mouse_opacity + anchors.fill: parent + preventStealing: true + function handleMouse(mouse) { + if (mouse.buttons & Qt.LeftButton) { + opacityCursor.x = Math.max(0,Math.min(mouse.x - 6,width-2*6)); + opacityCursor.y = 0 + } + } + onPositionChanged:(mouse)=> handleMouse(mouse) + onPressed:(mouse)=> handleMouse(mouse) + } + } + } + + Column{ + anchors{ + left: parent.left + leftMargin: 20 + top: layout_slider_bar.bottom + topMargin: 10 + right: parent.right + rightMargin: 20 + } + spacing: 5 + Item{ + width: parent.width + height: text_box_color.height + FluText{ + text: control.editText + anchors{ + verticalCenter: parent.verticalCenter + left:parent.left + } + } + FluTextBox{ + id:text_box_color + width: 136 + validator: RegularExpressionValidator { + regularExpression: /^[0-9A-F]{8}$/ + } + anchors{ + right: parent.right + } + leftPadding: 20 + FluText{ + text:"#" + anchors{ + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 5 + } + } + onTextEdited: { + if(text!==""){ + var colorString = text_box_color.text.padStart(8,"0") + var c = Qt.rgba( + parseInt(colorString.substring(2, 4), 16) / 255, + parseInt(colorString.substring(4, 6), 16) / 255, + parseInt(colorString.substring(6, 8), 16) / 255, + parseInt(colorString.substring(0, 2), 16) / 255) + layout_color_hue.colorValue = c + } + } + } + } + Row{ + spacing: 10 + FluTextBox{ + id:text_box_r + width: 120 + validator: RegularExpressionValidator { + regularExpression: /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$/ + } + onTextEdited: { + if(text!==""){ + layout_color_hue.updateColor() + } + } + } + FluText{ + text: control.redText + anchors.verticalCenter: parent.verticalCenter + } + } + Row{ + spacing: 10 + FluTextBox{ + id:text_box_g + width: 120 + validator: RegularExpressionValidator { + regularExpression: /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$/ + } + onTextEdited: { + if(text!==""){ + layout_color_hue.updateColor() + } + } + } + FluText{ + text: control.greenText + anchors.verticalCenter: parent.verticalCenter + } + } + Row{ + spacing: 10 + FluTextBox{ + id:text_box_b + width: 120 + validator: RegularExpressionValidator { + regularExpression: /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$/ + } + onTextEdited: { + if(text!==""){ + layout_color_hue.updateColor() + } + } + } + FluText{ + text: control.blueText + anchors.verticalCenter: parent.verticalCenter + } + } + Row{ + spacing: 10 + FluTextBox{ + id:text_box_a + width: 120 + validator: RegularExpressionValidator { + regularExpression: /^(100|[1-9]?\d)$/ + } + FluText{ + id:text_opacity + text:"%" + anchors.verticalCenter: parent.verticalCenter + x:Math.min(text_box_a.implicitWidth,text_box_a.width)-38 + } + onTextEdited: { + if(text!==""){ + opacityCursor.x = Number(text)/100 * (layout_opacity.width-12) + } + } + } + FluText{ + text: control.opacityText + anchors.verticalCenter: parent.verticalCenter + } + } + } + } + } + } +} diff --git a/src/FluentUI/Controls/FluComboBox.qml b/src/FluentUI/Controls/FluComboBox.qml new file mode 100644 index 00000000..fb7a1665 --- /dev/null +++ b/src/FluentUI/Controls/FluComboBox.qml @@ -0,0 +1,146 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI +import QtQuick.Templates as T + +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,0.5) + selectedTextColor: color + text: control.editable ? control.editText : control.displayText + enabled: control.editable + autoScroll: control.editable + font:control.font + readOnly: control.down + color: { + if(control.disabled) { + return FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + } + return 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{ + borderWidth: 0 + inputItem: contentItem + } + Component.onCompleted: { + forceActiveFocus() + } + Keys.onEnterPressed: (event)=> handleCommit(event) + Keys.onReturnPressed:(event)=> handleCommit(event) + function handleCommit(event){ + control.commit(control.editText) + accepted() + } + } + + 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 + modal: true + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: control.delegateModel + currentIndex: control.highlightedIndex + highlightMoveDuration: 0 + boundsMovement: Flickable.StopAtBounds + 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/FluentUI/Controls/FluContentDialog.qml b/src/FluentUI/Controls/FluContentDialog.qml new file mode 100644 index 00000000..6c4ae127 --- /dev/null +++ b/src/FluentUI/Controls/FluContentDialog.qml @@ -0,0 +1,163 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Window +import FluentUI + +FluPopup { + id: control + property string title: "" + property string message: "" + property string neutralText: qsTr("Close") + property string negativeText: qsTr("Cancel") + property string positiveText: qsTr("OK") + property int messageTextFormart: Text.AutoText + property int delayTime: 100 + property int buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton + property var contentDelegate: Component{ + Item{ + } + } + property var onNeutralClickListener + property var onNegativeClickListener + property var onPositiveClickListener + signal neutralClicked + signal negativeClicked + signal positiveClicked + implicitWidth: 400 + implicitHeight: layout_content.height + focus: true + Component{ + id:com_message + Flickable{ + id:sroll_message + contentHeight: text_message.height + contentWidth: width + clip: true + boundsBehavior:Flickable.StopAtBounds + width: parent.width + height: message === "" ? 0 : Math.min(text_message.height,300) + ScrollBar.vertical: FluScrollBar {} + FluText{ + id:text_message + font: FluTextStyle.Body + wrapMode: Text.WrapAnywhere + text:message + width: parent.width + topPadding: 4 + leftPadding: 20 + rightPadding: 20 + bottomPadding: 4 + } + } + } + Rectangle { + id:layout_content + width: parent.width + height: layout_column.childrenRect.height + color: 'transparent' + radius:5 + ColumnLayout{ + id:layout_column + width: parent.width + FluText{ + id:text_title + font: FluTextStyle.Title + text:title + topPadding: 20 + leftPadding: 20 + rightPadding: 20 + wrapMode: Text.WrapAnywhere + } + FluLoader{ + sourceComponent: com_message + Layout.fillWidth: true + Layout.preferredHeight: status===Loader.Ready ? item.height : 0 + } + FluLoader{ + sourceComponent:control.visible ? control.contentDelegate : undefined + Layout.fillWidth: true + onStatusChanged: { + if(status===Loader.Ready){ + Layout.preferredHeight = item.implicitHeight + }else{ + Layout.preferredHeight = 0 + } + } + } + Rectangle{ + id:layout_actions + Layout.fillWidth: true + Layout.preferredHeight: 60 + radius: 5 + color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) + RowLayout{ + anchors + { + centerIn: parent + margins: spacing + fill: parent + } + spacing: 10 + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + FluButton{ + id:neutral_btn + visible: control.buttonFlags&FluContentDialogType.NeutralButton + text: neutralText + width: parent.width + anchors.centerIn: parent + onClicked: { + if(control.onNeutralClickListener){ + control.onNeutralClickListener() + }else{ + neutralClicked() + control.close() + } + } + } + } + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + FluButton{ + id:negative_btn + visible: control.buttonFlags&FluContentDialogType.NegativeButton + width: parent.width + anchors.centerIn: parent + text: negativeText + onClicked: { + if(control.onNegativeClickListener){ + control.onNegativeClickListener() + }else{ + negativeClicked() + control.close() + } + } + } + } + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + FluFilledButton{ + id:positive_btn + visible: control.buttonFlags&FluContentDialogType.PositiveButton + text: positiveText + width: parent.width + anchors.centerIn: parent + onClicked: { + if(control.onPositiveClickListener){ + control.onPositiveClickListener() + }else{ + positiveClicked() + control.close() + } + } + } + } + } + } + } + } +} diff --git a/src/FluentUI/Controls/FluContentPage.qml b/src/FluentUI/Controls/FluContentPage.qml new file mode 100644 index 00000000..02815fab --- /dev/null +++ b/src/FluentUI/Controls/FluContentPage.qml @@ -0,0 +1,60 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI + +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 + } + } + FluStatusLayout{ + id:status_view + color: "#00000000" + statusMode: FluStatusLayoutType.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/FluentUI/Controls/FluControl.qml b/src/FluentUI/Controls/FluControl.qml new file mode 100644 index 00000000..50f672e4 --- /dev/null +++ b/src/FluentUI/Controls/FluControl.qml @@ -0,0 +1,28 @@ +import QtQuick +import QtQuick.Controls.impl +import FluentUI +import QtQuick.Templates 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/FluentUI/Controls/FluCopyableText.qml b/src/FluentUI/Controls/FluCopyableText.qml new file mode 100644 index 00000000..34c1fc7f --- /dev/null +++ b/src/FluentUI/Controls/FluCopyableText.qml @@ -0,0 +1,35 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +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,0.5) + 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/FluentUI/Controls/FluDatePicker.qml b/src/FluentUI/Controls/FluDatePicker.qml new file mode 100644 index 00000000..abfcf47d --- /dev/null +++ b/src/FluentUI/Controls/FluDatePicker.qml @@ -0,0 +1,415 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI + +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 + property string yearText: qsTr("Year") + property string monthText: qsTr("Month") + property string dayText: qsTr("Day") + property string cancelText: qsTr("Cancel") + property string okText: qsTr("OK") + signal accepted() + id:control + color: { + if(mouse_area.containsMouse){ + return hoverColor + } + return normalColor + } + height: 30 + width: 300 + radius: 4 + border.width: 1 + border.color: dividerColor + Component.onCompleted: { + if(current){ + const now = current; + var year = text_year.text === control.yearText? now.getFullYear() : Number(text_year.text); + var month = text_month.text === control.monthText? now.getMonth() + 1 : Number(text_month.text); + var day = text_day.text === control.dayText ? now.getDate() : Number(text_day.text); + text_year.text = year + text_month.text = month + text_day.text = day + } + } + 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:control.yearText + } + 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:control.monthText + } + 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:control.dayText + } + Menu{ + id:popup + modal: true + width: container.width + height: container.height + Overlay.modal: Item {} + 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){ + return item_mouse.containsMouse ? Qt.lighter(FluTheme.primaryColor,1.1): FluTheme.primaryColor + } + 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: FluLoader{ + 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: FluLoader{ + 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: FluLoader{ + 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: control.cancelText + onClicked: { + popup.close() + } + } + FluFilledButton{ + anchors{ + right: parent.right + left: divider.right + rightMargin: 20 + leftMargin: 10 + verticalCenter: parent.verticalCenter + } + text: control.okText + 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 + control.accepted() + } + } + } + } + } + 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 === control.yearText? now.getFullYear() : Number(text_year.text); + var month = text_month.text === control.monthText? now.getMonth() + 1 : Number(text_month.text); + var day = text_day.text === control.dayText ? 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/FluentUI/Controls/FluDivider.qml b/src/FluentUI/Controls/FluDivider.qml new file mode 100644 index 00000000..3c6748a1 --- /dev/null +++ b/src/FluentUI/Controls/FluDivider.qml @@ -0,0 +1,34 @@ +import QtQuick +import QtQuick.Window +import FluentUI + +Item { + id:control + property int orientation: Qt.Horizontal + property int spacing:0 + property int size: 1 + QtObject{ + id:d + property bool isVertical : orientation === Qt.Vertical + property int parentHeight: { + if(control.parent){ + return control.parent.height + } + return control.height + } + property int parentWidth: { + if(control.parent){ + return control.parent.width + } + return control.width + } + } + width: d.isVertical ? spacing*2+size : d.parentWidth + height: d.isVertical ? d.parentHeight : spacing*2+size + FluRectangle{ + color: FluTheme.dividerColor + width: d.isVertical ? size : control.width + height: d.isVertical ? control.height : size + anchors.centerIn: parent + } +} diff --git a/src/FluentUI/Controls/FluDropDownButton.qml b/src/FluentUI/Controls/FluDropDownButton.qml new file mode 100644 index 00000000..5e9f8c3d --- /dev/null +++ b/src/FluentUI/Controls/FluDropDownButton.qml @@ -0,0 +1,96 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import QtQuick.Window +import FluentUI + +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(246/255,246/255,246/255,1) + property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/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 + verticalPadding: 0 + 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/FluentUI/Controls/FluExpander.qml b/src/FluentUI/Controls/FluExpander.qml new file mode 100644 index 00000000..b2230a70 --- /dev/null +++ b/src/FluentUI/Controls/FluExpander.qml @@ -0,0 +1,133 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Window +import FluentUI + +Item { + property string headerText: "" + property bool expand: false + property int contentHeight : 300 + default property alias content: container.data + id:control + implicitHeight: Math.max((layout_header.height + layout_container.height),layout_header.height) + implicitWidth: 400 + QtObject{ + id:d + property bool flag: false + function toggle(){ + d.flag = true + expand = !expand + d.flag = false + } + } + clip: true + 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: { + d.toggle() + } + } + 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: { + d.toggle() + } + 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{ + id:layout_container + anchors{ + top: layout_header.bottom + topMargin: -1 + left: layout_header.left + } + visible: contentHeight+container.anchors.topMargin !== 0 + height: contentHeight+container.anchors.topMargin + width: parent.width + z:-999 + Rectangle{ + id:container + anchors.fill: parent + radius: 4 + clip: true + 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) + anchors.topMargin: -contentHeight + states: [ + State{ + name:"expand" + when: control.expand + PropertyChanges { + target: container + anchors.topMargin:0 + } + }, + State{ + name:"collapsed" + when: !control.expand + PropertyChanges { + target: container + anchors.topMargin:-contentHeight + } + } + ] + transitions: [ + Transition { + to:"expand" + NumberAnimation { + properties: "anchors.topMargin" + duration: FluTheme.enableAnimation && d.flag ? 167 : 0 + easing.type: Easing.OutCubic + } + }, + Transition { + to:"collapsed" + NumberAnimation { + properties: "anchors.topMargin" + duration: FluTheme.enableAnimation && d.flag ? 167 : 0 + easing.type: Easing.OutCubic + } + } + ] + } + } +} diff --git a/src/FluentUI/Controls/FluFilledButton.qml b/src/FluentUI/Controls/FluFilledButton.qml new file mode 100644 index 00000000..b83505cf --- /dev/null +++ b/src/FluentUI/Controls/FluFilledButton.qml @@ -0,0 +1,72 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +Button { + property bool disabled: false + property string contentDescription: "" + property color normalColor: FluTheme.primaryColor + 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 + verticalPadding: 0 + horizontalPadding:12 + background: Rectangle{ + implicitWidth: 28 + implicitHeight: 28 + radius: 4 + FluFocusRectangle{ + visible: control.visualFocus + radius:4 + } + gradient: Gradient { + GradientStop { position: 0.33; color: control.enabled ? control.normalColor : Qt.rgba(0,0,0,0) } + GradientStop { position: 1.0; color: control.enabled ? Qt.darker(control.normalColor,1.3) : Qt.rgba(0,0,0,0) } + } + Rectangle{ + radius: parent.radius + anchors{ + fill: parent + topMargin: control.enabled ? 0 : 0 + leftMargin: control.enabled ? 1 : 0 + rightMargin: control.enabled ? 1 : 0 + bottomMargin: control.enabled ? 2 : 0 + } + 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/FluentUI/Controls/FluFlipView.qml b/src/FluentUI/Controls/FluFlipView.qml new file mode 100644 index 00000000..1f3012a8 --- /dev/null +++ b/src/FluentUI/Controls/FluFlipView.qml @@ -0,0 +1,107 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +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/FluentUI/Controls/FluFocusRectangle.qml b/src/FluentUI/Controls/FluFocusRectangle.qml new file mode 100644 index 00000000..5c6c9596 --- /dev/null +++ b/src/FluentUI/Controls/FluFocusRectangle.qml @@ -0,0 +1,19 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +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/FluentUI/Controls/FluIcon.qml b/src/FluentUI/Controls/FluIcon.qml new file mode 100644 index 00000000..edf17b61 --- /dev/null +++ b/src/FluentUI/Controls/FluIcon.qml @@ -0,0 +1,19 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +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/FluentUI/Controls/FluIconButton.qml b/src/FluentUI/Controls/FluIconButton.qml new file mode 100644 index 00000000..b52dcff6 --- /dev/null +++ b/src/FluentUI/Controls/FluIconButton.qml @@ -0,0 +1,130 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Controls.Basic +import FluentUI + +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.itemHoverColor + property color pressedColor: FluTheme.itemPressColor + property color normalColor: FluTheme.itemNormalColor + property color disableColor: FluTheme.itemNormalColor + 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) + } + } + property color textColor: FluTheme.fontPrimaryColor + 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 + font:FluTextStyle.Caption + 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{ + FluLoader{ + 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 + color: control.textColor + font: control.font + } + } + } + Component{ + id:com_column + ColumnLayout{ + FluLoader{ + 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 + color: control.textColor + font: control.font + } + } + } + contentItem:FluLoader{ + sourceComponent: { + if(display === Button.TextUnderIcon){ + return com_column + } + return com_row + } + } + FluTooltip{ + id:tool_tip + visible: { + if(control.text === ""){ + return false + } + if(control.display !== Button.IconOnly){ + return false + } + return hovered + } + text:control.text + delay: 1000 + } +} diff --git a/src/FluentUI/Controls/FluImage.qml b/src/FluentUI/Controls/FluImage.qml new file mode 100644 index 00000000..dcdc3fc1 --- /dev/null +++ b/src/FluentUI/Controls/FluImage.qml @@ -0,0 +1,48 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +Image { + property string errorButtonText: qsTr("Reload") + property var clickErrorListener : function(){ + image.source = "" + image.source = control.source + } + property Component errorItem : com_error + property Component loadingItem: com_loading + id: control + FluLoader{ + 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.itemHoverColor + FluProgressRing{ + anchors.centerIn: parent + visible: control.status === Image.Loading + } + } + } + Component{ + id:com_error + Rectangle{ + color: FluTheme.itemHoverColor + FluFilledButton{ + text: control.errorButtonText + anchors.centerIn: parent + visible: control.status === Image.Error + onClicked: clickErrorListener() + } + } + } +} diff --git a/src/FluentUI/Controls/FluImageButton.qml b/src/FluentUI/Controls/FluImageButton.qml new file mode 100644 index 00000000..b028eee4 --- /dev/null +++ b/src/FluentUI/Controls/FluImageButton.qml @@ -0,0 +1,18 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +Button{ + id:control + property string normalImage: "" + property string hoveredImage: "" + property string pushedImage: "" + background: Item{ + implicitHeight: 12 + implicitWidth: 12 + BorderImage { + anchors.fill: parent + source: control.hovered ? (control.pressed ? control.pushedImage : control.hoveredImage ) : control.normalImage + } + } +} diff --git a/src/FluentUI/Controls/FluInfoBar.qml b/src/FluentUI/Controls/FluInfoBar.qml new file mode 100644 index 00000000..4eaa185c --- /dev/null +++ b/src/FluentUI/Controls/FluInfoBar.qml @@ -0,0 +1,252 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +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{ + parent: Overlay.overlay + z:999 + spacing: 20 + width: root.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: duration > 0; repeat: duration > 0 + onTriggered: content.close(); + } + FluLoader{ + 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 + (btn_close.visible ? 30 : 48); + 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" + } + } + FluShadow{ + radius: 4 + } + 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; + 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" + } + } + } + + Column{ + spacing: 5 + FluText{ + text:_super.text + wrapMode: Text.WrapAnywhere + width: Math.min(implicitWidth,mcontrol.maxWidth) + } + FluText{ + text: _super.moremsg + visible: _super.moremsg + wrapMode : Text.WrapAnywhere + textColor: FluColors.Grey120 + width: Math.min(implicitWidth,mcontrol.maxWidth) + } + } + + FluIconButton{ + id:btn_close + iconSource: FluentIcons.ChromeClose + iconSize: 10 + y:5 + visible: _super.duration<=0 + 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; + 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" + } + } + onClicked: _super.close() + } + } + } + } + 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/FluentUI/Controls/FluItemDelegate.qml b/src/FluentUI/Controls/FluItemDelegate.qml new file mode 100644 index 00000000..265bc3cc --- /dev/null +++ b/src/FluentUI/Controls/FluItemDelegate.qml @@ -0,0 +1,39 @@ +import QtQuick +import QtQuick.Controls.Basic +import QtQuick.Templates as T +import FluentUI + +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: 0 + verticalPadding: 8 + horizontalPadding: 10 + icon.color: control.palette.text + contentItem:FluText { + text: control.text + font: control.font + color:{ + if(control.down){ + return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120 + } + return FluTheme.dark ? FluColors.White : FluColors.Grey220 + } + } + background: Rectangle { + implicitWidth: 100 + implicitHeight: 30 + 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/FluentUI/Controls/FluLoader.qml b/src/FluentUI/Controls/FluLoader.qml new file mode 100644 index 00000000..fcf5dae5 --- /dev/null +++ b/src/FluentUI/Controls/FluLoader.qml @@ -0,0 +1,5 @@ +import QtQuick + +Loader { + Component.onDestruction: sourceComponent = undefined +} diff --git a/src/FluentUI/Controls/FluLoadingButton.qml b/src/FluentUI/Controls/FluLoadingButton.qml new file mode 100644 index 00000000..5b91a281 --- /dev/null +++ b/src/FluentUI/Controls/FluLoadingButton.qml @@ -0,0 +1,41 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +FluButton { + property bool loading: false + id: control + disabled: loading + contentItem: Row{ + spacing: 6 + FluText { + text: control.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font: control.font + color: control.textColor + anchors.verticalCenter: parent.verticalCenter + } + Item{ + width: control.loading ? 16 : 0 + height: 16 + anchors.verticalCenter: parent.verticalCenter + visible: Number(width)!==0 + clip: true + Behavior on width { + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 167 + easing.type: Easing.OutCubic + } + } + FluProgressRing{ + width: 16 + height: 16 + strokeWidth:3 + anchors.centerIn: parent + } + } + } +} diff --git a/src/FluentUI/Controls/FluMenu.qml b/src/FluentUI/Controls/FluMenu.qml new file mode 100644 index 00000000..5090f3ac --- /dev/null +++ b/src/FluentUI/Controls/FluMenu.qml @@ -0,0 +1,59 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Templates as T +import FluentUI + +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: Color.transparent(control.palette.shadow, 0.5) + } + T.Overlay.modeless: Rectangle { + color: Color.transparent(control.palette.shadow, 0.12) + } +} diff --git a/src/FluentUI/Controls/FluMenuBar.qml b/src/FluentUI/Controls/FluMenuBar.qml new file mode 100644 index 00000000..9c76ec42 --- /dev/null +++ b/src/FluentUI/Controls/FluMenuBar.qml @@ -0,0 +1,21 @@ +import QtQuick +import QtQuick.Templates as T +import QtQuick.Controls.impl + +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/FluentUI/Controls/FluMenuBarItem.qml b/src/FluentUI/Controls/FluMenuBarItem.qml new file mode 100644 index 00000000..b7e9e175 --- /dev/null +++ b/src/FluentUI/Controls/FluMenuBarItem.qml @@ -0,0 +1,61 @@ +import QtQuick +import QtQuick.Templates as T +import QtQuick.Controls.impl +import FluentUI + +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(control.highlighted){ + return FluTheme.itemCheckColor + } + if(control.hovered){ + return FluTheme.itemHoverColor + } + return FluTheme.itemNormalColor + } + } +} + diff --git a/src/FluentUI/Controls/FluMenuItem.qml b/src/FluentUI/Controls/FluMenuItem.qml new file mode 100644 index 00000000..a1577c6b --- /dev/null +++ b/src/FluentUI/Controls/FluMenuItem.qml @@ -0,0 +1,111 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Controls.impl +import QtQuick.Templates as T +import FluentUI + +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 + font:FluTextStyle.Body + 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 + } + FluLoader{ + id:loader_icon + sourceComponent: iconDelegate + anchors.verticalCenter: parent.verticalCenter + visible: status === Loader.Ready + } + FluText { + id:content_text + text: control.text + font: control.font + 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(control.highlighted){ + return FluTheme.itemCheckColor + } + return FluTheme.itemNormalColor + } + } + } +} diff --git a/src/FluentUI/Controls/FluMenuSeparator.qml b/src/FluentUI/Controls/FluMenuSeparator.qml new file mode 100644 index 00000000..a687e30a --- /dev/null +++ b/src/FluentUI/Controls/FluMenuSeparator.qml @@ -0,0 +1,19 @@ +import QtQuick +import QtQuick.Controls.impl +import QtQuick.Templates as T +import FluentUI + +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/FluentUI/Controls/FluMultilineTextBox.qml b/src/FluentUI/Controls/FluMultilineTextBox.qml new file mode 100644 index 00000000..6d1c3649 --- /dev/null +++ b/src/FluentUI/Controls/FluMultilineTextBox.qml @@ -0,0 +1,82 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +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) + property bool isCtrlEnterForNewline: false + id:control + enabled: !disabled + color: { + if(!enabled){ + return disableColor + } + return normalColor + } + font:FluTextStyle.Body + wrapMode: Text.WrapAnywhere + padding: 8 + leftPadding: padding+4 + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + selectedTextColor: color + selectionColor: FluTools.colorAlpha(FluTheme.primaryColor,0.5) + placeholderTextColor: { + if(!enabled){ + return placeholderDisableColor + } + if(focus){ + return placeholderFocusColor + } + return placeholderNormalColor + } + selectByMouse: true + width: 240 + background: FluTextBoxBackground{ + inputItem: control + } + Keys.onEnterPressed: (event)=> d.handleCommit(event) + Keys.onReturnPressed:(event)=> d.handleCommit(event) + QtObject{ + id:d + function handleCommit(event){ + if(isCtrlEnterForNewline){ + if(event.modifiers & Qt.ControlModifier){ + insert(control.cursorPosition, "\n") + return + } + control.commit(control.text) + }else{ + if(event.modifiers & Qt.ControlModifier){ + control.commit(control.text) + return + } + insert(control.cursorPosition, "\n") + } + } + } + MouseArea{ + anchors.fill: parent + cursorShape: Qt.IBeamCursor + acceptedButtons: Qt.RightButton + onClicked: { + if(control.echoMode === TextInput.Password){ + return + } + if(control.readOnly && control.text === ""){ + return + } + menu.popup() + } + } + FluTextBoxMenu{ + id:menu + inputItem: control + } +} diff --git a/src/FluentUI/Controls/FluNavigationView.qml b/src/FluentUI/Controls/FluNavigationView.qml new file mode 100644 index 00000000..a44027a7 --- /dev/null +++ b/src/FluentUI/Controls/FluNavigationView.qml @@ -0,0 +1,1344 @@ +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Controls.Basic +import QtQuick.Layouts +import FluentUI + +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 pageMode: FluNavigationViewType.Stack + property FluMenu navItemRightMenu + property FluMenu navItemExpanderRightMenu + property int navCompactWidth: 50 + property int navTopMargin: 0 + property int cellHeight: 38 + property int cellWidth: 300 + property bool hideNavAppBar: false + property alias buttonMenu: btn_menu + property alias buttonBack: btn_back + property alias imageLogo: image_logo + 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 + property color itemDisableColor: FluTheme.dark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1) + onIsCompactAndNotPanelChanged: { + collapseAll() + } + function handleItems(){ + var _idx = 0 + var data = [] + var comEmpty = Qt.createComponent("FluPaneItemEmpty.qml"); + if(items){ + for(var i=0;i{ + if (mouse.button === Qt.RightButton) { + if(model.menuDelegate){ + loader_item_menu.sourceComponent = model.menuDelegate + connection_item_menu.target = loader_item_menu.item + loader_item_menu.modelData = model + loader_item_menu.item.popup(); + } + } + } + z:-100 + } + onClicked: { + if(d.isCompactAndNotPanel && model.children.length > 0){ + let h = 38*Math.min(Math.max(model.children.length,1),8) + let y = mapToItem(control,0,0).y + if(h+y>control.height){ + y = control.height - h + } + control_popup.showPopup(Qt.point(control.navCompactWidth,y),h,model.children) + return + } + model.isExpand = !model.isExpand + } + Rectangle{ + color:Qt.rgba(255/255,77/255,79/255,1) + width: 10 + height: 10 + radius: 5 + border.width: 1 + border.color: Qt.rgba(1,1,1,1) + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + rightMargin: 3 + verticalCenterOffset: -8 + } + visible: { + if(!model){ + return false + } + if(!model.isExpand){ + for(var i=0;i{ + if (mouse.button === Qt.RightButton) { + if(model.menuDelegate){ + loader_item_menu.sourceComponent = model.menuDelegate + connection_item_menu.target = loader_item_menu.item + loader_item_menu.modelData = model + loader_item_menu.item.popup(); + } + }else{ + item_control.clicked() + } + } + } + Rectangle{ + radius: 4 + anchors.fill: parent + color: { + if(!item_control.enabled){ + return FluTheme.itemNormalColor + } + if(type===0){ + if(nav_list.currentIndex === _idx){ + return FluTheme.itemCheckColor + } + }else{ + if(nav_list.currentIndex === (nav_list.count-layout_footer.count+_idx)){ + return FluTheme.itemCheckColor + } + } + if(item_control.hovered){ + return FluTheme.itemHoverColor + } + return FluTheme.itemNormalColor + } + Component{ + id:com_icon + FluIcon{ + iconSource: { + if(model&&model.icon){ + return model.icon + } + return 0 + } + color: { + if(!item_control.enabled){ + return d.itemDisableColor + } + return FluTheme.dark ? "#FFFFFF" : "#000000" + } + iconSize: 15 + } + } + Item{ + id:item_icon + height: 30 + width: visible ? 30 : 8 + visible: { + if(model){ + return model.iconVisible + } + return true + } + anchors{ + left:parent.left + verticalCenter: parent.verticalCenter + leftMargin: d.isCompactAndNotPanel ? (parent.width - 30)/2 : 3 + } + FluLoader{ + anchors.centerIn: parent + sourceComponent: { + if(model&&model.iconDelegate){ + return model.iconDelegate + } + return com_icon + } + } + } + FluText{ + id:item_title + text:{ + if(model){ + if(!item_icon.visible && d.isCompactAndNotPanel){ + return model.title[0] + } + return model.title + } + return "" + } + visible: { + if(d.isCompactAndNotPanel){ + if(item_icon.visible){ + return false + } + return true + } + return true + } + elide: Text.ElideRight + color:{ + if(!item_control.enabled){ + return d.itemDisableColor + } + if(item_mouse.pressed){ + return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120 + } + return FluTheme.dark ? FluColors.White : FluColors.Grey220 + } + anchors{ + verticalCenter: parent.verticalCenter + left:item_icon.right + right: item_dot_loader.left + } + } + FluLoader{ + id:item_edit_loader + anchors{ + top: parent.top + bottom: parent.bottom + left: item_title.left + right: item_title.right + rightMargin: 8 + } + sourceComponent: { + if(d.isCompact){ + return undefined + } + if(!model){ + return undefined + } + return model.showEdit ? model.editDelegate : undefined + } + onStatusChanged: { + if(status === FluLoader.Ready){ + item.forceActiveFocus() + item_connection_edit_focus.target = item + } + } + Connections{ + id:item_connection_edit_focus + ignoreUnknownSignals:true + function onActiveFocusChanged(focus){ + if(focus === false){ + model.showEdit = false + } + } + function onCommit(text){ + model.title = text + model.showEdit = false + } + } + } + FluLoader{ + id:item_dot_loader + property bool isDot: (item_dot_loader.item&&item_dot_loader.item.isDot) + anchors{ + right: parent.right + verticalCenter: parent.verticalCenter + rightMargin: isDot ? 3 : 10 + verticalCenterOffset: isDot ? -8 : 0 + } + sourceComponent: { + if(model&&model.infoBadge){ + return model.infoBadge + } + return undefined + } + Connections{ + target: d + function onIsCompactAndNotPanelChanged(){ + if(item_dot_loader.item){ + item_dot_loader.item.isDot = d.isCompactAndNotPanel + } + } + } + } + } + } + } + } + Item { + id:nav_app_bar + width: parent.width + height: visible ? 40 : 0 + anchors{ + top: parent.top + topMargin: control.topPadding + } + visible: !control.hideNavAppBar + z:999 + RowLayout{ + height:parent.height + spacing: 0 + FluIconButton{ + id:btn_back + iconSource: FluentIcons.ChromeBack + Layout.leftMargin: 5 + Layout.alignment: Qt.AlignVCenter + disabled: { + return d.stackItems.length <= 1 + } + iconSize: 13 + onClicked: { + d.stackItems = d.stackItems.slice(0, -1) + var item = d.stackItems[d.stackItems.length-1] + if(item._idx<(nav_list.count - layout_footer.count)){ + layout_footer.currentIndex = -1 + }else{ + layout_footer.currentIndex = item._idx-(nav_list.count-layout_footer.count) + } + nav_list.currentIndex = item._idx + if(pageMode === FluNavigationViewType.Stack){ + var nav_stack = loader_content.item.navStack() + var nav_stack2 = loader_content.item.navStack2() + nav_stack.pop() + if(nav_stack.currentItem.launchMode === FluPageType.SingleInstance){ + var url = nav_stack.currentItem.url + var pageIndex = -1 + for(var i=0;i children + id:control +} diff --git a/src/FluentUI/Controls/FluPage.qml b/src/FluentUI/Controls/FluPage.qml new file mode 100644 index 00000000..87420acd --- /dev/null +++ b/src/FluentUI/Controls/FluPage.qml @@ -0,0 +1,43 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Window +import FluentUI + +Item { + property int launchMode: FluPageType.SingleTop + property bool animDisabled: false + property string url : "" + signal animationEnd() + 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 + timer.restart() + } + Timer{ + id:timer + interval: !animDisabled && FluTheme.enableAnimation ? 200 : 0 + onTriggered: { + control.animationEnd() + } + } +} diff --git a/src/FluentUI/Controls/FluPagination.qml b/src/FluentUI/Controls/FluPagination.qml new file mode 100644 index 00000000..37f6807d --- /dev/null +++ b/src/FluentUI/Controls/FluPagination.qml @@ -0,0 +1,100 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +Item { + signal requestPage(int page,int count) + property string previousText: qsTr("") + 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/FluentUI/Controls/FluPaneItem.qml b/src/FluentUI/Controls/FluPaneItem.qml new file mode 100644 index 00000000..d2214015 --- /dev/null +++ b/src/FluentUI/Controls/FluPaneItem.qml @@ -0,0 +1,25 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property var _ext + property var _parent + property bool visible: true + property string title + property var url + property bool disabled: false + property int icon + property bool iconVisible: true + property Component infoBadge + property int count: 0 + property var onTapListener + property Component iconDelegate + property Component menuDelegate + property Component editDelegate + property var extra + property bool showEdit + signal tap +} diff --git a/src/FluentUI/Controls/FluPaneItemEmpty.qml b/src/FluentUI/Controls/FluPaneItemEmpty.qml new file mode 100644 index 00000000..0f12e384 --- /dev/null +++ b/src/FluentUI/Controls/FluPaneItemEmpty.qml @@ -0,0 +1,11 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property var _ext + property var _parent + property bool visible: true +} diff --git a/src/FluentUI/Controls/FluPaneItemExpander.qml b/src/FluentUI/Controls/FluPaneItemExpander.qml new file mode 100644 index 00000000..93c2e648 --- /dev/null +++ b/src/FluentUI/Controls/FluPaneItemExpander.qml @@ -0,0 +1,18 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +FluObject { + readonly property string key : FluTools.uuid() + property int _idx + property bool visible: true + property string title + property var icon + property bool disabled: false + property bool iconVisible: true + property bool isExpand: false + property bool showEdit + property Component iconDelegate + property Component menuDelegate + property Component editDelegate +} diff --git a/src/FluentUI/Controls/FluPaneItemHeader.qml b/src/FluentUI/Controls/FluPaneItemHeader.qml new file mode 100644 index 00000000..6918097f --- /dev/null +++ b/src/FluentUI/Controls/FluPaneItemHeader.qml @@ -0,0 +1,11 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property bool visible: true + property string title + property var parent +} diff --git a/src/FluentUI/Controls/FluPaneItemSeparator.qml b/src/FluentUI/Controls/FluPaneItemSeparator.qml new file mode 100644 index 00000000..23433b68 --- /dev/null +++ b/src/FluentUI/Controls/FluPaneItemSeparator.qml @@ -0,0 +1,12 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +QtObject { + readonly property string key : FluTools.uuid() + property int _idx + property bool visible: true + property var parent + property real spacing + property int size:1 +} diff --git a/src/FluentUI/Controls/FluPasswordBox.qml b/src/FluentUI/Controls/FluPasswordBox.qml new file mode 100644 index 00000000..e493a95c --- /dev/null +++ b/src/FluentUI/Controls/FluPasswordBox.qml @@ -0,0 +1,73 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +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: 7 + rightPadding: 40 + leftPadding: padding+4 + echoMode:btn_reveal.pressed ? TextField.Normal : TextField.Password + renderType: FluTheme.nativeText ? Text.NativeRendering : Text.QtRendering + selectionColor: FluTools.colorAlpha(FluTheme.primaryColor,0.5) + selectedTextColor: color + placeholderTextColor: { + if(!enabled){ + return placeholderDisableColor + } + if(focus){ + return placeholderFocusColor + } + return placeholderNormalColor + } + selectByMouse: true + width: 240 + background: FluTextBoxBackground{ + inputItem: control + } + 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: 30 + height: 20 + verticalPadding: 0 + horizontalPadding: 0 + iconColor: FluTheme.dark ? Qt.rgba(222/255,222/255,222/255,1) : Qt.rgba(97/255,97/255,97/255,1) + visible: control.text !== "" + anchors{ + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: 5 + } + } + FluTextBoxMenu{ + id:menu + inputItem: control + } +} diff --git a/src/FluentUI/Controls/FluPivot.qml b/src/FluentUI/Controls/FluPivot.qml new file mode 100644 index 00000000..df0374ca --- /dev/null +++ b/src/FluentUI/Controls/FluPivot.qml @@ -0,0 +1,95 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +Page { + default property alias content: d.children + property alias currentIndex: nav_list.currentIndex + property color textNormalColor: FluTheme.dark ? FluColors.Grey120 : FluColors.Grey120 + property color textHoverColor: FluTheme.dark ? FluColors.Grey10 : FluColors.Black + property int textSize: 28 + property bool textBold: true + property int textSpacing: 10 + property int headerSpacing: 20 + property int headerHeight: 40 + id:control + width: 400 + height: 300 + implicitHeight: height + implicitWidth: width + FluObject{ + id:d + property int tabY: control.headerHeight/2+control.textSize/2 + 3 + } + background:Item{} + header:ListView{ + id:nav_list + implicitHeight: control.headerHeight + implicitWidth: control.width + model:d.children + spacing: control.headerSpacing + interactive: false + orientation: ListView.Horizontal + highlightMoveDuration: FluTheme.enableAnimation ? 167 : 0 + highlight: Item{ + clip: true + Rectangle{ + height: 3 + radius: 1.5 + color: FluTheme.primaryColor + width: nav_list.currentItem ? nav_list.currentItem.width : 0 + y:d.tabY + 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 + focusPolicy:Qt.TabFocus + background:Item{ + FluFocusRectangle{ + anchors.margins: -4 + visible: item_button.activeFocus + radius:4 + } + } + contentItem: Item{ + FluText { + id:item_title + text: modelData.title + anchors.centerIn: parent + font.pixelSize: control.textSize + font.bold: control.textBold + color: { + if(item_button.hovered || nav_list.currentIndex === index) + return textHoverColor + return textNormalColor + } + } + } + onClicked: { + nav_list.currentIndex = index + } + } + } + Item{ + id:container + anchors.fill: parent + Repeater{ + model:d.children + FluLoader{ + property var argument: modelData.argument + anchors.fill: parent + sourceComponent: modelData.contentItem + visible: nav_list.currentIndex === index + } + } + } +} diff --git a/src/FluentUI/Controls/FluPivotItem.qml b/src/FluentUI/Controls/FluPivotItem.qml new file mode 100644 index 00000000..b241dc44 --- /dev/null +++ b/src/FluentUI/Controls/FluPivotItem.qml @@ -0,0 +1,9 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +QtObject { + property string title + property Component contentItem + property var argument +} diff --git a/src/FluentUI/Controls/FluPopup.qml b/src/FluentUI/Controls/FluPopup.qml new file mode 100644 index 00000000..78d9d5bb --- /dev/null +++ b/src/FluentUI/Controls/FluPopup.qml @@ -0,0 +1,54 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Window +import FluentUI + +Popup { + id: control + padding: 0 + modal:true + parent: Overlay.overlay + x: Math.round((d.parentWidth - width) / 2) + y: Math.round((d.parentHeight - height) / 2) + closePolicy: Popup.CloseOnEscape + enter: Transition { + NumberAnimation { + property: "opacity" + duration: FluTheme.enableAnimation ? 83 : 0 + from:0 + to:1 + } + } + height:Math.min(implicitHeight,d.parentHeight) + exit:Transition { + 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) + FluShadow{ + radius: 5 + } + } + QtObject{ + id:d + property int parentHeight: { + if(control.parent){ + return control.parent.height + } + return control.height + } + property int parentWidth: { + if(control.parent){ + return control.parent.width + } + return control.width + } + } +} diff --git a/src/FluentUI/Controls/FluProgressBar.qml b/src/FluentUI/Controls/FluProgressBar.qml new file mode 100644 index 00000000..bca37cea --- /dev/null +++ b/src/FluentUI/Controls/FluProgressBar.qml @@ -0,0 +1,69 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +ProgressBar{ + property int duration: 888 + property real strokeWidth: 6 + property bool progressVisible: false + property color color: FluTheme.primaryColor + 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 + } + onIndeterminateChanged:{ + if(!indeterminate){ + animator_x.duration = 0 + rect_progress.x = 0 + animator_x.duration = control.duration + } + } + background: Rectangle { + implicitWidth: 150 + implicitHeight: control.strokeWidth + color: control.backgroundColor + radius: d._radius + } + contentItem: FluClip { + 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 { + id:animator_x + running: control.indeterminate && control.visible + from: -rect_progress.width + to:control.width+rect_progress.width + loops: Animation.Infinite + duration: control.duration + } + } + } + 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/FluentUI/Controls/FluProgressButton.qml b/src/FluentUI/Controls/FluProgressButton.qml new file mode 100644 index 00000000..1c21c78e --- /dev/null +++ b/src/FluentUI/Controls/FluProgressButton.qml @@ -0,0 +1,136 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +Button { + property real progress + property bool disabled: false + property string contentDescription: "" + QtObject{ + id:d + property bool checked: (rect_back.height === background.height) && (progress === 1) + } + property color normalColor: { + if(d.checked){ + return FluTheme.primaryColor + }else{ + return FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) + } + } + property color hoverColor: { + if(d.checked){ + return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1) + }else{ + return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1) + } + } + property color disableColor: { + if(d.checked){ + return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) + }else{ + return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1) + } + } + property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.2) : Qt.lighter(normalColor,1.2) + Accessible.role: Accessible.Button + Accessible.name: control.text + Accessible.description: contentDescription + Accessible.onPressAction: control.clicked() + focusPolicy:Qt.TabFocus + id: control + enabled: !disabled + verticalPadding: 0 + horizontalPadding:12 + background: FluClip{ + implicitWidth: 28 + implicitHeight: 28 + radius: [4,4,4,4] + Rectangle{ + anchors.fill: parent + border.color: FluTheme.dark ? "#505050" : "#DFDFDF" + border.width: d.checked ? 0 : 1 + radius: 4 + color:{ + if(!enabled){ + return disableColor + } + if(d.checked){ + if(pressed){ + return pressedColor + } + } + return hovered ? hoverColor :normalColor + } + } + Rectangle{ + id:rect_back + width: parent.width * control.progress + height: control.progress === 1 ? background.height : 3 + visible: !d.checked + color: FluTheme.primaryColor + anchors.bottom: parent.bottom + Behavior on height{ + enabled: control.progress !== 0 + SequentialAnimation { + PauseAnimation { + duration: FluTheme.enableAnimation ? 167 : 0 + } + NumberAnimation{ + duration: FluTheme.enableAnimation ? 167 : 0 + from: 3 + to: background.height + } + } + } + Behavior on width{ + NumberAnimation{ + duration: 167 + } + } + } + FluFocusRectangle{ + visible: control.activeFocus + radius:4 + } + } + contentItem: FluText { + text: control.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: { + if(d.checked){ + 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) + } + }else{ + if(FluTheme.dark){ + if(!enabled){ + return Qt.rgba(131/255,131/255,131/255,1) + } + if(!d.checked){ + 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(!d.checked){ + if(pressed){ + return Qt.rgba(96/255,96/255,96/255,1) + } + } + return Qt.rgba(0,0,0,1) + } + } + } + } +} diff --git a/src/FluentUI/Controls/FluProgressRing.qml b/src/FluentUI/Controls/FluProgressRing.qml new file mode 100644 index 00000000..480aee9d --- /dev/null +++ b/src/FluentUI/Controls/FluProgressRing.qml @@ -0,0 +1,93 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +ProgressBar{ + property int duration: 2000 + property real strokeWidth: 6 + property bool progressVisible: false + property color color: FluTheme.primaryColor + 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 + } + onIndeterminateChanged:{ + canvas.requestPaint() + } + QtObject{ + id:d + property real _radius: control.width/2-control.strokeWidth/2 + property real _progress: control.indeterminate ? 0.0 : control.visualPosition + on_ProgressChanged: { + canvas.requestPaint() + } + } + Connections{ + target: FluTheme + function onDarkChanged(){ + canvas.requestPaint() + } + } + contentItem: Item { + id:layout_item + Canvas { + id:canvas + anchors.fill: parent + antialiasing: true + renderTarget: Canvas.Image + property real startAngle: 0 + property real sweepAngle: 0 + SequentialAnimation on startAngle { + loops: Animation.Infinite + running: control.visible && control.indeterminate + PropertyAnimation { from: 0; to: 450; duration: control.duration/2 } + PropertyAnimation { from: 450; to: 1080; duration: control.duration/2 } + } + SequentialAnimation on sweepAngle { + loops: Animation.Infinite + running: control.visible && control.indeterminate + PropertyAnimation { from: 0; to: 180; duration: control.duration/2 } + PropertyAnimation { from: 180; to: 0; duration: control.duration/2 } + } + onStartAngleChanged: { + requestPaint() + } + 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.lineCap = "round" + ctx.beginPath() + if(control.indeterminate){ + ctx.arc(width/2, height/2, d._radius , Math.PI * (startAngle - 90) / 180, Math.PI * (startAngle - 90 + sweepAngle) / 180) + }else{ + 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/FluentUI/Controls/FluQRCode.qml b/src/FluentUI/Controls/FluQRCode.qml new file mode 100644 index 00000000..9a6428b4 --- /dev/null +++ b/src/FluentUI/Controls/FluQRCode.qml @@ -0,0 +1,23 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +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 + } + FluQrCodeItem{ + id:qrcode + size:control.size-margins + anchors.centerIn: parent + } +} diff --git a/src/FluentUI/Controls/FluRadioButton.qml b/src/FluentUI/Controls/FluRadioButton.qml new file mode 100644 index 00000000..ac67b5ee --- /dev/null +++ b/src/FluentUI/Controls/FluRadioButton.qml @@ -0,0 +1,94 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import QtQuick.Layouts +import FluentUI + +Button { + property string contentDescription: "" + property bool disabled: false + property color borderNormalColor: checked ? FluTheme.primaryColor : 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() + 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/FluentUI/Controls/FluRadioButtons.qml b/src/FluentUI/Controls/FluRadioButtons.qml new file mode 100644 index 00000000..eb8c817d --- /dev/null +++ b/src/FluentUI/Controls/FluRadioButtons.qml @@ -0,0 +1,33 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import QtQuick.Layouts +import FluentUI + +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/FluentUI/Controls/FluRemoteLoader.qml b/src/FluentUI/Controls/FluRemoteLoader.qml new file mode 100644 index 00000000..13c7142d --- /dev/null +++ b/src/FluentUI/Controls/FluRemoteLoader.qml @@ -0,0 +1,39 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +FluStatusLayout { + property url source: "" + property bool lazy: false + color:"transparent" + id:control + onErrorClicked: { + reload() + } + Component.onCompleted: { + if(!lazy){ + loader.source = control.source + } + } + FluLoader{ + id:loader + anchors.fill: parent + asynchronous: true + onStatusChanged: { + if(status === Loader.Error){ + control.statusMode = FluStatusLayoutType.Error + }else if(status === Loader.Loading){ + control.statusMode = FluStatusLayoutType.Loading + }else{ + control.statusMode = FluStatusLayoutType.Success + } + } + } + function reload(){ + var timestamp = Date.now(); + loader.source = control.source+"?"+timestamp + } + function itemLodaer(){ + return loader + } +} diff --git a/src/FluentUI/Controls/FluScrollBar.qml b/src/FluentUI/Controls/FluScrollBar.qml new file mode 100644 index 00000000..0d66e6a8 --- /dev/null +++ b/src/FluentUI/Controls/FluScrollBar.qml @@ -0,0 +1,187 @@ +import QtQuick +import QtQuick.Controls.impl +import QtQuick.Templates as T +import FluentUI + +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) + + visible: control.policy !== T.ScrollBar.AlwaysOff + minimumSize: Math.max(orientation === Qt.Horizontal ? height / width : width / height,0.3) + QtObject{ + id:d + property int minLine : 2 + property int maxLine : 6 + } + z: horizontal? 10 : 20 + verticalPadding : vertical ? 15 : 3 + horizontalPadding : horizontal ? 15 : 3 + background: Rectangle{ + id:back_rect + radius: 5 + color:FluTheme.dark ? Qt.rgba(44/255,44/255,44/255,1) : Qt.rgba(255/255,255/255,255/255,1) + opacity:{ + if(vertical){ + return d.maxLine === Number(rect_bar.width) + } + return d.maxLine === Number(rect_bar.height) + } + Behavior on opacity { + NumberAnimation{ + duration: 50 + } + } + } + FluIconButton{ + width: 12 + height: 12 + iconSize: 8 + verticalPadding: 0 + horizontalPadding: 0 + visible: control.horizontal + opacity: back_rect.opacity + anchors{ + left: parent.left + leftMargin: 2 + verticalCenter: parent.verticalCenter + } + iconColor: control.color + iconSource: FluentIcons.CaretLeftSolid8 + onClicked: { + control.decrease() + } + } + FluIconButton{ + width: 12 + height: 12 + iconSize: 8 + verticalPadding: 0 + horizontalPadding: 0 + iconColor: control.color + opacity: back_rect.opacity + anchors{ + right: parent.right + rightMargin: 2 + verticalCenter: parent.verticalCenter + } + visible: control.horizontal + iconSource: FluentIcons.CaretRightSolid8 + onClicked: { + control.increase() + } + } + FluIconButton{ + width: 12 + height: 12 + iconSize: 8 + verticalPadding: 0 + horizontalPadding: 0 + iconColor: control.color + opacity: back_rect.opacity + anchors{ + top: parent.top + topMargin: 2 + horizontalCenter: parent.horizontalCenter + } + visible: control.vertical + iconSource: FluentIcons.CaretUpSolid8 + onClicked: { + control.decrease() + } + } + FluIconButton{ + width: 12 + height: 12 + iconSize: 8 + verticalPadding: 0 + horizontalPadding: 0 + iconColor: control.color + opacity: back_rect.opacity + anchors{ + bottom: parent.bottom + bottomMargin: 2 + horizontalCenter: parent.horizontalCenter + } + visible: control.vertical + iconSource: FluentIcons.CaretDownSolid8 + onClicked: { + control.increase() + } + } + contentItem: Item { + property bool collapsed: (control.policy === T.ScrollBar.AlwaysOn || (control.active && control.size < 1.0)) + implicitWidth: control.interactive ? d.maxLine : d.minLine + implicitHeight: control.interactive ? d.maxLine : d.minLine + Rectangle{ + id:rect_bar + width: vertical ? d.minLine : parent.width + height: horizontal ? d.minLine : 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 ? d.maxLine : parent.width + height: horizontal ? d.maxLine : parent.height + } + } + ,State{ + name:"hide" + when: !contentItem.collapsed + PropertyChanges { + target: rect_bar + width: vertical ? d.minLine : parent.width + height: horizontal ? d.minLine : 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" + SequentialAnimation { + PauseAnimation { duration: 450 } + NumberAnimation { + target: rect_bar + properties: vertical ? "width" : "height" + duration: 167 + easing.type: Easing.OutCubic + } + } + } + ] + } +} diff --git a/src/FluentUI/Controls/FluScrollIndicator.qml b/src/FluentUI/Controls/FluScrollIndicator.qml new file mode 100644 index 00000000..3e4b1685 --- /dev/null +++ b/src/FluentUI/Controls/FluScrollIndicator.qml @@ -0,0 +1,49 @@ +import QtQuick +import QtQuick.Controls.impl +import QtQuick.Templates 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/FluentUI/Controls/FluScrollablePage.qml b/src/FluentUI/Controls/FluScrollablePage.qml new file mode 100644 index 00000000..6aafc0c9 --- /dev/null +++ b/src/FluentUI/Controls/FluScrollablePage.qml @@ -0,0 +1,79 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Window +import QtQuick.Controls +import FluentUI + +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 + } + } + FluStatusLayout{ + id:status_view + color: "#00000000" + statusMode: FluStatusLayoutType.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/FluentUI/Controls/FluShadow.qml b/src/FluentUI/Controls/FluShadow.qml new file mode 100644 index 00000000..af236e1e --- /dev/null +++ b/src/FluentUI/Controls/FluShadow.qml @@ -0,0 +1,24 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +Item { + //高性能阴影!!!比DropShadow阴影性能高出数倍!!! + property color color: FluTheme.dark ? "#FFFFFF" : "#999999" + property int elevation: 6 + property int radius: 4 + id:control + anchors.fill: parent + Repeater{ + model: elevation + Rectangle{ + anchors.fill: parent + color: "#00000000" + opacity: 0.01 * (elevation-index+1) + anchors.margins: -index + radius: control.radius+index + border.width: index + border.color: control.color + } + } +} diff --git a/src/FluentUI/Controls/FluShortcutPicker.qml b/src/FluentUI/Controls/FluShortcutPicker.qml new file mode 100644 index 00000000..f3a592b8 --- /dev/null +++ b/src/FluentUI/Controls/FluShortcutPicker.qml @@ -0,0 +1,235 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +FluIconButton { + id:control + property var current : ["Ctrl","Shift","A"] + property string title: qsTr("Activate the Shortcut") + property string message: qsTr("Press the key combination to change the shortcut") + property string positiveText: qsTr("Save") + property string neutralText: qsTr("Cancel") + property string negativeText: qsTr("Reset") + signal accepted() + QtObject{ + id: d + function keyToString(key_code,shift = true) + { + switch(key_code) + { + case Qt.Key_Period: return "."; + case Qt.Key_Greater: return shift ? ">" : "."; + case Qt.Key_Comma: return ","; + case Qt.Key_Less: return shift ? "<" : ","; + case Qt.Key_Slash: return "/"; + case Qt.Key_Question: return shift ? "?" : "/"; + case Qt.Key_Semicolon: return ";"; + case Qt.Key_Colon: return shift ? ":" : ";"; + case Qt.Key_Apostrophe: return "'"; + case Qt.Key_QuoteDbl: return shift ? "'" : "\""; + case Qt.Key_QuoteLeft: return "`"; + case Qt.Key_AsciiTilde: return shift ? "~" : "`"; + case Qt.Key_Minus: return "-"; + case Qt.Key_Underscore: return shift ? "_" : "-"; + case Qt.Key_Equal: return "="; + case Qt.Key_Plus: return shift ? "+" : "="; + case Qt.Key_BracketLeft: return "["; + case Qt.Key_BraceLeft: return shift ? "{" : "["; + case Qt.Key_BracketRight: return "]"; + case Qt.Key_BraceRight: return shift ? "}" : "]"; + case Qt.Key_Backslash: return "\\"; + case Qt.Key_Bar: return shift ? "|" : "\\"; + case Qt.Key_Up: return "Up"; + case Qt.Key_Down: return "Down"; + case Qt.Key_Right: return "Right"; + case Qt.Key_Left: return "Left"; + case Qt.Key_Space: return "Space"; + case Qt.Key_PageDown: return "PgDown"; + case Qt.Key_PageUp: return "PgUp"; + case Qt.Key_0: return "0"; + case Qt.Key_1: return "1"; + case Qt.Key_2: return "2"; + case Qt.Key_3: return "3"; + case Qt.Key_4: return "4"; + case Qt.Key_5: return "5"; + case Qt.Key_6: return "6"; + case Qt.Key_7: return "7"; + case Qt.Key_8: return "8"; + case Qt.Key_9: return "9"; + case Qt.Key_Exclam: return shift ? "!" : "1"; + case Qt.Key_At: return shift ? "@" : "2"; + case Qt.Key_NumberSign: return shift ? "#" : "3"; + case Qt.Key_Dollar: return shift ? "$" : "4"; + case Qt.Key_Percent: return shift ? "%" : "5"; + case Qt.Key_AsciiCircum: return shift ? "^" : "6"; + case Qt.Key_Ampersand: return shift ? "&" : "7"; + case Qt.Key_Asterisk: return shift ? "*" : "8"; + case Qt.Key_ParenLeft: return shift ? "(" : "9"; + case Qt.Key_ParenRight: return shift ? ")" : "0"; + case Qt.Key_A: return "A"; + case Qt.Key_B: return "B"; + case Qt.Key_C: return "C"; + case Qt.Key_D: return "D"; + case Qt.Key_E: return "E"; + case Qt.Key_F: return "F"; + case Qt.Key_G: return "G"; + case Qt.Key_H: return "H"; + case Qt.Key_I: return "I"; + case Qt.Key_J: return "J"; + case Qt.Key_K: return "K"; + case Qt.Key_L: return "L"; + case Qt.Key_M: return "M"; + case Qt.Key_N: return "N"; + case Qt.Key_O: return "O"; + case Qt.Key_P: return "P"; + case Qt.Key_Q: return "Q"; + case Qt.Key_R: return "R"; + case Qt.Key_S: return "S"; + case Qt.Key_T: return "T"; + case Qt.Key_U: return "U"; + case Qt.Key_V: return "V"; + case Qt.Key_W: return "W"; + case Qt.Key_X: return "X"; + case Qt.Key_Y: return "Y"; + case Qt.Key_Z: return "Z"; + case Qt.Key_F1: return "F1"; + case Qt.Key_F2: return "F2"; + case Qt.Key_F3: return "F3"; + case Qt.Key_F4: return "F4"; + case Qt.Key_F5: return "F5"; + case Qt.Key_F6: return "F6"; + case Qt.Key_F7: return "F7"; + case Qt.Key_F8: return "F8"; + case Qt.Key_F9: return "F9"; + case Qt.Key_F10: return "F10"; + case Qt.Key_F11: return "F11"; + case Qt.Key_F12: return "F12"; + case Qt.Key_Home: return "Home"; + case Qt.Key_End: return "End"; + case Qt.Key_Insert: return "Insert"; + case Qt.Key_Delete: return "Delete"; + } + return ""; + } + } + background: Rectangle{ + border.color: FluTheme.dark ? "#505050" : "#DFDFDF" + border.width: 1 + implicitHeight: 42 + implicitWidth: layout_row.width+28 + radius: control.radius + color:control.color + FluFocusRectangle{ + visible: control.activeFocus + } + } + Component{ + id:com_item_key + Rectangle{ + id:item_key_control + color:FluTheme.primaryColor + width: Math.max(item_text.implicitWidth+12,28) + height: Math.max(item_text.implicitHeight,28) + radius: 4 + Text{ + id:item_text + color: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1) + font.pixelSize: 13 + text: keyText + anchors.centerIn: parent + } + } + } + Row{ + id:layout_row + spacing: 5 + anchors.centerIn: parent + Repeater{ + model: control.current + delegate: Loader{ + property var keyText: modelData + sourceComponent: com_item_key + } + } + Item{ + width: 3 + height: 1 + } + FluIcon{ + iconSource: FluentIcons.EditMirrored + iconSize: 13 + anchors{ + verticalCenter: parent.verticalCenter + } + } + } + FluContentDialog{ + id:content_dialog + property var keysModel: [] + title: control.title + message: control.message + buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton | FluContentDialogType.NeutralButton + positiveText: control.positiveText + neutralText: control.neutralText + negativeText: control.negativeText + onVisibleChanged: { + if(visible){ + content_dialog.keysModel = control.current + } + } + onPositiveClicked: { + control.current = content_dialog.keysModel + control.accepted() + } + onNegativeClickListener: function(){ + content_dialog.keysModel = control.current + } + contentDelegate: Component{ + Item{ + implicitWidth: parent.width + implicitHeight: 100 + Component.onCompleted: { + forceActiveFocus() + } + Keys.enabled: true + Keys.onPressed: + (event)=>{ + var keyNames = [] + if (event.modifiers & Qt.AltModifier) { + keyNames.push("Alt") + } + if (event.modifiers & Qt.ControlModifier) { + keyNames.push("Ctrl") + } + if (event.modifiers & Qt.ShiftModifier) { + keyNames.push("Shift") + } + var keyName = d.keyToString(event.key,false) + if(keyName!==""){ + keyNames.push(keyName) + content_dialog.keysModel = keyNames + } + event.accepted = true + } + Keys.onTabPressed: + (event)=>{ + event.accepted = true + } + Row{ + spacing: 5 + anchors.centerIn: parent + Repeater{ + model: content_dialog.keysModel + delegate: Loader{ + property var keyText: modelData + sourceComponent: com_item_key + } + } + } + } + } + } + onClicked: { + content_dialog.open() + } +} diff --git a/src/FluentUI/Controls/FluSlider.qml b/src/FluentUI/Controls/FluSlider.qml new file mode 100644 index 00000000..7b0be429 --- /dev/null +++ b/src/FluentUI/Controls/FluSlider.qml @@ -0,0 +1,75 @@ +import QtQuick +import QtQuick.Controls.impl +import QtQuick.Templates as T +import FluentUI + +T.Slider { + property bool tooltipEnabled: true + property string text: String(control.value) + 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: 20 + implicitHeight: 20 + radius: 10 + color:FluTheme.dark ? Qt.rgba(69/255,69/255,69/255,1) :Qt.rgba(1,1,1,1) + FluShadow{ + radius: 10 + } + FluIcon{ + width: 10 + height: 10 + Behavior on scale{ + NumberAnimation{ + duration: 167 + easing.type: Easing.OutCubic + } + } + iconSource: FluentIcons.FullCircleMask + iconSize: 10 + scale:{ + if(control.pressed){ + return 0.9 + } + return control.hovered ? 1.2 : 1 + } + iconColor: FluTheme.primaryColor + anchors.centerIn: parent + } + } + 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.primaryColor + } + } + FluTooltip{ + parent: control.handle + visible: control.tooltipEnabled && (control.pressed || control.hovered) + text:control.text + } +} diff --git a/src/FluentUI/Controls/FluSpinBox.qml b/src/FluentUI/Controls/FluSpinBox.qml new file mode 100644 index 00000000..c3265efa --- /dev/null +++ b/src/FluentUI/Controls/FluSpinBox.qml @@ -0,0 +1,160 @@ +import QtQuick +import QtQuick.Controls.impl +import QtQuick.Templates as T +import FluentUI + +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,0.5) + selectedTextColor: color + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + readOnly: !control.editable + validator: control.validator + inputMethodHints: control.inputMethodHints + Rectangle{ + width: parent.width + height: contentItem.activeFocus ? 2 : 1 + anchors.bottom: parent.bottom + visible: contentItem.enabled + color: { + if(contentItem.activeFocus){ + return FluTheme.primaryColor + } + if(FluTheme.dark){ + return Qt.rgba(166/255,166/255,166/255,1) + }else{ + return Qt.rgba(183/255,183/255,183/255,1) + } + } + Behavior on height{ + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 83 + easing.type: Easing.OutCubic + } + } + } + } + + up.indicator: FluClip { + 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: FluClip { + 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/FluentUI/Controls/FluSplitLayout.qml b/src/FluentUI/Controls/FluSplitLayout.qml new file mode 100644 index 00000000..f13673a8 --- /dev/null +++ b/src/FluentUI/Controls/FluSplitLayout.qml @@ -0,0 +1,30 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +SplitView { + property color handleColor : FluTheme.dark ? Qt.rgba(159/255,159/255,159/255,1) : Qt.rgba(138/255,138/255,138/255,1) + id:control + QtObject{ + id:d + property bool isVertical: control.orientation === Qt.Vertical + } + handle: Rectangle { + implicitWidth: d.isVertical ? control.width : 12 + implicitHeight: d.isVertical ? 12 : control.height + clip: true + color: { + if(SplitHandle.pressed){ + return FluTheme.itemPressColor + } + return SplitHandle.hovered ? FluTheme.itemHoverColor : FluTheme.itemNormalColor + } + Rectangle{ + width: d.isVertical ? 26 : 4 + height: d.isVertical ? 4 : 26 + anchors.centerIn: parent + color: control.handleColor + radius: 2 + } + } +} diff --git a/src/FluentUI/Controls/FluStaggeredLayout.qml b/src/FluentUI/Controls/FluStaggeredLayout.qml new file mode 100644 index 00000000..9f0da327 --- /dev/null +++ b/src/FluentUI/Controls/FluStaggeredLayout.qml @@ -0,0 +1,68 @@ +import QtQuick + +Item { + property int itemWidth : 200 + property alias model: rep.model + property alias delegate: rep.delegate + property int rowSpacing: 8 + property int colSpacing: 8 + id: control + QtObject{ + id:d + property int cellWidth : itemWidth+rowSpacing + property int colCount: { + var cols = parseInt(control.width/cellWidth) + return cols>0?cols:1 + } + property var colsHeightArr: [] + property int maxHeight: 0 + property var itemsInRep: [] + onMaxHeightChanged: { + control.implicitHeight = maxHeight + } + onColCountChanged: { + refresh() + } + function refresh(){ + d.colsHeightArr = [] + var count = itemsInRep.length + for(var i=0; i { + d.addToFall(index, item) + d.itemsInRep.push(item) + } + } + function clear(){ + d.maxHeight = 0 + d.colsHeightArr = [] + d.itemsInRep = [] + model.clear() + } +} diff --git a/src/FluentUI/Controls/FluStatusLayout.qml b/src/FluentUI/Controls/FluStatusLayout.qml new file mode 100644 index 00000000..ab82ba21 --- /dev/null +++ b/src/FluentUI/Controls/FluStatusLayout.qml @@ -0,0 +1,116 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +Item{ + id:control + default property alias content: container.data + property int statusMode: FluStatusLayoutType.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===FluStatusLayoutType.Success + } + FluLoader{ + id:loader + anchors.fill: parent + visible: statusMode!==FluStatusLayoutType.Success + sourceComponent: { + if(statusMode === FluStatusLayoutType.Loading){ + return loadingItem + } + if(statusMode === FluStatusLayoutType.Empty){ + return emptyItem + } + if(statusMode === FluStatusLayoutType.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 = FluStatusLayoutType.Success + } + function showLoadingView(){ + statusMode = FluStatusLayoutType.Loading + } + function showEmptyView(){ + statusMode = FluStatusLayoutType.Empty + } + function showErrorView(){ + statusMode = FluStatusLayoutType.Error + } +} diff --git a/src/FluentUI/Controls/FluTabView.qml b/src/FluentUI/Controls/FluTabView.qml new file mode 100644 index 00000000..dab42f31 --- /dev/null +++ b/src/FluentUI/Controls/FluTabView.qml @@ -0,0 +1,299 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +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 + Item{ + 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) + } + 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) + if(idx<0){ + return + } + if(idx>=tab_nav.count){ + return + } + if (d.dragIndex !== idx) { + tab_model.move(d.dragIndex, idx, 1) + d.dragIndex = idx; + } + } + } + FluRectangle{ + anchors.fill: parent + radius: [6,6,0,0] + color: { + if(item_mouse_hove.containsMouse || item_btn_close.hovered){ + return FluTheme.itemHoverColor + } + if(tab_nav.currentIndex === index){ + return FluTheme.itemCheckColor + } + return FluTheme.itemNormalColor + } + } + 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.Never) + 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 + orientation: Qt.Vertical + 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 + FluLoader{ + 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/FluentUI/Controls/FluTableView.qml b/src/FluentUI/Controls/FluTableView.qml new file mode 100644 index 00000000..2acda1f5 --- /dev/null +++ b/src/FluentUI/Controls/FluTableView.qml @@ -0,0 +1,849 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import QtQuick.Layouts +import Qt.labs.qmlmodels +import FluentUI + +Rectangle { + property var columnSource + property var dataSource + property color borderColor: FluTheme.dark ? "#252525" : "#e4e4e4" + property alias rows: table_view.rows + property alias columns: table_view.columns + property bool horizonalHeaderVisible: true + property bool verticalHeaderVisible: true + property color selectedBorderColor: FluTheme.primaryColor + property color selectedColor: FluTools.colorAlpha(FluTheme.primaryColor,0.3) + property alias sourceModel: table_model + 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 columns= [] + var columnsData = [] + var headerRow = {} + columnSource.forEach(function(item){ + var column = Qt.createQmlObject('import Qt.labs.qmlmodels 1.0;TableModelColumn{}',table_model); + column.display = item.dataIndex + columnsData.push(item) + columns.push(column) + headerRow[item.dataIndex] = item.title + }) + d.columns_data = columnsData + table_model.columns = columns + header_column_model.columns = columns + header_column_model.rows = [headerRow] + } + } + QtObject{ + id:d + property var current + property int rowHoverIndex: -1 + property int defaultItemWidth: 100 + property int defaultItemHeight: 42 + property var columns_data: [] + property var editDelegate + property var editPosition + function getEditDelegate(column){ + var obj =d.columns_data[column].editDelegate + if(obj){ + return obj + } + if(d.columns_data[column].editMultiline === true){ + return com_edit_multiline + } + return com_edit + } + } + onDataSourceChanged: { + table_model.clear() + table_model.rows = dataSource + } + TableModel { + id:table_model + TableModelColumn {} + } + TableModel{ + id:header_column_model + TableModelColumn {} + } + TableModel{ + id:header_row_model + TableModelColumn { display: "rowIndex" } + } + FluTableSortProxyModel{ + id:table_sort_model + model: table_model + } + Component{ + id:com_edit + FluTextBox{ + id:text_box + text: String(display) + readOnly: true === d.columns_data[column].readOnly + Component.onCompleted: { + forceActiveFocus() + selectAll() + } + onCommit: { + if(!readOnly){ + editTextChaged(text_box.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 === d.columns_data[column].readOnly + verticalAlignment: TextInput.AlignVCenter + Component.onCompleted: { + forceActiveFocus() + selectAll() + } + rightPadding: 24 + onCommit: { + if(!readOnly){ + editTextChaged(text_box.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: String(display) + elide: Text.ElideRight + wrapMode: Text.WrapAnywhere + anchors{ + fill: parent + leftMargin: 11 + rightMargin: 11 + topMargin: 6 + bottomMargin: 6 + } + verticalAlignment: Text.AlignVCenter + MouseArea{ + acceptedButtons: Qt.NoButton + id: hover_handler + hoverEnabled: true + anchors.fill: parent + } + FluTooltip{ + text: item_text.text + delay: 500 + visible: item_text.contentWidth < item_text.implicitWidth && item_text.contentHeight < item_text.implicitHeight && hover_handler.containsMouse + } + } + } + Component{ + id:com_table_delegate + MouseArea{ + id:item_table_mouse + property var rowObject : control.getRow(row) + property var itemModel: model + property bool editVisible: { + if(d.editPosition === undefined){ + return false + } + if(d.editPosition._key === rowObject._key && d.editPosition.column === column){ + return true + } + return false + } + hoverEnabled: true + onEntered: { + d.rowHoverIndex = row + } + onWidthChanged: { + if(editVisible){ + updateEditPosition() + } + } + onHeightChanged: { + if(editVisible){ + updateEditPosition() + } + } + onXChanged: { + if(editVisible){ + updateEditPosition() + } + } + onYChanged: { + if(editVisible){ + updateEditPosition() + } + } + function updateEditPosition(){ + var obj = {} + obj._key = rowObject._key + obj.column = column + obj.row = row + obj.x = item_table_mouse.x + obj.y = item_table_mouse.y + 1 + obj.width = item_table_mouse.width + obj.height = item_table_mouse.height - 2 + d.editPosition = obj + } + Rectangle{ + id:item_table + anchors.fill: parent + property point position: Qt.point(column,row) + property bool isRowSelected: { + if(rowObject === null) + return false + if(d.current){ + return rowObject._key === d.current._key + } + return false + } + color:{ + if(item_table.isRowSelected){ + return control.selectedColor + } + if(d.rowHoverIndex === row || item_table.isRowSelected){ + return FluTheme.dark ? Qt.rgba(1,1,1,0.06) : Qt.rgba(0,0,0,0.06) + } + return (row%2!==0) ? control.color : (FluTheme.dark ? Qt.rgba(1,1,1,0.015) : Qt.rgba(0,0,0,0.015)) + } + MouseArea{ + anchors.fill: parent + acceptedButtons: Qt.LeftButton + onPressed:{ + closeEditor() + } + onCanceled: { + } + onReleased: { + } + onDoubleClicked:{ + if(typeof(display) == "object"){ + return + } + d.editDelegate = d.getEditDelegate(column) + updateEditPosition() + loader_edit.display = display + } + onClicked: + (event)=>{ + d.current = rowObject + closeEditor() + event.accepted = true + } + } + FluLoader{ + property var model: itemModel + property var display: itemModel.display + property int row: item_table.position.y + property int column: item_table.position.x + property bool isObject: typeof(display) == "object" + property var options: { + if(isObject){ + return display.options + } + return {} + } + anchors.fill: parent + sourceComponent: { + if(isObject){ + return display.comId + } + return com_text + } + } + Item{ + anchors.fill: parent + visible: item_table.isRowSelected + Rectangle{ + width: 1 + height: parent.height + anchors.left: parent.left + color: control.selectedBorderColor + visible: column === 0 + } + Rectangle{ + width: 1 + height: parent.height + anchors.right: parent.right + color: control.selectedBorderColor + visible: column === control.columns-1 + } + Rectangle{ + width: parent.width + height: 1 + anchors.top: parent.top + color: control.selectedBorderColor + } + Rectangle{ + width: parent.width + height: 1 + anchors.bottom: parent.bottom + color: control.selectedBorderColor + } + } + } + } + } + MouseArea{ + id:layout_mouse_table + hoverEnabled: true + anchors{ + left: header_vertical.right + top: header_horizontal.bottom + right: parent.right + bottom: parent.bottom + } + onExited: { + d.rowHoverIndex = -1 + } + onCanceled: { + d.rowHoverIndex = -1 + } + TableView { + id:table_view + ListModel{ + id:model_columns + } + boundsBehavior: Flickable.StopAtBounds + syncView: header_horizontal + syncDirection: Qt.Horizontal + anchors.fill: parent + ScrollBar.vertical:scroll_bar_v + rowHeightProvider: function(row) { + var rowObject = control.getRow(row) + var height = rowObject.height + if(height){ + return height + } + var minimumHeight = rowObject._minimumHeight + if(minimumHeight){ + return minimumHeight + } + return d.defaultItemHeight + } + model: table_sort_model + clip: true + onRowsChanged: { + closeEditor() + } + delegate: com_table_delegate + FluLoader{ + id:loader_edit + property var tableView: control + property var display + property int column: { + if(d.editPosition){ + return d.editPosition.column + } + return 0 + } + property int row: { + if(d.editPosition){ + return d.editPosition.row + } + return 0 + } + signal editTextChaged(string text) + sourceComponent: d.editPosition ? d.editDelegate : undefined + onEditTextChaged: + (text)=>{ + var obj = control.getRow(row) + obj[d.columns_data[column].dataIndex] = text + control.setRow(row,obj) + } + width: { + if(d.editPosition){ + return d.editPosition.width + } + return 0 + } + height: { + if(d.editPosition){ + return d.editPosition.height + } + return 0 + } + x:{ + if(d.editPosition){ + return d.editPosition.x + } + return 0 + } + y:{ + if(d.editPosition){ + return d.editPosition.y + } + return 0 + } + z:999 + } + } + } + Component{ + id:com_column_header_delegate + Rectangle{ + id:column_item_control + readonly property real cellPadding: 8 + property bool canceled: false + property int columnIndex: column + readonly property var columnObject : d.columns_data[column] + implicitWidth: { + return (item_column_loader.item && item_column_loader.item.implicitWidth) + (cellPadding * 2) + } + implicitHeight: Math.max(36, (item_column_loader.item&&item_column_loader.item.implicitHeight) + (cellPadding * 2)) + color: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1) + Rectangle{ + border.color: control.borderColor + width: parent.width + height: 1 + anchors.top: parent.top + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: parent.width + height: 1 + anchors.bottom: parent.bottom + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: 1 + height: parent.height + anchors.left: parent.left + visible: column !== 0 + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: 1 + height: parent.height + anchors.right: parent.right + color:"#00000000" + visible: column === table_view.columns - 1 + } + 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() + } + } + FluLoader{ + id:item_column_loader + property var itemModel: model + property var modelData: model.display + property var tableView: table_view + property var tableModel: table_model + property var options:{ + if(typeof(modelData) == "object"){ + return modelData.options + } + return {} + } + property int column: column_item_control.columnIndex + width: parent.width + height: parent.height + sourceComponent: { + if(typeof(modelData) == "object"){ + return modelData.comId + } + return com_column_text + } + } + MouseArea{ + property point clickPos: "0,0" + height: parent.height + width: 6 + anchors.right: parent.right + acceptedButtons: Qt.LeftButton + hoverEnabled: true + visible: !(columnObject.width === columnObject.minimumWidth && columnObject.width === columnObject.maximumWidth && columnObject.width) + cursorShape: Qt.SplitHCursor + preventStealing: true + onPressed : + (mouse)=>{ + FluTools.setOverrideCursor(Qt.SplitHCursor) + clickPos = Qt.point(mouse.x, mouse.y) + } + onReleased:{ + FluTools.restoreOverrideCursor() + } + onCanceled: { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=>{ + if(!pressed){ + return + } + var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y) + var minimumWidth = columnObject.minimumWidth + var maximumWidth = columnObject.maximumWidth + var w = columnObject.width + if(!w){ + w = d.defaultItemWidth + } + if(!minimumWidth){ + minimumWidth = d.defaultItemWidth + } + if(!maximumWidth){ + maximumWidth = 65535 + } + columnObject.width = Math.min(Math.max(minimumWidth, w + delta.x),maximumWidth) + header_horizontal.forceLayout() + } + } + } + } + Component{ + id:com_row_header_delegate + Rectangle{ + id:item_control + readonly property real cellPadding: 8 + property bool canceled: false + property var rowObject: control.getRow(row) + implicitWidth: Math.max(30, row_text.implicitWidth + (cellPadding * 2)) + implicitHeight: row_text.implicitHeight + (cellPadding * 2) + color: FluTheme.dark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(247/255,247/255,247/255,1) + Rectangle{ + border.color: control.borderColor + width: parent.width + height: 1 + anchors.top: parent.top + visible: row !== 0 + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: parent.width + height: 1 + anchors.bottom: parent.bottom + visible: row === table_view.rows - 1 + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: 1 + height: parent.height + anchors.left: parent.left + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: 1 + height: parent.height + anchors.right: parent.right + color:"#00000000" + } + FluText{ + id:row_text + anchors.centerIn: parent + text: model.display + } + 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() + } + } + MouseArea{ + property point clickPos: "0,0" + height: 6 + width: parent.width + anchors.bottom: parent.bottom + acceptedButtons: Qt.LeftButton + cursorShape: Qt.SplitVCursor + preventStealing: true + visible: { + if(rowObject === null) + return false + return !(rowObject.height === rowObject._minimumHeight && rowObject.height === rowObject._maximumHeight && rowObject.height) + } + onPressed : + (mouse)=>{ + FluTools.setOverrideCursor(Qt.SplitVCursor) + clickPos = Qt.point(mouse.x, mouse.y) + } + onReleased:{ + FluTools.restoreOverrideCursor() + } + onCanceled: { + FluTools.restoreOverrideCursor() + } + onPositionChanged: + (mouse)=>{ + if(!pressed){ + return + } + var rowObject = control.getRow(row) + var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y) + var minimumHeight = rowObject._minimumHeight + var maximumHeight = rowObject._maximumHeight + var h = rowObject.height + if(!h){ + h = d.defaultItemHeight + } + if(!minimumHeight){ + minimumHeight = d.defaultItemHeight + } + if(!maximumHeight){ + maximumHeight = 65535 + } + rowObject.height = Math.min(Math.max(minimumHeight, h + delta.y),maximumHeight) + control.setRow(row,rowObject) + table_view.forceLayout() + } + } + } + } + Component{ + id:com_column_text + FluText { + id: column_text + text: modelData + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + Item{ + id: header_vertical_column + anchors{ + top: header_horizontal.top + bottom: header_horizontal.bottom + left: parent.left + right: header_vertical.right + } + Rectangle{ + border.color: control.borderColor + width: parent.width + height: 1 + anchors.top: parent.top + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: parent.width + height: 1 + anchors.bottom: parent.bottom + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: 1 + height: parent.height + anchors.left: parent.left + color:"#00000000" + } + Rectangle{ + border.color: control.borderColor + width: 1 + height: parent.height + anchors.right: parent.right + color:"#00000000" + } + } + TableView { + id: header_horizontal + model: header_column_model + anchors{ + left: header_vertical.right + right: layout_mouse_table.right + top: parent.top + } + visible: control.horizonalHeaderVisible + height: visible ? Math.max(1, contentHeight) : 0 + boundsBehavior: Flickable.StopAtBounds + clip: true + ScrollBar.horizontal:scroll_bar_h + columnWidthProvider: function(column) { + var columnObject = d.columns_data[column] + var width = columnObject.width + if(width){ + return width + } + var minimumWidth = columnObject.minimumWidth + if(minimumWidth){ + return minimumWidth + } + return d.defaultItemWidth + } + onContentXChanged:{ + timer_horizontal_force_layout.restart() + } + Timer{ + id:timer_horizontal_force_layout + interval: 50 + onTriggered: { + header_horizontal.forceLayout() + } + } + delegate: com_column_header_delegate + } + TableView { + id: header_vertical + boundsBehavior: Flickable.StopAtBounds + anchors{ + top: layout_mouse_table.top + left: parent.left + } + visible: control.verticalHeaderVisible + implicitWidth: visible ? Math.max(1, contentWidth) : 0 + implicitHeight: syncView ? syncView.height : 0 + syncDirection: Qt.Vertical + syncView: table_view + clip: true + model: header_row_model + Connections{ + target: table_model + function onRowCountChanged(){ + header_row_model.rows = Array.from({length: table_model.rows.length}, (_, i) => ({rowIndex:i+1})) + } + } + onContentYChanged:{ + timer_vertical_force_layout.restart() + } + Timer{ + id:timer_vertical_force_layout + interval: 50 + onTriggered: { + header_vertical.forceLayout() + } + } + delegate: com_row_header_delegate + } + FluScrollBar { + id:scroll_bar_h + anchors{ + left: layout_mouse_table.left + right: parent.right + bottom: layout_mouse_table.bottom + } + z:999 + } + FluScrollBar { + id:scroll_bar_v + anchors{ + top: layout_mouse_table.top + bottom: layout_mouse_table.bottom + right: parent.right + } + z:999 + } + function closeEditor(){ + d.editPosition = undefined + d.editDelegate = undefined + } + function resetPosition(){ + scroll_bar_h.position = 0 + scroll_bar_v.position = 0 + } + function customItem(comId,options={}){ + var o = {} + o.comId = comId + o.options = options + return o + } + function sort(callback=undefined){ + if(callback){ + table_sort_model.setComparator(function(left,right){ + return callback(table_model.getRow(left),table_model.getRow(right)) + }) + }else{ + table_sort_model.setComparator(undefined) + } + } + function filter(callback=undefined){ + if(callback){ + table_sort_model.setFilter(function(index){ + return callback(table_model.getRow(index)) + }) + }else{ + table_sort_model.setFilter(undefined) + } + } + function setRow(rowIndex,obj){ + if(rowIndex>=0 && rowIndex=0 && rowIndex=0 && rowIndex 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: { + if(control.echoMode === TextInput.Password){ + return + } + if(control.readOnly && control.text === ""){ + return + } + menu.popup() + } + } + RowLayout{ + height: parent.height + anchors{ + right: parent.right + rightMargin: 5 + } + spacing: 4 + FluIconButton{ + iconSource: FluentIcons.Cancel + iconSize: 12 + Layout.preferredWidth: 30 + Layout.preferredHeight: 20 + Layout.alignment: Qt.AlignVCenter + iconColor: FluTheme.dark ? Qt.rgba(222/255,222/255,222/255,1) : Qt.rgba(97/255,97/255,97/255,1) + verticalPadding: 0 + horizontalPadding: 0 + visible: { + if(control.cleanEnabled === false){ + return false + } + if(control.readOnly) + return false + return control.text !== "" + } + contentDescription:"Clean" + onClicked:{ + control.clear() + } + } + FluIcon{ + id:icon_end + iconSource: control.iconSource + iconSize: 12 + Layout.alignment: Qt.AlignVCenter + Layout.rightMargin: 7 + iconColor: FluTheme.dark ? Qt.rgba(222/255,222/255,222/255,1) : Qt.rgba(97/255,97/255,97/255,1) + visible: control.iconSource != 0 + } + } + FluTextBoxMenu{ + id:menu + inputItem: control + } +} diff --git a/src/FluentUI/Controls/FluTextBoxBackground.qml b/src/FluentUI/Controls/FluTextBoxBackground.qml new file mode 100644 index 00000000..3ec71baf --- /dev/null +++ b/src/FluentUI/Controls/FluTextBoxBackground.qml @@ -0,0 +1,56 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +FluClip{ + property Item inputItem + property int borderWidth: 1 + id:control + radius: [4,4,4,4] + Rectangle{ + radius: 4 + anchors.fill: parent + color: { + if(inputItem && 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 && inputItem.activeFocus){ + return FluTheme.dark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1) + } + if(inputItem && 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) + } + border.width: control.borderWidth + border.color: { + if(inputItem && 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 && inputItem.activeFocus ? 2 : 1 + anchors.bottom: parent.bottom + visible: !(inputItem && inputItem.disabled) + color: { + if(inputItem && inputItem.activeFocus){ + return FluTheme.primaryColor + } + if(FluTheme.dark){ + return Qt.rgba(166/255,166/255,166/255,1) + }else{ + return Qt.rgba(134/255,134/255,134/255,1) + } + } + Behavior on height{ + enabled: FluTheme.enableAnimation + NumberAnimation{ + duration: 83 + easing.type: Easing.OutCubic + } + } + } +} diff --git a/src/FluentUI/Controls/FluTextBoxMenu.qml b/src/FluentUI/Controls/FluTextBoxMenu.qml new file mode 100644 index 00000000..3be0c1b2 --- /dev/null +++ b/src/FluentUI/Controls/FluTextBoxMenu.qml @@ -0,0 +1,104 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +FluMenu{ + property string cutText : qsTr("Cut") + property string copyText : qsTr("Copy") + property string pasteText : qsTr("Paste") + property string selectAllText : qsTr("Select All") + property var inputItem + id:menu + enableAnimation: false + width: 120 + focus: false + onVisibleChanged: { + if(inputItem){ + inputItem.forceActiveFocus() + } + } + Connections{ + target: { + if(inputItem){ + return inputItem + } + return null + } + function onTextChanged() { + menu.close() + } + function onActiveFocusChanged() { + if(!inputItem.activeFocus){ + menu.close() + } + } + } + FluIconButton{ + display: Button.TextOnly + text:cutText + focus: false + padding: 0 + height: visible ? 36 : 0 + visible: { + if(inputItem){ + return inputItem.selectedText !== "" && !inputItem.readOnly + } + return false + } + onClicked: { + inputItem.cut() + menu.close() + } + } + FluIconButton{ + display: Button.TextOnly + text:copyText + focus: false + padding: 0 + height: visible ? 36 : 0 + visible: { + if(inputItem){ + return inputItem.selectedText !== "" + } + return false + } + onClicked: { + inputItem.copy() + menu.close() + } + } + FluIconButton{ + display: Button.TextOnly + text:pasteText + focus: false + padding: 0 + visible: { + if(inputItem){ + return !inputItem.readOnly + } + return false + } + height: visible ? 36 : 0 + onClicked: { + inputItem.paste() + menu.close() + } + } + FluIconButton{ + display: Button.TextOnly + text:selectAllText + focus: false + padding: 0 + height: visible ? 36 : 0 + visible: { + if(inputItem){ + return inputItem.text !== "" + } + return false + } + onClicked: { + inputItem.selectAll() + menu.close() + } + } +} diff --git a/src/FluentUI/Controls/FluTextButton.qml b/src/FluentUI/Controls/FluTextButton.qml new file mode 100644 index 00000000..68d98129 --- /dev/null +++ b/src/FluentUI/Controls/FluTextButton.qml @@ -0,0 +1,65 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Basic +import FluentUI + +Button { + property bool disabled: false + property string contentDescription: "" + property color normalColor: FluTheme.primaryColor + 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.itemHoverColor + property color backgroundPressedColor: FluTheme.itemPressColor + property color backgroundNormalColor: FluTheme.itemNormalColor + property color backgroundDisableColor: FluTheme.itemNormalColor + 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/FluentUI/Controls/FluTimePicker.qml b/src/FluentUI/Controls/FluTimePicker.qml new file mode 100644 index 00000000..f34b6dd6 --- /dev/null +++ b/src/FluentUI/Controls/FluTimePicker.qml @@ -0,0 +1,429 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Window +import FluentUI + +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 + property string amText: "上午" + property string pmText: "下午" + property string hourText: "时" + property string minuteText: "分" + property string cancelText: "取消" + property string okText: "确定" + signal accepted() + id:control + color: { + if(mouse_area.containsMouse){ + return hoverColor + } + return normalColor + } + height: 30 + width: 300 + radius: 4 + border.width: 1 + border.color: dividerColor + Component.onCompleted: { + if(current){ + var now = current; + var hour + var ampm; + if(isH){ + hour = now.getHours(); + if(hour>12){ + ampm = control.pmText + hour = hour-12 + }else{ + ampm = control.amText + } + }else{ + hour = now.getHours(); + } + hour = text_hour.text === control.hourText ? hour.toString().padStart(2, '0') : text_hour.text + var minute = text_minute.text === control.minuteText ? now.getMinutes().toString().padStart(2, '0') : text_minute.text + ampm = text_ampm.text === "%1/%2".arg(control.amText).arg(control.pmText) ? ampm : text_ampm.text + text_hour.text = hour + text_minute.text = minute + if(isH){ + text_ampm.text = ampm + } + } + } + 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: control.hourText + } + 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: control.minuteText + } + 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: "%1/%2".arg(control.amText).arg(control.pmText) + } + Menu{ + id:popup + width: container.width + height: container.height + modal: true + Overlay.modal: Item {} + 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){ + return item_mouse.containsMouse ? Qt.darker(FluTheme.primaryColor,1.1) : FluTheme.primaryColor + } + 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: FluLoader{ + 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: FluLoader{ + 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: [control.amText,control.pmText] + clip: true + visible: isH + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightMoveDuration: 0 + ScrollBar.vertical: FluScrollBar {} + Layout.alignment: Qt.AlignVCenter + boundsBehavior:Flickable.StopAtBounds + delegate: FluLoader{ + 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: control.cancelText + onClicked: { + popup.close() + } + } + FluFilledButton{ + anchors{ + right: parent.right + left: divider.right + rightMargin: 20 + leftMargin: 10 + verticalCenter: parent.verticalCenter + } + text: control.okText + 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 === control.amText) ? 0 : 12; + } else { + hours24 = (period === control.pmText) ? hours24 : hours24 + 12; + } + } + date.setHours(hours24); + date.setMinutes(parseInt(minutes)); + date.setSeconds(0); + current = date + control.accepted() + } + } + } + } + } + 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 = control.pmText + hour = hour-12 + }else{ + ampm = control.amText + } + }else{ + hour = now.getHours(); + } + hour = text_hour.text === control.hourText ? hour.toString().padStart(2, '0') : text_hour.text + var minute = text_minute.text === control.minuteText ? now.getMinutes().toString().padStart(2, '0') : text_minute.text + ampm = text_ampm.text === "%1/%2".arg(control.amText).arg(control.pmText) ? 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/FluentUI/Controls/FluTimeline.qml b/src/FluentUI/Controls/FluTimeline.qml new file mode 100644 index 00000000..4477e00e --- /dev/null +++ b/src/FluentUI/Controls/FluTimeline.qml @@ -0,0 +1,309 @@ +import QtQuick +import QtQuick.Controls +import FluentUI + +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: { + if(!model){ + return false + } + for(var i=0;icontrol.height) + return d.pos.y-height-control.targetMargins - 15 + return ty + } + return 0 + } + border.width: 0 + FluShadow{ + radius: 5 + } + FluText{ + text: { + if(d.step){ + return d.step.title + } + return "" + } + font: FluTextStyle.BodyStrong + elide: Text.ElideRight + anchors{ + top: parent.top + left: parent.left + topMargin: 15 + leftMargin: 15 + right: parent.right + rightMargin: 32 + } + } + FluText{ + id: text_desc + font: FluTextStyle.Body + wrapMode: Text.WrapAnywhere + maximumLineCount: 4 + elide: Text.ElideRight + text: { + if(d.step){ + return d.step.description + } + return "" + } + anchors{ + top: parent.top + left: parent.left + right: parent.right + rightMargin: 15 + topMargin: 42 + leftMargin: 15 + } + } + FluLoader{ + id: loader_next + property bool isEnd: control.index === steps.length-1 + sourceComponent: com_next_button + anchors{ + top: text_desc.bottom + topMargin: 10 + right: parent.right + rightMargin: 15 + } + } + FluLoader{ + id: loader_prev + visible: control.index !== 0 + sourceComponent: com_prev_button + anchors{ + right: loader_next.left + top: loader_next.top + rightMargin: 14 + } + } + FluIconButton{ + anchors{ + right: parent.right + top: parent.top + margins: 10 + } + width: 26 + height: 26 + verticalPadding: 0 + horizontalPadding: 0 + iconSize: 12 + iconSource: FluentIcons.ChromeClose + onClicked: { + control.close() + } + } + } + FluIcon{ + iconSource: layout_panne.dir?FluentIcons.FlickUp:FluentIcons.FlickDown + color: layout_panne.color + x: { + if(d.target){ + return d.pos.x+d.target.width/2-10 + } + return 0 + } + y: { + if(d.target){ + return d.pos.y+(layout_panne.dir?-height:d.target.height) + } + return 0 + } + } +} diff --git a/src/FluentUI/Controls/FluTreeView.qml b/src/FluentUI/Controls/FluTreeView.qml new file mode 100644 index 00000000..12ef0a60 --- /dev/null +++ b/src/FluentUI/Controls/FluTreeView.qml @@ -0,0 +1,440 @@ +import QtQuick +import QtQuick.Window +import QtQuick.Layouts +import QtQuick.Controls +import Qt.labs.qmlmodels +import FluentUI + +Item { + property int currentIndex : -1 + property var dataSource + property bool showLine: true + property bool draggable: false + property int cellHeight: 30 + property int depthPadding: 30 + property bool checkable: false + property color lineColor: FluTheme.dark ? Qt.rgba(111/255,111/255,111/255,1) : Qt.rgba(217/255,217/255,217/255,1) + id:control + QtObject { + id:d + property int dy + property var current + property int dropIndex: -1 + property bool isDropTopArea: false + property int dragIndex: -1 + property color hitColor: FluTheme.primaryColor + } + onDataSourceChanged: { + tree_model.setDataSource(dataSource) + } + FluTreeModel{ + id:tree_model + } + ListView{ + id:table_view + ScrollBar.horizontal: FluScrollBar{} + ScrollBar.vertical: FluScrollBar{} + boundsBehavior: Flickable.StopAtBounds + model: tree_model + anchors.fill: parent + clip: true + flickableDirection: Flickable.HorizontalAndVerticalFlick + contentWidth: contentItem.childrenRect.width + reuseItems: true + removeDisplaced : Transition{ + ParallelAnimation{ + NumberAnimation { + properties: "y" + duration: 167 + from: d.dy + table_view.height + easing.type: Easing.OutCubic + } + NumberAnimation { + properties: "opacity" + duration: 88 + from: 0 + to: 1 + } + } + } + move: Transition { + NumberAnimation { property: "y"; duration: 200 } + } + add: Transition{ + ParallelAnimation{ + NumberAnimation { + properties: "y" + duration: 167 + from: d.dy - control.cellHeight + easing.type: Easing.OutCubic + } + NumberAnimation { + properties: "opacity" + duration: 88 + from: 0 + to: 1 + } + } + } + delegate: Item { + id:item_control + implicitWidth: item_loader_container.width + implicitHeight: item_loader_container.height + ListView.onReused: { + item_loader_container.item.reused() + } + ListView.onPooled: { + item_loader_container.item.pooled() + } + FluLoader{ + property var itemControl: item_control + property var itemModel: dataModel + property int rowIndex: index + property bool isItemLoader: true + id:item_loader_container + sourceComponent: com_item_container + } + } + FluLoader{ + id:loader_container + property var itemControl + property var itemModel + property bool isItemLoader: false + } + } + Component{ + id:com_item_container + Item{ + signal reused + signal pooled + onReused: { + + } + onPooled: { + } + property bool isCurrent: d.current === itemModel + id:item_container + width: { + var w = 46 + item_loader_cell.width + control.depthPadding*itemModel.depth + if(control.width>w){ + return control.width + } + return w + } + height: control.cellHeight + implicitWidth: width + implicitHeight: height + function toggle(){ + var pos = FluTools.cursorPos() + var viewPos = table_view.mapToGlobal(0,0) + d.dy = table_view.contentY + pos.y-viewPos.y + if(itemModel.isExpanded){ + tree_model.collapse(rowIndex) + }else{ + tree_model.expand(rowIndex) + } + } + Rectangle{ + width: 3 + height: 18 + radius: 1.5 + color: FluTheme.primaryColor + visible: isCurrent + anchors{ + left: parent.left + leftMargin: 6 + verticalCenter: parent.verticalCenter + } + } + MouseArea{ + id:item_mouse + property point clickPos: Qt.point(0,0) + anchors.fill: parent + drag.target:control.draggable ? loader_container : undefined + hoverEnabled: true + drag.onActiveChanged: { + if(drag.active){ + if(itemModel.isExpanded && itemModel.hasChildren()){ + tree_model.collapse(rowIndex) + } + d.dragIndex = rowIndex + loader_container.sourceComponent = com_item_container + } + } + onPressed: + (mouse)=>{ + clickPos = Qt.point(mouse.x,mouse.y) + loader_container.itemControl = itemControl + loader_container.itemModel = itemModel + var cellPosition = item_container.mapToItem(table_view, 0, 0) + loader_container.width = item_container.width + loader_container.height = item_container.height + loader_container.x = 0 + loader_container.y = cellPosition.y + } + onClicked: { + d.current = itemModel + } + onDoubleClicked: { + if(itemModel.hasChildren()){ + item_container.toggle() + } + } + onPositionChanged: + (mouse)=> { + if(!drag.active){ + return + } + var cellPosition = item_container.mapToItem(table_view, 0, 0) + if(mouse.y+cellPosition.y<0 || mouse.y+cellPosition.y>table_view.height){ + d.dropIndex = -1 + return + } + if((mouse.x-table_view.contentX)>table_view.width || (mouse.x-table_view.contentX)<0){ + d.dropIndex = -1 + return + } + var pos = FluTools.cursorPos() + var viewPos = table_view.mapToGlobal(0,0) + var y = table_view.contentY + pos.y-viewPos.y + var index = Math.floor(y/control.cellHeight) + if(index<0 || index>table_view.count-1){ + d.dropIndex = -1 + return + } + if(tree_model.hitHasChildrenExpanded(index) && y>index*control.cellHeight+control.cellHeight/2){ + d.dropIndex = index + 1 + d.isDropTopArea = true + }else{ + d.dropIndex = index + if(y>index*control.cellHeight+control.cellHeight/2){ + d.isDropTopArea = false + }else{ + d.isDropTopArea = true + } + } + } + onCanceled: { + loader_container.sourceComponent = undefined + loader_container.x = 0 + loader_container.y = 0 + d.dropIndex = -1 + d.dragIndex = -1 + } + onReleased: { + loader_container.sourceComponent = undefined + if(d.dropIndex !== -1){ + tree_model.dragAnddrop(d.dragIndex,d.dropIndex,d.isDropTopArea) + } + d.dropIndex = -1 + d.dragIndex = -1 + loader_container.x = 0 + loader_container.y = 0 + } + } + Drag.active: item_mouse.drag.active + Rectangle{ + id:item_line_drop_tip + anchors{ + left: layout_row.left + leftMargin: 26 + right: parent.right + rightMargin: 10 + bottom: parent.bottom + bottomMargin: -1.5 + top: undefined + } + states: [ + State { + when:d.isDropTopArea + AnchorChanges { + target: item_line_drop_tip + anchors.top: item_container.top + anchors.bottom: undefined + } + PropertyChanges { + target: item_line_drop_tip + anchors.topMargin: -1.5 + } + } + ] + height: 3 + radius: 1.5 + color: d.hitColor + visible: d.dropIndex === rowIndex + Rectangle{ + width: 10 + height: 10 + radius: 5 + border.width: 3 + border.color: d.hitColor + color: FluTheme.dark ? FluColors.Black : FluColors.White + anchors{ + top: parent.top + left: parent.left + topMargin: -3 + leftMargin: -5 + } + } + } + FluRectangle{ + width: 1 + color: control.lineColor + visible: control.showLine && isItemLoader && itemModel.depth !== 0 && !itemModel.hasChildren() + height: itemModel.hideLineFooter() ? parent.height/2 : parent.height + anchors{ + top: parent.top + left: item_line_h.left + } + } + FluRectangle{ + id:item_line_h + height: 1 + color: control.lineColor + visible: control.showLine && isItemLoader && itemModel.depth !== 0 && !itemModel.hasChildren() + width: depthPadding - 10 + anchors{ + right: layout_row.left + rightMargin: -24 + verticalCenter: parent.verticalCenter + } + } + Repeater{ + model: Math.max(itemModel.depth-1,0) + delegate: FluRectangle{ + required property int index + width: 1 + color: control.lineColor + visible: control.showLine && isItemLoader && itemModel.depth !== 0 && itemModel.hasNextNodeByIndex(index) + anchors{ + top:parent.top + bottom: parent.bottom + left: parent.left + leftMargin: control.depthPadding*(index+1) + 24 + } + } + } + Rectangle{ + anchors.fill: parent + radius: 4 + anchors.leftMargin: 6 + anchors.rightMargin: 6 + border.color: d.hitColor + border.width: d.dragIndex === rowIndex ? 1 : 0 + color: { + if(isCurrent){ + return FluTheme.itemCheckColor + } + if(item_mouse.containsMouse || item_check_box.hovered){ + return FluTheme.itemHoverColor + } + if(item_loader_expand.item && item_loader_expand.item.hovered){ + return FluTheme.itemHoverColor + } + return FluTheme.itemNormalColor + } + } + RowLayout{ + id:layout_row + height: parent.height + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + spacing: 0 + anchors.leftMargin: 14 + control.depthPadding*itemModel.depth + Component{ + id:com_icon_btn + FluIconButton{ + opacity: itemModel.hasChildren() + onClicked: { + item_container.toggle() + } + contentItem:FluIcon{ + rotation: itemModel.isExpanded?0:-90 + iconSource:FluentIcons.ChevronDown + iconSize: 16 + anchors.centerIn: parent + } + } + } + + FluLoader{ + id:item_loader_expand + Layout.preferredWidth: 20 + Layout.preferredHeight: 20 + sourceComponent: itemModel.hasChildren() ? com_icon_btn : undefined + Layout.alignment: Qt.AlignVCenter + } + + FluCheckBox{ + id:item_check_box + Layout.preferredWidth: 18 + Layout.preferredHeight: 18 + Layout.leftMargin: 5 + horizontalPadding:0 + verticalPadding: 0 + checked: itemModel.checked + enableAnimation:false + visible: control.checkable + padding: 0 + clickListener: function(){ + tree_model.checkRow(rowIndex,!itemModel.checked) + } + Layout.alignment: Qt.AlignVCenter + } + FluLoader{ + property var dataModel: itemModel + property var itemMouse: item_mouse + id:item_loader_cell + Layout.leftMargin: 10 + Layout.preferredWidth: { + if(item){ + return item.width + } + return 0 + } + Layout.fillHeight: true + sourceComponent:com_item_text + } + } + } + } + Component{ + id:com_item_text + Item{ + width: item_text.width + FluText { + id:item_text + text: dataModel.title + rightPadding: 14 + anchors.centerIn: parent + color:{ + if(itemMouse.pressed){ + return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120 + } + return FluTheme.dark ? FluColors.White : FluColors.Grey220 + } + } + } + } + function selectionModel(){ + return tree_model.selectionModel + } + function count(){ + return tree_model.dataSourceSize + } + function visibleCount(){ + return table_view.count + } + function collapse(rowIndex){ + tree_model.collapse(rowIndex) + } + function expand(rowIndex){ + tree_model.expand(rowIndex) + } + function allExpand(){ + tree_model.allExpand() + } + function allCollapse(){ + tree_model.allCollapse() + } +} diff --git a/src/FluentUI/Controls/FluWindow.qml b/src/FluentUI/Controls/FluWindow.qml new file mode 100644 index 00000000..8d43c129 --- /dev/null +++ b/src/FluentUI/Controls/FluWindow.qml @@ -0,0 +1,320 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +Window { + default property alias contentData : layout_content.data + property string windowIcon: FluApp.windowIcon + property int launchMode: FluWindowType.Standard + property var argument:({}) + property var background : com_background + property bool fixSize: false + property Component loadingItem: com_loading + property bool fitsAppBarWindows: false + property Item appBar: FluAppBar { + title: window.title + height: 30 + showDark: window.showDark + showClose: window.showClose + showMinimize: window.showMinimize + showMaximize: window.showMaximize + showStayTop: window.showStayTop + icon: window.windowIcon + } + property color backgroundColor: { + if(active){ + return FluTheme.windowActiveBackgroundColor + } + return FluTheme.windowBackgroundColor + } + property bool stayTop: false + property bool showDark: false + property bool showClose: true + property bool showMinimize: true + property bool showMaximize: true + property bool showStayTop: false + property bool autoMaximize: false + property bool autoVisible: true + property bool autoCenter: true + property bool autoDestory: true + property bool useSystemAppBar + property color resizeBorderColor: { + if(window.active){ + return FluTheme.dark ? "#333333" : "#6E6E6E" + } + return FluTheme.dark ? "#3D3D3E" : "#A7A7A7" + } + property int resizeBorderWidth: 1 + property var closeListener: function(event){ + if(autoDestory){ + destoryOnClose() + }else{ + visible = false + event.accepted = false + } + } + signal showSystemMenu + signal initArgument(var argument) + signal firstVisible() + property int _realHeight + property int _realWidth + property int _appBarHeight: appBar.height + property var _windowRegister + property string _route + id:window + color:"transparent" + Component.onCompleted: { + _realHeight = height + _realWidth = width + useSystemAppBar = FluApp.useSystemAppBar + if(useSystemAppBar && autoCenter){ + moveWindowToDesktopCenter() + } + fixWindowSize() + lifecycle.onCompleted(window) + initArgument(argument) + if(!useSystemAppBar){ + loader_frameless_helper.sourceComponent = com_frameless_helper + } + if(window.autoVisible){ + if(window.autoMaximize){ + window.showMaximized() + }else{ + window.show() + } + } + } + Component.onDestruction: { + lifecycle.onDestruction() + } + onShowSystemMenu: { + if(loader_frameless_helper.item){ + loader_frameless_helper.item.showSystemMenu() + } + } + onVisibleChanged: { + if(visible && d.isFirstVisible){ + window.firstVisible() + d.isFirstVisible = false + } + lifecycle.onVisible(visible) + } + onWidthChanged: { + window.appBar.width = width + } + QtObject{ + id:d + property bool isFirstVisible: true + } + Connections{ + target: window + function onClosing(event){closeListener(event)} + } + Component{ + id:com_frameless_helper + FluFramelessHelper{ + onLoadCompleted:{ + if(autoCenter){ + window.moveWindowToDesktopCenter() + } + } + } + } + Component{ + id:com_background + Rectangle{ + color: window.backgroundColor + } + } + Component{ + id:com_app_bar + Item{ + data: window.appBar + } + } + Component{ + id:com_loading + Popup{ + id:popup_loading + focus: true + width: window.width + height: window.height + anchors.centerIn: Overlay.overlay + closePolicy: { + if(cancel){ + return Popup.CloseOnEscape | Popup.CloseOnPressOutside + } + return Popup.NoAutoClose + } + Overlay.modal: Item {} + onVisibleChanged: { + if(!visible){ + loader_loading.sourceComponent = undefined + } + } + padding: 0 + opacity: 0 + visible:true + Behavior on opacity { + SequentialAnimation { + PauseAnimation { + duration: 88 + } + NumberAnimation{ + duration: 167 + } + } + } + Component.onCompleted: { + opacity = 1 + } + background: Rectangle{ + color:"#44000000" + } + contentItem: Item{ + MouseArea{ + anchors.fill: parent + onClicked: { + if (cancel){ + popup_loading.visible = false + } + } + } + ColumnLayout{ + spacing: 8 + anchors.centerIn: parent + FluProgressRing{ + Layout.alignment: Qt.AlignHCenter + } + FluText{ + text:loadingText + Layout.alignment: Qt.AlignHCenter + } + } + } + } + } + Component{ + id:com_border + Rectangle{ + color:"transparent" + border.width: window.resizeBorderWidth + border.color: window.resizeBorderColor + } + } + FluLoader{ + id:loader_frameless_helper + } + FluLoader{ + anchors.fill: parent + sourceComponent: background + } + FluLoader{ + id:loader_app_bar + anchors { + top: parent.top + left: parent.left + right: parent.right + } + height: { + if(window.useSystemAppBar){ + return 0 + } + return window.fitsAppBarWindows ? 0 : window.appBar.height + } + sourceComponent: window.useSystemAppBar ? undefined : com_app_bar + } + Item{ + id:layout_content + anchors{ + top: loader_app_bar.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + clip: true + } + FluLoader{ + property string loadingText + property bool cancel: false + id:loader_loading + anchors.fill: parent + } + FluInfoBar{ + id:info_bar + root: window + } + FluWindowLifecycle{ + id:lifecycle + } + FluLoader{ + id:loader_border + anchors.fill: parent + sourceComponent: { + if(window.useSystemAppBar){ + return undefined + } + if(FluTools.isWindows10OrGreater()){ + return undefined + } + if(window.visibility === Window.Maximized || window.visibility === Window.FullScreen){ + return undefined + } + return com_border + } + } + function destoryOnClose(){ + lifecycle.onDestoryOnClose() + } + function showLoading(text = qsTr("Loading..."),cancel = true){ + loader_loading.loadingText = text + loader_loading.cancel = cancel + loader_loading.sourceComponent = com_loading + } + function hideLoading(){ + loader_loading.sourceComponent = undefined + } + function showSuccess(text,duration,moremsg){ + info_bar.showSuccess(text,duration,moremsg) + } + function showInfo(text,duration,moremsg){ + info_bar.showInfo(text,duration,moremsg) + } + function showWarning(text,duration,moremsg){ + info_bar.showWarning(text,duration,moremsg) + } + function showError(text,duration,moremsg){ + info_bar.showError(text,duration,moremsg) + } + function moveWindowToDesktopCenter(){ + screen = Qt.application.screens[FluTools.cursorScreenIndex()] + var availableGeometry = FluTools.desktopAvailableGeometry(window) + window.setGeometry((availableGeometry.width-window.width)/2+Screen.virtualX,(availableGeometry.height-window.height)/2+Screen.virtualY,window.width,window.height) + } + function fixWindowSize(){ + if(fixSize){ + window.maximumWidth = window.width + window.maximumHeight = window.height + window.minimumWidth = window.width + window.minimumHeight = window.height + } + } + function registerForWindowResult(path){ + return FluApp.createWindowRegister(window,path) + } + function onResult(data){ + if(_windowRegister){ + _windowRegister.onResult(data) + } + } + function showMaximized(){ + if(FluTools.isWin()){ + if(loader_frameless_helper.item){ + loader_frameless_helper.item.showMaximized() + } + }else{ + window.visibility = Qt.WindowMaximized + } + } +} diff --git a/src/FluentUI/Controls/FluWindowDialog.qml b/src/FluentUI/Controls/FluWindowDialog.qml new file mode 100644 index 00000000..60a40d21 --- /dev/null +++ b/src/FluentUI/Controls/FluWindowDialog.qml @@ -0,0 +1,33 @@ +import QtQuick +import QtQuick.Window +import QtQuick.Controls +import QtQuick.Layouts +import FluentUI + +FluWindow { + id:control + property Component contentDelegate + autoVisible: false + autoCenter: false + autoDestory: true + fixSize: true + Loader{ + anchors.fill: parent + sourceComponent: { + if(control.autoDestory){ + return control.visible ? control.contentDelegate : undefined + } + return control.contentDelegate + } + } + closeListener: function(event){ + visible = false + event.accepted = false + } + function showDialog(){ + var x = transientParent.x + (transientParent.width - width)/2 + var y = transientParent.y + (transientParent.height - height)/2 + setGeometry(x,y,width,height) + visible = true + } +} diff --git a/src/FluentUI/Font/Segoe_Fluent_Icons.ttf b/src/FluentUI/Font/Segoe_Fluent_Icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8f05a4bbc13461ba7144efa9c0d3f38634de1283 GIT binary patch literal 408752 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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 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 T-|Wu*C93JG*3SoP9%lXz9{#lZ literal 0 HcmV?d00001 diff --git a/src/FluentUI/Image/btn_close_hovered.png b/src/FluentUI/Image/btn_close_hovered.png new file mode 100644 index 0000000000000000000000000000000000000000..afd646f39da99c5f925f0c8bf3a48ad75b6d3732 GIT binary patch literal 10314 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 A+W-In literal 0 HcmV?d00001 diff --git a/src/FluentUI/Image/btn_close_normal.png b/src/FluentUI/Image/btn_close_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..de922d4bc45a3c6827d4fa02514bcd71addf3cfc GIT binary patch literal 10096 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 literal 0 HcmV?d00001 diff --git a/src/FluentUI/Image/btn_max_normal.png b/src/FluentUI/Image/btn_max_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..4c1bc6292aa9e02b11b02c4b38faa3b22c9c28d6 GIT binary patch literal 10128 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 literal 0 HcmV?d00001 diff --git a/src/FluentUI/Image/btn_max_pushed.png b/src/FluentUI/Image/btn_max_pushed.png new file mode 100644 index 0000000000000000000000000000000000000000..22fc333e5a91a8f42fd2e7a06ea5f7c4ca973b43 GIT binary patch literal 10412 zcmcIq36xaTnQmoFR~|-T%M;{r~S@Zmpbs=BeYxOdL~FQ!{Sn3_AzkCq!SPM&kY5uKNA>Ho9%b1sydt zM|MVEhrHeJo$i{N@2)A%o!2>U)*0zssiiKHFJ%jL-7Rf+x~AroY29s^+`>Xl0oiuy)?8*|nzBUZ@pyZZbz5Rx5QKb%|!qlv+lp zOc9x)JV|JpxM{9ydtV7iYtJ{N=h(1U7JjQwG<9~irBkV{uCBT+URP>wOi`_Mim()8 zNj#D4Slrr~=}xwGOzK;~7CLh6#kS63skJs*F_SGV>a0&d)1ED~wDm9B+R~|G&ScVLsO{ux(L$bJ;xkT&mDqXu;YYc$Sv+YfGEW3E%y3wT?~EsBg0;d?wcU&>*PeuJiSIl>Aq$t0Zu6-h0fhGa(NX;SGtacCja zAQbCc?X319f+y4b)m0;{@>sD!m{+&}senae4!`HIj#5KsSEjw-HNw(E@vl@h{W~(3 z#cMybv;Y6qzSp?9rc7&N0SuZ-MEglaT+?$jsez|<;MDs($AeEtXWG$g2|v@=Z-eIgrSjSFhU!} zRp2YdnbtzGz-585+JPW9uwDg(7y81ZcymGLp{Fg8j%PUuT;&j~F<6H02Sh3oINBQK z`dWI7I8137NS88Z2O~m{a_ws28Y8)so^f3c9UbOq!nspn=aqw+=V?}9nIvlv46K#c zNkt1hiM0{ogww2a21~EJmP2!n)ESw~@oYo1Rz8`{Dw$L&+mL6uf@De#buE?8=JNtv z>g2PuM=wnXN#@*K17Xz7WLROSYiTFXc#gP9>2MjXrIMLkHk-_2-&rQ|8R=$+x>f@t zGNXAmNtkk@wK7TQ#go~b6uBJD%e<_h*P=z>JwhB$XilhgX+S8|ERaE{rP9=dFbbcd#xbE(jtwaFn6{ew3Vs&okW@H`GK>kh zs}Y79t8GZBZv!WEoX|7M#qkAIq;YHtN=dGyEGwy*^#oN`XgDRW;J{^Rj%yh9A2`Yj ztf3U&sAYyx-{Gzdc@=4n_GA!HK`7LOk{$xtxZDxO4LqDnHJFD3aH&T;LL!rBtF(0t zWs;h}=d>Ekm!1Pb(qKQ4NsKE(mng(*5Gqw|Z^9?SfyE8CK^ex}0J5krsT7iWRip{u zP!G(6qoQRcB{)Qf9^ruvLR(E5I7);jAf9o`d-IhcA!kBaYh3O7Rir7UJn08qd&7d^ zaUrA)9Zza∾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 F_+JZJBpUz# literal 0 HcmV?d00001 diff --git a/src/FluentUI/Image/btn_min_hovered.png b/src/FluentUI/Image/btn_min_hovered.png new file mode 100644 index 0000000000000000000000000000000000000000..41e9395ecc2d0b032f114280986664c1aedb0e5c GIT binary patch literal 10143 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 literal 0 HcmV?d00001 diff --git a/src/FluentUI/Image/btn_min_pushed.png b/src/FluentUI/Image/btn_min_pushed.png new file mode 100644 index 0000000000000000000000000000000000000000..57f7211ae5b2d9614e7b7811768e45de9cfc0410 GIT binary patch literal 10260 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 literal 0 HcmV?d00001 diff --git a/src/FluentUI/Image/noise.png b/src/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 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

    {F)tTsH8tJ;L}2-?hX-=Z43o_h<&^W6s$BdOSG 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 literal 0 HcmV?d00001 diff --git a/src/FluentUI/JS/Chart.js b/src/FluentUI/JS/Chart.js new file mode 100644 index 00000000..cce4f915 --- /dev/null +++ b/src/FluentUI/JS/Chart.js @@ -0,0 +1,20822 @@ +/*! + * Chart.js v2.9.4 + * https://www.chartjs.org + * (c) 2020 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)]; +} + +/* MIT license */ + + + +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') { + console.debug(_window) + _window.Color = Color; +} + +var chartjsColor = Color; + +function isValidKey(key) { + return ['__proto__', 'prototype', 'constructor'].indexOf(key) === -1; +} + +/** + * @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 = Object.create(source); + 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) { + if (!isValidKey(key)) { + // We want to ensure we do not copy prototypes over + // as this can pollute global namespaces + return; + } + + 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) { + if (!isValidKey(key)) { + // We want to ensure we do not copy prototypes over + // as this can pollute global namespaces + return; + } + + 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(Object.create(null), [ + 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 = valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor)); + model.borderWidth = valueOrDefault$6(options.hoverBorderWidth, options.borderWidth); + model.radius = 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 + var sizes = layout.horizontal ? [newWidth, chartArea.w] : [newHeight, chartArea.h]; + return sizes[0] !== sizes[1] && (!isNaN(sizes[0]) || !isNaN(sizes[1])); + } +} + +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); + } + }]; + }; + if(Array.isArray(chart.boxes)){ + 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) { + if(chart.boxes){ + if(layoutItem){ + if(Array.isArray(chart.boxes)){ + var index = chart.boxes.indexOf(layoutItem) + 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