| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "views/controls/button/custom_button.h" | 5 #include "views/controls/button/custom_button.h" |
| 6 | 6 |
| 7 #include "app/throb_animation.h" | 7 #include "app/throb_animation.h" |
| 8 #include "base/keyboard_codes.h" | 8 #include "base/keyboard_codes.h" |
| 9 | 9 |
| 10 namespace views { | 10 namespace views { |
| 11 | 11 |
| 12 // How long the hover animation takes if uninterrupted. | 12 // How long the hover animation takes if uninterrupted. |
| 13 static const int kHoverFadeDurationMs = 150; | 13 static const int kHoverFadeDurationMs = 150; |
| 14 | 14 |
| 15 //////////////////////////////////////////////////////////////////////////////// | 15 //////////////////////////////////////////////////////////////////////////////// |
| 16 // CustomButton, public: | 16 // CustomButton, public: |
| 17 | 17 |
| 18 CustomButton::~CustomButton() { | 18 CustomButton::~CustomButton() { |
| 19 } | 19 } |
| 20 | 20 |
| 21 void CustomButton::SetState(ButtonState state) { | 21 void CustomButton::SetState(ButtonState state) { |
| 22 if (state != state_) { | 22 if (state == state_) |
| 23 if (animate_on_state_change_ || !hover_animation_->is_animating()) { | 23 return; |
| 24 animate_on_state_change_ = true; | 24 |
| 25 if (state_ == BS_NORMAL && state == BS_HOT) { | 25 if (animate_on_state_change_ || !hover_animation_->is_animating()) { |
| 26 // Button is hovered from a normal state, start hover animation. | 26 animate_on_state_change_ = true; |
| 27 hover_animation_->Show(); | 27 if (state_ == BS_NORMAL && state == BS_HOT) { |
| 28 } else if (state_ == BS_HOT && state == BS_NORMAL) { | 28 // Button is hovered from a normal state, start hover animation. |
| 29 // Button is returning to a normal state from hover, start hover | 29 hover_animation_->Show(); |
| 30 // fade animation. | 30 } else if (state_ == BS_HOT && state == BS_NORMAL) { |
| 31 hover_animation_->Hide(); | 31 // Button is returning to a normal state from hover, start hover |
| 32 } else { | 32 // fade animation. |
| 33 hover_animation_->Stop(); | 33 hover_animation_->Hide(); |
| 34 } | 34 } else { |
| 35 hover_animation_->Stop(); |
| 35 } | 36 } |
| 37 } |
| 36 | 38 |
| 37 state_ = state; | 39 state_ = state; |
| 38 SchedulePaint(); | 40 SchedulePaint(); |
| 39 } | |
| 40 } | 41 } |
| 41 | 42 |
| 42 void CustomButton::StartThrobbing(int cycles_til_stop) { | 43 void CustomButton::StartThrobbing(int cycles_til_stop) { |
| 43 animate_on_state_change_ = false; | 44 animate_on_state_change_ = false; |
| 44 hover_animation_->StartThrobbing(cycles_til_stop); | 45 hover_animation_->StartThrobbing(cycles_til_stop); |
| 45 } | 46 } |
| 46 | 47 |
| 47 void CustomButton::SetAnimationDuration(int duration) { | 48 void CustomButton::SetAnimationDuration(int duration) { |
| 48 hover_animation_->SetSlideDuration(duration); | 49 hover_animation_->SetSlideDuration(duration); |
| 49 } | 50 } |
| 50 | 51 |
| 51 //////////////////////////////////////////////////////////////////////////////// | 52 //////////////////////////////////////////////////////////////////////////////// |
| 52 // CustomButton, View overrides: | 53 // CustomButton, View overrides: |
| 53 | 54 |
| 54 bool CustomButton::GetAccessibleState(AccessibilityTypes::State* state) { | 55 bool CustomButton::GetAccessibleState(AccessibilityTypes::State* state) { |
| 55 *state = 0; | 56 *state = 0; |
| 56 switch (state_) { | 57 switch (state_) { |
| 57 case BS_NORMAL: | |
| 58 *state = 0; | |
| 59 case BS_HOT: | 58 case BS_HOT: |
| 60 *state = AccessibilityTypes::STATE_HOTTRACKED; | 59 *state = AccessibilityTypes::STATE_HOTTRACKED; |
| 61 case BS_PUSHED: | 60 case BS_PUSHED: |
| 62 *state = AccessibilityTypes::STATE_PRESSED; | 61 *state = AccessibilityTypes::STATE_PRESSED; |
| 63 case BS_DISABLED: | 62 case BS_DISABLED: |
| 64 *state = AccessibilityTypes::STATE_UNAVAILABLE; | 63 *state = AccessibilityTypes::STATE_UNAVAILABLE; |
| 64 case BS_NORMAL: |
| 65 case BS_COUNT: | 65 case BS_COUNT: |
| 66 // No additional accessibility state set for this button state. | 66 // No additional accessibility state set for this button state. |
| 67 break; | 67 break; |
| 68 } | 68 } |
| 69 | 69 |
| 70 return true; | 70 return true; |
| 71 } | 71 } |
| 72 | 72 |
| 73 void CustomButton::SetEnabled(bool enabled) { | 73 void CustomButton::SetEnabled(bool enabled) { |
| 74 if (enabled && state_ == BS_DISABLED) { | 74 if (enabled ? (state_ == BS_DISABLED) : (state_ != BS_DISABLED)) |
| 75 SetState(BS_NORMAL); | 75 SetState(enabled ? BS_NORMAL : BS_DISABLED); |
| 76 } else if (!enabled && state_ != BS_DISABLED) { | |
| 77 SetState(BS_DISABLED); | |
| 78 } | |
| 79 } | 76 } |
| 80 | 77 |
| 81 bool CustomButton::IsEnabled() const { | 78 bool CustomButton::IsEnabled() const { |
| 82 return state_ != BS_DISABLED; | 79 return state_ != BS_DISABLED; |
| 83 } | 80 } |
| 84 | 81 |
| 85 bool CustomButton::IsFocusable() const { | 82 bool CustomButton::IsFocusable() const { |
| 86 return (state_ != BS_DISABLED) && View::IsFocusable(); | 83 return (state_ != BS_DISABLED) && View::IsFocusable(); |
| 87 } | 84 } |
| 88 | 85 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 100 } | 97 } |
| 101 | 98 |
| 102 bool CustomButton::IsTriggerableEvent(const MouseEvent& e) { | 99 bool CustomButton::IsTriggerableEvent(const MouseEvent& e) { |
| 103 return (triggerable_event_flags_ & e.GetFlags()) != 0; | 100 return (triggerable_event_flags_ & e.GetFlags()) != 0; |
| 104 } | 101 } |
| 105 | 102 |
| 106 //////////////////////////////////////////////////////////////////////////////// | 103 //////////////////////////////////////////////////////////////////////////////// |
| 107 // CustomButton, View overrides (protected): | 104 // CustomButton, View overrides (protected): |
| 108 | 105 |
| 109 bool CustomButton::AcceleratorPressed(const Accelerator& accelerator) { | 106 bool CustomButton::AcceleratorPressed(const Accelerator& accelerator) { |
| 110 if (enabled_) { | 107 if (!enabled_) |
| 111 SetState(BS_NORMAL); | 108 return false; |
| 112 KeyEvent key_event(Event::ET_KEY_RELEASED, accelerator.GetKeyCode(), | 109 |
| 113 accelerator.modifiers(), 0, 0); | 110 SetState(BS_NORMAL); |
| 114 NotifyClick(key_event); | 111 KeyEvent key_event(Event::ET_KEY_RELEASED, accelerator.GetKeyCode(), |
| 115 return true; | 112 accelerator.modifiers(), 0, 0); |
| 116 } | 113 NotifyClick(key_event); |
| 117 return false; | 114 return true; |
| 118 } | 115 } |
| 119 | 116 |
| 120 bool CustomButton::OnMousePressed(const MouseEvent& e) { | 117 bool CustomButton::OnMousePressed(const MouseEvent& e) { |
| 121 if (state_ != BS_DISABLED) { | 118 if (state_ != BS_DISABLED) { |
| 122 if (ShouldEnterPushedState(e) && HitTest(e.location())) | 119 if (ShouldEnterPushedState(e) && HitTest(e.location())) |
| 123 SetState(BS_PUSHED); | 120 SetState(BS_PUSHED); |
| 124 if (request_focus_on_press_) | 121 if (request_focus_on_press_) |
| 125 RequestFocus(); | 122 RequestFocus(); |
| 126 } | 123 } |
| 127 return true; | 124 return true; |
| 128 } | 125 } |
| 129 | 126 |
| 130 bool CustomButton::OnMouseDragged(const MouseEvent& e) { | 127 bool CustomButton::OnMouseDragged(const MouseEvent& e) { |
| 131 if (state_ != BS_DISABLED) { | 128 if (state_ != BS_DISABLED) { |
| 132 if (!HitTest(e.location())) | 129 if (HitTest(e.location())) |
| 130 SetState(ShouldEnterPushedState(e) ? BS_PUSHED : BS_HOT); |
| 131 else |
| 133 SetState(BS_NORMAL); | 132 SetState(BS_NORMAL); |
| 134 else if (ShouldEnterPushedState(e)) | |
| 135 SetState(BS_PUSHED); | |
| 136 else | |
| 137 SetState(BS_HOT); | |
| 138 } | 133 } |
| 139 return true; | 134 return true; |
| 140 } | 135 } |
| 141 | 136 |
| 142 void CustomButton::OnMouseReleased(const MouseEvent& e, bool canceled) { | 137 void CustomButton::OnMouseReleased(const MouseEvent& e, bool canceled) { |
| 143 if (InDrag()) { | 138 // Starting a drag results in a MouseReleased, we need to ignore it. |
| 144 // Starting a drag results in a MouseReleased, we need to ignore it. | 139 if ((state_ == BS_DISABLED) || InDrag()) |
| 140 return; |
| 141 |
| 142 if (!HitTest(e.location())) { |
| 143 SetState(BS_NORMAL); |
| 145 return; | 144 return; |
| 146 } | 145 } |
| 147 | 146 |
| 148 if (state_ != BS_DISABLED) { | 147 SetState(BS_HOT); |
| 149 if (canceled || !HitTest(e.location())) { | 148 if (!canceled && IsTriggerableEvent(e)) { |
| 150 SetState(BS_NORMAL); | 149 NotifyClick(e); |
| 151 } else { | 150 // NOTE: We may be deleted at this point (by the listener's notification |
| 152 SetState(BS_HOT); | 151 // handler). |
| 153 if (IsTriggerableEvent(e)) { | |
| 154 NotifyClick(e); | |
| 155 // We may be deleted at this point (by the listener's notification | |
| 156 // handler) so no more doing anything, just return. | |
| 157 return; | |
| 158 } | |
| 159 } | |
| 160 } | 152 } |
| 161 } | 153 } |
| 162 | 154 |
| 163 void CustomButton::OnMouseEntered(const MouseEvent& e) { | 155 void CustomButton::OnMouseEntered(const MouseEvent& e) { |
| 164 if (state_ != BS_DISABLED) | 156 if (state_ != BS_DISABLED) |
| 165 SetState(BS_HOT); | 157 SetState(BS_HOT); |
| 166 } | 158 } |
| 167 | 159 |
| 168 void CustomButton::OnMouseMoved(const MouseEvent& e) { | 160 void CustomButton::OnMouseMoved(const MouseEvent& e) { |
| 169 if (state_ != BS_DISABLED) { | 161 if (state_ != BS_DISABLED) |
| 170 if (HitTest(e.location())) { | 162 SetState(HitTest(e.location()) ? BS_HOT : BS_NORMAL); |
| 171 SetState(BS_HOT); | |
| 172 } else { | |
| 173 SetState(BS_NORMAL); | |
| 174 } | |
| 175 } | |
| 176 } | 163 } |
| 177 | 164 |
| 178 void CustomButton::OnMouseExited(const MouseEvent& e) { | 165 void CustomButton::OnMouseExited(const MouseEvent& e) { |
| 179 // Starting a drag results in a MouseExited, we need to ignore it. | 166 // Starting a drag results in a MouseExited, we need to ignore it. |
| 180 if (state_ != BS_DISABLED && !InDrag()) | 167 if (state_ != BS_DISABLED && !InDrag()) |
| 181 SetState(BS_NORMAL); | 168 SetState(BS_NORMAL); |
| 182 } | 169 } |
| 183 | 170 |
| 184 bool CustomButton::OnKeyPressed(const KeyEvent& e) { | 171 bool CustomButton::OnKeyPressed(const KeyEvent& e) { |
| 185 if (state_ != BS_DISABLED) { | 172 if (state_ == BS_DISABLED) |
| 186 // Space sets button state to pushed. Enter clicks the button. This matches | 173 return false; |
| 187 // the Windows native behavior of buttons, where Space clicks the button | 174 |
| 188 // on KeyRelease and Enter clicks the button on KeyPressed. | 175 // Space sets button state to pushed. Enter clicks the button. This matches |
| 189 if (e.GetKeyCode() == base::VKEY_SPACE) { | 176 // the Windows native behavior of buttons, where Space clicks the button on |
| 190 SetState(BS_PUSHED); | 177 // KeyRelease and Enter clicks the button on KeyPressed. |
| 191 return true; | 178 if (e.GetKeyCode() == base::VKEY_SPACE) { |
| 192 } else if (e.GetKeyCode() == base::VKEY_RETURN) { | 179 SetState(BS_PUSHED); |
| 193 SetState(BS_NORMAL); | 180 } else if (e.GetKeyCode() == base::VKEY_RETURN) { |
| 194 NotifyClick(e); | 181 SetState(BS_NORMAL); |
| 195 return true; | 182 NotifyClick(e); |
| 196 } | |
| 197 } | 183 } |
| 198 return false; | 184 return true; |
| 199 } | 185 } |
| 200 | 186 |
| 201 bool CustomButton::OnKeyReleased(const KeyEvent& e) { | 187 bool CustomButton::OnKeyReleased(const KeyEvent& e) { |
| 202 if (state_ != BS_DISABLED) { | 188 if ((state_ == BS_DISABLED) || (e.GetKeyCode() != base::VKEY_SPACE)) |
| 203 if (e.GetKeyCode() == base::VKEY_SPACE) { | 189 return false; |
| 204 SetState(BS_NORMAL); | 190 |
| 205 NotifyClick(e); | 191 SetState(BS_NORMAL); |
| 206 return true; | 192 NotifyClick(e); |
| 207 } | 193 return true; |
| 208 } | |
| 209 return false; | |
| 210 } | 194 } |
| 211 | 195 |
| 212 void CustomButton::OnDragDone() { | 196 void CustomButton::OnDragDone() { |
| 213 SetState(BS_NORMAL); | 197 SetState(BS_NORMAL); |
| 214 } | 198 } |
| 215 | 199 |
| 216 void CustomButton::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) { | 200 void CustomButton::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) { |
| 217 if (GetContextMenuController()) { | 201 if (!GetContextMenuController()) |
| 218 // We're about to show the context menu. Showing the context menu likely | 202 return; |
| 219 // means we won't get a mouse exited and reset state. Reset it now to be | 203 |
| 220 // sure. | 204 // We're about to show the context menu. Showing the context menu likely means |
| 221 if (state_ != BS_DISABLED) | 205 // we won't get a mouse exited and reset state. Reset it now to be sure. |
| 222 SetState(BS_NORMAL); | 206 if (state_ != BS_DISABLED) |
| 223 View::ShowContextMenu(p, is_mouse_gesture); | 207 SetState(BS_NORMAL); |
| 224 } | 208 View::ShowContextMenu(p, is_mouse_gesture); |
| 225 } | 209 } |
| 226 | 210 |
| 227 void CustomButton::ViewHierarchyChanged(bool is_add, View *parent, | 211 void CustomButton::ViewHierarchyChanged(bool is_add, View *parent, |
| 228 View *child) { | 212 View *child) { |
| 229 if (!is_add && state_ != BS_DISABLED) | 213 if (!is_add && state_ != BS_DISABLED) |
| 230 SetState(BS_NORMAL); | 214 SetState(BS_NORMAL); |
| 231 } | 215 } |
| 232 | 216 |
| 233 void CustomButton::SetHotTracked(bool flag) { | 217 void CustomButton::SetHotTracked(bool flag) { |
| 234 if (state_ != BS_DISABLED) | 218 if (state_ != BS_DISABLED) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 251 // CustomButton, AnimationDelegate implementation: | 235 // CustomButton, AnimationDelegate implementation: |
| 252 | 236 |
| 253 void CustomButton::AnimationProgressed(const Animation* animation) { | 237 void CustomButton::AnimationProgressed(const Animation* animation) { |
| 254 SchedulePaint(); | 238 SchedulePaint(); |
| 255 } | 239 } |
| 256 | 240 |
| 257 bool CustomButton::ShouldEnterPushedState(const MouseEvent& e) { | 241 bool CustomButton::ShouldEnterPushedState(const MouseEvent& e) { |
| 258 return IsTriggerableEvent(e); | 242 return IsTriggerableEvent(e); |
| 259 } | 243 } |
| 260 | 244 |
| 261 //////////////////////////////////////////////////////////////////////////////// | |
| 262 // CustomButton, private: | |
| 263 | |
| 264 void CustomButton::SetHighlighted(bool highlighted) { | |
| 265 if (highlighted && state_ != BS_DISABLED) { | |
| 266 SetState(BS_HOT); | |
| 267 } else if (!highlighted && state_ != BS_DISABLED) { | |
| 268 SetState(BS_NORMAL); | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 bool CustomButton::IsHighlighted() const { | |
| 273 return state_ == BS_HOT; | |
| 274 } | |
| 275 | |
| 276 bool CustomButton::IsPushed() const { | |
| 277 return state_ == BS_PUSHED; | |
| 278 } | |
| 279 | |
| 280 } // namespace views | 245 } // namespace views |
| OLD | NEW |