decoration.dart 4.39 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.

5
import 'basic_types.dart';
6
import 'edge_insets.dart';
7

8
export 'edge_insets.dart' show EdgeInsets;
9 10 11

// This group of classes is intended for painting in cartesian coordinates.

12 13 14 15 16 17 18 19 20
/// A description of a box decoration (a decoration applied to a [Rect]).
///
/// This class presents the abstract interface for all decorations.
/// See [BoxDecoration] for a concrete example.
///
/// To actually paint a [Decoration], use the [createBoxPainter]
/// method to obtain a [BoxPainter]. [Decoration] objects can be
/// shared between boxes; [BoxPainter] objects can cache resources to
/// make painting on a particular surface faster.
21
abstract class Decoration {
22
  /// Abstract const constructor.
23
  const Decoration();
24 25 26 27 28 29 30 31

  /// In checked mode, throws an exception if the object is not in a
  /// valid configuration. Otherwise, returns true.
  ///
  /// This is intended to be used as follows:
  /// ```dart
  ///   assert(myDecoration.debugAssertValid());
  /// ```
32
  bool debugAssertValid() => true;
33 34 35 36 37 38

  /// Returns the insets to apply when using this decoration on a box
  /// that has contents, so that the contents do not overlap the edges
  /// of the decoration. For example, if the decoration draws a frame
  /// around its edge, the padding would return the distance by which
  /// to inset the children so as to not overlap the frame.
39
  EdgeInsets get padding => null;
40 41

  /// Linearly interpolates from [a] to [this].
42
  Decoration lerpFrom(Decoration a, double t) => this;
43 44

  /// Linearly interpolates from [this] to [b].
45
  Decoration lerpTo(Decoration b, double t) => b;
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

  /// Linearly interpolates from [begin] to [end].
  ///
  /// This defers to [end]'s [lerpTo] function if [end] is not null,
  /// otherwise it uses [begin]'s [lerpFrom] function.
  static Decoration lerp(Decoration begin, Decoration end, double t) {
    if (end != null)
      return end.lerpTo(begin, t);
    if (begin != null)
      return begin.lerpFrom(end, t);
    return null;
  }

  /// Tests whether the given point, on a rectangle of a given size,
  /// would be considered to hit the decoration or not. For example,
  /// if the decoration only draws a circle, this function might
  /// return true if the point was inside the circle and false
  /// otherwise.
64
  bool hitTest(Size size, Point position) => true;
65 66 67 68 69 70

  /// Whether this [Decoration] subclass needs its painters to use
  /// [addChangeListener] to listen for updates. For example, if a
  /// decoration draws a background image, owners would have to listen
  /// for the image's load completing so that they could repaint
  /// themselves when appropriate.
71
  bool get needsListeners => false;
72 73 74 75

  /// Register a listener. See [needsListeners].
  ///
  /// Only call this if [needsListeners] is true.
76
  void addChangeListener(VoidCallback listener) { assert(false); }
77 78 79 80 81

  /// Unregisters a listener previous registered with
  /// [addChangeListener]. See [needsListeners].
  ///
  /// Only call this if [needsListeners] is true.
82
  void removeChangeListener(VoidCallback listener) { assert(false); }
83 84

  /// Returns a [BoxPainter] that will paint this decoration.
85
  BoxPainter createBoxPainter();
86 87

  @override
88 89 90
  String toString([String prefix = '']) => '$prefix$runtimeType';
}

91 92 93 94
/// A stateful class that can paint a particular [Decoration].
///
/// [BoxPainter] objects can cache resources so that they can be used
/// multiple times.
Ian Hickson's avatar
Ian Hickson committed
95
abstract class BoxPainter { // ignore: one_member_abstracts
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

  /// Paints the [Decoration] for which this object was created on the
  /// given canvas using the given rectangle.
  ///
  /// If this object caches resources for painting (e.g. [Paint]
  /// objects), the cache may be flushed when [paint] is called with a
  /// new [Rect]. For this reason, it may be more efficient to call
  /// [Decoration.createBoxPainter] for each different rectangle that
  /// is being painted in a particular frame.
  ///
  /// For example, if a decoration's owner wants to paint a particular
  /// decoration once for its whole size, and once just in the bottom
  /// right, it might get two [BoxPainter] instances, one for each.
  /// However, when its size changes, it could continue using those
  /// same instances, since the previous resources would no longer be
  /// relevant and thus losing them would not be an issue.
112
  void paint(Canvas canvas, Rect rect);
113
}