media_notification_volume_slider_view.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright 2021 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. #include "components/media_message_center/media_notification_volume_slider_view.h"
  5. #include "ui/base/metadata/metadata_impl_macros.h"
  6. #include "ui/gfx/canvas.h"
  7. #include "ui/gfx/geometry/skia_conversions.h"
  8. #include "ui/views/controls/focus_ring.h"
  9. namespace media_message_center {
  10. namespace {
  11. constexpr int kThumbRadius = 4;
  12. constexpr int kSliderHeight = 2;
  13. constexpr float kScrollVolumeDelta = 0.1;
  14. constexpr float kKeyVolumeDelta = 0.05;
  15. } // anonymous namespace
  16. MediaNotificationVolumeSliderView::MediaNotificationVolumeSliderView(
  17. base::RepeatingCallback<void(float)> set_volume_callback)
  18. : set_volume_callback_(set_volume_callback) {
  19. views::FocusRing::Install(this);
  20. SetFocusBehavior(FocusBehavior::ALWAYS);
  21. }
  22. MediaNotificationVolumeSliderView::~MediaNotificationVolumeSliderView() =
  23. default;
  24. void MediaNotificationVolumeSliderView::UpdateColor(SkColor foreground,
  25. SkColor background) {
  26. foreground_color_ = foreground;
  27. background_color_ = background;
  28. SchedulePaint();
  29. }
  30. void MediaNotificationVolumeSliderView::SetVolume(float volume) {
  31. volume_ = std::min(1.0f, std::max(0.0f, volume));
  32. SchedulePaint();
  33. }
  34. void MediaNotificationVolumeSliderView::SetMute(bool mute) {
  35. mute_ = mute;
  36. SchedulePaint();
  37. }
  38. bool MediaNotificationVolumeSliderView::OnMousePressed(
  39. const ui::MouseEvent& event) {
  40. HandleMouseOrGestureEvent(event.x());
  41. return true;
  42. }
  43. bool MediaNotificationVolumeSliderView::OnMouseDragged(
  44. const ui::MouseEvent& event) {
  45. HandleMouseOrGestureEvent(event.x());
  46. return true;
  47. }
  48. void MediaNotificationVolumeSliderView::OnGestureEvent(
  49. ui::GestureEvent* event) {
  50. if (event->type() == ui::EventType::ET_GESTURE_TAP)
  51. HandleMouseOrGestureEvent(event->x());
  52. }
  53. bool MediaNotificationVolumeSliderView::OnKeyPressed(
  54. const ui::KeyEvent& event) {
  55. if (event.key_code() == ui::KeyboardCode::VKEY_UP ||
  56. event.key_code() == ui::KeyboardCode::VKEY_RIGHT) {
  57. HandleVolumeChangeWithDelta(true /* volume_up */, kKeyVolumeDelta);
  58. return true;
  59. }
  60. if (event.key_code() == ui::KeyboardCode::VKEY_DOWN ||
  61. event.key_code() == ui::KeyboardCode::VKEY_LEFT) {
  62. HandleVolumeChangeWithDelta(false /* volume_up */, kKeyVolumeDelta);
  63. return true;
  64. }
  65. return false;
  66. }
  67. bool MediaNotificationVolumeSliderView::OnMouseWheel(
  68. const ui::MouseWheelEvent& event) {
  69. if (event.y_offset() == 0)
  70. return false;
  71. HandleVolumeChangeWithDelta(event.y_offset() > 0 /* volume_up */,
  72. kScrollVolumeDelta);
  73. return true;
  74. }
  75. void MediaNotificationVolumeSliderView::OnPaint(gfx::Canvas* canvas) {
  76. views::View::OnPaint(canvas);
  77. float volume = mute_ ? 0.0 : volume_;
  78. gfx::Rect content_bound = GetContentsBounds();
  79. int offset_y = (content_bound.height() - kSliderHeight) / 2;
  80. // Draw background bar taking entire content width and |kSliderHeight|.
  81. SkPath background_path;
  82. background_path.addRoundRect(
  83. gfx::RectToSkRect(
  84. gfx::Rect(0, offset_y, content_bound.width(), kSliderHeight)),
  85. kSliderHeight / 2, kSliderHeight / 2);
  86. cc::PaintFlags background_flags;
  87. background_flags.setStyle(cc::PaintFlags::kFill_Style);
  88. background_flags.setAntiAlias(true);
  89. background_flags.setColor(background_color_);
  90. canvas->DrawPath(background_path, background_flags);
  91. SkPath foreground_path;
  92. // The effective length of the volume slider bar is the content width minus
  93. // the thumb size because we want the thumb completely stays inside the
  94. // slider.
  95. int foreground_width =
  96. static_cast<int>((content_bound.width() - 2 * kThumbRadius) * volume) +
  97. kThumbRadius;
  98. foreground_path.addRoundRect(
  99. gfx::RectToSkRect(
  100. gfx::Rect(0, offset_y, foreground_width, kSliderHeight)),
  101. kSliderHeight / 2, kSliderHeight / 2);
  102. cc::PaintFlags foreground_flags;
  103. foreground_flags.setStyle(cc::PaintFlags::kFill_Style);
  104. foreground_flags.setAntiAlias(true);
  105. foreground_flags.setColor(foreground_color_);
  106. canvas->DrawPath(foreground_path, foreground_flags);
  107. // Draw thumb.
  108. int thumb_offset_x = foreground_width - kThumbRadius;
  109. int thumb_offset_y = (content_bound.height() - 2 * kThumbRadius) / 2;
  110. SkPath thumb_path;
  111. thumb_path.addRoundRect(
  112. gfx::RectToSkRect(gfx::Rect(thumb_offset_x, thumb_offset_y,
  113. 2 * kThumbRadius, 2 * kThumbRadius)),
  114. kThumbRadius, kThumbRadius);
  115. canvas->DrawPath(thumb_path, foreground_flags);
  116. }
  117. void MediaNotificationVolumeSliderView::HandleMouseOrGestureEvent(
  118. float location_x) {
  119. float new_volume = (location_x - kThumbRadius) /
  120. (GetContentsBounds().width() - 2 * kThumbRadius);
  121. new_volume = std::min(1.0f, std::max(0.0f, new_volume));
  122. set_volume_callback_.Run(new_volume);
  123. }
  124. void MediaNotificationVolumeSliderView::HandleVolumeChangeWithDelta(
  125. bool volume_up,
  126. float delta) {
  127. float new_volume = volume_up ? volume_ + delta : volume_ - delta;
  128. new_volume = std::min(1.0f, std::max(0.0f, new_volume));
  129. set_volume_callback_.Run(new_volume);
  130. }
  131. BEGIN_METADATA(MediaNotificationVolumeSliderView, views::View)
  132. END_METADATA
  133. } // namespace media_message_center