| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ash/common/system/tray/tray_background_view.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "ash/common/ash_constants.h" | |
| 10 #include "ash/common/material_design/material_design_controller.h" | |
| 11 #include "ash/common/shelf/shelf_constants.h" | |
| 12 #include "ash/common/shelf/wm_shelf.h" | |
| 13 #include "ash/common/shelf/wm_shelf_util.h" | |
| 14 #include "ash/common/system/tray/system_tray.h" | |
| 15 #include "ash/common/system/tray/tray_constants.h" | |
| 16 #include "ash/common/system/tray/tray_event_filter.h" | |
| 17 #include "ash/common/wm_shell.h" | |
| 18 #include "ash/common/wm_window.h" | |
| 19 #include "ash/public/cpp/shell_window_ids.h" | |
| 20 #include "ash/resources/grit/ash_resources.h" | |
| 21 #include "base/memory/ptr_util.h" | |
| 22 #include "ui/accessibility/ax_node_data.h" | |
| 23 #include "ui/base/nine_image_painter_factory.h" | |
| 24 #include "ui/compositor/layer.h" | |
| 25 #include "ui/compositor/layer_animation_element.h" | |
| 26 #include "ui/compositor/scoped_layer_animation_settings.h" | |
| 27 #include "ui/events/event_constants.h" | |
| 28 #include "ui/gfx/animation/tween.h" | |
| 29 #include "ui/gfx/canvas.h" | |
| 30 #include "ui/gfx/geometry/rect.h" | |
| 31 #include "ui/gfx/geometry/size.h" | |
| 32 #include "ui/gfx/image/image_skia.h" | |
| 33 #include "ui/gfx/image/image_skia_operations.h" | |
| 34 #include "ui/gfx/nine_image_painter.h" | |
| 35 #include "ui/gfx/scoped_canvas.h" | |
| 36 #include "ui/gfx/skia_util.h" | |
| 37 #include "ui/gfx/transform.h" | |
| 38 #include "ui/views/animation/flood_fill_ink_drop_ripple.h" | |
| 39 #include "ui/views/animation/ink_drop_highlight.h" | |
| 40 #include "ui/views/animation/ink_drop_mask.h" | |
| 41 #include "ui/views/background.h" | |
| 42 #include "ui/views/layout/box_layout.h" | |
| 43 #include "ui/wm/core/window_animations.h" | |
| 44 | |
| 45 namespace { | |
| 46 | |
| 47 const int kAnimationDurationForPopupMs = 200; | |
| 48 | |
| 49 // Duration of opacity animation for visibility changes. | |
| 50 const int kAnimationDurationForVisibilityMs = 250; | |
| 51 | |
| 52 // When becoming visible delay the animation so that StatusAreaWidgetDelegate | |
| 53 // can animate sibling views out of the position to be occuped by the | |
| 54 // TrayBackgroundView. | |
| 55 const int kShowAnimationDelayMs = 100; | |
| 56 | |
| 57 // Additional padding used to adjust the user-visible size of status tray | |
| 58 // and overview button dark background. | |
| 59 const int kBackgroundAdjustPadding = 3; | |
| 60 | |
| 61 // Switches left and right insets if RTL mode is active. | |
| 62 void MirrorInsetsIfNecessary(gfx::Insets* insets) { | |
| 63 if (base::i18n::IsRTL()) { | |
| 64 insets->Set(insets->top(), insets->right(), insets->bottom(), | |
| 65 insets->left()); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 // Returns background insets relative to the contents bounds of the view and | |
| 70 // mirrored if RTL mode is active. | |
| 71 gfx::Insets GetMirroredBackgroundInsets(ash::ShelfAlignment shelf_alignment) { | |
| 72 gfx::Insets insets; | |
| 73 if (IsHorizontalAlignment(shelf_alignment)) { | |
| 74 insets.Set(0, ash::kHitRegionPadding, 0, | |
| 75 ash::kHitRegionPadding + ash::kSeparatorWidth); | |
| 76 } else { | |
| 77 insets.Set(ash::kHitRegionPadding, 0, | |
| 78 ash::kHitRegionPadding + ash::kSeparatorWidth, 0); | |
| 79 } | |
| 80 MirrorInsetsIfNecessary(&insets); | |
| 81 return insets; | |
| 82 } | |
| 83 | |
| 84 } // namespace | |
| 85 | |
| 86 using views::TrayBubbleView; | |
| 87 | |
| 88 namespace ash { | |
| 89 | |
| 90 // static | |
| 91 const char TrayBackgroundView::kViewClassName[] = "tray/TrayBackgroundView"; | |
| 92 | |
| 93 // Used to track when the anchor widget changes position on screen so that the | |
| 94 // bubble position can be updated. | |
| 95 class TrayBackgroundView::TrayWidgetObserver : public views::WidgetObserver { | |
| 96 public: | |
| 97 explicit TrayWidgetObserver(TrayBackgroundView* host) : host_(host) {} | |
| 98 | |
| 99 void OnWidgetBoundsChanged(views::Widget* widget, | |
| 100 const gfx::Rect& new_bounds) override { | |
| 101 host_->AnchorUpdated(); | |
| 102 } | |
| 103 | |
| 104 void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override { | |
| 105 host_->AnchorUpdated(); | |
| 106 } | |
| 107 | |
| 108 private: | |
| 109 TrayBackgroundView* host_; | |
| 110 | |
| 111 DISALLOW_COPY_AND_ASSIGN(TrayWidgetObserver); | |
| 112 }; | |
| 113 | |
| 114 class TrayBackground : public views::Background { | |
| 115 public: | |
| 116 TrayBackground(TrayBackgroundView* tray_background_view, bool draws_active) | |
| 117 : tray_background_view_(tray_background_view), | |
| 118 draws_active_(draws_active), | |
| 119 color_(SK_ColorTRANSPARENT) {} | |
| 120 | |
| 121 ~TrayBackground() override {} | |
| 122 | |
| 123 void set_color(SkColor color) { color_ = color; } | |
| 124 | |
| 125 private: | |
| 126 WmShelf* GetShelf() const { return tray_background_view_->shelf(); } | |
| 127 | |
| 128 void PaintMaterial(gfx::Canvas* canvas, views::View* view) const { | |
| 129 cc::PaintFlags background_flags; | |
| 130 background_flags.setAntiAlias(true); | |
| 131 background_flags.setColor(color_); | |
| 132 gfx::Insets insets = | |
| 133 GetMirroredBackgroundInsets(GetShelf()->GetAlignment()); | |
| 134 gfx::Rect bounds = view->GetLocalBounds(); | |
| 135 bounds.Inset(insets); | |
| 136 canvas->DrawRoundRect(bounds, kTrayRoundedBorderRadius, background_flags); | |
| 137 | |
| 138 if (draws_active_ && tray_background_view_->is_active()) { | |
| 139 cc::PaintFlags highlight_flags; | |
| 140 highlight_flags.setAntiAlias(true); | |
| 141 highlight_flags.setColor(kShelfButtonActivatedHighlightColor); | |
| 142 canvas->DrawRoundRect(bounds, kTrayRoundedBorderRadius, highlight_flags); | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 void PaintNonMaterial(gfx::Canvas* canvas, views::View* view) const { | |
| 147 const static int kImageTypeDefault = 0; | |
| 148 // TODO(estade): leftover type which should be removed along with the rest | |
| 149 // of pre-MD code. | |
| 150 // const static int kImageTypeOnBlack = 1; | |
| 151 const static int kImageTypePressed = 2; | |
| 152 const static int kNumStates = 3; | |
| 153 | |
| 154 const static int kImageHorizontal = 0; | |
| 155 const static int kImageVertical = 1; | |
| 156 const static int kNumOrientations = 2; | |
| 157 | |
| 158 const int kGridSizeForPainter = 9; | |
| 159 | |
| 160 const int kImages[kNumOrientations][kNumStates][kGridSizeForPainter] = { | |
| 161 { | |
| 162 // Horizontal | |
| 163 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ), | |
| 164 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ_ONBLACK), | |
| 165 IMAGE_GRID_HORIZONTAL(IDR_AURA_TRAY_BG_HORIZ_PRESSED), | |
| 166 }, | |
| 167 { | |
| 168 // Vertical | |
| 169 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL), | |
| 170 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL_ONBLACK), | |
| 171 IMAGE_GRID_VERTICAL(IDR_AURA_TRAY_BG_VERTICAL_PRESSED), | |
| 172 }}; | |
| 173 | |
| 174 WmShelf* shelf = GetShelf(); | |
| 175 const int orientation = IsHorizontalAlignment(shelf->GetAlignment()) | |
| 176 ? kImageHorizontal | |
| 177 : kImageVertical; | |
| 178 | |
| 179 int state = kImageTypeDefault; | |
| 180 if (draws_active_ && tray_background_view_->is_active()) | |
| 181 state = kImageTypePressed; | |
| 182 else | |
| 183 state = kImageTypeDefault; | |
| 184 | |
| 185 ui::CreateNineImagePainter(kImages[orientation][state]) | |
| 186 ->Paint(canvas, view->GetLocalBounds()); | |
| 187 } | |
| 188 | |
| 189 // Overridden from views::Background. | |
| 190 void Paint(gfx::Canvas* canvas, views::View* view) const override { | |
| 191 if (MaterialDesignController::IsShelfMaterial()) | |
| 192 PaintMaterial(canvas, view); | |
| 193 else | |
| 194 PaintNonMaterial(canvas, view); | |
| 195 } | |
| 196 | |
| 197 // Reference to the TrayBackgroundView for which this is a background. | |
| 198 TrayBackgroundView* tray_background_view_; | |
| 199 | |
| 200 // Determines whether we should draw an active background for the view when it | |
| 201 // is active. This is used in non-MD mode. In material design mode, an active | |
| 202 // ink drop ripple would indicate if the view is active or not. | |
| 203 // TODO(mohsen): This is used only in non-MD version. Remove when non-MD code | |
| 204 // is removed (see https://crbug.com/614453). | |
| 205 bool draws_active_; | |
| 206 | |
| 207 SkColor color_; | |
| 208 | |
| 209 DISALLOW_COPY_AND_ASSIGN(TrayBackground); | |
| 210 }; | |
| 211 | |
| 212 TrayBackgroundView::TrayContainer::TrayContainer(ShelfAlignment alignment) | |
| 213 : alignment_(alignment) { | |
| 214 UpdateLayout(); | |
| 215 } | |
| 216 | |
| 217 void TrayBackgroundView::TrayContainer::SetAlignment(ShelfAlignment alignment) { | |
| 218 if (alignment_ == alignment) | |
| 219 return; | |
| 220 alignment_ = alignment; | |
| 221 UpdateLayout(); | |
| 222 } | |
| 223 | |
| 224 void TrayBackgroundView::TrayContainer::SetMargin(int main_axis_margin, | |
| 225 int cross_axis_margin) { | |
| 226 main_axis_margin_ = main_axis_margin; | |
| 227 cross_axis_margin_ = cross_axis_margin; | |
| 228 UpdateLayout(); | |
| 229 } | |
| 230 | |
| 231 void TrayBackgroundView::TrayContainer::ChildPreferredSizeChanged( | |
| 232 views::View* child) { | |
| 233 PreferredSizeChanged(); | |
| 234 } | |
| 235 | |
| 236 void TrayBackgroundView::TrayContainer::ChildVisibilityChanged(View* child) { | |
| 237 PreferredSizeChanged(); | |
| 238 } | |
| 239 | |
| 240 void TrayBackgroundView::TrayContainer::ViewHierarchyChanged( | |
| 241 const ViewHierarchyChangedDetails& details) { | |
| 242 if (details.parent == this) | |
| 243 PreferredSizeChanged(); | |
| 244 } | |
| 245 | |
| 246 void TrayBackgroundView::TrayContainer::UpdateLayout() { | |
| 247 bool is_horizontal = IsHorizontalAlignment(alignment_); | |
| 248 | |
| 249 // Adjust the size of status tray dark background by adding additional | |
| 250 // empty border. | |
| 251 views::BoxLayout::Orientation orientation = | |
| 252 is_horizontal ? views::BoxLayout::kHorizontal | |
| 253 : views::BoxLayout::kVertical; | |
| 254 | |
| 255 if (ash::MaterialDesignController::IsShelfMaterial()) { | |
| 256 const int hit_region_with_separator = kHitRegionPadding + kSeparatorWidth; | |
| 257 gfx::Insets insets( | |
| 258 is_horizontal | |
| 259 ? gfx::Insets(0, kHitRegionPadding, 0, hit_region_with_separator) | |
| 260 : gfx::Insets(kHitRegionPadding, 0, hit_region_with_separator, 0)); | |
| 261 MirrorInsetsIfNecessary(&insets); | |
| 262 SetBorder(views::CreateEmptyBorder(insets)); | |
| 263 } else { | |
| 264 SetBorder(views::CreateEmptyBorder(gfx::Insets(kBackgroundAdjustPadding))); | |
| 265 } | |
| 266 | |
| 267 int horizontal_margin = main_axis_margin_; | |
| 268 int vertical_margin = cross_axis_margin_; | |
| 269 if (!is_horizontal) | |
| 270 std::swap(horizontal_margin, vertical_margin); | |
| 271 views::BoxLayout* layout = | |
| 272 new views::BoxLayout(orientation, horizontal_margin, vertical_margin, 0); | |
| 273 | |
| 274 if (!ash::MaterialDesignController::IsShelfMaterial()) | |
| 275 layout->SetDefaultFlex(1); | |
| 276 layout->set_minimum_cross_axis_size(kTrayItemSize); | |
| 277 views::View::SetLayoutManager(layout); | |
| 278 | |
| 279 PreferredSizeChanged(); | |
| 280 } | |
| 281 | |
| 282 //////////////////////////////////////////////////////////////////////////////// | |
| 283 // TrayBackgroundView | |
| 284 | |
| 285 TrayBackgroundView::TrayBackgroundView(WmShelf* wm_shelf) | |
| 286 // Note the ink drop style is ignored. | |
| 287 : ActionableView(nullptr, TrayPopupInkDropStyle::FILL_BOUNDS), | |
| 288 wm_shelf_(wm_shelf), | |
| 289 tray_container_(NULL), | |
| 290 shelf_alignment_(SHELF_ALIGNMENT_BOTTOM), | |
| 291 background_(NULL), | |
| 292 is_active_(false), | |
| 293 separator_visible_(true), | |
| 294 widget_observer_(new TrayWidgetObserver(this)) { | |
| 295 DCHECK(wm_shelf_); | |
| 296 set_notify_enter_exit_on_child(true); | |
| 297 set_ink_drop_base_color(kShelfInkDropBaseColor); | |
| 298 set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity); | |
| 299 | |
| 300 tray_container_ = new TrayContainer(shelf_alignment_); | |
| 301 SetContents(tray_container_); | |
| 302 tray_event_filter_.reset(new TrayEventFilter); | |
| 303 | |
| 304 SetPaintToLayer(); | |
| 305 layer()->SetFillsBoundsOpaquely(false); | |
| 306 // Start the tray items not visible, because visibility changes are animated. | |
| 307 views::View::SetVisible(false); | |
| 308 } | |
| 309 | |
| 310 TrayBackgroundView::~TrayBackgroundView() { | |
| 311 if (GetWidget()) | |
| 312 GetWidget()->RemoveObserver(widget_observer_.get()); | |
| 313 StopObservingImplicitAnimations(); | |
| 314 } | |
| 315 | |
| 316 void TrayBackgroundView::Initialize() { | |
| 317 GetWidget()->AddObserver(widget_observer_.get()); | |
| 318 } | |
| 319 | |
| 320 // static | |
| 321 void TrayBackgroundView::InitializeBubbleAnimations( | |
| 322 views::Widget* bubble_widget) { | |
| 323 WmWindow* window = WmWindow::Get(bubble_widget->GetNativeWindow()); | |
| 324 window->SetVisibilityAnimationType( | |
| 325 ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); | |
| 326 window->SetVisibilityAnimationTransition(::wm::ANIMATE_HIDE); | |
| 327 window->SetVisibilityAnimationDuration( | |
| 328 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMs)); | |
| 329 } | |
| 330 | |
| 331 void TrayBackgroundView::SetVisible(bool visible) { | |
| 332 if (visible == layer()->GetTargetVisibility()) | |
| 333 return; | |
| 334 | |
| 335 if (visible) { | |
| 336 // The alignment of the shelf can change while the TrayBackgroundView is | |
| 337 // hidden. Reset the offscreen transform so that the animation to becoming | |
| 338 // visible reflects the current layout. | |
| 339 HideTransformation(); | |
| 340 // SetVisible(false) is defered until the animation for hiding is done. | |
| 341 // Otherwise the view is immediately hidden and the animation does not | |
| 342 // render. | |
| 343 views::View::SetVisible(true); | |
| 344 // If SetVisible(true) is called while animating to not visible, then | |
| 345 // views::View::SetVisible(true) is a no-op. When the previous animation | |
| 346 // ends layer->SetVisible(false) is called. To prevent this | |
| 347 // layer->SetVisible(true) immediately interrupts the animation of this | |
| 348 // property, and keeps the layer visible. | |
| 349 layer()->SetVisible(true); | |
| 350 } | |
| 351 | |
| 352 ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator()); | |
| 353 animation.SetTransitionDuration( | |
| 354 base::TimeDelta::FromMilliseconds(kAnimationDurationForVisibilityMs)); | |
| 355 animation.SetPreemptionStrategy( | |
| 356 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
| 357 | |
| 358 if (visible) { | |
| 359 animation.SetTweenType(gfx::Tween::EASE_OUT); | |
| 360 // Show is delayed so as to allow time for other children of | |
| 361 // StatusAreaWidget to begin animating to their new positions. | |
| 362 layer()->GetAnimator()->SchedulePauseForProperties( | |
| 363 base::TimeDelta::FromMilliseconds(kShowAnimationDelayMs), | |
| 364 ui::LayerAnimationElement::OPACITY | | |
| 365 ui::LayerAnimationElement::TRANSFORM); | |
| 366 layer()->SetOpacity(1.0f); | |
| 367 gfx::Transform transform; | |
| 368 transform.Translate(0.0f, 0.0f); | |
| 369 layer()->SetTransform(transform); | |
| 370 } else { | |
| 371 // Listen only to the hide animation. As we cannot turn off visibility | |
| 372 // until the animation is over. | |
| 373 animation.AddObserver(this); | |
| 374 animation.SetTweenType(gfx::Tween::EASE_IN); | |
| 375 layer()->SetOpacity(0.0f); | |
| 376 layer()->SetVisible(false); | |
| 377 HideTransformation(); | |
| 378 } | |
| 379 } | |
| 380 | |
| 381 const char* TrayBackgroundView::GetClassName() const { | |
| 382 return kViewClassName; | |
| 383 } | |
| 384 | |
| 385 void TrayBackgroundView::ChildPreferredSizeChanged(views::View* child) { | |
| 386 PreferredSizeChanged(); | |
| 387 } | |
| 388 | |
| 389 void TrayBackgroundView::GetAccessibleNodeData(ui::AXNodeData* node_data) { | |
| 390 ActionableView::GetAccessibleNodeData(node_data); | |
| 391 node_data->SetName(GetAccessibleNameForTray()); | |
| 392 } | |
| 393 | |
| 394 void TrayBackgroundView::AboutToRequestFocusFromTabTraversal(bool reverse) { | |
| 395 // Return focus to the login view. See crbug.com/120500. | |
| 396 views::View* v = GetNextFocusableView(); | |
| 397 if (v) | |
| 398 v->AboutToRequestFocusFromTabTraversal(reverse); | |
| 399 } | |
| 400 | |
| 401 std::unique_ptr<views::InkDropRipple> TrayBackgroundView::CreateInkDropRipple() | |
| 402 const { | |
| 403 return base::MakeUnique<views::FloodFillInkDropRipple>( | |
| 404 size(), GetBackgroundInsets(), GetInkDropCenterBasedOnLastEvent(), | |
| 405 GetInkDropBaseColor(), ink_drop_visible_opacity()); | |
| 406 } | |
| 407 | |
| 408 std::unique_ptr<views::InkDropHighlight> | |
| 409 TrayBackgroundView::CreateInkDropHighlight() const { | |
| 410 gfx::Rect bounds = GetBackgroundBounds(); | |
| 411 // Currently, we don't handle view resize. To compensate for that, enlarge the | |
| 412 // bounds by two tray icons so that the hightlight looks good even if two more | |
| 413 // icons are added when it is visible. Note that ink drop mask handles resize | |
| 414 // correctly, so the extra highlight would be clipped. | |
| 415 // TODO(mohsen): Remove this extra size when resize is handled properly (see | |
| 416 // https://crbug.com/669253). | |
| 417 const int icon_size = kTrayIconSize + 2 * kTrayImageItemPadding; | |
| 418 bounds.set_width(bounds.width() + 2 * icon_size); | |
| 419 bounds.set_height(bounds.height() + 2 * icon_size); | |
| 420 std::unique_ptr<views::InkDropHighlight> highlight( | |
| 421 new views::InkDropHighlight(bounds.size(), 0, | |
| 422 gfx::RectF(bounds).CenterPoint(), | |
| 423 GetInkDropBaseColor())); | |
| 424 highlight->set_visible_opacity(kTrayPopupInkDropHighlightOpacity); | |
| 425 return highlight; | |
| 426 } | |
| 427 | |
| 428 void TrayBackgroundView::OnGestureEvent(ui::GestureEvent* event) { | |
| 429 // If there is no ink drop, show "touch feedback". | |
| 430 // TODO(mohsen): This is used only in non-MD version. Remove when non-MD code | |
| 431 // is removed (see https://crbug.com/614453). | |
| 432 if (ink_drop_mode() == InkDropMode::OFF) { | |
| 433 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { | |
| 434 SetIsActive(true); | |
| 435 } else if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || | |
| 436 event->type() == ui::ET_GESTURE_TAP_CANCEL) { | |
| 437 SetIsActive(false); | |
| 438 } | |
| 439 } | |
| 440 ActionableView::OnGestureEvent(event); | |
| 441 } | |
| 442 | |
| 443 void TrayBackgroundView::SetContents(views::View* contents) { | |
| 444 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0)); | |
| 445 AddChildView(contents); | |
| 446 } | |
| 447 | |
| 448 void TrayBackgroundView::SetContentsBackground(bool draws_active) { | |
| 449 background_ = new TrayBackground(this, draws_active); | |
| 450 tray_container_->set_background(background_); | |
| 451 } | |
| 452 | |
| 453 void TrayBackgroundView::SetShelfAlignment(ShelfAlignment alignment) { | |
| 454 shelf_alignment_ = alignment; | |
| 455 tray_container_->SetAlignment(alignment); | |
| 456 } | |
| 457 | |
| 458 void TrayBackgroundView::OnImplicitAnimationsCompleted() { | |
| 459 // If there is another animation in the queue, the reverse animation was | |
| 460 // triggered before the completion of animating to invisible. Do not turn off | |
| 461 // the visibility so that the next animation may render. The value of | |
| 462 // layer()->GetTargetVisibility() can be incorrect if the hide animation was | |
| 463 // aborted to schedule an animation to become visible. As the new animation | |
| 464 // is not yet added to the queue. crbug.com/374236 | |
| 465 if (layer()->GetAnimator()->is_animating() || layer()->GetTargetVisibility()) | |
| 466 return; | |
| 467 views::View::SetVisible(false); | |
| 468 } | |
| 469 | |
| 470 bool TrayBackgroundView::RequiresNotificationWhenAnimatorDestroyed() const { | |
| 471 // This is needed so that OnImplicitAnimationsCompleted() is called even upon | |
| 472 // destruction of the animator. This can occure when parallel animations | |
| 473 // caused by ScreenRotationAnimator end before the animations of | |
| 474 // TrayBackgroundView. This allows for a proper update to the visual state of | |
| 475 // the view. (crbug.com/476667) | |
| 476 return true; | |
| 477 } | |
| 478 | |
| 479 void TrayBackgroundView::HideTransformation() { | |
| 480 gfx::Transform transform; | |
| 481 if (IsHorizontalAlignment(shelf_alignment_)) | |
| 482 transform.Translate(width(), 0.0f); | |
| 483 else | |
| 484 transform.Translate(0.0f, height()); | |
| 485 layer()->SetTransform(transform); | |
| 486 } | |
| 487 | |
| 488 TrayBubbleView::AnchorAlignment TrayBackgroundView::GetAnchorAlignment() const { | |
| 489 if (shelf_alignment_ == SHELF_ALIGNMENT_LEFT) | |
| 490 return TrayBubbleView::ANCHOR_ALIGNMENT_LEFT; | |
| 491 if (shelf_alignment_ == SHELF_ALIGNMENT_RIGHT) | |
| 492 return TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT; | |
| 493 return TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM; | |
| 494 } | |
| 495 | |
| 496 void TrayBackgroundView::SetIsActive(bool is_active) { | |
| 497 if (is_active_ == is_active) | |
| 498 return; | |
| 499 is_active_ = is_active; | |
| 500 AnimateInkDrop(is_active_ ? views::InkDropState::ACTIVATED | |
| 501 : views::InkDropState::DEACTIVATED, | |
| 502 nullptr); | |
| 503 if (!background_) | |
| 504 return; | |
| 505 // TODO(mohsen): This is needed for non-MD version. Remove when non-MD code is | |
| 506 // removed (see https://crbug.com/614453). | |
| 507 SchedulePaint(); | |
| 508 } | |
| 509 | |
| 510 void TrayBackgroundView::UpdateBubbleViewArrow( | |
| 511 views::TrayBubbleView* bubble_view) { | |
| 512 // Nothing to do here. | |
| 513 } | |
| 514 | |
| 515 void TrayBackgroundView::UpdateShelfItemBackground(SkColor color) { | |
| 516 if (background_) { | |
| 517 background_->set_color(color); | |
| 518 SchedulePaint(); | |
| 519 } | |
| 520 } | |
| 521 | |
| 522 views::View* TrayBackgroundView::GetBubbleAnchor() const { | |
| 523 return tray_container_; | |
| 524 } | |
| 525 | |
| 526 gfx::Insets TrayBackgroundView::GetBubbleAnchorInsets() const { | |
| 527 gfx::Insets anchor_insets = GetBubbleAnchor()->GetInsets(); | |
| 528 gfx::Insets tray_bg_insets = GetInsets(); | |
| 529 if (GetAnchorAlignment() == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) { | |
| 530 return gfx::Insets(-tray_bg_insets.top(), anchor_insets.left(), | |
| 531 -tray_bg_insets.bottom(), anchor_insets.right()); | |
| 532 } else { | |
| 533 return gfx::Insets(anchor_insets.top(), -tray_bg_insets.left(), | |
| 534 anchor_insets.bottom(), -tray_bg_insets.right()); | |
| 535 } | |
| 536 } | |
| 537 | |
| 538 std::unique_ptr<views::InkDropMask> TrayBackgroundView::CreateInkDropMask() | |
| 539 const { | |
| 540 return base::MakeUnique<views::RoundRectInkDropMask>( | |
| 541 size(), GetBackgroundInsets(), kTrayRoundedBorderRadius); | |
| 542 } | |
| 543 | |
| 544 bool TrayBackgroundView::ShouldEnterPushedState(const ui::Event& event) { | |
| 545 if (is_active_) | |
| 546 return false; | |
| 547 | |
| 548 return ActionableView::ShouldEnterPushedState(event); | |
| 549 } | |
| 550 | |
| 551 bool TrayBackgroundView::PerformAction(const ui::Event& event) { | |
| 552 return false; | |
| 553 } | |
| 554 | |
| 555 void TrayBackgroundView::HandlePerformActionResult(bool action_performed, | |
| 556 const ui::Event& event) { | |
| 557 // When an action is performed, ink drop ripple is handled in SetIsActive(). | |
| 558 if (action_performed) | |
| 559 return; | |
| 560 ActionableView::HandlePerformActionResult(action_performed, event); | |
| 561 } | |
| 562 | |
| 563 void TrayBackgroundView::OnPaintFocus(gfx::Canvas* canvas) { | |
| 564 // The tray itself expands to the right and bottom edge of the screen to make | |
| 565 // sure clicking on the edges brings up the popup. However, the focus border | |
| 566 // should be only around the container. | |
| 567 gfx::RectF paint_bounds; | |
| 568 paint_bounds = gfx::RectF(GetBackgroundBounds()); | |
| 569 paint_bounds.Inset(gfx::Insets(-kFocusBorderThickness)); | |
| 570 canvas->DrawSolidFocusRect(paint_bounds, kFocusBorderColor, | |
| 571 kFocusBorderThickness); | |
| 572 } | |
| 573 | |
| 574 void TrayBackgroundView::OnPaint(gfx::Canvas* canvas) { | |
| 575 ActionableView::OnPaint(canvas); | |
| 576 if (shelf()->GetBackgroundType() == | |
| 577 ShelfBackgroundType::SHELF_BACKGROUND_DEFAULT || | |
| 578 !separator_visible_) { | |
| 579 return; | |
| 580 } | |
| 581 // In the given |canvas|, for a horizontal shelf draw a separator line to the | |
| 582 // right or left of the TrayBackgroundView when the system is LTR or RTL | |
| 583 // aligned, respectively. For a vertical shelf draw the separator line | |
| 584 // underneath the items instead. | |
| 585 const gfx::Rect local_bounds = GetLocalBounds(); | |
| 586 const SkColor color = SkColorSetA(SK_ColorWHITE, 0x4D); | |
| 587 | |
| 588 if (IsHorizontalAlignment(shelf_alignment_)) { | |
| 589 const gfx::PointF point( | |
| 590 base::i18n::IsRTL() ? 0 : (local_bounds.width() - kSeparatorWidth), | |
| 591 (GetShelfConstant(SHELF_SIZE) - kTrayItemSize) / 2); | |
| 592 const gfx::Vector2dF vector(0, kTrayItemSize); | |
| 593 canvas->Draw1pxLine(point, point + vector, color); | |
| 594 } else { | |
| 595 const gfx::PointF point((GetShelfConstant(SHELF_SIZE) - kTrayItemSize) / 2, | |
| 596 local_bounds.height() - kSeparatorWidth); | |
| 597 const gfx::Vector2dF vector(kTrayItemSize, 0); | |
| 598 canvas->Draw1pxLine(point, point + vector, color); | |
| 599 } | |
| 600 } | |
| 601 | |
| 602 gfx::Insets TrayBackgroundView::GetBackgroundInsets() const { | |
| 603 gfx::Insets insets = GetMirroredBackgroundInsets(shelf_alignment_); | |
| 604 | |
| 605 // |insets| are relative to contents bounds. Change them to be relative to | |
| 606 // local bounds. | |
| 607 gfx::Insets local_contents_insets = | |
| 608 GetLocalBounds().InsetsFrom(GetContentsBounds()); | |
| 609 MirrorInsetsIfNecessary(&local_contents_insets); | |
| 610 insets += local_contents_insets; | |
| 611 | |
| 612 return insets; | |
| 613 } | |
| 614 | |
| 615 gfx::Rect TrayBackgroundView::GetBackgroundBounds() const { | |
| 616 gfx::Insets insets = GetBackgroundInsets(); | |
| 617 gfx::Rect bounds = GetLocalBounds(); | |
| 618 bounds.Inset(insets); | |
| 619 return bounds; | |
| 620 } | |
| 621 | |
| 622 } // namespace ash | |
| OLD | NEW |