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/shelf/app_list_button.h" 6 7 #include "ash/ash_constants.h" 8 #include "ash/ash_switches.h" 9 #include "ash/shelf/shelf_button.h" 10 #include "ash/shelf/shelf_button_host.h" 11 #include "ash/shelf/shelf_item_types.h" 12 #include "ash/shelf/shelf_layout_manager.h" 13 #include "ash/shelf/shelf_widget.h" 14 #include "ash/shell.h" 15 #include "base/command_line.h" 16 #include "grit/ash_resources.h" 17 #include "grit/ash_strings.h" 18 #include "ui/accessibility/ax_view_state.h" 19 #include "ui/base/l10n/l10n_util.h" 20 #include "ui/base/resource/resource_bundle.h" 21 #include "ui/compositor/layer.h" 22 #include "ui/compositor/layer_animation_element.h" 23 #include "ui/compositor/layer_animation_sequence.h" 24 #include "ui/compositor/scoped_layer_animation_settings.h" 25 #include "ui/gfx/canvas.h" 26 #include "ui/gfx/image/image_skia_operations.h" 27 #include "ui/views/controls/button/image_button.h" 28 #include "ui/views/painter.h" 29 30 namespace ash { 31 // static 32 const int AppListButton::kImageBoundsSize = 7; 33 34 35 AppListButton::AppListButton(views::ButtonListener* listener, 36 ShelfButtonHost* host, 37 ShelfWidget* shelf_widget) 38 : views::ImageButton(listener), 39 draw_background_as_active_(false), 40 touch_feedback_enabled_(CommandLine::ForCurrentProcess()-> 41 HasSwitch(switches::kAshEnableTouchViewTouchFeedback)), 42 host_(host), 43 shelf_widget_(shelf_widget) { 44 SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_TITLE)); 45 SetSize(gfx::Size(kShelfSize, kShelfSize)); 46 SetFocusPainter(views::Painter::CreateSolidFocusPainter( 47 kFocusBorderColor, gfx::Insets(1, 1, 1, 1))); 48 } 49 50 AppListButton::~AppListButton() { 51 } 52 53 bool AppListButton::OnMousePressed(const ui::MouseEvent& event) { 54 ImageButton::OnMousePressed(event); 55 host_->PointerPressedOnButton(this, ShelfButtonHost::MOUSE, event); 56 return true; 57 } 58 59 void AppListButton::OnMouseReleased(const ui::MouseEvent& event) { 60 ImageButton::OnMouseReleased(event); 61 host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, false); 62 } 63 64 void AppListButton::OnMouseCaptureLost() { 65 host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, true); 66 ImageButton::OnMouseCaptureLost(); 67 } 68 69 bool AppListButton::OnMouseDragged(const ui::MouseEvent& event) { 70 ImageButton::OnMouseDragged(event); 71 host_->PointerDraggedOnButton(this, ShelfButtonHost::MOUSE, event); 72 return true; 73 } 74 75 void AppListButton::OnMouseMoved(const ui::MouseEvent& event) { 76 ImageButton::OnMouseMoved(event); 77 host_->MouseMovedOverButton(this); 78 } 79 80 void AppListButton::OnMouseEntered(const ui::MouseEvent& event) { 81 ImageButton::OnMouseEntered(event); 82 host_->MouseEnteredButton(this); 83 } 84 85 void AppListButton::OnMouseExited(const ui::MouseEvent& event) { 86 ImageButton::OnMouseExited(event); 87 host_->MouseExitedButton(this); 88 } 89 90 void AppListButton::OnGestureEvent(ui::GestureEvent* event) { 91 switch (event->type()) { 92 case ui::ET_GESTURE_SCROLL_BEGIN: 93 if (touch_feedback_enabled_) 94 SetDrawBackgroundAsActive(false); 95 host_->PointerPressedOnButton(this, ShelfButtonHost::TOUCH, *event); 96 event->SetHandled(); 97 return; 98 case ui::ET_GESTURE_SCROLL_UPDATE: 99 host_->PointerDraggedOnButton(this, ShelfButtonHost::TOUCH, *event); 100 event->SetHandled(); 101 return; 102 case ui::ET_GESTURE_SCROLL_END: 103 case ui::ET_SCROLL_FLING_START: 104 host_->PointerReleasedOnButton(this, ShelfButtonHost::TOUCH, false); 105 event->SetHandled(); 106 return; 107 case ui::ET_GESTURE_TAP_DOWN: 108 if (touch_feedback_enabled_) 109 SetDrawBackgroundAsActive(true); 110 ImageButton::OnGestureEvent(event); 111 break; 112 case ui::ET_GESTURE_TAP_CANCEL: 113 case ui::ET_GESTURE_TAP: 114 if (touch_feedback_enabled_) 115 SetDrawBackgroundAsActive(false); 116 ImageButton::OnGestureEvent(event); 117 break; 118 default: 119 ImageButton::OnGestureEvent(event); 120 return; 121 } 122 } 123 124 void AppListButton::OnPaint(gfx::Canvas* canvas) { 125 // Call the base class first to paint any background/borders. 126 View::OnPaint(canvas); 127 128 int background_image_id = 0; 129 if (Shell::GetInstance()->GetAppListTargetVisibility() || 130 draw_background_as_active_) { 131 background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED; 132 } else { 133 if (shelf_widget_->GetDimsShelf()) 134 background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK; 135 else 136 background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL; 137 } 138 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 139 const gfx::ImageSkia* background_image = 140 rb.GetImageNamed(background_image_id).ToImageSkia(); 141 const gfx::ImageSkia* forground_image = 142 rb.GetImageNamed(IDR_ASH_SHELF_ICON_APPLIST).ToImageSkia(); 143 144 gfx::Rect contents_bounds = GetContentsBounds(); 145 gfx::Rect background_bounds, forground_bounds; 146 147 ShelfAlignment alignment = shelf_widget_->GetAlignment(); 148 background_bounds.set_size(background_image->size()); 149 if (alignment == SHELF_ALIGNMENT_LEFT) { 150 background_bounds.set_x(contents_bounds.width() - 151 ShelfLayoutManager::kShelfItemInset - background_image->width()); 152 background_bounds.set_y(contents_bounds.y() + 153 (contents_bounds.height() - background_image->height()) / 2); 154 } else if(alignment == SHELF_ALIGNMENT_RIGHT) { 155 background_bounds.set_x(ShelfLayoutManager::kShelfItemInset); 156 background_bounds.set_y(contents_bounds.y() + 157 (contents_bounds.height() - background_image->height()) / 2); 158 } else { 159 background_bounds.set_y(ShelfLayoutManager::kShelfItemInset); 160 background_bounds.set_x(contents_bounds.x() + 161 (contents_bounds.width() - background_image->width()) / 2); 162 } 163 164 forground_bounds.set_size(forground_image->size()); 165 forground_bounds.set_x(background_bounds.x() + 166 std::max(0, 167 (background_bounds.width() - forground_bounds.width()) / 2)); 168 forground_bounds.set_y(background_bounds.y() + 169 std::max(0, 170 (background_bounds.height() - forground_bounds.height()) / 2)); 171 172 canvas->DrawImageInt(*background_image, 173 background_bounds.x(), 174 background_bounds.y()); 175 canvas->DrawImageInt(*forground_image, 176 forground_bounds.x(), 177 forground_bounds.y()); 178 179 views::Painter::PaintFocusPainter(this, canvas, focus_painter()); 180 } 181 182 void AppListButton::GetAccessibleState(ui::AXViewState* state) { 183 state->role = ui::AX_ROLE_BUTTON; 184 state->name = host_->GetAccessibleName(this); 185 } 186 187 void AppListButton::SetDrawBackgroundAsActive( 188 bool draw_background_as_active) { 189 if (draw_background_as_active_ == draw_background_as_active) 190 return; 191 draw_background_as_active_ = draw_background_as_active; 192 SchedulePaint(); 193 } 194 195 } // namespace ash 196