OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/views/status_bubble_views.h" | 5 #include "chrome/browser/ui/views/status_bubble_views.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/i18n/rtl.h" | 10 #include "base/i18n/rtl.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
16 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
18 #include "chrome/browser/themes/theme_properties.h" | 18 #include "chrome/browser/themes/theme_properties.h" |
19 #include "components/url_formatter/elide_url.h" | 19 #include "components/url_formatter/elide_url.h" |
20 #include "components/url_formatter/url_formatter.h" | 20 #include "components/url_formatter/url_formatter.h" |
21 #include "third_party/skia/include/core/SkPaint.h" | 21 #include "third_party/skia/include/core/SkPaint.h" |
22 #include "third_party/skia/include/core/SkRRect.h" | 22 #include "third_party/skia/include/core/SkPath.h" |
23 #include "third_party/skia/include/pathops/SkPathOps.h" | |
23 #include "ui/base/theme_provider.h" | 24 #include "ui/base/theme_provider.h" |
24 #include "ui/display/display.h" | 25 #include "ui/display/display.h" |
25 #include "ui/display/screen.h" | 26 #include "ui/display/screen.h" |
26 #include "ui/gfx/animation/animation_delegate.h" | 27 #include "ui/gfx/animation/animation_delegate.h" |
27 #include "ui/gfx/animation/linear_animation.h" | 28 #include "ui/gfx/animation/linear_animation.h" |
28 #include "ui/gfx/canvas.h" | 29 #include "ui/gfx/canvas.h" |
29 #include "ui/gfx/font_list.h" | 30 #include "ui/gfx/font_list.h" |
30 #include "ui/gfx/geometry/point.h" | 31 #include "ui/gfx/geometry/point.h" |
31 #include "ui/gfx/geometry/rect.h" | 32 #include "ui/gfx/geometry/rect.h" |
32 #include "ui/gfx/skia_util.h" | 33 #include "ui/gfx/skia_util.h" |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 }; | 129 }; |
129 | 130 |
130 enum BubbleStyle { | 131 enum BubbleStyle { |
131 STYLE_BOTTOM, | 132 STYLE_BOTTOM, |
132 STYLE_FLOATING, | 133 STYLE_FLOATING, |
133 STYLE_STANDARD, | 134 STYLE_STANDARD, |
134 STYLE_STANDARD_RIGHT | 135 STYLE_STANDARD_RIGHT |
135 }; | 136 }; |
136 | 137 |
137 StatusView(views::Widget* popup, | 138 StatusView(views::Widget* popup, |
138 const ui::ThemeProvider* theme_provider); | 139 const gfx::Size& popup_size_, |
140 SkColor bubble_color, | |
141 SkColor bubble_text_color, | |
142 bool has_client_edge); | |
139 ~StatusView() override; | 143 ~StatusView() override; |
140 | 144 |
141 // Set the bubble text to a certain value, hides the bubble if text is | 145 // Set the bubble text to a certain value, hides the bubble if text is |
142 // an empty string. Trigger animation sequence to display if | 146 // an empty string. Trigger animation sequence to display if |
143 // |should_animate_open|. | 147 // |should_animate_open|. |
144 void SetText(const base::string16& text, bool should_animate_open); | 148 void SetText(const base::string16& text, bool should_animate_open); |
145 | 149 |
146 BubbleState state() const { return state_; } | 150 BubbleState state() const { return state_; } |
147 BubbleStyle style() const { return style_; } | 151 BubbleStyle style() const { return style_; } |
148 void SetStyle(BubbleStyle style); | 152 void SetStyle(BubbleStyle style); |
149 | 153 |
150 // Show the bubble instantly. | 154 // Show the bubble instantly. |
151 void Show(); | 155 void Show(); |
152 | 156 |
153 // Hide the bubble instantly. | 157 // Hide the bubble instantly. |
154 void Hide(); | 158 void Hide(); |
155 | 159 |
156 // Resets any timers we have. Typically called when the user moves a | 160 // Resets any timers we have. Typically called when the user moves a |
157 // mouse. | 161 // mouse. |
158 void ResetTimer(); | 162 void ResetTimer(); |
159 | 163 |
160 // This call backs the StatusView in order to fade the bubble in and out. | 164 // This call backs the StatusView in order to fade the bubble in and out. |
161 void SetOpacity(float opacity); | 165 void SetOpacity(float opacity); |
162 | 166 |
163 // Depending on the state of the bubble this will either hide the popup or | 167 // Depending on the state of the bubble this will either hide the popup or |
164 // not. | 168 // not. |
165 void OnAnimationEnded(); | 169 void OnAnimationEnded(); |
166 | 170 |
171 void SetWidth(int new_width); | |
172 | |
167 private: | 173 private: |
168 class InitialTimer; | 174 class InitialTimer; |
169 | 175 |
170 // Manage the timers that control the delay before a fade begins or ends. | 176 // Manage the timers that control the delay before a fade begins or ends. |
171 void StartTimer(base::TimeDelta time); | 177 void StartTimer(base::TimeDelta time); |
172 void OnTimer(); | 178 void OnTimer(); |
173 void CancelTimer(); | 179 void CancelTimer(); |
174 void RestartTimer(base::TimeDelta delay); | 180 void RestartTimer(base::TimeDelta delay); |
175 | 181 |
176 // Manage the fades and starting and stopping the animations correctly. | 182 // Manage the fades and starting and stopping the animations correctly. |
177 void StartFade(float start, float end, int duration); | 183 void StartFade(float start, float end, int duration); |
178 void StartHiding(); | 184 void StartHiding(); |
179 void StartShowing(); | 185 void StartShowing(); |
180 | 186 |
181 // views::View: | 187 // views::View: |
182 const char* GetClassName() const override; | 188 const char* GetClassName() const override; |
183 void OnPaint(gfx::Canvas* canvas) override; | 189 void OnPaint(gfx::Canvas* canvas) override; |
184 | 190 |
185 BubbleState state_; | 191 BubbleState state_; |
186 BubbleStyle style_; | 192 BubbleStyle style_; |
187 | 193 |
188 std::unique_ptr<StatusViewAnimation> animation_; | 194 std::unique_ptr<StatusViewAnimation> animation_; |
189 | 195 |
190 // Handle to the widget that contains us. | 196 // Handle to the widget that contains us. |
191 views::Widget* popup_; | 197 views::Widget* popup_; |
192 | 198 |
193 // The currently-displayed text. | 199 // The currently-displayed text. |
194 base::string16 text_; | 200 base::string16 text_; |
195 | 201 |
196 // Holds the theme provider of the frame that created us. | 202 gfx::Size popup_size_; |
197 const ui::ThemeProvider* theme_provider_; | 203 |
204 const SkColor bubble_color_; | |
205 const SkColor bubble_text_color_; | |
206 const bool has_client_edge_; | |
198 | 207 |
199 base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_; | 208 base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_; |
200 | 209 |
201 DISALLOW_COPY_AND_ASSIGN(StatusView); | 210 DISALLOW_COPY_AND_ASSIGN(StatusView); |
202 }; | 211 }; |
203 | 212 |
204 StatusBubbleViews::StatusView::StatusView( | 213 StatusBubbleViews::StatusView::StatusView(views::Widget* popup, |
205 views::Widget* popup, | 214 const gfx::Size& popup_size, |
206 const ui::ThemeProvider* theme_provider) | 215 SkColor bubble_color, |
216 SkColor bubble_text_color, | |
217 bool has_client_edge) | |
207 : state_(BUBBLE_HIDDEN), | 218 : state_(BUBBLE_HIDDEN), |
208 style_(STYLE_STANDARD), | 219 style_(STYLE_STANDARD), |
209 animation_(new StatusViewAnimation(this, 0, 0)), | 220 animation_(new StatusViewAnimation(this, 0, 0)), |
210 popup_(popup), | 221 popup_(popup), |
211 theme_provider_(theme_provider), | 222 popup_size_(popup_size), |
223 bubble_color_(bubble_color), | |
224 bubble_text_color_(bubble_text_color), | |
225 has_client_edge_(has_client_edge), | |
212 timer_factory_(this) {} | 226 timer_factory_(this) {} |
213 | 227 |
214 StatusBubbleViews::StatusView::~StatusView() { | 228 StatusBubbleViews::StatusView::~StatusView() { |
215 animation_->Stop(); | 229 animation_->Stop(); |
216 CancelTimer(); | 230 CancelTimer(); |
217 } | 231 } |
218 | 232 |
219 void StatusBubbleViews::StatusView::SetText(const base::string16& text, | 233 void StatusBubbleViews::StatusView::SetText(const base::string16& text, |
220 bool should_animate_open) { | 234 bool should_animate_open) { |
221 if (text.empty()) { | 235 if (text.empty()) { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
354 | 368 |
355 void StatusBubbleViews::StatusView::OnAnimationEnded() { | 369 void StatusBubbleViews::StatusView::OnAnimationEnded() { |
356 if (state_ == BUBBLE_HIDING_FADE) { | 370 if (state_ == BUBBLE_HIDING_FADE) { |
357 state_ = BUBBLE_HIDDEN; | 371 state_ = BUBBLE_HIDDEN; |
358 popup_->Hide(); | 372 popup_->Hide(); |
359 } else if (state_ == BUBBLE_SHOWING_FADE) { | 373 } else if (state_ == BUBBLE_SHOWING_FADE) { |
360 state_ = BUBBLE_SHOWN; | 374 state_ = BUBBLE_SHOWN; |
361 } | 375 } |
362 } | 376 } |
363 | 377 |
378 void StatusBubbleViews::StatusView::SetWidth(int new_width) { | |
379 popup_size_.set_width(new_width); | |
380 } | |
381 | |
364 const char* StatusBubbleViews::StatusView::GetClassName() const { | 382 const char* StatusBubbleViews::StatusView::GetClassName() const { |
365 return "StatusBubbleViews::StatusView"; | 383 return "StatusBubbleViews::StatusView"; |
366 } | 384 } |
367 | 385 |
368 void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) { | 386 void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) { |
369 SkPaint paint; | 387 canvas->Save(); |
370 paint.setStyle(SkPaint::kFill_Style); | 388 float scale = canvas->UndoDeviceScaleFactor(); |
371 paint.setAntiAlias(true); | 389 const float radius = kBubbleCornerRadius * scale; |
372 SkColor toolbar_color = theme_provider_->GetColor( | |
373 ThemeProperties::COLOR_TOOLBAR); | |
374 paint.setColor(toolbar_color); | |
375 | |
376 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen(); | |
377 | 390 |
378 SkScalar rad[8] = {}; | 391 SkScalar rad[8] = {}; |
379 | 392 |
380 // Top Edges - if the bubble is in its bottom position (sticking downwards), | 393 // Top Edges - if the bubble is in its bottom position (sticking downwards), |
381 // then we square the top edges. Otherwise, we square the edges based on the | 394 // then we square the top edges. Otherwise, we square the edges based on the |
382 // position of the bubble within the window (the bubble is positioned in the | 395 // position of the bubble within the window (the bubble is positioned in the |
383 // southeast corner in RTL and in the southwest corner in LTR). | 396 // southeast corner in RTL and in the southwest corner in LTR). |
384 if (style_ != STYLE_BOTTOM) { | 397 if (style_ != STYLE_BOTTOM) { |
385 if (base::i18n::IsRTL() != (style_ == STYLE_STANDARD_RIGHT)) { | 398 if (base::i18n::IsRTL() != (style_ == STYLE_STANDARD_RIGHT)) { |
386 // The text is RtL or the bubble is on the right side (but not both). | 399 // The text is RtL or the bubble is on the right side (but not both). |
387 | 400 |
388 // Top Left corner. | 401 // Top Left corner. |
389 rad[0] = kBubbleCornerRadius; | 402 rad[0] = radius; |
390 rad[1] = kBubbleCornerRadius; | 403 rad[1] = radius; |
391 } else { | 404 } else { |
392 // Top Right corner. | 405 // Top Right corner. |
393 rad[2] = kBubbleCornerRadius; | 406 rad[2] = radius; |
394 rad[3] = kBubbleCornerRadius; | 407 rad[3] = radius; |
395 } | 408 } |
396 } | 409 } |
397 | 410 |
398 // Bottom edges - Keep these squared off if the bubble is in its standard | 411 // Bottom edges - Keep these squared off if the bubble is in its standard |
399 // position (sticking upward). | 412 // position (sticking upward). |
400 if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) { | 413 if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) { |
401 // Bottom Right Corner. | 414 // Bottom Right Corner. |
402 rad[4] = kBubbleCornerRadius; | 415 rad[4] = radius; |
403 rad[5] = kBubbleCornerRadius; | 416 rad[5] = radius; |
404 | 417 |
405 // Bottom Left Corner. | 418 // Bottom Left Corner. |
406 rad[6] = kBubbleCornerRadius; | 419 rad[6] = radius; |
407 rad[7] = kBubbleCornerRadius; | 420 rad[7] = radius; |
408 } | 421 } |
409 | 422 |
410 // Draw the bubble's shadow. | 423 // Snap to pixels to avoid shadow blurriness. |
411 int width = popup_bounds.width(); | 424 const int width = std::round(popup_size_.width() * scale); |
412 int height = popup_bounds.height(); | 425 const int height = std::round(popup_size_.height() * scale); |
413 gfx::Rect rect(gfx::Rect(popup_bounds.size())); | |
414 SkPaint shadow_paint; | |
415 shadow_paint.setAntiAlias(true); | |
416 shadow_paint.setColor(kShadowColor); | |
417 | 426 |
418 SkRRect rrect; | 427 // We overlap the client edge or window frame by kShadowThickness dips above |
419 rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad); | 428 // in Reposition(). In order to draw on the innermost pixel we inset the |
420 canvas->sk_canvas()->drawRRect(rrect, shadow_paint); | 429 // bubble a bit. This avoids the bubble drawing further and further outside |
430 // the window as the scale increases. | |
Peter Kasting
2016/08/27 04:07:31
Nit: I think if you move this down lower it can be
Bret
2016/08/29 21:57:42
Done.
| |
431 const int subdip_layout_inset = std::floor(kShadowThickness * scale); | |
Peter Kasting
2016/08/27 04:07:31
Nit: I would call this |shadow_thickness_px| at th
Bret
2016/08/29 21:57:42
Done.
| |
421 | 432 |
422 const int shadow_size = 2 * kShadowThickness; | 433 if (!has_client_edge_) { |
423 // Draw the bubble. | 434 // Clip out the edges when the bubble is docked so that it doesn't draw over |
424 rect.SetRect(SkIntToScalar(kShadowThickness), SkIntToScalar(kShadowThickness), | 435 // the window border, since there's no client edge. But we do want the |
425 SkIntToScalar(width - shadow_size), | 436 // border when the bubble is floating so it looks complete. |
Peter Kasting
2016/08/27 04:07:31
Nit: Maybe this would be slightly less awkward?
Bret
2016/08/29 21:57:42
Done; edited the suggestion.
| |
426 SkIntToScalar(height - shadow_size)); | 437 const int clip_left = style_ == STYLE_STANDARD ? subdip_layout_inset : 0; |
427 rrect.setRectRadii(RectToSkRect(rect), (const SkVector*)rad); | 438 const int clip_right = |
428 canvas->sk_canvas()->drawRRect(rrect, paint); | 439 style_ == STYLE_STANDARD_RIGHT ? subdip_layout_inset : 0; |
440 const int clip_bottom = clip_left || clip_right ? subdip_layout_inset : 0; | |
441 gfx::Rect clip_rect(clip_left, 0, width - clip_right, height - clip_bottom); | |
442 canvas->ClipRect(clip_rect); | |
443 } | |
444 | |
445 gfx::RectF bubble_rect(width, height); | |
446 const int inset_left = | |
447 style_ != STYLE_STANDARD_RIGHT ? subdip_layout_inset : 1; | |
Peter Kasting
2016/08/27 04:07:31
Nit: Prefer "style == STANDARD_RIGHT ? 1 : var" so
Bret
2016/08/29 21:57:42
Done.
| |
448 const int inset_right = | |
449 style_ == STYLE_STANDARD_RIGHT ? subdip_layout_inset : 1; | |
Peter Kasting
2016/08/27 04:07:31
Nit: I was confused for a bit why we were insettin
Bret
2016/08/29 21:57:42
Done; edited the suggested comment.
| |
450 bubble_rect.Inset(inset_left - 0.5, 0.5, inset_right - 0.5, | |
451 subdip_layout_inset - 0.5); | |
452 | |
453 SkPath path; | |
454 path.addRoundRect(gfx::RectFToSkRect(bubble_rect), rad); | |
455 | |
456 SkPaint paint; | |
457 paint.setStyle(SkPaint::kStroke_Style); | |
458 paint.setStrokeWidth(1); | |
459 paint.setAntiAlias(true); | |
460 | |
461 SkPath stroke_path; | |
462 paint.getFillPath(path, &stroke_path); | |
463 | |
464 // Get the fill path by subtracting the shadow so they align neatly. | |
465 SkPath fill_path; | |
466 Op(path, stroke_path, kDifference_SkPathOp, &fill_path); | |
467 paint.setStyle(SkPaint::kFill_Style); | |
468 paint.setColor(bubble_color_); | |
469 canvas->sk_canvas()->drawPath(fill_path, paint); | |
470 | |
471 paint.setColor(kShadowColor); | |
472 canvas->sk_canvas()->drawPath(stroke_path, paint); | |
473 | |
474 canvas->Restore(); | |
429 | 475 |
430 // Compute text bounds. | 476 // Compute text bounds. |
431 const gfx::FontList font_list; | 477 gfx::Rect text_rect(kTextPositionX, 0, |
432 int text_width = | 478 popup_size_.width() - kTextHorizPadding, |
433 std::min(gfx::GetStringWidth(text_, font_list), | 479 popup_size_.height()); |
434 width - shadow_size - kTextPositionX - kTextHorizPadding); | 480 text_rect.Inset(kShadowThickness, kShadowThickness); |
435 int text_height = height - shadow_size; | |
436 gfx::Rect text_bounds(kShadowThickness + kTextPositionX, | |
437 kShadowThickness, | |
438 std::max(0, text_width), | |
439 std::max(0, text_height)); | |
440 // Make sure the text is aligned to the right on RTL UIs. | 481 // Make sure the text is aligned to the right on RTL UIs. |
441 text_bounds.set_x(GetMirroredXForRect(text_bounds)); | 482 text_rect.set_x(GetMirroredXForRect(text_rect)); |
442 | 483 |
443 // Text color is the foreground tab text color at 60% alpha. | 484 // Text color is the foreground tab text color at 60% alpha. |
444 SkColor text_color = color_utils::AlphaBlend( | 485 SkColor blended_text_color = |
445 theme_provider_->GetColor(ThemeProperties::COLOR_TAB_TEXT), toolbar_color, | 486 color_utils::AlphaBlend(bubble_text_color_, bubble_color_, 0x99); |
446 0x99); | |
447 canvas->DrawStringRect( | 487 canvas->DrawStringRect( |
448 text_, font_list, | 488 text_, gfx::FontList(), |
449 color_utils::GetReadableColor(text_color, toolbar_color), text_bounds); | 489 color_utils::GetReadableColor(blended_text_color, bubble_color_), |
490 text_rect); | |
450 } | 491 } |
451 | 492 |
452 | 493 |
453 // StatusBubbleViews::StatusViewAnimation -------------------------------------- | 494 // StatusBubbleViews::StatusViewAnimation -------------------------------------- |
454 | 495 |
455 StatusBubbleViews::StatusViewAnimation::StatusViewAnimation( | 496 StatusBubbleViews::StatusViewAnimation::StatusViewAnimation( |
456 StatusView* status_view, | 497 StatusView* status_view, |
457 float opacity_start, | 498 float opacity_start, |
458 float opacity_end) | 499 float opacity_end) |
459 : gfx::LinearAnimation(kFramerate, this), | 500 : gfx::LinearAnimation(kFramerate, this), |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 status_view_(status_view), | 539 status_view_(status_view), |
499 expansion_start_(0), | 540 expansion_start_(0), |
500 expansion_end_(0) { | 541 expansion_end_(0) { |
501 } | 542 } |
502 | 543 |
503 // Manage the expansion of the bubble. | 544 // Manage the expansion of the bubble. |
504 void StartExpansion(const base::string16& expanded_text, | 545 void StartExpansion(const base::string16& expanded_text, |
505 int current_width, | 546 int current_width, |
506 int expansion_end); | 547 int expansion_end); |
507 | 548 |
508 // Set width of fully expanded bubble. | |
509 void SetExpandedWidth(int expanded_width); | |
510 | |
511 private: | 549 private: |
512 // Animation functions. | 550 // Animation functions. |
513 int GetCurrentBubbleWidth(); | 551 int GetCurrentBubbleWidth(); |
514 void SetBubbleWidth(int width); | 552 void SetBubbleWidth(int width); |
515 void AnimateToState(double state) override; | 553 void AnimateToState(double state) override; |
516 void AnimationEnded(const gfx::Animation* animation) override; | 554 void AnimationEnded(const gfx::Animation* animation) override; |
517 | 555 |
518 // Manager that owns us. | 556 // Manager that owns us. |
519 StatusBubbleViews* status_bubble_; | 557 StatusBubbleViews* status_bubble_; |
520 | 558 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
562 void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) { | 600 void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) { |
563 status_bubble_->SetBubbleWidth(width); | 601 status_bubble_->SetBubbleWidth(width); |
564 status_view_->SchedulePaint(); | 602 status_view_->SchedulePaint(); |
565 } | 603 } |
566 | 604 |
567 | 605 |
568 // StatusBubbleViews ----------------------------------------------------------- | 606 // StatusBubbleViews ----------------------------------------------------------- |
569 | 607 |
570 const int StatusBubbleViews::kShadowThickness = 1; | 608 const int StatusBubbleViews::kShadowThickness = 1; |
571 | 609 |
572 StatusBubbleViews::StatusBubbleViews(views::View* base_view) | 610 StatusBubbleViews::StatusBubbleViews(views::View* base_view, |
611 bool has_client_edge) | |
573 : contains_mouse_(false), | 612 : contains_mouse_(false), |
574 offset_(0), | 613 offset_(0), |
575 base_view_(base_view), | 614 base_view_(base_view), |
576 view_(NULL), | 615 view_(NULL), |
577 download_shelf_is_visible_(false), | 616 download_shelf_is_visible_(false), |
578 is_expanded_(false), | 617 is_expanded_(false), |
618 has_client_edge_(has_client_edge), | |
579 expand_timer_factory_(this) { | 619 expand_timer_factory_(this) { |
580 expand_view_.reset(); | 620 expand_view_.reset(); |
581 } | 621 } |
582 | 622 |
583 StatusBubbleViews::~StatusBubbleViews() { | 623 StatusBubbleViews::~StatusBubbleViews() { |
584 CancelExpandTimer(); | 624 CancelExpandTimer(); |
585 if (popup_.get()) | 625 if (popup_.get()) |
586 popup_->CloseNow(); | 626 popup_->CloseNow(); |
587 } | 627 } |
588 | 628 |
589 void StatusBubbleViews::Init() { | 629 void StatusBubbleViews::Init() { |
590 if (!popup_.get()) { | 630 if (!popup_.get()) { |
591 popup_.reset(new views::Widget); | 631 popup_.reset(new views::Widget); |
592 views::Widget* frame = base_view_->GetWidget(); | 632 views::Widget* frame = base_view_->GetWidget(); |
593 if (!view_) | 633 if (!view_) { |
594 view_ = new StatusView(popup_.get(), frame->GetThemeProvider()); | 634 const ui::ThemeProvider* theme_provider = frame->GetThemeProvider(); |
635 view_ = new StatusView( | |
636 popup_.get(), size_, | |
637 theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR), | |
638 theme_provider->GetColor(ThemeProperties::COLOR_TAB_TEXT), | |
639 has_client_edge_); | |
640 } | |
595 if (!expand_view_.get()) | 641 if (!expand_view_.get()) |
596 expand_view_.reset(new StatusViewExpander(this, view_)); | 642 expand_view_.reset(new StatusViewExpander(this, view_)); |
597 | 643 |
598 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); | 644 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); |
599 #if defined(OS_WIN) | 645 #if defined(OS_WIN) |
600 // On Windows use the software compositor to ensure that we don't block | 646 // On Windows use the software compositor to ensure that we don't block |
601 // the UI thread blocking issue during command buffer creation. We can | 647 // the UI thread blocking issue during command buffer creation. We can |
602 // revert this change once http://crbug.com/125248 is fixed. | 648 // revert this change once http://crbug.com/125248 is fixed. |
603 params.force_software_compositing = true; | 649 params.force_software_compositing = true; |
604 #endif | 650 #endif |
(...skipping 14 matching lines...) Expand all Loading... | |
619 popup_->SetContentsView(view_); | 665 popup_->SetContentsView(view_); |
620 #if defined(USE_ASH) | 666 #if defined(USE_ASH) |
621 ash::wm::GetWindowState(popup_->GetNativeWindow())-> | 667 ash::wm::GetWindowState(popup_->GetNativeWindow())-> |
622 set_ignored_by_shelf(true); | 668 set_ignored_by_shelf(true); |
623 #endif | 669 #endif |
624 RepositionPopup(); | 670 RepositionPopup(); |
625 } | 671 } |
626 } | 672 } |
627 | 673 |
628 void StatusBubbleViews::Reposition() { | 674 void StatusBubbleViews::Reposition() { |
629 // In restored mode, the client area has a client edge between it and the | 675 // Overlap the client edge that's shown in restored mode, or when there is no |
630 // frame. | 676 // client edge this makes the bubble snug with the corner of the window. |
631 int overlap = kShadowThickness; | 677 int overlap = kShadowThickness; |
632 int height = GetPreferredSize().height(); | 678 int height = GetPreferredSize().height(); |
633 int base_view_height = base_view()->bounds().height(); | 679 int base_view_height = base_view()->bounds().height(); |
634 gfx::Point origin(-overlap, base_view_height - height + overlap); | 680 gfx::Point origin(-overlap, base_view_height - height + overlap); |
635 SetBounds(origin.x(), origin.y(), base_view()->bounds().width() / 3, height); | 681 SetBounds(origin.x(), origin.y(), base_view()->bounds().width() / 3, height); |
636 } | 682 } |
637 | 683 |
638 void StatusBubbleViews::RepositionPopup() { | 684 void StatusBubbleViews::RepositionPopup() { |
639 if (popup_.get()) { | 685 if (popup_.get()) { |
640 gfx::Point top_left; | 686 gfx::Point top_left; |
641 // TODO(flackr): Get the non-transformed point so that the status bubble | 687 // TODO(flackr): Get the non-transformed point so that the status bubble |
642 // popup window's position is consistent with the base_view_'s window. | 688 // popup window's position is consistent with the base_view_'s window. |
643 views::View::ConvertPointToScreen(base_view_, &top_left); | 689 views::View::ConvertPointToScreen(base_view_, &top_left); |
644 | 690 |
691 view_->SetWidth(size_.width()); | |
645 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), | 692 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), |
646 top_left.y() + position_.y(), | 693 top_left.y() + position_.y(), |
647 size_.width(), size_.height())); | 694 size_.width(), size_.height())); |
648 } | 695 } |
649 } | 696 } |
650 | 697 |
651 gfx::Size StatusBubbleViews::GetPreferredSize() { | 698 gfx::Size StatusBubbleViews::GetPreferredSize() { |
652 return gfx::Size(0, gfx::FontList().GetHeight() + kTotalVerticalPadding); | 699 return gfx::Size(0, gfx::FontList().GetHeight() + kTotalVerticalPadding); |
653 } | 700 } |
654 | 701 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
699 return; | 746 return; |
700 } | 747 } |
701 | 748 |
702 // Reset expansion state only when bubble is completely hidden. | 749 // Reset expansion state only when bubble is completely hidden. |
703 if (view_->state() == StatusView::BUBBLE_HIDDEN) { | 750 if (view_->state() == StatusView::BUBBLE_HIDDEN) { |
704 is_expanded_ = false; | 751 is_expanded_ = false; |
705 SetBubbleWidth(GetStandardStatusBubbleWidth()); | 752 SetBubbleWidth(GetStandardStatusBubbleWidth()); |
706 } | 753 } |
707 | 754 |
708 // Set Elided Text corresponding to the GURL object. | 755 // Set Elided Text corresponding to the GURL object. |
709 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen(); | 756 int text_width = static_cast<int>(size_.width() - (kShadowThickness * 2) - |
710 int text_width = static_cast<int>(popup_bounds.width() - | 757 kTextPositionX - kTextHorizPadding - 1); |
711 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1); | |
712 url_text_ = | 758 url_text_ = |
713 url_formatter::ElideUrl(url, gfx::FontList(), text_width); | 759 url_formatter::ElideUrl(url, gfx::FontList(), text_width); |
714 | 760 |
715 // An URL is always treated as a left-to-right string. On right-to-left UIs | 761 // An URL is always treated as a left-to-right string. On right-to-left UIs |
716 // we need to explicitly mark the URL as LTR to make sure it is displayed | 762 // we need to explicitly mark the URL as LTR to make sure it is displayed |
717 // correctly. | 763 // correctly. |
718 url_text_ = base::i18n::GetDisplayStringInLTRDirectionality(url_text_); | 764 url_text_ = base::i18n::GetDisplayStringInLTRDirectionality(url_text_); |
719 | 765 |
720 if (IsFrameVisible()) { | 766 if (IsFrameVisible()) { |
721 view_->SetText(url_text_, true); | 767 view_->SetText(url_text_, true); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
865 | 911 |
866 bool StatusBubbleViews::IsFrameMaximized() { | 912 bool StatusBubbleViews::IsFrameMaximized() { |
867 views::Widget* frame = base_view_->GetWidget(); | 913 views::Widget* frame = base_view_->GetWidget(); |
868 views::Widget* window = frame->GetTopLevelWidget(); | 914 views::Widget* window = frame->GetTopLevelWidget(); |
869 return window && window->IsMaximized(); | 915 return window && window->IsMaximized(); |
870 } | 916 } |
871 | 917 |
872 void StatusBubbleViews::ExpandBubble() { | 918 void StatusBubbleViews::ExpandBubble() { |
873 // Elide URL to maximum possible size, then check actual length (it may | 919 // Elide URL to maximum possible size, then check actual length (it may |
874 // still be too long to fit) before expanding bubble. | 920 // still be too long to fit) before expanding bubble. |
875 gfx::Rect popup_bounds = popup_->GetWindowBoundsInScreen(); | |
876 int max_status_bubble_width = GetMaxStatusBubbleWidth(); | 921 int max_status_bubble_width = GetMaxStatusBubbleWidth(); |
877 const gfx::FontList font_list; | 922 const gfx::FontList font_list; |
878 url_text_ = url_formatter::ElideUrl(url_, font_list, max_status_bubble_width); | 923 url_text_ = url_formatter::ElideUrl(url_, font_list, max_status_bubble_width); |
879 int expanded_bubble_width = | 924 int expanded_bubble_width = |
880 std::max(GetStandardStatusBubbleWidth(), | 925 std::max(GetStandardStatusBubbleWidth(), |
881 std::min(gfx::GetStringWidth(url_text_, font_list) + | 926 std::min(gfx::GetStringWidth(url_text_, font_list) + |
882 (kShadowThickness * 2) + kTextPositionX + | 927 (kShadowThickness * 2) + kTextPositionX + |
883 kTextHorizPadding + 1, | 928 kTextHorizPadding + 1, |
884 max_status_bubble_width)); | 929 max_status_bubble_width)); |
885 is_expanded_ = true; | 930 is_expanded_ = true; |
886 expand_view_->StartExpansion(url_text_, popup_bounds.width(), | 931 expand_view_->StartExpansion(url_text_, size_.width(), expanded_bubble_width); |
887 expanded_bubble_width); | |
888 } | 932 } |
889 | 933 |
890 int StatusBubbleViews::GetStandardStatusBubbleWidth() { | 934 int StatusBubbleViews::GetStandardStatusBubbleWidth() { |
891 return base_view_->bounds().width() / 3; | 935 return base_view_->bounds().width() / 3; |
892 } | 936 } |
893 | 937 |
894 int StatusBubbleViews::GetMaxStatusBubbleWidth() { | 938 int StatusBubbleViews::GetMaxStatusBubbleWidth() { |
895 const ui::NativeTheme* theme = base_view_->GetNativeTheme(); | 939 const ui::NativeTheme* theme = base_view_->GetNativeTheme(); |
896 return static_cast<int>(std::max(0, base_view_->bounds().width() - | 940 return static_cast<int>(std::max(0, base_view_->bounds().width() - |
897 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1 - | 941 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1 - |
898 views::NativeScrollBar::GetVerticalScrollBarWidth(theme))); | 942 views::NativeScrollBar::GetVerticalScrollBarWidth(theme))); |
899 } | 943 } |
900 | 944 |
901 void StatusBubbleViews::SetBubbleWidth(int width) { | 945 void StatusBubbleViews::SetBubbleWidth(int width) { |
902 size_.set_width(width); | 946 size_.set_width(width); |
903 SetBounds(original_position_.x(), original_position_.y(), | 947 SetBounds(original_position_.x(), original_position_.y(), |
904 size_.width(), size_.height()); | 948 size_.width(), size_.height()); |
905 } | 949 } |
906 | 950 |
907 void StatusBubbleViews::CancelExpandTimer() { | 951 void StatusBubbleViews::CancelExpandTimer() { |
908 if (expand_timer_factory_.HasWeakPtrs()) | 952 if (expand_timer_factory_.HasWeakPtrs()) |
909 expand_timer_factory_.InvalidateWeakPtrs(); | 953 expand_timer_factory_.InvalidateWeakPtrs(); |
910 } | 954 } |
OLD | NEW |