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

Side by Side Diff: ash/wm/maximize_bubble_controller.cc

Issue 10823025: Adding new maximize menu according to spec (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixed problem with full screen applications Created 8 years, 4 months 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
OLDNEW
(Empty)
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.
4
5 #include "ash/wm/maximize_bubble_controller.h"
6
7 #include "ash/shell.h"
8 #include "ash/shell_window_ids.h"
9 #include "ash/wm/window_animations.h"
10 #include "ash/wm/workspace/frame_maximize_button.h"
11 #include "base/bind.h"
msw 2012/08/04 01:21:30 nit: is this include necessary?
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
12 #include "base/message_loop.h"
msw 2012/08/04 01:21:30 nit: is this include necessary?
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
13 #include "base/timer.h"
14 #include "grit/ash_strings.h"
15 #include "grit/ui_resources.h"
16 #include "ui/aura/event.h"
17 #include "ui/aura/focus_manager.h"
18 #include "ui/aura/window.h"
19 #include "ui/base/l10n/l10n_util.h"
20 #include "ui/base/resource/resource_bundle.h"
21 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/screen.h"
23 #include "ui/views/bubble/bubble_delegate.h"
24 #include "ui/views/bubble/bubble_frame_view.h"
25 #include "ui/views/controls/button/button.h"
26 #include "ui/views/controls/button/image_button.h"
27 #include "ui/views/controls/label.h"
28 #include "ui/views/events/event.h"
29 #include "ui/views/layout/box_layout.h"
30 #include "ui/views/mouse_watcher.h"
31 #include "ui/views/widget/widget.h"
32
33 namespace {
34
35 // The spacing between two buttons.
36 const int kLayoutSpacing = -1;
37
38 // The background color
msw 2012/08/04 01:21:30 nit: period or remove comment (name is self-explan
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
39 const SkColor kBubbleBackgroundColor = 0xc8141414;
40
41 // The text color within the bubble
msw 2012/08/04 01:21:30 nit: period or remove comment (name is self-explan
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
42 const SkColor kBubbleTextColor = SK_ColorWHITE;
43
44 // The line width of the bubble.
45 const int kLineWidth = 1;
46
47 // The pixel dimensions of the arrow.
48 const int kArrowHeight = 10;
49 const int kArrowWidth = 20;
50
51 // The delay of the bubble appearance.
52 const int kBubbleAppearanceDelayMS = 200;
53 const int kAnimationDurationForPopupMS = 200;
54
55 class MaximizeBubbleBorder : public views::BubbleBorder {
56 public:
57 MaximizeBubbleBorder(views::View* content_view, views::View* anchor);
58
59 virtual ~MaximizeBubbleBorder() {}
60
61 // Overridden from views::BubbleBorder to match the design specs.
62 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
63 const gfx::Size& contents_size) const OVERRIDE;
64
65 // Overridden from views::Border
msw 2012/08/04 01:21:30 nit: period or colon
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
66 virtual void Paint(const views::View& view,
67 gfx::Canvas* canvas) const OVERRIDE;
68 private:
69 views::View* anchor_;
70 views::View* content_view_;
71
72 DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleBorder);
73 };
74
75 MaximizeBubbleBorder::MaximizeBubbleBorder(views::View* content_view,
76 views::View* anchor)
77 : views::BubbleBorder(views::BubbleBorder::TOP_RIGHT,
78 views::BubbleBorder::NO_SHADOW),
79 anchor_(anchor),
80 content_view_(content_view) {
81 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
82 }
83
84 gfx::Rect MaximizeBubbleBorder::GetBounds(
85 const gfx::Rect& position_relative_to,
86 const gfx::Size& contents_size) const {
87 gfx::Size border_size(contents_size);
88 gfx::Insets insets;
89 GetInsets(&insets);
90 border_size.Enlarge(insets.width(), insets.height());
91
92 // Position the bubble to center the box on the anchor.
93 int x = (-border_size.width() + anchor_->width())/2;
msw 2012/08/04 01:21:30 nit: spaces around division '/'
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
94 // Position the bubble under the anchor, overlapping the arrow with it.
95 int y = anchor_->height() - insets.top();
96
97 gfx::Point view_origin(x, y);
98 views::View::ConvertPointToScreen(anchor_, &view_origin);
99
100 return gfx::Rect(view_origin, border_size);
101 }
102
103 void MaximizeBubbleBorder::Paint(const views::View& view,
104 gfx::Canvas* canvas) const {
105 gfx::Insets inset;
106 GetInsets(&inset);
107
108 // Draw the border line around everything.
109 int y = inset.top();
110 // Top
111 canvas->FillRect(gfx::Rect(inset.left(),
112 y - kLineWidth,
113 content_view_->width(),
114 kLineWidth),
115 kBubbleBackgroundColor);
116 // Bottom
117 canvas->FillRect(gfx::Rect(inset.left(),
118 y + content_view_->height(),
119 content_view_->width(),
120 kLineWidth),
121 kBubbleBackgroundColor);
122 // Left
123 canvas->FillRect(gfx::Rect(inset.left() - kLineWidth,
124 y - kLineWidth,
125 kLineWidth,
126 content_view_->height() + 2 * kLineWidth),
127 kBubbleBackgroundColor);
128 // Right
129 canvas->FillRect(gfx::Rect(inset.left() + content_view_->width(),
130 y - kLineWidth,
131 kLineWidth,
132 content_view_->height() + 2 * kLineWidth),
133 kBubbleBackgroundColor);
134
135 // Draw the arrow afterwards covering the border.
136 SkPath path;
137 path.incReserve(4);
138 // The center of the tip should be in the middle of the button.
139 int tip_x = inset.left() + content_view_->width() / 2;
140 int left_base_x = tip_x - kArrowWidth / 2;
141 int left_base_y = y;
142 int tip_y = left_base_y - kArrowHeight;
143 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y));
144 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y));
145 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth),
146 SkIntToScalar(left_base_y));
147
148 SkPaint paint;
149 paint.setStyle(SkPaint::kFill_Style);
150 paint.setColor(kBubbleBackgroundColor);
151 canvas->DrawPath(path, paint);
152 }
153
154 } // namespace
155
156 namespace ash {
157
158 class BubbleContentsButtonRow;
159 class BubbleContentsView;
160 class BubbleDialogButton;
161
162 // The mouse watcher host which makes sure that the bubble does not get closed
163 // while the mouse cursor is over the maximize button or the balloon content.
164 // Note: This object gets destroyed when the MouseWatcher gets destroyed.
165 class BubbleMouseWatcherHost: public views::MouseWatcherHost {
166 public:
167 explicit BubbleMouseWatcherHost(MaximizeBubbleController::Bubble* bubble)
168 : bubble_(bubble) {}
169 virtual ~BubbleMouseWatcherHost() {}
170
171 // Implementation of MouseWatcherHost.
172 virtual bool Contains(const gfx::Point& screen_point,
173 views::MouseWatcherHost::MouseEventType type);
174 private:
175 MaximizeBubbleController::Bubble* bubble_;
176
177 DISALLOW_COPY_AND_ASSIGN(BubbleMouseWatcherHost);
178 };
179
180 // The class which creates and manages the bubble menu element.
181 // It creates a 'bubble border' and the content accordingly.
182 // Note: Since the SnapSizer will show animations on top of the maximize button
183 // this menu gets created as a separate window and the SnapSizer will be
184 // created underneath this window.
185 class MaximizeBubbleController::Bubble : public views::BubbleDelegateView,
186 public views::MouseWatcherListener {
187 public:
188 explicit Bubble(MaximizeBubbleController* owner);
189 virtual ~Bubble() {}
190
191 // The window of the menu under which the SnapSizer will get created.
192 aura::Window* GetBubbleWindow();
193
194 // Overridden from views::BubbleDelegateView.
195 virtual gfx::Rect GetAnchorRect() OVERRIDE;
196
197 // Implementation of MouseWatcherListener.
198 virtual void MouseMovedOutOfHost();
199
200 // Implementation of MouseWatcherHost.
201 virtual bool Contains(const gfx::Point& screen_point,
202 views::MouseWatcherHost::MouseEventType type);
203
204 // Overridden from views::View.
205 virtual gfx::Size GetPreferredSize() OVERRIDE;
206
207 // Overridden from views::Widget::Observer.
208 virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE;
209
210 // Called from the controller class to indicate that the menu should get
211 // destroyed.
212 virtual void ControllerRequestsCloseAndDelete();
213
214 // Called from the owning class to change the menu content to the given
215 // |snap_type| so that the user knows what is selected.
216 void SetSnapType(SnapType snap_type);
217
218 // Get the owning MaximizeBubbleController. This might return NULL in case
219 // of an asynchronous shutdown.
220 MaximizeBubbleController* controller() const { return owner_; }
221
222 private:
223 // True if the shut down has been initiated.
224 bool shutting_down_;
225
226 // Our owning class.
227 MaximizeBubbleController* owner_;
228
229 // The widget which contains our menu and the bubble border.
230 views::Widget* bubble_widget_;
231
232 // The content accessor of the menu.
233 BubbleContentsView* contents_view_;
234
235 // The mouse watcher which takes care of out of window hover events.
236 scoped_ptr<views::MouseWatcher> mouse_watcher_;
237
238 DISALLOW_COPY_AND_ASSIGN(Bubble);
239 };
240
241 // A class that creates all buttons and put them into a view.
242 class BubbleContentsButtonRow
243 : public views::View,
msw 2012/08/04 01:21:30 nit: move to the line above.
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
244 public views::ButtonListener {
245 public:
246 explicit BubbleContentsButtonRow(MaximizeBubbleController::Bubble* bubble);
247
248 virtual ~BubbleContentsButtonRow() {}
249
250 // Overridden from ButtonListener.
251 virtual void ButtonPressed(views::Button* sender,
252 const views::Event& event) OVERRIDE;
253 // Called from BubbleDialogButton.
254 void ButtonHovered(BubbleDialogButton* sender);
255
256 private:
257 // The owning object which gets notifications.
258 MaximizeBubbleController::Bubble* bubble_;
259
260 // The created buttons for our menu.
261 BubbleDialogButton* left_button_;
262 BubbleDialogButton* minimize_button_;
263 BubbleDialogButton* right_button_;
264
265 DISALLOW_COPY_AND_ASSIGN(BubbleContentsButtonRow);
266 };
267
268 // A class which creates the content of the bubble: The buttons, and the label.
269 class BubbleContentsView : public views::View {
270 public:
271 explicit BubbleContentsView(MaximizeBubbleController::Bubble* bubble);
272
273 virtual ~BubbleContentsView() {}
274
275 // Set the label content to reflect the currently selected |snap_type|.
276 // This function can be executed through the frame maximize button as well as
277 // through hover operations.
278 void SetSnapType(SnapType snap_type);
279
280 private:
281 // The owning class.
282 MaximizeBubbleController::Bubble* bubble_;
283
284 // The object which owns all the buttons.
285 BubbleContentsButtonRow* buttons_view_;
286
287 // The label object which shows the user the selected action.
288 views::Label* label_view_;
289
290 DISALLOW_COPY_AND_ASSIGN(BubbleContentsView);
291 };
292
293 // The image button gets overridden to be able to capture mouse hover events.
294 // The constructor also assigns all button states and
295 class BubbleDialogButton : public views::ImageButton {
296 public:
297 explicit BubbleDialogButton(
298 BubbleContentsButtonRow* button_row_listener,
299 int normal_image,
300 int hovered_image,
301 int pressed_image);
302 virtual ~BubbleDialogButton() {}
303
304 // CustomButton overrides:
305 virtual void OnMouseCaptureLost() OVERRIDE;
306 virtual void OnMouseEntered(const views::MouseEvent& event) OVERRIDE;
307 virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE;
308
309 private:
310 // The creating class which needs to get notified in case of a hover event.
311 BubbleContentsButtonRow* button_row_;
312
313 DISALLOW_COPY_AND_ASSIGN(BubbleDialogButton);
314 };
315
316 MaximizeBubbleController::Bubble::Bubble(MaximizeBubbleController* owner)
317 : views::BubbleDelegateView(owner->frame_maximize_button(),
318 views::BubbleBorder::TOP_RIGHT),
319 shutting_down_(false),
320 owner_(owner),
321 bubble_widget_(NULL),
322 contents_view_(NULL) {
323 set_margins(gfx::Insets());
324
325 // The window needs to be owned by the root so that the SnapSizer does not
326 // cover it upon animation.
327 aura::Window* parent = Shell::GetContainer(
328 Shell::GetActiveRootWindow(),
329 internal::kShellWindowId_LauncherContainer);
330 set_parent_window(parent);
331
332 set_notify_enter_exit_on_child(true);
333 set_try_mirroring_arrow(false);
334 SetPaintToLayer(true);
335 SetFillsBoundsOpaquely(false);
336 set_color(kBubbleBackgroundColor);
337 set_close_on_deactivate(false);
338 set_background(
339 views::Background::CreateSolidBackground(kBubbleBackgroundColor));
340
341 SetLayoutManager(new views::BoxLayout(
342 views::BoxLayout::kVertical, 0, 0, kLayoutSpacing));
343
344 contents_view_ = new BubbleContentsView(this);
345 AddChildView(contents_view_);
346
347 // Note that the returned widget has an observer which points to our
348 // functions.
349 bubble_widget_ = views::BubbleDelegateView::CreateBubble(this);
350
351 SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
352 bubble_widget_->non_client_view()->frame_view()->set_background(NULL);
353
354 MaximizeBubbleBorder* bubble_border = new MaximizeBubbleBorder(
355 this,
356 anchor_view());
357 GetBubbleFrameView()->SetBubbleBorder(bubble_border);
358 GetBubbleFrameView()->set_background(NULL);
359
360 // Recalculate size with new border.
361 SizeToContents();
362
363 // Setup animation.
364 ash::SetWindowVisibilityAnimationType(
365 bubble_widget_->GetNativeWindow(),
366 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
367 ash::SetWindowVisibilityAnimationTransition(
368 bubble_widget_->GetNativeWindow(),
369 ash::ANIMATE_BOTH);
370 ash::SetWindowVisibilityAnimationDuration(
371 bubble_widget_->GetNativeWindow(),
372 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS));
373
374 Show();
375 // We don't want to lose the focus on our parent window because the button
376 // would otherwise lose the highlight when the "helper bubble" is shown.
377 views::Widget* widget =
378 owner_->frame_maximize_button()->parent()->GetWidget();
379 if (widget) {
380 aura::Window* parent_window = widget->GetNativeWindow();
381 parent_window->GetFocusManager()->SetFocusedWindow(parent_window, NULL);
382 }
383 mouse_watcher_.reset(new views::MouseWatcher(
384 new BubbleMouseWatcherHost(this),
385 this));
386 mouse_watcher_->Start();
387 }
388
389 bool BubbleMouseWatcherHost::Contains(
390 const gfx::Point& screen_point,
391 views::MouseWatcherHost::MouseEventType type) {
392 return bubble_->Contains(screen_point, type);
393 }
394
395 aura::Window* MaximizeBubbleController::Bubble::GetBubbleWindow() {
396 return bubble_widget_ ? bubble_widget_->GetNativeWindow() : NULL;
397 }
398
399 gfx::Rect MaximizeBubbleController::Bubble::GetAnchorRect() {
400 if (!owner_)
401 return gfx::Rect();
402
403 gfx::Rect anchor_rect =
404 owner_->frame_maximize_button()->GetBoundsInScreen();
405 return anchor_rect;
406 }
407
408 void MaximizeBubbleController::Bubble::MouseMovedOutOfHost() {
409 if (!owner_ || shutting_down_)
410 return;
411 // When we leave the bubble, we might be still be in gesture mode or over
412 // the maximize button. So only close if none of the other cases apply.
413 if (!owner_->frame_maximize_button()->is_snap_enabled()) {
414 gfx::Point screen_location = gfx::Screen::GetCursorScreenPoint();
415 if (!owner_->frame_maximize_button()->GetBoundsInScreen().Contains(
416 screen_location)) {
417 owner_->RequestDestructionThroughOwner();
418 }
419 }
420 }
421
422 bool MaximizeBubbleController::Bubble::Contains(
423 const gfx::Point& screen_point,
424 views::MouseWatcherHost::MouseEventType type) {
425 if (!owner_ || shutting_down_)
426 return false;
427 // Check if either a gesture is taking place (=> bubble stays no matter what
428 // the mouse does) or the mouse is over the maximize button or the bubble
429 // content.
430 return (owner_->frame_maximize_button()->is_snap_enabled() ||
431 owner_->frame_maximize_button()->GetBoundsInScreen().Contains(
432 screen_point) ||
433 contents_view_->GetBoundsInScreen().Contains(screen_point));
434 }
435
436 gfx::Size MaximizeBubbleController::Bubble::GetPreferredSize() {
437 return contents_view_->GetPreferredSize();
438 }
439
440 void MaximizeBubbleController::Bubble::OnWidgetClosing(views::Widget* widget) {
441 if (bubble_widget_ != widget)
442 return;
443
444 mouse_watcher_->Stop();
445
446 if (owner_) {
447 // If the bubble destruction was triggered by some other external influence
448 // then ourselves, the owner needs to be informed that the menu is gone.
449 shutting_down_ = true;
450 owner_->RequestDestructionThroughOwner();
451 owner_ = NULL;
452 }
453 // Remove any existing observers.
454 bubble_widget_->RemoveObserver(this);
455 anchor_widget()->RemoveObserver(this);
456 }
457
458 void MaximizeBubbleController::Bubble::ControllerRequestsCloseAndDelete() {
459 // This only gets called from the owning base class once it is deleted.
460 if (shutting_down_)
461 return;
462 shutting_down_ = true;
463 owner_ = NULL;
464
465 // Close the widget asynchronously.
466 bubble_widget_->Close();
467 }
468
469 void MaximizeBubbleController::Bubble::SetSnapType(SnapType snap_type) {
470 if (contents_view_)
471 contents_view_->SetSnapType(snap_type);
472 }
473
474 BubbleContentsButtonRow::BubbleContentsButtonRow(
475 MaximizeBubbleController::Bubble* bubble)
476 : bubble_(bubble),
477 left_button_(NULL),
478 minimize_button_(NULL),
479 right_button_(NULL) {
480 SetLayoutManager(new views::BoxLayout(
481 views::BoxLayout::kHorizontal, 0, 0, kLayoutSpacing));
482 set_background(
483 views::Background::CreateSolidBackground(kBubbleBackgroundColor));
484
485 left_button_ = new BubbleDialogButton(
486 this,
487 IDR_AURA_WINDOW_POSITION_LEFT,
488 IDR_AURA_WINDOW_POSITION_LEFT_H,
489 IDR_AURA_WINDOW_POSITION_LEFT_P);
490 minimize_button_ = new BubbleDialogButton(
491 this,
492 IDR_AURA_WINDOW_POSITION_MIDDLE,
493 IDR_AURA_WINDOW_POSITION_MIDDLE_H,
494 IDR_AURA_WINDOW_POSITION_MIDDLE_P);
495 right_button_ = new BubbleDialogButton(
496 this,
497 IDR_AURA_WINDOW_POSITION_RIGHT,
498 IDR_AURA_WINDOW_POSITION_RIGHT_H,
499 IDR_AURA_WINDOW_POSITION_RIGHT_P);
500 }
501
502 // Overridden from ButtonListener.
503 void BubbleContentsButtonRow::ButtonPressed(views::Button* sender,
504 const views::Event& event) {
505 // While shutting down, the connection to the owner might already be
506 // broken.
msw 2012/08/04 01:21:30 nit: fits on line above.
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
507 if (!bubble_->controller())
508 return;
509 if (sender == left_button_)
510 bubble_->controller()->OnButtonClicked(SNAP_LEFT);
511 else if (sender == minimize_button_)
512 bubble_->controller()->OnButtonClicked(SNAP_MINIMIZE);
513 else if (sender == right_button_)
514 bubble_->controller()->OnButtonClicked(SNAP_RIGHT);
515 else {
msw 2012/08/04 01:21:30 nit: remove {} to be consistent with the other blo
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
516 NOTREACHED() << "Unknown button pressed.";
517 }
518 }
519
520 // Called from BubbleDialogButton.
521 void BubbleContentsButtonRow::ButtonHovered(BubbleDialogButton* sender) {
522 // While shutting down, the connection to the owner might already be
523 // broken.
msw 2012/08/04 01:21:30 nit: fits on line above.
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
524 if (!bubble_->controller())
525 return;
526 if (sender == left_button_)
527 bubble_->controller()->OnButtonHover(SNAP_LEFT);
528 else if (sender == minimize_button_)
529 bubble_->controller()->OnButtonHover(SNAP_MINIMIZE);
530 else if (sender == right_button_)
531 bubble_->controller()->OnButtonHover(SNAP_RIGHT);
532 else
533 bubble_->controller()->OnButtonHover(SNAP_NONE);
534 }
535
536 BubbleContentsView::BubbleContentsView(
537 MaximizeBubbleController::Bubble* bubble)
538 : bubble_(bubble),
539 buttons_view_(NULL),
540 label_view_(NULL) {
541 SetLayoutManager(new views::BoxLayout(
542 views::BoxLayout::kVertical, 0, 0, kLayoutSpacing));
543 set_background(
544 views::Background::CreateSolidBackground(kBubbleBackgroundColor));
545
546 buttons_view_ = new BubbleContentsButtonRow(bubble);
547 AddChildView(buttons_view_);
548
549 label_view_ = new views::Label();
550 SetSnapType(SNAP_NONE);
551 label_view_->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
552 label_view_->SetBackgroundColor(kBubbleBackgroundColor);
553 label_view_->SetEnabledColor(kBubbleTextColor);
554 AddChildView(label_view_);
555 }
556
557 // Set the label content to reflect the currently selected |snap_type|.
558 // This function can be executed through the frame maximize button as well as
559 // through hover operations.
560 void BubbleContentsView::SetSnapType(SnapType snap_type) {
561 if (!bubble_->controller())
562 return;
563
564 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
565 switch (snap_type) {
566 case SNAP_LEFT:
567 label_view_->SetText(rb.GetLocalizedString(IDS_ASH_SNAP_WINDOW_LEFT));
msw 2012/08/04 01:21:30 Consider setting a local int string_id = ... for e
Mr4D (OOO till 08-26) 2012/08/04 02:56:22 Done.
568 return;
569 case SNAP_RIGHT:
570 label_view_->SetText(rb.GetLocalizedString(IDS_ASH_SNAP_WINDOW_RIGHT));
571 return;
572 case SNAP_MAXIMIZE:
573 DCHECK(!bubble_->controller()->is_maximized());
574 label_view_->SetText(rb.GetLocalizedString(IDS_ASH_MAXIMIZE_WINDOW));
575 return;
576 case SNAP_MINIMIZE:
577 label_view_->SetText(rb.GetLocalizedString(IDS_ASH_MINIMIZE_WINDOW));
578 return;
579 case SNAP_RESTORE:
580 DCHECK(bubble_->controller()->is_maximized());
581 label_view_->SetText(rb.GetLocalizedString(IDS_ASH_RESTORE_WINDOW));
582 return;
583 default:
584 // If nothing is selected, we automatically select the click operation.
585 label_view_->SetText(rb.GetLocalizedString(
586 bubble_->controller()->is_maximized() ? IDS_ASH_RESTORE_WINDOW :
587 IDS_ASH_MAXIMIZE_WINDOW));
588 return;
589 }
590 }
591
592 MaximizeBubbleController::MaximizeBubbleController(
593 FrameMaximizeButton* frame_maximize_button,
594 bool is_maximized)
595 : frame_maximize_button_(frame_maximize_button),
596 bubble_(NULL),
597 is_maximized_(is_maximized) {
598 // Create the task which will create the bubble delayed.
599 base::OneShotTimer<MaximizeBubbleController>* new_timer =
600 new base::OneShotTimer<MaximizeBubbleController>();
601 new_timer->Start(
602 FROM_HERE,
603 base::TimeDelta::FromMilliseconds(kBubbleAppearanceDelayMS),
604 this,
605 &MaximizeBubbleController::CreateBubble);
606 timer_.reset(new_timer);
607 }
608
609 MaximizeBubbleController::~MaximizeBubbleController() {
610 // Note: The destructor only gets initiated through the owner.
611 timer_.reset();
612 if (bubble_) {
613 bubble_->ControllerRequestsCloseAndDelete();
614 bubble_ = NULL;
615 }
616 }
617
618 void MaximizeBubbleController::SetSnapType(SnapType snap_type) {
619 if (bubble_)
620 bubble_->SetSnapType(snap_type);
621 }
622
623 aura::Window* MaximizeBubbleController::GetBubbleWindow() {
624 return bubble_ ? bubble_->GetBubbleWindow() : NULL;
625 }
626
627 void MaximizeBubbleController::DelayCreation() {
628 if (timer_.get() && timer_->IsRunning())
629 timer_->Reset();
630 }
631
632 void MaximizeBubbleController::OnButtonClicked(SnapType snap_type) {
633 frame_maximize_button_->ExecuteSnapAndCloseMenu(snap_type);
634 }
635
636 void MaximizeBubbleController::OnButtonHover(SnapType snap_type) {
637 frame_maximize_button_->SnapButtonHovered(snap_type);
638 }
639
640 void MaximizeBubbleController::RequestDestructionThroughOwner() {
641 // Tell the parent to destroy us (if this didn't happen yet).
642 if (timer_.get()) {
643 timer_.reset(NULL);
644 // Informs the owner that the menu is gone and requests |this| destruction.
645 frame_maximize_button_->DestroyMaximizeMenu();
646 // Note: After this call |this| is destroyed.
647 }
648 }
649
650 void MaximizeBubbleController::CreateBubble() {
651 if (!bubble_)
652 bubble_ = new Bubble(this);
653
654 timer_->Stop();
655 }
656
657 BubbleDialogButton::BubbleDialogButton(
658 BubbleContentsButtonRow* button_row,
659 int normal_image,
660 int hovered_image,
661 int pressed_image)
662 : views::ImageButton(button_row),
663 button_row_(button_row) {
664 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
665 SetImage(views::CustomButton::BS_NORMAL, rb.GetImageSkiaNamed(normal_image));
666 SetImage(views::CustomButton::BS_HOT, rb.GetImageSkiaNamed(hovered_image));
667 SetImage(views::CustomButton::BS_PUSHED,
668 rb.GetImageSkiaNamed(pressed_image));
669 button_row->AddChildView(this);
670 }
671
672 void BubbleDialogButton::OnMouseCaptureLost() {
673 button_row_->ButtonHovered(NULL);
674 views::ImageButton::OnMouseCaptureLost();
675 }
676
677 void BubbleDialogButton::OnMouseEntered(const views::MouseEvent& event) {
678 button_row_->ButtonHovered(this);
679 views::ImageButton::OnMouseEntered(event);
680 }
681
682 void BubbleDialogButton::OnMouseExited(const views::MouseEvent& event) {
683 button_row_->ButtonHovered(NULL);
684 views::ImageButton::OnMouseExited(event);
685 }
686
687 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698