Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: views/bubble/border_contents_view.cc

Issue 8588064: views: Move bubble, events, focus and layout to ui/views/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/bubble/border_contents_view.h ('k') | views/bubble/bubble_border.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 #include "views/bubble/border_contents_view.h"
6
7 #include <algorithm>
8
9 #include "ui/gfx/screen.h"
10
11 static const int kTopMargin = 6;
12 static const int kLeftMargin = 6;
13 static const int kBottomMargin = 6;
14 static const int kRightMargin = 6;
15
16 namespace {
17
18 // Computes how much |window_bounds| is off-screen of the monitor bounds
19 // |monitor_bounds| and puts the values in |offscreen_insets|.
20 // Returns false if |window_bounds| is actually contained in |monitor_bounds|,
21 // in which case |offscreen_insets| is not modified.
22 bool ComputeOffScreenInsets(const gfx::Rect& monitor_bounds,
23 const gfx::Rect& window_bounds,
24 gfx::Insets* offscreen_insets) {
25 if (monitor_bounds.Contains(window_bounds))
26 return false;
27
28 if (!offscreen_insets)
29 return true;
30
31 // window_bounds
32 // +-------------------------------+
33 // | top |
34 // | +----------------+ |
35 // | left | monitor_bounds | right |
36 // | +----------------+ |
37 // | bottom |
38 // +-------------------------------+
39 int top = std::max(0, monitor_bounds.y() - window_bounds.y());
40 int left = std::max(0, monitor_bounds.x() - window_bounds.x());
41 int bottom = std::max(0, window_bounds.bottom() - monitor_bounds.bottom());
42 int right = std::max(0, window_bounds.right() - monitor_bounds.right());
43
44 offscreen_insets->Set(top, left, bottom, right);
45 return true;
46 }
47
48 // Convenience method that returns the height of |insets| if |vertical| is
49 // true, its width otherwise.
50 int GetInsetsLength(const gfx::Insets& insets, bool vertical) {
51 return vertical ? insets.height() : insets.width();
52 }
53
54 } // namespace
55
56 namespace views {
57
58 BorderContentsView::BorderContentsView()
59 : bubble_border_(NULL),
60 content_margins_(kTopMargin, kLeftMargin, kBottomMargin, kRightMargin) {
61 }
62
63 BorderContentsView::BorderContentsView(int top_margin,
64 int left_margin,
65 int bottom_margin,
66 int right_margin)
67 : bubble_border_(NULL),
68 content_margins_(top_margin, left_margin, bottom_margin, right_margin) {
69 }
70
71 BorderContentsView::~BorderContentsView() {}
72
73 void BorderContentsView::Init() {
74 // Default arrow location.
75 BubbleBorder::ArrowLocation arrow_location =
76 BubbleBorder::TOP_LEFT;
77 if (base::i18n::IsRTL())
78 arrow_location = BubbleBorder::horizontal_mirror(arrow_location);
79 DCHECK(!bubble_border_);
80
81 // TODO(alicet): Expose the shadow option in BorderContentsView when we make
82 // the fullscreen exit bubble use the new bubble code.
83 bubble_border_ = new BubbleBorder(arrow_location,
84 views::BubbleBorder::NO_SHADOW);
85 set_border(bubble_border_);
86 set_background(new BubbleBackground(bubble_border_));
87 }
88
89 void BorderContentsView::SetBackgroundColor(SkColor color) {
90 bubble_border_->set_background_color(color);
91 }
92
93 void BorderContentsView::SetAlignment(
94 views::BubbleBorder::BubbleAlignment alignment) {
95 bubble_border_->set_alignment(alignment);
96 }
97
98 void BorderContentsView::SizeAndGetBounds(
99 const gfx::Rect& position_relative_to,
100 BubbleBorder::ArrowLocation arrow_location,
101 bool allow_bubble_offscreen,
102 const gfx::Size& contents_size,
103 gfx::Rect* contents_bounds,
104 gfx::Rect* window_bounds) {
105 if (base::i18n::IsRTL())
106 arrow_location = BubbleBorder::horizontal_mirror(arrow_location);
107 bubble_border_->set_arrow_location(arrow_location);
108 // Set the border.
109 set_border(bubble_border_);
110
111 // Give the contents a margin.
112 gfx::Size local_contents_size(contents_size);
113 local_contents_size.Enlarge(content_margins_.width(),
114 content_margins_.height());
115
116 // Try putting the arrow in its initial location, and calculating the bounds.
117 *window_bounds =
118 bubble_border_->GetBounds(position_relative_to, local_contents_size);
119 if (!allow_bubble_offscreen) {
120 gfx::Rect monitor_bounds = GetMonitorBounds(position_relative_to);
121 if (!monitor_bounds.IsEmpty()) {
122 // Try to resize vertically if this does not fit on the screen.
123 MirrorArrowIfOffScreen(true, // |vertical|.
124 position_relative_to, monitor_bounds,
125 local_contents_size, &arrow_location,
126 window_bounds);
127 // Then try to resize horizontally if it still does not fit on the screen.
128 MirrorArrowIfOffScreen(false, // |vertical|.
129 position_relative_to, monitor_bounds,
130 local_contents_size, &arrow_location,
131 window_bounds);
132 }
133 }
134
135 // Calculate the bounds of the contained contents (in window coordinates) by
136 // subtracting the border dimensions and margin amounts.
137 *contents_bounds = gfx::Rect(gfx::Point(), window_bounds->size());
138 gfx::Insets insets;
139 bubble_border_->GetInsets(&insets);
140 insets += content_margins_;
141 contents_bounds->Inset(insets);
142 }
143
144 gfx::Rect BorderContentsView::GetMonitorBounds(const gfx::Rect& rect) {
145 return gfx::Screen::GetMonitorWorkAreaNearestPoint(rect.CenterPoint());
146 }
147
148 void BorderContentsView::MirrorArrowIfOffScreen(
149 bool vertical,
150 const gfx::Rect& position_relative_to,
151 const gfx::Rect& monitor_bounds,
152 const gfx::Size& local_contents_size,
153 BubbleBorder::ArrowLocation* arrow_location,
154 gfx::Rect* window_bounds) {
155 // If the bounds don't fit, move the arrow to its mirrored position to see if
156 // it improves things.
157 gfx::Insets offscreen_insets;
158 if (ComputeOffScreenInsets(monitor_bounds, *window_bounds,
159 &offscreen_insets) &&
160 GetInsetsLength(offscreen_insets, vertical) > 0) {
161 BubbleBorder::ArrowLocation original_arrow_location =
162 *arrow_location;
163 *arrow_location =
164 vertical ? BubbleBorder::vertical_mirror(*arrow_location) :
165 BubbleBorder::horizontal_mirror(*arrow_location);
166
167 // Change the arrow and get the new bounds.
168 bubble_border_->set_arrow_location(*arrow_location);
169 *window_bounds = bubble_border_->GetBounds(position_relative_to,
170 local_contents_size);
171 gfx::Insets new_offscreen_insets;
172 // If there is more of the window offscreen, we'll keep the old arrow.
173 if (ComputeOffScreenInsets(monitor_bounds, *window_bounds,
174 &new_offscreen_insets) &&
175 GetInsetsLength(new_offscreen_insets, vertical) >=
176 GetInsetsLength(offscreen_insets, vertical)) {
177 *arrow_location = original_arrow_location;
178 bubble_border_->set_arrow_location(*arrow_location);
179 *window_bounds = bubble_border_->GetBounds(position_relative_to,
180 local_contents_size);
181 }
182 }
183 }
184
185 } // namespace views
OLDNEW
« no previous file with comments | « views/bubble/border_contents_view.h ('k') | views/bubble/bubble_border.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698