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

Side by Side Diff: ash/frame/caption_buttons/frame_caption_button_container_view.cc

Issue 2215223003: Moves most frame related classes to ash/common/frame (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comment Created 4 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 2013 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/frame/caption_buttons/frame_caption_button_container_view.h"
6
7 #include <cmath>
8 #include <map>
9
10 #include "ash/common/ash_switches.h"
11 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
12 #include "ash/common/wm_shell.h"
13 #include "ash/frame/caption_buttons/frame_caption_button.h"
14 #include "ash/frame/caption_buttons/frame_size_button.h"
15 #include "ash/shell.h"
16 #include "ui/base/hit_test.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
19 #include "ui/gfx/animation/slide_animation.h"
20 #include "ui/gfx/animation/tween.h"
21 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/geometry/insets.h"
23 #include "ui/gfx/geometry/point.h"
24 #include "ui/gfx/vector_icons_public.h"
25 #include "ui/strings/grit/ui_strings.h" // Accessibility names
26 #include "ui/views/widget/widget.h"
27 #include "ui/views/widget/widget_delegate.h"
28
29 namespace ash {
30
31 namespace {
32
33 // Duration of the animation of the position of |minimize_button_|.
34 const int kPositionAnimationDurationMs = 500;
35
36 // Duration of the animation of the alpha of |size_button_|.
37 const int kAlphaAnimationDurationMs = 250;
38
39 // Delay during |maximize_mode_animation_| hide to wait before beginning to
40 // animate the position of |minimize_button_|.
41 const int kHidePositionDelayMs = 100;
42
43 // Duration of |maximize_mode_animation_| hiding.
44 // Hiding size button 250
45 // |------------------------|
46 // Delay 100 Slide minimize button 500
47 // |---------|-------------------------------------------------|
48 const int kHideAnimationDurationMs =
49 kHidePositionDelayMs + kPositionAnimationDurationMs;
50
51 // Delay during |maximize_mode_animation_| show to wait before beginning to
52 // animate the alpha of |size_button_|.
53 const int kShowAnimationAlphaDelayMs = 100;
54
55 // Duration of |maximize_mode_animation_| showing.
56 // Slide minimize button 500
57 // |-------------------------------------------------|
58 // Delay 100 Show size button 250
59 // |---------|-----------------------|
60 const int kShowAnimationDurationMs = kPositionAnimationDurationMs;
61
62 // Value of |maximize_mode_animation_| showing to begin animating alpha of
63 // |size_button_|.
64 float SizeButtonShowStartValue() {
65 return static_cast<float>(kShowAnimationAlphaDelayMs) /
66 kShowAnimationDurationMs;
67 }
68
69 // Amount of |maximize_mode_animation_| showing to animate the alpha of
70 // |size_button_|.
71 float SizeButtonShowDuration() {
72 return static_cast<float>(kAlphaAnimationDurationMs) /
73 kShowAnimationDurationMs;
74 }
75
76 // Amount of |maximize_mode_animation_| hiding to animate the alpha of
77 // |size_button_|.
78 float SizeButtonHideDuration() {
79 return static_cast<float>(kAlphaAnimationDurationMs) /
80 kHideAnimationDurationMs;
81 }
82
83 // Value of |maximize_mode_animation_| hiding to begin animating the position of
84 // |minimize_button_|.
85 float HidePositionStartValue() {
86 return 1.0f -
87 static_cast<float>(kHidePositionDelayMs) / kHideAnimationDurationMs;
88 }
89
90 // Converts |point| from |src| to |dst| and hittests against |dst|.
91 bool ConvertPointToViewAndHitTest(const views::View* src,
92 const views::View* dst,
93 const gfx::Point& point) {
94 gfx::Point converted(point);
95 views::View::ConvertPointToTarget(src, dst, &converted);
96 return dst->HitTestPoint(converted);
97 }
98
99 // Bounds animation values to the range 0.0 - 1.0. Allows for mapping of offset
100 // animations to the expected range so that gfx::Tween::CalculateValue() can be
101 // used.
102 double CapAnimationValue(double value) {
103 return std::min(1.0, std::max(0.0, value));
104 }
105
106 } // namespace
107
108 // static
109 const char FrameCaptionButtonContainerView::kViewClassName[] =
110 "FrameCaptionButtonContainerView";
111
112 FrameCaptionButtonContainerView::FrameCaptionButtonContainerView(
113 views::Widget* frame)
114 : frame_(frame),
115 minimize_button_(NULL),
116 size_button_(NULL),
117 close_button_(NULL) {
118 bool size_button_visibility = ShouldSizeButtonBeVisible();
119 maximize_mode_animation_.reset(new gfx::SlideAnimation(this));
120 maximize_mode_animation_->SetTweenType(gfx::Tween::LINEAR);
121
122 // Ensure animation tracks visibility of size button.
123 if (size_button_visibility)
124 maximize_mode_animation_->Reset(1.0f);
125
126 // Insert the buttons left to right.
127 minimize_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_MINIMIZE);
128 minimize_button_->SetAccessibleName(
129 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE));
130 minimize_button_->SetVisible(frame_->widget_delegate()->CanMinimize());
131 AddChildView(minimize_button_);
132
133 size_button_ = new FrameSizeButton(this, frame, this);
134 size_button_->SetAccessibleName(
135 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE));
136 size_button_->SetVisible(size_button_visibility);
137 AddChildView(size_button_);
138
139 close_button_ = new FrameCaptionButton(this, CAPTION_BUTTON_ICON_CLOSE);
140 close_button_->SetAccessibleName(
141 l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
142 AddChildView(close_button_);
143 }
144
145 FrameCaptionButtonContainerView::~FrameCaptionButtonContainerView() {}
146
147 void FrameCaptionButtonContainerView::TestApi::EndAnimations() {
148 container_view_->maximize_mode_animation_->End();
149 }
150
151 void FrameCaptionButtonContainerView::SetButtonImage(
152 CaptionButtonIcon icon,
153 gfx::VectorIconId icon_image_id) {
154 button_icon_id_map_[icon] = icon_image_id;
155
156 FrameCaptionButton* buttons[] = {minimize_button_, size_button_,
157 close_button_};
158 for (size_t i = 0; i < arraysize(buttons); ++i) {
159 if (buttons[i]->icon() == icon)
160 buttons[i]->SetImage(icon, FrameCaptionButton::ANIMATE_NO, icon_image_id);
161 }
162 }
163
164 void FrameCaptionButtonContainerView::SetPaintAsActive(bool paint_as_active) {
165 minimize_button_->set_paint_as_active(paint_as_active);
166 size_button_->set_paint_as_active(paint_as_active);
167 close_button_->set_paint_as_active(paint_as_active);
168 }
169
170 void FrameCaptionButtonContainerView::SetUseLightImages(bool light) {
171 minimize_button_->set_use_light_images(light);
172 size_button_->set_use_light_images(light);
173 close_button_->set_use_light_images(light);
174 }
175
176 void FrameCaptionButtonContainerView::ResetWindowControls() {
177 SetButtonsToNormal(ANIMATE_NO);
178 }
179
180 int FrameCaptionButtonContainerView::NonClientHitTest(
181 const gfx::Point& point) const {
182 if (close_button_->visible() &&
183 ConvertPointToViewAndHitTest(this, close_button_, point)) {
184 return HTCLOSE;
185 } else if (size_button_->visible() &&
186 ConvertPointToViewAndHitTest(this, size_button_, point)) {
187 return HTMAXBUTTON;
188 } else if (minimize_button_->visible() &&
189 ConvertPointToViewAndHitTest(this, minimize_button_, point)) {
190 return HTMINBUTTON;
191 }
192 return HTNOWHERE;
193 }
194
195 void FrameCaptionButtonContainerView::UpdateSizeButtonVisibility() {
196 bool visible = ShouldSizeButtonBeVisible();
197 if (visible) {
198 size_button_->SetVisible(true);
199 maximize_mode_animation_->SetSlideDuration(kShowAnimationDurationMs);
200 maximize_mode_animation_->Show();
201 } else {
202 maximize_mode_animation_->SetSlideDuration(kHideAnimationDurationMs);
203 maximize_mode_animation_->Hide();
204 }
205 }
206
207 void FrameCaptionButtonContainerView::SetButtonSize(const gfx::Size& size) {
208 minimize_button_->set_size(size);
209 size_button_->set_size(size);
210 close_button_->set_size(size);
211 }
212
213 gfx::Size FrameCaptionButtonContainerView::GetPreferredSize() const {
214 int width = 0;
215 for (int i = 0; i < child_count(); ++i) {
216 const views::View* child = child_at(i);
217 if (child->visible())
218 width += child_at(i)->GetPreferredSize().width();
219 }
220 return gfx::Size(width, close_button_->GetPreferredSize().height());
221 }
222
223 void FrameCaptionButtonContainerView::Layout() {
224 int x = 0;
225 for (int i = 0; i < child_count(); ++i) {
226 views::View* child = child_at(i);
227 if (!child->visible())
228 continue;
229
230 gfx::Size size = child->GetPreferredSize();
231 child->SetBounds(x, 0, size.width(), size.height());
232 x += size.width();
233 }
234 if (maximize_mode_animation_->is_animating()) {
235 AnimationProgressed(maximize_mode_animation_.get());
236 }
237 }
238
239 const char* FrameCaptionButtonContainerView::GetClassName() const {
240 return kViewClassName;
241 }
242
243 void FrameCaptionButtonContainerView::AnimationEnded(
244 const gfx::Animation* animation) {
245 // Ensure that position is calculated at least once.
246 AnimationProgressed(animation);
247
248 double current_value = maximize_mode_animation_->GetCurrentValue();
249 if (current_value == 0.0) {
250 size_button_->SetVisible(false);
251 PreferredSizeChanged();
252 }
253 }
254
255 void FrameCaptionButtonContainerView::AnimationProgressed(
256 const gfx::Animation* animation) {
257 double current_value = animation->GetCurrentValue();
258 int size_alpha = 0;
259 int minimize_x = 0;
260 if (maximize_mode_animation_->IsShowing()) {
261 double scaled_value =
262 CapAnimationValue((current_value - SizeButtonShowStartValue()) /
263 SizeButtonShowDuration());
264 double tweened_value_alpha =
265 gfx::Tween::CalculateValue(gfx::Tween::EASE_OUT, scaled_value);
266 size_alpha = gfx::Tween::LinearIntValueBetween(tweened_value_alpha, 0, 255);
267
268 double tweened_value_slide =
269 gfx::Tween::CalculateValue(gfx::Tween::EASE_OUT, current_value);
270 minimize_x = gfx::Tween::LinearIntValueBetween(tweened_value_slide,
271 size_button_->x(), 0);
272 } else {
273 double scaled_value_alpha =
274 CapAnimationValue((1.0f - current_value) / SizeButtonHideDuration());
275 double tweened_value_alpha =
276 gfx::Tween::CalculateValue(gfx::Tween::EASE_IN, scaled_value_alpha);
277 size_alpha = gfx::Tween::LinearIntValueBetween(tweened_value_alpha, 255, 0);
278
279 double scaled_value_position = CapAnimationValue(
280 (HidePositionStartValue() - current_value) / HidePositionStartValue());
281 double tweened_value_position =
282 gfx::Tween::CalculateValue(gfx::Tween::EASE_OUT, scaled_value_position);
283 minimize_x = gfx::Tween::LinearIntValueBetween(tweened_value_position, 0,
284 size_button_->x());
285 }
286 size_button_->SetAlpha(size_alpha);
287 minimize_button_->SetX(minimize_x);
288 }
289
290 void FrameCaptionButtonContainerView::SetButtonIcon(FrameCaptionButton* button,
291 CaptionButtonIcon icon,
292 Animate animate) {
293 // The early return is dependant on |animate| because callers use
294 // SetButtonIcon() with ANIMATE_NO to progress |button|'s crossfade animation
295 // to the end.
296 if (button->icon() == icon &&
297 (animate == ANIMATE_YES || !button->IsAnimatingImageSwap())) {
298 return;
299 }
300
301 FrameCaptionButton::Animate fcb_animate =
302 (animate == ANIMATE_YES) ? FrameCaptionButton::ANIMATE_YES
303 : FrameCaptionButton::ANIMATE_NO;
304 auto it = button_icon_id_map_.find(icon);
305 if (it != button_icon_id_map_.end())
306 button->SetImage(icon, fcb_animate, it->second);
307 }
308
309 bool FrameCaptionButtonContainerView::ShouldSizeButtonBeVisible() const {
310 return !WmShell::Get()
311 ->maximize_mode_controller()
312 ->IsMaximizeModeWindowManagerEnabled() &&
313 frame_->widget_delegate()->CanMaximize();
314 }
315
316 void FrameCaptionButtonContainerView::ButtonPressed(views::Button* sender,
317 const ui::Event& event) {
318 // Abort any animations of the button icons.
319 SetButtonsToNormal(ANIMATE_NO);
320
321 UserMetricsAction action = UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE;
322 if (sender == minimize_button_) {
323 frame_->Minimize();
324 } else if (sender == size_button_) {
325 if (frame_->IsFullscreen()) { // Can be clicked in immersive fullscreen.
326 frame_->Restore();
327 action = UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN;
328 } else if (frame_->IsMaximized()) {
329 frame_->Restore();
330 action = UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE;
331 } else {
332 frame_->Maximize();
333 action = UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE;
334 }
335
336 if (event.IsGestureEvent())
337 WmShell::Get()->RecordGestureAction(GESTURE_FRAMEMAXIMIZE_TAP);
338 } else if (sender == close_button_) {
339 frame_->Close();
340 action = UMA_WINDOW_CLOSE_BUTTON_CLICK;
341 } else {
342 return;
343 }
344 WmShell::Get()->RecordUserMetricsAction(action);
345 }
346
347 bool FrameCaptionButtonContainerView::IsMinimizeButtonVisible() const {
348 return minimize_button_->visible();
349 }
350
351 void FrameCaptionButtonContainerView::SetButtonsToNormal(Animate animate) {
352 SetButtonIcons(CAPTION_BUTTON_ICON_MINIMIZE, CAPTION_BUTTON_ICON_CLOSE,
353 animate);
354 minimize_button_->SetState(views::Button::STATE_NORMAL);
355 size_button_->SetState(views::Button::STATE_NORMAL);
356 close_button_->SetState(views::Button::STATE_NORMAL);
357 }
358
359 void FrameCaptionButtonContainerView::SetButtonIcons(
360 CaptionButtonIcon minimize_button_icon,
361 CaptionButtonIcon close_button_icon,
362 Animate animate) {
363 SetButtonIcon(minimize_button_, minimize_button_icon, animate);
364 SetButtonIcon(close_button_, close_button_icon, animate);
365 }
366
367 const FrameCaptionButton* FrameCaptionButtonContainerView::GetButtonClosestTo(
368 const gfx::Point& position_in_screen) const {
369 // Since the buttons all have the same size, the closest button is the button
370 // with the center point closest to |position_in_screen|.
371 // TODO(pkotwicz): Make the caption buttons not overlap.
372 gfx::Point position(position_in_screen);
373 views::View::ConvertPointFromScreen(this, &position);
374
375 FrameCaptionButton* buttons[] = {minimize_button_, size_button_,
376 close_button_};
377 int min_squared_distance = INT_MAX;
378 FrameCaptionButton* closest_button = NULL;
379 for (size_t i = 0; i < arraysize(buttons); ++i) {
380 FrameCaptionButton* button = buttons[i];
381 if (!button->visible())
382 continue;
383
384 gfx::Point center_point = button->GetLocalBounds().CenterPoint();
385 views::View::ConvertPointToTarget(button, this, &center_point);
386 int squared_distance = static_cast<int>(
387 pow(static_cast<double>(position.x() - center_point.x()), 2) +
388 pow(static_cast<double>(position.y() - center_point.y()), 2));
389 if (squared_distance < min_squared_distance) {
390 min_squared_distance = squared_distance;
391 closest_button = button;
392 }
393 }
394 return closest_button;
395 }
396
397 void FrameCaptionButtonContainerView::SetHoveredAndPressedButtons(
398 const FrameCaptionButton* to_hover,
399 const FrameCaptionButton* to_press) {
400 FrameCaptionButton* buttons[] = {minimize_button_, size_button_,
401 close_button_};
402 for (size_t i = 0; i < arraysize(buttons); ++i) {
403 FrameCaptionButton* button = buttons[i];
404 views::Button::ButtonState new_state = views::Button::STATE_NORMAL;
405 if (button == to_hover)
406 new_state = views::Button::STATE_HOVERED;
407 else if (button == to_press)
408 new_state = views::Button::STATE_PRESSED;
409 button->SetState(new_state);
410 }
411 }
412
413 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698