Chromium Code Reviews| 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/tray_bubble_view.h" | 5 #include "ui/views/bubble/tray_bubble_view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "third_party/skia/include/core/SkCanvas.h" | 9 #include "third_party/skia/include/core/SkCanvas.h" |
| 10 #include "third_party/skia/include/core/SkColor.h" | 10 #include "third_party/skia/include/core/SkColor.h" |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 // to stack bubbles with no arrows correctly. Also calculates the arrow offset. | 41 // to stack bubbles with no arrows correctly. Also calculates the arrow offset. |
| 42 class TrayBubbleBorder : public views::BubbleBorder { | 42 class TrayBubbleBorder : public views::BubbleBorder { |
| 43 public: | 43 public: |
| 44 TrayBubbleBorder(views::View* owner, | 44 TrayBubbleBorder(views::View* owner, |
| 45 views::View* anchor, | 45 views::View* anchor, |
| 46 TrayBubbleView::InitParams params) | 46 TrayBubbleView::InitParams params) |
| 47 : views::BubbleBorder(params.arrow_location, params.shadow), | 47 : views::BubbleBorder(params.arrow_location, params.shadow), |
| 48 owner_(owner), | 48 owner_(owner), |
| 49 anchor_(anchor), | 49 anchor_(anchor), |
| 50 tray_arrow_offset_(params.arrow_offset) { | 50 tray_arrow_offset_(params.arrow_offset) { |
| 51 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | 51 set_alignment(params.arrow_alignment); |
| 52 set_background_color(params.arrow_color); | 52 set_background_color(params.arrow_color); |
| 53 } | 53 } |
| 54 | 54 |
| 55 virtual ~TrayBubbleBorder() {} | 55 virtual ~TrayBubbleBorder() {} |
| 56 | 56 |
| 57 // Overridden from views::BubbleBorder. | 57 // Overridden from views::BubbleBorder. |
| 58 // Override views::BubbleBorder to set the bubble on top of the anchor when | 58 // Override views::BubbleBorder to set the bubble on top of the anchor when |
| 59 // it has no arrow. | 59 // it has no arrow. |
| 60 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, | 60 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, |
| 61 const gfx::Size& contents_size) const OVERRIDE { | 61 const gfx::Size& contents_size) const OVERRIDE { |
| 62 if (arrow_location() != NONE) { | 62 if (has_arrow(arrow_location())) { |
| 63 return views::BubbleBorder::GetBounds(position_relative_to, | 63 return views::BubbleBorder::GetBounds(position_relative_to, |
| 64 contents_size); | 64 contents_size); |
| 65 } | 65 } |
| 66 | 66 |
| 67 gfx::Size border_size(contents_size); | 67 gfx::Size border_size(contents_size); |
| 68 gfx::Insets insets = GetInsets(); | 68 gfx::Insets insets = GetInsets(); |
| 69 border_size.Enlarge(insets.width(), insets.height()); | 69 border_size.Enlarge(insets.width(), insets.height()); |
| 70 | 70 |
| 71 const int x = position_relative_to.x() + | 71 const int x = position_relative_to.x() + |
| 72 position_relative_to.width() / 2 - border_size.width() / 2; | 72 position_relative_to.width() / 2 - border_size.width() / 2; |
| 73 // Position the bubble on top of the anchor. | 73 // Position the bubble on top of the anchor. |
| 74 const int y = position_relative_to.y() - border_size.height() | 74 const int y = position_relative_to.y() - border_size.height() |
| 75 + insets.height() - kBubbleSpacing; | 75 + insets.height() - kBubbleSpacing; |
| 76 return gfx::Rect(x, y, border_size.width(), border_size.height()); | 76 return gfx::Rect(x, y, border_size.width(), border_size.height()); |
| 77 } | 77 } |
| 78 | 78 |
| 79 // Anchor point is in screen coordinates. | |
| 79 void UpdateArrowOffset() { | 80 void UpdateArrowOffset() { |
| 81 if (!has_arrow(arrow_location())) { | |
| 82 return; | |
| 83 } | |
| 84 | |
| 80 int arrow_offset = 0; | 85 int arrow_offset = 0; |
| 81 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT || | 86 gfx::Point pt(0, 0); |
| 82 arrow_location() == views::BubbleBorder::BOTTOM_LEFT) { | 87 if (tray_arrow_offset_ == TrayBubbleView::InitParams::kArrowDefaultOffset) { |
| 83 // Note: tray_arrow_offset_ is relative to the anchor widget. | 88 set_arrow_offset(kArrowMinOffset); |
| 84 if (tray_arrow_offset_ == | 89 return; |
| 85 TrayBubbleView::InitParams::kArrowDefaultOffset) { | 90 } |
| 86 arrow_offset = kArrowMinOffset; | 91 // Note: tray_arrow_offset_ is relative to the anchor widget. |
| 87 } else { | 92 if (is_arrow_on_horizontal(arrow_location())) |
| 88 const int width = owner_->GetWidget()->GetContentsView()->width(); | 93 pt.set_x(tray_arrow_offset_); |
| 89 gfx::Point pt(tray_arrow_offset_, 0); | 94 else |
| 90 views::View::ConvertPointToScreen( | 95 pt.set_y(tray_arrow_offset_); |
| 91 anchor_->GetWidget()->GetRootView(), &pt); | 96 |
| 92 views::View::ConvertPointFromScreen( | 97 if (anchor_) { |
| 93 owner_->GetWidget()->GetRootView(), &pt); | 98 views::View::ConvertPointToScreen( |
| 94 arrow_offset = pt.x(); | 99 anchor_->GetWidget()->GetRootView(), &pt); |
| 95 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) | |
| 96 arrow_offset = width - arrow_offset; | |
| 97 arrow_offset = std::max(arrow_offset, kArrowMinOffset); | |
| 98 } | |
| 99 } else { | 100 } else { |
| 100 if (tray_arrow_offset_ == | 101 pt.Offset(anchor_point_.x(), anchor_point_.y()); |
| 101 TrayBubbleView::InitParams::kArrowDefaultOffset) { | |
| 102 arrow_offset = kArrowMinOffset; | |
| 103 } else { | |
| 104 gfx::Point pt(0, tray_arrow_offset_); | |
| 105 views::View::ConvertPointToScreen( | |
| 106 anchor_->GetWidget()->GetRootView(), &pt); | |
| 107 views::View::ConvertPointFromScreen( | |
| 108 owner_->GetWidget()->GetRootView(), &pt); | |
| 109 arrow_offset = pt.y(); | |
| 110 arrow_offset = std::max(arrow_offset, kArrowMinOffset); | |
| 111 } | |
| 112 } | 102 } |
| 103 | |
| 104 views::View::ConvertPointFromScreen( | |
| 105 owner_->GetWidget()->GetRootView(), &pt); | |
| 106 const int width = owner_->GetWidget()->GetContentsView()->width(); | |
| 107 | |
| 108 if (is_arrow_on_horizontal(arrow_location())) { | |
| 109 arrow_offset = pt.x(); | |
| 110 if (!is_arrow_on_left(arrow_location())) | |
| 111 arrow_offset = width - arrow_offset; | |
| 112 } else { | |
| 113 arrow_offset = pt.y(); | |
| 114 } | |
| 115 | |
| 116 arrow_offset = std::max(arrow_offset, kArrowMinOffset); | |
| 113 set_arrow_offset(arrow_offset); | 117 set_arrow_offset(arrow_offset); |
| 114 } | 118 } |
| 115 | 119 |
| 116 private: | 120 private: |
| 117 views::View* owner_; | 121 views::View* owner_; |
| 118 views::View* anchor_; | 122 views::View* anchor_; |
| 123 gfx::Point anchor_point_; | |
| 119 const int tray_arrow_offset_; | 124 const int tray_arrow_offset_; |
| 120 | 125 |
| 121 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); | 126 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); |
| 122 }; | 127 }; |
| 123 | 128 |
| 124 // This mask layer clips the bubble's content so that it does not overwrite the | 129 // This mask layer clips the bubble's content so that it does not overwrite the |
| 125 // rounded bubble corners. | 130 // rounded bubble corners. |
| 126 // TODO(miket): This does not work on Windows. Implement layer masking or | 131 // TODO(miket): This does not work on Windows. Implement layer masking or |
| 127 // alternate solutions if the TrayBubbleView is needed there in the future. | 132 // alternate solutions if the TrayBubbleView is needed there in the future. |
| 128 class TrayBubbleContentMask : public ui::LayerDelegate { | 133 class TrayBubbleContentMask : public ui::LayerDelegate { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 140 private: | 145 private: |
| 141 ui::Layer layer_; | 146 ui::Layer layer_; |
| 142 SkScalar corner_radius_; | 147 SkScalar corner_radius_; |
| 143 | 148 |
| 144 DISALLOW_COPY_AND_ASSIGN(TrayBubbleContentMask); | 149 DISALLOW_COPY_AND_ASSIGN(TrayBubbleContentMask); |
| 145 }; | 150 }; |
| 146 | 151 |
| 147 TrayBubbleContentMask::TrayBubbleContentMask(int corner_radius) | 152 TrayBubbleContentMask::TrayBubbleContentMask(int corner_radius) |
| 148 : layer_(ui::LAYER_TEXTURED), | 153 : layer_(ui::LAYER_TEXTURED), |
| 149 corner_radius_(corner_radius) { | 154 corner_radius_(corner_radius) { |
| 155 #ifdef USE_AURA | |
|
Pete Williamson
2013/01/17 19:07:45
Remove ifdefs
dewittj
2013/01/18 00:57:46
Done.
| |
| 150 layer_.set_delegate(this); | 156 layer_.set_delegate(this); |
| 157 #endif | |
| 151 } | 158 } |
| 152 | 159 |
| 153 TrayBubbleContentMask::~TrayBubbleContentMask() { | 160 TrayBubbleContentMask::~TrayBubbleContentMask() { |
| 161 #ifdef USE_AURA | |
| 154 layer_.set_delegate(NULL); | 162 layer_.set_delegate(NULL); |
| 163 #endif | |
| 155 } | 164 } |
| 156 | 165 |
| 157 void TrayBubbleContentMask::OnPaintLayer(gfx::Canvas* canvas) { | 166 void TrayBubbleContentMask::OnPaintLayer(gfx::Canvas* canvas) { |
| 158 SkPath path; | 167 SkPath path; |
| 159 path.addRoundRect(gfx::RectToSkRect(gfx::Rect(layer()->bounds().size())), | 168 path.addRoundRect(gfx::RectToSkRect(gfx::Rect(layer()->bounds().size())), |
| 160 corner_radius_, corner_radius_); | 169 corner_radius_, corner_radius_); |
| 161 SkPaint paint; | 170 SkPaint paint; |
| 162 paint.setAlpha(255); | 171 paint.setAlpha(255); |
| 163 paint.setStyle(SkPaint::kFill_Style); | 172 paint.setStyle(SkPaint::kFill_Style); |
| 164 canvas->DrawPath(path, paint); | 173 canvas->DrawPath(path, paint); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 : anchor_type(anchor_type), | 235 : anchor_type(anchor_type), |
| 227 anchor_alignment(anchor_alignment), | 236 anchor_alignment(anchor_alignment), |
| 228 min_width(min_width), | 237 min_width(min_width), |
| 229 max_width(max_width), | 238 max_width(max_width), |
| 230 max_height(0), | 239 max_height(0), |
| 231 can_activate(false), | 240 can_activate(false), |
| 232 close_on_deactivate(true), | 241 close_on_deactivate(true), |
| 233 arrow_color(SK_ColorBLACK), | 242 arrow_color(SK_ColorBLACK), |
| 234 arrow_location(views::BubbleBorder::NONE), | 243 arrow_location(views::BubbleBorder::NONE), |
| 235 arrow_offset(kArrowDefaultOffset), | 244 arrow_offset(kArrowDefaultOffset), |
| 236 shadow(views::BubbleBorder::BIG_SHADOW) { | 245 shadow(views::BubbleBorder::BIG_SHADOW), |
| 246 arrow_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE) { | |
| 237 } | 247 } |
| 238 | 248 |
| 239 // static | 249 // static |
| 240 TrayBubbleView* TrayBubbleView::Create(gfx::NativeView parent_window, | 250 TrayBubbleView* TrayBubbleView::Create(gfx::NativeView parent_window, |
| 241 views::View* anchor, | 251 views::View* anchor, |
| 242 Delegate* delegate, | 252 Delegate* delegate, |
| 243 InitParams* init_params) { | 253 InitParams* init_params) { |
| 244 // Set arrow_location here so that it can be passed correctly to the | 254 // Set arrow_location here so that it can be passed correctly to the |
| 245 // BubbleView constructor. | 255 // BubbleView constructor. |
| 246 if (init_params->anchor_type == ANCHOR_TYPE_TRAY) { | 256 if (init_params->anchor_type == ANCHOR_TYPE_TRAY) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 } | 296 } |
| 287 | 297 |
| 288 TrayBubbleView::~TrayBubbleView() { | 298 TrayBubbleView::~TrayBubbleView() { |
| 289 // Inform host items (models) that their views are being destroyed. | 299 // Inform host items (models) that their views are being destroyed. |
| 290 if (delegate_) | 300 if (delegate_) |
| 291 delegate_->BubbleViewDestroyed(); | 301 delegate_->BubbleViewDestroyed(); |
| 292 } | 302 } |
| 293 | 303 |
| 294 void TrayBubbleView::InitializeAndShowBubble() { | 304 void TrayBubbleView::InitializeAndShowBubble() { |
| 295 // Must occur after call to BubbleDelegateView::CreateBubble(). | 305 // Must occur after call to BubbleDelegateView::CreateBubble(). |
| 296 SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | 306 SetAlignment(params_.arrow_alignment); |
| 297 bubble_border_->UpdateArrowOffset(); | 307 bubble_border_->UpdateArrowOffset(); |
| 298 | 308 |
| 299 if (get_use_acceleration_when_possible()) | 309 if (get_use_acceleration_when_possible()) |
| 300 layer()->parent()->SetMaskLayer(bubble_content_mask_->layer()); | 310 layer()->parent()->SetMaskLayer(bubble_content_mask_->layer()); |
| 301 | 311 |
| 302 Show(); | 312 Show(); |
| 303 UpdateBubble(); | 313 UpdateBubble(); |
| 304 } | 314 } |
| 305 | 315 |
| 306 void TrayBubbleView::UpdateBubble() { | 316 void TrayBubbleView::UpdateBubble() { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 views::View* parent, | 417 views::View* parent, |
| 408 views::View* child) { | 418 views::View* child) { |
| 409 if (get_use_acceleration_when_possible() && is_add && child == this) { | 419 if (get_use_acceleration_when_possible() && is_add && child == this) { |
| 410 parent->SetPaintToLayer(true); | 420 parent->SetPaintToLayer(true); |
| 411 parent->SetFillsBoundsOpaquely(true); | 421 parent->SetFillsBoundsOpaquely(true); |
| 412 parent->layer()->SetMasksToBounds(true); | 422 parent->layer()->SetMasksToBounds(true); |
| 413 } | 423 } |
| 414 } | 424 } |
| 415 | 425 |
| 416 } // namespace views | 426 } // namespace views |
| OLD | NEW |