Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ash / wm / workspace / magnetism_matcher.h
blob5c17c7a587c1db2a25cb20596db17e86c6defb47
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef ASH_WM_WORKSPACE_MAGNETISM_MATCHER_H_
6 #define ASH_WM_WORKSPACE_MAGNETISM_MATCHER_H_
8 #include <utility>
9 #include <vector>
11 #include "ash/ash_export.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_vector.h"
15 #include "ui/gfx/rect.h"
17 namespace ash {
19 enum MagnetismEdge {
20 MAGNETISM_EDGE_TOP = 1 << 0,
21 MAGNETISM_EDGE_LEFT = 1 << 1,
22 MAGNETISM_EDGE_BOTTOM = 1 << 2,
23 MAGNETISM_EDGE_RIGHT = 1 << 3,
26 const uint32 kAllMagnetismEdges =
27 MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM |
28 MAGNETISM_EDGE_RIGHT;
30 // MagnetismEdgeMatcher is used for matching a particular edge of a window. You
31 // shouldn't need to use this directly, instead use MagnetismMatcher which takes
32 // care of all edges.
33 // MagnetismEdgeMatcher maintains a range of the visible portions of the
34 // edge. As ShouldAttach() is invoked the visible range is updated.
35 class MagnetismEdgeMatcher {
36 public:
37 MagnetismEdgeMatcher(const gfx::Rect& bounds, MagnetismEdge edge);
38 ~MagnetismEdgeMatcher();
40 MagnetismEdge edge() const { return edge_; }
41 const gfx::Rect& bounds() const { return bounds_; }
43 // Returns true if the edge is completely obscured. If true ShouldAttach()
44 // will return false.
45 bool is_edge_obscured() const { return ranges_.empty(); }
47 // Returns true if should attach to the specified bounds.
48 bool ShouldAttach(const gfx::Rect& bounds);
50 private:
51 typedef std::pair<int,int> Range;
52 typedef std::vector<Range> Ranges;
54 // Removes |range| from |ranges_|.
55 void UpdateRanges(const Range& range);
57 static int GetPrimaryCoordinate(const gfx::Rect& bounds, MagnetismEdge edge) {
58 switch (edge) {
59 case MAGNETISM_EDGE_TOP:
60 return bounds.y();
61 case MAGNETISM_EDGE_LEFT:
62 return bounds.x();
63 case MAGNETISM_EDGE_BOTTOM:
64 return bounds.bottom();
65 case MAGNETISM_EDGE_RIGHT:
66 return bounds.right();
68 NOTREACHED();
69 return 0;
72 static MagnetismEdge FlipEdge(MagnetismEdge edge) {
73 switch (edge) {
74 case MAGNETISM_EDGE_TOP:
75 return MAGNETISM_EDGE_BOTTOM;
76 case MAGNETISM_EDGE_BOTTOM:
77 return MAGNETISM_EDGE_TOP;
78 case MAGNETISM_EDGE_LEFT:
79 return MAGNETISM_EDGE_RIGHT;
80 case MAGNETISM_EDGE_RIGHT:
81 return MAGNETISM_EDGE_LEFT;
83 NOTREACHED();
84 return MAGNETISM_EDGE_LEFT;
87 Range GetPrimaryRange(const gfx::Rect& bounds) const {
88 switch (edge_) {
89 case MAGNETISM_EDGE_TOP:
90 case MAGNETISM_EDGE_BOTTOM:
91 return Range(bounds.y(), bounds.bottom());
92 case MAGNETISM_EDGE_LEFT:
93 case MAGNETISM_EDGE_RIGHT:
94 return Range(bounds.x(), bounds.right());
96 NOTREACHED();
97 return Range();
100 Range GetSecondaryRange(const gfx::Rect& bounds) const {
101 switch (edge_) {
102 case MAGNETISM_EDGE_TOP:
103 case MAGNETISM_EDGE_BOTTOM:
104 return Range(bounds.x(), bounds.right());
105 case MAGNETISM_EDGE_LEFT:
106 case MAGNETISM_EDGE_RIGHT:
107 return Range(bounds.y(), bounds.bottom());
109 NOTREACHED();
110 return Range();
113 static bool RangesIntersect(const Range& r1, const Range& r2) {
114 return r2.first < r1.second && r2.second > r1.first;
117 // The bounds of window.
118 const gfx::Rect bounds_;
120 // The edge this matcher checks.
121 const MagnetismEdge edge_;
123 // Visible ranges of the edge. Initialized with GetSecondaryRange() and
124 // updated as ShouldAttach() is invoked. When empty the edge is completely
125 // obscured by other bounds.
126 Ranges ranges_;
128 DISALLOW_COPY_AND_ASSIGN(MagnetismEdgeMatcher);
131 enum SecondaryMagnetismEdge {
132 SECONDARY_MAGNETISM_EDGE_LEADING,
133 SECONDARY_MAGNETISM_EDGE_TRAILING,
134 SECONDARY_MAGNETISM_EDGE_NONE,
137 // Used to identify a matched edge. |primary_edge| is relative to the source and
138 // indicates the edge the two are to share. For example, if |primary_edge| is
139 // MAGNETISM_EDGE_RIGHT then the right edge of the source should snap to to the
140 // left edge of the target. |secondary_edge| indicates one of the edges along
141 // the opposite axis should should also be aligned. For example, if
142 // |primary_edge| is MAGNETISM_EDGE_RIGHT and |secondary_edge| is
143 // SECONDARY_MAGNETISM_EDGE_LEADING then the source should snap to the left top
144 // corner of the target.
145 struct MatchedEdge {
146 MagnetismEdge primary_edge;
147 SecondaryMagnetismEdge secondary_edge;
150 // MagnetismMatcher is used to test if a window should snap to another window.
151 // To use MagnetismMatcher do the following:
152 // . Create it with the bounds of the window being dragged.
153 // . Iterate over the child windows checking if the window being dragged should
154 // attach to it using ShouldAttach().
155 // . Use AreEdgesObscured() to test if no other windows can match (because all
156 // edges are completely obscured).
157 class ASH_EXPORT MagnetismMatcher {
158 public:
159 static const int kMagneticDistance;
161 // |edges| is a bitmask of MagnetismEdges to match against.
162 MagnetismMatcher(const gfx::Rect& bounds, uint32 edges);
163 ~MagnetismMatcher();
165 // Returns true if |bounds| is close enough to the initial bounds that the two
166 // should be attached. If true is returned |edge| is set to indicates how the
167 // two should snap together. See description of MatchedEdge for details.
168 bool ShouldAttach(const gfx::Rect& bounds, MatchedEdge* edge);
170 // Returns true if no other matches are possible.
171 bool AreEdgesObscured() const;
173 private:
174 // Sets |secondary_edge| based on whether the secondary edges should snap.
175 void AttachToSecondaryEdge(const gfx::Rect& bounds,
176 MagnetismEdge edge,
177 SecondaryMagnetismEdge* secondary_edge) const;
179 // The edges to match against.
180 const int32 edges_;
182 ScopedVector<MagnetismEdgeMatcher> matchers_;
184 DISALLOW_COPY_AND_ASSIGN(MagnetismMatcher);
187 } // namespace ash
189 #endif // ASH_WM_WORKSPACE_MAGNETISM_MATCHER_H_