"Fossies" - the Fresh Open Source Software Archive

Member "flutter-1.22.4/dev/integration_tests/flutter_gallery/lib/gallery/options.dart" (13 Nov 2020, 16479 Bytes) of package /linux/misc/flutter-1.22.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Dart source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2014 The Flutter Authors. All rights reserved.
    2 // Use of this source code is governed by a BSD-style license that can be
    3 // found in the LICENSE file.
    4 
    5 import 'package:flutter/material.dart';
    6 
    7 import 'about.dart';
    8 import 'scales.dart';
    9 
   10 @immutable
   11 class GalleryOptions {
   12   const GalleryOptions({
   13     this.themeMode,
   14     this.textScaleFactor,
   15     this.visualDensity,
   16     this.textDirection = TextDirection.ltr,
   17     this.timeDilation = 1.0,
   18     this.platform,
   19     this.showOffscreenLayersCheckerboard = false,
   20     this.showRasterCacheImagesCheckerboard = false,
   21     this.showPerformanceOverlay = false,
   22   });
   23 
   24   final ThemeMode themeMode;
   25   final GalleryTextScaleValue textScaleFactor;
   26   final GalleryVisualDensityValue visualDensity;
   27   final TextDirection textDirection;
   28   final double timeDilation;
   29   final TargetPlatform platform;
   30   final bool showPerformanceOverlay;
   31   final bool showRasterCacheImagesCheckerboard;
   32   final bool showOffscreenLayersCheckerboard;
   33 
   34   GalleryOptions copyWith({
   35     ThemeMode themeMode,
   36     GalleryTextScaleValue textScaleFactor,
   37     GalleryVisualDensityValue visualDensity,
   38     TextDirection textDirection,
   39     double timeDilation,
   40     TargetPlatform platform,
   41     bool showPerformanceOverlay,
   42     bool showRasterCacheImagesCheckerboard,
   43     bool showOffscreenLayersCheckerboard,
   44   }) {
   45     return GalleryOptions(
   46       themeMode: themeMode ?? this.themeMode,
   47       textScaleFactor: textScaleFactor ?? this.textScaleFactor,
   48       visualDensity: visualDensity ?? this.visualDensity,
   49       textDirection: textDirection ?? this.textDirection,
   50       timeDilation: timeDilation ?? this.timeDilation,
   51       platform: platform ?? this.platform,
   52       showPerformanceOverlay: showPerformanceOverlay ?? this.showPerformanceOverlay,
   53       showOffscreenLayersCheckerboard: showOffscreenLayersCheckerboard ?? this.showOffscreenLayersCheckerboard,
   54       showRasterCacheImagesCheckerboard: showRasterCacheImagesCheckerboard ?? this.showRasterCacheImagesCheckerboard,
   55     );
   56   }
   57 
   58   @override
   59   bool operator ==(Object other) {
   60     if (other.runtimeType != runtimeType)
   61       return false;
   62     return other is GalleryOptions
   63         && other.themeMode == themeMode
   64         && other.textScaleFactor == textScaleFactor
   65         && other.visualDensity == visualDensity
   66         && other.textDirection == textDirection
   67         && other.platform == platform
   68         && other.showPerformanceOverlay == showPerformanceOverlay
   69         && other.showRasterCacheImagesCheckerboard == showRasterCacheImagesCheckerboard
   70         && other.showOffscreenLayersCheckerboard == showRasterCacheImagesCheckerboard;
   71   }
   72 
   73   @override
   74   int get hashCode => hashValues(
   75     themeMode,
   76     textScaleFactor,
   77     visualDensity,
   78     textDirection,
   79     timeDilation,
   80     platform,
   81     showPerformanceOverlay,
   82     showRasterCacheImagesCheckerboard,
   83     showOffscreenLayersCheckerboard,
   84   );
   85 
   86   @override
   87   String toString() {
   88     return '$runtimeType($themeMode)';
   89   }
   90 }
   91 
   92 const double _kItemHeight = 48.0;
   93 const EdgeInsetsDirectional _kItemPadding = EdgeInsetsDirectional.only(start: 56.0);
   94 
   95 class _OptionsItem extends StatelessWidget {
   96   const _OptionsItem({ Key key, this.child }) : super(key: key);
   97 
   98   final Widget child;
   99 
  100   @override
  101   Widget build(BuildContext context) {
  102     final double textScaleFactor = MediaQuery.textScaleFactorOf(context);
  103 
  104     return MergeSemantics(
  105       child: Container(
  106         constraints: BoxConstraints(minHeight: _kItemHeight * textScaleFactor),
  107         padding: _kItemPadding,
  108         alignment: AlignmentDirectional.centerStart,
  109         child: DefaultTextStyle(
  110           style: DefaultTextStyle.of(context).style,
  111           maxLines: 2,
  112           overflow: TextOverflow.fade,
  113           child: IconTheme(
  114             data: Theme.of(context).primaryIconTheme,
  115             child: child,
  116           ),
  117         ),
  118       ),
  119     );
  120   }
  121 }
  122 
  123 class _BooleanItem extends StatelessWidget {
  124   const _BooleanItem(this.title, this.value, this.onChanged, { this.switchKey });
  125 
  126   final String title;
  127   final bool value;
  128   final ValueChanged<bool> onChanged;
  129   // [switchKey] is used for accessing the switch from driver tests.
  130   final Key switchKey;
  131 
  132   @override
  133   Widget build(BuildContext context) {
  134     final bool isDark = Theme.of(context).brightness == Brightness.dark;
  135     return _OptionsItem(
  136       child: Row(
  137         children: <Widget>[
  138           Expanded(child: Text(title)),
  139           Switch(
  140             key: switchKey,
  141             value: value,
  142             onChanged: onChanged,
  143             activeColor: const Color(0xFF39CEFD),
  144             activeTrackColor: isDark ? Colors.white30 : Colors.black26,
  145           ),
  146         ],
  147       ),
  148     );
  149   }
  150 }
  151 
  152 class _ActionItem extends StatelessWidget {
  153   const _ActionItem(this.text, this.onTap);
  154 
  155   final String text;
  156   final VoidCallback onTap;
  157 
  158   @override
  159   Widget build(BuildContext context) {
  160     return _OptionsItem(
  161       child: _FlatButton(
  162         onPressed: onTap,
  163         child: Text(text),
  164       ),
  165     );
  166   }
  167 }
  168 
  169 class _FlatButton extends StatelessWidget {
  170   const _FlatButton({ Key key, this.onPressed, this.child }) : super(key: key);
  171 
  172   final VoidCallback onPressed;
  173   final Widget child;
  174 
  175   @override
  176   Widget build(BuildContext context) {
  177     return FlatButton(
  178       padding: EdgeInsets.zero,
  179       onPressed: onPressed,
  180       child: DefaultTextStyle(
  181         style: Theme.of(context).primaryTextTheme.subtitle1,
  182         child: child,
  183       ),
  184     );
  185   }
  186 }
  187 
  188 class _Heading extends StatelessWidget {
  189   const _Heading(this.text);
  190 
  191   final String text;
  192 
  193   @override
  194   Widget build(BuildContext context) {
  195     final ThemeData theme = Theme.of(context);
  196     return _OptionsItem(
  197       child: DefaultTextStyle(
  198         style: theme.textTheme.headline6.copyWith(
  199           fontFamily: 'GoogleSans',
  200           color: theme.colorScheme.onPrimary,
  201           fontWeight: FontWeight.w700,
  202         ),
  203         child: Semantics(
  204           child: Text(text),
  205           header: true,
  206         ),
  207       ),
  208     );
  209   }
  210 }
  211 
  212 class _ThemeModeItem extends StatelessWidget {
  213   const _ThemeModeItem(this.options, this.onOptionsChanged);
  214 
  215   final GalleryOptions options;
  216   final ValueChanged<GalleryOptions> onOptionsChanged;
  217 
  218   static final Map<ThemeMode, String> modeLabels = <ThemeMode, String>{
  219     ThemeMode.system: 'System Default',
  220     ThemeMode.light: 'Light',
  221     ThemeMode.dark: 'Dark',
  222   };
  223 
  224   @override
  225   Widget build(BuildContext context) {
  226     return _OptionsItem(
  227       child: Row(
  228         children: <Widget>[
  229           Expanded(
  230             child: Column(
  231               crossAxisAlignment: CrossAxisAlignment.start,
  232               children: <Widget>[
  233                 const Text('Theme'),
  234                 Text(
  235                   modeLabels[options.themeMode],
  236                   style: Theme.of(context).primaryTextTheme.bodyText2,
  237                 ),
  238               ],
  239             ),
  240           ),
  241           PopupMenuButton<ThemeMode>(
  242             padding: const EdgeInsetsDirectional.only(end: 16.0),
  243             icon: const Icon(Icons.arrow_drop_down),
  244             initialValue: options.themeMode,
  245             itemBuilder: (BuildContext context) {
  246               return ThemeMode.values.map<PopupMenuItem<ThemeMode>>((ThemeMode mode) {
  247                 return PopupMenuItem<ThemeMode>(
  248                   value: mode,
  249                   child: Text(modeLabels[mode]),
  250                 );
  251               }).toList();
  252             },
  253             onSelected: (ThemeMode mode) {
  254               onOptionsChanged(
  255                 options.copyWith(themeMode: mode),
  256               );
  257             },
  258           ),
  259         ],
  260       ),
  261     );
  262   }
  263 }
  264 
  265 class _TextScaleFactorItem extends StatelessWidget {
  266   const _TextScaleFactorItem(this.options, this.onOptionsChanged);
  267 
  268   final GalleryOptions options;
  269   final ValueChanged<GalleryOptions> onOptionsChanged;
  270 
  271   @override
  272   Widget build(BuildContext context) {
  273     return _OptionsItem(
  274       child: Row(
  275         children: <Widget>[
  276           Expanded(
  277             child: Column(
  278               crossAxisAlignment: CrossAxisAlignment.start,
  279               children: <Widget>[
  280                 const Text('Text size'),
  281                 Text(
  282                   options.textScaleFactor.label,
  283                   style: Theme.of(context).primaryTextTheme.bodyText2,
  284                 ),
  285               ],
  286             ),
  287           ),
  288           PopupMenuButton<GalleryTextScaleValue>(
  289             padding: const EdgeInsetsDirectional.only(end: 16.0),
  290             icon: const Icon(Icons.arrow_drop_down),
  291             itemBuilder: (BuildContext context) {
  292               return kAllGalleryTextScaleValues.map<PopupMenuItem<GalleryTextScaleValue>>((GalleryTextScaleValue scaleValue) {
  293                 return PopupMenuItem<GalleryTextScaleValue>(
  294                   value: scaleValue,
  295                   child: Text(scaleValue.label),
  296                 );
  297               }).toList();
  298             },
  299             onSelected: (GalleryTextScaleValue scaleValue) {
  300               onOptionsChanged(
  301                 options.copyWith(textScaleFactor: scaleValue),
  302               );
  303             },
  304           ),
  305         ],
  306       ),
  307     );
  308   }
  309 }
  310 
  311 class _VisualDensityItem extends StatelessWidget {
  312   const _VisualDensityItem(this.options, this.onOptionsChanged);
  313 
  314   final GalleryOptions options;
  315   final ValueChanged<GalleryOptions> onOptionsChanged;
  316 
  317   @override
  318   Widget build(BuildContext context) {
  319     return _OptionsItem(
  320       child: Row(
  321         children: <Widget>[
  322           Expanded(
  323             child: Column(
  324               crossAxisAlignment: CrossAxisAlignment.start,
  325               children: <Widget>[
  326                 const Text('Visual density'),
  327                 Text(
  328                   options.visualDensity.label,
  329                   style: Theme.of(context).primaryTextTheme.bodyText2,
  330                 ),
  331               ],
  332             ),
  333           ),
  334           PopupMenuButton<GalleryVisualDensityValue>(
  335             padding: const EdgeInsetsDirectional.only(end: 16.0),
  336             icon: const Icon(Icons.arrow_drop_down),
  337             itemBuilder: (BuildContext context) {
  338               return kAllGalleryVisualDensityValues.map<PopupMenuItem<GalleryVisualDensityValue>>((GalleryVisualDensityValue densityValue) {
  339                 return PopupMenuItem<GalleryVisualDensityValue>(
  340                   value: densityValue,
  341                   child: Text(densityValue.label),
  342                 );
  343               }).toList();
  344             },
  345             onSelected: (GalleryVisualDensityValue densityValue) {
  346               onOptionsChanged(
  347                 options.copyWith(visualDensity: densityValue),
  348               );
  349             },
  350           ),
  351         ],
  352       ),
  353     );
  354   }
  355 }
  356 
  357 class _TextDirectionItem extends StatelessWidget {
  358   const _TextDirectionItem(this.options, this.onOptionsChanged);
  359 
  360   final GalleryOptions options;
  361   final ValueChanged<GalleryOptions> onOptionsChanged;
  362 
  363   @override
  364   Widget build(BuildContext context) {
  365     return _BooleanItem(
  366       'Force RTL',
  367       options.textDirection == TextDirection.rtl,
  368       (bool value) {
  369         onOptionsChanged(
  370           options.copyWith(
  371             textDirection: value ? TextDirection.rtl : TextDirection.ltr,
  372           ),
  373         );
  374       },
  375       switchKey: const Key('text_direction'),
  376     );
  377   }
  378 }
  379 
  380 class _TimeDilationItem extends StatelessWidget {
  381   const _TimeDilationItem(this.options, this.onOptionsChanged);
  382 
  383   final GalleryOptions options;
  384   final ValueChanged<GalleryOptions> onOptionsChanged;
  385 
  386   @override
  387   Widget build(BuildContext context) {
  388     return _BooleanItem(
  389       'Slow motion',
  390       options.timeDilation != 1.0,
  391       (bool value) {
  392         onOptionsChanged(
  393           options.copyWith(
  394             timeDilation: value ? 20.0 : 1.0,
  395           ),
  396         );
  397       },
  398       switchKey: const Key('slow_motion'),
  399     );
  400   }
  401 }
  402 
  403 class _PlatformItem extends StatelessWidget {
  404   const _PlatformItem(this.options, this.onOptionsChanged);
  405 
  406   final GalleryOptions options;
  407   final ValueChanged<GalleryOptions> onOptionsChanged;
  408 
  409   String _platformLabel(TargetPlatform platform) {
  410     switch(platform) {
  411       case TargetPlatform.android:
  412         return 'Mountain View';
  413       case TargetPlatform.fuchsia:
  414         return 'Fuchsia';
  415       case TargetPlatform.iOS:
  416         return 'Cupertino';
  417       case TargetPlatform.linux:
  418         return 'Material Desktop (linux)';
  419       case TargetPlatform.macOS:
  420         return 'Material Desktop (macOS)';
  421       case TargetPlatform.windows:
  422         return 'Material Desktop (Windows)';
  423     }
  424     assert(false);
  425     return null;
  426   }
  427 
  428   @override
  429   Widget build(BuildContext context) {
  430     return _OptionsItem(
  431       child: Row(
  432         children: <Widget>[
  433           Expanded(
  434             child: Column(
  435               crossAxisAlignment: CrossAxisAlignment.start,
  436               children: <Widget>[
  437                 const Text('Platform mechanics'),
  438                  Text(
  439                    _platformLabel(options.platform),
  440                    style: Theme.of(context).primaryTextTheme.bodyText2,
  441                  ),
  442               ],
  443             ),
  444           ),
  445           PopupMenuButton<TargetPlatform>(
  446             padding: const EdgeInsetsDirectional.only(end: 16.0),
  447             icon: const Icon(Icons.arrow_drop_down),
  448             itemBuilder: (BuildContext context) {
  449               return TargetPlatform.values.map((TargetPlatform platform) {
  450                 return PopupMenuItem<TargetPlatform>(
  451                   value: platform,
  452                   child: Text(_platformLabel(platform)),
  453                 );
  454               }).toList();
  455             },
  456             onSelected: (TargetPlatform platform) {
  457               onOptionsChanged(
  458                 options.copyWith(platform: platform),
  459               );
  460             },
  461           ),
  462         ],
  463       ),
  464     );
  465   }
  466 }
  467 
  468 class GalleryOptionsPage extends StatelessWidget {
  469   const GalleryOptionsPage({
  470     Key key,
  471     this.options,
  472     this.onOptionsChanged,
  473     this.onSendFeedback,
  474   }) : super(key: key);
  475 
  476   final GalleryOptions options;
  477   final ValueChanged<GalleryOptions> onOptionsChanged;
  478   final VoidCallback onSendFeedback;
  479 
  480   List<Widget> _enabledDiagnosticItems() {
  481     // Boolean showFoo options with a value of null: don't display
  482     // the showFoo option at all.
  483     if (options.showOffscreenLayersCheckerboard == null &&
  484         options.showRasterCacheImagesCheckerboard == null &&
  485         options.showPerformanceOverlay == null)
  486       return const <Widget>[];
  487 
  488     return <Widget>[
  489       const Divider(),
  490       const _Heading('Diagnostics'),
  491       if (options.showOffscreenLayersCheckerboard != null)
  492         _BooleanItem(
  493           'Highlight offscreen layers',
  494           options.showOffscreenLayersCheckerboard,
  495           (bool value) {
  496             onOptionsChanged(options.copyWith(showOffscreenLayersCheckerboard: value));
  497           },
  498         ),
  499       if (options.showRasterCacheImagesCheckerboard != null)
  500         _BooleanItem(
  501           'Highlight raster cache images',
  502           options.showRasterCacheImagesCheckerboard,
  503           (bool value) {
  504             onOptionsChanged(options.copyWith(showRasterCacheImagesCheckerboard: value));
  505           },
  506         ),
  507       if (options.showPerformanceOverlay != null)
  508         _BooleanItem(
  509           'Show performance overlay',
  510           options.showPerformanceOverlay,
  511           (bool value) {
  512             onOptionsChanged(options.copyWith(showPerformanceOverlay: value));
  513           },
  514         ),
  515     ];
  516   }
  517 
  518   @override
  519   Widget build(BuildContext context) {
  520     final ThemeData theme = Theme.of(context);
  521 
  522     return DefaultTextStyle(
  523       style: theme.primaryTextTheme.subtitle1,
  524       child: ListView(
  525         padding: const EdgeInsets.only(bottom: 124.0),
  526         children: <Widget>[
  527           const _Heading('Display'),
  528           _ThemeModeItem(options, onOptionsChanged),
  529           _TextScaleFactorItem(options, onOptionsChanged),
  530           _VisualDensityItem(options, onOptionsChanged),
  531           _TextDirectionItem(options, onOptionsChanged),
  532           _TimeDilationItem(options, onOptionsChanged),
  533           const Divider(),
  534           const ExcludeSemantics(child: _Heading('Platform mechanics')),
  535           _PlatformItem(options, onOptionsChanged),
  536           ..._enabledDiagnosticItems(),
  537           const Divider(),
  538           const _Heading('Flutter gallery'),
  539           _ActionItem('About Flutter Gallery', () {
  540             showGalleryAboutDialog(context);
  541           }),
  542           _ActionItem('Send feedback', onSendFeedback),
  543         ],
  544       ),
  545     );
  546   }
  547 }