您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
632 行
25 KiB
632 行
25 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using uiwidgets;
|
|
using Unity.UIWidgets.foundation;
|
|
using Unity.UIWidgets.material;
|
|
using Unity.UIWidgets.painting;
|
|
using Unity.UIWidgets.rendering;
|
|
using Unity.UIWidgets.ui;
|
|
using Unity.UIWidgets.widgets;
|
|
using UnityEngine;
|
|
using Color = Unity.UIWidgets.ui.Color;
|
|
|
|
namespace UIWidgetsGallery.gallery
|
|
{
|
|
public static class GalleryOptionUtils
|
|
{
|
|
public const float _kItemHeight = 48.0f;
|
|
|
|
//TODO: uncomment this when fixes on EdgeInsetsDirectional lands
|
|
//public static readonly EdgeInsetsDirectional _kItemPadding = EdgeInsetsDirectional.only(start: 56.0f);
|
|
public static readonly EdgeInsets _kItemPadding = EdgeInsets.only(left: 56.0f);
|
|
}
|
|
|
|
public class GalleryOptions : IEquatable<GalleryOptions>
|
|
{
|
|
public GalleryOptions(
|
|
ThemeMode? themeMode = null,
|
|
GalleryTextScaleValue textScaleFactor = null,
|
|
GalleryVisualDensityValue visualDensity = null,
|
|
TextDirection? textDirection = null,
|
|
float timeDilation = 1.0f,
|
|
RuntimePlatform? platform = null,
|
|
bool showOffscreenLayersCheckerboard = false,
|
|
bool showRasterCacheImagesCheckerboard = false,
|
|
bool showPerformanceOverlay = false
|
|
)
|
|
{
|
|
textDirection = textDirection ?? TextDirection.ltr;
|
|
this.themeMode = themeMode;
|
|
this.textScaleFactor = textScaleFactor;
|
|
this.visualDensity = visualDensity;
|
|
this.textDirection = textDirection;
|
|
this.timeDilation = timeDilation;
|
|
this.platform = platform;
|
|
this.showOffscreenLayersCheckerboard = showOffscreenLayersCheckerboard;
|
|
this.showRasterCacheImagesCheckerboard = showRasterCacheImagesCheckerboard;
|
|
this.showPerformanceOverlay = showPerformanceOverlay;
|
|
}
|
|
|
|
public readonly ThemeMode? themeMode;
|
|
public readonly GalleryTextScaleValue textScaleFactor;
|
|
public readonly GalleryVisualDensityValue visualDensity;
|
|
public readonly TextDirection? textDirection;
|
|
public readonly float timeDilation;
|
|
public readonly RuntimePlatform? platform;
|
|
public readonly bool showPerformanceOverlay;
|
|
public readonly bool showRasterCacheImagesCheckerboard;
|
|
public readonly bool showOffscreenLayersCheckerboard;
|
|
|
|
internal GalleryOptions copyWith(
|
|
ThemeMode? themeMode = null,
|
|
GalleryTextScaleValue textScaleFactor = null,
|
|
GalleryVisualDensityValue visualDensity = null,
|
|
TextDirection? textDirection = null,
|
|
float? timeDilation = null,
|
|
RuntimePlatform? platform = null,
|
|
bool? showPerformanceOverlay = null,
|
|
bool? showRasterCacheImagesCheckerboard = null,
|
|
bool? showOffscreenLayersCheckerboard = null
|
|
)
|
|
{
|
|
return new GalleryOptions(
|
|
themeMode: themeMode ?? this.themeMode,
|
|
textScaleFactor: textScaleFactor ?? this.textScaleFactor,
|
|
visualDensity: visualDensity ?? this.visualDensity,
|
|
textDirection: textDirection ?? this.textDirection,
|
|
timeDilation: timeDilation ?? this.timeDilation,
|
|
platform: platform ?? this.platform,
|
|
showPerformanceOverlay: showPerformanceOverlay ?? this.showPerformanceOverlay,
|
|
showOffscreenLayersCheckerboard:
|
|
showOffscreenLayersCheckerboard ?? this.showOffscreenLayersCheckerboard,
|
|
showRasterCacheImagesCheckerboard: showRasterCacheImagesCheckerboard ??
|
|
this.showRasterCacheImagesCheckerboard
|
|
);
|
|
}
|
|
|
|
public bool Equals(GalleryOptions other)
|
|
{
|
|
if (ReferenceEquals(this, other)) return true;
|
|
|
|
if (ReferenceEquals(other, null)) return false;
|
|
|
|
return this.themeMode.Equals(other.themeMode)
|
|
&& this.textScaleFactor == other.textScaleFactor
|
|
&& this.visualDensity == other.visualDensity
|
|
&& this.textDirection == other.textDirection
|
|
&& this.platform == other.platform
|
|
&& this.showPerformanceOverlay == other.showPerformanceOverlay
|
|
&& this.showRasterCacheImagesCheckerboard == other.showRasterCacheImagesCheckerboard
|
|
&& this.showOffscreenLayersCheckerboard == other.showOffscreenLayersCheckerboard;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (ReferenceEquals(this, obj)) return true;
|
|
|
|
if (ReferenceEquals(obj, null)) return false;
|
|
|
|
if (obj.GetType() != this.GetType()) return false;
|
|
|
|
return this.Equals((GalleryOptions) obj);
|
|
}
|
|
|
|
public static bool operator ==(GalleryOptions left, GalleryOptions right)
|
|
{
|
|
return Equals(left, right);
|
|
}
|
|
|
|
public static bool operator !=(GalleryOptions left, GalleryOptions right)
|
|
{
|
|
return !Equals(left, right);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
unchecked
|
|
{
|
|
var hashcode = this.themeMode?.GetHashCode() ?? 0;
|
|
hashcode = (hashcode * 397) ^ this.textScaleFactor.GetHashCode();
|
|
hashcode = (hashcode * 397) ^ this.visualDensity.GetHashCode();
|
|
hashcode = (hashcode * 397) ^ (this.textDirection?.GetHashCode() ?? 0);
|
|
hashcode = (hashcode * 397) ^ this.timeDilation.GetHashCode();
|
|
hashcode = (hashcode * 397) ^ (this.platform?.GetHashCode() ?? 0);
|
|
hashcode = (hashcode * 397) ^ this.showPerformanceOverlay.GetHashCode();
|
|
hashcode = (hashcode * 397) ^ this.showRasterCacheImagesCheckerboard.GetHashCode();
|
|
hashcode = (hashcode * 397) ^ this.showOffscreenLayersCheckerboard.GetHashCode();
|
|
return hashcode;
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{this.GetType()}{this.themeMode}";
|
|
}
|
|
}
|
|
|
|
internal class _OptionsItem : StatelessWidget
|
|
{
|
|
public _OptionsItem(Key key = null, Widget child = null) : base(key: key)
|
|
{
|
|
this.child = child;
|
|
}
|
|
|
|
public readonly Widget child;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
float textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
|
|
|
return new Container(
|
|
constraints: new BoxConstraints(minHeight: GalleryOptionUtils._kItemHeight * textScaleFactor),
|
|
padding: GalleryOptionUtils._kItemPadding,
|
|
alignment: AlignmentDirectional.centerStart,
|
|
child: new DefaultTextStyle(
|
|
style: DefaultTextStyle.of(context).style,
|
|
maxLines: 2,
|
|
overflow: TextOverflow.fade,
|
|
child: new IconTheme(
|
|
data: Theme.of(context).primaryIconTheme,
|
|
child: this.child
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _BooleanItem : StatelessWidget
|
|
{
|
|
public _BooleanItem(string title, bool value, ValueChanged<bool?> onChanged, Key switchKey = null)
|
|
{
|
|
this.title = title;
|
|
this.value = value;
|
|
this.onChanged = onChanged;
|
|
this.switchKey = switchKey;
|
|
}
|
|
|
|
public readonly string title;
|
|
public readonly bool value;
|
|
public readonly ValueChanged<bool?> onChanged;
|
|
public readonly Key switchKey;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
bool isDark = Theme.of(context).brightness == Brightness.dark;
|
|
return new _OptionsItem(
|
|
child: new Row(
|
|
children: new List<Widget>
|
|
{
|
|
new Expanded(child: new Text(this.title)),
|
|
new Switch(
|
|
key: this.switchKey,
|
|
value: this.value,
|
|
onChanged: this.onChanged,
|
|
activeColor: new Color(0xFF39CEFD),
|
|
activeTrackColor: isDark ? Colors.white30 : Colors.black26
|
|
)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _ActionItem : StatelessWidget
|
|
{
|
|
public _ActionItem(string text, VoidCallback onTap)
|
|
{
|
|
this.text = text;
|
|
this.onTap = onTap;
|
|
}
|
|
|
|
public readonly string text;
|
|
public readonly VoidCallback onTap;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new _OptionsItem(
|
|
child: new _FlatButton(
|
|
onPressed: this.onTap,
|
|
child: new Text(this.text)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _FlatButton : StatelessWidget
|
|
{
|
|
public _FlatButton(Key key = null, VoidCallback onPressed = null, Widget child = null) : base(key: key)
|
|
{
|
|
this.child = child;
|
|
this.onPressed = onPressed;
|
|
}
|
|
|
|
public readonly VoidCallback onPressed;
|
|
public readonly Widget child;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new FlatButton(
|
|
padding: EdgeInsets.zero,
|
|
onPressed: this.onPressed,
|
|
child: new DefaultTextStyle(
|
|
style: Theme.of(context).primaryTextTheme.subtitle1,
|
|
child: this.child
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _Heading : StatelessWidget
|
|
{
|
|
public _Heading(string text)
|
|
{
|
|
this.text = text;
|
|
}
|
|
|
|
public readonly string text;
|
|
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
ThemeData theme = Theme.of(context);
|
|
return new _OptionsItem(
|
|
child: new DefaultTextStyle(
|
|
style: theme.textTheme.headline6.copyWith(
|
|
color: theme.colorScheme.onPrimary,
|
|
fontWeight: FontWeight.w700
|
|
),
|
|
child: new Text(this.text)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _ThemeModeItem : StatelessWidget
|
|
{
|
|
public _ThemeModeItem(GalleryOptions options, ValueChanged<GalleryOptions> onOptionsChanged)
|
|
{
|
|
this.options = options;
|
|
this.onOptionsChanged = onOptionsChanged;
|
|
}
|
|
|
|
public readonly GalleryOptions options;
|
|
public readonly ValueChanged<GalleryOptions> onOptionsChanged;
|
|
|
|
public static readonly Dictionary<ThemeMode, string> modeLabels = new Dictionary<ThemeMode, string>
|
|
{
|
|
{ThemeMode.system, "System Default"},
|
|
{ThemeMode.light, "Light"},
|
|
{ThemeMode.dark, "Dark"},
|
|
};
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new _OptionsItem(
|
|
child: new Row(
|
|
children: new List<Widget>
|
|
{
|
|
new Expanded(
|
|
child: new Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: new List<Widget>
|
|
{
|
|
new Text("Theme"),
|
|
new Text(
|
|
modeLabels[this.options.themeMode.Value],
|
|
style: Theme.of(context).primaryTextTheme.bodyText2
|
|
)
|
|
}
|
|
)
|
|
),
|
|
new PopupMenuButton<ThemeMode>(
|
|
//TODO: uncomment this when fixes on EdgeInsetsDirectional lands
|
|
//padding: const EdgeInsetsDirectional.only(end: 16.0),
|
|
padding: EdgeInsets.only(right: 16.0f),
|
|
icon: new Icon(Icons.arrow_drop_down),
|
|
initialValue: this.options.themeMode.Value,
|
|
itemBuilder: (BuildContext subContext) =>
|
|
{
|
|
return modeLabels.Keys.Select<ThemeMode, PopupMenuEntry<ThemeMode>>((ThemeMode mode) =>
|
|
{
|
|
return new PopupMenuItem<ThemeMode>(
|
|
value: mode,
|
|
child: new Text(modeLabels[mode])
|
|
);
|
|
}).ToList();
|
|
},
|
|
onSelected: (ThemeMode mode) =>
|
|
{
|
|
this.onOptionsChanged(this.options.copyWith(themeMode: mode)
|
|
);
|
|
}
|
|
)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _TextScaleFactorItem : StatelessWidget
|
|
{
|
|
public _TextScaleFactorItem(GalleryOptions options, ValueChanged<GalleryOptions> onOptionsChanged)
|
|
{
|
|
this.options = options;
|
|
this.onOptionsChanged = onOptionsChanged;
|
|
}
|
|
|
|
public readonly GalleryOptions options;
|
|
public readonly ValueChanged<GalleryOptions> onOptionsChanged;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new _OptionsItem(
|
|
child: new Row(
|
|
children: new List<Widget>
|
|
{
|
|
new Expanded(
|
|
child: new Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: new List<Widget>
|
|
{
|
|
new Text("Text size"),
|
|
new Text(this.options.textScaleFactor.label,
|
|
style: Theme.of(context).primaryTextTheme.bodyText2
|
|
)
|
|
}
|
|
)
|
|
),
|
|
new PopupMenuButton<GalleryTextScaleValue>(
|
|
//TODO: uncomment this when fixes on EdgeInsetsDirectional lands
|
|
//padding: EdgeInsetsDirectional.only(end: 16.0f),
|
|
padding: EdgeInsets.only(right: 16.0f),
|
|
icon: new Icon(Icons.arrow_drop_down),
|
|
itemBuilder: (BuildContext subContext) =>
|
|
{
|
|
return GalleryTextScaleValue.kAllGalleryTextScaleValues
|
|
.Select<GalleryTextScaleValue, PopupMenuEntry<GalleryTextScaleValue>>(
|
|
(GalleryTextScaleValue scaleValue) =>
|
|
{
|
|
return new PopupMenuItem<GalleryTextScaleValue>(
|
|
value: scaleValue,
|
|
child: new Text(scaleValue.label)
|
|
);
|
|
}).ToList();
|
|
},
|
|
onSelected: (GalleryTextScaleValue scaleValue) =>
|
|
{
|
|
this.onOptionsChanged(this.options.copyWith(textScaleFactor: scaleValue)
|
|
);
|
|
}
|
|
)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _VisualDensityItem : StatelessWidget
|
|
{
|
|
public _VisualDensityItem(GalleryOptions options, ValueChanged<GalleryOptions> onOptionsChanged)
|
|
{
|
|
this.options = options;
|
|
this.onOptionsChanged = onOptionsChanged;
|
|
}
|
|
|
|
public readonly GalleryOptions options;
|
|
public readonly ValueChanged<GalleryOptions> onOptionsChanged;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new _OptionsItem(
|
|
child: new Row(
|
|
children: new List<Widget>
|
|
{
|
|
new Expanded(
|
|
child: new Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: new List<Widget>
|
|
{
|
|
new Text("Visual density"),
|
|
new Text(this.options.visualDensity.label,
|
|
style: Theme.of(context).primaryTextTheme.bodyText2
|
|
)
|
|
}
|
|
)
|
|
),
|
|
new PopupMenuButton<GalleryVisualDensityValue>(
|
|
//TODO: uncomment this when fixes on EdgeInsetsDirectional lands
|
|
//padding: EdgeInsetsDirectional.only(end: 16.0f),
|
|
padding: EdgeInsets.only(right: 16.0f),
|
|
icon: new Icon(Icons.arrow_drop_down),
|
|
itemBuilder: (BuildContext subContext) =>
|
|
{
|
|
return GalleryVisualDensityValue.kAllGalleryVisualDensityValues
|
|
.Select<GalleryVisualDensityValue, PopupMenuEntry<GalleryVisualDensityValue>>(
|
|
(GalleryVisualDensityValue densityValue) =>
|
|
{
|
|
return new PopupMenuItem<GalleryVisualDensityValue>(
|
|
value: densityValue,
|
|
child: new Text(densityValue.label)
|
|
);
|
|
}).ToList();
|
|
},
|
|
onSelected: (GalleryVisualDensityValue densityValue) =>
|
|
{
|
|
this.onOptionsChanged(this.options.copyWith(visualDensity: densityValue)
|
|
);
|
|
}
|
|
)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _TextDirectionItem : StatelessWidget
|
|
{
|
|
public _TextDirectionItem(GalleryOptions options, ValueChanged<GalleryOptions> onOptionsChanged)
|
|
{
|
|
this.options = options;
|
|
this.onOptionsChanged = onOptionsChanged;
|
|
}
|
|
|
|
public readonly GalleryOptions options;
|
|
public readonly ValueChanged<GalleryOptions> onOptionsChanged;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new _BooleanItem(
|
|
"Force RTL", this.options.textDirection == TextDirection.rtl,
|
|
(bool? value) =>
|
|
{
|
|
this.onOptionsChanged(this.options.copyWith(
|
|
textDirection: value == true ? TextDirection.rtl : TextDirection.ltr
|
|
)
|
|
);
|
|
},
|
|
switchKey: Key.key("text_direction")
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _TimeDilationItem : StatelessWidget
|
|
{
|
|
public _TimeDilationItem(GalleryOptions options, ValueChanged<GalleryOptions> onOptionsChanged)
|
|
{
|
|
this.options = options;
|
|
this.onOptionsChanged = onOptionsChanged;
|
|
}
|
|
|
|
public readonly GalleryOptions options;
|
|
public readonly ValueChanged<GalleryOptions> onOptionsChanged;
|
|
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new _BooleanItem(
|
|
"Slow motion", this.options.timeDilation != 1.0f,
|
|
(bool? value) =>
|
|
{
|
|
this.onOptionsChanged(this.options.copyWith(
|
|
timeDilation: value == true ? 20.0f : 1.0f
|
|
)
|
|
);
|
|
},
|
|
switchKey: Key.key("slow_motion")
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _PlatformItem : StatelessWidget
|
|
{
|
|
public _PlatformItem(GalleryOptions options, ValueChanged<GalleryOptions> onOptionsChanged)
|
|
{
|
|
this.options = options;
|
|
this.onOptionsChanged = onOptionsChanged;
|
|
}
|
|
|
|
public readonly GalleryOptions options;
|
|
public readonly ValueChanged<GalleryOptions> onOptionsChanged;
|
|
|
|
private string _platformLabel(RuntimePlatform? platform)
|
|
{
|
|
return platform.ToString();
|
|
}
|
|
|
|
private static List<RuntimePlatform> _platforms = new List<RuntimePlatform>
|
|
{RuntimePlatform.Android, RuntimePlatform.IPhonePlayer, RuntimePlatform.WindowsPlayer};
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new _OptionsItem(
|
|
child: new Row(
|
|
children: new List<Widget>
|
|
{
|
|
new Expanded(
|
|
child: new Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: new List<Widget>
|
|
{
|
|
new Text("Platform mechanics"),
|
|
new Text(this._platformLabel(this.options.platform),
|
|
style: Theme.of(context).primaryTextTheme.bodyText2
|
|
)
|
|
}
|
|
)
|
|
),
|
|
new PopupMenuButton<RuntimePlatform>(
|
|
//TODO: uncomment this when fixes on EdgeInsetsDirectional lands
|
|
//padding: EdgeInsetsDirectional.only(end: 16.0f),
|
|
padding: EdgeInsets.only(right: 16.0f),
|
|
icon: new Icon(Icons.arrow_drop_down),
|
|
itemBuilder: (BuildContext subContext) =>
|
|
{
|
|
return _platforms.Select<RuntimePlatform, PopupMenuEntry<RuntimePlatform>>(
|
|
(RuntimePlatform platform) =>
|
|
{
|
|
return new PopupMenuItem<RuntimePlatform>(
|
|
value: platform,
|
|
child: new Text(this._platformLabel(platform))
|
|
);
|
|
}).ToList();
|
|
},
|
|
onSelected: (RuntimePlatform platform) =>
|
|
{
|
|
this.onOptionsChanged(this.options.copyWith(platform: platform)
|
|
);
|
|
}
|
|
)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class GalleryOptionsPage : StatelessWidget
|
|
{
|
|
public GalleryOptionsPage(
|
|
Key key = null,
|
|
GalleryOptions options = null,
|
|
ValueChanged<GalleryOptions> onOptionsChanged = null,
|
|
VoidCallback onSendFeedback = null
|
|
) : base(key: key)
|
|
{
|
|
this.options = options;
|
|
this.onOptionsChanged = onOptionsChanged;
|
|
this.onSendFeedback = onSendFeedback;
|
|
}
|
|
|
|
public readonly GalleryOptions options;
|
|
public readonly ValueChanged<GalleryOptions> onOptionsChanged;
|
|
public readonly VoidCallback onSendFeedback;
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
ThemeData theme = Theme.of(context);
|
|
|
|
return new DefaultTextStyle(
|
|
style: theme.primaryTextTheme.subtitle1,
|
|
child: new ListView(
|
|
padding: EdgeInsets.only(bottom: 124.0f),
|
|
children: new List<Widget>
|
|
{
|
|
new _Heading("Display"),
|
|
new _ThemeModeItem(this.options, this.onOptionsChanged),
|
|
new _TextScaleFactorItem(this.options, this.onOptionsChanged),
|
|
new _VisualDensityItem(this.options, this.onOptionsChanged),
|
|
new _TextDirectionItem(this.options, this.onOptionsChanged),
|
|
new _TimeDilationItem(this.options, this.onOptionsChanged),
|
|
new Divider(),
|
|
new _PlatformItem(this.options, this.onOptionsChanged),
|
|
new Divider(),
|
|
new _Heading("Flutter gallery"),
|
|
new _ActionItem("About Flutter Gallery",
|
|
() => { GalleryAboutUtils.showGalleryAboutDialog(context); }),
|
|
new _ActionItem("Send feedback", this.onSendFeedback)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|