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

ash / wm / desks / templates / saved_desk_icon_container.h [blame]

// Copyright 2021 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_WM_DESKS_TEMPLATES_SAVED_DESK_ICON_CONTAINER_H_
#define ASH_WM_DESKS_TEMPLATES_SAVED_DESK_ICON_CONTAINER_H_

#include <cstddef>
#include <string>
#include <utility>
#include <vector>

#include "ash/wm/desks/templates/saved_desk_icon_view.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/view.h"

namespace ui {
class ColorProvider;
}

namespace ash {

class DeskTemplate;

// This class determines which app icons/favicons to show for a saved desk and
// creates the according SavedDeskIconView's. The last SavedDeskIconView in the
// layout is used for storing the overflow count of icons. Not every view in the
// container is visible.
//   _______________________________________________________________________
//   |  _________  _________   _________________   _________   _________   |
//   |  |       |  |       |   |       |       |   |       |   |       |   |
//   |  |   I   |  |   I   |   |   I      + N  |   |   I   |   |  + N  |   |
//   |  |_______|  |_______|   |_______|_______|   |_______|   |_______|   |
//   |_____________________________________________________________________|
//
// If there are multiple apps associated with a certain icon, the icon is drawn
// once with a +N label attached, up to +99. If there are too many icons to be
// displayed within the given width, we draw as many and a label at the end that
// says +N, up to +99.
class SavedDeskIconContainer : public views::BoxLayoutView {
  METADATA_HEADER(SavedDeskIconContainer, views::BoxLayoutView)

 public:
  // A struct for storing the various information used to determine which app
  // icons/favicons to display.
  struct IconInfo {
    std::string app_id;
    std::string app_title;
    int activation_index;
    int count;
  };

  using IconIdentifierAndIconInfo =
      std::pair<SavedDeskIconIdentifier, IconInfo>;

  SavedDeskIconContainer();
  SavedDeskIconContainer(const SavedDeskIconContainer&) = delete;
  SavedDeskIconContainer& operator=(const SavedDeskIconContainer&) = delete;
  ~SavedDeskIconContainer() override;

  // The maximum number of icons that can be displayed.
  static constexpr int kMaxIcons = 4;

  // views::BoxLayoutView:
  void Layout(PassKey) override;

  // Given a saved desk, determine which icons to show in this and create
  // the according SavedDeskIconView's.
  void PopulateIconContainerFromTemplate(const DeskTemplate* desk_template);

  // Given `windows`, determine which icons to show in this and create the
  // according SavedDeskIconView's.
  void PopulateIconContainerFromWindows(
      const std::vector<raw_ptr<aura::Window, VectorExperimental>>& windows);

 private:
  // Return a copy of child icon views.
  std::vector<SavedDeskIconView*> GetIconViews() const;

  // Function that runs when a child view finishes loading its icon. Sort child
  // icons and the overflow icon.
  void OnViewLoaded(views::View* icon_view);

  // Sort child icons and update overflow icon.
  void SortIconsAndUpdateOverflowIcon();

  // Sort all child icons using its key. Please note, the overflow icon will
  // always stay at the end. Default icons will always come after non-default
  // icons. The order of non-default icons will be stable, i.e. it preserves the
  // original order.
  void SortIcons();

  // Update icon visibility and the overflow icon depending on the available
  // space.
  void UpdateOverflowIcon();

  // Given a sorted vector of pairs of icon identifier and icon info, create
  // views for them.
  void CreateIconViewsFromIconIdentifiers(
      const std::vector<IconIdentifierAndIconInfo>&
          icon_identifier_to_icon_info);

  // Pointer of the overflow icon view.
  raw_ptr<views::View> overflow_icon_view_ = nullptr;

  // Number of apps that are not shown as icons in the container.
  int uncreated_app_count_ = 0;

  // If `this` is created with an incognito window, store the ui::ColorProvider
  // of one of the incognito windows to retrieve its icon's color.
  raw_ptr<const ui::ColorProvider> incognito_window_color_provider_ = nullptr;

  base::WeakPtrFactory<SavedDeskIconContainer> weak_ptr_factory_{this};
};

BEGIN_VIEW_BUILDER(/* no export */,
                   SavedDeskIconContainer,
                   views::BoxLayoutView)
VIEW_BUILDER_METHOD(PopulateIconContainerFromTemplate, const DeskTemplate*)
VIEW_BUILDER_METHOD(
    PopulateIconContainerFromWindows,
    const std::vector<raw_ptr<aura::Window, VectorExperimental>>&)
END_VIEW_BUILDER

}  // namespace ash

DEFINE_VIEW_BUILDER(/* no export */, ash::SavedDeskIconContainer)

#endif  // ASH_WM_DESKS_TEMPLATES_SAVED_DESK_ICON_CONTAINER_H_