using System; using System.Collections.Generic; using System.Linq; using System.Text; using Unity.UIWidgets.async2; using Unity.UIWidgets.engine; using Unity.UIWidgets.foundation; using Unity.UIWidgets.gestures; using Unity.UIWidgets.painting; using Unity.UIWidgets.services; using Unity.UIWidgets.ui; using Unity.UIWidgets.widgets; using UnityEngine; using Color = Unity.UIWidgets.ui.Color; using TextStyle = Unity.UIWidgets.painting.TextStyle; namespace Unity.UIWidgets.widgets { public delegate Locale LocaleListResolutionCallback(List locales, List supportedLocales); public delegate Locale LocaleResolutionCallback(Locale locale, List supportedLocales); public delegate string GenerateAppTitle(BuildContext context); public delegate PageRoute PageRouteFactory(RouteSettings settings, WidgetBuilder builder); public delegate List InitialRouteListFactory(string initialRoute); public class WidgetsApp : StatefulWidget { public readonly TransitionBuilder builder; public readonly Widget home; public readonly string initialRoute; public readonly GlobalKey navigatorKey; public readonly List navigatorObservers; public readonly RouteFactory onGenerateRoute; public readonly InitialRouteListFactory onGenerateInitialRoutes; public readonly RouteFactory onUnknownRoute; public readonly PageRouteFactory pageRouteBuilder; public readonly Dictionary routes; public readonly TextStyle textStyle; public readonly Window window; public readonly bool showPerformanceOverlay; public readonly Locale locale; public readonly List localizationsDelegates; public readonly LocaleListResolutionCallback localeListResolutionCallback; public readonly LocaleResolutionCallback localeResolutionCallback; public readonly List supportedLocales; public readonly string title; public readonly GenerateAppTitle onGenerateTitle; public readonly Color color; public readonly InspectorSelectButtonBuilder inspectorSelectButtonBuilder; public static bool showPerformanceOverlayOverride = false; public static bool debugShowWidgetInspectorOverride = false; public static bool debugAllowBannerOverride = true; public readonly bool debugShowCheckedModeBanner; public readonly bool checkerboardRasterCacheImages; public readonly bool checkerboardOffscreenLayers; public readonly bool showSemanticsDebugger; public readonly bool debugShowWidgetInspector; public readonly Dictionary shortcuts; public readonly Dictionary actions; public WidgetsApp( Key key = null, GlobalKey navigatorKey = null, RouteFactory onGenerateRoute = null, InitialRouteListFactory onGenerateInitialRoutes = null, RouteFactory onUnknownRoute = null, List navigatorObservers = null, string initialRoute = null, PageRouteFactory pageRouteBuilder = null, Widget home = null, Dictionary routes = null, TransitionBuilder builder = null, string title = "", GenerateAppTitle onGenerateTitle = null, TextStyle textStyle = null, Color color = null, Locale locale = null, List localizationsDelegates = null, LocaleListResolutionCallback localeListResolutionCallback = null, LocaleResolutionCallback localeResolutionCallback = null, List supportedLocales = null, bool showPerformanceOverlay = false, bool checkerboardRasterCacheImages = false, bool checkerboardOffscreenLayers = false, bool showSemanticsDebugger = false, bool debugShowWidgetInspector = false, bool debugShowCheckedModeBanner = true, InspectorSelectButtonBuilder inspectorSelectButtonBuilder = null, Dictionary shortcuts = null, Dictionary actions = null ) : base(key) { routes = routes ?? new Dictionary(); supportedLocales = supportedLocales ?? new List {new Locale("en", "US")}; window = Window.instance; D.assert(routes != null); D.assert(color != null); D.assert(supportedLocales != null && supportedLocales.isNotEmpty()); this.home = home; this.navigatorKey = navigatorKey; this.onGenerateRoute = onGenerateRoute; this.onGenerateInitialRoutes = onGenerateInitialRoutes; this.onUnknownRoute = onUnknownRoute; this.pageRouteBuilder = pageRouteBuilder; this.routes = routes; this.navigatorObservers = navigatorObservers ?? new List(); this.initialRoute = initialRoute; this.builder = builder; this.textStyle = textStyle; this.locale = locale; this.localizationsDelegates = localizationsDelegates; this.localeListResolutionCallback = localeListResolutionCallback; this.localeResolutionCallback = localeResolutionCallback; this.supportedLocales = supportedLocales; this.showPerformanceOverlay = showPerformanceOverlay; this.checkerboardOffscreenLayers = checkerboardOffscreenLayers; this.checkerboardRasterCacheImages = checkerboardRasterCacheImages; this.showSemanticsDebugger = showSemanticsDebugger; this.debugShowWidgetInspector = debugShowWidgetInspector; this.debugShowCheckedModeBanner = debugShowCheckedModeBanner; this.onGenerateTitle = onGenerateTitle; this.title = title; this.color = color; this.inspectorSelectButtonBuilder = inspectorSelectButtonBuilder; this.shortcuts = shortcuts; this.actions = actions; D.assert( home == null || onGenerateInitialRoutes == null, () => "If onGenerateInitialRoutes is specifiied, the home argument will be redundant." ); D.assert( home == null || !this.routes.ContainsKey(Navigator.defaultRouteName), () => "If the home property is specified, the routes table " + "cannot include an entry for \" / \", since it would be redundant." ); D.assert( builder != null || home != null || this.routes.ContainsKey(Navigator.defaultRouteName) || onGenerateRoute != null || onUnknownRoute != null, () => "Either the home property must be specified, " + "or the routes table must include an entry for \"/\", " + "or there must be on onGenerateRoute callback specified, " + "or there must be an onUnknownRoute callback specified, " + "or the builder property must be specified, " + "because otherwise there is nothing to fall back on if the " + "app is started with an intent that specifies an unknown route." ); D.assert( (home != null || routes.isNotEmpty() || onGenerateRoute != null || onUnknownRoute != null) || (builder != null && navigatorKey == null && initialRoute == null && navigatorObservers.isEmpty()),()=> "If no route is provided using " + "home, routes, onGenerateRoute, or onUnknownRoute, " + "a non-null callback for the builder property must be provided, " + "and the other navigator-related properties, " + "navigatorKey, initialRoute, and navigatorObservers, " + "must have their initial values " + "(null, null, and the empty list, respectively)."); D.assert( builder != null || onGenerateRoute != null || pageRouteBuilder != null, () => "If neither builder nor onGenerateRoute are provided, the " + "pageRouteBuilder must be specified so that the default handler " + "will know what kind of PageRoute transition to build." ); } public static readonly Dictionary _defaultShortcuts = new Dictionary(){ // Activation {new LogicalKeySet(LogicalKeyboardKey.enter), new Intent(ActivateAction.key)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.space), new Intent(ActivateAction.key)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.gameButtonA), new Intent(ActivateAction.key)}, // Keyboard traversal. {new widgets.LogicalKeySet(LogicalKeyboardKey.tab), new Intent(NextFocusAction.key)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.shift, LogicalKeyboardKey.tab), new Intent(PreviousFocusAction.key)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowLeft), new DirectionalFocusIntent(TraversalDirection.left)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowRight), new DirectionalFocusIntent(TraversalDirection.right)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowDown), new DirectionalFocusIntent(TraversalDirection.down)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowUp), new DirectionalFocusIntent(TraversalDirection.up)}, // Scrolling {new widgets.LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowUp), new ScrollIntent(direction: AxisDirection.up)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowDown), new ScrollIntent(direction: AxisDirection.down)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowLeft), new ScrollIntent(direction: AxisDirection.left)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.arrowRight), new ScrollIntent(direction: AxisDirection.right)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.pageUp), new ScrollIntent(direction: AxisDirection.up, type: ScrollIncrementType.page)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.pageDown), new ScrollIntent(direction: AxisDirection.down, type: ScrollIncrementType.page)}, }; // Default shortcuts for the web platform. public static readonly Dictionary _defaultWebShortcuts = new Dictionary(){ // Activation {new widgets.LogicalKeySet(LogicalKeyboardKey.space), new Intent(ActivateAction.key)}, // Keyboard traversal. {new widgets.LogicalKeySet(LogicalKeyboardKey.tab), new Intent(NextFocusAction.key)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.shift, LogicalKeyboardKey.tab),new Intent(PreviousFocusAction.key)}, // Scrolling {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowUp), new ScrollIntent(direction: AxisDirection.up)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowDown), new ScrollIntent(direction: AxisDirection.down)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowLeft), new ScrollIntent(direction: AxisDirection.left)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.arrowRight), new ScrollIntent(direction: AxisDirection.right)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.pageUp), new ScrollIntent(direction: AxisDirection.up, type: ScrollIncrementType.page)}, {new widgets.LogicalKeySet(LogicalKeyboardKey.pageDown), new ScrollIntent(direction: AxisDirection.down, type: ScrollIncrementType.page)}, }; // Default shortcuts for the macOS platform. public static readonly Dictionary _defaultMacOsShortcuts = new Dictionary(){ // Activation {new LogicalKeySet(LogicalKeyboardKey.enter), new Intent(ActivateAction.key)}, {new LogicalKeySet(LogicalKeyboardKey.space), new Intent(ActivateAction.key)}, // Keyboard traversal {new LogicalKeySet(LogicalKeyboardKey.tab), new Intent(NextFocusAction.key)}, {new LogicalKeySet(LogicalKeyboardKey.shift, LogicalKeyboardKey.tab), new Intent(PreviousFocusAction.key)}, {new LogicalKeySet(LogicalKeyboardKey.arrowLeft), new DirectionalFocusIntent(TraversalDirection.left)}, {new LogicalKeySet(LogicalKeyboardKey.arrowRight), new DirectionalFocusIntent(TraversalDirection.right)}, {new LogicalKeySet(LogicalKeyboardKey.arrowDown), new DirectionalFocusIntent(TraversalDirection.down)}, {new LogicalKeySet(LogicalKeyboardKey.arrowUp), new DirectionalFocusIntent(TraversalDirection.up)}, // Scrolling {new LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowUp), new ScrollIntent(direction: AxisDirection.up)}, {new LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowDown), new ScrollIntent(direction: AxisDirection.down)}, {new LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowLeft), new ScrollIntent(direction: AxisDirection.left)}, {new LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.arrowRight), new ScrollIntent(direction: AxisDirection.right)}, {new LogicalKeySet(LogicalKeyboardKey.pageUp), new ScrollIntent(direction: AxisDirection.up, type: ScrollIncrementType.page)}, {new LogicalKeySet(LogicalKeyboardKey.pageDown), new ScrollIntent(direction: AxisDirection.down, type: ScrollIncrementType.page)}, }; public static Dictionary defaultShortcuts { get { if (foundation_.kIsWeb) { return _defaultWebShortcuts; } switch (Application.platform) { case RuntimePlatform.Android: //case TargetPlatform.fuchsia: case RuntimePlatform.LinuxPlayer: case RuntimePlatform.WindowsPlayer: return _defaultShortcuts; case RuntimePlatform.OSXPlayer: return _defaultMacOsShortcuts; case RuntimePlatform.IPhonePlayer: // No keyboard support on iOS yet. break; } return new Dictionary(); } } /// The default value of [WidgetsApp.actions]. public static readonly Dictionary defaultActions = new Dictionary(){ {DoNothingAction.key, () => new DoNothingAction()}, {RequestFocusAction.key, () => new RequestFocusAction()}, {NextFocusAction.key, () => new NextFocusAction()}, {PreviousFocusAction.key, () => new PreviousFocusAction()}, {DirectionalFocusAction.key, () => new DirectionalFocusAction()}, {ScrollAction.key, () => new ScrollAction()}, }; public override State createState() { return new _WidgetsAppState(); } } class _WidgetsAppState : State, WidgetsBindingObserver { public void didChangeMetrics() { setState(); } public void didChangeTextScaleFactor() { setState(); } public void didChangePlatformBrightness() { setState(() => { }); } public void didChangeLocales(List locale) { Locale newLocale = _resolveLocales(locale, widget.supportedLocales); if (newLocale != _locale) { setState(() => { _locale = newLocale; }); } } List _localizationsDelegates { get { List _delegates = new List(); if (widget.localizationsDelegates != null) { _delegates.AddRange(widget.localizationsDelegates); } _delegates.Add(DefaultWidgetsLocalizations.del); return _delegates; } } public override void initState() { base.initState(); _updateNavigator(); _locale = _resolveLocales(new List {new Locale("en", "US")}, widget.supportedLocales); WidgetsBinding.instance.addObserver(this); } public override void didUpdateWidget(StatefulWidget oldWidget) { base.didUpdateWidget(oldWidget); if (widget.navigatorKey != ((WidgetsApp) oldWidget).navigatorKey) { _updateNavigator(); } } public override void dispose() { WidgetsBinding.instance.removeObserver(this); base.dispose(); } GlobalKey _navigator; void _updateNavigator() { _navigator = widget.navigatorKey ?? new GlobalObjectKey(this); } Route _onGenerateRoute(RouteSettings settings) { var name = settings.name; var pageContentBuilder = name == Navigator.defaultRouteName && widget.home != null ? context => widget.home : widget.routes.getOrDefault(name); if (pageContentBuilder != null) { D.assert(widget.pageRouteBuilder != null, () => "The default onGenerateRoute handler for WidgetsApp must have a " + "pageRouteBuilder set if the home or routes properties are set."); var route = widget.pageRouteBuilder( settings, pageContentBuilder ); D.assert(route != null, () => "The pageRouteBuilder for WidgetsApp must return a valid non-null Route."); return route; } if (widget.onGenerateRoute != null) { return widget.onGenerateRoute(settings); } return null; } public Future didPopRoute() { ///async D.assert(mounted); var navigator = _navigator?.currentState; if (navigator == null) { return Future.value(false).to(); } return navigator.maybePop(); } public Future didPushRoute(string route) { D.assert(mounted); var navigator = _navigator?.currentState; if (navigator == null) { return Future.value(false).to(); } navigator.pushNamed(route); return Future.value(true).to(); } public void didChangeAccessibilityFeatures() {} Route _onUnknownRoute(RouteSettings settings) { D.assert(() => { if (widget.onUnknownRoute == null) { throw new UIWidgetsError( $"Could not find a generator for route {settings} in the {GetType()}.\n" + $"Generators for routes are searched for in the following order:\n" + " 1. For the \"/\" route, the \"home\" property, if non-null, is used.\n" + " 2. Otherwise, the \"routes\" table is used, if it has an entry for " + "the route.\n" + " 3. Otherwise, onGenerateRoute is called. It should return a " + "non-null value for any valid route not handled by \"home\" and \"routes\".\n" + " 4. Finally if all else fails onUnknownRoute is called.\n" + "Unfortunately, onUnknownRoute was not set." ); } return true; }); var result = widget.onUnknownRoute(settings) as Route; D.assert(() => { if (result == null) { throw new UIWidgetsError( "The onUnknownRoute callback returned null.\n" + "When the $runtimeType requested the route $settings from its " + "onUnknownRoute callback, the callback returned null. Such callbacks " + "must never return null." ); } return true; }); return result; } Locale _locale; Locale _resolveLocales(List preferredLocales, List supportedLocales) { if (widget.localeListResolutionCallback != null) { Locale locale = widget.localeListResolutionCallback(preferredLocales, widget.supportedLocales); if (locale != null) { return locale; } } if (widget.localeResolutionCallback != null) { Locale locale = widget.localeResolutionCallback( preferredLocales != null && preferredLocales.isNotEmpty() ? preferredLocales.first() : null, widget.supportedLocales ); if (locale != null) { return locale; } } return basicLocaleListResolution(preferredLocales, supportedLocales); } static Locale basicLocaleListResolution(List preferredLocales, List supportedLocales) { if (preferredLocales == null || preferredLocales.isEmpty()) { return supportedLocales.first(); } Dictionary allSupportedLocales = new Dictionary(); Dictionary languageAndCountryLocales = new Dictionary(); Dictionary languageAndScriptLocales = new Dictionary(); Dictionary languageLocales = new Dictionary(); Dictionary countryLocales = new Dictionary(); foreach (Locale locale in supportedLocales) { allSupportedLocales.putIfAbsent( locale.languageCode + "_" + locale.scriptCode + "_" + locale.countryCode, () => locale); languageLocales.putIfAbsent(locale.languageCode, () => locale); countryLocales.putIfAbsent(locale.countryCode, () => locale); languageAndScriptLocales.putIfAbsent(locale.languageCode + "_" + locale.scriptCode, () => locale); languageAndCountryLocales.putIfAbsent(locale.languageCode + "_" + locale.countryCode, () => locale); } Locale matchesLanguageCode = null; Locale matchesCountryCode = null; for (int localeIndex = 0; localeIndex < preferredLocales.Count; localeIndex++) { Locale userLocale = preferredLocales[localeIndex]; if (allSupportedLocales.ContainsKey(userLocale.languageCode + "_" + userLocale.scriptCode + "_" + userLocale.countryCode)) { return userLocale; } if (userLocale.scriptCode != null) { Locale match = null; if (languageAndScriptLocales.TryGetValue(userLocale.languageCode + "_" + userLocale.scriptCode, out match)) { if (match != null) { return match; } } } if (userLocale.countryCode != null) { //Locale match = languageAndCountryLocales['${userLocale.languageCode}_${userLocale.countryCode}']; Locale match = null; if (languageAndCountryLocales.TryGetValue(userLocale.languageCode + "_" + userLocale.countryCode, out match)) { if (match != null) { return match; } } } if (matchesLanguageCode != null) { return matchesLanguageCode; } if (languageLocales.ContainsKey(userLocale.languageCode)) { matchesLanguageCode = languageLocales[userLocale.languageCode]; if (localeIndex == 0 && !(localeIndex + 1 < preferredLocales.Count && preferredLocales[localeIndex + 1].languageCode == userLocale.languageCode)) { return matchesLanguageCode; } } if (matchesCountryCode == null && userLocale.countryCode != null) { if (countryLocales.ContainsKey(userLocale.countryCode)) { matchesCountryCode = countryLocales[userLocale.countryCode]; } } } Locale resolvedLocale = matchesLanguageCode ?? matchesCountryCode ?? supportedLocales.first(); return resolvedLocale; } void inspectorShowChanged() { setState(); } bool _debugCheckLocalizations(Locale appLocale) { D.assert(() => { HashSet unsupportedTypes = new HashSet(); foreach (var _delegate in _localizationsDelegates) { unsupportedTypes.Add(_delegate.type); } foreach ( LocalizationsDelegate _delegate in _localizationsDelegates) { if (!unsupportedTypes.Contains(_delegate.type)) continue; if (_delegate.isSupported(appLocale)) unsupportedTypes.Remove(_delegate.type); } if (unsupportedTypes.isEmpty()) return true; List list = new List {"CupertinoLocalizations"}; List unsupportedTypesList = new List(); foreach (var type in unsupportedTypes) { unsupportedTypesList.Add(type.ToString()); } if (unsupportedTypesList.SequenceEqual(list)) return true; StringBuilder message = new StringBuilder(); message.Append('\u2550' * 8); message.Append( "Warning: This application's locale, $appLocale, is not supported by all of its\n" + "localization delegates." ); foreach ( Type unsupportedType in unsupportedTypes) { if (unsupportedType.ToString() == "CupertinoLocalizations") continue; message.Append( "> A "+ unsupportedType + " delegate that supports the " + appLocale + "locale was not found." ); } message.Append( "See https://flutter.dev/tutorials/internationalization/ for more\n" + "information about configuring an app's locale, supportedLocales,\n" + "and localizationsDelegates parameters." ); message.Append('\u2550' * 8); return true; }); return true; } public override Widget build(BuildContext context) { Widget navigator = null; if (_navigator != null) { RouteListFactory routeListFactory = (state, route) => {return widget.onGenerateInitialRoutes(route); }; navigator = new Navigator( key: _navigator, initialRoute: WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName ? WidgetsBinding.instance.window.defaultRouteName : widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName, onGenerateRoute: _onGenerateRoute, onGenerateInitialRoutes: widget.onGenerateInitialRoutes == null ? Navigator.defaultGenerateInitialRoutes : routeListFactory, onUnknownRoute: _onUnknownRoute, observers: widget.navigatorObservers ); } Widget result; if (widget.builder != null) { result = new Builder( builder: _context => { return widget.builder(_context, navigator); } ); } else { D.assert(navigator != null); result = navigator; } if (widget.textStyle != null) { result = new DefaultTextStyle( style: widget.textStyle, child: result ); } PerformanceOverlay performanceOverlay = null; if (widget.showPerformanceOverlay || WidgetsApp.showPerformanceOverlayOverride) { performanceOverlay = PerformanceOverlay.allEnabled( checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages, checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers ); } else if (widget.checkerboardRasterCacheImages || widget.checkerboardOffscreenLayers) { performanceOverlay = new PerformanceOverlay( checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages, checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers ); } if (performanceOverlay != null) { result = new Stack( children: new List { result, new Positioned(top: 0.0f, left: 0.0f, right: 0.0f, child: performanceOverlay) }); } D.assert(() => { if (widget.debugShowWidgetInspector || WidgetsApp.debugShowWidgetInspectorOverride) { result = new WidgetInspector( child: result, selectButtonBuilder: widget.inspectorSelectButtonBuilder ); } if (widget.debugShowCheckedModeBanner && WidgetsApp.debugAllowBannerOverride) { result = new CheckedModeBanner( child: result ); } return true; }); Widget title = null; if (widget.onGenerateTitle != null) { title = new Builder( builder: (BuildContext context1)=> { string title1 = widget.onGenerateTitle(context1); D.assert(title1 != null,()=> "onGenerateTitle must return a non-null String"); return new Title( title: title1, color: widget.color, child: result ); } ); } else { title = new Title( title: widget.title, color: widget.color, child: result ); } Locale appLocale = widget.locale != null ? _resolveLocales(new List {widget.locale}, widget.supportedLocales) : _locale; D.assert(_debugCheckLocalizations(appLocale)); result = new Shortcuts( shortcuts: widget.shortcuts ?? WidgetsApp.defaultShortcuts, debugLabel: "", child: new Actions( actions: widget.actions ?? WidgetsApp.defaultActions, child: new FocusTraversalGroup( policy: new ReadingOrderTraversalPolicy(), child: new _MediaQueryFromWindow( child: new Localizations( locale: appLocale, delegates: _localizationsDelegates.ToList(), child: title ) ) ) ) ); return result; } Widget _InspectorSelectButtonBuilder(BuildContext context, VoidCallback onPressed) { return new _InspectorSelectButton(onPressed); } } public class _MediaQueryFromWindow : StatefulWidget { public _MediaQueryFromWindow(Key key = null, Widget child = null) : base(key: key) { this.child = child; } public readonly Widget child; public override State createState() { return new _MediaQueryFromWindowsState(); } } class _MediaQueryFromWindowsState : State<_MediaQueryFromWindow>,WidgetsBindingObserver { public override void initState() { base.initState(); WidgetsBinding.instance.addObserver(this); } public void didChangeAccessibilityFeatures() { setState(()=> { }); } public void didChangeMetrics() { setState(()=>{ }); } public void didChangeTextScaleFactor() { setState(()=> { }); } public void didChangePlatformBrightness() { setState(()=> { }); } public void didChangeLocales(List locale) { throw new NotImplementedException(); } public Future didPopRoute() { throw new NotImplementedException(); } public Future didPushRoute(string route) { throw new NotImplementedException(); } public override Widget build(BuildContext context) { return new MediaQuery( data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), child: widget.child ); } public override void dispose() { WidgetsBinding.instance.removeObserver(this); base.dispose(); } } class _InspectorSelectButton : StatelessWidget { public readonly GestureTapCallback onPressed; public _InspectorSelectButton( VoidCallback onPressed, Key key = null ) : base(key) { this.onPressed = () => onPressed(); } public override Widget build(BuildContext context) { return new GestureDetector( onTap: onPressed, child: new Container( color: Color.fromARGB(255, 0, 0, 255), padding: EdgeInsets.all(10), child: new Text("Select", style: new TextStyle(color: Color.fromARGB(255, 255, 255, 255))) ) ); } } }