OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/views/status_bubble_views.h" | 5 #include "chrome/browser/views/status_bubble_views.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "app/gfx/canvas.h" | 9 #include "app/gfx/canvas.h" |
10 #include "app/gfx/text_elider.h" | 10 #include "app/gfx/text_elider.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "grit/generated_resources.h" | 21 #include "grit/generated_resources.h" |
22 #include "grit/theme_resources.h" | 22 #include "grit/theme_resources.h" |
23 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
24 #include "third_party/skia/include/core/SkPaint.h" | 24 #include "third_party/skia/include/core/SkPaint.h" |
25 #include "third_party/skia/include/core/SkPath.h" | 25 #include "third_party/skia/include/core/SkPath.h" |
26 #include "third_party/skia/include/core/SkRect.h" | 26 #include "third_party/skia/include/core/SkRect.h" |
27 #include "views/controls/label.h" | 27 #include "views/controls/label.h" |
28 #include "views/widget/root_view.h" | 28 #include "views/widget/root_view.h" |
29 #include "views/widget/widget.h" | 29 #include "views/widget/widget.h" |
30 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
31 #include "views/controls/scrollbar/native_scroll_bar.h" | |
32 #include "views/widget/widget_win.h" | 31 #include "views/widget/widget_win.h" |
33 #endif | 32 #endif |
34 | 33 |
35 // The alpha and color of the bubble's shadow. | 34 // The alpha and color of the bubble's shadow. |
36 static const SkColor kShadowColor = SkColorSetARGB(30, 0, 0, 0); | 35 static const SkColor kShadowColor = SkColorSetARGB(30, 0, 0, 0); |
37 | 36 |
38 // The roundedness of the edges of our bubble. | 37 // The roundedness of the edges of our bubble. |
39 static const int kBubbleCornerRadius = 4; | 38 static const int kBubbleCornerRadius = 4; |
40 | 39 |
41 // How close the mouse can get to the infobubble before it starts sliding | 40 // How close the mouse can get to the infobubble before it starts sliding |
42 // off-screen. | 41 // off-screen. |
43 static const int kMousePadding = 20; | 42 static const int kMousePadding = 20; |
44 | 43 |
45 // The color of the text | 44 // The color of the text |
46 static const SkColor kTextColor = SkColorSetRGB(100, 100, 100); | 45 static const SkColor kTextColor = SkColorSetRGB(100, 100, 100); |
47 | 46 |
48 // The color of the highlight text | 47 // The color of the highlight text |
49 static const SkColor kTextHighlightColor = SkColorSetRGB(242, 250, 255); | 48 static const SkColor kTextHighlightColor = SkColorSetRGB(242, 250, 255); |
50 | 49 |
51 // The horizontal offset of the text within the status bubble, not including the | 50 // The horizontal offset of the text within the status bubble, not including the |
52 // outer shadow ring. | 51 // outer shadow ring. |
53 static const int kTextPositionX = 3; | 52 static const int kTextPositionX = 3; |
54 | 53 |
55 // The minimum horizontal space between the (right) end of the text and the edge | 54 // The minimum horizontal space between the (right) end of the text and the edge |
56 // of the status bubble, not including the outer shadow ring, or a 1 px gap we | 55 // of the status bubble, not including the outer shadow ring, or a 1 px gap we |
57 // leave so we can shift all the text by 1 px to produce a "highlight" effect. | 56 // leave so we can shit all the text by 1 px to produce a "highlight" effect. |
58 static const int kTextHorizPadding = 1; | 57 static const int kTextHorizPadding = 1; |
59 | 58 |
60 // Delays before we start hiding or showing the bubble after we receive a | 59 // Delays before we start hiding or showing the bubble after we receive a |
61 // show or hide request. | 60 // show or hide request. |
62 static const int kShowDelay = 80; | 61 static const int kShowDelay = 80; |
63 static const int kHideDelay = 250; | 62 static const int kHideDelay = 250; |
64 | 63 |
65 // How long each fade should last for. | 64 // How long each fade should last for. |
66 static const int kShowFadeDurationMS = 120; | 65 static const int kShowFadeDurationMS = 120; |
67 static const int kHideFadeDurationMS = 200; | 66 static const int kHideFadeDurationMS = 200; |
68 static const int kFramerate = 25; | 67 static const int kFramerate = 25; |
69 | 68 |
70 // How long each expansion step should take. | |
71 static const int kExpansionStepDurationMS = 150; | |
72 | |
73 // View ----------------------------------------------------------------------- | 69 // View ----------------------------------------------------------------------- |
74 // StatusView manages the display of the bubble, applying text changes and | 70 // StatusView manages the display of the bubble, applying text changes and |
75 // fading in or out the bubble as required. | 71 // fading in or out the bubble as required. |
76 class StatusBubbleViews::StatusView : public views::Label, | 72 class StatusBubbleViews::StatusView : public views::Label, |
77 public Animation, | 73 public Animation, |
78 public AnimationDelegate { | 74 public AnimationDelegate { |
79 public: | 75 public: |
80 StatusView(StatusBubble* status_bubble, views::Widget* popup, | 76 StatusView(StatusBubble* status_bubble, views::Widget* popup, |
81 ThemeProvider* theme_provider) | 77 ThemeProvider* theme_provider) |
82 : Animation(kFramerate, this), | 78 : Animation(kFramerate, this), |
(...skipping 27 matching lines...) Expand all Loading... |
110 | 106 |
111 enum BubbleStyle { | 107 enum BubbleStyle { |
112 STYLE_BOTTOM, | 108 STYLE_BOTTOM, |
113 STYLE_FLOATING, | 109 STYLE_FLOATING, |
114 STYLE_STANDARD, | 110 STYLE_STANDARD, |
115 STYLE_STANDARD_RIGHT | 111 STYLE_STANDARD_RIGHT |
116 }; | 112 }; |
117 | 113 |
118 // Set the bubble text to a certain value, hides the bubble if text is | 114 // Set the bubble text to a certain value, hides the bubble if text is |
119 // an empty string. | 115 // an empty string. |
120 void SetTextAndAnimate(const std::wstring& text); | |
121 | |
122 // Set the bubble text to a certain value without triggering animation | |
123 // sequence. Called by the StatusViewExpander after bubble has been | |
124 // fully expanded. | |
125 void SetText(const std::wstring& text); | 116 void SetText(const std::wstring& text); |
126 | 117 |
127 BubbleStage GetState() const { return stage_; } | 118 BubbleStage GetState() const { return stage_; } |
128 | 119 |
129 void SetStyle(BubbleStyle style); | 120 void SetStyle(BubbleStyle style); |
130 | 121 |
131 BubbleStyle GetStyle() const { return style_; } | 122 BubbleStyle GetStyle() const { return style_; } |
132 | 123 |
133 // Show the bubble instantly. | 124 // Show the bubble instantly. |
134 void Show(); | 125 void Show(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 // fade-in can easily turn into a fade out, opacity_start_ is sometimes | 171 // fade-in can easily turn into a fade out, opacity_start_ is sometimes |
181 // a value between 0 and 1. | 172 // a value between 0 and 1. |
182 double opacity_start_; | 173 double opacity_start_; |
183 double opacity_end_; | 174 double opacity_end_; |
184 | 175 |
185 // Holds the theme provider of the frame that created us. | 176 // Holds the theme provider of the frame that created us. |
186 ThemeProvider* theme_provider_; | 177 ThemeProvider* theme_provider_; |
187 }; | 178 }; |
188 | 179 |
189 void StatusBubbleViews::StatusView::SetText(const std::wstring& text) { | 180 void StatusBubbleViews::StatusView::SetText(const std::wstring& text) { |
190 text_ = text; | |
191 SchedulePaint(); | |
192 } | |
193 | |
194 void StatusBubbleViews::StatusView::SetTextAndAnimate( | |
195 const std::wstring& text) { | |
196 if (text.empty()) { | 181 if (text.empty()) { |
197 // The string was empty. | 182 // The string was empty. |
198 StartHiding(); | 183 StartHiding(); |
199 } else { | 184 } else { |
200 // We want to show the string. | 185 // We want to show the string. |
201 text_ = text; | 186 text_ = text; |
202 StartShowing(); | 187 StartShowing(); |
203 } | 188 } |
204 | 189 |
205 SchedulePaint(); | 190 SchedulePaint(); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 SchedulePaint(); | 310 SchedulePaint(); |
326 } | 311 } |
327 | 312 |
328 void StatusBubbleViews::StatusView::AnimateToState(double state) { | 313 void StatusBubbleViews::StatusView::AnimateToState(double state) { |
329 SetOpacity(GetCurrentOpacity()); | 314 SetOpacity(GetCurrentOpacity()); |
330 } | 315 } |
331 | 316 |
332 void StatusBubbleViews::StatusView::AnimationEnded( | 317 void StatusBubbleViews::StatusView::AnimationEnded( |
333 const Animation* animation) { | 318 const Animation* animation) { |
334 SetOpacity(opacity_end_); | 319 SetOpacity(opacity_end_); |
| 320 |
335 if (stage_ == BUBBLE_HIDING_FADE) { | 321 if (stage_ == BUBBLE_HIDING_FADE) { |
336 stage_ = BUBBLE_HIDDEN; | 322 stage_ = BUBBLE_HIDDEN; |
337 popup_->Hide(); | 323 popup_->Hide(); |
338 } else if (stage_ == BUBBLE_SHOWING_FADE) { | 324 } else if (stage_ == BUBBLE_SHOWING_FADE) { |
339 stage_ = BUBBLE_SHOWN; | 325 stage_ = BUBBLE_SHOWN; |
340 } | 326 } |
341 } | 327 } |
342 | 328 |
343 void StatusBubbleViews::StatusView::SetStyle(BubbleStyle style) { | 329 void StatusBubbleViews::StatusView::SetStyle(BubbleStyle style) { |
344 if (style_ != style) { | 330 if (style_ != style) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 | 446 |
461 canvas->DrawStringInt(text_, | 447 canvas->DrawStringInt(text_, |
462 views::Label::GetFont(), | 448 views::Label::GetFont(), |
463 kTextColor, | 449 kTextColor, |
464 body_bounds.x(), | 450 body_bounds.x(), |
465 body_bounds.y(), | 451 body_bounds.y(), |
466 body_bounds.width(), | 452 body_bounds.width(), |
467 body_bounds.height()); | 453 body_bounds.height()); |
468 } | 454 } |
469 | 455 |
470 | |
471 // StatusViewExpander --------------------------------------------------------- | |
472 // StatusViewExpander manages the expansion and contraction of the status | |
473 // bubble as it accommodates URL's too long to fit in the standard bubble. | |
474 // Changes are passed through to the StatusView to paint. | |
475 class StatusBubbleViews::StatusViewExpander : public Animation, | |
476 public AnimationDelegate { | |
477 public: | |
478 StatusViewExpander(StatusBubble* status_bubble, StatusView* status_view) | |
479 : Animation(kFramerate, this), | |
480 status_bubble_(status_bubble), | |
481 status_view_(status_view), | |
482 expansion_start_(0), | |
483 expansion_end_(0) { | |
484 } | |
485 | |
486 // Manage the expansion of the bubble. | |
487 void StartExpansion(std::wstring expanded_text, int current_width, | |
488 int expansion_end); | |
489 | |
490 // Set width of fully expanded bubble. | |
491 void SetExpandedWidth(int expanded_width); | |
492 | |
493 private: | |
494 // Animation functions. | |
495 int GetCurrentBubbleWidth(); | |
496 void SetBubbleWidth(int width); | |
497 void AnimateToState(double state); | |
498 void AnimationEnded(const Animation* animation); | |
499 | |
500 // We are changing the bounds and text of this view. | |
501 StatusView* status_view_; | |
502 | |
503 // Manager that owns us. | |
504 StatusBubble* status_bubble_; | |
505 | |
506 // The currently displayed text. | |
507 std::wstring text_; | |
508 | |
509 // Text elided to fit maximum possible status bar width. | |
510 std::wstring expanded_text_; | |
511 | |
512 // Widths at expansion start and end. | |
513 int expansion_start_; | |
514 int expansion_end_; | |
515 }; | |
516 | |
517 void StatusBubbleViews::StatusViewExpander::AnimateToState(double state) { | |
518 SetBubbleWidth(GetCurrentBubbleWidth()); | |
519 } | |
520 | |
521 void StatusBubbleViews::StatusViewExpander::AnimationEnded( | |
522 const Animation* animation) { | |
523 SetBubbleWidth(expansion_end_); | |
524 status_view_->SetText(expanded_text_); | |
525 } | |
526 | |
527 void StatusBubbleViews::StatusViewExpander::StartExpansion( | |
528 std::wstring expanded_text, int expansion_start, | |
529 int expansion_end) { | |
530 expanded_text_ = expanded_text; | |
531 expansion_start_ = expansion_start; | |
532 expansion_end_ = expansion_end; | |
533 SetDuration(kExpansionStepDurationMS); | |
534 Start(); | |
535 } | |
536 | |
537 int StatusBubbleViews::StatusViewExpander::GetCurrentBubbleWidth() { | |
538 return static_cast<int>(expansion_start_ + | |
539 (expansion_end_ - expansion_start_) * Animation::GetCurrentValue()); | |
540 } | |
541 | |
542 void StatusBubbleViews::StatusViewExpander::SetBubbleWidth(int width) { | |
543 status_bubble_->SetBubbleWidth(width); | |
544 status_view_->SchedulePaint(); | |
545 } | |
546 | |
547 // StatusBubble --------------------------------------------------------------- | 456 // StatusBubble --------------------------------------------------------------- |
548 | 457 |
549 const int StatusBubbleViews::kShadowThickness = 1; | 458 const int StatusBubbleViews::kShadowThickness = 1; |
550 | 459 |
551 StatusBubbleViews::StatusBubbleViews(views::Widget* frame) | 460 StatusBubbleViews::StatusBubbleViews(views::Widget* frame) |
552 : offset_(0), | 461 : offset_(0), |
553 popup_(NULL), | 462 popup_(NULL), |
554 opacity_(0), | 463 opacity_(0), |
555 frame_(frame), | 464 frame_(frame), |
556 view_(NULL), | 465 view_(NULL), |
557 download_shelf_is_visible_(false), | 466 download_shelf_is_visible_(false) { |
558 is_expanded_(false), | |
559 expand_timer_factory_(this) { | |
560 } | 467 } |
561 | 468 |
562 StatusBubbleViews::~StatusBubbleViews() { | 469 StatusBubbleViews::~StatusBubbleViews() { |
563 CancelExpandTimer(); | |
564 if (popup_.get()) | 470 if (popup_.get()) |
565 popup_->CloseNow(); | 471 popup_->CloseNow(); |
566 } | 472 } |
567 | 473 |
568 void StatusBubbleViews::Init() { | 474 void StatusBubbleViews::Init() { |
569 if (!popup_.get()) { | 475 if (!popup_.get()) { |
570 #if defined(OS_WIN) | 476 #if defined(OS_WIN) |
571 views::WidgetWin* popup = new views::WidgetWin; | 477 views::WidgetWin* popup = new views::WidgetWin; |
572 popup->set_delete_on_destroy(false); | 478 popup->set_delete_on_destroy(false); |
573 | 479 |
574 if (!view_) | 480 if (!view_) |
575 view_ = new StatusView(this, popup, frame_->GetThemeProvider()); | 481 view_ = new StatusView(this, popup, frame_->GetThemeProvider()); |
576 if (!expand_view_) | |
577 expand_view_ = new StatusViewExpander(this, view_); | |
578 | 482 |
579 popup->set_window_style(WS_POPUP); | 483 popup->set_window_style(WS_POPUP); |
580 popup->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | | 484 popup->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | |
581 WS_EX_TRANSPARENT | | 485 WS_EX_TRANSPARENT | |
582 l10n_util::GetExtendedTooltipStyles()); | 486 l10n_util::GetExtendedTooltipStyles()); |
583 popup->SetOpacity(0x00); | 487 popup->SetOpacity(0x00); |
584 popup->Init(frame_->GetNativeView(), gfx::Rect()); | 488 popup->Init(frame_->GetNativeView(), gfx::Rect()); |
585 popup->SetContentsView(view_); | 489 popup->SetContentsView(view_); |
586 Reposition(); | 490 Reposition(); |
587 popup->Show(); | 491 popup->Show(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 Reposition(); | 528 Reposition(); |
625 } | 529 } |
626 | 530 |
627 void StatusBubbleViews::SetStatus(const std::wstring& status_text) { | 531 void StatusBubbleViews::SetStatus(const std::wstring& status_text) { |
628 if (status_text_ == status_text) | 532 if (status_text_ == status_text) |
629 return; | 533 return; |
630 | 534 |
631 Init(); | 535 Init(); |
632 status_text_ = status_text; | 536 status_text_ = status_text; |
633 if (!status_text_.empty()) { | 537 if (!status_text_.empty()) { |
634 view_->SetTextAndAnimate(status_text); | 538 view_->SetText(status_text); |
635 view_->Show(); | 539 view_->Show(); |
636 } else if (!url_text_.empty()) { | 540 } else if (!url_text_.empty()) { |
637 view_->SetTextAndAnimate(url_text_); | 541 view_->SetText(url_text_); |
638 } else { | 542 } else { |
639 view_->SetTextAndAnimate(std::wstring()); | 543 view_->SetText(std::wstring()); |
640 } | 544 } |
641 } | 545 } |
642 | 546 |
643 void StatusBubbleViews::SetURL(const GURL& url, const std::wstring& languages) { | 547 void StatusBubbleViews::SetURL(const GURL& url, const std::wstring& languages) { |
644 languages_ = languages; | |
645 url_ = url; | |
646 Init(); | 548 Init(); |
647 | 549 |
648 // If we want to clear a displayed URL but there is a status still to | 550 // If we want to clear a displayed URL but there is a status still to |
649 // display, display that status instead. | 551 // display, display that status instead. |
650 if (url.is_empty() && !status_text_.empty()) { | 552 if (url.is_empty() && !status_text_.empty()) { |
651 url_text_ = std::wstring(); | 553 url_text_ = std::wstring(); |
652 view_->SetTextAndAnimate(status_text_); | 554 view_->SetText(status_text_); |
653 return; | 555 return; |
654 } | 556 } |
655 | 557 |
656 // Reset expansion state only when bubble is completely hidden. | |
657 if (view_->GetState() == StatusView::BUBBLE_HIDDEN) { | |
658 is_expanded_ = false; | |
659 SetBubbleWidth(GetStandardStatusBubbleWidth()); | |
660 } | |
661 | |
662 // Set Elided Text corresponding to the GURL object. | 558 // Set Elided Text corresponding to the GURL object. |
663 gfx::Rect popup_bounds; | 559 gfx::Rect popup_bounds; |
664 popup_->GetBounds(&popup_bounds, true); | 560 popup_->GetBounds(&popup_bounds, true); |
665 int text_width = static_cast<int>(popup_bounds.width() - | 561 int text_width = static_cast<int>(popup_bounds.width() - |
666 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1); | 562 (kShadowThickness * 2) - kTextPositionX - kTextHorizPadding - 1); |
667 url_text_ = gfx::ElideUrl(url, view_->Label::GetFont(), text_width, | 563 url_text_ = gfx::ElideUrl(url, view_->Label::GetFont(), text_width, |
668 languages); | 564 languages); |
669 | 565 |
670 url_parse::Parsed parsed; | |
671 std::wstring original_url_text_ = | |
672 net::FormatUrl(url, languages, true, true, &parsed, NULL); | |
673 | |
674 // An URL is always treated as a left-to-right string. On right-to-left UIs | 566 // An URL is always treated as a left-to-right string. On right-to-left UIs |
675 // we need to explicitly mark the URL as LTR to make sure it is displayed | 567 // we need to explicitly mark the URL as LTR to make sure it is displayed |
676 // correctly. | 568 // correctly. |
677 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT && | 569 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT && |
678 !url_text_.empty()) | 570 !url_text_.empty()) |
679 l10n_util::WrapStringWithLTRFormatting(&url_text_); | 571 l10n_util::WrapStringWithLTRFormatting(&url_text_); |
680 | 572 view_->SetText(url_text_); |
681 view_->SetTextAndAnimate(url_text_); | |
682 | |
683 CancelExpandTimer(); | |
684 | |
685 // If bubble is already in expanded state, shift immediately to adjust to | |
686 // new text size (shrinking or expanding). Otherwise delay for | |
687 // kExpandHoverDelay ms. | |
688 if (is_expanded_ && !url.is_empty()) | |
689 ExpandBubble(); | |
690 else if (original_url_text_.length() > url_text_.length()) | |
691 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
692 expand_timer_factory_.NewRunnableMethod( | |
693 &StatusBubbleViews::ExpandBubble), kExpandHoverDelay); | |
694 } | 573 } |
695 | 574 |
696 void StatusBubbleViews::Hide() { | 575 void StatusBubbleViews::Hide() { |
697 status_text_ = std::wstring(); | 576 status_text_ = std::wstring(); |
698 url_text_ = std::wstring(); | 577 url_text_ = std::wstring(); |
699 if (view_) | 578 if (view_) |
700 view_->Hide(); | 579 view_->Hide(); |
701 } | 580 } |
702 | 581 |
703 void StatusBubbleViews::MouseMoved() { | 582 void StatusBubbleViews::MouseMoved() { |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 const int bubble_bottom_y = top_left.y() + position_.y() + size_.height(); | 668 const int bubble_bottom_y = top_left.y() + position_.y() + size_.height(); |
790 | 669 |
791 if (bubble_bottom_y + offset > monitor_rect.height() || | 670 if (bubble_bottom_y + offset > monitor_rect.height() || |
792 (download_shelf_is_visible_ && | 671 (download_shelf_is_visible_ && |
793 view_->GetStyle() == StatusView::STYLE_FLOATING)) { | 672 view_->GetStyle() == StatusView::STYLE_FLOATING)) { |
794 // The offset is still too large. Move the bubble to the right and reset | 673 // The offset is still too large. Move the bubble to the right and reset |
795 // Y offset_ to zero. | 674 // Y offset_ to zero. |
796 view_->SetStyle(StatusView::STYLE_STANDARD_RIGHT); | 675 view_->SetStyle(StatusView::STYLE_STANDARD_RIGHT); |
797 offset_ = 0; | 676 offset_ = 0; |
798 | 677 |
799 // Subtract border width + bubble width. | 678 // Substract border width + bubble width. |
800 int right_position_x = window_width - (position_.x() + size_.width()); | 679 int right_position_x = window_width - (position_.x() + size_.width()); |
801 popup_->SetBounds(gfx::Rect(top_left.x() + right_position_x, | 680 popup_->SetBounds(gfx::Rect(top_left.x() + right_position_x, |
802 top_left.y() + position_.y(), | 681 top_left.y() + position_.y(), |
803 size_.width(), size_.height())); | 682 size_.width(), size_.height())); |
804 } else { | 683 } else { |
805 offset_ = offset; | 684 offset_ = offset; |
806 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), | 685 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), |
807 top_left.y() + position_.y() + offset_, | 686 top_left.y() + position_.y() + offset_, |
808 size_.width(), size_.height())); | 687 size_.width(), size_.height())); |
809 } | 688 } |
810 } else if (offset_ != 0 || | 689 } else if (offset_ != 0 || |
811 view_->GetStyle() == StatusView::STYLE_STANDARD_RIGHT) { | 690 view_->GetStyle() == StatusView::STYLE_STANDARD_RIGHT) { |
812 offset_ = 0; | 691 offset_ = 0; |
813 view_->SetStyle(StatusView::STYLE_STANDARD); | 692 view_->SetStyle(StatusView::STYLE_STANDARD); |
814 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), | 693 popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), |
815 top_left.y() + position_.y(), | 694 top_left.y() + position_.y(), |
816 size_.width(), size_.height())); | 695 size_.width(), size_.height())); |
817 } | 696 } |
818 } | 697 } |
819 | |
820 void StatusBubbleViews::ExpandBubble() { | |
821 // Elide url to maximum possible size, then check actual length (it may | |
822 // still be too long to fit) before expanding bubble. | |
823 gfx::Rect popup_bounds; | |
824 popup_->GetBounds(&popup_bounds, true); | |
825 int max_status_bubble_width = GetMaxStatusBubbleWidth(); | |
826 url_text_ = gfx::ElideUrl(url_, view_->Label::GetFont(), | |
827 max_status_bubble_width, languages_); | |
828 int expanded_bubble_width = | |
829 std::max(GetStandardStatusBubbleWidth(), | |
830 std::min(view_->Label::GetFont().GetStringWidth(url_text_) + | |
831 (kShadowThickness * 2) + kTextPositionX + kTextHorizPadding + 1, | |
832 max_status_bubble_width)); | |
833 is_expanded_ = true; | |
834 expand_view_->StartExpansion(url_text_, popup_bounds.width(), | |
835 expanded_bubble_width); | |
836 } | |
837 | |
838 int StatusBubbleViews::GetStandardStatusBubbleWidth() { | |
839 gfx::Rect frame_bounds; | |
840 frame_->GetBounds(&frame_bounds, false); | |
841 return frame_bounds.width() / 3; | |
842 } | |
843 | |
844 int StatusBubbleViews::GetMaxStatusBubbleWidth() { | |
845 gfx::Rect frame_bounds; | |
846 frame_->GetBounds(&frame_bounds, false); | |
847 return static_cast<int>(frame_bounds.width() - (kShadowThickness * 2) - | |
848 kTextPositionX - kTextHorizPadding - 1 - | |
849 views::NativeScrollBar::GetVerticalScrollBarWidth()); | |
850 } | |
851 | |
852 void StatusBubbleViews::SetBubbleWidth(int width) { | |
853 size_.set_width(width); | |
854 SetBounds(position_.x(), position_.y(), size_.width(), size_.height()); | |
855 } | |
856 | |
857 void StatusBubbleViews::CancelExpandTimer() { | |
858 if (!expand_timer_factory_.empty()) | |
859 expand_timer_factory_.RevokeAll(); | |
860 } | |
861 | |
OLD | NEW |