Commit 13f9e91f authored by Adam Barth's avatar Adam Barth

Cleanup the global scope a bit:

- Remove unused FocusChanged typedef.
- Remove unused centerOfAttentionHeroTag.
- Modernize static functions for interacting with Scrollable by moving them
  into the Scrollable class.
parent f58c3d2b
...@@ -85,7 +85,7 @@ class EnsureVisibleAppState extends State<EnsureVisibleApp> { ...@@ -85,7 +85,7 @@ class EnsureVisibleAppState extends State<EnsureVisibleApp> {
cardModel: cardModels[index], cardModel: cardModels[index],
selected: index == selectedCardIndex, selected: index == selectedCardIndex,
onTap: (BuildContext context) { onTap: (BuildContext context) {
ensureWidgetIsVisible(context, duration: const Duration(milliseconds: 200)) Scrollable.ensureVisible(context, duration: const Duration(milliseconds: 200))
.then((_) { .then((_) {
setState(() { selectedCardIndex = index; }); setState(() { selectedCardIndex = index; });
}); });
......
...@@ -129,7 +129,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> { ...@@ -129,7 +129,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
markers[MarkerType.topLeft] = box.localToGlobal(new Point(0.0, 0.0)); markers[MarkerType.topLeft] = box.localToGlobal(new Point(0.0, 0.0));
final Size size = box.size; final Size size = box.size;
markers[MarkerType.bottomRight] = box.localToGlobal(new Point(size.width, size.height)); markers[MarkerType.bottomRight] = box.localToGlobal(new Point(size.width, size.height));
final ScrollableState scrollable = findScrollableAncestor(target.currentContext); final ScrollableState scrollable = Scrollable.of(target.currentContext);
markersScrollOffset = scrollable.scrollOffset; markersScrollOffset = scrollable.scrollOffset;
}); });
} }
......
...@@ -194,10 +194,10 @@ class DragTarget<T> extends StatefulComponent { ...@@ -194,10 +194,10 @@ class DragTarget<T> extends StatefulComponent {
final DragTargetWillAccept<T> onWillAccept; final DragTargetWillAccept<T> onWillAccept;
final DragTargetAccept<T> onAccept; final DragTargetAccept<T> onAccept;
DragTargetState<T> createState() => new DragTargetState<T>(); _DragTargetState<T> createState() => new _DragTargetState<T>();
} }
class DragTargetState<T> extends State<DragTarget<T>> { class _DragTargetState<T> extends State<DragTarget<T>> {
final List<T> _candidateData = new List<T>(); final List<T> _candidateData = new List<T>();
final List<dynamic> _rejectedData = new List<dynamic>(); final List<dynamic> _rejectedData = new List<dynamic>();
...@@ -279,7 +279,7 @@ class _DragAvatar<T> { ...@@ -279,7 +279,7 @@ class _DragAvatar<T> {
final Widget feedback; final Widget feedback;
final Offset feedbackOffset; final Offset feedbackOffset;
DragTargetState _activeTarget; _DragTargetState _activeTarget;
bool _activeTargetWillAcceptDrop = false; bool _activeTargetWillAcceptDrop = false;
Offset _lastOffset; Offset _lastOffset;
OverlayEntry _entry; OverlayEntry _entry;
...@@ -299,7 +299,7 @@ class _DragAvatar<T> { ...@@ -299,7 +299,7 @@ class _DragAvatar<T> {
_lastOffset = globalPosition - dragStartPoint; _lastOffset = globalPosition - dragStartPoint;
_entry.markNeedsBuild(); _entry.markNeedsBuild();
HitTestResult result = WidgetFlutterBinding.instance.hitTest(globalPosition + feedbackOffset); HitTestResult result = WidgetFlutterBinding.instance.hitTest(globalPosition + feedbackOffset);
DragTargetState target = _getDragTarget(result.path); _DragTargetState target = _getDragTarget(result.path);
if (target == _activeTarget) if (target == _activeTarget)
return; return;
if (_activeTarget != null) if (_activeTarget != null)
...@@ -308,13 +308,13 @@ class _DragAvatar<T> { ...@@ -308,13 +308,13 @@ class _DragAvatar<T> {
_activeTargetWillAcceptDrop = _activeTarget != null && _activeTarget.didEnter(data); _activeTargetWillAcceptDrop = _activeTarget != null && _activeTarget.didEnter(data);
} }
DragTargetState _getDragTarget(List<HitTestEntry> path) { _DragTargetState _getDragTarget(List<HitTestEntry> path) {
// Look for the RenderBox that corresponds to the hit target (the hit target // Look for the RenderBox that corresponds to the hit target (the hit target
// widget builds a RenderMetadata box for us for this purpose). // widget builds a RenderMetadata box for us for this purpose).
for (HitTestEntry entry in path) { for (HitTestEntry entry in path) {
if (entry.target is RenderMetaData) { if (entry.target is RenderMetaData) {
RenderMetaData renderMetaData = entry.target; RenderMetaData renderMetaData = entry.target;
if (renderMetaData.metaData is DragTargetState) if (renderMetaData.metaData is _DragTargetState)
return renderMetaData.metaData; return renderMetaData.metaData;
} }
} }
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
import 'framework.dart'; import 'framework.dart';
typedef void FocusChanged(GlobalKey key);
// _noFocusedScope is used by Focus to track the case where none of the Focus // _noFocusedScope is used by Focus to track the case where none of the Focus
// component's subscopes (e.g. dialogs) are focused. This is distinct from the // component's subscopes (e.g. dialogs) are focused. This is distinct from the
// focused scope being null, which means that we haven't yet decided which scope // focused scope being null, which means that we haven't yet decided which scope
......
...@@ -335,7 +335,7 @@ enum _StateLifecycle { ...@@ -335,7 +335,7 @@ enum _StateLifecycle {
/// The signature of setState() methods. /// The signature of setState() methods.
typedef void StateSetter(VoidCallback fn); typedef void StateSetter(VoidCallback fn);
/// The logic and internal state for a StatefulComponent. /// The logic and internal state for a [StatefulComponent].
abstract class State<T extends StatefulComponent> { abstract class State<T extends StatefulComponent> {
/// The current configuration (an instance of the corresponding /// The current configuration (an instance of the corresponding
/// StatefulComponent class). /// StatefulComponent class).
...@@ -439,13 +439,13 @@ abstract class State<T extends StatefulComponent> { ...@@ -439,13 +439,13 @@ abstract class State<T extends StatefulComponent> {
} }
} }
abstract class ProxyComponent extends Widget { abstract class _ProxyComponent extends Widget {
const ProxyComponent({ Key key, this.child }) : super(key: key); const _ProxyComponent({ Key key, this.child }) : super(key: key);
final Widget child; final Widget child;
} }
abstract class ParentDataWidget extends ProxyComponent { abstract class ParentDataWidget extends _ProxyComponent {
const ParentDataWidget({ Key key, Widget child }) const ParentDataWidget({ Key key, Widget child })
: super(key: key, child: child); : super(key: key, child: child);
...@@ -460,7 +460,7 @@ abstract class ParentDataWidget extends ProxyComponent { ...@@ -460,7 +460,7 @@ abstract class ParentDataWidget extends ProxyComponent {
void applyParentData(RenderObject renderObject); void applyParentData(RenderObject renderObject);
} }
abstract class InheritedWidget extends ProxyComponent { abstract class InheritedWidget extends _ProxyComponent {
const InheritedWidget({ Key key, Widget child }) const InheritedWidget({ Key key, Widget child })
: super(key: key, child: child); : super(key: key, child: child);
...@@ -1248,8 +1248,8 @@ class StatefulComponentElement<T extends StatefulComponent, U extends State<T>> ...@@ -1248,8 +1248,8 @@ class StatefulComponentElement<T extends StatefulComponent, U extends State<T>>
} }
} }
abstract class ProxyElement<T extends ProxyComponent> extends ComponentElement<T> { abstract class _ProxyElement<T extends _ProxyComponent> extends ComponentElement<T> {
ProxyElement(T widget) : super(widget) { _ProxyElement(T widget) : super(widget) {
_builder = (BuildContext context) => this.widget.child; _builder = (BuildContext context) => this.widget.child;
} }
...@@ -1267,7 +1267,7 @@ abstract class ProxyElement<T extends ProxyComponent> extends ComponentElement<T ...@@ -1267,7 +1267,7 @@ abstract class ProxyElement<T extends ProxyComponent> extends ComponentElement<T
void notifyDescendants(T oldWidget); void notifyDescendants(T oldWidget);
} }
class ParentDataElement extends ProxyElement<ParentDataWidget> { class ParentDataElement extends _ProxyElement<ParentDataWidget> {
ParentDataElement(ParentDataWidget widget) : super(widget); ParentDataElement(ParentDataWidget widget) : super(widget);
void mount(Element parent, dynamic slot) { void mount(Element parent, dynamic slot) {
...@@ -1300,7 +1300,7 @@ class ParentDataElement extends ProxyElement<ParentDataWidget> { ...@@ -1300,7 +1300,7 @@ class ParentDataElement extends ProxyElement<ParentDataWidget> {
class InheritedElement extends ProxyElement<InheritedWidget> { class InheritedElement extends _ProxyElement<InheritedWidget> {
InheritedElement(InheritedWidget widget) : super(widget); InheritedElement(InheritedWidget widget) : super(widget);
void notifyDescendants(InheritedWidget oldWidget) { void notifyDescendants(InheritedWidget oldWidget) {
......
...@@ -56,8 +56,6 @@ import 'transitions.dart'; ...@@ -56,8 +56,6 @@ import 'transitions.dart';
// should interpolate the inherited properties from their value at the source to // should interpolate the inherited properties from their value at the source to
// their value at the target. See: https://github.com/flutter/flutter/issues/213 // their value at the target. See: https://github.com/flutter/flutter/issues/213
final Object centerOfAttentionHeroTag = new Object();
class _HeroManifest { class _HeroManifest {
const _HeroManifest({ const _HeroManifest({
this.key, this.key,
......
...@@ -52,6 +52,55 @@ abstract class Scrollable extends StatefulComponent { ...@@ -52,6 +52,55 @@ abstract class Scrollable extends StatefulComponent {
final SnapOffsetCallback snapOffsetCallback; final SnapOffsetCallback snapOffsetCallback;
final double snapAlignmentOffset; final double snapAlignmentOffset;
/// Returns the closest enclosing scrollable for the given context.
static ScrollableState of(BuildContext context) {
return context.ancestorStateOfType(ScrollableState);
}
/// Scrolls the closest enclosing scrollable to make the given context visible.
static Future ensureVisible(BuildContext context, { Duration duration, Curve curve }) {
assert(context.findRenderObject() is RenderBox);
// TODO(abarth): This function doesn't handle nested scrollable widgets.
ScrollableState scrollable = Scrollable.of(context);
if (scrollable == null)
return new Future.value();
RenderBox targetBox = context.findRenderObject();
assert(targetBox.attached);
Size targetSize = targetBox.size;
RenderBox scrollableBox = scrollable.context.findRenderObject();
assert(scrollableBox.attached);
Size scrollableSize = scrollableBox.size;
double scrollOffsetDelta;
switch (scrollable.config.scrollDirection) {
case ScrollDirection.vertical:
Point targetCenter = targetBox.localToGlobal(new Point(0.0, targetSize.height / 2.0));
Point scrollableCenter = scrollableBox.localToGlobal(new Point(0.0, scrollableSize.height / 2.0));
scrollOffsetDelta = targetCenter.y - scrollableCenter.y;
break;
case ScrollDirection.horizontal:
Point targetCenter = targetBox.localToGlobal(new Point(targetSize.width / 2.0, 0.0));
Point scrollableCenter = scrollableBox.localToGlobal(new Point(scrollableSize.width / 2.0, 0.0));
scrollOffsetDelta = targetCenter.x - scrollableCenter.x;
break;
case ScrollDirection.both:
assert(false); // See https://github.com/flutter/engine/issues/888
break;
}
ExtentScrollBehavior scrollBehavior = scrollable.scrollBehavior;
double scrollOffset = (scrollable.scrollOffset + scrollOffsetDelta)
.clamp(scrollBehavior.minScrollOffset, scrollBehavior.maxScrollOffset);
if (scrollOffset != scrollable.scrollOffset)
return scrollable.scrollTo(scrollOffset, duration: duration, curve: curve);
return new Future.value();
}
ScrollableState createState(); ScrollableState createState();
} }
...@@ -261,69 +310,12 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> { ...@@ -261,69 +310,12 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
} }
} }
ScrollableState findScrollableAncestor(BuildContext context) {
ScrollableState result;
context.visitAncestorElements((Element element) {
if (element is StatefulComponentElement) {
if (element.state is ScrollableState) {
result = element.state;
return false;
}
}
return true;
});
return result;
}
class ScrollNotification extends Notification { class ScrollNotification extends Notification {
ScrollNotification(this.scrollable, this.position); ScrollNotification(this.scrollable, this.position);
final ScrollableState scrollable; final ScrollableState scrollable;
final double position; final double position;
} }
Future ensureWidgetIsVisible(BuildContext context, { Duration duration, Curve curve }) {
assert(context.findRenderObject() is RenderBox);
// TODO(abarth): This function doesn't handle nested scrollable widgets.
ScrollableState scrollable = findScrollableAncestor(context);
if (scrollable == null)
return new Future.value();
RenderBox targetBox = context.findRenderObject();
assert(targetBox.attached);
Size targetSize = targetBox.size;
RenderBox scrollableBox = scrollable.context.findRenderObject();
assert(scrollableBox.attached);
Size scrollableSize = scrollableBox.size;
double scrollOffsetDelta;
switch (scrollable.config.scrollDirection) {
case ScrollDirection.vertical:
Point targetCenter = targetBox.localToGlobal(new Point(0.0, targetSize.height / 2.0));
Point scrollableCenter = scrollableBox.localToGlobal(new Point(0.0, scrollableSize.height / 2.0));
scrollOffsetDelta = targetCenter.y - scrollableCenter.y;
break;
case ScrollDirection.horizontal:
Point targetCenter = targetBox.localToGlobal(new Point(targetSize.width / 2.0, 0.0));
Point scrollableCenter = scrollableBox.localToGlobal(new Point(scrollableSize.width / 2.0, 0.0));
scrollOffsetDelta = targetCenter.x - scrollableCenter.x;
break;
case ScrollDirection.both:
assert(false); // See https://github.com/flutter/engine/issues/888
break;
}
ExtentScrollBehavior scrollBehavior = scrollable.scrollBehavior;
double scrollOffset = (scrollable.scrollOffset + scrollOffsetDelta)
.clamp(scrollBehavior.minScrollOffset, scrollBehavior.maxScrollOffset);
if (scrollOffset != scrollable.scrollOffset)
return scrollable.scrollTo(scrollOffset, duration: duration, curve: curve);
return new Future.value();
}
/// A simple scrollable widget that has a single child. Use this component if /// A simple scrollable widget that has a single child. Use this component if
/// you are not worried about offscreen widgets consuming resources. /// you are not worried about offscreen widgets consuming resources.
class ScrollableViewport extends Scrollable { class ScrollableViewport extends Scrollable {
......
...@@ -18,10 +18,10 @@ abstract class StatusTransitionComponent extends StatefulComponent { ...@@ -18,10 +18,10 @@ abstract class StatusTransitionComponent extends StatefulComponent {
Widget build(BuildContext context); Widget build(BuildContext context);
StatusTransitionState createState() => new StatusTransitionState(); _StatusTransitionState createState() => new _StatusTransitionState();
} }
class StatusTransitionState extends State<StatusTransitionComponent> { class _StatusTransitionState extends State<StatusTransitionComponent> {
void initState() { void initState() {
super.initState(); super.initState();
config.performance.addStatusListener(_performanceStatusChanged); config.performance.addStatusListener(_performanceStatusChanged);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment