| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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/shelf/app_list_button.h" | |
| 6 | |
| 7 #include "ash/common/shelf/ink_drop_button_listener.h" | |
| 8 #include "ash/common/shelf/shelf_constants.h" | |
| 9 #include "ash/common/shelf/shelf_view.h" | |
| 10 #include "ash/common/shelf/wm_shelf.h" | |
| 11 #include "ash/common/wm_shell.h" | |
| 12 #include "ash/public/cpp/shelf_types.h" | |
| 13 #include "ash/strings/grit/ash_strings.h" | |
| 14 #include "ash/system/tray/tray_popup_utils.h" | |
| 15 #include "base/memory/ptr_util.h" | |
| 16 #include "ui/accessibility/ax_node_data.h" | |
| 17 #include "ui/base/l10n/l10n_util.h" | |
| 18 #include "ui/gfx/canvas.h" | |
| 19 #include "ui/gfx/scoped_canvas.h" | |
| 20 #include "ui/views/animation/flood_fill_ink_drop_ripple.h" | |
| 21 #include "ui/views/animation/ink_drop_impl.h" | |
| 22 #include "ui/views/animation/ink_drop_mask.h" | |
| 23 #include "ui/views/painter.h" | |
| 24 | |
| 25 namespace ash { | |
| 26 | |
| 27 AppListButton::AppListButton(InkDropButtonListener* listener, | |
| 28 ShelfView* shelf_view, | |
| 29 WmShelf* wm_shelf) | |
| 30 : views::ImageButton(nullptr), | |
| 31 is_showing_app_list_(false), | |
| 32 background_color_(kShelfDefaultBaseColor), | |
| 33 listener_(listener), | |
| 34 shelf_view_(shelf_view), | |
| 35 wm_shelf_(wm_shelf) { | |
| 36 DCHECK(listener_); | |
| 37 DCHECK(shelf_view_); | |
| 38 DCHECK(wm_shelf_); | |
| 39 | |
| 40 SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); | |
| 41 set_ink_drop_base_color(kShelfInkDropBaseColor); | |
| 42 set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity); | |
| 43 SetAccessibleName( | |
| 44 l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE)); | |
| 45 SetSize( | |
| 46 gfx::Size(GetShelfConstant(SHELF_SIZE), GetShelfConstant(SHELF_SIZE))); | |
| 47 SetFocusPainter(TrayPopupUtils::CreateFocusPainter()); | |
| 48 set_notify_action(CustomButton::NOTIFY_ON_PRESS); | |
| 49 } | |
| 50 | |
| 51 AppListButton::~AppListButton() {} | |
| 52 | |
| 53 void AppListButton::OnAppListShown() { | |
| 54 AnimateInkDrop(views::InkDropState::ACTIVATED, nullptr); | |
| 55 is_showing_app_list_ = true; | |
| 56 wm_shelf_->UpdateAutoHideState(); | |
| 57 } | |
| 58 | |
| 59 void AppListButton::OnAppListDismissed() { | |
| 60 AnimateInkDrop(views::InkDropState::DEACTIVATED, nullptr); | |
| 61 is_showing_app_list_ = false; | |
| 62 wm_shelf_->UpdateAutoHideState(); | |
| 63 } | |
| 64 | |
| 65 void AppListButton::UpdateShelfItemBackground(SkColor color) { | |
| 66 background_color_ = color; | |
| 67 SchedulePaint(); | |
| 68 } | |
| 69 | |
| 70 bool AppListButton::OnMousePressed(const ui::MouseEvent& event) { | |
| 71 ImageButton::OnMousePressed(event); | |
| 72 shelf_view_->PointerPressedOnButton(this, ShelfView::MOUSE, event); | |
| 73 return true; | |
| 74 } | |
| 75 | |
| 76 void AppListButton::OnMouseReleased(const ui::MouseEvent& event) { | |
| 77 ImageButton::OnMouseReleased(event); | |
| 78 shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, false); | |
| 79 } | |
| 80 | |
| 81 void AppListButton::OnMouseCaptureLost() { | |
| 82 shelf_view_->PointerReleasedOnButton(this, ShelfView::MOUSE, true); | |
| 83 ImageButton::OnMouseCaptureLost(); | |
| 84 } | |
| 85 | |
| 86 bool AppListButton::OnMouseDragged(const ui::MouseEvent& event) { | |
| 87 ImageButton::OnMouseDragged(event); | |
| 88 shelf_view_->PointerDraggedOnButton(this, ShelfView::MOUSE, event); | |
| 89 return true; | |
| 90 } | |
| 91 | |
| 92 void AppListButton::OnGestureEvent(ui::GestureEvent* event) { | |
| 93 switch (event->type()) { | |
| 94 case ui::ET_GESTURE_SCROLL_BEGIN: | |
| 95 AnimateInkDrop(views::InkDropState::HIDDEN, event); | |
| 96 shelf_view_->PointerPressedOnButton(this, ShelfView::TOUCH, *event); | |
| 97 event->SetHandled(); | |
| 98 return; | |
| 99 case ui::ET_GESTURE_SCROLL_UPDATE: | |
| 100 shelf_view_->PointerDraggedOnButton(this, ShelfView::TOUCH, *event); | |
| 101 event->SetHandled(); | |
| 102 return; | |
| 103 case ui::ET_GESTURE_SCROLL_END: | |
| 104 case ui::ET_SCROLL_FLING_START: | |
| 105 shelf_view_->PointerReleasedOnButton(this, ShelfView::TOUCH, false); | |
| 106 event->SetHandled(); | |
| 107 return; | |
| 108 case ui::ET_GESTURE_TAP_DOWN: | |
| 109 if (!WmShell::Get()->IsApplistVisible()) | |
| 110 AnimateInkDrop(views::InkDropState::ACTION_PENDING, event); | |
| 111 ImageButton::OnGestureEvent(event); | |
| 112 break; | |
| 113 default: | |
| 114 ImageButton::OnGestureEvent(event); | |
| 115 return; | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 void AppListButton::OnPaint(gfx::Canvas* canvas) { | |
| 120 // Call the base class first to paint any background/borders. | |
| 121 View::OnPaint(canvas); | |
| 122 | |
| 123 gfx::PointF circle_center(GetCenterPoint()); | |
| 124 | |
| 125 // Paint the circular background. | |
| 126 cc::PaintFlags bg_flags; | |
| 127 bg_flags.setColor(background_color_); | |
| 128 bg_flags.setAntiAlias(true); | |
| 129 bg_flags.setStyle(cc::PaintFlags::kFill_Style); | |
| 130 canvas->DrawCircle(circle_center, kAppListButtonRadius, bg_flags); | |
| 131 | |
| 132 // Paint a white ring as the foreground. The ceil/dsf math assures that the | |
| 133 // ring draws sharply and is centered at all scale factors. | |
| 134 const float kRingOuterRadiusDp = 7.f; | |
| 135 const float kRingThicknessDp = 1.5f; | |
| 136 gfx::ScopedCanvas scoped_canvas(canvas); | |
| 137 const float dsf = canvas->UndoDeviceScaleFactor(); | |
| 138 circle_center.Scale(dsf); | |
| 139 | |
| 140 cc::PaintFlags fg_flags; | |
| 141 fg_flags.setAntiAlias(true); | |
| 142 fg_flags.setStyle(cc::PaintFlags::kStroke_Style); | |
| 143 fg_flags.setColor(kShelfIconColor); | |
| 144 const float thickness = std::ceil(kRingThicknessDp * dsf); | |
| 145 const float radius = std::ceil(kRingOuterRadiusDp * dsf) - thickness / 2; | |
| 146 fg_flags.setStrokeWidth(thickness); | |
| 147 // Make sure the center of the circle lands on pixel centers. | |
| 148 canvas->DrawCircle(circle_center, radius, fg_flags); | |
| 149 | |
| 150 views::Painter::PaintFocusPainter(this, canvas, focus_painter()); | |
| 151 } | |
| 152 | |
| 153 void AppListButton::GetAccessibleNodeData(ui::AXNodeData* node_data) { | |
| 154 node_data->role = ui::AX_ROLE_BUTTON; | |
| 155 node_data->SetName(shelf_view_->GetTitleForView(this)); | |
| 156 } | |
| 157 | |
| 158 std::unique_ptr<views::InkDropRipple> AppListButton::CreateInkDropRipple() | |
| 159 const { | |
| 160 gfx::Point center = GetCenterPoint(); | |
| 161 gfx::Rect bounds(center.x() - kAppListButtonRadius, | |
| 162 center.y() - kAppListButtonRadius, 2 * kAppListButtonRadius, | |
| 163 2 * kAppListButtonRadius); | |
| 164 return base::MakeUnique<views::FloodFillInkDropRipple>( | |
| 165 size(), GetLocalBounds().InsetsFrom(bounds), | |
| 166 GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(), | |
| 167 ink_drop_visible_opacity()); | |
| 168 } | |
| 169 | |
| 170 void AppListButton::NotifyClick(const ui::Event& event) { | |
| 171 ImageButton::NotifyClick(event); | |
| 172 if (listener_) | |
| 173 listener_->ButtonPressed(this, event, GetInkDrop()); | |
| 174 } | |
| 175 | |
| 176 bool AppListButton::ShouldEnterPushedState(const ui::Event& event) { | |
| 177 if (!shelf_view_->ShouldEventActivateButton(this, event)) | |
| 178 return false; | |
| 179 if (WmShell::Get()->IsApplistVisible()) | |
| 180 return false; | |
| 181 return views::ImageButton::ShouldEnterPushedState(event); | |
| 182 } | |
| 183 | |
| 184 std::unique_ptr<views::InkDrop> AppListButton::CreateInkDrop() { | |
| 185 std::unique_ptr<views::InkDropImpl> ink_drop = | |
| 186 CustomButton::CreateDefaultInkDropImpl(); | |
| 187 ink_drop->SetShowHighlightOnHover(false); | |
| 188 return std::move(ink_drop); | |
| 189 } | |
| 190 | |
| 191 std::unique_ptr<views::InkDropMask> AppListButton::CreateInkDropMask() const { | |
| 192 return base::MakeUnique<views::CircleInkDropMask>(size(), GetCenterPoint(), | |
| 193 kAppListButtonRadius); | |
| 194 } | |
| 195 | |
| 196 gfx::Point AppListButton::GetCenterPoint() const { | |
| 197 // For a bottom-aligned shelf, the button bounds could have a larger height | |
| 198 // than width (in the case of touch-dragging the shelf updwards) or a larger | |
| 199 // width than height (in the case of a shelf hide/show animation), so adjust | |
| 200 // the y-position of the circle's center to ensure correct layout. Similarly | |
| 201 // adjust the x-position for a left- or right-aligned shelf. | |
| 202 const int x_mid = width() / 2.f; | |
| 203 const int y_mid = height() / 2.f; | |
| 204 ShelfAlignment alignment = wm_shelf_->GetAlignment(); | |
| 205 if (alignment == SHELF_ALIGNMENT_BOTTOM || | |
| 206 alignment == SHELF_ALIGNMENT_BOTTOM_LOCKED) { | |
| 207 return gfx::Point(x_mid, x_mid); | |
| 208 } else if (alignment == SHELF_ALIGNMENT_RIGHT) { | |
| 209 return gfx::Point(y_mid, y_mid); | |
| 210 } else { | |
| 211 DCHECK_EQ(alignment, SHELF_ALIGNMENT_LEFT); | |
| 212 return gfx::Point(width() - y_mid, y_mid); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 } // namespace ash | |
| OLD | NEW |