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 |