Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2647)

Unified Diff: ash/system/tray/system_tray_bubble_view.cc

Issue 10514008: Add WebNotificationTray (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ash/system/tray/system_tray_bubble_view.h ('k') | ash/system/tray/system_tray_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ash/system/tray/system_tray_bubble_view.cc
diff --git a/ash/system/tray/system_tray_bubble_view.cc b/ash/system/tray/system_tray_bubble_view.cc
new file mode 100644
index 0000000000000000000000000000000000000000..33a5527d8e30a4ba923c3525f122644a094b2570
--- /dev/null
+++ b/ash/system/tray/system_tray_bubble_view.cc
@@ -0,0 +1,299 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/system/tray/system_tray_bubble_view.h"
+
+#include "ash/shell.h"
+#include "ash/shell_window_ids.h"
+#include "ash/system/tray/tray_constants.h"
+#include "ash/wm/shelf_layout_manager.h"
+#include "grit/ash_strings.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/effects/SkBlurImageFilter.h"
+#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/layout/box_layout.h"
+
+namespace ash {
+
+namespace {
+
+const int kShadowThickness = 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 kArrowPaddingFromBottom = 17;
+
+const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0);
+
+void DrawBlurredShadowAroundView(gfx::Canvas* canvas,
+ int top,
+ int bottom,
+ int width,
+ const gfx::Insets& inset) {
+ SkPath path;
+ path.incReserve(4);
+ path.moveTo(SkIntToScalar(inset.left() + kShadowThickness),
+ SkIntToScalar(top + kShadowThickness + 1));
+ path.lineTo(SkIntToScalar(inset.left() + kShadowThickness),
+ SkIntToScalar(bottom));
+ path.lineTo(SkIntToScalar(width),
+ SkIntToScalar(bottom));
+ path.lineTo(SkIntToScalar(width),
+ SkIntToScalar(top + kShadowThickness + 1));
+
+ SkPaint paint;
+ paint.setColor(kShadowColor);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ paint.setStrokeWidth(SkIntToScalar(3));
+ paint.setImageFilter(new SkBlurImageFilter(
+ SkIntToScalar(3), SkIntToScalar(3)))->unref();
+ canvas->sk_canvas()->drawPath(path, paint);
+}
+
+class SystemTrayBubbleBorder : public views::BubbleBorder {
+ public:
+ SystemTrayBubbleBorder(views::View* owner,
+ views::BubbleBorder::ArrowLocation arrow_location,
+ int arrow_offset)
+ : views::BubbleBorder(arrow_location,
+ views::BubbleBorder::NO_SHADOW),
+ owner_(owner),
+ arrow_offset_(arrow_offset) {
+ set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
+ }
+
+ virtual ~SystemTrayBubbleBorder() {}
+
+ private:
+ // Overridden from views::BubbleBorder.
+ // Override views::BubbleBorder to set the bubble on top of the anchor when
+ // it has no arrow.
+ virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
+ const gfx::Size& contents_size) const OVERRIDE {
+ if (arrow_location() != NONE) {
+ return views::BubbleBorder::GetBounds(position_relative_to,
+ contents_size);
+ }
+
+ gfx::Size border_size(contents_size);
+ gfx::Insets insets;
+ GetInsets(&insets);
+ border_size.Enlarge(insets.width(), insets.height());
+
+ const int kArrowOverlap = 3;
+ int x = position_relative_to.x() +
+ position_relative_to.width() / 2 - border_size.width() / 2;
+ // Position the bubble on top of the anchor.
+ int y = position_relative_to.y() +
+ kArrowOverlap - border_size.height();
+ return gfx::Rect(x, y, border_size.width(), border_size.height());
+ }
+
+ // Overridden from views::Border.
+ virtual void Paint(const views::View& view,
+ gfx::Canvas* canvas) const OVERRIDE {
+ gfx::Insets inset;
+ GetInsets(&inset);
+ DrawBlurredShadowAroundView(canvas, 0, owner_->height(), owner_->width(),
+ inset);
+
+ // Draw the bottom line.
+ int y = owner_->height() + 1;
+ canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(),
+ kBottomLineHeight), kBorderDarkColor);
+
+ if (!Shell::GetInstance()->shelf()->IsVisible() ||
+ arrow_location() == views::BubbleBorder::NONE)
+ return;
+
+ // Draw the arrow after drawing child borders, so that the arrow can cover
+ // the its overlap section with child border.
+ SkPath path;
+ path.incReserve(4);
+ if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) {
+ int tip_x = base::i18n::IsRTL() ? arrow_offset_ :
+ owner_->width() - arrow_offset_;
+ tip_x = std::min(std::max(kArrowWidth / 2, tip_x),
+ owner_->width() - kArrowWidth / 2);
+ int left_base_x = tip_x - kArrowWidth / 2;
+ int left_base_y = y;
+ int tip_y = left_base_y + kArrowHeight;
+ 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 {
+ int tip_y = y - arrow_offset_;
+ tip_y = std::min(std::max(kArrowWidth / 2, tip_y),
+ owner_->height() - kArrowWidth / 2);
+ int top_base_y = tip_y - kArrowWidth / 2;
+ int top_base_x, tip_x;
+ if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) {
+ top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset;
+ tip_x = top_base_x - kArrowHeight;
+ } else {
+ DCHECK(arrow_location() == views::BubbleBorder::RIGHT_BOTTOM);
+ top_base_x = inset.left() + owner_->width() -
+ kSystemTrayBubbleHorizontalInset;
+ tip_x = top_base_x + kArrowHeight;
+ }
+ 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);
+
+ // Now draw the arrow border.
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setColor(kBorderDarkColor);
+ canvas->DrawPath(path, paint);
+
+ }
+
+ views::View* owner_;
+ const int arrow_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBorder);
+};
+
+} // namespace
+
+namespace internal {
+
+SystemTrayBubbleView::SystemTrayBubbleView(
+ views::View* anchor,
+ views::BubbleBorder::ArrowLocation arrow_location,
+ Host* host,
+ bool can_activate)
+ : views::BubbleDelegateView(anchor, arrow_location),
+ host_(host),
+ can_activate_(can_activate),
+ max_height_(0),
+ bubble_width_(kTrayPopupWidth) {
+ set_margin(0);
+ set_parent_window(ash::Shell::GetInstance()->GetContainer(
+ ash::internal::kShellWindowId_SettingBubbleContainer));
+ set_notify_enter_exit_on_child(true);
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(true);
+}
+
+SystemTrayBubbleView::~SystemTrayBubbleView() {
+ // Inform host items (models) that their views are being destroyed.
+ if (host_)
+ host_->BubbleViewDestroyed();
+}
+
+void SystemTrayBubbleView::SetBubbleBorder(int arrow_offset) {
+ SystemTrayBubbleBorder* bubble_border = new SystemTrayBubbleBorder(
+ this, arrow_location(), arrow_offset);
+ GetBubbleFrameView()->SetBubbleBorder(bubble_border);
+ // Recalculate with new border.
+ SizeToContents();
+}
+
+void SystemTrayBubbleView::UpdateAnchor() {
+ SizeToContents();
+ GetWidget()->GetRootView()->SchedulePaint();
+}
+
+void SystemTrayBubbleView::SetMaxHeight(int height) {
+ max_height_ = height;
+ if (GetWidget())
+ SizeToContents();
+}
+
+void SystemTrayBubbleView::Init() {
+ views::BoxLayout* layout =
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0);
+ layout->set_spread_blank_space(true);
+ SetLayoutManager(layout);
+ 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() ? kPaddingFromRightEdgeOfScreenBottomAlignment :
+ rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment,
+ rect.height() - kPaddingFromBottomOfScreenBottomAlignment,
+ 0, 0);
+ }
+ return rect;
+}
+
+gfx::Rect SystemTrayBubbleView::GetBubbleBounds() {
+ // Same as BubbleDelegateView implementation, but don't try mirroring.
+ return GetBubbleFrameView()->GetUpdatedWindowBounds(GetAnchorRect(),
+ GetPreferredSize(), false /*try_mirroring_arrow*/);
+}
+
+bool SystemTrayBubbleView::CanActivate() const {
+ return can_activate_;
+}
+
+gfx::Size SystemTrayBubbleView::GetPreferredSize() {
+ gfx::Size size = views::BubbleDelegateView::GetPreferredSize();
+ int height = size.height();
+ if (max_height_ != 0 && height > max_height_)
+ height = max_height_;
+ return gfx::Size(bubble_width_, height);
+}
+
+void SystemTrayBubbleView::OnMouseEntered(const views::MouseEvent& event) {
+ if (host_)
+ host_->OnMouseEnteredView();
+}
+
+void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) {
+ if (host_)
+ host_->OnMouseExitedView();
+}
+
+void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) {
+ if (can_activate_) {
+ state->role = ui::AccessibilityTypes::ROLE_WINDOW;
+ state->name = l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME);
+ }
+}
+
+void SystemTrayBubbleView::ChildPreferredSizeChanged(View* child) {
+ SizeToContents();
+}
+
+void SystemTrayBubbleView::ViewHierarchyChanged(bool is_add,
+ views::View* parent,
+ views::View* child) {
+ if (is_add && child == this) {
+ parent->SetPaintToLayer(true);
+ parent->SetFillsBoundsOpaquely(true);
+ parent->layer()->SetMasksToBounds(true);
+ }
+}
+
+} // namespace internal
+} // namespace ash
« no previous file with comments | « ash/system/tray/system_tray_bubble_view.h ('k') | ash/system/tray/system_tray_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698