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 "ash/system/tray/tray_bubble_view.h" | 5 #include "ash/system/tray/tray_bubble_view.h" |
| 6 | 6 |
| 7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
| 8 #include "ash/shell_window_ids.h" | 8 #include "ash/shell_window_ids.h" |
| 9 #include "ash/system/tray/tray_constants.h" | 9 #include "ash/system/tray/tray_constants.h" |
| 10 #include "ash/wm/shelf_layout_manager.h" | 10 #include "ash/wm/shelf_layout_manager.h" |
| 11 #include "ash/wm/window_animations.h" | |
| 11 #include "grit/ash_strings.h" | 12 #include "grit/ash_strings.h" |
| 12 #include "third_party/skia/include/core/SkCanvas.h" | 13 #include "third_party/skia/include/core/SkCanvas.h" |
| 13 #include "third_party/skia/include/core/SkColor.h" | 14 #include "third_party/skia/include/core/SkColor.h" |
| 14 #include "third_party/skia/include/core/SkPaint.h" | 15 #include "third_party/skia/include/core/SkPaint.h" |
| 15 #include "third_party/skia/include/core/SkPath.h" | 16 #include "third_party/skia/include/core/SkPath.h" |
| 16 #include "third_party/skia/include/effects/SkBlurImageFilter.h" | 17 #include "third_party/skia/include/effects/SkBlurImageFilter.h" |
| 17 #include "ui/aura/event.h" | 18 #include "ui/aura/event.h" |
| 18 #include "ui/aura/window.h" | 19 #include "ui/aura/window.h" |
| 19 #include "ui/base/accessibility/accessible_view_state.h" | 20 #include "ui/base/accessibility/accessible_view_state.h" |
| 20 #include "ui/base/l10n/l10n_util.h" | 21 #include "ui/base/l10n/l10n_util.h" |
| 21 #include "ui/gfx/canvas.h" | 22 #include "ui/gfx/canvas.h" |
| 22 #include "ui/gfx/insets.h" | 23 #include "ui/gfx/insets.h" |
| 23 #include "ui/gfx/screen.h" | 24 #include "ui/gfx/screen.h" |
| 24 #include "ui/views/bubble/bubble_frame_view.h" | 25 #include "ui/views/bubble/bubble_frame_view.h" |
| 25 #include "ui/views/layout/box_layout.h" | 26 #include "ui/views/layout/box_layout.h" |
| 26 | 27 |
| 27 namespace ash { | 28 namespace ash { |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 const int kShadowThickness = 4; | 32 const int kShadowThickness = 4; |
| 32 const int kBottomLineHeight = 1; | 33 const int kBottomLineHeight = 1; |
| 33 const int kSystemTrayBubbleHorizontalInset = 1; | 34 const int kSystemTrayBubbleHorizontalInset = 1; |
| 34 const int kSystemTrayBubbleVerticalInset = 1; | 35 const int kSystemTrayBubbleVerticalInset = 1; |
| 35 | 36 |
| 36 const int kArrowHeight = 10; | 37 const int kArrowHeight = 10; |
| 37 const int kArrowWidth = 20; | 38 const int kArrowWidth = 20; |
| 38 | 39 |
| 39 // Inset the arrow a bit from the edge. | 40 // Inset the arrow a bit from the edge. |
| 40 const int kArrowMinOffset = kArrowWidth / 2 + 4; | 41 const int kArrowEdgeMargin = 12; |
| 42 const int kArrowMinOffset = kArrowWidth / 2 + kArrowEdgeMargin; | |
| 41 | 43 |
| 42 const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0); | 44 const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0); |
| 43 | 45 |
| 46 const int kAnimationDurationForPopupMS = 200; | |
| 47 | |
| 44 void DrawBlurredShadowAroundView(gfx::Canvas* canvas, | 48 void DrawBlurredShadowAroundView(gfx::Canvas* canvas, |
| 45 int top, | 49 int top, |
| 46 int bottom, | 50 int bottom, |
| 47 int width, | 51 int width, |
| 48 const gfx::Insets& inset) { | 52 const gfx::Insets& inset) { |
| 49 SkPath path; | 53 SkPath path; |
| 50 path.incReserve(4); | 54 path.incReserve(4); |
| 51 path.moveTo(SkIntToScalar(inset.left() + kShadowThickness), | 55 path.moveTo(SkIntToScalar(inset.left() + kShadowThickness), |
| 52 SkIntToScalar(top + kShadowThickness + 1)); | 56 SkIntToScalar(top + kShadowThickness + 1)); |
| 53 path.lineTo(SkIntToScalar(inset.left() + kShadowThickness), | 57 path.lineTo(SkIntToScalar(inset.left() + kShadowThickness), |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 72 TrayBubbleBorder(views::View* owner, | 76 TrayBubbleBorder(views::View* owner, |
| 73 views::View* anchor, | 77 views::View* anchor, |
| 74 views::BubbleBorder::ArrowLocation arrow_location, | 78 views::BubbleBorder::ArrowLocation arrow_location, |
| 75 int arrow_offset) | 79 int arrow_offset) |
| 76 : views::BubbleBorder(arrow_location, | 80 : views::BubbleBorder(arrow_location, |
| 77 views::BubbleBorder::NO_SHADOW), | 81 views::BubbleBorder::NO_SHADOW), |
| 78 owner_(owner), | 82 owner_(owner), |
| 79 anchor_(anchor), | 83 anchor_(anchor), |
| 80 tray_arrow_offset_(arrow_offset) { | 84 tray_arrow_offset_(arrow_offset) { |
| 81 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | 85 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
| 86 // Normally all rendering is mirrored for RTL. This doesn't work correctly | |
| 87 // with status area bubbles, and would make Paint much more complex. | |
| 88 // Instead, set rtl_mirrored_ to false so that GetInsets() returns | |
| 89 // the unmirrored insets. | |
| 90 set_rtl_mirrored(false); | |
| 82 } | 91 } |
| 83 | 92 |
| 84 virtual ~TrayBubbleBorder() {} | 93 virtual ~TrayBubbleBorder() {} |
| 85 | 94 |
| 86 private: | |
| 87 views::Background* FindAppropriateBackground(views::View* view, | |
| 88 const gfx::Point& point) const { | |
| 89 views::Background* background = NULL; | |
| 90 views::View* target = view->GetEventHandlerForPoint(point); | |
| 91 for (; target && !background; target = target->parent()) | |
| 92 background = target->background(); | |
| 93 return background; | |
| 94 } | |
| 95 | |
| 96 // Overridden from views::BubbleBorder. | 95 // Overridden from views::BubbleBorder. |
| 97 // Override views::BubbleBorder to set the bubble on top of the anchor when | 96 // Override views::BubbleBorder to set the bubble on top of the anchor when |
| 98 // it has no arrow. | 97 // it has no arrow. |
| 99 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, | 98 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, |
| 100 const gfx::Size& contents_size) const OVERRIDE { | 99 const gfx::Size& contents_size) const OVERRIDE { |
| 101 if (arrow_location() != NONE) { | 100 if (arrow_location() != NONE) { |
| 102 return views::BubbleBorder::GetBounds(position_relative_to, | 101 return views::BubbleBorder::GetBounds(position_relative_to, |
| 103 contents_size); | 102 contents_size); |
| 104 } | 103 } |
| 105 | 104 |
| 106 gfx::Size border_size(contents_size); | 105 gfx::Size border_size(contents_size); |
| 107 gfx::Insets insets; | 106 gfx::Insets insets; |
| 108 GetInsets(&insets); | 107 GetInsets(&insets); |
| 109 border_size.Enlarge(insets.width(), insets.height()); | 108 border_size.Enlarge(insets.width(), insets.height()); |
| 110 | 109 |
| 111 const int kArrowOverlap = 3; | 110 const int kArrowOverlap = 3; |
| 112 int x = position_relative_to.x() + | 111 int x = position_relative_to.x() + |
| 113 position_relative_to.width() / 2 - border_size.width() / 2; | 112 position_relative_to.width() / 2 - border_size.width() / 2; |
| 114 // Position the bubble on top of the anchor. | 113 // Position the bubble on top of the anchor. |
| 115 int y = position_relative_to.y() + | 114 int y = position_relative_to.y() + |
| 116 kArrowOverlap - border_size.height(); | 115 kArrowOverlap - border_size.height(); |
| 117 return gfx::Rect(x, y, border_size.width(), border_size.height()); | 116 return gfx::Rect(x, y, border_size.width(), border_size.height()); |
| 118 } | 117 } |
| 119 | 118 |
| 120 // Overridden from views::Border. | 119 // Overridden from views::Border. |
| 121 virtual void Paint(const views::View& view, | 120 virtual void Paint(const views::View& view, |
| 122 gfx::Canvas* canvas) const OVERRIDE { | 121 gfx::Canvas* canvas) const OVERRIDE { |
| 123 gfx::Insets inset; | 122 gfx::Insets inset; |
| 124 GetInsets(&inset); | 123 // Get the unmirrored insets for the arrow location. |
| 124 GetInsetsForArrowLocation(&inset, arrow_location()); | |
| 125 DrawBlurredShadowAroundView( | 125 DrawBlurredShadowAroundView( |
| 126 canvas, 0, owner_->height(), owner_->width(), inset); | 126 canvas, 0, owner_->height(), owner_->width(), inset); |
| 127 | 127 |
| 128 // Draw the bottom line. | 128 // Draw the bottom line. |
| 129 int y = owner_->height() + inset.top(); | 129 int y = owner_->height() + inset.top(); |
| 130 canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(), | 130 canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(), |
| 131 kBottomLineHeight), kBorderDarkColor); | 131 kBottomLineHeight), kBorderDarkColor); |
| 132 | 132 |
| 133 if (!Shell::GetInstance()->shelf()->IsVisible() || | 133 if (!Shell::GetInstance()->shelf()->IsVisible() || |
| 134 arrow_location() == views::BubbleBorder::NONE) | 134 arrow_location() == views::BubbleBorder::NONE) |
| 135 return; | 135 return; |
| 136 | 136 |
| 137 gfx::Point arrow_reference; | 137 gfx::Point arrow_reference; |
| 138 | 138 |
| 139 // Draw the arrow after drawing child borders, so that the arrow can cover | 139 // Draw the arrow after drawing child borders, so that the arrow can cover |
|
msw
2012/07/24 00:32:43
This should be calling the default implementation
| |
| 140 // the its overlap section with child border. | 140 // the its overlap section with child border. |
|
msw
2012/07/24 00:32:44
grammar nit: "the its"
stevenjb
2012/07/26 23:48:30
Done.
| |
| 141 SkPath path; | 141 SkPath path; |
| 142 path.incReserve(4); | 142 path.incReserve(4); |
| 143 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT || | 143 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT || |
| 144 arrow_location() == views::BubbleBorder::BOTTOM_LEFT) { | 144 arrow_location() == views::BubbleBorder::BOTTOM_LEFT) { |
| 145 // Do not let the arrow too close to the edge of the bubble and | 145 // Note: tray_arrow_offset_ is relative to the anchor widget. |
| 146 // and the edge of the anchor. | 146 int tip_x; |
| 147 int tip_x = base::i18n::IsRTL() ? | 147 if (tray_arrow_offset_ == |
| 148 std::min(std::max(tray_arrow_offset_, kArrowMinOffset), | 148 internal::TrayBubbleView::InitParams::kArrowDefaultOffset) { |
| 149 std::min(owner_->width(), anchor_->width()) | 149 if (arrow_location() == views::BubbleBorder::BOTTOM_LEFT) |
| 150 - kArrowMinOffset) : | 150 tip_x = kArrowMinOffset; |
| 151 std::min(std::max(owner_->width() - tray_arrow_offset_, | 151 else |
| 152 owner_->width() - | 152 tip_x = owner_->width() - kArrowMinOffset; |
| 153 std::min(owner_->width(), anchor_->width()) + | 153 } else { |
| 154 kArrowMinOffset), | 154 gfx::Point pt(tray_arrow_offset_, 0); |
| 155 owner_->width() - kArrowMinOffset); | 155 views::View::ConvertPointToScreen( |
| 156 anchor_->GetWidget()->GetRootView(), &pt); | |
| 157 views::View::ConvertPointFromScreen( | |
| 158 owner_->GetWidget()->GetRootView(), &pt); | |
| 159 tip_x = std::min(pt.x(), owner_->width() - kArrowMinOffset); | |
| 160 tip_x = std::max(tip_x, kArrowMinOffset); | |
| 161 } | |
| 156 int left_base_x = tip_x - kArrowWidth / 2; | 162 int left_base_x = tip_x - kArrowWidth / 2; |
| 157 int left_base_y = y; | 163 int left_base_y = y; |
| 158 int tip_y = left_base_y + kArrowHeight; | 164 int tip_y = left_base_y + kArrowHeight; |
| 159 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); | 165 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); |
| 160 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); | 166 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); |
| 161 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), | 167 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), |
| 162 SkIntToScalar(left_base_y)); | 168 SkIntToScalar(left_base_y)); |
| 163 arrow_reference.SetPoint(tip_x, left_base_y - kArrowHeight); | 169 arrow_reference.SetPoint(tip_x, left_base_y - kArrowHeight); |
| 164 } else { | 170 } else { |
| 165 int tip_y = y - tray_arrow_offset_; | 171 int tip_y; |
| 166 tip_y = std::min(std::max(kArrowMinOffset, tip_y), | 172 if (tray_arrow_offset_ == |
| 167 owner_->height() - kArrowMinOffset); | 173 internal::TrayBubbleView::InitParams::kArrowDefaultOffset) { |
| 174 tip_y = owner_->height() - kArrowMinOffset; | |
| 175 } else { | |
| 176 int pty = y - tray_arrow_offset_; | |
| 177 gfx::Point pt(0, pty); | |
| 178 views::View::ConvertPointToScreen( | |
| 179 anchor_->GetWidget()->GetRootView(), &pt); | |
| 180 views::View::ConvertPointFromScreen( | |
| 181 owner_->GetWidget()->GetRootView(), &pt); | |
| 182 tip_y = std::min(pt.y(), owner_->height() - kArrowMinOffset); | |
| 183 tip_y = std::max(tip_y, kArrowMinOffset); | |
| 184 } | |
| 168 int top_base_y = tip_y - kArrowWidth / 2; | 185 int top_base_y = tip_y - kArrowWidth / 2; |
| 169 int top_base_x, tip_x; | 186 int top_base_x, tip_x; |
| 170 if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) { | 187 if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) { |
| 171 top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset; | 188 top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset; |
| 172 tip_x = top_base_x - kArrowHeight; | 189 tip_x = top_base_x - kArrowHeight; |
| 173 arrow_reference.SetPoint(top_base_x + kArrowHeight, tip_y); | 190 arrow_reference.SetPoint(top_base_x + kArrowHeight, tip_y); |
| 174 } else { | 191 } else { |
| 175 DCHECK(arrow_location() == views::BubbleBorder::RIGHT_BOTTOM); | 192 DCHECK(arrow_location() == views::BubbleBorder::RIGHT_BOTTOM); |
| 176 top_base_x = inset.left() + owner_->width() - | 193 top_base_x = inset.left() + owner_->width() - |
| 177 kSystemTrayBubbleHorizontalInset; | 194 kSystemTrayBubbleHorizontalInset; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 192 paint.setColor(background ? background->get_color() : kBackgroundColor); | 209 paint.setColor(background ? background->get_color() : kBackgroundColor); |
| 193 canvas->DrawPath(path, paint); | 210 canvas->DrawPath(path, paint); |
| 194 | 211 |
| 195 // Now draw the arrow border. | 212 // Now draw the arrow border. |
| 196 paint.setStyle(SkPaint::kStroke_Style); | 213 paint.setStyle(SkPaint::kStroke_Style); |
| 197 paint.setColor(kBorderDarkColor); | 214 paint.setColor(kBorderDarkColor); |
| 198 canvas->DrawPath(path, paint); | 215 canvas->DrawPath(path, paint); |
| 199 | 216 |
| 200 } | 217 } |
| 201 | 218 |
| 219 private: | |
| 220 views::Background* FindAppropriateBackground(views::View* view, | |
| 221 const gfx::Point& point) const { | |
| 222 views::Background* background = NULL; | |
| 223 views::View* target = view->GetEventHandlerForPoint(point); | |
| 224 for (; target && !background; target = target->parent()) | |
| 225 background = target->background(); | |
| 226 return background; | |
| 227 } | |
| 228 | |
| 202 views::View* owner_; | 229 views::View* owner_; |
| 203 views::View* anchor_; | 230 views::View* anchor_; |
| 204 const int tray_arrow_offset_; | 231 const int tray_arrow_offset_; |
| 205 | 232 |
| 206 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); | 233 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBorder); |
| 207 }; | 234 }; |
| 208 | 235 |
| 209 } // namespace | 236 } // namespace |
| 210 | 237 |
| 211 namespace internal { | 238 namespace internal { |
| 212 | 239 |
| 240 // static | |
| 241 const int TrayBubbleView::InitParams::kArrowDefaultOffset = -1; | |
| 242 | |
| 243 TrayBubbleView::InitParams::InitParams(AnchorType anchor_type, | |
| 244 ShelfAlignment shelf_alignment) | |
| 245 : anchor_type(anchor_type), | |
| 246 shelf_alignment(shelf_alignment), | |
| 247 bubble_width(kTrayPopupWidth), | |
| 248 max_height(0), | |
| 249 can_activate(false), | |
| 250 arrow_offset(kArrowDefaultOffset) { | |
| 251 } | |
| 252 | |
| 253 TrayBubbleView* TrayBubbleView::Create(views::View* anchor, | |
| 254 Host* host, | |
| 255 const InitParams& init_params) { | |
| 256 // Set arrow_location here so that it can be passed correctly to the | |
| 257 // BubbleView constructor. | |
| 258 views::BubbleBorder::ArrowLocation arrow_location; | |
| 259 if (init_params.anchor_type == ANCHOR_TYPE_TRAY) { | |
| 260 if (init_params.shelf_alignment == SHELF_ALIGNMENT_BOTTOM) { | |
| 261 arrow_location = base::i18n::IsRTL() ? | |
| 262 views::BubbleBorder::BOTTOM_LEFT : views::BubbleBorder::BOTTOM_RIGHT; | |
| 263 } else if (init_params.shelf_alignment == SHELF_ALIGNMENT_LEFT) { | |
| 264 arrow_location = views::BubbleBorder::LEFT_BOTTOM; | |
| 265 } else { | |
| 266 arrow_location = views::BubbleBorder::RIGHT_BOTTOM; | |
| 267 } | |
| 268 } else { | |
| 269 arrow_location = views::BubbleBorder::NONE; | |
| 270 } | |
| 271 | |
| 272 return new TrayBubbleView(init_params, arrow_location, anchor, host); | |
| 273 } | |
| 274 | |
| 213 TrayBubbleView::TrayBubbleView( | 275 TrayBubbleView::TrayBubbleView( |
| 276 const InitParams& init_params, | |
| 277 views::BubbleBorder::ArrowLocation arrow_location, | |
| 214 views::View* anchor, | 278 views::View* anchor, |
| 215 views::BubbleBorder::ArrowLocation arrow_location, | 279 Host* host) |
| 216 Host* host, | |
| 217 bool can_activate, | |
| 218 int bubble_width) | |
| 219 : views::BubbleDelegateView(anchor, arrow_location), | 280 : views::BubbleDelegateView(anchor, arrow_location), |
| 220 host_(host), | 281 params_(init_params), |
| 221 can_activate_(can_activate), | 282 host_(host) { |
| 222 max_height_(0), | |
| 223 bubble_width_(bubble_width) { | |
| 224 set_margins(gfx::Insets()); | 283 set_margins(gfx::Insets()); |
| 225 set_parent_window(Shell::GetContainer( | 284 set_parent_window(Shell::GetContainer( |
| 226 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), | 285 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), |
| 227 internal::kShellWindowId_SettingBubbleContainer)); | 286 internal::kShellWindowId_SettingBubbleContainer)); |
| 228 set_notify_enter_exit_on_child(true); | 287 set_notify_enter_exit_on_child(true); |
| 229 SetPaintToLayer(true); | 288 SetPaintToLayer(true); |
| 230 SetFillsBoundsOpaquely(true); | 289 SetFillsBoundsOpaquely(true); |
| 231 } | 290 } |
| 232 | 291 |
| 233 TrayBubbleView::~TrayBubbleView() { | 292 TrayBubbleView::~TrayBubbleView() { |
| 234 // Inform host items (models) that their views are being destroyed. | 293 // Inform host items (models) that their views are being destroyed. |
| 235 if (host_) | 294 if (host_) |
| 236 host_->BubbleViewDestroyed(); | 295 host_->BubbleViewDestroyed(); |
| 237 } | 296 } |
| 238 | 297 |
| 239 void TrayBubbleView::SetBubbleBorder(int arrow_offset) { | |
| 240 DCHECK(GetWidget()); | |
| 241 TrayBubbleBorder* bubble_border = new TrayBubbleBorder( | |
| 242 this, anchor_view(), arrow_location(), arrow_offset); | |
| 243 GetBubbleFrameView()->SetBubbleBorder(bubble_border); | |
| 244 // Recalculate size with new border. | |
| 245 SizeToContents(); | |
| 246 } | |
| 247 | |
| 248 void TrayBubbleView::UpdateAnchor() { | 298 void TrayBubbleView::UpdateAnchor() { |
| 249 SizeToContents(); | 299 SizeToContents(); |
| 250 GetWidget()->GetRootView()->SchedulePaint(); | 300 GetWidget()->GetRootView()->SchedulePaint(); |
| 251 } | 301 } |
| 252 | 302 |
| 253 void TrayBubbleView::SetMaxHeight(int height) { | 303 void TrayBubbleView::SetMaxHeight(int height) { |
| 254 max_height_ = height; | 304 params_.max_height = height; |
| 255 if (GetWidget()) | 305 if (GetWidget()) |
| 256 SizeToContents(); | 306 SizeToContents(); |
| 257 } | 307 } |
| 258 | 308 |
| 259 void TrayBubbleView::Init() { | 309 void TrayBubbleView::Init() { |
| 260 views::BoxLayout* layout = | 310 views::BoxLayout* layout = |
| 261 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); | 311 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); |
| 262 layout->set_spread_blank_space(true); | 312 layout->set_spread_blank_space(true); |
| 263 SetLayoutManager(layout); | 313 SetLayoutManager(layout); |
| 264 set_background(NULL); | 314 set_background(NULL); |
| 265 } | 315 } |
| 266 | 316 |
| 267 gfx::Rect TrayBubbleView::GetAnchorRect() { | 317 gfx::Rect TrayBubbleView::GetAnchorRect() { |
| 268 gfx::Rect rect; | 318 gfx::Rect rect; |
| 269 if (host_) | 319 |
| 270 rect = host_->GetAnchorRect(); | 320 if (anchor_widget()->IsVisible()) { |
| 321 rect = anchor_widget()->GetWindowBoundsInScreen(); | |
| 322 if (params_.anchor_type == ANCHOR_TYPE_TRAY) { | |
| 323 if (params_.shelf_alignment == SHELF_ALIGNMENT_BOTTOM) { | |
| 324 bool rtl = base::i18n::IsRTL(); | |
| 325 rect.Inset( | |
| 326 rtl ? kPaddingFromRightEdgeOfScreenBottomAlignment : 0, | |
| 327 0, | |
| 328 rtl ? 0 : kPaddingFromRightEdgeOfScreenBottomAlignment, | |
| 329 kPaddingFromBottomOfScreenBottomAlignment); | |
| 330 } else if (params_.shelf_alignment == SHELF_ALIGNMENT_LEFT) { | |
| 331 rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
| 332 kPaddingFromBottomOfScreenVerticalAlignment); | |
| 333 } else { | |
| 334 rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
| 335 0, 0, kPaddingFromBottomOfScreenVerticalAlignment); | |
| 336 } | |
| 337 } else if (params_.anchor_type == ANCHOR_TYPE_BUBBLE) { | |
| 338 // Invert the offsets to align with the bubble below. | |
| 339 if (params_.shelf_alignment == SHELF_ALIGNMENT_LEFT) { | |
| 340 rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
| 341 0, 0, kPaddingFromBottomOfScreenVerticalAlignment); | |
| 342 } else if (params_.shelf_alignment == SHELF_ALIGNMENT_RIGHT) { | |
| 343 rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
| 344 kPaddingFromBottomOfScreenVerticalAlignment); | |
| 345 } | |
| 346 } | |
| 347 } | |
| 348 | |
| 271 // TODO(jennyz): May need to add left/right alignment in the following code. | 349 // TODO(jennyz): May need to add left/right alignment in the following code. |
| 272 if (rect.IsEmpty()) { | 350 if (rect.IsEmpty()) { |
| 273 rect = gfx::Screen::GetPrimaryDisplay().bounds(); | 351 rect = gfx::Screen::GetPrimaryDisplay().bounds(); |
| 274 rect = gfx::Rect( | 352 rect = gfx::Rect( |
| 275 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : | 353 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : |
| 276 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, | 354 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, |
| 277 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, | 355 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, |
| 278 0, 0); | 356 0, 0); |
| 279 } | 357 } |
| 280 return rect; | 358 return rect; |
| 281 } | 359 } |
| 282 | 360 |
| 283 gfx::Rect TrayBubbleView::GetBubbleBounds() { | 361 gfx::Rect TrayBubbleView::GetBubbleBounds() { |
| 284 // Same as BubbleDelegateView implementation, but don't try mirroring. | 362 // Same as BubbleDelegateView implementation, but don't try mirroring. |
| 285 return GetBubbleFrameView()->GetUpdatedWindowBounds( | 363 return GetBubbleFrameView()->GetUpdatedWindowBounds( |
| 286 GetAnchorRect(), GetPreferredSize(), false /*try_mirroring_arrow*/); | 364 GetAnchorRect(), GetPreferredSize(), false /*try_mirroring_arrow*/); |
| 287 } | 365 } |
| 288 | 366 |
| 289 bool TrayBubbleView::CanActivate() const { | 367 bool TrayBubbleView::CanActivate() const { |
| 290 return can_activate_; | 368 return params_.can_activate; |
| 369 } | |
| 370 | |
| 371 // Overridden to create BubbleFrameView and set the border to TrayBubbleBorder | |
| 372 // (instead of creating a default BubbleBorder and replacing it). | |
| 373 views::NonClientFrameView* TrayBubbleView::CreateNonClientFrameView( | |
| 374 views::Widget* widget) { | |
| 375 views::BubbleFrameView* bubble_frame_view = | |
|
msw
2012/07/23 22:20:49
Instead of changing the BubbleFrameView constructi
stevenjb
2012/07/23 23:32:06
The problem was that first a BubbleBorder() was ge
msw
2012/07/24 00:32:44
Ah, that's fair. Consider passing a BubbleBorder i
stevenjb
2012/07/26 23:48:30
Done.
| |
| 376 new views::BubbleFrameView(margins()); | |
| 377 TrayBubbleBorder* bubble_border = new TrayBubbleBorder( | |
| 378 this, anchor_view(), arrow_location(), params_.arrow_offset); | |
| 379 bubble_frame_view->SetBubbleBorder(bubble_border); | |
| 380 return bubble_frame_view; | |
| 291 } | 381 } |
| 292 | 382 |
| 293 gfx::Size TrayBubbleView::GetPreferredSize() { | 383 gfx::Size TrayBubbleView::GetPreferredSize() { |
| 294 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); | 384 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); |
| 295 int height = size.height(); | 385 int height = size.height(); |
| 296 if (max_height_ != 0 && height > max_height_) | 386 if (params_.max_height != 0 && height > params_.max_height) |
| 297 height = max_height_; | 387 height = params_.max_height; |
| 298 return gfx::Size(bubble_width_, height); | 388 return gfx::Size(params_.bubble_width, height); |
| 299 } | 389 } |
| 300 | 390 |
| 301 void TrayBubbleView::OnMouseEntered(const views::MouseEvent& event) { | 391 void TrayBubbleView::OnMouseEntered(const views::MouseEvent& event) { |
| 302 if (host_) | 392 if (host_) |
| 303 host_->OnMouseEnteredView(); | 393 host_->OnMouseEnteredView(); |
| 304 } | 394 } |
| 305 | 395 |
| 306 void TrayBubbleView::OnMouseExited(const views::MouseEvent& event) { | 396 void TrayBubbleView::OnMouseExited(const views::MouseEvent& event) { |
| 307 if (host_) | 397 if (host_) |
| 308 host_->OnMouseExitedView(); | 398 host_->OnMouseExitedView(); |
| 309 } | 399 } |
| 310 | 400 |
| 311 void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { | 401 void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { |
| 312 if (can_activate_) { | 402 if (params_.can_activate) { |
| 313 state->role = ui::AccessibilityTypes::ROLE_WINDOW; | 403 state->role = ui::AccessibilityTypes::ROLE_WINDOW; |
| 314 state->name = l10n_util::GetStringUTF16( | 404 state->name = l10n_util::GetStringUTF16( |
| 315 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); | 405 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); |
| 316 } | 406 } |
| 317 } | 407 } |
| 318 | 408 |
| 319 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { | 409 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { |
| 320 SizeToContents(); | 410 SizeToContents(); |
| 321 } | 411 } |
| 322 | 412 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 333 TrayBubbleView::Host::Host() | 423 TrayBubbleView::Host::Host() |
| 334 : widget_(NULL), | 424 : widget_(NULL), |
| 335 tray_view_(NULL) { | 425 tray_view_(NULL) { |
| 336 Shell::GetInstance()->AddEnvEventFilter(this); | 426 Shell::GetInstance()->AddEnvEventFilter(this); |
| 337 } | 427 } |
| 338 | 428 |
| 339 TrayBubbleView::Host::~Host() { | 429 TrayBubbleView::Host::~Host() { |
| 340 Shell::GetInstance()->RemoveEnvEventFilter(this); | 430 Shell::GetInstance()->RemoveEnvEventFilter(this); |
| 341 } | 431 } |
| 342 | 432 |
| 343 void TrayBubbleView::Host::InitializeHost(views::Widget* widget, | 433 void TrayBubbleView::Host::PostCreateBubble(views::Widget* widget, |
| 344 views::View* tray_view) { | 434 TrayBubbleView* bubble_view, |
| 435 views::View* tray_view) { | |
| 345 widget_ = widget; | 436 widget_ = widget; |
| 346 tray_view_ = tray_view; | 437 tray_view_ = tray_view; |
| 438 | |
| 439 // Must occur after call to BubbleDelegateView::CreateBubble(). | |
| 440 bubble_view->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | |
| 441 | |
| 442 // Setup animation. | |
| 443 ash::SetWindowVisibilityAnimationType( | |
| 444 widget->GetNativeWindow(), | |
| 445 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); | |
| 446 ash::SetWindowVisibilityAnimationTransition( | |
| 447 widget->GetNativeWindow(), | |
| 448 ash::ANIMATE_BOTH); | |
| 449 ash::SetWindowVisibilityAnimationDuration( | |
| 450 widget->GetNativeWindow(), | |
| 451 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); | |
| 347 } | 452 } |
| 348 | 453 |
| 349 bool TrayBubbleView::Host::PreHandleKeyEvent(aura::Window* target, | 454 bool TrayBubbleView::Host::PreHandleKeyEvent(aura::Window* target, |
| 350 aura::KeyEvent* event) { | 455 aura::KeyEvent* event) { |
| 351 return false; | 456 return false; |
| 352 } | 457 } |
| 353 | 458 |
| 354 bool TrayBubbleView::Host::PreHandleMouseEvent(aura::Window* target, | 459 bool TrayBubbleView::Host::PreHandleMouseEvent(aura::Window* target, |
| 355 aura::MouseEvent* event) { | 460 aura::MouseEvent* event) { |
| 356 if (event->type() == ui::ET_MOUSE_PRESSED) | 461 if (event->type() == ui::ET_MOUSE_PRESSED) |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 387 return; | 492 return; |
| 388 } | 493 } |
| 389 // Handle clicking outside the bubble and tray. We don't block the event, so | 494 // Handle clicking outside the bubble and tray. We don't block the event, so |
| 390 // it will also be handled by whatever widget was clicked on. | 495 // it will also be handled by whatever widget was clicked on. |
| 391 OnClickedOutsideView(); | 496 OnClickedOutsideView(); |
| 392 } | 497 } |
| 393 | 498 |
| 394 | 499 |
| 395 } // namespace internal | 500 } // namespace internal |
| 396 } // namespace ash | 501 } // namespace ash |
| OLD | NEW |