From b55c500cf4025de345ee0dee5a42ed21a034ca0a Mon Sep 17 00:00:00 2001 From: Reuben Turner Date: Fri, 3 Feb 2023 12:05:32 -0500 Subject: [PATCH] Version 1.9.0 (#339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Sidebar top (#244) * chore: refactor dir structure * feat: Sidebar top & updated default control color * feat(example): search results in top * chore: bump version, changelog * chore: run flutter pub upgrade * Update CHANGELOG.md * Update lib/src/layout/sidebar/sidebar.dart Co-authored-by: Minas Giannekas * chore: update issue templates * chore: update pr_prelaunch script * Flutter 3 upgrade & MacosColor update (#248) * chore: Update pubspec.yaml files to support Flutter 3 * chore: run dart fix --apply * chore: migrate Scrollbar to Flutter 3 * chore: update flutter_lints & subsequent fixes * feat: add missing functions to MacosColor the Color class has a number of functions that MacosColor had not implemented * chore: use super parameters * chore: update changelog * chore: tweak example app Uses the new PlatformMenuBar. Also update product name. * chore: small changelog tweak * chore: run flutter format . * chore: run dart fix --apply * chore: run flutter format . * chore: remove unused code in example * chore: remove unused import * chore: remove unused code * Starter app (#251) * chore: Update pubspec.yaml files to support Flutter 3 * chore: run dart fix --apply * chore: migrate Scrollbar to Flutter 3 * chore: update flutter_lints & subsequent fixes * feat: add missing functions to MacosColor the Color class has a number of functions that MacosColor had not implemented * chore: use super parameters * chore: update changelog * chore: tweak example app Uses the new PlatformMenuBar. Also update product name. * chore: small changelog tweak * chore: run flutter format . * chore: run dart fix --apply * chore: run flutter format . * chore: remove unused code in example * chore: remove unused import * feat: first pass at starter app brick * chore: improve starter app brick * chore: fix widget test in starter app * feat: conditional prompts & running pub get * chore: finalize brick * chore: run flutter format * chore: exclude starter app from analyzer * Full screen opaque toolbar issue (closes #249) (#252) * fix: don't show app window toolbar when in full screen * chore: update README * chore: update brick app window code * chore: update pubspec and changelog * chore: update actions Co-authored-by: Reuben Turner * Version 1.4.1 (#255) * Sidebar top (#244) * chore: refactor dir structure * feat: Sidebar top & updated default control color * feat(example): search results in top * chore: bump version, changelog * chore: run flutter pub upgrade * Update CHANGELOG.md * Update lib/src/layout/sidebar/sidebar.dart Co-authored-by: Minas Giannekas * chore: update issue templates * chore: update pr_prelaunch script * Flutter 3 upgrade & MacosColor update (#248) * chore: Update pubspec.yaml files to support Flutter 3 * chore: run dart fix --apply * chore: migrate Scrollbar to Flutter 3 * chore: update flutter_lints & subsequent fixes * feat: add missing functions to MacosColor the Color class has a number of functions that MacosColor had not implemented * chore: use super parameters * chore: update changelog * chore: tweak example app Uses the new PlatformMenuBar. Also update product name. * chore: small changelog tweak * chore: run flutter format . * chore: run dart fix --apply * chore: run flutter format . * chore: remove unused code in example * chore: remove unused import * chore: remove unused code * Starter app (#251) * chore: Update pubspec.yaml files to support Flutter 3 * chore: run dart fix --apply * chore: migrate Scrollbar to Flutter 3 * chore: update flutter_lints & subsequent fixes * feat: add missing functions to MacosColor the Color class has a number of functions that MacosColor had not implemented * chore: use super parameters * chore: update changelog * chore: tweak example app Uses the new PlatformMenuBar. Also update product name. * chore: small changelog tweak * chore: run flutter format . * chore: run dart fix --apply * chore: run flutter format . * chore: remove unused code in example * chore: remove unused import * feat: first pass at starter app brick * chore: improve starter app brick * chore: fix widget test in starter app * feat: conditional prompts & running pub get * chore: finalize brick * chore: run flutter format * chore: exclude starter app from analyzer * Full screen opaque toolbar issue (closes #249) (#252) * fix: don't show app window toolbar when in full screen * chore: update README * chore: update brick app window code * chore: update pubspec and changelog * chore: update actions Co-authored-by: Reuben Turner Co-authored-by: Minas Giannekas * chore: repository, homepage fields * chore: update readme * feat(starter_app): Version 1.1.0 * feat(starter_app): multi-window support * feat: starter_app 1.2.1 * chore: move brick to its own repo & go back to old pana action * Expand remaining part of row in MacosListTile (#265) * Expand remaining part of row https://github.com/GroovinChip/macos_ui/issues/264 * Increment to version 1.4.2 * End sidebar (#267) * chore: add missing trailing comma * chore: improve MacosIconButton animation curve * chore: remove false_secrets from pubspec.yaml * feat: end sidebar Also fixes the tests portion of the pr_prelaunch_tasks script * feat: add "isEndSidebarShown" to MacosWindowScope * fix: Correct the placement of the leading widget in disclosure sidebar items (#272) * chore: Update changelog * test: fix issues with date_picker_test * Account for cases where the month and the day are the same * Fix offstage warnings by removing tester taps that disabled the caret controls * Update Actions (#279) * Update flutter_analysis.yml * Update dart_code_metrics.yaml * Update gh_pages.yml * Update pana_analysis.yml * Update codecov.yaml * fix syntax issue * Version 1.6.0 - `MacosTabView` & `MacosSegmentedControl` (#273) * feat: MacosTabView & MacosSegmentedControl * chore: fixup scripts * test: tests for segmented control & tab view * chore: remove unused code * chore: run flutter format . * chore: bump code metrics * docs: dartdoc updates * docs: fix a documentation error * chore: run flutter format . * refactor: make active property of MacosTab optional, since it is handled via MacosSegmentedControl * chore: fix import change * refactor: change colors to match default native app design * docs: update tab view screenshot in readme * chore: update README example for MacosTabView * chore: fix typo in MacosSegmentedControl * chore: fix typo in MacosSegmentedControl docstring * test: remove explicitly setting active property of MacosTabs Co-authored-by: Minas Giannekas * Version 1.7.0: `MacosImageIcon` & sidebar updates (#274) * feat: MacosTabView & MacosSegmentedControl * chore: fixup scripts * test: tests for segmented control & tab view * chore: remove unused code * chore: run flutter format . * chore: bump code metrics * docs: dartdoc updates * docs: fix a documentation error * chore: run flutter format . * feat: MacosImageIcon & sidebar updates * test: fix issues with date_picker_test * Account for cases where the month and the day are the same * Fix offstage warnings by removing tester taps that disabled the caret controls * refactor: make active property of MacosTab optional, since it is handled via MacosSegmentedControl * chore: fix import change * refactor: change colors to match default native app design * docs: update tab view screenshot in readme * chore: fix README * test: fix date picker test Co-authored-by: Minas Giannekas * chore: fix typo in pr template * feat: gh action to auto-generate releases on push to stable * chore: update release action with latest from stable * feat: add action to publish to pub * docs: update readme * Addresses #237 * Adds MacosColorWell to selectors section * Adds code snippets for date & time pickers * fix: 1.7.1 Fixes issue where end sidebar window breakpoint wasn’t being respected * Tab view padding (#285) * fix: use prepared title wrapped with a DefaultTextStyle instead of the raw title (#289) * chore: fix typo Closes #290 * feat: add `backgroundColor` to `MacosSheet` (#291) * chore: fix Flutter 3.3 warnings * fix: address ScrollController bug in MacosPopupButton (#300) * fix(tests): account for Jan -> Dec & Dec -> Jan date_picker_test.dart was failing due to not accounting for going from January to December and vice-versa. * fix(plugin): Ensure the native color panel releases when closed * Update flutter_analysis.yml Closes #334 * Various bug fixes & minor updates (#338) * Macos slider (#337) * chore: run flutter format . * chore: fix analysis * chore: Bump version and update CHANGELOG.md * chore: Update images to self taken ones as MacOS images are outdated * fix: fix position offset by a small value * fix: PR review feedback * Update lib/src/indicators/slider.dart --------- Co-authored-by: Reuben Turner --------- Co-authored-by: Minas Giannekas Co-authored-by: Jon Saw Co-authored-by: Minas Giannekas Co-authored-by: st merlhin <77164238+stMerlHin@users.noreply.github.com> Co-authored-by: jtdLab <72231111+jtdLab@users.noreply.github.com> Co-authored-by: Norbert Kozsir --- .github/workflows/flutter_analysis.yml | 2 +- CHANGELOG.md | 16 + README.md | 36 +- example/lib/main.dart | 6 +- example/lib/pages/buttons_page.dart | 12 +- example/lib/pages/colors_page.dart | 616 +++++++++--------- example/lib/pages/dialogs_page.dart | 267 ++++---- example/lib/pages/fields_page.dart | 175 ++--- example/lib/pages/indicators_page.dart | 91 +-- example/lib/pages/selectors_page.dart | 3 +- example/lib/pages/tabview_page.dart | 2 +- example/lib/pages/toolbar_page.dart | 3 +- example/macos/Podfile | 2 +- example/macos/Podfile.lock | 4 +- .../macos/Runner.xcodeproj/project.pbxproj | 9 +- example/macos/Runner/MainFlutterWindow.swift | 3 +- example/pubspec.lock | 104 +-- lib/macos_ui.dart | 1 + lib/src/fields/search_field.dart | 2 +- lib/src/fields/text_field.dart | 59 +- lib/src/indicators/scrollbar.dart | 4 +- lib/src/indicators/slider.dart | 373 +++++++++++ lib/src/labels/tooltip.dart | 3 +- lib/src/layout/content_area.dart | 13 +- lib/src/layout/sidebar/sidebar_items.dart | 2 +- lib/src/layout/window.dart | 6 +- lib/src/library.dart | 3 +- lib/src/theme/macos_colors.dart | 19 + macos/Classes/ColorPanelProvider.swift | 1 + pr_prelaunch_tasks.sh | 4 +- pubspec.lock | 332 ++++++---- pubspec.yaml | 2 +- test/buttons/checkbox_test.dart | 2 +- test/buttons/help_button_test.dart | 4 +- test/buttons/icon_button_test.dart | 4 +- test/buttons/popup_button_test.dart | 2 +- test/buttons/pulldown_button_test.dart | 4 +- test/buttons/push_button_test.dart | 4 +- test/buttons/radio_button_test.dart | 4 +- test/buttons/segmented_control_test.dart | 4 +- test/buttons/switch_test.dart | 2 +- test/fields/search_field_test.dart | 2 +- test/fields/text_field_test.dart | 2 +- test/indicators/slider_test.dart | 114 ++++ test/layout/macos_list_tile_test.dart | 4 +- test/layout/resizeable_pane_test.dart | 3 +- test/layout/tab_view_test.dart | 2 +- test/selectors/date_picker_test.dart | 12 +- test/theme/help_button_theme_test.dart | 2 +- test/theme/icon_button_theme_test.dart | 2 +- test/theme/icon_theme_test.dart | 2 +- test/theme/popup_button_theme_test.dart | 4 +- test/theme/pulldown_button_theme_test.dart | 2 +- test/theme/push_button_theme_test.dart | 2 +- test/theme/search_field_theme_test.dart | 2 +- 55 files changed, 1526 insertions(+), 834 deletions(-) create mode 100644 lib/src/indicators/slider.dart create mode 100644 test/indicators/slider_test.dart diff --git a/.github/workflows/flutter_analysis.yml b/.github/workflows/flutter_analysis.yml index a9686ffd..29e896de 100644 --- a/.github/workflows/flutter_analysis.yml +++ b/.github/workflows/flutter_analysis.yml @@ -16,7 +16,7 @@ jobs: run: flutter pub get - name: Format code - run: flutter format --set-exit-if-changed . + run: dart format --set-exit-if-changed . - name: Analyze code run: flutter analyze --fatal-infos . diff --git a/CHANGELOG.md b/CHANGELOG.md index 06984cb8..97e63f9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## [1.9.0] +* Implement `MacosSlider` + +## [1.8.0] +🚨 Breaking Changes 🚨 +* `ContentArea.builder` has been changed from a `ScrollableWidgetBuilder` to a `WidgetBuilder` due to +changes in Flutter 3.7. The `MacosScrollBar` widget needs to undergo radical changes in order to achieve the +native macOS scrollbar look and feel in the future, so this will be revisited at that time. + +Other changes +* Per Flutter 3.7.0: Replace deprecated `MacosTextField.toolbarOptions` with `MacosTextField.contextMenuBuilder` +* Ensure the color panel releases when it is closed +* Avoid render overflows in the `Sidebar` when the window height is resized below a certain threshold ([#325](https://github.com/GroovinChip/macos_ui/issues/325)) +* Update `MacosScrollBar.thumbVisibility` with the latest change introduced in Flutter 3.7 +* Update `README.md` to address issues [#325](https://github.com/GroovinChip/macos_ui/issues/325) & [#332](https://github.com/GroovinChip/macos_ui/issues/332) + ## [1.7.6] * Fixed a bug where `MacosPopupButton` would report that a `ScrollController` was not attached to any views diff --git a/README.md b/README.md index 5951a0a3..f88241c4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,9 @@ Guides, codelabs, and other documentation can be found at https://macosui.dev -## 🚨 Usage notes +## 🚨 Usage notes +### Platform Compatibility + pub.dev shows that `macos_ui` only supports macOS. This is because `macos_ui` calls some native code, and therefore specifies macOS as a plugin platform in the `pubspec.yaml` file. `macos_ui` _will_ work on any platform that Flutter supports, **but you will get best results on macOS**. @@ -25,6 +27,14 @@ The features of `macos_ui` that will _not_ work on platforms other than macOS du * The `MacosColors.controlAccentColor()` function * The `MacosColorWell` widget +### Popups & window resizing + +Since at this time Flutter does not allow UI elements to overflow the bounds of the window, popups are constrained to +the available space. + +Therefore, if you are using widgets that create popups in your toolbar, like `ToolBarPopupButton`, you +should avoid allowing your application window to be resized below the height of your tallest popup. + ## Contents
@@ -196,6 +206,7 @@ class BlurryContainerViewController: NSViewController { self.addChild(flutterViewController) flutterViewController.view.frame = self.view.bounds ++ flutterViewController.backgroundColor = .clear // **Required post-Flutter 3.7.0** flutterViewController.view.autoresizingMask = [.width, .height] self.view.addSubview(flutterViewController.view) } @@ -847,6 +858,29 @@ CapacityIndicator( You can set `discrete` to `true` to make it a discrete capacity indicator. +### MacosSlider + +A slider is a control that lets people select a value from a continuous or discrete range of values by moving the slider thumb. + + Continuous | Discrete | +|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| ![Continuous Slider Example](https://i.imgur.com/dc4YjoX.png) | ![Discrete Slider Example](https://i.imgur.com/KckOTUf.png) | +| A horizontal slider where any value continuous value between a min and max can be selected | A horizontal slider where only discrete values between a min and max can be selected. Tick marks are often displayed to provide context. | + + +Here's an example of how to create an interactive continuous slider: + +```dart +double value = 0.5; + +MacosSlider( + value: value, + onChanged: (v) { + setState(() => value = v); + }, +), +``` + ### RatingIndicator A rating indicator uses a series of horizontally arranged graphical symbols to communicate a ranking level. The default diff --git a/example/lib/main.dart b/example/lib/main.dart index caca0fda..0b33c9af 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -171,11 +171,11 @@ class _WidgetGalleryState extends State { ], ), minWidth: 200, - builder: (context, controller) { + builder: (context, _) { return SidebarItems( currentIndex: pageIndex, onChanged: (i) => setState(() => pageIndex = i), - scrollController: controller, + scrollController: ScrollController(), itemSize: SidebarItemSize.large, items: [ const SidebarItem( @@ -263,7 +263,7 @@ class _WidgetGalleryState extends State { minWidth: 200, maxWidth: 300, shownByDefault: false, - builder: (context, scrollController) { + builder: (context, _) { return const Center( child: Text('End Sidebar'), ); diff --git a/example/lib/pages/buttons_page.dart b/example/lib/pages/buttons_page.dart index 22b03b57..29722f3b 100644 --- a/example/lib/pages/buttons_page.dart +++ b/example/lib/pages/buttons_page.dart @@ -70,8 +70,9 @@ class _ButtonsPageState extends State { }, ), ContentArea( - builder: (context, scrollController) { + builder: (context) { return SingleChildScrollView( + // controller: _, padding: const EdgeInsets.all(20), child: Column( children: [ @@ -140,23 +141,22 @@ class _ButtonsPageState extends State { buttonSize: ButtonSize.small, child: const Text('Small'), onPressed: () { - Navigator.push( - context, + Navigator.of(context).push( MaterialPageRoute( builder: (_) { return MacosScaffold( toolBar: const ToolBar( - title: Text("New page"), + title: Text('New page'), ), children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: PushButton( buttonSize: ButtonSize.large, child: const Text('Go Back'), onPressed: () { - Navigator.maybePop(context); + Navigator.of(context).maybePop(); }, ), ); diff --git a/example/lib/pages/colors_page.dart b/example/lib/pages/colors_page.dart index 54362098..37bc59f2 100644 --- a/example/lib/pages/colors_page.dart +++ b/example/lib/pages/colors_page.dart @@ -27,313 +27,315 @@ class _ColorsPageState extends State { ], ), children: [ - ContentArea(builder: (context, scrollController) { - return SingleChildScrollView( - controller: scrollController, - padding: const EdgeInsets.all(20), - child: Column( - children: [ - Wrap( - spacing: 8.0, - runSpacing: 8.0, - children: [ - const MacosTooltip( - message: 'System Red', - child: ColorBox( - color: MacosColors.systemRedColor, - ), - ), - MacosTooltip( - message: 'System Red Dark', - child: ColorBox( - color: MacosColors.systemRedColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Green', - child: ColorBox( - color: MacosColors.systemGreenColor, - ), - ), - MacosTooltip( - message: 'System Green Dark', - child: ColorBox( - color: MacosColors.systemGreenColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Blue', - child: ColorBox( - color: MacosColors.systemBlueColor, - ), - ), - MacosTooltip( - message: 'System Blue Dark', - child: ColorBox( - color: MacosColors.systemBlueColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Orange', - child: ColorBox( - color: MacosColors.systemOrangeColor, - ), - ), - MacosTooltip( - message: 'System Orange Dark', - child: ColorBox( - color: MacosColors.systemOrangeColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Yellow', - child: ColorBox( - color: MacosColors.systemYellowColor, - ), - ), - MacosTooltip( - message: 'System Yellow Dark', - child: ColorBox( - color: MacosColors.systemYellowColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Brown', - child: ColorBox( - color: MacosColors.systemBrownColor, - ), - ), - MacosTooltip( - message: 'System Brown Dark', - child: ColorBox( - color: MacosColors.systemBrownColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Pink', - child: ColorBox( - color: MacosColors.systemPinkColor, - ), - ), - MacosTooltip( - message: 'System Pink Dark', - child: ColorBox( - color: MacosColors.systemPinkColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Purple', - child: ColorBox( - color: MacosColors.systemPurpleColor, - ), - ), - MacosTooltip( - message: 'System Purple Dark', - child: ColorBox( - color: MacosColors.systemPurpleColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Teal', - child: ColorBox( - color: MacosColors.systemTealColor, - ), - ), - MacosTooltip( - message: 'System Teal Dark', - child: ColorBox( - color: MacosColors.systemTealColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Indigo', - child: ColorBox( - color: MacosColors.systemIndigoColor, - ), - ), - MacosTooltip( - message: 'System Indigo Dark', - child: ColorBox( - color: MacosColors.systemIndigoColor.darkColor, - ), - ), - const MacosTooltip( - message: 'System Gray', - child: ColorBox( - color: MacosColors.systemGrayColor, - ), - ), - MacosTooltip( - message: 'System Gray Dark', - child: ColorBox( - color: MacosColors.systemGrayColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Link', - child: ColorBox( - color: MacosColors.linkColor, - ), - ), - MacosTooltip( - message: 'Link Dark', - child: ColorBox( - color: MacosColors.linkColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Unemphasized Background', - child: ColorBox( - color: - MacosColors.unemphasizedSelectedTextBackgroundColor, - ), - ), - MacosTooltip( - message: 'Unemphasized Background Dark', - child: ColorBox( - color: MacosColors - .unemphasizedSelectedTextBackgroundColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Control Background', - child: ColorBox( - color: MacosColors.controlBackgroundColor, - ), - ), - MacosTooltip( - message: 'Control Background Dark', - child: ColorBox( - color: MacosColors.controlBackgroundColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Control', - child: ColorBox( - color: MacosColors.controlColor, - ), - ), - MacosTooltip( - message: 'Control Dark', - child: ColorBox( - color: MacosColors.controlColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Control Text', - child: ColorBox( - color: MacosColors.controlTextColor, - ), - ), - MacosTooltip( - message: 'Control Text Dark', - child: ColorBox( - color: MacosColors.controlTextColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Control Text Disabled', - child: ColorBox( - color: MacosColors.disabledControlTextColor, - ), - ), - MacosTooltip( - message: 'Control Text Disabled Dark', - child: ColorBox( - color: MacosColors.disabledControlTextColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Selected Control', - child: ColorBox( - color: MacosColors.selectedControlColor, - ), - ), - MacosTooltip( - message: 'Selected Control Dark', - child: ColorBox( - color: MacosColors.selectedControlColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Selected Control Text', - child: ColorBox( - color: MacosColors.selectedControlTextColor, - ), - ), - MacosTooltip( - message: 'Selected Control Text Dark', - child: ColorBox( - color: MacosColors.selectedControlTextColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Keyboard Focus Indicator', - child: ColorBox( - color: MacosColors.keyboardFocusIndicatorColor, - ), - ), - MacosTooltip( - message: 'Keyboard Focus Indicator', - child: ColorBox( - color: - MacosColors.keyboardFocusIndicatorColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Label', - child: ColorBox( - color: MacosColors.labelColor, - ), - ), - MacosTooltip( - message: 'Label Dark', - child: ColorBox( - color: MacosColors.labelColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Secondary Label', - child: ColorBox( - color: MacosColors.secondaryLabelColor, - ), - ), - MacosTooltip( - message: 'Secondary Label Dark', - child: ColorBox( - color: MacosColors.secondaryLabelColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Tertiary Label', - child: ColorBox( - color: MacosColors.tertiaryLabelColor, - ), - ), - MacosTooltip( - message: 'Tertiary Label Dark', - child: ColorBox( - color: MacosColors.tertiaryLabelColor.darkColor, - ), - ), - const MacosTooltip( - message: 'Quaternary Label', - child: ColorBox( - color: MacosColors.quaternaryLabelColor, - ), - ), - MacosTooltip( - message: 'Quaternary Label Dark', - child: ColorBox( - color: MacosColors.quaternaryLabelColor.darkColor, - ), - ), - ], - ), - ], - ), - ); - }), + ContentArea( + builder: (context) { + return SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: [ + const MacosTooltip( + message: 'System Red', + child: ColorBox( + color: MacosColors.systemRedColor, + ), + ), + MacosTooltip( + message: 'System Red Dark', + child: ColorBox( + color: MacosColors.systemRedColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Green', + child: ColorBox( + color: MacosColors.systemGreenColor, + ), + ), + MacosTooltip( + message: 'System Green Dark', + child: ColorBox( + color: MacosColors.systemGreenColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Blue', + child: ColorBox( + color: MacosColors.systemBlueColor, + ), + ), + MacosTooltip( + message: 'System Blue Dark', + child: ColorBox( + color: MacosColors.systemBlueColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Orange', + child: ColorBox( + color: MacosColors.systemOrangeColor, + ), + ), + MacosTooltip( + message: 'System Orange Dark', + child: ColorBox( + color: MacosColors.systemOrangeColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Yellow', + child: ColorBox( + color: MacosColors.systemYellowColor, + ), + ), + MacosTooltip( + message: 'System Yellow Dark', + child: ColorBox( + color: MacosColors.systemYellowColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Brown', + child: ColorBox( + color: MacosColors.systemBrownColor, + ), + ), + MacosTooltip( + message: 'System Brown Dark', + child: ColorBox( + color: MacosColors.systemBrownColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Pink', + child: ColorBox( + color: MacosColors.systemPinkColor, + ), + ), + MacosTooltip( + message: 'System Pink Dark', + child: ColorBox( + color: MacosColors.systemPinkColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Purple', + child: ColorBox( + color: MacosColors.systemPurpleColor, + ), + ), + MacosTooltip( + message: 'System Purple Dark', + child: ColorBox( + color: MacosColors.systemPurpleColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Teal', + child: ColorBox( + color: MacosColors.systemTealColor, + ), + ), + MacosTooltip( + message: 'System Teal Dark', + child: ColorBox( + color: MacosColors.systemTealColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Indigo', + child: ColorBox( + color: MacosColors.systemIndigoColor, + ), + ), + MacosTooltip( + message: 'System Indigo Dark', + child: ColorBox( + color: MacosColors.systemIndigoColor.darkColor, + ), + ), + const MacosTooltip( + message: 'System Gray', + child: ColorBox( + color: MacosColors.systemGrayColor, + ), + ), + MacosTooltip( + message: 'System Gray Dark', + child: ColorBox( + color: MacosColors.systemGrayColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Link', + child: ColorBox( + color: MacosColors.linkColor, + ), + ), + MacosTooltip( + message: 'Link Dark', + child: ColorBox( + color: MacosColors.linkColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Unemphasized Background', + child: ColorBox( + color: MacosColors + .unemphasizedSelectedTextBackgroundColor, + ), + ), + MacosTooltip( + message: 'Unemphasized Background Dark', + child: ColorBox( + color: MacosColors + .unemphasizedSelectedTextBackgroundColor + .darkColor, + ), + ), + const MacosTooltip( + message: 'Control Background', + child: ColorBox( + color: MacosColors.controlBackgroundColor, + ), + ), + MacosTooltip( + message: 'Control Background Dark', + child: ColorBox( + color: MacosColors.controlBackgroundColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Control', + child: ColorBox( + color: MacosColors.controlColor, + ), + ), + MacosTooltip( + message: 'Control Dark', + child: ColorBox( + color: MacosColors.controlColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Control Text', + child: ColorBox( + color: MacosColors.controlTextColor, + ), + ), + MacosTooltip( + message: 'Control Text Dark', + child: ColorBox( + color: MacosColors.controlTextColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Control Text Disabled', + child: ColorBox( + color: MacosColors.disabledControlTextColor, + ), + ), + MacosTooltip( + message: 'Control Text Disabled Dark', + child: ColorBox( + color: MacosColors.disabledControlTextColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Selected Control', + child: ColorBox( + color: MacosColors.selectedControlColor, + ), + ), + MacosTooltip( + message: 'Selected Control Dark', + child: ColorBox( + color: MacosColors.selectedControlColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Selected Control Text', + child: ColorBox( + color: MacosColors.selectedControlTextColor, + ), + ), + MacosTooltip( + message: 'Selected Control Text Dark', + child: ColorBox( + color: MacosColors.selectedControlTextColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Keyboard Focus Indicator', + child: ColorBox( + color: MacosColors.keyboardFocusIndicatorColor, + ), + ), + MacosTooltip( + message: 'Keyboard Focus Indicator', + child: ColorBox( + color: + MacosColors.keyboardFocusIndicatorColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Label', + child: ColorBox( + color: MacosColors.labelColor, + ), + ), + MacosTooltip( + message: 'Label Dark', + child: ColorBox( + color: MacosColors.labelColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Secondary Label', + child: ColorBox( + color: MacosColors.secondaryLabelColor, + ), + ), + MacosTooltip( + message: 'Secondary Label Dark', + child: ColorBox( + color: MacosColors.secondaryLabelColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Tertiary Label', + child: ColorBox( + color: MacosColors.tertiaryLabelColor, + ), + ), + MacosTooltip( + message: 'Tertiary Label Dark', + child: ColorBox( + color: MacosColors.tertiaryLabelColor.darkColor, + ), + ), + const MacosTooltip( + message: 'Quaternary Label', + child: ColorBox( + color: MacosColors.quaternaryLabelColor, + ), + ), + MacosTooltip( + message: 'Quaternary Label Dark', + child: ColorBox( + color: MacosColors.quaternaryLabelColor.darkColor, + ), + ), + ], + ), + ], + ), + ); + }, + ), ], ); } diff --git a/example/lib/pages/dialogs_page.dart b/example/lib/pages/dialogs_page.dart index 8e89d7e6..53db5028 100644 --- a/example/lib/pages/dialogs_page.dart +++ b/example/lib/pages/dialogs_page.dart @@ -28,152 +28,153 @@ class _DialogsPageState extends State { ], ), children: [ - ContentArea(builder: (context, scrollController) { - return SingleChildScrollView( - controller: scrollController, - padding: const EdgeInsets.all(20), - child: Center( - child: Column( - children: [ - PushButton( - buttonSize: ButtonSize.large, - child: const Text('Show Alert Dialog 1'), - onPressed: () => showMacosAlertDialog( - context: context, - builder: (context) => MacosAlertDialog( - appIcon: const FlutterLogo( - size: 56, - ), - title: const Text( - 'Alert Dialog with Primary Action', - ), - message: const Text( - 'This is an alert dialog with a primary action and no secondary action', - ), - //horizontalActions: false, - primaryButton: PushButton( - buttonSize: ButtonSize.large, - onPressed: Navigator.of(context).pop, - child: const Text('Primary'), + ContentArea( + builder: (context) { + return SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Center( + child: Column( + children: [ + PushButton( + buttonSize: ButtonSize.large, + child: const Text('Show Alert Dialog 1'), + onPressed: () => showMacosAlertDialog( + context: context, + builder: (context) => MacosAlertDialog( + appIcon: const FlutterLogo( + size: 56, + ), + title: const Text( + 'Alert Dialog with Primary Action', + ), + message: const Text( + 'This is an alert dialog with a primary action and no secondary action', + ), + //horizontalActions: false, + primaryButton: PushButton( + buttonSize: ButtonSize.large, + onPressed: Navigator.of(context).pop, + child: const Text('Primary'), + ), ), ), ), - ), - const SizedBox(height: 16), - PushButton( - buttonSize: ButtonSize.large, - child: const Text('Show Alert Dialog 2'), - onPressed: () => showMacosAlertDialog( - context: context, - builder: (context) => MacosAlertDialog( - appIcon: const FlutterLogo( - size: 56, - ), - title: const Text( - 'Alert Dialog with Secondary Action', - ), - message: const Text( - 'This is an alert dialog with primary action and secondary action laid out horizontally', - textAlign: TextAlign.center, - ), - //horizontalActions: false, - primaryButton: PushButton( - buttonSize: ButtonSize.large, - onPressed: Navigator.of(context).pop, - child: const Text('Primary'), - ), - secondaryButton: PushButton( - buttonSize: ButtonSize.large, - isSecondary: true, - onPressed: Navigator.of(context).pop, - child: const Text('Secondary'), + const SizedBox(height: 16), + PushButton( + buttonSize: ButtonSize.large, + child: const Text('Show Alert Dialog 2'), + onPressed: () => showMacosAlertDialog( + context: context, + builder: (context) => MacosAlertDialog( + appIcon: const FlutterLogo( + size: 56, + ), + title: const Text( + 'Alert Dialog with Secondary Action', + ), + message: const Text( + 'This is an alert dialog with primary action and secondary action laid out horizontally', + textAlign: TextAlign.center, + ), + //horizontalActions: false, + primaryButton: PushButton( + buttonSize: ButtonSize.large, + onPressed: Navigator.of(context).pop, + child: const Text('Primary'), + ), + secondaryButton: PushButton( + buttonSize: ButtonSize.large, + isSecondary: true, + onPressed: Navigator.of(context).pop, + child: const Text('Secondary'), + ), ), ), ), - ), - const SizedBox(height: 16), - PushButton( - buttonSize: ButtonSize.large, - child: const Text('Show Alert Dialog 3'), - onPressed: () => showMacosAlertDialog( - context: context, - builder: (context) => MacosAlertDialog( - appIcon: const FlutterLogo( - size: 56, - ), - title: const Text( - 'Alert Dialog with Secondary Action', - ), - message: const Text( - 'This is an alert dialog with primary action and secondary action laid out vertically', - textAlign: TextAlign.center, - ), - horizontalActions: false, - primaryButton: PushButton( - buttonSize: ButtonSize.large, - onPressed: Navigator.of(context).pop, - child: const Text('Primary'), - ), - secondaryButton: PushButton( - buttonSize: ButtonSize.large, - isSecondary: true, - onPressed: Navigator.of(context).pop, - child: const Text('Secondary'), + const SizedBox(height: 16), + PushButton( + buttonSize: ButtonSize.large, + child: const Text('Show Alert Dialog 3'), + onPressed: () => showMacosAlertDialog( + context: context, + builder: (context) => MacosAlertDialog( + appIcon: const FlutterLogo( + size: 56, + ), + title: const Text( + 'Alert Dialog with Secondary Action', + ), + message: const Text( + 'This is an alert dialog with primary action and secondary action laid out vertically', + textAlign: TextAlign.center, + ), + horizontalActions: false, + primaryButton: PushButton( + buttonSize: ButtonSize.large, + onPressed: Navigator.of(context).pop, + child: const Text('Primary'), + ), + secondaryButton: PushButton( + buttonSize: ButtonSize.large, + isSecondary: true, + onPressed: Navigator.of(context).pop, + child: const Text('Secondary'), + ), ), ), ), - ), - const SizedBox(height: 16), - PushButton( - buttonSize: ButtonSize.large, - child: const Text('Show Alert Dialog 4'), - onPressed: () => showMacosAlertDialog( - context: context, - builder: (context) => MacosAlertDialog( - appIcon: const FlutterLogo( - size: 56, - ), - title: const Text( - 'Alert Dialog with Secondary Action', - ), - message: const Text( - 'This is an alert dialog with primary action and secondary ' - 'action laid out vertically. It also contains a "suppress" option.', - textAlign: TextAlign.center, - ), - horizontalActions: false, - primaryButton: PushButton( - buttonSize: ButtonSize.large, - onPressed: Navigator.of(context).pop, - child: const Text('Primary'), - ), - secondaryButton: PushButton( - buttonSize: ButtonSize.large, - isSecondary: true, - onPressed: Navigator.of(context).pop, - child: const Text('Secondary'), + const SizedBox(height: 16), + PushButton( + buttonSize: ButtonSize.large, + child: const Text('Show Alert Dialog 4'), + onPressed: () => showMacosAlertDialog( + context: context, + builder: (context) => MacosAlertDialog( + appIcon: const FlutterLogo( + size: 56, + ), + title: const Text( + 'Alert Dialog with Secondary Action', + ), + message: const Text( + 'This is an alert dialog with primary action and secondary ' + 'action laid out vertically. It also contains a "suppress" option.', + textAlign: TextAlign.center, + ), + horizontalActions: false, + primaryButton: PushButton( + buttonSize: ButtonSize.large, + onPressed: Navigator.of(context).pop, + child: const Text('Primary'), + ), + secondaryButton: PushButton( + buttonSize: ButtonSize.large, + isSecondary: true, + onPressed: Navigator.of(context).pop, + child: const Text('Secondary'), + ), + suppress: const DoNotNotifyRow(), ), - suppress: const DoNotNotifyRow(), ), ), - ), - const SizedBox(height: 16), - PushButton( - buttonSize: ButtonSize.large, - child: const Text('Show sheet'), - onPressed: () { - showMacosSheet( - context: context, - barrierDismissible: true, - builder: (_) => const DemoSheet(), - ); - }, - ), - ], + const SizedBox(height: 16), + PushButton( + buttonSize: ButtonSize.large, + child: const Text('Show sheet'), + onPressed: () { + showMacosSheet( + context: context, + barrierDismissible: true, + builder: (_) => const DemoSheet(), + ); + }, + ), + ], + ), ), - ), - ); - }), + ); + }, + ), ], ); } diff --git a/example/lib/pages/fields_page.dart b/example/lib/pages/fields_page.dart index 14be06fb..e7865f98 100644 --- a/example/lib/pages/fields_page.dart +++ b/example/lib/pages/fields_page.dart @@ -27,101 +27,104 @@ class _FieldsPageState extends State { ], ), children: [ - ContentArea(builder: (context, scrollController) { - return SingleChildScrollView( - padding: const EdgeInsets.all(20), - child: Column( - children: [ - const SizedBox( - width: 300.0, - child: MacosTextField( - placeholder: 'Type some text here', - maxLines: 1, + ContentArea( + builder: (context) { + return SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + const SizedBox( + width: 300.0, + child: MacosTextField( + placeholder: 'Type some text here', + maxLines: 1, + ), ), - ), - const SizedBox(height: 20), - const SizedBox( - width: 300.0, - child: MacosTextField( - prefix: MacosIcon(CupertinoIcons.money_dollar), - placeholder: 'Type some text here', + const SizedBox(height: 20), + const SizedBox( + width: 300.0, + child: MacosTextField( + prefix: MacosIcon(CupertinoIcons.money_dollar), + placeholder: 'Type some text here', - /// If both suffix and clear button mode is provided, - /// suffix will override the clear button. - // suffix: Text('SUFFIX'), - clearButtonMode: OverlayVisibilityMode.always, - maxLines: 1, + /// If both suffix and clear button mode is provided, + /// suffix will override the clear button. + // suffix: Text('SUFFIX'), + clearButtonMode: OverlayVisibilityMode.always, + maxLines: 1, + ), ), - ), - const SizedBox(height: 20), - const SizedBox( - width: 300.0, - child: MacosTextField.borderless( - prefix: MacosIcon(CupertinoIcons.search), - placeholder: 'Type some text here', + const SizedBox(height: 20), + const SizedBox( + width: 300.0, + child: MacosTextField.borderless( + prefix: MacosIcon(CupertinoIcons.search), + placeholder: 'Type some text here', - /// If both suffix and clear button mode is provided, - /// suffix will override the clear button. - suffix: Text('SUFFIX'), - // clearButtonMode: OverlayVisibilityMode.always, - maxLines: 1, + /// If both suffix and clear button mode is provided, + /// suffix will override the clear button. + suffix: Text('SUFFIX'), + // clearButtonMode: OverlayVisibilityMode.always, + maxLines: 1, + ), ), - ), - const SizedBox(height: 20), - const SizedBox( - width: 300.0, - child: MacosTextField( - enabled: false, - prefix: MacosIcon(CupertinoIcons.search), - placeholder: 'Disabled field', + const SizedBox(height: 20), + const SizedBox( + width: 300.0, + child: MacosTextField( + enabled: false, + prefix: MacosIcon(CupertinoIcons.search), + placeholder: 'Disabled field', - /// If both suffix and clear button mode is provided, - /// suffix will override the clear button. - // suffix: Text('SUFFIX'), - clearButtonMode: OverlayVisibilityMode.always, - maxLines: 1, + /// If both suffix and clear button mode is provided, + /// suffix will override the clear button. + // suffix: Text('SUFFIX'), + clearButtonMode: OverlayVisibilityMode.always, + maxLines: 1, + ), ), - ), - const SizedBox(height: 20), - SizedBox( - width: 300.0, - child: MacosSearchField( - results: countries.map((e) => SearchResultItem(e)).toList(), - placeholder: 'Search for a country...', - onResultSelected: (resultItem) { - // Retrieve the user-selected search suggestion via its - // searchKey property. - debugPrint(resultItem.searchKey); - }, - onChanged: (searchQuery) => debugPrint(searchQuery), + const SizedBox(height: 20), + SizedBox( + width: 300.0, + child: MacosSearchField( + results: + countries.map((e) => SearchResultItem(e)).toList(), + placeholder: 'Search for a country...', + onResultSelected: (resultItem) { + // Retrieve the user-selected search suggestion via its + // searchKey property. + debugPrint(resultItem.searchKey); + }, + onChanged: (searchQuery) => debugPrint(searchQuery), + ), ), - ), - const SizedBox(height: 20), - SizedBox( - width: 300.0, - // Example of search field with custom SearchResultItems - // and height. - child: MacosSearchField( - results: actionResults, - resultHeight: 40.0, - emptyWidget: const Center( - child: Padding( - padding: EdgeInsets.all(8.0), - child: Text("No action found!"), - )), - placeholder: 'Search for an action...', - onResultSelected: (resultItem) { - // Retrieve the user-selected search suggestion via its - // searchKey property. - debugPrint(resultItem.searchKey); - }, - onChanged: (searchQuery) => debugPrint(searchQuery), + const SizedBox(height: 20), + SizedBox( + width: 300.0, + // Example of search field with custom SearchResultItems + // and height. + child: MacosSearchField( + results: actionResults, + resultHeight: 40.0, + emptyWidget: const Center( + child: Padding( + padding: EdgeInsets.all(8.0), + child: Text("No action found!"), + )), + placeholder: 'Search for an action...', + onResultSelected: (resultItem) { + // Retrieve the user-selected search suggestion via its + // searchKey property. + debugPrint(resultItem.searchKey); + }, + onChanged: (searchQuery) => debugPrint(searchQuery), + ), ), - ), - ], - ), - ); - }), + ], + ), + ); + }, + ), ResizablePane( minWidth: 180, startWidth: 200, diff --git a/example/lib/pages/indicators_page.dart b/example/lib/pages/indicators_page.dart index 506f961d..58a6d391 100644 --- a/example/lib/pages/indicators_page.dart +++ b/example/lib/pages/indicators_page.dart @@ -11,7 +11,8 @@ class IndicatorsPage extends StatefulWidget { class _IndicatorsPageState extends State { double ratingValue = 0; - double sliderValue = 0; + double capacitorValue = 0; + double sliderValue = 0.3; @override Widget build(BuildContext context) { @@ -31,44 +32,56 @@ class _IndicatorsPageState extends State { ], ), children: [ - ContentArea(builder: (context, scrollController) { - return SingleChildScrollView( - padding: const EdgeInsets.all(20), - controller: scrollController, - child: Column( - children: [ - CapacityIndicator( - value: sliderValue, - onChanged: (v) => setState(() => sliderValue = v), - discrete: true, - ), - const SizedBox(height: 20), - CapacityIndicator( - value: sliderValue, - onChanged: (v) => setState(() => sliderValue = v), - ), - const SizedBox(height: 20), - RatingIndicator( - value: ratingValue, - onChanged: (v) => setState(() => ratingValue = v), - ), - const SizedBox(height: 20), - const ProgressCircle(), - const SizedBox(height: 20), - const RelevanceIndicator( - value: 25, - amount: 50, - ), - const SizedBox(height: 20), - const Label( - icon: MacosIcon(CupertinoIcons.tag), - text: SelectableText('A determinate progress circle: '), - child: ProgressCircle(value: 50), - ), - ], - ), - ); - }), + ContentArea( + builder: (context) { + return SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Column( + children: [ + CapacityIndicator( + value: sliderValue, + onChanged: (v) => setState(() => sliderValue = v), + discrete: true, + ), + const SizedBox(height: 20), + CapacityIndicator( + value: sliderValue, + onChanged: (v) => setState(() => sliderValue = v), + ), + const SizedBox(height: 20), + MacosSlider( + value: sliderValue, + onChanged: (v) => setState(() => sliderValue = v), + ), + const SizedBox(height: 20), + MacosSlider( + value: sliderValue, + discrete: true, + onChanged: (v) => setState(() => sliderValue = v), + ), + const SizedBox(height: 20), + RatingIndicator( + value: ratingValue, + onChanged: (v) => setState(() => ratingValue = v), + ), + const SizedBox(height: 20), + const ProgressCircle(), + const SizedBox(height: 20), + const RelevanceIndicator( + value: 25, + amount: 50, + ), + const SizedBox(height: 20), + const Label( + icon: MacosIcon(CupertinoIcons.tag), + text: SelectableText('A determinate progress circle: '), + child: ProgressCircle(value: 50), + ), + ], + ), + ); + }, + ), ], ); } diff --git a/example/lib/pages/selectors_page.dart b/example/lib/pages/selectors_page.dart index e44a1936..a8c1634a 100644 --- a/example/lib/pages/selectors_page.dart +++ b/example/lib/pages/selectors_page.dart @@ -28,8 +28,9 @@ class _SelectorsPageState extends State { ), children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return SingleChildScrollView( + // controller: scrollController, padding: const EdgeInsets.all(20), child: Column( children: [ diff --git a/example/lib/pages/tabview_page.dart b/example/lib/pages/tabview_page.dart index 786b11b0..2497c2ea 100644 --- a/example/lib/pages/tabview_page.dart +++ b/example/lib/pages/tabview_page.dart @@ -22,7 +22,7 @@ class _TabViewPageState extends State { ), children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Padding( padding: const EdgeInsets.all(24.0), child: MacosTabView( diff --git a/example/lib/pages/toolbar_page.dart b/example/lib/pages/toolbar_page.dart index 447a05a0..4e77fc86 100644 --- a/example/lib/pages/toolbar_page.dart +++ b/example/lib/pages/toolbar_page.dart @@ -156,9 +156,8 @@ class _ToolbarPageState extends State { ], ), children: [ - ContentArea(builder: (context, scrollController) { + ContentArea(builder: (context) { return SingleChildScrollView( - controller: scrollController, padding: const EdgeInsets.all(30), child: Center( child: Column( diff --git a/example/macos/Podfile b/example/macos/Podfile index dade8dfa..049abe29 100644 --- a/example/macos/Podfile +++ b/example/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.11' +platform :osx, '10.14' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 5bd494b2..90ae1621 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -14,9 +14,9 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/macos_ui/macos SPEC CHECKSUMS: - FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811 + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 macos_ui: 125c911559d646194386d84c017ad6819122e2db -PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c +PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 COCOAPODS: 1.11.3 diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index fb2b09e9..e7c1634c 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -295,6 +295,7 @@ }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -404,7 +405,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -483,7 +484,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -530,7 +531,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/example/macos/Runner/MainFlutterWindow.swift b/example/macos/Runner/MainFlutterWindow.swift index 1c6ce4e9..22fb7aee 100644 --- a/example/macos/Runner/MainFlutterWindow.swift +++ b/example/macos/Runner/MainFlutterWindow.swift @@ -29,6 +29,7 @@ class BlurryContainerViewController: NSViewController { self.addChild(flutterViewController) flutterViewController.view.frame = self.view.bounds + flutterViewController.backgroundColor = .clear flutterViewController.view.autoresizingMask = [.width, .height] self.view.addSubview(flutterViewController.view) } @@ -78,4 +79,4 @@ class MainFlutterWindow: NSWindow, NSWindowDelegate { func windowDidExitFullScreen(_ notification: Notification) { self.toolbar?.isVisible = true } -} \ No newline at end of file +} diff --git a/example/pubspec.lock b/example/pubspec.lock index 89ae8821..47da932b 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,49 +5,56 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" flutter: @@ -59,7 +66,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_test: @@ -67,62 +75,77 @@ packages: description: flutter source: sdk version: "0.0.0" + js: + dependency: transitive + description: + name: js + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" + source: hosted + version: "0.6.5" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.1" macos_ui: dependency: "direct main" description: path: ".." relative: true source: path - version: "1.7.6" + version: "1.9.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted version: "1.0.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" provider: dependency: "direct main" description: name: provider - url: "https://pub.dartlang.org" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" source: hosted - version: "6.0.3" + version: "6.0.5" sky_engine: dependency: transitive description: flutter @@ -132,51 +155,58 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" sdks: - dart: ">=2.17.0 <3.0.0" + dart: ">=2.18.0 <3.0.0" flutter: ">=1.20.0" diff --git a/lib/macos_ui.dart b/lib/macos_ui.dart index b783a572..619f0956 100644 --- a/lib/macos_ui.dart +++ b/lib/macos_ui.dart @@ -37,6 +37,7 @@ export 'src/indicators/progress_indicators.dart'; export 'src/indicators/rating_indicator.dart'; export 'src/indicators/relevance_indicator.dart'; export 'src/indicators/scrollbar.dart'; +export 'src/indicators/slider.dart'; export 'src/labels/label.dart'; export 'src/labels/tooltip.dart'; export 'src/layout/content_area.dart'; diff --git a/lib/src/fields/search_field.dart b/lib/src/fields/search_field.dart index ccece251..e550dde4 100644 --- a/lib/src/fields/search_field.dart +++ b/lib/src/fields/search_field.dart @@ -241,7 +241,7 @@ class _MacosSearchFieldState extends State> { } if (isResultExpanded) { _overlayEntry = _createOverlay(); - Overlay.of(context)!.insert(_overlayEntry); + Overlay.of(context).insert(_overlayEntry); } else { _overlayEntry.remove(); } diff --git a/lib/src/fields/text_field.dart b/lib/src/fields/text_field.dart index b69a1f97..99f390cc 100644 --- a/lib/src/fields/text_field.dart +++ b/lib/src/fields/text_field.dart @@ -255,7 +255,7 @@ class MacosTextField extends StatefulWidget { this.textAlign = TextAlign.start, this.textAlignVertical, this.readOnly = false, - ToolbarOptions? toolbarOptions, + this.contextMenuBuilder = _defaultContextMenuBuilder, this.showCursor, this.autofocus = false, this.obscuringCharacter = '•', @@ -314,19 +314,7 @@ class MacosTextField extends StatefulWidget { !identical(keyboardType, TextInputType.text), 'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.'), keyboardType = keyboardType ?? - (maxLines == 1 ? TextInputType.text : TextInputType.multiline), - toolbarOptions = toolbarOptions ?? - (obscureText - ? const ToolbarOptions( - selectAll: true, - paste: true, - ) - : const ToolbarOptions( - copy: true, - cut: true, - selectAll: true, - paste: true, - )); + (maxLines == 1 ? TextInputType.text : TextInputType.multiline); /// Creates a borderless macOS-style text field. /// @@ -386,7 +374,6 @@ class MacosTextField extends StatefulWidget { this.textAlign = TextAlign.start, this.textAlignVertical, this.readOnly = false, - ToolbarOptions? toolbarOptions, this.showCursor, this.autofocus = false, this.obscuringCharacter = '•', @@ -421,6 +408,7 @@ class MacosTextField extends StatefulWidget { this.scrollPhysics, this.autofillHints, this.restorationId, + this.contextMenuBuilder = _defaultContextMenuBuilder, }) : smartDashesType = smartDashesType ?? (obscureText ? SmartDashesType.disabled : SmartDashesType.enabled), smartQuotesType = smartQuotesType ?? @@ -445,19 +433,7 @@ class MacosTextField extends StatefulWidget { !identical(keyboardType, TextInputType.text), 'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.'), keyboardType = keyboardType ?? - (maxLines == 1 ? TextInputType.text : TextInputType.multiline), - toolbarOptions = toolbarOptions ?? - (obscureText - ? const ToolbarOptions( - selectAll: true, - paste: true, - ) - : const ToolbarOptions( - copy: true, - cut: true, - selectAll: true, - paste: true, - )); + (maxLines == 1 ? TextInputType.text : TextInputType.multiline); /// Controls the text being edited. /// @@ -563,12 +539,23 @@ class MacosTextField extends StatefulWidget { /// {@macro flutter.widgets.editableText.textAlign} final TextAlign textAlign; - /// Configuration of toolbar options. + /// {@macro flutter.widgets.EditableText.contextMenuBuilder} /// - /// If not set, select all and paste will default to be enabled. Copy and cut - /// will be disabled if [obscureText] is true. If [readOnly] is true, - /// paste and cut will be disabled regardless. - final ToolbarOptions toolbarOptions; + /// If not provided, will build a default menu based on the platform. + /// + /// See also: + /// + /// * [CupertinoAdaptiveTextSelectionToolbar], which is built by default. + final EditableTextContextMenuBuilder? contextMenuBuilder; + + static Widget _defaultContextMenuBuilder( + BuildContext context, + EditableTextState editableTextState, + ) { + return CupertinoAdaptiveTextSelectionToolbar.editableText( + editableTextState: editableTextState, + ); + } /// {@macro flutter.material.InputDecorator.textAlignVertical} final TextAlignVertical? textAlignVertical; @@ -880,6 +867,10 @@ class MacosTextField extends StatefulWidget { textAlignVertical, defaultValue: null, )); + properties.add(DiagnosticsProperty( + 'contextMenuBuilder', + contextMenuBuilder, + )); } } @@ -1350,7 +1341,6 @@ class _MacosTextFieldState extends State key: editableTextKey, controller: controller, readOnly: widget.readOnly, - toolbarOptions: widget.toolbarOptions, showCursor: widget.showCursor, showSelectionHandles: _showSelectionHandles, focusNode: _effectiveFocusNode, @@ -1402,6 +1392,7 @@ class _MacosTextFieldState extends State autofillHints: widget.autofillHints, restorationId: 'editable', mouseCursor: SystemMouseCursors.text, + contextMenuBuilder: widget.contextMenuBuilder, ), ), ), diff --git a/lib/src/indicators/scrollbar.dart b/lib/src/indicators/scrollbar.dart index 4ac8ddea..98c60b33 100644 --- a/lib/src/indicators/scrollbar.dart +++ b/lib/src/indicators/scrollbar.dart @@ -98,7 +98,9 @@ class MacosScrollbar extends StatelessWidget { crossAxisMargin: theme.crossAxisMargin, mainAxisMargin: theme.mainAxisMargin, interactive: theme.interactive, - thumbVisibility: m.MaterialStateProperty.resolveWith((states) => true), + thumbVisibility: m.MaterialStateProperty.resolveWith((states) { + return isAlwaysShown; + }), trackVisibility: m.MaterialStateProperty.resolveWith((states) { return trackVisibility; }), diff --git a/lib/src/indicators/slider.dart b/lib/src/indicators/slider.dart new file mode 100644 index 00000000..8a172c2e --- /dev/null +++ b/lib/src/indicators/slider.dart @@ -0,0 +1,373 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:macos_ui/macos_ui.dart'; + +const double _kSliderMinWidth = 100.0; +const double _kSliderBorderRadius = 16.0; +const double _kSliderHeight = 4.0; +const double _kContinuousThumbSize = 20; +const double _kOverallHeight = 20; +const double _kTickWidth = 2.0; +const double _kTickHeight = 8.0; + +const double _kDiscreteThumbWidth = 6.0; +const double _kDiscreteThumbBorderRadius = 8; + +/// {@template macosSlider} +/// A slider is a horizontal track with a control, called a thumb, +/// that people can adjust between a minimum and maximum value. +/// +/// The slider doesn't maintain any state itself, instead the user is expected to +/// update this widget with a new [value] whenever the slider changes. +/// +/// {@image } +/// {@endtemplate} +class MacosSlider extends StatelessWidget { + /// {@macro macosSlider} + const MacosSlider({ + super.key, + required this.value, + required this.onChanged, + this.discrete = false, + this.splits = 15, + this.min = 0.0, + this.max = 1.0, + this.color = CupertinoColors.systemBlue, + this.backgroundColor = MacosColors.sliderBackgroundColor, + this.tickBackgroundColor = MacosColors.tickBackgroundColor, + this.thumbColor = MacosColors.sliderThumbColor, + this.semanticLabel, + }) : assert(value >= min && value <= max), + assert(min < max), + assert(splits >= 2); + + /// The value of this slider. + /// + /// This value must be between [min] and [max], inclusive. + final double value; + + /// Called whenever the value of the slider changes + final ValueChanged onChanged; + + /// Whether the slider is discrete or continuous. + /// + /// Continuous sliders have a thumb that can be dragged anywhere along the track. + /// Discrete sliders have a thumb that can only be dragged to the tick marks. + /// + /// [splits] will only be considered if this is true. + final bool discrete; + + /// The minimum value of this slider + final double min; + + /// The maximum value of this slider + final double max; + + /// The number of discrete splits when using [discrete] mode. + /// + /// This includes the split at [min] and [max] + final int splits; + + /// The color of the slider (the part where the thumb is sliding on) that is not + /// considered selected. + /// + /// Defaults to [CupertinoColors.quaternaryLabel] + final Color backgroundColor; + + /// The color of background ticks when using [discrete] mode. + final Color tickBackgroundColor; + + /// The color of the slider (the part where the thumb is sliding on) that is + /// considered selected. + /// + /// Defaults to [CupertinoColors.systemBlue] + final Color color; + + /// The color of the thumb. + final Color thumbColor; + + /// The semantic label used by screen readers. + final String? semanticLabel; + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DoubleProperty('value', value)); + properties.add(ObjectFlagProperty.has('onChanged', onChanged)); + properties.add(DoubleProperty('min', min)); + properties.add(DoubleProperty('max', max)); + properties.add(ColorProperty('color', color)); + properties.add(ColorProperty('backgroundColor', backgroundColor)); + properties.add(ColorProperty('tickBackgroundColor', tickBackgroundColor)); + properties.add(ColorProperty('thumbColor', thumbColor)); + properties + .add(FlagProperty('discrete', value: discrete, ifTrue: 'discrete')); + properties.add(IntProperty('splits', splits)); + properties.add(StringProperty('semanticLabel', semanticLabel)); + } + + double get _percentage { + if (discrete) { + final double splitPercentage = 1 / (splits - 1); + final int splitIndex = (value / splitPercentage).round(); + return splitIndex * splitPercentage; + } else { + return (value - min) / (max - min); + } + } + + void _update(double sliderWidth, double localPosition) { + if (discrete) { + final double splitPercentage = 1 / (splits - 1); + final int splitIndex = (localPosition / sliderWidth / splitPercentage) + .round() + .clamp(0, splits - 1); + onChanged(splitIndex * splitPercentage); + } else { + final double newValue = (localPosition / sliderWidth) * (max - min) + min; + onChanged(newValue.clamp(min, max)); + } + } + + @override + Widget build(BuildContext context) { + return Semantics( + slider: true, + label: semanticLabel, + value: value.toStringAsFixed(2), + child: ConstrainedBox( + constraints: const BoxConstraints(minWidth: _kSliderMinWidth), + child: LayoutBuilder( + builder: (context, constraints) { + double width = constraints.maxWidth; + if (width.isInfinite) width = _kSliderMinWidth; + + // Padding around every element so the thumb is clickable as it never + // leaves the edge of the stack + double horizontalPadding; + if (discrete) { + horizontalPadding = _kDiscreteThumbWidth / 2; + } else { + horizontalPadding = _kContinuousThumbSize / 2; + } + width -= horizontalPadding * 2; + + return SizedBox( + height: _kOverallHeight, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onHorizontalDragStart: (details) { + _update(width, details.localPosition.dx - horizontalPadding); + }, + onHorizontalDragUpdate: (details) { + _update(width, details.localPosition.dx - horizontalPadding); + }, + onTapDown: (details) { + _update(width, details.localPosition.dx - horizontalPadding); + }, + child: Stack( + children: [ + Center( + child: Container( + margin: + EdgeInsets.symmetric(horizontal: horizontalPadding), + height: _kSliderHeight, + width: width, + decoration: BoxDecoration( + color: MacosDynamicColor.resolve( + backgroundColor, + context, + ), + borderRadius: + BorderRadius.circular(_kSliderBorderRadius), + ), + ), + ), + Align( + alignment: Alignment.centerLeft, + child: Container( + margin: + EdgeInsets.symmetric(horizontal: horizontalPadding), + height: _kSliderHeight, + width: width * _percentage, + decoration: BoxDecoration( + color: MacosDynamicColor.resolve(color, context), + borderRadius: + BorderRadius.circular(_kSliderBorderRadius), + ), + ), + ), + if (discrete) + Padding( + padding: + EdgeInsets.symmetric(horizontal: horizontalPadding), + child: SizedBox( + height: _kOverallHeight, + width: width, + child: CustomPaint( + size: Size(width, _kOverallHeight), + painter: _DiscreteTickPainter( + color: MacosDynamicColor.resolve(color, context), + backgroundColor: MacosDynamicColor.resolve( + backgroundColor, + context, + ), + selectedPercentage: _percentage, + ticks: splits, + ), + ), + ), + ), + if (!discrete) + Positioned( + left: width * _percentage - _kContinuousThumbSize / 2, + width: _kContinuousThumbSize * 2, + height: _kContinuousThumbSize, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: horizontalPadding, + ), + child: _ContinuousThumb( + color: + MacosDynamicColor.resolve(thumbColor, context), + ), + ), + ), + if (discrete) + Positioned( + left: width * _percentage - _kDiscreteThumbWidth / 2, + width: _kDiscreteThumbWidth * 2, + height: _kContinuousThumbSize, + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: horizontalPadding, + ), + child: _DiscreteThumb( + color: + MacosDynamicColor.resolve(thumbColor, context), + ), + ), + ), + ], + ), + ), + ); + }, + ), + ), + ); + } +} + +class _ContinuousThumb extends StatelessWidget { + const _ContinuousThumb({ + required this.color, + }); + + final Color color; + + @override + Widget build(BuildContext context) { + return Container( + height: _kContinuousThumbSize, + width: _kContinuousThumbSize, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(_kContinuousThumbSize), + boxShadow: const [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.1), + blurRadius: 1, + spreadRadius: 1, + offset: Offset(0, 1), + ), + ], + ), + ); + } +} + +class _DiscreteThumb extends StatelessWidget { + const _DiscreteThumb({ + required this.color, + }); + + final Color color; + @override + Widget build(BuildContext context) { + return Container( + height: _kContinuousThumbSize, + width: _kDiscreteThumbWidth, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(_kDiscreteThumbBorderRadius), + boxShadow: const [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.1), + blurRadius: 1, + spreadRadius: 1, + offset: Offset(0, 1), + ), + ], + ), + ); + } +} + +class _DiscreteTickPainter extends CustomPainter { + _DiscreteTickPainter({ + required this.ticks, + required this.selectedPercentage, + required this.backgroundColor, + required this.color, + }); + + final int ticks; + final double selectedPercentage; + final Color backgroundColor; + final Color color; + + @override + void paint(Canvas canvas, Size size) { + var width = size.width; + + var spaceBetween = width / (ticks - 1); + + var paint = Paint() + ..color = color + ..strokeWidth = 1 + ..strokeCap = StrokeCap.round; + + var backgroundPaint = Paint() + ..color = backgroundColor + ..strokeWidth = 1 + ..strokeCap = StrokeCap.round; + + for (var i = 0; i < ticks; i++) { + var x = spaceBetween * i; + + var isPastSelectedPercentage = x / width > selectedPercentage; + + canvas.drawRRect( + RRect.fromRectAndRadius( + Rect.fromLTWH( + x - 1, + (size.height / 2) - (_kTickHeight / 2), + _kTickWidth, + _kTickHeight, + ), + const Radius.circular(8), + ), + isPastSelectedPercentage ? backgroundPaint : paint, + ); + } + } + + @override + bool shouldRepaint(_DiscreteTickPainter oldDelegate) { + return oldDelegate.ticks != ticks || + oldDelegate.selectedPercentage != selectedPercentage || + oldDelegate.backgroundColor != backgroundColor || + oldDelegate.color != color; + } +} diff --git a/lib/src/labels/tooltip.dart b/lib/src/labels/tooltip.dart index dbc530b3..0c42f005 100644 --- a/lib/src/labels/tooltip.dart +++ b/lib/src/labels/tooltip.dart @@ -170,7 +170,7 @@ class _MacosTooltipState extends State final OverlayState overlayState = Overlay.of( context, debugRequiredFor: widget, - )!; + ); final RenderBox box = context.findRenderObject()! as RenderBox; Offset target = box.localToGlobal( @@ -256,7 +256,6 @@ class _MacosTooltipState extends State @override Widget build(BuildContext context) { assert(debugCheckHasMacosTheme(context)); - assert(Overlay.of(context, debugRequiredFor: widget) != null); final tooltipTheme = MacosTooltipTheme.of(context); height = tooltipTheme.height!; diff --git a/lib/src/layout/content_area.dart b/lib/src/layout/content_area.dart index cad517d4..0012292b 100644 --- a/lib/src/layout/content_area.dart +++ b/lib/src/layout/content_area.dart @@ -1,4 +1,3 @@ -import 'package:macos_ui/src/indicators/scrollbar.dart'; import 'package:macos_ui/src/layout/scaffold.dart'; import 'package:macos_ui/src/library.dart'; @@ -16,18 +15,12 @@ class ContentArea extends StatelessWidget { this.minWidth = 300, }) : super(key: const Key('macos_scaffold_content_area')); - /// The builder that creates a child to display in this widget, which will - /// use the provided [_scrollController] to enable the scrollbar to work. - /// - /// Pass the [_scrollController] obtained from this method, to a scrollable - /// widget used in this method to work with the internal [MacosScrollbar]. - final ScrollableWidgetBuilder? builder; + /// The builder that creates a child to display in this widget. + final WidgetBuilder? builder; /// Specifies the minimum width that this [ContentArea] can have. final double minWidth; - static final _scrollController = ScrollController(); - @override Widget build(BuildContext context) { return ConstrainedBox( @@ -37,7 +30,7 @@ class ContentArea extends StatelessWidget { child: SafeArea( left: false, right: false, - child: builder!(context, _scrollController), + child: builder!(context), ), ); } diff --git a/lib/src/layout/sidebar/sidebar_items.dart b/lib/src/layout/sidebar/sidebar_items.dart index 27b47bd3..f13779d8 100644 --- a/lib/src/layout/sidebar/sidebar_items.dart +++ b/lib/src/layout/sidebar/sidebar_items.dart @@ -383,7 +383,7 @@ class __DisclosureSidebarItemState extends State<_DisclosureSidebarItem> }); }); } - PageStorage.of(context)?.writeState(context, _isExpanded); + PageStorage.of(context).writeState(context, _isExpanded); }); // widget.onExpansionChanged?.call(_isExpanded); } diff --git a/lib/src/layout/window.dart b/lib/src/layout/window.dart index 6769a9de..d8cb563c 100644 --- a/lib/src/layout/window.dart +++ b/lib/src/layout/window.dart @@ -220,7 +220,8 @@ class _MacosWindowState extends State { if (_sidebarScrollController.hasClients && _sidebarScrollController.offset > 0.0) Divider(thickness: 1, height: 1, color: dividerColor), - if (widget.sidebar!.top != null) + if (widget.sidebar!.top != null && + constraints.maxHeight < 81) Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: widget.sidebar!.top!, @@ -235,7 +236,8 @@ class _MacosWindowState extends State { ), ), ), - if (widget.sidebar?.bottom != null) + if (widget.sidebar?.bottom != null && + constraints.maxHeight < 141) Padding( padding: const EdgeInsets.all(16.0), child: widget.sidebar!.bottom!, diff --git a/lib/src/library.dart b/lib/src/library.dart index 481030ed..b473c28f 100644 --- a/lib/src/library.dart +++ b/lib/src/library.dart @@ -6,7 +6,8 @@ export 'package:flutter/cupertino.dart' createCupertinoColorProperty, cupertinoTextSelectionControls, DefaultCupertinoLocalizations, - cupertinoDesktopTextSelectionControls; + cupertinoDesktopTextSelectionControls, + CupertinoAdaptiveTextSelectionToolbar; export 'package:flutter/material.dart' show Brightness, diff --git a/lib/src/theme/macos_colors.dart b/lib/src/theme/macos_colors.dart index 59bad194..f5d92d80 100644 --- a/lib/src/theme/macos_colors.dart +++ b/lib/src/theme/macos_colors.dart @@ -291,6 +291,25 @@ class MacosColors { darkColor: Color.fromRGBO(26, 169, 255, 0.3), ); + /// The color of the thumb of [MacosSlider]. + static const sliderThumbColor = CupertinoDynamicColor.withBrightness( + color: Color.fromRGBO(255, 255, 255, 1), + darkColor: Color.fromRGBO(152, 152, 157, 1), + ); + + /// The color of the tick marks which are not selected (the portion to the right of the thumb) of [MacosSlider]. + static const tickBackgroundColor = CupertinoDynamicColor.withBrightness( + color: Color.fromRGBO(220, 220, 220, 1), + darkColor: Color.fromRGBO(70, 70, 70, 1), + ); + + /// The color of the slider in [MacosSlider] which is not selected (the portion + /// to the right of the thumb). + static const sliderBackgroundColor = CupertinoDynamicColor.withBrightness( + color: Color.fromRGBO(0, 0, 0, 0.1), + darkColor: Color.fromRGBO(255, 255, 255, 0.1), + ); + /// The accent color selected by the user in system preferences. /// /// No dark variant. diff --git a/macos/Classes/ColorPanelProvider.swift b/macos/Classes/ColorPanelProvider.swift index 3770b7cd..4f080f8b 100644 --- a/macos/Classes/ColorPanelProvider.swift +++ b/macos/Classes/ColorPanelProvider.swift @@ -15,6 +15,7 @@ class ColorPanelProvider: NSObject, FlutterStreamHandler { colorPanel.setAction(#selector(startStream(colorPanel:))) colorPanel.makeKeyAndOrderFront(self) colorPanel.isContinuous = true + colorPanel.isReleasedWhenClosed = true } func setPickerMode(panelMode: String) { diff --git a/pr_prelaunch_tasks.sh b/pr_prelaunch_tasks.sh index 0d836662..b7d2ff83 100644 --- a/pr_prelaunch_tasks.sh +++ b/pr_prelaunch_tasks.sh @@ -1,6 +1,6 @@ -flutter format --set-exit-if-changed . +dart format --set-exit-if-changed . if [ $? -eq 1 ]; then - flutter format lib + dart format lib git add . git commit -m "chore: run flutter format ." echo "push changes? [y/n]" diff --git a/pubspec.lock b/pubspec.lock index 469a5adc..eb16ba9a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,135 +5,146 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: d976d24314f193899a3079b14fe336215a63a3b1e1c3743eabba8f83e049e9a9 + url: "https://pub.dev" source: hosted - version: "43.0.0" + version: "49.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "40ba2c6d2ab41a66476f8f1f099da6be0795c1b47221f5e2c5f8ad6048cdffae" + url: "https://pub.dev" source: hosted - version: "4.3.1" + version: "5.1.0" analyzer_plugin: dependency: transitive description: name: analyzer_plugin - url: "https://pub.dartlang.org" + sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d + url: "https://pub.dev" source: hosted - version: "0.10.0" + version: "0.11.2" ansicolor: dependency: transitive description: name: ansicolor - url: "https://pub.dartlang.org" + sha256: "607f8fa9786f392043f169898923e6c59b4518242b68b8862eb8a8b7d9c30b4a" + url: "https://pub.dev" source: hosted version: "2.0.1" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.1" coverage: dependency: transitive description: name: coverage - url: "https://pub.dartlang.org" + sha256: "961c4aebd27917269b1896382c7cb1b1ba81629ba669ba09c27a7e5710ec9040" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.6.2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + url: "https://pub.dev" source: hosted - version: "0.17.1" + version: "0.17.2" dart_code_metrics: dependency: "direct dev" description: name: dart_code_metrics - url: "https://pub.dartlang.org" + sha256: "219607f5abbf4c0d254ca39ee009f9ff28df91c40aef26718fde15af6b7a6c24" + url: "https://pub.dev" source: hosted - version: "4.17.1" + version: "4.21.3" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "6.1.4" flutter: dependency: "direct main" description: flutter @@ -143,7 +154,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_test: @@ -155,170 +167,234 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "3.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.1" html: dependency: transitive description: name: html - url: "https://pub.dartlang.org" + sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + url: "https://pub.dev" source: hosted - version: "0.15.0" + version: "0.15.1" + http: + dependency: transitive + description: + name: http + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" + source: hosted + version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.2" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "4.8.0" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.4" mocktail: dependency: "direct dev" description: name: mocktail - url: "https://pub.dartlang.org" + sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" + url: "https://pub.dev" source: hosted version: "0.3.0" node_preamble: dependency: transitive description: name: node_preamble - url: "https://pub.dartlang.org" + sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + url: "https://pub.dev" source: hosted version: "2.0.1" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "5.1.0" + platform: + dependency: transitive + description: + name: platform + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" + source: hosted + version: "3.1.0" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "4.2.4" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.3" + pub_updater: + dependency: transitive + description: + name: pub_updater + sha256: "42890302ab2672adf567dc2b20e55b4ecc29d7e19c63b6b98143ab68dd717d3a" + url: "https://pub.dev" + source: hosted + version: "0.2.4" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - url: "https://pub.dartlang.org" + sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306 + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.3" sky_engine: dependency: transitive description: flutter @@ -328,128 +404,146 @@ packages: dependency: transitive description: name: source_map_stack_trace - url: "https://pub.dartlang.org" + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" source_maps: dependency: transitive description: name: source_maps - url: "https://pub.dartlang.org" + sha256: "490098075234dcedb83c5d949b4c93dad5e6b7702748de000be2b57b8e6b2427" + url: "https://pub.dev" source: hosted - version: "0.10.10" + version: "0.10.11" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test: dependency: transitive description: name: test - url: "https://pub.dartlang.org" + sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d + url: "https://pub.dev" source: hosted - version: "1.21.4" + version: "1.22.0" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" test_core: dependency: transitive description: name: test_core - url: "https://pub.dartlang.org" + sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888" + url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.4.20" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7 + url: "https://pub.dev" source: hosted - version: "7.5.0" + version: "9.4.0" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - url: "https://pub.dartlang.org" + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.2.0" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" source: hosted - version: "5.3.1" + version: "6.2.2" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" sdks: - dart: ">=2.17.0 <3.0.0" + dart: ">=2.18.0 <3.0.0" flutter: ">=1.20.0" diff --git a/pubspec.yaml b/pubspec.yaml index 12962428..db2162f8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: macos_ui description: Flutter widgets and themes implementing the current macOS design language. -version: 1.7.6 +version: 1.9.0 homepage: "https://macosui.dev" repository: "https://github.com/GroovinChip/macos_ui" diff --git a/test/buttons/checkbox_test.dart b/test/buttons/checkbox_test.dart index 9ba9c1a5..323c3425 100644 --- a/test/buttons/checkbox_test.dart +++ b/test/buttons/checkbox_test.dart @@ -12,7 +12,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return StatefulBuilder( builder: (context, setState) { return MacosCheckbox( diff --git a/test/buttons/help_button_test.dart b/test/buttons/help_button_test.dart index 5f42d50a..095acbc6 100644 --- a/test/buttons/help_button_test.dart +++ b/test/buttons/help_button_test.dart @@ -24,7 +24,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return HelpButton( onPressed: mockOnPressedFunction.handler, ); @@ -55,7 +55,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return HelpButton( key: helpButtonKey, onPressed: mockOnTapCancelFunction.handler, diff --git a/test/buttons/icon_button_test.dart b/test/buttons/icon_button_test.dart index 58c371d3..a6d893de 100644 --- a/test/buttons/icon_button_test.dart +++ b/test/buttons/icon_button_test.dart @@ -19,7 +19,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return MacosIconButton( icon: const Icon(CupertinoIcons.add), onPressed: mockOnPressedFunction.handler, @@ -48,7 +48,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return MacosIconButton( key: iconButtonKey, icon: const Icon(CupertinoIcons.add), diff --git a/test/buttons/popup_button_test.dart b/test/buttons/popup_button_test.dart index d685d3da..a57d1516 100644 --- a/test/buttons/popup_button_test.dart +++ b/test/buttons/popup_button_test.dart @@ -17,7 +17,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return StatefulBuilder( builder: (context, setState) { return MacosPopupButton( diff --git a/test/buttons/pulldown_button_test.dart b/test/buttons/pulldown_button_test.dart index 8f4f0201..fd319577 100644 --- a/test/buttons/pulldown_button_test.dart +++ b/test/buttons/pulldown_button_test.dart @@ -22,7 +22,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosPulldownButton( title: "test", @@ -67,7 +67,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosPulldownButton( title: "test", diff --git a/test/buttons/push_button_test.dart b/test/buttons/push_button_test.dart index f9a57691..3cd6c5e5 100644 --- a/test/buttons/push_button_test.dart +++ b/test/buttons/push_button_test.dart @@ -25,7 +25,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return PushButton( buttonSize: ButtonSize.small, onPressed: mockOnPressedFunction.handler, @@ -58,7 +58,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return PushButton( buttonSize: ButtonSize.small, key: pushButtonKey, diff --git a/test/buttons/radio_button_test.dart b/test/buttons/radio_button_test.dart index 1a288cba..f900a867 100644 --- a/test/buttons/radio_button_test.dart +++ b/test/buttons/radio_button_test.dart @@ -20,7 +20,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosRadioButton( value: TestOptions.first, @@ -53,7 +53,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosRadioButton( value: TestOptions.second, diff --git a/test/buttons/segmented_control_test.dart b/test/buttons/segmented_control_test.dart index 8e19831e..f85c9d89 100644 --- a/test/buttons/segmented_control_test.dart +++ b/test/buttons/segmented_control_test.dart @@ -14,7 +14,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosSegmentedControl( controller: controller, @@ -59,7 +59,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosSegmentedControl( controller: controller, diff --git a/test/buttons/switch_test.dart b/test/buttons/switch_test.dart index 75c3e863..9c32d1b4 100644 --- a/test/buttons/switch_test.dart +++ b/test/buttons/switch_test.dart @@ -12,7 +12,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosSwitch( value: selected, diff --git a/test/fields/search_field_test.dart b/test/fields/search_field_test.dart index a6f1a750..507b5648 100644 --- a/test/fields/search_field_test.dart +++ b/test/fields/search_field_test.dart @@ -29,7 +29,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: SizedBox( width: 300.0, diff --git a/test/fields/text_field_test.dart b/test/fields/text_field_test.dart index d83ce27b..eff83bc2 100644 --- a/test/fields/text_field_test.dart +++ b/test/fields/text_field_test.dart @@ -12,7 +12,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosTextField( controller: controller, diff --git a/test/indicators/slider_test.dart b/test/indicators/slider_test.dart new file mode 100644 index 00000000..23bb0b35 --- /dev/null +++ b/test/indicators/slider_test.dart @@ -0,0 +1,114 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:macos_ui/macos_ui.dart'; + +void main() { + final TestWidgetsFlutterBinding binding = + TestWidgetsFlutterBinding.ensureInitialized(); + testWidgets('debugFillProperties', (tester) async { + final builder = DiagnosticPropertiesBuilder(); + MacosSlider( + value: 0.5, + onChanged: (newValue) {}, + ).debugFillProperties(builder); + + final description = builder.properties + .where((node) => !node.isFiltered(DiagnosticLevel.info)) + .map((node) => node.toString()) + .toList(); + + expect( + description, + [ + 'value: 0.5', + 'has onChanged', + 'min: 0.0', + 'max: 1.0', + 'color: systemBlue(*color = Color(0xff007aff)*, darkColor = Color(0xff0a84ff), highContrastColor = Color(0xff0040dd), darkHighContrastColor = Color(0xff409cff), resolved by: UNRESOLVED)', + 'backgroundColor: CupertinoDynamicColor(*color = Color(0x19000000)*, darkColor = Color(0x19ffffff), resolved by: UNRESOLVED)', + 'tickBackgroundColor: CupertinoDynamicColor(*color = Color(0xffdcdcdc)*, darkColor = Color(0xff464646), resolved by: UNRESOLVED)', + 'thumbColor: CupertinoDynamicColor(*color = Color(0xffffffff)*, darkColor = Color(0xff98989d), resolved by: UNRESOLVED)', + 'splits: 15', + 'semanticLabel: null', + ], + ); + }); + + testWidgets('Continuous slider can move when tapped', (tester) async { + tester.binding.window.physicalSizeTestValue = const Size(100, 50); + binding.window.devicePixelRatioTestValue = 1.0; + + final value = ValueNotifier(0.25); + await tester.pumpWidget( + CupertinoApp( + home: Center( + child: MacosSlider( + value: value.value, + onChanged: (newValue) { + value.value = newValue; + }, + ), + ), + ), + ); + + expect(value.value, 0.25); + + // Tap on the right half of the slider. + await tester.tapAt(const Offset(50, 25)); + await tester.pumpAndSettle(); + + expect(value.value, greaterThan(0.25)); + + await tester.tapAt(const Offset(0, 25)); + await tester.pumpAndSettle(); + + expect(value.value, 0.0); + addTearDown(tester.binding.window.clearPhysicalSizeTestValue); + }); + + testWidgets('Discrete slider snaps to correct values', (widgetTester) async { + widgetTester.binding.window.physicalSizeTestValue = const Size(100, 50); + binding.window.devicePixelRatioTestValue = 1.0; + + final value = ValueNotifier(0.25); + await widgetTester.pumpWidget( + CupertinoApp( + home: Center( + child: MacosSlider( + value: value.value, + onChanged: (newValue) { + value.value = newValue; + }, + min: 0.0, + max: 1.0, + discrete: true, + splits: 3, + ), + ), + ), + ); + + expect(value.value, 0.25); + + // Tap on the right half of the slider. + await widgetTester.tapAt(const Offset(50, 25)); + await widgetTester.pumpAndSettle(); + + expect(value.value, 0.5); + + await widgetTester.tapAt(const Offset(0, 25)); + await widgetTester.pumpAndSettle(); + + expect(value.value, 0.0); + + // Tap slightly to the right of the 0.5 mark. + await widgetTester.tapAt(const Offset(55, 25)); + await widgetTester.pumpAndSettle(); + + expect(value.value, 0.5); + + addTearDown(widgetTester.binding.window.clearPhysicalSizeTestValue); + }); +} diff --git a/test/layout/macos_list_tile_test.dart b/test/layout/macos_list_tile_test.dart index de7fc538..e021b3b5 100644 --- a/test/layout/macos_list_tile_test.dart +++ b/test/layout/macos_list_tile_test.dart @@ -23,7 +23,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return MacosListTile( title: const Text('List Tile'), onClick: mockOnPressedFunction.handler, @@ -52,7 +52,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return MacosListTile( title: const Text('List Tile'), subtitle: const Text('Subtitle'), diff --git a/test/layout/resizeable_pane_test.dart b/test/layout/resizeable_pane_test.dart index c4cc72f6..26016e84 100644 --- a/test/layout/resizeable_pane_test.dart +++ b/test/layout/resizeable_pane_test.dart @@ -26,8 +26,7 @@ void main() { children: [ resizablePane, ContentArea( - builder: (context, scrollController) => - const Text('Hello there'), + builder: (context) => const Text('Hello there'), ), ], ), diff --git a/test/layout/tab_view_test.dart b/test/layout/tab_view_test.dart index 3673f4d1..89a0bad0 100644 --- a/test/layout/tab_view_test.dart +++ b/test/layout/tab_view_test.dart @@ -14,7 +14,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Padding( padding: const EdgeInsets.all(24.0), child: MacosTabView( diff --git a/test/selectors/date_picker_test.dart b/test/selectors/date_picker_test.dart index 77a96af8..5823869e 100644 --- a/test/selectors/date_picker_test.dart +++ b/test/selectors/date_picker_test.dart @@ -15,7 +15,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosDatePicker( onDateChanged: (date) {}, @@ -52,7 +52,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosDatePicker( onDateChanged: (date) {}, @@ -97,7 +97,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosDatePicker( onDateChanged: (date) {}, @@ -142,7 +142,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosDatePicker( onDateChanged: (date) {}, @@ -188,7 +188,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosDatePicker( onDateChanged: (date) { @@ -224,7 +224,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { return Center( child: MacosDatePicker( onDateChanged: (date) { diff --git a/test/theme/help_button_theme_test.dart b/test/theme/help_button_theme_test.dart index cd93ac74..aa73c2c4 100644 --- a/test/theme/help_button_theme_test.dart +++ b/test/theme/help_button_theme_test.dart @@ -59,7 +59,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { capturedContext = context; return const HelpButton(); }, diff --git a/test/theme/icon_button_theme_test.dart b/test/theme/icon_button_theme_test.dart index 92832505..bc7ff339 100644 --- a/test/theme/icon_button_theme_test.dart +++ b/test/theme/icon_button_theme_test.dart @@ -66,7 +66,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { capturedContext = context; return MacosIconButton( icon: const Icon(CupertinoIcons.add), diff --git a/test/theme/icon_theme_test.dart b/test/theme/icon_theme_test.dart index 23182817..5e37d2cd 100644 --- a/test/theme/icon_theme_test.dart +++ b/test/theme/icon_theme_test.dart @@ -66,7 +66,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { capturedContext = context; return const MacosIcon( CupertinoIcons.add, diff --git a/test/theme/popup_button_theme_test.dart b/test/theme/popup_button_theme_test.dart index 710f2f49..96f40400 100644 --- a/test/theme/popup_button_theme_test.dart +++ b/test/theme/popup_button_theme_test.dart @@ -70,7 +70,9 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: ( + context, + ) { capturedContext = context; return MacosPopupButton( value: popupValue, diff --git a/test/theme/pulldown_button_theme_test.dart b/test/theme/pulldown_button_theme_test.dart index 44264874..9342c46d 100644 --- a/test/theme/pulldown_button_theme_test.dart +++ b/test/theme/pulldown_button_theme_test.dart @@ -69,7 +69,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { capturedContext = context; return const Center( child: MacosPulldownButton( diff --git a/test/theme/push_button_theme_test.dart b/test/theme/push_button_theme_test.dart index 8ced6d85..b163be44 100644 --- a/test/theme/push_button_theme_test.dart +++ b/test/theme/push_button_theme_test.dart @@ -61,7 +61,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { capturedContext = context; return const PushButton( buttonSize: ButtonSize.small, diff --git a/test/theme/search_field_theme_test.dart b/test/theme/search_field_theme_test.dart index 866f83cc..cf740bfe 100644 --- a/test/theme/search_field_theme_test.dart +++ b/test/theme/search_field_theme_test.dart @@ -65,7 +65,7 @@ void main() { child: MacosScaffold( children: [ ContentArea( - builder: (context, scrollController) { + builder: (context) { capturedContext = context; return const Center( child: MacosSearchField(),