| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "ash/common/shelf/shelf_button.h" | 5 #include "ash/common/shelf/shelf_button.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "ash/common/ash_constants.h" | 9 #include "ash/common/ash_constants.h" |
| 10 #include "ash/common/shelf/ink_drop_button_listener.h" | 10 #include "ash/common/shelf/ink_drop_button_listener.h" |
| 11 #include "ash/common/shelf/shelf_constants.h" | 11 #include "ash/common/shelf/shelf_constants.h" |
| 12 #include "ash/common/shelf/shelf_view.h" | 12 #include "ash/common/shelf/shelf_view.h" |
| 13 #include "ash/common/shelf/wm_shelf.h" | 13 #include "ash/common/shelf/wm_shelf.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 16 #include "skia/ext/image_operations.h" | 16 #include "skia/ext/image_operations.h" |
| 17 #include "ui/accessibility/ax_node_data.h" | 17 #include "ui/accessibility/ax_node_data.h" |
| 18 #include "ui/compositor/layer.h" | 18 #include "ui/compositor/layer.h" |
| 19 #include "ui/gfx/animation/animation_delegate.h" | 19 #include "ui/gfx/animation/animation_delegate.h" |
| 20 #include "ui/gfx/animation/throb_animation.h" | 20 #include "ui/gfx/animation/throb_animation.h" |
| 21 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
| 22 #include "ui/gfx/geometry/vector2d.h" | 22 #include "ui/gfx/geometry/vector2d.h" |
| 23 #include "ui/gfx/image/image_skia_operations.h" | 23 #include "ui/gfx/image/image_skia_operations.h" |
| 24 #include "ui/gfx/scoped_canvas.h" |
| 24 #include "ui/gfx/skbitmap_operations.h" | 25 #include "ui/gfx/skbitmap_operations.h" |
| 25 #include "ui/views/animation/ink_drop_impl.h" | 26 #include "ui/views/animation/ink_drop_impl.h" |
| 26 #include "ui/views/animation/square_ink_drop_ripple.h" | 27 #include "ui/views/animation/square_ink_drop_ripple.h" |
| 27 #include "ui/views/controls/image_view.h" | 28 #include "ui/views/controls/image_view.h" |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 // Size of the bar. This is along the opposite axis of the shelf. For example, | |
| 32 // if the shelf is aligned horizontally then this is the height of the bar. | |
| 33 const int kBarSize = 3; | |
| 34 const int kIconSize = 32; | 32 const int kIconSize = 32; |
| 35 const int kAttentionThrobDurationMS = 800; | 33 const int kAttentionThrobDurationMS = 800; |
| 36 const int kMaxAnimationSeconds = 10; | 34 const int kMaxAnimationSeconds = 10; |
| 37 const int kIndicatorOffsetFromBottom = 2; | 35 const int kIndicatorOffsetFromBottom = 2; |
| 38 const int kIndicatorRadius = 2; | 36 const int kIndicatorRadiusDip = 2; |
| 39 const SkColor kIndicatorColor = SK_ColorWHITE; | 37 const SkColor kIndicatorColor = SK_ColorWHITE; |
| 40 // Canvas scale to ensure that the activity indicator is not pixelated even at | |
| 41 // the highest possible device scale factors. | |
| 42 const int kIndicatorCanvasScale = 5; | |
| 43 | 38 |
| 44 // Shelf item ripple constants. | 39 // Shelf item ripple constants. |
| 45 const int kInkDropSmallSize = 48; | 40 const int kInkDropSmallSize = 48; |
| 46 const int kInkDropLargeSize = 60; | 41 const int kInkDropLargeSize = 60; |
| 47 | 42 |
| 48 // Padding from the edge of the shelf to the application icon when the shelf | 43 // Padding from the edge of the shelf to the application icon when the shelf |
| 49 // is horizontally and vertically aligned, respectively. | 44 // is horizontally and vertically aligned, respectively. |
| 50 const int kIconPaddingHorizontal = 7; | 45 const int kIconPaddingHorizontal = 7; |
| 51 const int kIconPaddingVertical = 8; | 46 const int kIconPaddingVertical = 8; |
| 52 | 47 |
| 53 // Paints an activity indicator on |canvas| whose |size| is specified in DIP. | |
| 54 void PaintIndicatorOnCanvas(gfx::Canvas* canvas, const gfx::Size& size) { | |
| 55 cc::PaintFlags flags; | |
| 56 flags.setAntiAlias(true); | |
| 57 flags.setColor(kIndicatorColor); | |
| 58 canvas->DrawCircle( | |
| 59 gfx::Point(size.width() / 2, | |
| 60 size.height() - kIndicatorOffsetFromBottom - kIndicatorRadius), | |
| 61 kIndicatorRadius, flags); | |
| 62 } | |
| 63 | |
| 64 // Simple AnimationDelegate that owns a single ThrobAnimation instance to | 48 // Simple AnimationDelegate that owns a single ThrobAnimation instance to |
| 65 // keep all Draw Attention animations in sync. | 49 // keep all Draw Attention animations in sync. |
| 66 class ShelfButtonAnimation : public gfx::AnimationDelegate { | 50 class ShelfButtonAnimation : public gfx::AnimationDelegate { |
| 67 public: | 51 public: |
| 68 class Observer { | 52 class Observer { |
| 69 public: | 53 public: |
| 70 virtual void AnimationProgressed() = 0; | 54 virtual void AnimationProgressed() = 0; |
| 71 | 55 |
| 72 protected: | 56 protected: |
| 73 virtual ~Observer() {} | 57 virtual ~Observer() {} |
| 74 }; | 58 }; |
| 75 | 59 |
| 76 static ShelfButtonAnimation* GetInstance() { | 60 static ShelfButtonAnimation* GetInstance() { |
| 77 static ShelfButtonAnimation* s_instance = new ShelfButtonAnimation(); | 61 static ShelfButtonAnimation* s_instance = new ShelfButtonAnimation(); |
| 78 return s_instance; | 62 return s_instance; |
| 79 } | 63 } |
| 80 | 64 |
| 81 void AddObserver(Observer* observer) { observers_.AddObserver(observer); } | 65 void AddObserver(Observer* observer) { observers_.AddObserver(observer); } |
| 82 | 66 |
| 83 void RemoveObserver(Observer* observer) { | 67 void RemoveObserver(Observer* observer) { |
| 84 observers_.RemoveObserver(observer); | 68 observers_.RemoveObserver(observer); |
| 85 if (!observers_.might_have_observers()) | 69 if (!observers_.might_have_observers()) |
| 86 animation_.Stop(); | 70 animation_.Stop(); |
| 87 } | 71 } |
| 88 | 72 |
| 89 int GetAlpha() { return GetThrobAnimation().CurrentValueBetween(0, 255); } | 73 bool HasObserver(Observer* observer) const { |
| 74 return observers_.HasObserver(observer); |
| 75 } |
| 76 |
| 77 SkAlpha GetAlpha() { |
| 78 return GetThrobAnimation().CurrentValueBetween(SK_AlphaTRANSPARENT, |
| 79 SK_AlphaOPAQUE); |
| 80 } |
| 90 | 81 |
| 91 double GetAnimation() { return GetThrobAnimation().GetCurrentValue(); } | 82 double GetAnimation() { return GetThrobAnimation().GetCurrentValue(); } |
| 92 | 83 |
| 93 private: | 84 private: |
| 94 ShelfButtonAnimation() : animation_(this) { | 85 ShelfButtonAnimation() : animation_(this) { |
| 95 animation_.SetThrobDuration(kAttentionThrobDurationMS); | 86 animation_.SetThrobDuration(kAttentionThrobDurationMS); |
| 96 animation_.SetTweenType(gfx::Tween::SMOOTH_IN_OUT); | 87 animation_.SetTweenType(gfx::Tween::SMOOTH_IN_OUT); |
| 97 } | 88 } |
| 98 | 89 |
| 99 ~ShelfButtonAnimation() override {} | 90 ~ShelfButtonAnimation() override {} |
| (...skipping 20 matching lines...) Expand all Loading... |
| 120 base::ObserverList<Observer> observers_; | 111 base::ObserverList<Observer> observers_; |
| 121 | 112 |
| 122 DISALLOW_COPY_AND_ASSIGN(ShelfButtonAnimation); | 113 DISALLOW_COPY_AND_ASSIGN(ShelfButtonAnimation); |
| 123 }; | 114 }; |
| 124 | 115 |
| 125 } // namespace | 116 } // namespace |
| 126 | 117 |
| 127 namespace ash { | 118 namespace ash { |
| 128 | 119 |
| 129 //////////////////////////////////////////////////////////////////////////////// | 120 //////////////////////////////////////////////////////////////////////////////// |
| 130 // ShelfButton::BarView | 121 // ShelfButton::AppStatusIndicatorView |
| 131 | 122 |
| 132 class ShelfButton::BarView : public views::ImageView, | 123 class ShelfButton::AppStatusIndicatorView |
| 133 public ShelfButtonAnimation::Observer { | 124 : public views::View, |
| 125 public ShelfButtonAnimation::Observer { |
| 134 public: | 126 public: |
| 135 BarView(WmShelf* wm_shelf) | 127 AppStatusIndicatorView() |
| 136 : wm_shelf_(wm_shelf), | 128 : show_attention_(false), animation_end_time_(base::TimeTicks()) { |
| 137 show_attention_(false), | |
| 138 animation_end_time_(base::TimeTicks()), | |
| 139 animating_(false) { | |
| 140 // Make sure the events reach the parent view for handling. | 129 // Make sure the events reach the parent view for handling. |
| 141 set_can_process_events_within_subtree(false); | 130 set_can_process_events_within_subtree(false); |
| 142 } | 131 } |
| 143 | 132 |
| 144 ~BarView() override { | 133 ~AppStatusIndicatorView() override { |
| 145 if (show_attention_) | 134 ShelfButtonAnimation::GetInstance()->RemoveObserver(this); |
| 146 ShelfButtonAnimation::GetInstance()->RemoveObserver(this); | |
| 147 } | 135 } |
| 148 | 136 |
| 149 // views::View: | 137 // views::View: |
| 150 void OnPaint(gfx::Canvas* canvas) override { | 138 void OnPaint(gfx::Canvas* canvas) override { |
| 139 gfx::ScopedCanvas scoped(canvas); |
| 151 if (show_attention_) { | 140 if (show_attention_) { |
| 152 int alpha = | 141 SkAlpha alpha = ShelfButtonAnimation::GetInstance()->HasObserver(this) |
| 153 animating_ ? ShelfButtonAnimation::GetInstance()->GetAlpha() : 255; | 142 ? ShelfButtonAnimation::GetInstance()->GetAlpha() |
| 143 : SK_AlphaOPAQUE; |
| 154 canvas->SaveLayerAlpha(alpha); | 144 canvas->SaveLayerAlpha(alpha); |
| 155 views::ImageView::OnPaint(canvas); | |
| 156 canvas->Restore(); | |
| 157 } else { | |
| 158 views::ImageView::OnPaint(canvas); | |
| 159 } | 145 } |
| 146 |
| 147 DCHECK_EQ(width(), height()); |
| 148 DCHECK_EQ(kIndicatorRadiusDip, width() / 2); |
| 149 cc::PaintFlags flags; |
| 150 flags.setColor(kIndicatorColor); |
| 151 flags.setFlags(cc::PaintFlags::kAntiAlias_Flag); |
| 152 canvas->DrawCircle(gfx::Point(width() / 2, height() / 2), |
| 153 kIndicatorRadiusDip, flags); |
| 160 } | 154 } |
| 161 | 155 |
| 162 // ShelfButtonAnimation::Observer | 156 // ShelfButtonAnimation::Observer |
| 163 void AnimationProgressed() override { | 157 void AnimationProgressed() override { |
| 164 UpdateBounds(); | 158 UpdateAnimating(); |
| 165 SchedulePaint(); | 159 SchedulePaint(); |
| 166 } | 160 } |
| 167 | 161 |
| 168 void SetBarBoundsRect(const gfx::Rect& bounds) { | 162 void ShowAttention(bool show) { |
| 169 base_bounds_ = bounds; | 163 if (show_attention_ == show) |
| 170 UpdateBounds(); | 164 return; |
| 171 } | |
| 172 | 165 |
| 173 void ShowAttention(bool show) { | 166 show_attention_ = show; |
| 174 if (show_attention_ != show) { | |
| 175 show_attention_ = show; | |
| 176 if (show_attention_) { | |
| 177 animating_ = true; | |
| 178 animation_end_time_ = | |
| 179 base::TimeTicks::Now() + | |
| 180 base::TimeDelta::FromSeconds(kMaxAnimationSeconds); | |
| 181 ShelfButtonAnimation::GetInstance()->AddObserver(this); | |
| 182 } else { | |
| 183 animating_ = false; | |
| 184 ShelfButtonAnimation::GetInstance()->RemoveObserver(this); | |
| 185 } | |
| 186 } | |
| 187 UpdateBounds(); | |
| 188 } | |
| 189 | |
| 190 private: | |
| 191 void UpdateBounds() { | |
| 192 gfx::Rect bounds = base_bounds_; | |
| 193 if (show_attention_) { | 167 if (show_attention_) { |
| 194 // Scale from .35 to 1.0 of the total width (which is wider than the | 168 animation_end_time_ = base::TimeTicks::Now() + |
| 195 // visible width of the image), so the animation "rests" briefly at full | 169 base::TimeDelta::FromSeconds(kMaxAnimationSeconds); |
| 196 // visible width. Cap bounds length at kIconSize to prevent visual | 170 ShelfButtonAnimation::GetInstance()->AddObserver(this); |
| 197 // flutter while centering bar within further expanding bounds. | 171 } else { |
| 198 double animation = | |
| 199 animating_ ? ShelfButtonAnimation::GetInstance()->GetAnimation() | |
| 200 : 1.0; | |
| 201 double scale = .35 + .65 * animation; | |
| 202 if (wm_shelf_->IsHorizontalAlignment()) { | |
| 203 int width = base_bounds_.width() * scale; | |
| 204 bounds.set_width(std::min(width, kIconSize)); | |
| 205 int x_offset = (base_bounds_.width() - bounds.width()) / 2; | |
| 206 bounds.set_x(base_bounds_.x() + x_offset); | |
| 207 UpdateAnimating(bounds.width() == kIconSize); | |
| 208 } else { | |
| 209 int height = base_bounds_.height() * scale; | |
| 210 bounds.set_height(std::min(height, kIconSize)); | |
| 211 int y_offset = (base_bounds_.height() - bounds.height()) / 2; | |
| 212 bounds.set_y(base_bounds_.y() + y_offset); | |
| 213 UpdateAnimating(bounds.height() == kIconSize); | |
| 214 } | |
| 215 } | |
| 216 SetBoundsRect(bounds); | |
| 217 } | |
| 218 | |
| 219 void UpdateAnimating(bool max_length) { | |
| 220 if (!max_length) | |
| 221 return; | |
| 222 if (base::TimeTicks::Now() > animation_end_time_) { | |
| 223 animating_ = false; | |
| 224 ShelfButtonAnimation::GetInstance()->RemoveObserver(this); | 172 ShelfButtonAnimation::GetInstance()->RemoveObserver(this); |
| 225 } | 173 } |
| 226 } | 174 } |
| 227 | 175 |
| 228 WmShelf* wm_shelf_; | 176 private: |
| 177 void UpdateAnimating() { |
| 178 if (base::TimeTicks::Now() > animation_end_time_) |
| 179 ShelfButtonAnimation::GetInstance()->RemoveObserver(this); |
| 180 } |
| 181 |
| 229 bool show_attention_; | 182 bool show_attention_; |
| 230 base::TimeTicks animation_end_time_; // For attention throbbing underline. | 183 base::TimeTicks animation_end_time_; // For attention throbbing underline. |
| 231 bool animating_; // Is time-limited attention animation running? | |
| 232 gfx::Rect base_bounds_; | |
| 233 | 184 |
| 234 DISALLOW_COPY_AND_ASSIGN(BarView); | 185 DISALLOW_COPY_AND_ASSIGN(AppStatusIndicatorView); |
| 235 }; | 186 }; |
| 236 | 187 |
| 237 //////////////////////////////////////////////////////////////////////////////// | 188 //////////////////////////////////////////////////////////////////////////////// |
| 238 // ShelfButton | 189 // ShelfButton |
| 239 | 190 |
| 240 // static | 191 // static |
| 241 const char ShelfButton::kViewClassName[] = "ash/ShelfButton"; | 192 const char ShelfButton::kViewClassName[] = "ash/ShelfButton"; |
| 242 | 193 |
| 243 ShelfButton::ShelfButton(InkDropButtonListener* listener, ShelfView* shelf_view) | 194 ShelfButton::ShelfButton(InkDropButtonListener* listener, ShelfView* shelf_view) |
| 244 : CustomButton(nullptr), | 195 : CustomButton(nullptr), |
| 245 listener_(listener), | 196 listener_(listener), |
| 246 shelf_view_(shelf_view), | 197 shelf_view_(shelf_view), |
| 247 icon_view_(new views::ImageView()), | 198 icon_view_(new views::ImageView()), |
| 248 bar_(new BarView(shelf_view->wm_shelf())), | 199 indicator_(new AppStatusIndicatorView()), |
| 249 state_(STATE_NORMAL), | 200 state_(STATE_NORMAL), |
| 250 destroyed_flag_(nullptr) { | 201 destroyed_flag_(nullptr) { |
| 251 SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); | 202 SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); |
| 252 SetInkDropMode(InkDropMode::ON); | 203 SetInkDropMode(InkDropMode::ON); |
| 253 set_ink_drop_base_color(kShelfInkDropBaseColor); | 204 set_ink_drop_base_color(kShelfInkDropBaseColor); |
| 254 set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity); | 205 set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity); |
| 255 | 206 |
| 256 const gfx::ShadowValue kShadows[] = { | 207 const gfx::ShadowValue kShadows[] = { |
| 257 gfx::ShadowValue(gfx::Vector2d(0, 2), 0, SkColorSetARGB(0x1A, 0, 0, 0)), | 208 gfx::ShadowValue(gfx::Vector2d(0, 2), 0, SkColorSetARGB(0x1A, 0, 0, 0)), |
| 258 gfx::ShadowValue(gfx::Vector2d(0, 3), 1, SkColorSetARGB(0x1A, 0, 0, 0)), | 209 gfx::ShadowValue(gfx::Vector2d(0, 3), 1, SkColorSetARGB(0x1A, 0, 0, 0)), |
| 259 gfx::ShadowValue(gfx::Vector2d(0, 0), 1, SkColorSetARGB(0x54, 0, 0, 0)), | 210 gfx::ShadowValue(gfx::Vector2d(0, 0), 1, SkColorSetARGB(0x54, 0, 0, 0)), |
| 260 }; | 211 }; |
| 261 icon_shadows_.assign(kShadows, kShadows + arraysize(kShadows)); | 212 icon_shadows_.assign(kShadows, kShadows + arraysize(kShadows)); |
| 262 | 213 |
| 263 // TODO: refactor the layers so each button doesn't require 2. | 214 // TODO: refactor the layers so each button doesn't require 2. |
| 264 icon_view_->SetPaintToLayer(); | 215 icon_view_->SetPaintToLayer(); |
| 265 icon_view_->layer()->SetFillsBoundsOpaquely(false); | 216 icon_view_->layer()->SetFillsBoundsOpaquely(false); |
| 266 icon_view_->SetHorizontalAlignment(views::ImageView::CENTER); | 217 icon_view_->SetHorizontalAlignment(views::ImageView::CENTER); |
| 267 icon_view_->SetVerticalAlignment(views::ImageView::LEADING); | 218 icon_view_->SetVerticalAlignment(views::ImageView::LEADING); |
| 268 // Do not make this interactive, so that events are sent to ShelfView. | 219 // Do not make this interactive, so that events are sent to ShelfView. |
| 269 icon_view_->set_can_process_events_within_subtree(false); | 220 icon_view_->set_can_process_events_within_subtree(false); |
| 270 | 221 |
| 271 AddChildView(bar_); | 222 AddChildView(indicator_); |
| 272 AddChildView(icon_view_); | 223 AddChildView(icon_view_); |
| 273 } | 224 } |
| 274 | 225 |
| 275 ShelfButton::~ShelfButton() { | 226 ShelfButton::~ShelfButton() { |
| 276 if (destroyed_flag_) | 227 if (destroyed_flag_) |
| 277 *destroyed_flag_ = true; | 228 *destroyed_flag_ = true; |
| 278 } | 229 } |
| 279 | 230 |
| 280 void ShelfButton::SetShadowedImage(const gfx::ImageSkia& image) { | 231 void ShelfButton::SetShadowedImage(const gfx::ImageSkia& image) { |
| 281 icon_view_->SetImage(gfx::ImageSkiaOperations::CreateImageWithDropShadow( | 232 icon_view_->SetImage(gfx::ImageSkiaOperations::CreateImageWithDropShadow( |
| (...skipping 28 matching lines...) Expand all Loading... |
| 310 | 261 |
| 311 const gfx::ImageSkia& ShelfButton::GetImage() const { | 262 const gfx::ImageSkia& ShelfButton::GetImage() const { |
| 312 return icon_view_->GetImage(); | 263 return icon_view_->GetImage(); |
| 313 } | 264 } |
| 314 | 265 |
| 315 void ShelfButton::AddState(State state) { | 266 void ShelfButton::AddState(State state) { |
| 316 if (!(state_ & state)) { | 267 if (!(state_ & state)) { |
| 317 state_ |= state; | 268 state_ |= state; |
| 318 Layout(); | 269 Layout(); |
| 319 if (state & STATE_ATTENTION) | 270 if (state & STATE_ATTENTION) |
| 320 bar_->ShowAttention(true); | 271 indicator_->ShowAttention(true); |
| 321 } | 272 } |
| 322 } | 273 } |
| 323 | 274 |
| 324 void ShelfButton::ClearState(State state) { | 275 void ShelfButton::ClearState(State state) { |
| 325 if (state_ & state) { | 276 if (state_ & state) { |
| 326 state_ &= ~state; | 277 state_ &= ~state; |
| 327 Layout(); | 278 Layout(); |
| 328 if (state & STATE_ATTENTION) | 279 if (state & STATE_ATTENTION) |
| 329 bar_->ShowAttention(false); | 280 indicator_->ShowAttention(false); |
| 330 } | 281 } |
| 331 } | 282 } |
| 332 | 283 |
| 333 gfx::Rect ShelfButton::GetIconBounds() const { | 284 gfx::Rect ShelfButton::GetIconBounds() const { |
| 334 return icon_view_->bounds(); | 285 return icon_view_->bounds(); |
| 335 } | 286 } |
| 336 | 287 |
| 337 void ShelfButton::OnDragStarted(const ui::LocatedEvent* event) { | 288 void ShelfButton::OnDragStarted(const ui::LocatedEvent* event) { |
| 338 AnimateInkDrop(views::InkDropState::HIDDEN, event); | 289 AnimateInkDrop(views::InkDropState::HIDDEN, event); |
| 339 } | 290 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 int y_offset = is_horizontal_shelf ? icon_pad : 0; | 350 int y_offset = is_horizontal_shelf ? icon_pad : 0; |
| 400 | 351 |
| 401 int icon_width = std::min(kIconSize, button_bounds.width() - x_offset); | 352 int icon_width = std::min(kIconSize, button_bounds.width() - x_offset); |
| 402 int icon_height = std::min(kIconSize, button_bounds.height() - y_offset); | 353 int icon_height = std::min(kIconSize, button_bounds.height() - y_offset); |
| 403 | 354 |
| 404 // If on the left or top 'invert' the inset so the constant gap is on | 355 // If on the left or top 'invert' the inset so the constant gap is on |
| 405 // the interior (towards the center of display) edge of the shelf. | 356 // the interior (towards the center of display) edge of the shelf. |
| 406 if (SHELF_ALIGNMENT_LEFT == wm_shelf->GetAlignment()) | 357 if (SHELF_ALIGNMENT_LEFT == wm_shelf->GetAlignment()) |
| 407 x_offset = button_bounds.width() - (kIconSize + icon_pad); | 358 x_offset = button_bounds.width() - (kIconSize + icon_pad); |
| 408 | 359 |
| 409 // Center icon with respect to the secondary axis, and ensure | 360 // Center icon with respect to the secondary axis. |
| 410 // that the icon doesn't occlude the bar highlight. | 361 if (is_horizontal_shelf) |
| 411 if (is_horizontal_shelf) { | |
| 412 x_offset = std::max(0, button_bounds.width() - icon_width) / 2; | 362 x_offset = std::max(0, button_bounds.width() - icon_width) / 2; |
| 413 if (y_offset + icon_height + kBarSize > button_bounds.height()) | 363 else |
| 414 icon_height = button_bounds.height() - (y_offset + kBarSize); | |
| 415 } else { | |
| 416 y_offset = std::max(0, button_bounds.height() - icon_height) / 2; | 364 y_offset = std::max(0, button_bounds.height() - icon_height) / 2; |
| 417 if (x_offset + icon_width + kBarSize > button_bounds.width()) | |
| 418 icon_width = button_bounds.width() - (x_offset + kBarSize); | |
| 419 } | |
| 420 | 365 |
| 421 // Expand bounds to include shadows. | 366 // Expand bounds to include shadows. |
| 422 gfx::Insets insets_shadows = gfx::ShadowValue::GetMargin(icon_shadows_); | 367 gfx::Insets insets_shadows = gfx::ShadowValue::GetMargin(icon_shadows_); |
| 423 // Adjust offsets to center icon, not icon + shadow. | 368 // Adjust offsets to center icon, not icon + shadow. |
| 424 x_offset += (insets_shadows.left() - insets_shadows.right()) / 2; | 369 x_offset += (insets_shadows.left() - insets_shadows.right()) / 2; |
| 425 y_offset += (insets_shadows.top() - insets_shadows.bottom()) / 2; | 370 y_offset += (insets_shadows.top() - insets_shadows.bottom()) / 2; |
| 426 gfx::Rect icon_view_bounds = | 371 gfx::Rect icon_view_bounds = |
| 427 gfx::Rect(button_bounds.x() + x_offset, button_bounds.y() + y_offset, | 372 gfx::Rect(button_bounds.x() + x_offset, button_bounds.y() + y_offset, |
| 428 icon_width, icon_height); | 373 icon_width, icon_height); |
| 374 // The indicator should be aligned with the icon, not the icon + shadow. |
| 375 gfx::Point indicator_midpoint = icon_view_bounds.CenterPoint(); |
| 429 icon_view_bounds.Inset(insets_shadows); | 376 icon_view_bounds.Inset(insets_shadows); |
| 430 icon_view_bounds.AdjustToFit(gfx::Rect(size())); | 377 icon_view_bounds.AdjustToFit(gfx::Rect(size())); |
| 431 icon_view_->SetBoundsRect(icon_view_bounds); | 378 icon_view_->SetBoundsRect(icon_view_bounds); |
| 432 | 379 |
| 433 // Icon size has been incorrect when running | 380 // Icon size has been incorrect when running |
| 434 // PanelLayoutManagerTest.PanelAlignmentSecondDisplay on valgrind bot, see | 381 // PanelLayoutManagerTest.PanelAlignmentSecondDisplay on valgrind bot, see |
| 435 // http://crbug.com/234854. | 382 // http://crbug.com/234854. |
| 436 DCHECK_LE(icon_width, kIconSize); | 383 DCHECK_LE(icon_width, kIconSize); |
| 437 DCHECK_LE(icon_height, kIconSize); | 384 DCHECK_LE(icon_height, kIconSize); |
| 438 | 385 |
| 439 bar_->SetBarBoundsRect(button_bounds); | 386 switch (wm_shelf->GetAlignment()) { |
| 387 case SHELF_ALIGNMENT_BOTTOM: |
| 388 case SHELF_ALIGNMENT_BOTTOM_LOCKED: |
| 389 indicator_midpoint.set_y(button_bounds.bottom() - kIndicatorRadiusDip - |
| 390 kIndicatorOffsetFromBottom); |
| 391 break; |
| 392 case SHELF_ALIGNMENT_LEFT: |
| 393 indicator_midpoint.set_x(button_bounds.x() + kIndicatorRadiusDip + |
| 394 kIndicatorOffsetFromBottom); |
| 395 break; |
| 396 case SHELF_ALIGNMENT_RIGHT: |
| 397 indicator_midpoint.set_x(button_bounds.right() - kIndicatorRadiusDip - |
| 398 kIndicatorOffsetFromBottom); |
| 399 break; |
| 400 } |
| 401 |
| 402 gfx::Rect indicator_bounds(indicator_midpoint, gfx::Size()); |
| 403 indicator_bounds.Inset(gfx::Insets(-kIndicatorRadiusDip)); |
| 404 indicator_->SetBoundsRect(indicator_bounds); |
| 440 | 405 |
| 441 UpdateState(); | 406 UpdateState(); |
| 442 } | 407 } |
| 443 | 408 |
| 444 void ShelfButton::ChildPreferredSizeChanged(views::View* child) { | 409 void ShelfButton::ChildPreferredSizeChanged(views::View* child) { |
| 445 Layout(); | 410 Layout(); |
| 446 } | 411 } |
| 447 | 412 |
| 448 void ShelfButton::OnFocus() { | 413 void ShelfButton::OnFocus() { |
| 449 AddState(STATE_FOCUSED); | 414 AddState(STATE_FOCUSED); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 return std::move(ink_drop); | 477 return std::move(ink_drop); |
| 513 } | 478 } |
| 514 | 479 |
| 515 void ShelfButton::NotifyClick(const ui::Event& event) { | 480 void ShelfButton::NotifyClick(const ui::Event& event) { |
| 516 CustomButton::NotifyClick(event); | 481 CustomButton::NotifyClick(event); |
| 517 if (listener_) | 482 if (listener_) |
| 518 listener_->ButtonPressed(this, event, GetInkDrop()); | 483 listener_->ButtonPressed(this, event, GetInkDrop()); |
| 519 } | 484 } |
| 520 | 485 |
| 521 void ShelfButton::UpdateState() { | 486 void ShelfButton::UpdateState() { |
| 522 UpdateBar(); | 487 indicator_->SetVisible(!(state_ & STATE_HIDDEN) && |
| 488 (state_ & STATE_ACTIVE || state_ & STATE_ATTENTION || |
| 489 state_ & STATE_RUNNING)); |
| 490 |
| 523 const bool is_horizontal_shelf = | 491 const bool is_horizontal_shelf = |
| 524 shelf_view_->wm_shelf()->IsHorizontalAlignment(); | 492 shelf_view_->wm_shelf()->IsHorizontalAlignment(); |
| 525 icon_view_->SetHorizontalAlignment(is_horizontal_shelf | 493 icon_view_->SetHorizontalAlignment(is_horizontal_shelf |
| 526 ? views::ImageView::CENTER | 494 ? views::ImageView::CENTER |
| 527 : views::ImageView::LEADING); | 495 : views::ImageView::LEADING); |
| 528 icon_view_->SetVerticalAlignment(is_horizontal_shelf | 496 icon_view_->SetVerticalAlignment(is_horizontal_shelf |
| 529 ? views::ImageView::LEADING | 497 ? views::ImageView::LEADING |
| 530 : views::ImageView::CENTER); | 498 : views::ImageView::CENTER); |
| 531 SchedulePaint(); | 499 SchedulePaint(); |
| 532 } | 500 } |
| 533 | 501 |
| 534 void ShelfButton::UpdateBar() { | |
| 535 bool draw_bar = !(state_ & STATE_HIDDEN) && | |
| 536 (state_ & STATE_ACTIVE || state_ & STATE_ATTENTION || | |
| 537 state_ & STATE_RUNNING); | |
| 538 | |
| 539 if (draw_bar) { | |
| 540 WmShelf* wm_shelf = shelf_view_->wm_shelf(); | |
| 541 gfx::ImageSkia image; | |
| 542 if (wm_shelf->IsVisible()) { | |
| 543 gfx::Size size(kShelfButtonSize, GetShelfConstant(SHELF_SIZE)); | |
| 544 gfx::Canvas canvas(size, kIndicatorCanvasScale, true /* is_opaque */); | |
| 545 PaintIndicatorOnCanvas(&canvas, size); | |
| 546 image = gfx::ImageSkia(canvas.ExtractImageRep()); | |
| 547 } | |
| 548 ShelfAlignment shelf_alignment = wm_shelf->GetAlignment(); | |
| 549 if (!wm_shelf->IsHorizontalAlignment()) { | |
| 550 image = gfx::ImageSkiaOperations::CreateRotatedImage( | |
| 551 image, shelf_alignment == SHELF_ALIGNMENT_LEFT | |
| 552 ? SkBitmapOperations::ROTATION_90_CW | |
| 553 : SkBitmapOperations::ROTATION_270_CW); | |
| 554 } | |
| 555 bar_->SetImage(image); | |
| 556 switch (shelf_alignment) { | |
| 557 case SHELF_ALIGNMENT_BOTTOM: | |
| 558 case SHELF_ALIGNMENT_BOTTOM_LOCKED: | |
| 559 bar_->SetHorizontalAlignment(views::ImageView::CENTER); | |
| 560 bar_->SetVerticalAlignment(views::ImageView::TRAILING); | |
| 561 break; | |
| 562 case SHELF_ALIGNMENT_LEFT: | |
| 563 bar_->SetHorizontalAlignment(views::ImageView::LEADING); | |
| 564 bar_->SetVerticalAlignment(views::ImageView::CENTER); | |
| 565 break; | |
| 566 case SHELF_ALIGNMENT_RIGHT: | |
| 567 bar_->SetHorizontalAlignment(views::ImageView::TRAILING); | |
| 568 bar_->SetVerticalAlignment(views::ImageView::CENTER); | |
| 569 break; | |
| 570 } | |
| 571 bar_->SchedulePaint(); | |
| 572 } | |
| 573 | |
| 574 bar_->SetVisible(draw_bar); | |
| 575 } | |
| 576 | |
| 577 } // namespace ash | 502 } // namespace ash |
| OLD | NEW |