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

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

Powered by Google App Engine
This is Rietveld 408576698