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 "third_party/skia/include/core/SkCanvas.h" | 7 #include "third_party/skia/include/core/SkCanvas.h" |
| 8 #include "third_party/skia/include/core/SkColor.h" | 8 #include "third_party/skia/include/core/SkColor.h" |
| 9 #include "third_party/skia/include/core/SkPaint.h" | 9 #include "third_party/skia/include/core/SkPaint.h" |
| 10 #include "third_party/skia/include/core/SkPath.h" | 10 #include "third_party/skia/include/core/SkPath.h" |
| 11 #include "third_party/skia/include/effects/SkBlurImageFilter.h" | 11 #include "third_party/skia/include/effects/SkBlurImageFilter.h" |
| 12 #include "ui/base/accessibility/accessible_view_state.h" | 12 #include "ui/base/accessibility/accessible_view_state.h" |
| 13 #include "ui/base/events/event.h" | 13 #include "ui/base/events/event.h" |
| 14 #include "ui/base/l10n/l10n_util.h" | 14 #include "ui/base/l10n/l10n_util.h" |
| 15 #include "ui/gfx/canvas.h" | 15 #include "ui/gfx/canvas.h" |
| 16 #include "ui/gfx/insets.h" | 16 #include "ui/gfx/insets.h" |
| 17 #include "ui/gfx/path.h" | 17 #include "ui/gfx/path.h" |
| 18 #include "ui/gfx/rect.h" | |
| 18 #include "ui/gfx/skia_util.h" | 19 #include "ui/gfx/skia_util.h" |
| 19 #include "ui/views/bubble/bubble_frame_view.h" | 20 #include "ui/views/bubble/bubble_frame_view.h" |
| 20 #include "ui/views/layout/box_layout.h" | 21 #include "ui/views/layout/box_layout.h" |
| 21 #include "ui/views/widget/widget.h" | 22 #include "ui/views/widget/widget.h" |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 // Inset the arrow a bit from the edge. | 26 // Inset the arrow a bit from the edge. |
| 26 const int kArrowMinOffset = 20; | 27 const int kArrowMinOffset = 20; |
| 27 const int kBubbleSpacing = 20; | 28 const int kBubbleSpacing = 20; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 } | 111 } |
| 111 | 112 |
| 112 private: | 113 private: |
| 113 views::View* owner_; | 114 views::View* owner_; |
| 114 views::View* anchor_; | 115 views::View* anchor_; |
| 115 const int tray_arrow_offset_; | 116 const int tray_arrow_offset_; |
| 116 | 117 |
| 117 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); | 118 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); |
| 118 }; | 119 }; |
| 119 | 120 |
| 120 // Custom background for TrayBubbleView. Fills in the top and bottom margins | 121 // This mask layer clips the bubble's content so that it does not overwrite the |
| 121 // with appropriate background colors without overwriting the rounded corners. | 122 // rounded bubble corners. |
| 122 class TrayBubbleBackground : public views::Background { | 123 // TODO(miket): This does not work on Windows. Implement layer masking or |
| 124 // alternate solutions if the TrayBubbleView is needed there in the future. | |
| 125 class TrayBubbleContentMask : public ui::Layer, public ui::LayerDelegate { | |
|
msw
2012/11/12 19:15:02
Include layer.h and layer_delegate.h
bartfab (slow)
2012/11/13 09:58:54
Done.
| |
| 123 public: | 126 public: |
| 124 explicit TrayBubbleBackground(views::BubbleBorder* border, | 127 TrayBubbleContentMask(views::BubbleBorder* border) |
|
msw
2012/11/12 19:15:02
nit: |border| is only used for its corner radius,
bartfab (slow)
2012/11/13 09:58:54
Done.
| |
| 125 SkColor top_color, | 128 : Layer(ui::LAYER_TEXTURED), |
| 126 SkColor bottom_color) | 129 radius_(SkIntToScalar(border->GetBorderCornerRadius() - 1)) { |
| 127 : border_(border), | 130 set_delegate(this); |
| 128 top_color_(top_color), | |
| 129 bottom_color_(bottom_color), | |
| 130 radius_(SkIntToScalar(border->GetBorderCornerRadius() - 1)) { | |
| 131 } | 131 } |
| 132 | 132 |
| 133 SkScalar radius() const { return radius_; } | 133 // Overridden from LayerDelegate: |
| 134 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE { | |
| 135 SkPath path; | |
| 136 path.addRoundRect(gfx::RectToSkRect(gfx::Rect(bounds().size())), | |
| 137 radius_, radius_); | |
| 138 SkPaint paint; | |
| 139 paint.setAlpha(255); | |
| 140 paint.setStyle(SkPaint::kFill_Style); | |
| 141 canvas->DrawPath(path, paint); | |
| 142 } | |
| 134 | 143 |
| 135 // Overridden from Background: | 144 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE { |
|
msw
2012/11/12 19:15:02
Both super classes have a function with this signa
bartfab (slow)
2012/11/13 09:58:54
The implementation of OnDeviceScaleFactorChanged a
| |
| 136 virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { | 145 Layer::OnDeviceScaleFactorChanged(device_scale_factor); |
| 137 canvas->Save(); | 146 } |
| 138 | 147 |
| 139 // Set a clip mask for the bubble's rounded corners. | 148 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE { |
| 140 gfx::Rect bounds(view->GetContentsBounds()); | 149 return base::Closure(); |
| 141 const int border_thickness(border_->GetBorderThickness()); | |
| 142 bounds.Inset(-border_thickness, -border_thickness); | |
| 143 SkPath path; | |
| 144 path.addRoundRect(gfx::RectToSkRect(bounds), radius_, radius_); | |
| 145 canvas->ClipPath(path); | |
| 146 | |
| 147 // Paint the header and footer (assumes the bubble contents fill in their | |
| 148 // own backgrounds). | |
| 149 SkPaint paint; | |
| 150 paint.setStyle(SkPaint::kFill_Style); | |
| 151 | |
| 152 gfx::Rect top_rect(bounds); | |
| 153 top_rect.set_height(radius_); | |
| 154 paint.setColor(top_color_); | |
| 155 canvas->DrawRect(top_rect, paint); | |
| 156 | |
| 157 gfx::Rect bottom_rect(bounds); | |
| 158 bottom_rect.set_y(bounds.y() + (bounds.height() - radius_)); | |
| 159 bottom_rect.set_height(radius_); | |
| 160 paint.setColor(bottom_color_); | |
| 161 canvas->DrawRect(bottom_rect, paint); | |
| 162 | |
| 163 canvas->Restore(); | |
| 164 } | 150 } |
| 165 | 151 |
| 166 private: | 152 private: |
| 167 views::BubbleBorder* border_; | |
| 168 SkColor top_color_; | |
| 169 SkColor bottom_color_; | |
| 170 SkScalar radius_; | 153 SkScalar radius_; |
| 171 | 154 |
| 172 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBackground); | 155 DISALLOW_COPY_AND_ASSIGN(TrayBubbleContentMask); |
| 173 }; | 156 }; |
| 174 | 157 |
| 175 // Custom layout for the bubble-view. Does the default box-layout if there is | 158 // Custom layout for the bubble-view. Does the default box-layout if there is |
| 176 // enough height. Otherwise, makes sure the bottom rows are visible. | 159 // enough height. Otherwise, makes sure the bottom rows are visible. |
| 177 class BottomAlignedBoxLayout : public views::BoxLayout { | 160 class BottomAlignedBoxLayout : public views::BoxLayout { |
| 178 public: | 161 public: |
| 179 explicit BottomAlignedBoxLayout(TrayBubbleView* bubble_view) | 162 explicit BottomAlignedBoxLayout(TrayBubbleView* bubble_view) |
| 180 : views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0), | 163 : views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0), |
| 181 bubble_view_(bubble_view) { | 164 bubble_view_(bubble_view) { |
| 182 } | 165 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 205 } | 188 } |
| 206 | 189 |
| 207 TrayBubbleView* bubble_view_; | 190 TrayBubbleView* bubble_view_; |
| 208 | 191 |
| 209 DISALLOW_COPY_AND_ASSIGN(BottomAlignedBoxLayout); | 192 DISALLOW_COPY_AND_ASSIGN(BottomAlignedBoxLayout); |
| 210 }; | 193 }; |
| 211 | 194 |
| 212 } // namespace internal | 195 } // namespace internal |
| 213 | 196 |
| 214 using internal::TrayBubbleBorder; | 197 using internal::TrayBubbleBorder; |
| 215 using internal::TrayBubbleBackground; | 198 using internal::TrayBubbleContentMask; |
| 216 using internal::BottomAlignedBoxLayout; | 199 using internal::BottomAlignedBoxLayout; |
| 217 | 200 |
| 218 // static | 201 // static |
| 219 const int TrayBubbleView::InitParams::kArrowDefaultOffset = -1; | 202 const int TrayBubbleView::InitParams::kArrowDefaultOffset = -1; |
| 220 | 203 |
| 221 TrayBubbleView::InitParams::InitParams(AnchorType anchor_type, | 204 TrayBubbleView::InitParams::InitParams(AnchorType anchor_type, |
| 222 AnchorAlignment anchor_alignment, | 205 AnchorAlignment anchor_alignment, |
| 223 int bubble_width) | 206 int bubble_width) |
| 224 : anchor_type(anchor_type), | 207 : anchor_type(anchor_type), |
| 225 anchor_alignment(anchor_alignment), | 208 anchor_alignment(anchor_alignment), |
| 226 bubble_width(bubble_width), | 209 bubble_width(bubble_width), |
| 227 max_height(0), | 210 max_height(0), |
| 228 can_activate(false), | 211 can_activate(false), |
| 229 close_on_deactivate(true), | 212 close_on_deactivate(true), |
| 230 top_color(SK_ColorBLACK), | |
| 231 arrow_color(SK_ColorBLACK), | 213 arrow_color(SK_ColorBLACK), |
| 232 arrow_location(views::BubbleBorder::NONE), | 214 arrow_location(views::BubbleBorder::NONE), |
| 233 arrow_offset(kArrowDefaultOffset), | 215 arrow_offset(kArrowDefaultOffset), |
| 234 shadow(views::BubbleBorder::BIG_SHADOW) { | 216 shadow(views::BubbleBorder::BIG_SHADOW) { |
| 235 } | 217 } |
| 236 | 218 |
| 237 // static | 219 // static |
| 238 TrayBubbleView* TrayBubbleView::Create(gfx::NativeView parent_window, | 220 TrayBubbleView* TrayBubbleView::Create(gfx::NativeView parent_window, |
| 239 views::View* anchor, | 221 views::View* anchor, |
| 240 Delegate* delegate, | 222 Delegate* delegate, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 258 } | 240 } |
| 259 | 241 |
| 260 TrayBubbleView::TrayBubbleView(gfx::NativeView parent_window, | 242 TrayBubbleView::TrayBubbleView(gfx::NativeView parent_window, |
| 261 views::View* anchor, | 243 views::View* anchor, |
| 262 Delegate* delegate, | 244 Delegate* delegate, |
| 263 const InitParams& init_params) | 245 const InitParams& init_params) |
| 264 : views::BubbleDelegateView(anchor, init_params.arrow_location), | 246 : views::BubbleDelegateView(anchor, init_params.arrow_location), |
| 265 params_(init_params), | 247 params_(init_params), |
| 266 delegate_(delegate), | 248 delegate_(delegate), |
| 267 bubble_border_(NULL), | 249 bubble_border_(NULL), |
| 268 bubble_background_(NULL), | |
| 269 is_gesture_dragging_(false) { | 250 is_gesture_dragging_(false) { |
| 270 set_parent_window(parent_window); | 251 set_parent_window(parent_window); |
| 271 set_notify_enter_exit_on_child(true); | 252 set_notify_enter_exit_on_child(true); |
| 272 set_close_on_deactivate(init_params.close_on_deactivate); | 253 set_close_on_deactivate(init_params.close_on_deactivate); |
| 254 set_margins(gfx::Insets()); | |
| 273 SetPaintToLayer(true); | 255 SetPaintToLayer(true); |
| 274 SetFillsBoundsOpaquely(true); | 256 SetFillsBoundsOpaquely(true); |
| 275 | 257 |
| 276 bubble_border_ = new TrayBubbleBorder(this, anchor_view(), params_); | 258 bubble_border_ = new TrayBubbleBorder(this, anchor_view(), params_); |
| 277 | 259 |
| 278 bubble_background_ = new TrayBubbleBackground( | 260 bubble_content_mask_.reset(new TrayBubbleContentMask(bubble_border_)); |
| 279 bubble_border_, init_params.top_color, init_params.arrow_color); | |
| 280 | |
| 281 // Inset the view on the top and bottom by the corner radius to avoid drawing | |
| 282 // over the the bubble corners. | |
| 283 const int radius = bubble_background_->radius(); | |
| 284 set_margins(gfx::Insets(radius, 0, radius, 0)); | |
| 285 } | 261 } |
| 286 | 262 |
| 287 TrayBubbleView::~TrayBubbleView() { | 263 TrayBubbleView::~TrayBubbleView() { |
| 288 // Inform host items (models) that their views are being destroyed. | 264 // Inform host items (models) that their views are being destroyed. |
| 289 if (delegate_) | 265 if (delegate_) |
| 290 delegate_->BubbleViewDestroyed(); | 266 delegate_->BubbleViewDestroyed(); |
| 291 } | 267 } |
| 292 | 268 |
| 293 void TrayBubbleView::InitializeAndShowBubble() { | 269 void TrayBubbleView::InitializeAndShowBubble() { |
| 294 // Must occur after call to BubbleDelegateView::CreateBubble(). | 270 // Must occur after call to BubbleDelegateView::CreateBubble(). |
| 295 SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | 271 SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
| 296 bubble_border_->UpdateArrowOffset(); | 272 bubble_border_->UpdateArrowOffset(); |
| 297 | 273 |
| 274 layer()->parent()->SetMaskLayer(bubble_content_mask_.get()); | |
| 275 | |
| 298 Show(); | 276 Show(); |
| 299 UpdateBubble(); | 277 UpdateBubble(); |
| 300 } | 278 } |
| 301 | 279 |
| 302 void TrayBubbleView::UpdateBubble() { | 280 void TrayBubbleView::UpdateBubble() { |
| 303 SizeToContents(); | 281 SizeToContents(); |
| 282 bubble_content_mask_->SetBounds(layer()->bounds()); | |
| 304 GetWidget()->GetRootView()->SchedulePaint(); | 283 GetWidget()->GetRootView()->SchedulePaint(); |
| 305 } | 284 } |
| 306 | 285 |
| 307 void TrayBubbleView::SetMaxHeight(int height) { | 286 void TrayBubbleView::SetMaxHeight(int height) { |
| 308 params_.max_height = height; | 287 params_.max_height = height; |
| 309 if (GetWidget()) | 288 if (GetWidget()) |
| 310 SizeToContents(); | 289 SizeToContents(); |
| 311 } | 290 } |
| 312 | 291 |
| 313 void TrayBubbleView::SetPaintArrow(bool paint_arrow) { | 292 void TrayBubbleView::SetPaintArrow(bool paint_arrow) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 329 return gfx::Rect(); | 308 return gfx::Rect(); |
| 330 return delegate_->GetAnchorRect(anchor_widget(), | 309 return delegate_->GetAnchorRect(anchor_widget(), |
| 331 params_.anchor_type, | 310 params_.anchor_type, |
| 332 params_.anchor_alignment); | 311 params_.anchor_alignment); |
| 333 } | 312 } |
| 334 | 313 |
| 335 bool TrayBubbleView::CanActivate() const { | 314 bool TrayBubbleView::CanActivate() const { |
| 336 return params_.can_activate; | 315 return params_.can_activate; |
| 337 } | 316 } |
| 338 | 317 |
| 339 // Overridden to create BubbleFrameView and set a custom border and background. | 318 // Overridden to create BubbleFrameView and set a custom border. |
| 340 views::NonClientFrameView* TrayBubbleView::CreateNonClientFrameView( | 319 views::NonClientFrameView* TrayBubbleView::CreateNonClientFrameView( |
| 341 views::Widget* widget) { | 320 views::Widget* widget) { |
| 342 views::BubbleFrameView* bubble_frame_view = | 321 views::BubbleFrameView* bubble_frame_view = |
| 343 new views::BubbleFrameView(margins(), bubble_border_); | 322 new views::BubbleFrameView(margins(), bubble_border_); |
| 344 bubble_frame_view->set_background(bubble_background_); | |
| 345 return bubble_frame_view; | 323 return bubble_frame_view; |
| 346 } | 324 } |
| 347 | 325 |
| 348 bool TrayBubbleView::WidgetHasHitTestMask() const { | 326 bool TrayBubbleView::WidgetHasHitTestMask() const { |
| 349 return true; | 327 return true; |
| 350 } | 328 } |
| 351 | 329 |
| 352 void TrayBubbleView::GetWidgetHitTestMask(gfx::Path* mask) const { | 330 void TrayBubbleView::GetWidgetHitTestMask(gfx::Path* mask) const { |
| 353 DCHECK(mask); | 331 DCHECK(mask); |
| 354 mask->addRect(gfx::RectToSkRect(GetBubbleFrameView()->GetContentsBounds())); | 332 mask->addRect(gfx::RectToSkRect(GetBubbleFrameView()->GetContentsBounds())); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 views::View* parent, | 365 views::View* parent, |
| 388 views::View* child) { | 366 views::View* child) { |
| 389 if (is_add && child == this) { | 367 if (is_add && child == this) { |
| 390 parent->SetPaintToLayer(true); | 368 parent->SetPaintToLayer(true); |
| 391 parent->SetFillsBoundsOpaquely(true); | 369 parent->SetFillsBoundsOpaquely(true); |
| 392 parent->layer()->SetMasksToBounds(true); | 370 parent->layer()->SetMasksToBounds(true); |
| 393 } | 371 } |
| 394 } | 372 } |
| 395 | 373 |
| 396 } // namespace views | 374 } // namespace views |
| OLD | NEW |