diff --git a/lib/src/macos_app.dart b/lib/src/macos_app.dart index 71265fa0..6f60758c 100644 --- a/lib/src/macos_app.dart +++ b/lib/src/macos_app.dart @@ -1,21 +1,54 @@ import 'package:macos_ui/macos_ui.dart'; -import 'package:flutter/material.dart' as m; +import 'package:flutter/cupertino.dart' as c; -/// Defines an application that uses macOS design +/// An application that uses macOS design. /// -/// todo: Documentation +/// A convenience widget that wraps a number of widgets that are commonly +/// required for an macOS-design targeting application. It builds upon a +/// [WidgetsApp] by macOS specific defaulting such as fonts and scrolling +/// physics. +/// +/// The [MacosApp] configures the top-level [Navigator] to search for routes +/// in the following order: +/// +/// 1. For the `/` route, the [home] property, if non-null, is used. +/// +/// 2. Otherwise, the [routes] table is used, if it has an entry for the route. +/// +/// 3. Otherwise, [onGenerateRoute] is called, if provided. It should return a +/// non-null value for any _valid_ route not handled by [home] and [routes]. +/// +/// 4. Finally if all else fails [onUnknownRoute] is called. +/// +/// If [home], [routes], [onGenerateRoute], and [onUnknownRoute] are all null, +/// and [builder] is not null, then no [Navigator] is created. +/// +/// This widget also configures the observer of the top-level [Navigator] (if +/// any) to perform [Hero] animations. class MacosApp extends StatefulWidget { + /// Creates a MacosApp. + /// + /// At least one of [home], [routes], [onGenerateRoute], or [builder] must be + /// non-null. If only [routes] is given, it must include an entry for the + /// [Navigator.defaultRouteName] (`/`), since that is the route used when the + /// application is launched with an intent that specifies an otherwise + /// unsupported route. + /// + /// This class creates an instance of [WidgetsApp]. + /// + /// The boolean arguments, [routes], and [navigatorObservers], must not be null. const MacosApp({ Key? key, this.navigatorKey, + this.home, + Map this.routes = + const {}, + this.initialRoute, this.onGenerateRoute, this.onGenerateInitialRoutes, this.onUnknownRoute, - this.navigatorObservers = const [], - this.initialRoute, - this.pageRouteBuilder, - this.home, - this.routes = const {}, + List this.navigatorObservers = + const [], this.builder, this.title = '', this.onGenerateTitle, @@ -29,33 +62,30 @@ class MacosApp extends StatefulWidget { this.checkerboardRasterCacheImages = false, this.checkerboardOffscreenLayers = false, this.showSemanticsDebugger = false, - this.debugShowWidgetInspector = false, this.debugShowCheckedModeBanner = true, - this.inspectorSelectButtonBuilder, this.shortcuts, this.actions, + this.restorationScopeId, + this.themeMode, this.style, this.darkStyle, - this.themeMode, }) : routeInformationProvider = null, routeInformationParser = null, routerDelegate = null, backButtonDispatcher = null, super(key: key); + /// Creates a [MacosApp] that uses the [Router] instead of a [Navigator]. MacosApp.router({ Key? key, - this.style, - this.darkStyle, - this.themeMode, this.routeInformationProvider, - required this.routeInformationParser, - required this.routerDelegate, - BackButtonDispatcher? backButtonDispatcher, + required RouteInformationParser this.routeInformationParser, + required RouterDelegate this.routerDelegate, + this.backButtonDispatcher, this.builder, this.title = '', this.onGenerateTitle, - required Color this.primaryColor, + this.primaryColor, this.locale, this.localizationsDelegates, this.localeListResolutionCallback, @@ -65,20 +95,17 @@ class MacosApp extends StatefulWidget { this.checkerboardRasterCacheImages = false, this.checkerboardOffscreenLayers = false, this.showSemanticsDebugger = false, - this.debugShowWidgetInspector = false, this.debugShowCheckedModeBanner = true, - this.inspectorSelectButtonBuilder, this.shortcuts, this.actions, - }) : assert(routeInformationParser != null && routerDelegate != null, - 'The routeInformationParser and routerDelegate cannot be null.'), - assert(supportedLocales.isNotEmpty), + this.restorationScopeId, + this.themeMode, + this.style, + this.darkStyle, + }) : assert(supportedLocales.isNotEmpty), navigatorObservers = null, - backButtonDispatcher = - backButtonDispatcher ?? RootBackButtonDispatcher(), navigatorKey = null, onGenerateRoute = null, - pageRouteBuilder = null, home = null, onGenerateInitialRoutes = null, onUnknownRoute = null, @@ -86,79 +113,178 @@ class MacosApp extends StatefulWidget { initialRoute = null, super(key: key); - final Map>? actions; - - final BackButtonDispatcher? backButtonDispatcher; - - final TransitionBuilder? builder; - - final bool checkerboardOffscreenLayers; - - final bool checkerboardRasterCacheImages; - - final Style? darkStyle; - - static bool debugAllowBannerOverride = true; - - final bool debugShowCheckedModeBanner; - - final bool debugShowWidgetInspector; - - static bool debugShowWidgetInspectorOverride = false; + /// {@macro flutter.widgets.widgetsApp.navigatorKey} + final GlobalKey? navigatorKey; + /// {@macro flutter.widgets.widgetsApp.home} final Widget? home; - final String? initialRoute; + /// The application's top-level routing table. + /// + /// When a named route is pushed with [Navigator.pushNamed], the route name is + /// looked up in this map. If the name is present, the associated + /// [WidgetBuilder] is used to construct a [CupertinoPageRoute] that performs + /// an appropriate transition, including [Hero] animations, to the new route. + /// + /// {@macro flutter.widgets.widgetsApp.routes} + final Map? routes; - final InspectorSelectButtonBuilder? inspectorSelectButtonBuilder; + /// {@macro flutter.widgets.widgetsApp.initialRoute} + final String? initialRoute; - final Locale? locale; + /// {@macro flutter.widgets.widgetsApp.onGenerateRoute} + final RouteFactory? onGenerateRoute; - final LocaleListResolutionCallback? localeListResolutionCallback; + /// {@macro flutter.widgets.widgetsApp.onGenerateInitialRoutes} + final InitialRouteListFactory? onGenerateInitialRoutes; - final LocaleResolutionCallback? localeResolutionCallback; + /// {@macro flutter.widgets.widgetsApp.onUnknownRoute} + final RouteFactory? onUnknownRoute; - final Iterable>? localizationsDelegates; + /// {@macro flutter.widgets.widgetsApp.navigatorObservers} + final List? navigatorObservers; - final GlobalKey? navigatorKey; + /// {@macro flutter.widgets.widgetsApp.routeInformationProvider} + final RouteInformationProvider? routeInformationProvider; - final List? navigatorObservers; + /// {@macro flutter.widgets.widgetsApp.routeInformationParser} + final RouteInformationParser? routeInformationParser; - final InitialRouteListFactory? onGenerateInitialRoutes; + /// {@macro flutter.widgets.widgetsApp.routerDelegate} + final RouterDelegate? routerDelegate; - final RouteFactory? onGenerateRoute; + /// {@macro flutter.widgets.widgetsApp.backButtonDispatcher} + final BackButtonDispatcher? backButtonDispatcher; - final GenerateAppTitle? onGenerateTitle; + /// {@macro flutter.widgets.widgetsApp.builder} + final TransitionBuilder? builder; - final RouteFactory? onUnknownRoute; + /// {@macro flutter.widgets.widgetsApp.title} + /// + /// This value is passed unmodified to [WidgetsApp.title]. + final String title; - final PageRouteFactory? pageRouteBuilder; + /// {@macro flutter.widgets.widgetsApp.onGenerateTitle} + /// + /// This value is passed unmodified to [WidgetsApp.onGenerateTitle]. + final GenerateAppTitle? onGenerateTitle; + /// {@macro flutter.widgets.widgetsApp.color} final Color? primaryColor; - final RouteInformationParser? routeInformationParser; + /// {@macro flutter.widgets.widgetsApp.locale} + final Locale? locale; - final RouteInformationProvider? routeInformationProvider; + /// {@macro flutter.widgets.widgetsApp.localizationsDelegates} + final Iterable>? localizationsDelegates; - final RouterDelegate? routerDelegate; + /// {@macro flutter.widgets.widgetsApp.localeListResolutionCallback} + /// + /// This callback is passed along to the [WidgetsApp] built by this widget. + final LocaleListResolutionCallback? localeListResolutionCallback; - final Map? routes; + /// {@macro flutter.widgets.LocaleResolutionCallback} + /// + /// This callback is passed along to the [WidgetsApp] built by this widget. + final LocaleResolutionCallback? localeResolutionCallback; - final Map? shortcuts; + /// {@macro flutter.widgets.widgetsApp.supportedLocales} + /// + /// It is passed along unmodified to the [WidgetsApp] built by this widget. + final Iterable supportedLocales; + /// Turns on a performance overlay. + /// + /// See also: + /// + /// * final bool showPerformanceOverlay; - static bool showPerformanceOverlayOverride = false; + /// Turns on checkerboarding of raster cache images. + final bool checkerboardRasterCacheImages; + /// Turns on checkerboarding of layers rendered to offscreen bitmaps. + final bool checkerboardOffscreenLayers; + + /// Turns on an overlay that shows the accessibility information + /// reported by the framework. final bool showSemanticsDebugger; - final Style? style; + /// {@macro flutter.widgets.widgetsApp.debugShowCheckedModeBanner} + final bool debugShowCheckedModeBanner; - final Iterable supportedLocales; + /// {@macro flutter.widgets.widgetsApp.shortcuts} + /// {@tool snippet} + /// This example shows how to add a single shortcut for + /// [LogicalKeyboardKey.select] to the default shortcuts without needing to + /// add your own [Shortcuts] widget. + /// + /// Alternatively, you could insert a [Shortcuts] widget with just the mapping + /// you want to add between the [WidgetsApp] and its child and get the same + /// effect. + /// + /// ```dart + /// Widget build(BuildContext context) { + /// return WidgetsApp( + /// shortcuts: { + /// ... WidgetsApp.defaultShortcuts, + /// LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(), + /// }, + /// color: const Color(0xFFFF0000), + /// builder: (BuildContext context, Widget? child) { + /// return const Placeholder(); + /// }, + /// ); + /// } + /// ``` + /// {@end-tool} + /// {@macro flutter.widgets.widgetsApp.shortcuts.seeAlso} + final Map? shortcuts; + + /// {@macro flutter.widgets.widgetsApp.actions} + /// {@tool snippet} + /// This example shows how to add a single action handling an + /// [ActivateAction] to the default actions without needing to + /// add your own [Actions] widget. + /// + /// Alternatively, you could insert a [Actions] widget with just the mapping + /// you want to add between the [WidgetsApp] and its child and get the same + /// effect. + /// + /// ```dart + /// Widget build(BuildContext context) { + /// return WidgetsApp( + /// actions: >{ + /// ... WidgetsApp.defaultActions, + /// ActivateAction: CallbackAction( + /// onInvoke: (Intent intent) { + /// // Do something here... + /// return null; + /// }, + /// ), + /// }, + /// color: const Color(0xFFFF0000), + /// builder: (BuildContext context, Widget? child) { + /// return const Placeholder(); + /// }, + /// ); + /// } + /// ``` + /// {@end-tool} + /// {@macro flutter.widgets.widgetsApp.actions.seeAlso} + final Map>? actions; + /// {@macro flutter.widgets.widgetsApp.restorationScopeId} + final String? restorationScopeId; + + /// The current theme mode. final ThemeMode? themeMode; - final String title; + /// The style used if [themeMode] is [ThemeMode.dark] + final Style? darkStyle; + + /// The style used if [themeMode] is [ThemeMode.light] + final Style? style; @override _MacosAppState createState() => _MacosAppState(); @@ -191,15 +317,13 @@ class _MacosAppState extends State { Widget _builder(BuildContext context, Widget? child) { final theme = this.theme(context); - return m.Material( - child: MacosTheme( - style: theme, - child: DefaultTextStyle( - style: TextStyle( - color: theme.typography?.body?.color, - ), - child: child!, + return MacosTheme( + style: theme, + child: DefaultTextStyle( + style: TextStyle( + color: theme.typography?.body?.color, ), + child: child!, ), ); } @@ -207,7 +331,7 @@ class _MacosAppState extends State { Widget _buildApp(BuildContext context) { final defaultColor = widget.primaryColor ?? CupertinoColors.systemBlue; if (_usesRouter) { - return m.MaterialApp.router( + return c.CupertinoApp.router( key: GlobalObjectKey(this), routeInformationProvider: widget.routeInformationProvider, routeInformationParser: widget.routeInformationParser!, @@ -230,7 +354,7 @@ class _MacosAppState extends State { actions: widget.actions, ); } - return m.MaterialApp( + return c.CupertinoApp( key: GlobalObjectKey(this), navigatorKey: widget.navigatorKey, navigatorObservers: widget.navigatorObservers!,