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

Side by Side Diff: ui/aura_shell/toplevel_frame_view.cc

Issue 9035001: Move some more WM functionality down into ash. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years 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 | « ui/aura_shell/toplevel_frame_view.h ('k') | ui/aura_shell/toplevel_layout_manager.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 "ui/aura_shell/toplevel_frame_view.h"
6
7 #include "grit/ui_resources.h"
8 #include "ui/aura/cursor.h"
9 #include "ui/base/animation/throb_animation.h"
10 #include "ui/base/hit_test.h"
11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/gfx/canvas.h"
13 #include "ui/views/controls/button/custom_button.h"
14 #include "ui/views/widget/widget.h"
15 #include "ui/views/widget/widget_delegate.h"
16
17 namespace aura_shell {
18 namespace internal {
19
20 namespace {
21 // The thickness of the left, right and bottom edges of the frame.
22 const int kFrameBorderThickness = 8;
23 const int kFrameOpacity = 50;
24 // The color used to fill the frame.
25 const SkColor kFrameColor = SkColorSetARGB(kFrameOpacity, 0, 0, 0);
26 const int kFrameBorderHiddenOpacity = 0;
27 const int kFrameBorderVisibleOpacity = kFrameOpacity;
28 // How long the hover animation takes if uninterrupted.
29 const int kHoverFadeDurationMs = 250;
30 } // namespace
31
32 // Buttons for window controls - close, zoom, etc.
33 class WindowControlButton : public views::CustomButton {
34 public:
35 WindowControlButton(views::ButtonListener* listener,
36 SkColor color,
37 const SkBitmap& icon)
38 : views::CustomButton(listener),
39 color_(color),
40 icon_(icon) {
41 }
42 virtual ~WindowControlButton() {}
43
44 // Overridden from views::View:
45 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
46 canvas->FillRect(GetBackgroundColor(), GetLocalBounds());
47 canvas->DrawBitmapInt(icon_, 0, 0);
48 }
49 virtual gfx::Size GetPreferredSize() OVERRIDE {
50 gfx::Size size(icon_.width(), icon_.height());
51 size.Enlarge(3, 2);
52 return size;
53 }
54
55 private:
56 SkColor GetBackgroundColor() {
57 return SkColorSetARGB(hover_animation_->CurrentValueBetween(0, 150),
58 SkColorGetR(color_),
59 SkColorGetG(color_),
60 SkColorGetB(color_));
61 }
62
63 SkColor color_;
64 SkBitmap icon_;
65
66 DISALLOW_COPY_AND_ASSIGN(WindowControlButton);
67 };
68
69 // Base class for all animatable frame components such as sizing borders and
70 // the window's caption. Provides shared animation and event-handling logic.
71 class FrameComponent : public views::View,
72 public ui::AnimationDelegate {
73 public:
74 virtual ~FrameComponent() {
75 }
76
77 // Control animations.
78 void Show() {
79 animation_->Show();
80 }
81 void Hide() {
82 animation_->Hide();
83 }
84
85 // Current animation state.
86 bool IsShowing() const {
87 return animation_->IsShowing();
88 }
89 bool IsHiding() const {
90 return animation_->IsClosing();
91 }
92
93 // Returns true if the view ignores events to itself or its children at the
94 // specified point in its parent's coordinates. By default, any events within
95 // the bounds of this view are ignored so that the parent (the NCFV) can
96 // handle them instead. Derived classes can override to disable this for some
97 // of their children.
98 virtual bool IgnoreEventsForPoint(const gfx::Point& point) {
99 gfx::Point translated_point(point);
100 ConvertPointToView(parent(), this, &translated_point);
101 return HitTest(translated_point);
102 }
103
104 protected:
105 FrameComponent()
106 : ALLOW_THIS_IN_INITIALIZER_LIST(
107 animation_(new ui::SlideAnimation(this))) {
108 animation_->SetSlideDuration(kHoverFadeDurationMs);
109 }
110
111 // Most of the frame components are rendered with a transparent bg.
112 void PaintTransparentBackground(gfx::Canvas* canvas) {
113 // Fill with current opacity value.
114 int opacity = animation_->CurrentValueBetween(kFrameBorderHiddenOpacity,
115 kFrameBorderVisibleOpacity);
116 canvas->FillRect(SkColorSetARGB(opacity,
117 SkColorGetR(kFrameColor),
118 SkColorGetG(kFrameColor),
119 SkColorGetB(kFrameColor)),
120 GetLocalBounds());
121 }
122
123 // Overridden from ui::AnimationDelegate:
124 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE {
125 SchedulePaint();
126 }
127
128 private:
129 scoped_ptr<ui::SlideAnimation> animation_;
130
131 DISALLOW_COPY_AND_ASSIGN(FrameComponent);
132 };
133
134 // A view that renders the title bar of the window, and also hosts the window
135 // controls.
136 class WindowCaption : public FrameComponent,
137 public views::ButtonListener {
138 public:
139 WindowCaption() {
140 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
141 close_button_ =
142 new WindowControlButton(this, SK_ColorRED,
143 *rb.GetBitmapNamed(IDR_AURA_WINDOW_CLOSE_ICON));
144 zoom_button_ =
145 new WindowControlButton(this, SK_ColorGREEN,
146 *rb.GetBitmapNamed(IDR_AURA_WINDOW_ZOOM_ICON));
147 AddChildView(close_button_);
148 AddChildView(zoom_button_);
149 }
150 virtual ~WindowCaption() {}
151
152 // Returns the hit-test code for the specified point in parent coordinates.
153 int NonClientHitTest(const gfx::Point& point) {
154 gfx::Point translated_point(point);
155 View::ConvertPointToView(parent(), this, &translated_point);
156 // The window controls come second.
157 if (close_button_->GetMirroredBounds().Contains(translated_point))
158 return HTCLOSE;
159 else if (zoom_button_->GetMirroredBounds().Contains(translated_point))
160 return HTMAXBUTTON;
161 return HTNOWHERE;
162 }
163
164 // Overridden from FrameComponent:
165 virtual bool IgnoreEventsForPoint(const gfx::Point& point) OVERRIDE {
166 gfx::Point translated_point(point);
167 ConvertPointToView(parent(), this, &translated_point);
168 if (PointIsInChildView(close_button_, translated_point))
169 return false;
170 if (PointIsInChildView(zoom_button_, translated_point))
171 return false;
172 return FrameComponent::IgnoreEventsForPoint(point);
173 }
174
175 // Overridden from views::View:
176 virtual gfx::Size GetPreferredSize() OVERRIDE {
177 return gfx::Size(0, close_button_->GetPreferredSize().height());
178 }
179
180 private:
181 // Returns true if the specified |point| in this view's coordinates hit tests
182 // against |child|, a child view of this view.
183 bool PointIsInChildView(views::View* child,
184 const gfx::Point& point) const {
185 gfx::Point child_point(point);
186 ConvertPointToView(this, child, &child_point);
187 return child->HitTest(child_point);
188 }
189
190 // Overridden from views::View:
191 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
192 PaintTransparentBackground(canvas);
193 }
194 virtual void Layout() OVERRIDE {
195 gfx::Size close_button_ps = close_button_->GetPreferredSize();
196 close_button_->SetBoundsRect(
197 gfx::Rect(width() - close_button_ps.width(),
198 0, close_button_ps.width(), close_button_ps.height()));
199
200 gfx::Size zoom_button_ps = zoom_button_->GetPreferredSize();
201 zoom_button_->SetBoundsRect(
202 gfx::Rect(close_button_->x() - zoom_button_ps.width(), 0,
203 zoom_button_ps.width(), zoom_button_ps.height()));
204 }
205
206 // Overridden from views::ButtonListener:
207 virtual void ButtonPressed(views::Button* sender,
208 const views::Event& event) OVERRIDE {
209 if (sender == close_button_) {
210 GetWidget()->Close();
211 } else if (sender == zoom_button_) {
212 if (GetWidget()->IsMaximized())
213 GetWidget()->Restore();
214 else
215 GetWidget()->Maximize();
216 }
217 }
218
219 views::Button* close_button_;
220 views::Button* zoom_button_;
221
222 DISALLOW_COPY_AND_ASSIGN(WindowCaption);
223 };
224
225 // A class that renders the sizing border that appears when the user moves
226 // their mouse over a sizing edge. This view is not actually responsible for
227 // resizing the window, the EventFilter is.
228 class SizingBorder : public FrameComponent {
229 public:
230 SizingBorder() {}
231 virtual ~SizingBorder() {}
232
233 void Configure(const gfx::Rect& hidden_bounds,
234 const gfx::Rect& visible_bounds) {
235 hidden_bounds_ = hidden_bounds;
236 visible_bounds_ = visible_bounds;
237 SetBoundsRect(hidden_bounds_);
238 }
239
240 protected:
241 // Overridden from ui::AnimationDelegate:
242 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE {
243 gfx::Rect current_bounds = animation->CurrentValueBetween(hidden_bounds_,
244 visible_bounds_);
245 SetBoundsRect(current_bounds);
246 FrameComponent::AnimationProgressed(animation);
247 }
248
249 private:
250 // Overridden from views::View:
251 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
252 PaintTransparentBackground(canvas);
253 }
254
255 // Each of these represents the hidden/visible states of the sizing border.
256 // When the view is shown or hidden it animates between them.
257 gfx::Rect hidden_bounds_;
258 gfx::Rect visible_bounds_;
259
260 DISALLOW_COPY_AND_ASSIGN(SizingBorder);
261 };
262
263 ////////////////////////////////////////////////////////////////////////////////
264 // ToplevelFrameView, public:
265
266 ToplevelFrameView::ToplevelFrameView()
267 : current_hittest_code_(HTNOWHERE),
268 caption_(new WindowCaption),
269 left_edge_(new SizingBorder),
270 right_edge_(new SizingBorder),
271 bottom_edge_(new SizingBorder) {
272 AddChildView(caption_);
273 AddChildView(left_edge_);
274 AddChildView(right_edge_);
275 AddChildView(bottom_edge_);
276 }
277
278 ToplevelFrameView::~ToplevelFrameView() {
279 }
280
281 ////////////////////////////////////////////////////////////////////////////////
282 // ToplevelFrameView, private:
283
284 int ToplevelFrameView::NonClientBorderThickness() const {
285 return kFrameBorderThickness;
286 }
287
288 int ToplevelFrameView::NonClientTopBorderHeight() const {
289 return caption_->GetPreferredSize().height();
290 }
291
292 int ToplevelFrameView::NonClientHitTestImpl(const gfx::Point& point) {
293 // Sanity check.
294 if (!GetLocalBounds().Contains(point))
295 return HTNOWHERE;
296
297 // The client view gets first crack at claiming the point.
298 int frame_component = GetWidget()->client_view()->NonClientHitTest(point);
299 if (frame_component != HTNOWHERE)
300 return frame_component;
301
302 frame_component = caption_->NonClientHitTest(point);
303 if (frame_component != HTNOWHERE)
304 return frame_component;
305
306 // Finally other portions of the frame/sizing border.
307 frame_component =
308 GetHTComponentForFrame(point,
309 NonClientBorderThickness(),
310 NonClientBorderThickness(),
311 NonClientBorderThickness(),
312 NonClientBorderThickness(),
313 GetWidget()->widget_delegate()->CanResize());
314
315 // Coerce HTCAPTION as a fallback.
316 return frame_component == HTNOWHERE ? HTCAPTION : frame_component;
317 }
318
319 void ToplevelFrameView::ShowFrameComponent(FrameComponent* frame_component) {
320 if (frame_component && !frame_component->IsShowing())
321 frame_component->Show();
322 if (caption_ != frame_component && !caption_->IsHiding())
323 caption_->Hide();
324 if (left_edge_ != frame_component && !left_edge_->IsHiding())
325 left_edge_->Hide();
326 if (right_edge_ != frame_component && !right_edge_->IsHiding())
327 right_edge_->Hide();
328 if (bottom_edge_ != frame_component && !bottom_edge_->IsHiding())
329 bottom_edge_->Hide();
330 }
331
332 gfx::Rect ToplevelFrameView::GetHiddenBoundsForSizingBorder(
333 int frame_component) const {
334 int border_size = NonClientBorderThickness();
335 int caption_height = NonClientTopBorderHeight();
336 switch (frame_component) {
337 case HTLEFT:
338 return gfx::Rect(border_size, caption_height, border_size,
339 height() - border_size - caption_height);
340 case HTBOTTOM:
341 return gfx::Rect(border_size, height() - 2 * border_size,
342 width() - 2 * border_size, border_size);
343 case HTRIGHT:
344 return gfx::Rect(width() - 2 * border_size, caption_height, border_size,
345 height() - border_size - caption_height);
346 default:
347 break;
348 }
349 return gfx::Rect();
350 }
351
352 gfx::Rect ToplevelFrameView::GetVisibleBoundsForSizingBorder(
353 int frame_component) const {
354 int border_size = NonClientBorderThickness();
355 int caption_height = NonClientTopBorderHeight();
356 switch (frame_component) {
357 case HTLEFT:
358 return gfx::Rect(0, caption_height, border_size,
359 height() - border_size - caption_height);
360 case HTBOTTOM:
361 return gfx::Rect(border_size, height() - border_size,
362 width() - 2 * border_size, border_size);
363 case HTRIGHT:
364 return gfx::Rect(width() - border_size, caption_height, border_size,
365 height() - border_size - caption_height);
366 default:
367 break;
368 }
369 return gfx::Rect();
370 }
371
372 ////////////////////////////////////////////////////////////////////////////////
373 // ToplevelFrameView, views::NonClientFrameView overrides:
374
375 gfx::Rect ToplevelFrameView::GetBoundsForClientView() const {
376 return client_view_bounds_;
377 }
378
379 gfx::Rect ToplevelFrameView::GetWindowBoundsForClientBounds(
380 const gfx::Rect& client_bounds) const {
381 gfx::Rect window_bounds = client_bounds;
382 window_bounds.Inset(-NonClientBorderThickness(),
383 -NonClientTopBorderHeight(),
384 -NonClientBorderThickness(),
385 -NonClientBorderThickness());
386 return window_bounds;
387 }
388
389 int ToplevelFrameView::NonClientHitTest(const gfx::Point& point) {
390 current_hittest_code_ = NonClientHitTestImpl(point);
391 return current_hittest_code_;
392 }
393
394 void ToplevelFrameView::GetWindowMask(const gfx::Size& size,
395 gfx::Path* window_mask) {
396 // Nothing.
397 }
398
399 void ToplevelFrameView::ResetWindowControls() {
400 NOTIMPLEMENTED();
401 }
402
403 void ToplevelFrameView::UpdateWindowIcon() {
404 NOTIMPLEMENTED();
405 }
406
407 ////////////////////////////////////////////////////////////////////////////////
408 // ToplevelFrameView, views::View overrides:
409
410 void ToplevelFrameView::Layout() {
411 client_view_bounds_ = GetLocalBounds();
412 client_view_bounds_.Inset(NonClientBorderThickness(),
413 NonClientTopBorderHeight(),
414 NonClientBorderThickness(),
415 NonClientBorderThickness());
416
417 caption_->SetBounds(NonClientBorderThickness(), 0,
418 width() - 2 * NonClientBorderThickness(),
419 NonClientTopBorderHeight());
420
421 left_edge_->Configure(GetHiddenBoundsForSizingBorder(HTLEFT),
422 GetVisibleBoundsForSizingBorder(HTLEFT));
423 right_edge_->Configure(GetHiddenBoundsForSizingBorder(HTRIGHT),
424 GetVisibleBoundsForSizingBorder(HTRIGHT));
425 bottom_edge_->Configure(GetHiddenBoundsForSizingBorder(HTBOTTOM),
426 GetVisibleBoundsForSizingBorder(HTBOTTOM));
427 }
428
429 void ToplevelFrameView::OnMouseMoved(const views::MouseEvent& event) {
430 switch (current_hittest_code_) {
431 case HTLEFT:
432 ShowFrameComponent(left_edge_);
433 break;
434 case HTRIGHT:
435 ShowFrameComponent(right_edge_);
436 break;
437 case HTBOTTOM:
438 ShowFrameComponent(bottom_edge_);
439 break;
440 case HTCAPTION:
441 ShowFrameComponent(caption_);
442 break;
443 default:
444 break;
445 }
446 }
447
448 void ToplevelFrameView::OnMouseExited(const views::MouseEvent& event) {
449 ShowFrameComponent(NULL);
450 }
451
452 views::View* ToplevelFrameView::GetEventHandlerForPoint(
453 const gfx::Point& point) {
454 if (left_edge_->IgnoreEventsForPoint(point) ||
455 right_edge_->IgnoreEventsForPoint(point) ||
456 bottom_edge_->IgnoreEventsForPoint(point) ||
457 caption_->IgnoreEventsForPoint(point)) {
458 return this;
459 }
460 return View::GetEventHandlerForPoint(point);
461 }
462
463 gfx::NativeCursor ToplevelFrameView::GetCursor(const views::MouseEvent& event) {
464 switch (current_hittest_code_) {
465 case HTBOTTOM:
466 return aura::kCursorSouthResize;
467 case HTBOTTOMLEFT:
468 return aura::kCursorSouthWestResize;
469 case HTBOTTOMRIGHT:
470 return aura::kCursorSouthEastResize;
471 case HTLEFT:
472 return aura::kCursorWestResize;
473 case HTRIGHT:
474 return aura::kCursorEastResize;
475 case HTTOP:
476 return aura::kCursorNorthResize;
477 case HTTOPLEFT:
478 return aura::kCursorNorthWestResize;
479 case HTTOPRIGHT:
480 return aura::kCursorNorthEastResize;
481 default:
482 return aura::kCursorNull;
483 }
484 }
485
486 } // namespace internal
487 } // namespace aura_shell
OLDNEW
« no previous file with comments | « ui/aura_shell/toplevel_frame_view.h ('k') | ui/aura_shell/toplevel_layout_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698