hit_test.dart 2.95 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

Ian Hickson's avatar
Ian Hickson committed
5 6 7
import 'events.dart';

/// An object that can hit-test pointers.
Ian Hickson's avatar
Ian Hickson committed
8
abstract class HitTestable { // ignore: one_member_abstracts
9 10 11 12
  // This class is intended to be used as an interface with the implements
  // keyword, and should not be extended directly.
  factory HitTestable._() => null;

13 14 15 16
  /// Check whether the given position hits this object.
  ///
  /// If this given position hits this object, consider adding a [HitTestEntry]
  /// to the given hit test result.
17
  void hitTest(HitTestResult result, Offset position);
Ian Hickson's avatar
Ian Hickson committed
18
}
19

20 21
/// An object that can dispatch events.
abstract class HitTestDispatcher { // ignore: one_member_abstracts
22 23 24 25
  // This class is intended to be used as an interface with the implements
  // keyword, and should not be extended directly.
  factory HitTestDispatcher._() => null;

26
  /// Override this method to dispatch events.
27 28 29
  void dispatchEvent(PointerEvent event, HitTestResult result);
}

Adam Barth's avatar
Adam Barth committed
30
/// An object that can handle events.
Ian Hickson's avatar
Ian Hickson committed
31
abstract class HitTestTarget { // ignore: one_member_abstracts
32 33 34 35
  // This class is intended to be used as an interface with the implements
  // keyword, and should not be extended directly.
  factory HitTestTarget._() => null;

36
  /// Override this method to receive events.
Ian Hickson's avatar
Ian Hickson committed
37
  void handleEvent(PointerEvent event, HitTestEntry entry);
38 39
}

Adam Barth's avatar
Adam Barth committed
40 41 42 43
/// Data collected during a hit test about a specific [HitTestTarget].
///
/// Subclass this object to pass additional information from the hit test phase
/// to the event propagation phase.
44
class HitTestEntry {
45
  /// Creates a hit test entry.
46
  const HitTestEntry(this.target);
Adam Barth's avatar
Adam Barth committed
47 48

  /// The [HitTestTarget] encountered during the hit test.
49
  final HitTestTarget target;
Ian Hickson's avatar
Ian Hickson committed
50

51
  @override
Ian Hickson's avatar
Ian Hickson committed
52
  String toString() => '$target';
53 54
}

Adam Barth's avatar
Adam Barth committed
55
/// The result of performing a hit test.
56
class HitTestResult {
57 58 59 60
  /// Creates a hit test result.
  ///
  /// If the [path] argument is null, the [path] field will be initialized with
  /// and empty list.
61
  HitTestResult({ List<HitTestEntry> path })
62
    : _path = path ?? <HitTestEntry>[];
63

64
  /// An unmodifiable list of [HitTestEntry] objects recorded during the hit test.
Adam Barth's avatar
Adam Barth committed
65
  ///
66 67 68
  /// The first entry in the path is the most specific, typically the one at
  /// the leaf of tree being hit tested. Event propagation starts with the most
  /// specific (i.e., first) entry and proceeds in order through the path.
69 70
  List<HitTestEntry> get path => new List<HitTestEntry>.unmodifiable(_path);
  final List<HitTestEntry> _path;
71

Adam Barth's avatar
Adam Barth committed
72 73 74
  /// Add a [HitTestEntry] to the path.
  ///
  /// The new entry is added at the end of the path, which means entries should
Ian Hickson's avatar
Ian Hickson committed
75 76
  /// be added in order from most specific to least specific, typically during an
  /// upward walk of the tree being hit tested.
Adam Barth's avatar
Adam Barth committed
77
  void add(HitTestEntry entry) {
78
    _path.add(entry);
79
  }
Ian Hickson's avatar
Ian Hickson committed
80

81
  @override
82
  String toString() => 'HitTestResult(${_path.isEmpty ? "<empty path>" : _path.join(", ")})';
83
}