| 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 "ui/views/bubble/bubble_frame_view.h" | 5 #include "ui/views/bubble/bubble_frame_view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "grit/ui_resources.h" |
| 10 #include "ui/base/hit_test.h" |
| 11 #include "ui/base/resource/resource_bundle.h" |
| 9 #include "ui/gfx/screen.h" | 12 #include "ui/gfx/screen.h" |
| 10 #include "ui/views/bubble/bubble_border.h" | 13 #include "ui/views/bubble/bubble_border.h" |
| 14 #include "ui/views/controls/button/label_button.h" |
| 11 #include "ui/views/widget/widget.h" | 15 #include "ui/views/widget/widget.h" |
| 12 #include "ui/views/window/client_view.h" | 16 #include "ui/views/window/client_view.h" |
| 13 | 17 |
| 14 namespace { | 18 namespace { |
| 15 | 19 |
| 16 // Get the |vertical| or horizontal screen overflow of the |window_bounds|. | 20 // Get the |vertical| or horizontal screen overflow of the |window_bounds|. |
| 17 int GetOffScreenLength(const gfx::Rect& monitor_bounds, | 21 int GetOffScreenLength(const gfx::Rect& monitor_bounds, |
| 18 const gfx::Rect& window_bounds, | 22 const gfx::Rect& window_bounds, |
| 19 bool vertical) { | 23 bool vertical) { |
| 20 if (monitor_bounds.IsEmpty() || monitor_bounds.Contains(window_bounds)) | 24 if (monitor_bounds.IsEmpty() || monitor_bounds.Contains(window_bounds)) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 34 return std::max(0, monitor_bounds.x() - window_bounds.x()) + | 38 return std::max(0, monitor_bounds.x() - window_bounds.x()) + |
| 35 std::max(0, window_bounds.right() - monitor_bounds.right()); | 39 std::max(0, window_bounds.right() - monitor_bounds.right()); |
| 36 } | 40 } |
| 37 | 41 |
| 38 } // namespace | 42 } // namespace |
| 39 | 43 |
| 40 namespace views { | 44 namespace views { |
| 41 | 45 |
| 42 BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins) | 46 BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins) |
| 43 : bubble_border_(NULL), | 47 : bubble_border_(NULL), |
| 44 content_margins_(content_margins) { | 48 content_margins_(content_margins), |
| 49 title_(NULL), |
| 50 close_(NULL), |
| 51 can_drag_(false) { |
| 52 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 53 title_ = new Label(string16(), rb.GetFont(ui::ResourceBundle::MediumFont)); |
| 54 title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 55 AddChildView(title_); |
| 56 |
| 57 close_ = new LabelButton(this, string16()); |
| 58 close_->SetImage(CustomButton::STATE_NORMAL, |
| 59 *rb.GetImageNamed(IDR_CLOSE_DIALOG).ToImageSkia()); |
| 60 close_->SetImage(CustomButton::STATE_HOVERED, |
| 61 *rb.GetImageNamed(IDR_CLOSE_DIALOG_H).ToImageSkia()); |
| 62 close_->SetImage(CustomButton::STATE_PRESSED, |
| 63 *rb.GetImageNamed(IDR_CLOSE_DIALOG_P).ToImageSkia()); |
| 64 close_->SetSize(close_->GetPreferredSize()); |
| 65 close_->set_border(NULL); |
| 66 close_->SetVisible(false); |
| 67 AddChildView(close_); |
| 45 } | 68 } |
| 46 | 69 |
| 47 BubbleFrameView::~BubbleFrameView() {} | 70 BubbleFrameView::~BubbleFrameView() {} |
| 48 | 71 |
| 49 gfx::Rect BubbleFrameView::GetBoundsForClientView() const { | 72 gfx::Rect BubbleFrameView::GetBoundsForClientView() const { |
| 50 gfx::Rect client_bounds = GetLocalBounds(); | 73 gfx::Rect client_bounds = GetLocalBounds(); |
| 51 client_bounds.Inset(border()->GetInsets()); | 74 client_bounds.Inset(GetInsets()); |
| 52 client_bounds.Inset(content_margins()); | |
| 53 return client_bounds; | 75 return client_bounds; |
| 54 } | 76 } |
| 55 | 77 |
| 56 gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds( | 78 gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds( |
| 57 const gfx::Rect& client_bounds) const { | 79 const gfx::Rect& client_bounds) const { |
| 58 return const_cast<BubbleFrameView*>(this)->GetUpdatedWindowBounds( | 80 return const_cast<BubbleFrameView*>(this)->GetUpdatedWindowBounds( |
| 59 gfx::Rect(), client_bounds.size(), false); | 81 gfx::Rect(), client_bounds.size(), false); |
| 60 } | 82 } |
| 61 | 83 |
| 62 int BubbleFrameView::NonClientHitTest(const gfx::Point& point) { | 84 int BubbleFrameView::NonClientHitTest(const gfx::Point& point) { |
| 85 if (close_->visible() && close_->GetMirroredBounds().Contains(point)) |
| 86 return HTCLOSE; |
| 87 if (can_drag_ && point.y() < GetInsets().top()) |
| 88 return HTCAPTION; |
| 63 return GetWidget()->client_view()->NonClientHitTest(point); | 89 return GetWidget()->client_view()->NonClientHitTest(point); |
| 64 } | 90 } |
| 65 | 91 |
| 92 void BubbleFrameView::GetWindowMask(const gfx::Size& size, |
| 93 gfx::Path* window_mask) {} |
| 94 |
| 95 void BubbleFrameView::ResetWindowControls() {} |
| 96 |
| 97 void BubbleFrameView::UpdateWindowIcon() {} |
| 98 |
| 99 void BubbleFrameView::UpdateWindowTitle() {} |
| 100 |
| 101 gfx::Insets BubbleFrameView::GetInsets() const { |
| 102 gfx::Insets insets = border()->GetInsets(); |
| 103 insets += content_margins_; |
| 104 insets += gfx::Insets(std::max(title_->text().empty() ? 0 : title_->height(), |
| 105 close_->visible() ? close_->height() : 0), |
| 106 0, 0, 0); |
| 107 return insets; |
| 108 } |
| 109 |
| 66 gfx::Size BubbleFrameView::GetPreferredSize() { | 110 gfx::Size BubbleFrameView::GetPreferredSize() { |
| 67 gfx::Size client_size(GetWidget()->client_view()->GetPreferredSize()); | 111 gfx::Size client_size(GetWidget()->client_view()->GetPreferredSize()); |
| 68 return GetUpdatedWindowBounds(gfx::Rect(), client_size, false).size(); | 112 return GetUpdatedWindowBounds(gfx::Rect(), client_size, false).size(); |
| 69 } | 113 } |
| 70 | 114 |
| 115 void BubbleFrameView::Layout() { |
| 116 gfx::Rect bounds = GetLocalBounds(); |
| 117 bounds.Inset(border()->GetInsets()); |
| 118 // Small additional insets yield the desired 10px visual close button insets. |
| 119 bounds.Inset(0, 2, close_->width() + 1, 0); |
| 120 close_->SetPosition(gfx::Point(bounds.right(), bounds.y())); |
| 121 // Small additional insets yield the desired 20px visual title label insets. |
| 122 bounds.Inset(19, 10, 0, 0); |
| 123 bounds.set_height(title_->font().GetHeight()); |
| 124 title_->SetBoundsRect(bounds); |
| 125 } |
| 126 |
| 127 std::string BubbleFrameView::GetClassName() const { |
| 128 return "ui/views/BubbleFrameView"; |
| 129 } |
| 130 |
| 131 void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) { |
| 132 if (sender == close_) |
| 133 GetWidget()->Close(); |
| 134 } |
| 135 |
| 71 void BubbleFrameView::SetBubbleBorder(BubbleBorder* border) { | 136 void BubbleFrameView::SetBubbleBorder(BubbleBorder* border) { |
| 72 bubble_border_ = border; | 137 bubble_border_ = border; |
| 73 set_border(bubble_border_); | 138 set_border(bubble_border_); |
| 74 | 139 |
| 75 // Update the background, which relies on the border. | 140 // Update the background, which relies on the border. |
| 76 set_background(new views::BubbleBackground(border)); | 141 set_background(new views::BubbleBackground(border)); |
| 77 } | 142 } |
| 78 | 143 |
| 144 void BubbleFrameView::SetTitle(const string16& title) { |
| 145 title_->SetText(title); |
| 146 } |
| 147 |
| 148 void BubbleFrameView::SetShowCloseButton(bool show) { |
| 149 close_->SetVisible(show); |
| 150 } |
| 151 |
| 79 gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect, | 152 gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect, |
| 80 gfx::Size client_size, | 153 gfx::Size client_size, |
| 81 bool adjust_if_offscreen) { | 154 bool adjust_if_offscreen) { |
| 82 // Give the contents a margin. | 155 // Give the contents a margin. |
| 83 client_size.Enlarge(content_margins_.width(), content_margins_.height()); | 156 client_size.Enlarge(content_margins_.width(), content_margins_.height()); |
| 84 | 157 |
| 85 const BubbleBorder::ArrowLocation arrow = bubble_border_->arrow_location(); | 158 const BubbleBorder::ArrowLocation arrow = bubble_border_->arrow_location(); |
| 86 if (adjust_if_offscreen && BubbleBorder::has_arrow(arrow)) { | 159 if (adjust_if_offscreen && BubbleBorder::has_arrow(arrow)) { |
| 87 if (!bubble_border_->is_arrow_at_center(arrow)) { | 160 if (!bubble_border_->is_arrow_at_center(arrow)) { |
| 88 // Try to mirror the anchoring if the bubble does not fit on the screen. | 161 // Try to mirror the anchoring if the bubble does not fit on the screen. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 // |offscreen_adjust|, e.g. positive |offscreen_adjust| means bubble | 232 // |offscreen_adjust|, e.g. positive |offscreen_adjust| means bubble |
| 160 // window needs to be moved to the right and that means we need to move arrow | 233 // window needs to be moved to the right and that means we need to move arrow |
| 161 // to the left, and that means negative offset. | 234 // to the left, and that means negative offset. |
| 162 bubble_border_->set_arrow_offset( | 235 bubble_border_->set_arrow_offset( |
| 163 bubble_border_->GetArrowOffset(window_bounds.size()) - offscreen_adjust); | 236 bubble_border_->GetArrowOffset(window_bounds.size()) - offscreen_adjust); |
| 164 if (offscreen_adjust) | 237 if (offscreen_adjust) |
| 165 SchedulePaint(); | 238 SchedulePaint(); |
| 166 } | 239 } |
| 167 | 240 |
| 168 } // namespace views | 241 } // namespace views |
| OLD | NEW |