1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156

ash / system / tray / hover_highlight_view.h [blame]

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_SYSTEM_TRAY_HOVER_HIGHLIGHT_VIEW_H_
#define ASH_SYSTEM_TRAY_HOVER_HIGHLIGHT_VIEW_H_

#include <memory>

#include "ash/ash_export.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/models/image_model.h"
#include "ui/gfx/font.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/controls/button/button.h"

namespace views {
class Border;
class ImageView;
class Label;
}  // namespace views

namespace ash {
class TriView;
class ViewClickListener;

// A view that changes background color on hover, and triggers a callback in the
// associated ViewClickListener on click. The view can also be forced to
// maintain a fixed height.
class ASH_EXPORT HoverHighlightView : public views::Button {
  METADATA_HEADER(HoverHighlightView, views::Button)

 public:
  enum class AccessibilityState {
    // The default accessibility view.
    DEFAULT,
    // This view is a checked checkbox.
    CHECKED_CHECKBOX,
    // This view is an unchecked checkbox.
    UNCHECKED_CHECKBOX
  };

  // If |listener| is null then no action is taken on click.
  explicit HoverHighlightView(ViewClickListener* listener);

  HoverHighlightView(const HoverHighlightView&) = delete;
  HoverHighlightView& operator=(const HoverHighlightView&) = delete;

  ~HoverHighlightView() override;

  // Convenience function for populating the view with an icon and a label. This
  // also sets the accessible name. Primarily used for scrollable rows in
  // detailed views.
  // New callers should use the function below which takes an ImageModel.
  // TODO(b/259490845): Change callers to pass an ImageModel and eliminate this.
  void AddIconAndLabel(const gfx::ImageSkia& image, const std::u16string& text);

  // The same as the above function with `ImageModel` parameter instead.
  void AddIconAndLabel(const ui::ImageModel& image, const std::u16string& text);

  // Convenience function for populating the view with an arbitrary view and a
  // label. This also sets the accessible name.
  void AddViewAndLabel(std::unique_ptr<views::View> view,
                       const std::u16string& text);

  // Populates the view with a text label, inset on the left by the horizontal
  // space that would normally be occupied by an icon.
  void AddLabelRow(const std::u16string& text);

  // Populates the view with a text label with custom start inset.
  void AddLabelRow(const std::u16string& text, int start_inset);

  // Adds an optional right icon to an already populated view. |icon_size| is
  // the size of the icon in DP.
  void AddRightIcon(const ui::ImageModel& image, int icon_size);

  // Adds an optional right view to an already populated view.
  void AddRightView(views::View* view,
                    std::unique_ptr<views::Border> border = nullptr);

  // Adds an additional right view next to the `right_view_`.
  // TODO (b/266761290): Remove this method when it's not needed.
  void AddAdditionalRightView(views::View* view);

  // Hides or shows the right view for an already populated view.
  void SetRightViewVisible(bool visible);

  // Sets the text of the sub label for an already populated view. |sub_text|
  // must not be empty and prior to calling this function, |text_label_| must
  // not be null.
  void SetSubText(const std::u16string& sub_text);

  // Allows view to expand its height. Size of unexapandable view is fixed and
  // equals to kTrayPopupItemHeight.
  void SetExpandable(bool expandable);

  // Changes the view's current accessibility state. This will fire an
  // accessibility event if needed.
  void SetAccessibilityState(AccessibilityState accessibility_state);

  // Removes current children of the view so that it can be re-populated.
  void Reset();

  bool is_populated() const { return is_populated_; }

  views::ImageView* icon() { return icon_; }
  views::Label* text_label() { return text_label_; }
  views::Label* sub_text_label() { return sub_text_label_; }
  views::View* left_view() { return left_view_; }
  views::View* right_view() { return right_view_; }
  views::View* sub_row() { return sub_row_; }
  TriView* tri_view() { return tri_view_; }

 protected:
  // Override from Button to also set the tooltip for all child elements.
  void OnSetTooltipText(const std::u16string& tooltip_text) override;

 private:
  friend class TrayAccessibilityTest;

  void PerformAction();

  // views::View:
  gfx::Size CalculatePreferredSize(
      const views::SizeBounds& available_size) const override;
  void OnFocus() override;

  // Adds a view that acts as a container for all views that are added into the
  // sub-row, i.e. the row below the label.
  void AddSubRowContainer();

  // views::Button:
  void OnEnabledChanged() override;

  void SetAndUpdateAccessibleDefaultAction();

  // Determines whether the view is populated or not. If it is, Reset() should
  // be called before re-populating the view.
  bool is_populated_ = false;

  const raw_ptr<ViewClickListener, DanglingUntriaged> listener_ = nullptr;
  raw_ptr<views::ImageView, DanglingUntriaged> icon_ = nullptr;
  raw_ptr<views::Label, DanglingUntriaged> text_label_ = nullptr;
  raw_ptr<views::Label, DanglingUntriaged> sub_text_label_ = nullptr;
  raw_ptr<views::View, DanglingUntriaged> left_view_ = nullptr;
  raw_ptr<views::View, DanglingUntriaged> right_view_ = nullptr;
  raw_ptr<views::View, DanglingUntriaged> sub_row_ = nullptr;
  raw_ptr<TriView, DanglingUntriaged> tri_view_ = nullptr;
  bool expandable_ = false;
  AccessibilityState accessibility_state_ = AccessibilityState::DEFAULT;
};

}  // namespace ash

#endif  // ASH_SYSTEM_TRAY_HOVER_HIGHLIGHT_VIEW_H_