From 3cbb20d176c950effb7d1479661fbe87c8e8ef91 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sun, 3 Jul 2016 21:16:21 -0700 Subject: [PATCH] Just use SemanticAnnotator instead of Iterable (#4813) --- packages/flutter/lib/src/material/slider.dart | 12 ++-- .../flutter/lib/src/material/toggleable.dart | 18 ++--- .../flutter/lib/src/rendering/object.dart | 61 +++++++---------- .../flutter/lib/src/rendering/paragraph.dart | 8 +-- .../flutter/lib/src/rendering/proxy_box.dart | 68 +++++++++---------- 5 files changed, 78 insertions(+), 89 deletions(-) diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart index 4e4119aa4e..6966ed40d6 100644 --- a/packages/flutter/lib/src/material/slider.dart +++ b/packages/flutter/lib/src/material/slider.dart @@ -423,14 +423,14 @@ class _RenderSlider extends RenderConstrainedBox implements SemanticActionHandle } @override - bool get hasSemantics => isInteractive; + bool get isSemanticBoundary => isInteractive; @override - Iterable getSemanticAnnotators() sync* { - yield (SemanticsNode semantics) { - if (isInteractive) - semantics.addAdjustmentActions(); - }; + SemanticAnnotator get semanticAnnotator => _annotate; + + void _annotate(SemanticsNode semantics) { + if (isInteractive) + semantics.addAdjustmentActions(); } @override diff --git a/packages/flutter/lib/src/material/toggleable.dart b/packages/flutter/lib/src/material/toggleable.dart index 0fd75943b0..0c8c4d4e3a 100644 --- a/packages/flutter/lib/src/material/toggleable.dart +++ b/packages/flutter/lib/src/material/toggleable.dart @@ -263,17 +263,17 @@ abstract class RenderToggleable extends RenderConstrainedBox implements Semantic } @override - bool get hasSemantics => isInteractive; + bool get isSemanticBoundary => isInteractive; @override - Iterable getSemanticAnnotators() sync* { - yield (SemanticsNode semantics) { - semantics - ..hasCheckedState = true - ..isChecked = _value; - if (isInteractive) - semantics.addAction(SemanticAction.tap); - }; + SemanticAnnotator get semanticAnnotator => _annotate; + + void _annotate(SemanticsNode semantics) { + semantics + ..hasCheckedState = true + ..isChecked = _value; + if (isInteractive) + semantics.addAction(SemanticAction.tap); } @override diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 089780a740..603117b6df 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -508,13 +508,11 @@ class _SemanticsGeometry { abstract class _SemanticsFragment { _SemanticsFragment({ RenderObject renderObjectOwner, - Iterable annotators, + this.annotator, List<_SemanticsFragment> children }) { assert(renderObjectOwner != null); _ancestorChain = [renderObjectOwner]; - if (annotators != null) - addAnnotators(annotators); assert(() { if (children == null) return true; @@ -526,6 +524,8 @@ abstract class _SemanticsFragment { _children = children ?? const <_SemanticsFragment>[]; } + final SemanticAnnotator annotator; + List _ancestorChain; void addAncestor(RenderObject ancestor) { _ancestorChain.add(ancestor); @@ -533,14 +533,6 @@ abstract class _SemanticsFragment { RenderObject get renderObjectOwner => _ancestorChain.first; - List _annotators; - void addAnnotators(Iterable moreAnnotators) { - if (_annotators == null) - _annotators = moreAnnotators is List ? moreAnnotators : moreAnnotators.toList(); - else - _annotators.addAll(moreAnnotators); - } - List<_SemanticsFragment> _children; bool _debugCompiled = false; @@ -579,9 +571,9 @@ class _CleanSemanticsFragment extends _SemanticsFragment { abstract class _InterestingSemanticsFragment extends _SemanticsFragment { _InterestingSemanticsFragment({ RenderObject renderObjectOwner, - Iterable annotators, + SemanticAnnotator annotator, Iterable<_SemanticsFragment> children - }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children); + }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children); bool get haveConcreteNode => true; @@ -590,7 +582,7 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment { assert(!_debugCompiled); assert(() { _debugCompiled = true; return true; }); SemanticsNode node = establishSemanticsNode(geometry, currentSemantics, parentSemantics); - for (SemanticAnnotator annotator in _annotators) + if (annotator != null) annotator(node); for (_SemanticsFragment child in _children) { assert(child._ancestorChain.last == renderObjectOwner); @@ -613,9 +605,9 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment { class _RootSemanticsFragment extends _InterestingSemanticsFragment { _RootSemanticsFragment({ RenderObject renderObjectOwner, - Iterable annotators, + SemanticAnnotator annotator, Iterable<_SemanticsFragment> children - }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children); + }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children); @override SemanticsNode establishSemanticsNode(_SemanticsGeometry geometry, SemanticsNode currentSemantics, SemanticsNode parentSemantics) { @@ -643,9 +635,9 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment { class _ConcreteSemanticsFragment extends _InterestingSemanticsFragment { _ConcreteSemanticsFragment({ RenderObject renderObjectOwner, - Iterable annotators, + SemanticAnnotator annotator, Iterable<_SemanticsFragment> children - }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children); + }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children); @override SemanticsNode establishSemanticsNode(_SemanticsGeometry geometry, SemanticsNode currentSemantics, SemanticsNode parentSemantics) { @@ -671,9 +663,9 @@ class _ConcreteSemanticsFragment extends _InterestingSemanticsFragment { class _ImplicitSemanticsFragment extends _InterestingSemanticsFragment { _ImplicitSemanticsFragment({ RenderObject renderObjectOwner, - Iterable annotators, + SemanticAnnotator annotator, Iterable<_SemanticsFragment> children - }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children); + }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children); @override bool get haveConcreteNode => _haveConcreteNode; @@ -683,7 +675,7 @@ class _ImplicitSemanticsFragment extends _InterestingSemanticsFragment { SemanticsNode establishSemanticsNode(_SemanticsGeometry geometry, SemanticsNode currentSemantics, SemanticsNode parentSemantics) { SemanticsNode node; assert(_haveConcreteNode == null); - _haveConcreteNode = currentSemantics == null && _annotators.isNotEmpty; + _haveConcreteNode = currentSemantics == null && annotator != null; if (haveConcreteNode) { renderObjectOwner._semantics ??= new SemanticsNode( handler: renderObjectOwner is SemanticActionHandler ? renderObjectOwner as dynamic : null @@ -758,10 +750,9 @@ class _ForkingSemanticsFragment extends _SemanticsFragment { /// 3. [flushPaint] visites any render objects that need to paint. During this /// phase, render objects get a chance to record painting commands into /// [PictureLayer]s and construct other composited [Layer]s. -/// 4. Finally, if [SemanticsNode.hasListeners] is true, [flushSemantics] will -/// compile the semantics for the render objects. This semantic information -/// is used by assistive technology to improve the accessibility of the -/// render tree. +/// 4. Finally, if semantics are enabled, [flushSemantics] will compile the +/// semantics for the render objects. This semantic information is used by +/// assistive technology to improve the accessibility of the render tree. /// /// The [RendererBinding] holds the pipeline owner for the render objects that /// are visible on screen. You can create other pipeline owners to manage @@ -1197,7 +1188,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { _needsPaint = false; markNeedsPaint(); } - if (_needsSemanticsUpdate && hasSemantics) { + if (_needsSemanticsUpdate && isSemanticBoundary) { // Don't enter this block if we've never updated semantics at all; // scheduleInitialSemantics() will handle it _needsSemanticsUpdate = false; @@ -1900,7 +1891,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { } /// Whether this RenderObject introduces a new box for accessibility purposes. - bool get hasSemantics => false; + bool get isSemanticBoundary => false; /// The bounding box, in the local coordinate system, of this /// object, for accessibility purposes. @@ -2024,7 +2015,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { _SemanticsFragment _getSemanticsFragment() { // early-exit if we're not dirty and have our own semantics - if (!_needsSemanticsUpdate && hasSemantics) { + if (!_needsSemanticsUpdate && isSemanticBoundary) { assert(_semantics != null); return new _CleanSemanticsFragment(renderObjectOwner: this); } @@ -2047,13 +2038,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { }); _needsSemanticsUpdate = false; _needsSemanticsGeometryUpdate = false; - Iterable annotators = getSemanticAnnotators(); + SemanticAnnotator annotator = semanticAnnotator; if (parent is! RenderObject) - return new _RootSemanticsFragment(renderObjectOwner: this, annotators: annotators, children: children); - if (hasSemantics) - return new _ConcreteSemanticsFragment(renderObjectOwner: this, annotators: annotators, children: children); - if (annotators.isNotEmpty) - return new _ImplicitSemanticsFragment(renderObjectOwner: this, annotators: annotators, children: children); + return new _RootSemanticsFragment(renderObjectOwner: this, annotator: annotator, children: children); + if (isSemanticBoundary) + return new _ConcreteSemanticsFragment(renderObjectOwner: this, annotator: annotator, children: children); + if (annotator != null) + return new _ImplicitSemanticsFragment(renderObjectOwner: this, annotator: annotator, children: children); _semantics = null; if (children == null) return null; @@ -2098,7 +2089,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// non-zero, and hasSemantics isn't true, then the associated call /// to markNeedsSemanticsUpdate() must not have 'onlyChanges' set, as /// it is possible that the node should be entirely removed. - Iterable getSemanticAnnotators() sync* { } + SemanticAnnotator get semanticAnnotator => null; // EVENTS diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart index ce933bbb44..265268bf7a 100644 --- a/packages/flutter/lib/src/rendering/paragraph.dart +++ b/packages/flutter/lib/src/rendering/paragraph.dart @@ -231,10 +231,10 @@ class RenderParagraph extends RenderBox { } @override - Iterable getSemanticAnnotators() sync* { - yield (SemanticsNode node) { - node.label = text.toPlainText(); - }; + SemanticAnnotator get semanticAnnotator => _annotate; + + void _annotate(SemanticsNode node) { + node.label = text.toPlainText(); } @override diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 4578c50b67..7ab769d6a4 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -2054,11 +2054,11 @@ class RenderSemanticsGestureHandler extends RenderProxyBox implements SemanticAc set onTap(GestureTapCallback value) { if (_onTap == value) return; - bool didHaveSemantics = hasSemantics; + bool wasSemanticBoundary = isSemanticBoundary; bool hadHandler = _onTap != null; _onTap = value; if ((value != null) != hadHandler) - markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics); + markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary); } /// Called when the user presses on the render object for a long period of time. @@ -2067,11 +2067,11 @@ class RenderSemanticsGestureHandler extends RenderProxyBox implements SemanticAc set onLongPress(GestureLongPressCallback value) { if (_onLongPress == value) return; - bool didHaveSemantics = hasSemantics; + bool wasSemanticBoundary = isSemanticBoundary; bool hadHandler = _onLongPress != null; _onLongPress = value; if ((value != null) != hadHandler) - markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics); + markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary); } /// Called when the user scrolls to the left or to the right. @@ -2080,11 +2080,11 @@ class RenderSemanticsGestureHandler extends RenderProxyBox implements SemanticAc set onHorizontalDragUpdate(GestureDragUpdateCallback value) { if (_onHorizontalDragUpdate == value) return; - bool didHaveSemantics = hasSemantics; + bool wasSemanticBoundary = isSemanticBoundary; bool hadHandler = _onHorizontalDragUpdate != null; _onHorizontalDragUpdate = value; if ((value != null) != hadHandler) - markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics); + markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary); } /// Called when the user scrolls up or down. @@ -2093,11 +2093,11 @@ class RenderSemanticsGestureHandler extends RenderProxyBox implements SemanticAc set onVerticalDragUpdate(GestureDragUpdateCallback value) { if (_onVerticalDragUpdate == value) return; - bool didHaveSemantics = hasSemantics; + bool wasSemanticBoundary = isSemanticBoundary; bool hadHandler = _onVerticalDragUpdate != null; _onVerticalDragUpdate = value; if ((value != null) != hadHandler) - markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics); + markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary); } /// The fraction of the dimension of this render box to use when @@ -2108,7 +2108,7 @@ class RenderSemanticsGestureHandler extends RenderProxyBox implements SemanticAc double scrollFactor; @override - bool get hasSemantics { + bool get isSemanticBoundary { return onTap != null || onLongPress != null || onHorizontalDragUpdate != null @@ -2116,19 +2116,17 @@ class RenderSemanticsGestureHandler extends RenderProxyBox implements SemanticAc } @override - Iterable getSemanticAnnotators() sync* { - if (hasSemantics) { - yield (SemanticsNode semantics) { - if (onTap != null) - semantics.addAction(SemanticAction.tap); - if (onLongPress != null) - semantics.addAction(SemanticAction.longPress); - if (onHorizontalDragUpdate != null) - semantics.addHorizontalScrollingActions(); - if (onVerticalDragUpdate != null) - semantics.addVerticalScrollingActions(); - }; - } + SemanticAnnotator get semanticAnnotator => isSemanticBoundary ? _annotate : null; + + void _annotate(SemanticsNode node) { + if (onTap != null) + node.addAction(SemanticAction.tap); + if (onLongPress != null) + node.addAction(SemanticAction.longPress); + if (onHorizontalDragUpdate != null) + node.addHorizontalScrollingActions(); + if (onVerticalDragUpdate != null) + node.addVerticalScrollingActions(); } @override @@ -2243,21 +2241,19 @@ class RenderSemanticAnnotations extends RenderProxyBox { } @override - bool get hasSemantics => container; + bool get isSemanticBoundary => container; @override - Iterable getSemanticAnnotators() sync* { + SemanticAnnotator get semanticAnnotator => checked != null || label != null ? _annotate : null; + + void _annotate(SemanticsNode node) { if (checked != null) { - yield (SemanticsNode semantics) { - semantics.hasCheckedState = true; - semantics.isChecked = checked; - }; - } - if (label != null) { - yield (SemanticsNode semantics) { - semantics.label = label; - }; + node + ..hasCheckedState = true + ..isChecked = checked; } + if (label != null) + node.label = label; } } @@ -2273,8 +2269,10 @@ class RenderMergeSemantics extends RenderProxyBox { RenderMergeSemantics({ RenderBox child }) : super(child); @override - Iterable getSemanticAnnotators() sync* { - yield (SemanticsNode node) { node.mergeAllDescendantsIntoThisNode = true; }; + SemanticAnnotator get semanticAnnotator => _annotate; + + void _annotate(SemanticsNode node) { + node.mergeAllDescendantsIntoThisNode = true; } }