_allHeroesFor(BuildContext context, bool isUserGestureTransition, NavigatorState navigator) { D.assert(context != null); D.assert(navigator != null); Dictionary <object, _HeroState> result = new Dictionary <object, _HeroState> { }; void addHero(StatefulElement hero, object tag) { D.assert(() => { if (result.ContainsKey(tag)) { throw new UIWidgetsError( "There are multiple heroes that share the same tag within a subtree.\n" + "Within each subtree for which heroes are to be animated (typically a PageRoute subtree), " + "each Hero must have a unique non-null tag.\n" + $"In this case, multiple heroes had the following tag: {tag}\n" + "Here is the subtree for one of the offending heroes:\n" + $"{hero.toStringDeep(prefixLineOne: "# ")}" ); } return(true); }); _HeroState heroState = (_HeroState)hero.state; result[tag] = heroState; } void visitor(Element element) { if (element.widget is Hero) { StatefulElement hero = (StatefulElement)element; Hero heroWidget = (Hero)element.widget; if (!isUserGestureTransition || heroWidget.transitionOnUserGestures) { object tag = heroWidget.tag; D.assert(tag != null); if (Navigator.of(hero) == navigator) { addHero(hero, tag); } else { ModalRoute heroRoute = ModalRoute.of(hero); if (heroRoute != null && heroRoute is PageRoute && heroRoute.isCurrent) { addHero(hero, tag); } } } } element.visitChildren(visitor); } context.visitChildElements(visitor); return(result); }
public _HeroFlightManifest( HeroFlightDirection type, OverlayState overlay, Rect navigatorRect, PageRoute fromRoute, PageRoute toRoute, _HeroState fromHero, _HeroState toHero, CreateRectTween createRectTween, HeroFlightShuttleBuilder shuttleBuilder, bool isUserGestureTransition ) { D.assert(fromHero.widget.tag == toHero.widget.tag); this.type = type; this.overlay = overlay; this.navigatorRect = navigatorRect; this.fromRoute = fromRoute; this.toRoute = toRoute; this.fromHero = fromHero; this.toHero = toHero; this.createRectTween = createRectTween; this.shuttleBuilder = shuttleBuilder; this.isUserGestureTransition = isUserGestureTransition; }
public _HeroFlightManifest( HeroFlightDirection type = default, OverlayState overlay = null, Rect navigatorRect = null, PageRoute fromRoute = null, PageRoute toRoute = null, _HeroState fromHero = null, _HeroState toHero = null, CreateRectTween createRectTween = null, HeroFlightShuttleBuilder shuttleBuilder = null, bool?isUserGestureTransition = null, bool?isDiverted = null ) { D.assert(fromHero.widget.tag.Equals(toHero.widget.tag)); this.type = type; this.overlay = overlay; this.navigatorRect = navigatorRect; this.fromRoute = fromRoute; this.toRoute = toRoute; this.fromHero = fromHero; this.toHero = toHero; this.createRectTween = createRectTween; this.shuttleBuilder = shuttleBuilder; this.isUserGestureTransition = isUserGestureTransition ?? false; this.isDiverted = isDiverted ?? false; }
internal static Dictionary <object, _HeroState> _allHeroesFor( BuildContext context, bool isUserGestureTransition, NavigatorState navigator) { D.assert(context != null); D.assert(navigator != null); Dictionary <object, _HeroState> result = new Dictionary <object, _HeroState> { }; void inviteHero(StatefulElement hero, object tag) { D.assert(() => { if (result.ContainsKey(tag)) { throw new UIWidgetsError( new List <DiagnosticsNode>() { new ErrorSummary("There are multiple heroes that share the same tag within a subtree."), new ErrorDescription( "Within each subtree for which heroes are to be animated (i.e. a PageRoute subtree), " + "each Hero must have a unique non-null tag.\n" + $"In this case, multiple heroes had the following tag: {tag}\n" ), new DiagnosticsProperty <StatefulElement>("Here is the subtree for one of the offending heroes", hero, linePrefix: "# ", style: DiagnosticsTreeStyle.dense), }); } return(true); }); Hero heroWidget = hero.widget as Hero; _HeroState heroState = hero.state as _HeroState; if (!isUserGestureTransition || heroWidget.transitionOnUserGestures) { result[tag] = heroState; } else { heroState.ensurePlaceholderIsHidden(); } } void visitor(Element element) { Widget widget = element.widget; if (widget is Hero) { StatefulElement hero = element as StatefulElement; object tag = ((Hero)widget).tag; D.assert(tag != null); if (Navigator.of(hero) == navigator) { inviteHero(hero, tag); } else { ModalRoute heroRoute = ModalRoute.of(hero); if (heroRoute != null && heroRoute is PageRoute && heroRoute.isCurrent) { inviteHero(hero, tag); } } } element.visitChildren(visitor); } context.visitChildElements(visitor); return(result); }
void _startHeroTransition( PageRoute from, PageRoute to, Animation <float> animation, HeroFlightDirection flightType, bool isUserGestureTransition ) { if (navigator == null || from.subtreeContext == null || to.subtreeContext == null) { to.offstage = false; // in case we set this in _maybeStartHeroTransition return; } Rect navigatorRect = HeroUtils._boundingBoxFor(navigator.context);//_globalBoundingBoxFor(navigator.context); Dictionary <object, _HeroState> fromHeroes = Hero._allHeroesFor(from.subtreeContext, isUserGestureTransition, navigator); Dictionary <object, _HeroState> toHeroes = Hero._allHeroesFor(to.subtreeContext, isUserGestureTransition, navigator); to.offstage = false; foreach (object tag in fromHeroes.Keys) { if (toHeroes.ContainsKey(tag)) { HeroFlightShuttleBuilder fromShuttleBuilder = fromHeroes[tag].widget.flightShuttleBuilder; HeroFlightShuttleBuilder toShuttleBuilder = toHeroes[tag].widget.flightShuttleBuilder; bool isDiverted = _flights.ContainsKey(tag); _HeroFlightManifest manifest = new _HeroFlightManifest( type: flightType, overlay: navigator.overlay, navigatorRect: navigatorRect, fromRoute: from, toRoute: to, fromHero: fromHeroes[tag], toHero: toHeroes[tag], createRectTween: createRectTween, shuttleBuilder: toShuttleBuilder ?? fromShuttleBuilder ?? _defaultHeroFlightShuttleBuilder, isUserGestureTransition: isUserGestureTransition, isDiverted: isDiverted ); //if (_flights.TryGetValue(tag, out var result)) { if (isDiverted) { _flights[tag].divert(manifest); } else { _flights[tag] = new _HeroFlight(_handleFlightEnded); _flights[tag].start(manifest); } } else if (_flights.TryGetValue(tag, out var result)) { result.abort(); } } foreach (object tag in toHeroes.Keys) { _HeroState heroState = null; if (!fromHeroes.TryGetValue(tag, out heroState)) { toHeroes[tag].ensurePlaceholderIsHidden(); } } }