xingweizhu
4 年前
当前提交
271aa04a
共有 18 个文件被更改,包括 1122 次插入 和 134 次删除
-
23Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/GalleryMain.cs
-
430Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/gallery/home.cs
-
1Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/gallery/options.cs
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine.meta
-
192Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/gallery/app.cs
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/gallery/app.cs.meta
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model.meta
-
107Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/app_state_model.cs
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/app_state_model.cs.meta
-
46Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/product.cs
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/product.cs.meta
-
285Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/products_repository.cs
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/products_repository.cs.meta
-
148Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/scoped_model.cs
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/model/scoped_model.cs.meta
-
3Samples/UIWidgetsSamples_2019_4/Assets/UIWidgetsGallery/demo/shrine/supplemental.meta
|
|||
using UIWidgetsGallery.gallery; |
|||
using Unity.UIWidgets.engine2; |
|||
//using Unity.UIWidgets.material;
|
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
using ui_ = Unity.UIWidgets.widgets.ui_; |
|||
/*protected override Widget createWidget() { |
|||
return new GalleryApp(); |
|||
}*/ |
|||
protected override void main() { |
|||
ui_.runApp(new GalleryApp()); |
|||
} |
|||
/*protected override void OnEnable() { |
|||
FontManager.instance.addFont(Resources.Load<Font>("fonts/MaterialIcons-Regular"), "Material Icons"); |
|||
FontManager.instance.addFont(Resources.Load<Font>("fonts/GalleryIcons"), "GalleryIcons"); |
|||
|
|||
FontManager.instance.addFont(Resources.Load<Font>("fonts/CupertinoIcons"), "CupertinoIcons"); |
|||
FontManager.instance.addFont(Resources.Load<Font>(path: "fonts/SF-Pro-Text-Regular"), ".SF Pro Text", FontWeight.w400); |
|||
FontManager.instance.addFont(Resources.Load<Font>(path: "fonts/SF-Pro-Text-Semibold"), ".SF Pro Text", FontWeight.w600); |
|||
FontManager.instance.addFont(Resources.Load<Font>(path: "fonts/SF-Pro-Text-Bold"), ".SF Pro Text", FontWeight.w700); |
|||
|
|||
protected new void OnEnable() { |
|||
}*/ |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: fb97b78a8c204fbb9c9dbf667cb23004 |
|||
timeCreated: 1612342718 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using uiwidgets; |
|||
using UIWidgetsGallery.demo.shrine.model; |
|||
using Unity.UIWidgets.async2; |
|||
using Unity.UIWidgets.cupertino; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.scheduler2; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
|
|||
namespace UIWidgetsGallery.gallery |
|||
{ |
|||
public class GalleryApp : StatefulWidget |
|||
{ |
|||
public GalleryApp( |
|||
Key key = null, |
|||
UpdateUrlFetcher updateUrlFetcher = null, |
|||
bool enablePerformanceOverlay = true, |
|||
bool enableRasterCacheImagesCheckerboard = true, |
|||
bool enableOffscreenLayersCheckerboard = true, |
|||
VoidCallback onSendFeedback = null, |
|||
bool testMode = false |
|||
) : base(key: key) |
|||
{ |
|||
this.updateUrlFetcher = updateUrlFetcher; |
|||
this.enablePerformanceOverlay = enablePerformanceOverlay; |
|||
this.enableRasterCacheImagesCheckerboard = enableRasterCacheImagesCheckerboard; |
|||
this.enableOffscreenLayersCheckerboard = enableOffscreenLayersCheckerboard; |
|||
this.onSendFeedback = onSendFeedback; |
|||
this.testMode = testMode; |
|||
} |
|||
|
|||
public readonly UpdateUrlFetcher updateUrlFetcher; |
|||
public readonly bool enablePerformanceOverlay; |
|||
public readonly bool enableRasterCacheImagesCheckerboard; |
|||
public readonly bool enableOffscreenLayersCheckerboard; |
|||
public readonly VoidCallback onSendFeedback; |
|||
public readonly bool testMode; |
|||
|
|||
public override State createState() |
|||
{ |
|||
return new _GalleryAppState(); |
|||
} |
|||
} |
|||
|
|||
internal class _GalleryAppState : State<GalleryApp> |
|||
{ |
|||
private GalleryOptions _options; |
|||
private Timer _timeDilationTimer; |
|||
private AppStateModel model; |
|||
|
|||
private Dictionary<string, WidgetBuilder> _buildRoutes() |
|||
{ |
|||
Dictionary<string, WidgetBuilder> routeBulders = new Dictionary<string, WidgetBuilder>(); |
|||
|
|||
foreach (var demo in GalleryDemo.kAllGalleryDemos) routeBulders.Add(demo.routeName, demo.buildRoute); |
|||
|
|||
return routeBulders; |
|||
} |
|||
|
|||
private static readonly RuntimePlatform defaultTargetPlatform = RuntimePlatform.WindowsPlayer; |
|||
|
|||
|
|||
public override void initState() |
|||
{ |
|||
base.initState(); |
|||
this._options = new GalleryOptions( |
|||
themeMode: ThemeMode.system, |
|||
textScaleFactor: GalleryTextScaleValue.kAllGalleryTextScaleValues[0], |
|||
visualDensity: GalleryVisualDensityValue.kAllGalleryVisualDensityValues[0], |
|||
timeDilation: scheduler_.timeDilation, |
|||
platform: defaultTargetPlatform |
|||
); |
|||
this.model = new AppStateModel(); |
|||
this.model.loadProducts(); |
|||
} |
|||
|
|||
public override void reassemble() |
|||
{ |
|||
this._options = this._options.copyWith(platform: defaultTargetPlatform); |
|||
base.reassemble(); |
|||
} |
|||
|
|||
public override void dispose() |
|||
{ |
|||
this._timeDilationTimer?.cancel(); |
|||
this._timeDilationTimer = null; |
|||
base.dispose(); |
|||
} |
|||
|
|||
private void _handleOptionsChanged(GalleryOptions newOptions) |
|||
{ |
|||
this.setState(() => |
|||
{ |
|||
if (this._options.timeDilation != newOptions.timeDilation) |
|||
{ |
|||
this._timeDilationTimer?.cancel(); |
|||
this._timeDilationTimer = null; |
|||
if (newOptions.timeDilation > 1.0f |
|||
) // We delay the time dilation change long enough that the user can see
|
|||
// that UI has started reacting and then we slam on the brakes so that
|
|||
// they see that the time is in fact now dilated.
|
|||
this._timeDilationTimer = Timer.create(new TimeSpan(0, 0, 0, 0, 150), |
|||
() => { scheduler_.timeDilation = newOptions.timeDilation; }); |
|||
else |
|||
scheduler_.timeDilation = newOptions.timeDilation; |
|||
} |
|||
|
|||
this._options = newOptions; |
|||
}); |
|||
} |
|||
|
|||
private Widget _applyTextScaleFactor(Widget child) |
|||
{ |
|||
return new Builder( |
|||
builder: (BuildContext context) => |
|||
{ |
|||
return new MediaQuery( |
|||
data: MediaQuery.of(context).copyWith( |
|||
textScaleFactor: this._options.textScaleFactor.scale |
|||
), |
|||
child: child |
|||
); |
|||
} |
|||
); |
|||
} |
|||
|
|||
private static void defaultSendFeedback() |
|||
{ |
|||
Debug.Log("hello UIWidgets !"); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
Widget home = new GalleryHome( |
|||
testMode: this.widget.testMode, |
|||
optionsPage: new GalleryOptionsPage( |
|||
options: this._options, |
|||
onOptionsChanged: this._handleOptionsChanged, |
|||
onSendFeedback: this.widget.onSendFeedback ?? defaultSendFeedback |
|||
) |
|||
); |
|||
|
|||
if (this.widget.updateUrlFetcher != null) |
|||
home = new Updater( |
|||
updateUrlFetcher: this.widget.updateUrlFetcher, |
|||
child: home |
|||
); |
|||
|
|||
return new ScopedModel<AppStateModel>( |
|||
model: this.model, |
|||
child: new MaterialApp( |
|||
theme: GalleyThemes.kLightGalleryTheme.copyWith(platform: this._options.platform, |
|||
visualDensity: this._options.visualDensity.visualDensity), |
|||
darkTheme: GalleyThemes.kDarkGalleryTheme.copyWith(platform: this._options.platform, |
|||
visualDensity: this._options.visualDensity.visualDensity), |
|||
themeMode: this._options.themeMode.Value, |
|||
title: "Flutter Gallery", |
|||
color: Colors.grey, |
|||
showPerformanceOverlay: this._options.showPerformanceOverlay, |
|||
checkerboardOffscreenLayers: this._options.showOffscreenLayersCheckerboard, |
|||
checkerboardRasterCacheImages: this._options.showRasterCacheImagesCheckerboard, |
|||
routes: this._buildRoutes(), |
|||
builder: (BuildContext subContext, Widget child) => |
|||
{ |
|||
return new Directionality( |
|||
textDirection: this._options.textDirection.Value, |
|||
child: this._applyTextScaleFactor( |
|||
// Specifically use a blank Cupertino theme here and do not transfer
|
|||
// over the Material primary color etc except the brightness to
|
|||
// showcase standard iOS looks.
|
|||
new Builder(builder: (BuildContext subsubContext) => |
|||
{ |
|||
return new CupertinoTheme( |
|||
data: new CupertinoThemeData( |
|||
brightness: Theme.of(context).brightness |
|||
), |
|||
child: child |
|||
); |
|||
}) |
|||
) |
|||
); |
|||
}, |
|||
home: home |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 63b65dbf55ef42bb81d7836bd42d60c9 |
|||
timeCreated: 1612341675 |
|
|||
fileFormatVersion: 2 |
|||
guid: 14605fd6a2e647e5a40284b48310def7 |
|||
timeCreated: 1612342746 |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace UIWidgetsGallery.demo.shrine.model |
|||
{ |
|||
public static class AppStateModelUtils |
|||
{ |
|||
public static readonly float _salesTaxRate = 0.06f; |
|||
public static readonly float _shippingCostPerItem = 7.0f; |
|||
} |
|||
|
|||
public class AppStateModel : Model |
|||
{ |
|||
private List<Product> _availableProducts; |
|||
|
|||
private Category _selectedCategory = Category.all; |
|||
|
|||
private Dictionary<int, int> _productsInCart = new Dictionary<int, int> { }; |
|||
|
|||
private Dictionary<int, int> productsInCart => new Dictionary<int, int>(this._productsInCart); |
|||
|
|||
public int totalCartQuantity => this._productsInCart.Values.Sum(); |
|||
|
|||
public Category selectedCategory => this._selectedCategory; |
|||
|
|||
public float subtotalCost |
|||
{ |
|||
get |
|||
{ |
|||
var sum = 0; |
|||
foreach (var id in this.productsInCart.Keys) |
|||
sum += this._availableProducts[id].price * this.productsInCart[id]; |
|||
return sum; |
|||
} |
|||
} |
|||
|
|||
public float shippingCost => AppStateModelUtils._shippingCostPerItem * this._productsInCart.Values.Sum(); |
|||
|
|||
public float tax => this.subtotalCost * AppStateModelUtils._salesTaxRate; |
|||
|
|||
public float totalCost => this.subtotalCost + this.shippingCost + this.tax; |
|||
|
|||
|
|||
public List<Product> getProducts() |
|||
{ |
|||
if (this._availableProducts == null) return new List<Product>(); |
|||
|
|||
if (this._selectedCategory == Category.all) |
|||
return new List<Product>(this._availableProducts); |
|||
else |
|||
return this._availableProducts |
|||
.Where((Product p) => p.category == this._selectedCategory) |
|||
.ToList(); |
|||
} |
|||
|
|||
public void addProductToCart(int productId) |
|||
{ |
|||
if (!this._productsInCart.ContainsKey(productId)) |
|||
this._productsInCart[productId] = 1; |
|||
else |
|||
this._productsInCart[productId]++; |
|||
|
|||
this.notifyListeners(); |
|||
} |
|||
|
|||
public void removeItemFromCart(int productId) |
|||
{ |
|||
if (this._productsInCart.ContainsKey(productId)) |
|||
{ |
|||
if (this._productsInCart[productId] == 1) |
|||
this._productsInCart.Remove(productId); |
|||
else |
|||
this._productsInCart[productId]--; |
|||
} |
|||
|
|||
this.notifyListeners(); |
|||
} |
|||
|
|||
public Product getProductById(int id) |
|||
{ |
|||
return this._availableProducts.First((Product p) => p.id == id); |
|||
} |
|||
|
|||
public void clearCart() |
|||
{ |
|||
this._productsInCart.Clear(); |
|||
this.notifyListeners(); |
|||
} |
|||
|
|||
public void loadProducts() |
|||
{ |
|||
this._availableProducts = ProductsRepository.loadProducts(Category.all); |
|||
this.notifyListeners(); |
|||
} |
|||
|
|||
public void setCategory(Category newCategory) |
|||
{ |
|||
this._selectedCategory = newCategory; |
|||
this.notifyListeners(); |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return $"AppStateModel(totalCost: {this.totalCost})"; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1e79c836d5b1466ea74fe5e3838c7760 |
|||
timeCreated: 1612342779 |
|
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace UIWidgetsGallery.demo.shrine.model |
|||
{ |
|||
public enum Category |
|||
{ |
|||
all, |
|||
accessories, |
|||
clothing, |
|||
home, |
|||
} |
|||
|
|||
public class Product |
|||
{ |
|||
public Product( |
|||
Category category, |
|||
int id, |
|||
bool isFeatured, |
|||
string name, |
|||
int price |
|||
) |
|||
{ |
|||
D.assert(name != null); |
|||
this.category = category; |
|||
this.id = id; |
|||
this.isFeatured = isFeatured; |
|||
this.name = name; |
|||
this.price = price; |
|||
} |
|||
|
|||
public readonly Category category; |
|||
public readonly int id; |
|||
public readonly bool isFeatured; |
|||
public readonly string name; |
|||
public readonly int price; |
|||
|
|||
private string assetName => $"{this.id}-0.jpg"; |
|||
private string assetPackage => "shrine_images"; |
|||
|
|||
|
|||
public override string ToString() |
|||
{ |
|||
return $"{this.name} (id={this.id})"; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b1cee3bedd0943a4b7c99b53520d96af |
|||
timeCreated: 1612342795 |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace UIWidgetsGallery.demo.shrine.model |
|||
{ |
|||
public static class ProductsRepository |
|||
{ |
|||
public static List<Product> loadProducts(Category category) |
|||
{ |
|||
List<Product> allProducts = new List<Product> |
|||
{ |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 0, |
|||
isFeatured: true, |
|||
name: "Vagabond sack", |
|||
price: 120 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 1, |
|||
isFeatured: true, |
|||
name: "Stella sunglasses", |
|||
price: 58 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 2, |
|||
isFeatured: false, |
|||
name: "Whitney belt", |
|||
price: 35 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 3, |
|||
isFeatured: true, |
|||
name: "Garden strand", |
|||
price: 98 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 4, |
|||
isFeatured: false, |
|||
name: "Strut earrings", |
|||
price: 34 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 5, |
|||
isFeatured: false, |
|||
name: "Varsity socks", |
|||
price: 12 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 6, |
|||
isFeatured: false, |
|||
name: "Weave keyring", |
|||
price: 16 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 7, |
|||
isFeatured: true, |
|||
name: "Gatsby hat", |
|||
price: 40 |
|||
), |
|||
new Product( |
|||
category: Category.accessories, |
|||
id: 8, |
|||
isFeatured: true, |
|||
name: "Shrug bag", |
|||
price: 198 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 9, |
|||
isFeatured: true, |
|||
name: "Gilt desk trio", |
|||
price: 58 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 10, |
|||
isFeatured: false, |
|||
name: "Copper wire rack", |
|||
price: 18 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 11, |
|||
isFeatured: false, |
|||
name: "Soothe ceramic set", |
|||
price: 28 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 12, |
|||
isFeatured: false, |
|||
name: "Hurrahs tea set", |
|||
price: 34 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 13, |
|||
isFeatured: true, |
|||
name: "Blue stone mug", |
|||
price: 18 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 14, |
|||
isFeatured: true, |
|||
name: "Rainwater tray", |
|||
price: 27 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 15, |
|||
isFeatured: true, |
|||
name: "Chambray napkins", |
|||
price: 16 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 16, |
|||
isFeatured: true, |
|||
name: "Succulent planters", |
|||
price: 16 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 17, |
|||
isFeatured: false, |
|||
name: "Quartet table", |
|||
price: 175 |
|||
), |
|||
new Product( |
|||
category: Category.home, |
|||
id: 18, |
|||
isFeatured: true, |
|||
name: "Kitchen quattro", |
|||
price: 129 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 19, |
|||
isFeatured: false, |
|||
name: "Clay sweater", |
|||
price: 48 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 20, |
|||
isFeatured: false, |
|||
name: "Sea tunic", |
|||
price: 45 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 21, |
|||
isFeatured: false, |
|||
name: "Plaster tunic", |
|||
price: 38 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 22, |
|||
isFeatured: false, |
|||
name: "White pinstripe shirt", |
|||
price: 70 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 23, |
|||
isFeatured: false, |
|||
name: "Chambray shirt", |
|||
price: 70 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 24, |
|||
isFeatured: true, |
|||
name: "Seabreeze sweater", |
|||
price: 60 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 25, |
|||
isFeatured: false, |
|||
name: "Gentry jacket", |
|||
price: 178 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 26, |
|||
isFeatured: false, |
|||
name: "Navy trousers", |
|||
price: 74 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 27, |
|||
isFeatured: true, |
|||
name: "Walter henley (white)", |
|||
price: 38 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 28, |
|||
isFeatured: true, |
|||
name: "Surf and perf shirt", |
|||
price: 48 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 29, |
|||
isFeatured: true, |
|||
name: "Ginger scarf", |
|||
price: 98 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 30, |
|||
isFeatured: true, |
|||
name: "Ramona crossover", |
|||
price: 68 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 31, |
|||
isFeatured: false, |
|||
name: "Chambray shirt", |
|||
price: 38 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 32, |
|||
isFeatured: false, |
|||
name: "Classic white collar", |
|||
price: 58 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 33, |
|||
isFeatured: true, |
|||
name: "Cerise scallop tee", |
|||
price: 42 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 34, |
|||
isFeatured: false, |
|||
name: "Shoulder rolls tee", |
|||
price: 27 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 35, |
|||
isFeatured: false, |
|||
name: "Grey slouch tank", |
|||
price: 24 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 36, |
|||
isFeatured: false, |
|||
name: "Sunshirt dress", |
|||
price: 58 |
|||
), |
|||
new Product( |
|||
category: Category.clothing, |
|||
id: 37, |
|||
isFeatured: true, |
|||
name: "Fine lines tee", |
|||
price: 58 |
|||
), |
|||
}; |
|||
if (category == Category.all) |
|||
return allProducts; |
|||
else |
|||
return allProducts.Where((Product p) => p.category == category).ToList(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: bee771cd2abb49a389131d2154c1538c |
|||
timeCreated: 1612342810 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.async2; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.demo.shrine.model |
|||
{ |
|||
public abstract class Model : Listenable |
|||
{ |
|||
readonly HashSet<VoidCallback> _listeners = new HashSet<VoidCallback>(); |
|||
internal int _version = 0; |
|||
int _microtaskVersion = 0; |
|||
|
|||
public void addListener(VoidCallback listener) { |
|||
_listeners.Add(listener); |
|||
} |
|||
|
|||
public void removeListener(VoidCallback listener) { |
|||
_listeners.Remove(listener); |
|||
} |
|||
|
|||
int listenerCount => _listeners.Count; |
|||
|
|||
protected void notifyListeners() { |
|||
// We schedule a microtask to debounce multiple changes that can occur
|
|||
// all at once.
|
|||
if (_microtaskVersion == _version) { |
|||
_microtaskVersion++; |
|||
async_.scheduleMicrotask(() => { |
|||
_version++; |
|||
_microtaskVersion = _version; |
|||
|
|||
// Convert the Set to a List before executing each listener. This
|
|||
// prevents errors that can arise if a listener removes itself during
|
|||
// invocation!
|
|||
_listeners.ToList().ForEach((VoidCallback listener) => listener()); |
|||
return null; |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class ScopedModel<T> : StatelessWidget where T : Model |
|||
{ |
|||
public ScopedModel(T model, Widget child) |
|||
{ |
|||
D.assert(model != null); |
|||
D.assert(child != null); |
|||
|
|||
this.model = model; |
|||
this.child = child; |
|||
} |
|||
|
|||
public readonly T model; |
|||
public readonly Widget child; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new AnimatedBuilder( |
|||
animation: model, |
|||
builder: (subContext, _) => new _InheritedModel<T>(model: model, child: child) |
|||
); |
|||
} |
|||
|
|||
public static T of( |
|||
BuildContext context, |
|||
bool rebuildOnChange = false |
|||
) { |
|||
Type type = typeof(_InheritedModel<T>); |
|||
|
|||
Widget widget = rebuildOnChange |
|||
? context.inheritFromWidgetOfExactType(type) |
|||
: context.ancestorWidgetOfExactType(type); |
|||
|
|||
if (widget == null) { |
|||
throw new ScopedModelError(); |
|||
} else { |
|||
return (widget as _InheritedModel<T>).model; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class _InheritedModel<T> : InheritedWidget where T : Model |
|||
{ |
|||
public readonly T model; |
|||
public readonly int version; |
|||
|
|||
public _InheritedModel(Key key = null, Widget child = null, T model = null) : |
|||
base(key: key, child: child) |
|||
{ |
|||
this.model = model; |
|||
this.version = model._version; |
|||
} |
|||
|
|||
public override bool updateShouldNotify(InheritedWidget oldWidget) |
|||
{ |
|||
var _oldWidget = (_InheritedModel<T>) oldWidget; |
|||
return _oldWidget.version != version; |
|||
} |
|||
} |
|||
|
|||
public delegate Widget ScopedModelDescendantBuilder<T>( |
|||
BuildContext context, |
|||
Widget child, |
|||
T model) where T : Model; |
|||
|
|||
public class ScopedModelDescendant<T> : StatelessWidget where T : Model |
|||
{ |
|||
public readonly ScopedModelDescendantBuilder<T> builder; |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public readonly bool rebuildOnChange; |
|||
|
|||
public ScopedModelDescendant( |
|||
ScopedModelDescendantBuilder<T> builder = null, |
|||
Widget child = null, |
|||
bool rebuildOnChange = true) |
|||
{ |
|||
D.assert(builder != null); |
|||
this.builder = builder; |
|||
this.child = child; |
|||
this.rebuildOnChange = rebuildOnChange; |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return builder( |
|||
context, |
|||
child, |
|||
ScopedModel<T>.of(context, rebuildOnChange: rebuildOnChange) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class ScopedModelError : UIWidgetsError |
|||
{ |
|||
public ScopedModelError() : base("") |
|||
{ |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return "Error: Could not find the correct ScopedModel."; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5aecacaf37684830a0325ef44da51137 |
|||
timeCreated: 1612343339 |
|
|||
fileFormatVersion: 2 |
|||
guid: d4ae99a1fe134a4581fd4dad88a477f7 |
|||
timeCreated: 1612342758 |
撰写
预览
正在加载...
取消
保存
Reference in new issue