1 // Copyright 2013 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 #ifndef ASH_SHELF_SHELF_APP_BUTTON_H_ 6 #define ASH_SHELF_SHELF_APP_BUTTON_H_ 7 8 #include "ash/ash_export.h" 9 #include "ash/shelf/shelf_button.h" 10 #include "ash/shelf/shelf_button_delegate.h" 11 #include "base/macros.h" 12 #include "base/timer/timer.h" 13 #include "ui/compositor/layer_animation_observer.h" 14 #include "ui/gfx/shadow_value.h" 15 #include "ui/views/animation/ink_drop_observer.h" 16 #include "ui/views/animation/ink_drop_state.h" 17 18 namespace views { 19 class ImageView; 20 } 21 22 namespace ash { 23 struct ShelfItem; 24 class ShelfView; 25 26 // Button used for app shortcuts on the shelf.. 27 class ASH_EXPORT ShelfAppButton : public ShelfButton, 28 public views::InkDropObserver, 29 public ui::ImplicitAnimationObserver { 30 public: 31 static const char kViewClassName[]; 32 33 // Used to indicate the current state of the button. 34 enum State { 35 // Nothing special. Usually represents an app shortcut item with no running 36 // instance. 37 STATE_NORMAL = 0, 38 // Button has mouse hovering on it. 39 STATE_HOVERED = 1 << 0, 40 // Underlying ShelfItem has a running instance. 41 STATE_RUNNING = 1 << 1, 42 // Underlying ShelfItem needs user's attention. 43 STATE_ATTENTION = 1 << 2, 44 // Hide the status (temporarily for some animations). 45 STATE_HIDDEN = 1 << 3, 46 // Button is being dragged. 47 STATE_DRAGGING = 1 << 4, 48 // App has at least 1 notification. 49 STATE_NOTIFICATION = 1 << 5, 50 // Underlying ShelfItem owns the window that is currently active. 51 STATE_ACTIVE = 1 << 6, 52 }; 53 54 // Returns whether |event| should be handled by a ShelfAppButton if a context 55 // menu for the view is shown. Note that the context menu controller will 56 // redirect gesture events to the hotseat widget if the context menu was shown 57 // for a ShelfAppButton). The hotseat widget uses this method to determine 58 // whether such events can/should be dropped without handling. 59 static bool ShouldHandleEventFromContextMenu(const ui::GestureEvent* event); 60 61 ShelfAppButton(ShelfView* shelf_view, 62 ShelfButtonDelegate* shelf_button_delegate); 63 ~ShelfAppButton() override; 64 65 // Sets the image to display for this entry. 66 void SetImage(const gfx::ImageSkia& image); 67 68 // Retrieve the image to show proxy operations. 69 const gfx::ImageSkia& GetImage() const; 70 71 // |state| is or'd into the current state. 72 void AddState(State state); 73 void ClearState(State state); state()74 int state() const { return state_; } 75 76 // Clears drag drag state that might have been set by gesture handling when a 77 // gesture ends. No-op if the drag state has already been cleared. 78 void ClearDragStateOnGestureEnd(); 79 80 // Returns the bounds of the icon. 81 gfx::Rect GetIconBounds() const; 82 83 // Returns the bounds of the icon in screen coordinates. 84 gfx::Rect GetIconBoundsInScreen() const; 85 86 views::InkDrop* GetInkDropForTesting(); 87 88 // Called when user started dragging the shelf button. 89 void OnDragStarted(const ui::LocatedEvent* event); 90 91 // Callback used when a menu for this ShelfAppButton is closed. 92 void OnMenuClosed(); 93 94 // views::Button overrides: 95 void ShowContextMenu(const gfx::Point& p, 96 ui::MenuSourceType source_type) override; 97 void GetAccessibleNodeData(ui::AXNodeData* node_data) override; 98 bool ShouldEnterPushedState(const ui::Event& event) override; 99 100 // views::View overrides: 101 const char* GetClassName() const override; 102 bool OnMousePressed(const ui::MouseEvent& event) override; 103 void OnMouseReleased(const ui::MouseEvent& event) override; 104 void OnMouseCaptureLost() override; 105 bool OnMouseDragged(const ui::MouseEvent& event) override; 106 void Layout() override; 107 void ChildPreferredSizeChanged(views::View* child) override; 108 109 // Update button state from ShelfItem. 110 void ReflectItemStatus(const ShelfItem& item); 111 112 // Returns whether the icon size is up to date. 113 bool IsIconSizeCurrent(); 114 115 bool FireDragTimerForTest(); 116 void FireRippleActivationTimerForTest(); 117 118 // Return the bounds in the local coordinates enclosing the small ripple area. 119 gfx::Rect CalculateSmallRippleArea() const; 120 121 // Gets the color of the |notification_indicator_| for test usage. 122 SkColor GetNotificationIndicatorColorForTest(); 123 124 protected: 125 // ui::EventHandler: 126 void OnGestureEvent(ui::GestureEvent* event) override; 127 128 // views::Button: 129 std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; 130 131 // ui::ImplicitAnimationObserver: 132 void OnImplicitAnimationsCompleted() override; 133 134 // Sets the icon image with a shadow. 135 void SetShadowedImage(const gfx::ImageSkia& bitmap); 136 137 private: 138 class AppNotificationIndicatorView; 139 class AppStatusIndicatorView; 140 141 // views::View: 142 bool HandleAccessibleAction(const ui::AXActionData& action_data) override; 143 144 // views::InkDropObserver: 145 void InkDropAnimationStarted() override; 146 void InkDropRippleAnimationEnded(views::InkDropState state) override; 147 148 // Updates the parts of the button to reflect the current |state_| and 149 // alignment. This may add or remove views, layout and paint. 150 void UpdateState(); 151 152 // Invoked when |touch_drag_timer_| fires to show dragging UI. 153 void OnTouchDragTimer(); 154 155 // Invoked when |ripple_activation_timer_| fires to activate the ink drop. 156 void OnRippleTimer(); 157 158 // Scales up app icon if |scale_up| is true, otherwise scales it back to 159 // normal size. 160 void ScaleAppIcon(bool scale_up); 161 162 // Calculates the icon bounds for an icon scaled by |icon_scale|. 163 gfx::Rect GetIconViewBounds(float icon_scale); 164 165 // Calculates the transform between the icon scaled by |icon_scale| and the 166 // normal size icon. 167 gfx::Transform GetScaleTransform(float icon_scale); 168 169 // Marks whether the ink drop animation has started or not. 170 void SetInkDropAnimationStarted(bool started); 171 172 // The icon part of a button can be animated independently of the rest. 173 views::ImageView* icon_view_; 174 175 // The ShelfView showing this ShelfAppButton. Owned by RootWindowController. 176 ShelfView* shelf_view_; 177 178 // Draws an indicator underneath the image to represent the state of the 179 // application. 180 AppStatusIndicatorView* indicator_; 181 182 // Draws an indicator in the top right corner of the image to represent an 183 // active notification. 184 AppNotificationIndicatorView* notification_indicator_; 185 186 // The current application state, a bitfield of State enum values. 187 int state_; 188 189 gfx::ShadowValues icon_shadows_; 190 191 // If non-null the destuctor sets this to true. This is set while the menu is 192 // showing and used to detect if the menu was deleted while running. 193 bool* destroyed_flag_; 194 195 // Whether the notification indicator is enabled. 196 const bool is_notification_indicator_enabled_; 197 198 // The bitmap image for this app button. 199 gfx::ImageSkia icon_image_; 200 201 // The scaling factor for displaying the app icon. 202 float icon_scale_ = 1.0f; 203 204 // Indicates whether the ink drop animation starts. 205 bool ink_drop_animation_started_ = false; 206 207 // A timer to defer showing drag UI when the shelf button is pressed. 208 base::OneShotTimer drag_timer_; 209 210 // A timer to activate the ink drop ripple during a long press. 211 base::OneShotTimer ripple_activation_timer_; 212 213 std::unique_ptr<ShelfButtonDelegate::ScopedActiveInkDropCount> 214 ink_drop_count_; 215 216 DISALLOW_COPY_AND_ASSIGN(ShelfAppButton); 217 }; 218 219 } // namespace ash 220 221 #endif // ASH_SHELF_SHELF_APP_BUTTON_H_ 222