Chromium Code Reviews| Index: ash/system/tray/system_tray_bubble.cc |
| diff --git a/ash/system/tray/system_tray_bubble.cc b/ash/system/tray/system_tray_bubble.cc |
| index 7145615c1cc0a4fe8ef09f0696fd2e7dc954d2cf..4b1a26d5495d694aa1b1e0ebfe15cc3c1f3d0d61 100644 |
| --- a/ash/system/tray/system_tray_bubble.cc |
| +++ b/ash/system/tray/system_tray_bubble.cc |
| @@ -34,12 +34,15 @@ namespace { |
| const int kShadowThickness = 4; |
| -const int kLeftPadding = 4; |
| const int kBottomLineHeight = 1; |
| +const int kSystemTrayBubbleHorizontalInset = 1; |
| +const int kSystemTrayBubbleVerticalInset = 1; |
| + |
| const int kArrowHeight = 10; |
| const int kArrowWidth = 20; |
| const int kArrowPaddingFromRight = 20; |
| +const int kMinArrowOffset = 12; |
| const int kAnimationDurationForPopupMS = 200; |
| @@ -128,20 +131,31 @@ class TrayPopupItemContainer : public views::View { |
| DISALLOW_COPY_AND_ASSIGN(TrayPopupItemContainer); |
| }; |
| -class SystemTrayBubbleBackground : public views::Background { |
| +class SystemTrayBubbleBorder : public views::BubbleBorder { |
| public: |
| - explicit SystemTrayBubbleBackground(views::View* owner) |
| - : owner_(owner) { |
| + SystemTrayBubbleBorder(views::View* owner, |
| + views::BubbleBorder::ArrowLocation arrow_location, |
| + int arrow_offset) |
| + : views::BubbleBorder(arrow_location, |
| + views::BubbleBorder::NO_SHADOW), |
| + owner_(owner), |
| + arrow_offset_(std::max(arrow_offset, kMinArrowOffset)) { |
| + set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
| } |
| - virtual ~SystemTrayBubbleBackground() {} |
| + virtual ~SystemTrayBubbleBorder() {} |
| private: |
| - // Overridden from views::Background. |
| - virtual void Paint(gfx::Canvas* canvas, views::View* view) const OVERRIDE { |
| + void PaintChildBorder(gfx::Canvas* canvas) const { |
| + gfx::Insets insets; |
| + GetInsets(&insets); |
| + canvas->Save(); |
| + canvas->Translate(gfx::Point(insets.left(), insets.top())); |
| views::View* last_view = NULL; |
| for (int i = 0; i < owner_->child_count(); i++) { |
| views::View* v = owner_->child_at(i); |
| + if (!v->visible()) |
| + continue; |
| if (!v->border()) { |
| canvas->DrawLine(gfx::Point(v->x(), v->y() - 1), |
| @@ -162,34 +176,9 @@ class SystemTrayBubbleBackground : public views::Background { |
| kBorderDarkColor); |
| last_view = v; |
| } |
| + canvas->Restore(); |
| } |
| - views::View* owner_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBackground); |
| -}; |
| - |
| -class SystemTrayBubbleBorder : public views::BubbleBorder { |
| - public: |
| - enum ArrowType { |
| - ARROW_TYPE_NONE, |
| - ARROW_TYPE_BOTTOM, |
| - }; |
| - |
| - SystemTrayBubbleBorder(views::View* owner, |
| - ArrowType arrow_type, |
| - int arrow_offset) |
| - : views::BubbleBorder(views::BubbleBorder::BOTTOM_RIGHT, |
| - views::BubbleBorder::NO_SHADOW), |
| - owner_(owner), |
| - arrow_type_(arrow_type), |
| - arrow_offset_(arrow_offset) { |
| - set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
| - } |
| - |
| - virtual ~SystemTrayBubbleBorder() {} |
| - |
| - private: |
| // Overridden from views::Border. |
| virtual void Paint(const views::View& view, |
| gfx::Canvas* canvas) const OVERRIDE { |
| @@ -198,43 +187,67 @@ class SystemTrayBubbleBorder : public views::BubbleBorder { |
| DrawBlurredShadowAroundView(canvas, 0, owner_->height(), owner_->width(), |
| inset); |
| + PaintChildBorder(canvas); |
| + |
| // Draw the bottom line. |
| int y = owner_->height() + 1; |
| - canvas->FillRect(gfx::Rect(kLeftPadding, y, owner_->width(), |
| + canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(), |
| kBottomLineHeight), kBorderDarkColor); |
| - if (!Shell::GetInstance()->shelf()->IsVisible()) |
| + if (!Shell::GetInstance()->shelf()->IsVisible() || |
| + arrow_location() == views::BubbleBorder::NONE) |
| return; |
| - // Draw the arrow. |
| - if (arrow_type_ == ARROW_TYPE_BOTTOM) { |
| + // Draw the arrow after drawing child borders, so that the arrow can cover |
| + // the its overlap section with child border. |
| + SkPath path; |
| + if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) { |
| int tip_x = base::i18n::IsRTL() ? arrow_offset_ : |
| owner_->width() - arrow_offset_; |
| int left_base_x = tip_x - kArrowWidth / 2; |
| int left_base_y = y; |
| int tip_y = left_base_y + kArrowHeight; |
| - |
| - SkPath path; |
| path.incReserve(4); |
|
sadrul
2012/05/17 23:30:29
Move this line after line 203 and remove from othe
jennyz
2012/05/18 00:00:42
Done.
|
| path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); |
| path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); |
| path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), |
| SkIntToScalar(left_base_y)); |
| + } else if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) { |
| + int tip_y = y - arrow_offset_; |
| + int top_base_y = tip_y - kArrowWidth / 2; |
| + int top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset; |
| + int tip_x = top_base_x - kArrowHeight; |
| + path.incReserve(4); |
| + path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y)); |
| + path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); |
| + path.lineTo(SkIntToScalar(top_base_x), |
| + SkIntToScalar(top_base_y + kArrowWidth)); |
| + } else if (arrow_location() == views::BubbleBorder::RIGHT_BOTTOM){ |
| + int tip_y = y - arrow_offset_; |
|
sadrul
2012/05/17 23:30:29
spacing in this block seems off
jennyz
2012/05/18 00:00:42
Done.
|
| + int top_base_y = tip_y - kArrowWidth / 2; |
| + int top_base_x = inset.left() + owner_->width() - |
| + kSystemTrayBubbleHorizontalInset; |
| + int tip_x = top_base_x + kArrowHeight; |
| + path.incReserve(4); |
| + path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y)); |
| + path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); |
| + path.lineTo(SkIntToScalar(top_base_x), |
| + SkIntToScalar(top_base_y + kArrowWidth)); |
| + } |
| - SkPaint paint; |
| - paint.setStyle(SkPaint::kFill_Style); |
| - paint.setColor(kHeaderBackgroundColorDark); |
| - canvas->DrawPath(path, paint); |
| + SkPaint paint; |
| + paint.setStyle(SkPaint::kFill_Style); |
| + paint.setColor(kHeaderBackgroundColorDark); |
| + canvas->DrawPath(path, paint); |
| + |
| + // Now draw the arrow border. |
| + paint.setStyle(SkPaint::kStroke_Style); |
| + paint.setColor(kBorderDarkColor); |
| + canvas->DrawPath(path, paint); |
| - // Now draw the arrow border. |
| - paint.setStyle(SkPaint::kStroke_Style); |
| - paint.setColor(kBorderDarkColor); |
| - canvas->DrawPath(path, paint); |
| - } |
| } |
| views::View* owner_; |
| - ArrowType arrow_type_; |
| const int arrow_offset_; |
| DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBorder); |
| @@ -247,9 +260,10 @@ namespace internal { |
| // SystemTrayBubbleView |
| SystemTrayBubbleView::SystemTrayBubbleView(views::View* anchor, |
| - SystemTrayBubble* host, |
| - bool can_activate) |
| - : views::BubbleDelegateView(anchor, views::BubbleBorder::BOTTOM_RIGHT), |
| + views::BubbleBorder::ArrowLocation arrow_location, |
| + SystemTrayBubble* host, |
| + bool can_activate) |
| + : views::BubbleDelegateView(anchor, arrow_location), |
| host_(host), |
| can_activate_(can_activate) { |
| set_margin(0); |
| @@ -275,22 +289,27 @@ void SystemTrayBubbleView::UpdateAnchor() { |
| void SystemTrayBubbleView::Init() { |
| views::BoxLayout* layout = |
| - new views::BoxLayout(views::BoxLayout::kVertical, 1, 1, 1); |
| + new views::BoxLayout(views::BoxLayout::kVertical, |
| + kSystemTrayBubbleHorizontalInset, |
| + kSystemTrayBubbleVerticalInset, |
| + 1); |
| layout->set_spread_blank_space(true); |
| SetLayoutManager(layout); |
| - set_background(new SystemTrayBubbleBackground(this)); |
| + set_background(NULL); |
| } |
| gfx::Rect SystemTrayBubbleView::GetAnchorRect() { |
| gfx::Rect rect; |
| if (host_) |
| rect = host_->GetAnchorRect(); |
| + // TODO(jennyz): May need to add left/right alignment in the following code. |
| if (rect.IsEmpty()) { |
| rect = gfx::Screen::GetPrimaryMonitor().bounds(); |
| - rect = gfx::Rect(base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : |
| - rect.width() - kPaddingFromRightEdgeOfScreen, |
| - rect.height() - kPaddingFromBottomOfScreen, |
| - 0, 0); |
| + rect = gfx::Rect( |
| + base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : |
| + rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, |
| + rect.height() - kPaddingFromBottomOfScreenBottomAlignment, |
| + 0, 0); |
| } |
| return rect; |
| } |
| @@ -378,8 +397,20 @@ void SystemTrayBubble::UpdateView( |
| void SystemTrayBubble::InitView(const InitParams& init_params) { |
| DCHECK(bubble_view_ == NULL); |
| anchor_type_ = init_params.anchor_type; |
| + views::BubbleBorder::ArrowLocation arrow_location; |
| + if (anchor_type_ == ANCHOR_TYPE_TRAY) { |
| + if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
| + arrow_location = views::BubbleBorder::BOTTOM_RIGHT; |
| + } else if (tray_->shelf_alignment() == SHELF_ALIGNMENT_LEFT) { |
| + arrow_location = views::BubbleBorder::LEFT_BOTTOM; |
| + } else { |
| + arrow_location = views::BubbleBorder::RIGHT_BOTTOM; |
| + } |
| + } else { |
| + arrow_location = views::BubbleBorder::NONE; |
| + } |
| bubble_view_ = new SystemTrayBubbleView( |
| - init_params.anchor, this, init_params.can_activate); |
| + init_params.anchor, arrow_location, this, init_params.can_activate); |
| if (bubble_type_ == BUBBLE_TYPE_NOTIFICATION) |
| bubble_view_->set_close_on_deactivate(false); |
| @@ -391,14 +422,8 @@ void SystemTrayBubble::InitView(const InitParams& init_params) { |
| // Must occur after call to CreateBubble() |
| bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
| bubble_widget_->non_client_view()->frame_view()->set_background(NULL); |
| - SystemTrayBubbleBorder::ArrowType arrow_type; |
| - if (anchor_type_ == ANCHOR_TYPE_TRAY) |
| - arrow_type = SystemTrayBubbleBorder::ARROW_TYPE_BOTTOM; |
| - else |
| - arrow_type = SystemTrayBubbleBorder::ARROW_TYPE_NONE; |
| - |
| SystemTrayBubbleBorder* bubble_border = new SystemTrayBubbleBorder( |
| - bubble_view_, arrow_type, init_params.arrow_offset); |
| + bubble_view_, arrow_location, init_params.arrow_offset); |
| bubble_view_->SetBubbleBorder(bubble_border); |
| bubble_widget_->AddObserver(this); |
| @@ -423,12 +448,23 @@ gfx::Rect SystemTrayBubble::GetAnchorRect() const { |
| if (widget->IsVisible()) { |
| rect = widget->GetWindowScreenBounds(); |
| if (anchor_type_ == ANCHOR_TYPE_TRAY) { |
| - rect.Inset( |
| - base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreen : 0, |
| - 0, |
| - base::i18n::IsRTL() ? 0 : kPaddingFromRightEdgeOfScreen, |
| - kPaddingFromBottomOfScreen); |
| + if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
| + rect.Inset( |
| + base::i18n::IsRTL() ? |
| + kPaddingFromRightEdgeOfScreenBottomAlignment : 0, |
| + 0, |
| + base::i18n::IsRTL() ? |
| + 0 : kPaddingFromRightEdgeOfScreenBottomAlignment, |
| + kPaddingFromBottomOfScreenBottomAlignment); |
| + } else if (tray_->shelf_alignment() == SHELF_ALIGNMENT_LEFT) { |
| + rect.Inset(0, 0, kPaddingFromLeftEdgeOfScreenLeftAlignment, |
| + kPaddingFromBottomOfScreenVerticalAlignment); |
| + } else { |
| + rect.Inset(-kPaddingFromRightEdgeOfScreenRightAlignment, |
| + 0, 0, kPaddingFromBottomOfScreenVerticalAlignment); |
| + } |
| } else if (anchor_type_ == ANCHOR_TYPE_BUBBLE) { |
| + // TODO(jennyz): add left/right launcher support for notification bubble. |
| rect.Inset( |
| base::i18n::IsRTL() ? kShadowThickness - 1 : 0, |
| 0, |