File: table_view.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (803 lines) | stat: -rw-r--r-- 31,199 bytes parent folder | download | duplicates (5)
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_H_
#define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_H_

#include <memory>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "ui/base/models/list_selection_model.h"
#include "ui/base/models/table_model.h"
#include "ui/base/models/table_model_observer.h"
#include "ui/color/color_id.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/render_text.h"
#include "ui/views/controls/table/table_grouper.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"

namespace ui {

struct AXActionData;

}  // namespace ui

namespace task_manager {

// Forward declaring TaskManagerView to use as a PassKey because it has
// permission to disable alternating row colors on macOS.
class TaskManagerView;

}  // namespace task_manager

// A TableView is a view that displays multiple rows with any number of columns.
// TableView is driven by a TableModel. The model returns the contents
// to display. TableModel also has an Observer which is used to notify
// TableView of changes to the model so that the display may be updated
// appropriately.
//
// TableView itself has an observer that is notified when the selection
// changes.
//
// When a table is sorted the model coordinates do not necessarily match the
// view coordinates. All table methods are in terms of the model. If you need to
// convert to view coordinates use ModelToView().
//
// Sorting is done by a locale sensitive string sort. You can customize the
// sort by way of overriding TableModel::CompareValues().
namespace views {

class AXVirtualView;
struct GroupRange;
class ScrollView;
class TableGrouper;
class TableHeader;
class TableViewObserver;
class TableViewTestHelper;

struct VIEWS_EXPORT TableHeaderStyle {
  TableHeaderStyle(int cell_vertical_padding,
                   int cell_horizontal_padding,
                   int resize_bar_vertical_padding,
                   int separator_horizontal_padding,
                   gfx::Font::Weight font_weight,
                   ui::ColorId separator_horizontal_color_id,
                   ui::ColorId separator_vertical_color_id,
                   ui::ColorId background_color_id,
                   float focus_ring_upper_corner_radius,
                   bool header_sort_state);
  TableHeaderStyle();
  ~TableHeaderStyle();

  std::optional<int> cell_vertical_padding;
  std::optional<int> cell_horizontal_padding;
  std::optional<int> resize_bar_vertical_padding;
  std::optional<int> separator_horizontal_padding;
  std::optional<gfx::Font::Weight> font_weight;
  std::optional<ui::ColorId> separator_horizontal_color_id;
  std::optional<ui::ColorId> separator_vertical_color_id;
  std::optional<ui::ColorId> background_color_id;

  // Applied to the top left corner of the first column, and top right corner
  // of the last column. Applied to both if there is only one column.
  std::optional<float> focus_ring_upper_corner_radius;

  // Add sort state to column header.
  std::optional<bool> header_sort_state;
};

struct TableBackgroundStyle {
  ui::ColorId background = ui::kColorTableBackground;
  ui::ColorId alternate = ui::kColorTableBackgroundAlternate;
  ui::ColorId selected_focused = ui::kColorTableBackgroundSelectedFocused;
  ui::ColorId selected_unfocused = ui::kColorTableBackgroundSelectedUnfocused;
};

struct TableStyle {
  TableBackgroundStyle background_tokens;

  // Icons will be drawn with a rounded rect background if this is set to true.
  bool icons_have_background = false;

  // Focus Ring is drawn inside the cell, instead of outside the cell.
  bool inset_focus_ring = false;
};

// The cell's in the first column of a table can contain:
// - only text
// - a small icon (16x16) and some text
// - a check box and some text
enum class TableType : bool { kTextOnly, kIconAndText };

class VIEWS_EXPORT TableView : public View, public ui::TableModelObserver {
  METADATA_HEADER(TableView, View)

 public:
  // Used by AdvanceActiveVisibleColumn(), AdvanceSelection() and
  // ResizeColumnViaKeyboard() to determine the direction to change the
  // selection.
  enum class AdvanceDirection : bool {
    kDecrement,
    kIncrement,
  };

  // Used to track a visible column. Useful only for the header.
  struct VIEWS_EXPORT VisibleColumn {
    VisibleColumn();
    ~VisibleColumn();

    // The column.
    ui::TableColumn column;

    // Starting x-coordinate of the column.
    int x = 0;

    // Width of the column.
    int width = 0;
  };

  // Describes a sorted column.
  struct VIEWS_EXPORT SortDescriptor {
    SortDescriptor() = default;
    SortDescriptor(int column_id, bool ascending)
        : column_id(column_id), ascending(ascending) {}

    // ID of the sorted column.
    int column_id = -1;

    // Is the sort ascending?
    bool ascending = true;
  };

  using SortDescriptors = std::vector<SortDescriptor>;

  static constexpr int kTextContext = style::CONTEXT_TABLE_ROW;
  static constexpr int kTextStyle = style::STYLE_BODY_4;

  // Creates a new table using the model and columns specified.
  // The table type applies to the content of the first column (text, icon and
  // text, checkbox and text).
  TableView();
  TableView(ui::TableModel* model,
            const std::vector<ui::TableColumn>& columns,
            TableType table_type,
            bool single_selection);

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

  ~TableView() override;

  // Returns a new ScrollView that contains the given |table|.
  static std::unique_ptr<ScrollView> CreateScrollViewWithTable(
      std::unique_ptr<TableView> table,
      bool has_border = true);

  // Returns a new Builder<ScrollView> that contains the |table| constructed
  // from the given Builder<TableView>.
  static Builder<ScrollView> CreateScrollViewBuilderWithTable(
      Builder<TableView>&& table);

  // Initialize the table with the appropriate data.
  void Init(ui::TableModel* model,
            const std::vector<ui::TableColumn>& columns,
            TableType table_type,
            bool single_selection);

  // Assigns a new model to the table view, detaching the old one if present.
  // If |model| is NULL, the table view cannot be used after this call. This
  // should be called in the containing view's destructor to avoid destruction
  // issues when the model needs to be deleted before the table.
  void SetModel(ui::TableModel* model);
  ui::TableModel* model() const { return model_; }

  void SetColumns(const std::vector<ui::TableColumn>& columns);

  void SetTableType(TableType table_type);
  TableType GetTableType() const;

  void SetSingleSelection(bool single_selection);
  bool GetSingleSelection() const;

  // Sets the TableGrouper. TableView does not own |grouper| (common use case is
  // to have TableModel implement TableGrouper).
  void SetGrouper(TableGrouper* grouper);

  // Determines whether to draw the TableGrouper on the left side of the table.
  void SetGrouperVisibility(bool visible);

  // Returns the number of rows in the TableView.
  size_t GetRowCount() const;

  // Selects the specified item, making sure it's visible.
  void Select(std::optional<size_t> model_row);

  // Selects all items.
  void SetSelectionAll(bool select);

  // Returns the first selected row in terms of the model.
  std::optional<size_t> GetFirstSelectedRow() const;

  const ui::ListSelectionModel& selection_model() const {
    return selection_model_;
  }

  // Changes the visibility of the specified column (by id).
  void SetColumnVisibility(int id, bool is_visible);
  bool IsColumnVisible(int id) const;

  // Returns true if the column with the specified id is known (either visible
  // or not).
  bool HasColumn(int id) const;

  // Returns whether an active row and column have been set.
  bool GetHasFocusIndicator() const;

  // These functions are deprecated. Favor calling the equivalent functions
  // below.
  void set_observer(TableViewObserver* observer) { observer_ = observer; }
  TableViewObserver* observer() const { return observer_; }

  // The following are equivalent to the above, but are named for compatibility
  // with metadata properties and view builder.
  void SetObserver(TableViewObserver* observer);
  TableViewObserver* GetObserver() const;

  std::optional<size_t> GetActiveVisibleColumnIndex() const;

  void SetActiveVisibleColumnIndex(std::optional<size_t> index);

  const std::vector<VisibleColumn>& visible_columns() const {
    return visible_columns_;
  }

  const VisibleColumn& GetVisibleColumn(size_t index);

  // Get the column ids for visible columns.
  std::vector<int> GetVisibleColumnIds() const;

  // Sets the width of the column. |index| is in terms of |visible_columns_|.
  void SetVisibleColumnWidth(size_t index, int width);

  // Modify the table sort order, depending on a clicked column and the previous
  // table sort order. Does nothing if this column is not sortable.
  //
  // When called repeatedly on the same sortable column, the sort order will
  // cycle through three states in order: sorted -> reverse-sorted -> unsorted.
  // When switching from one sort column to another, the previous sort column
  // will be remembered and used as a secondary sort key.
  void ToggleSortOrder(size_t visible_column_index);

  const SortDescriptors& sort_descriptors() const { return sort_descriptors_; }
  void SetSortDescriptors(const SortDescriptors& descriptors);
  bool GetIsSorted() const { return !sort_descriptors_.empty(); }

  // Maps from the index in terms of the model to that of the view.
  size_t ModelToView(size_t model_index) const;

  // Maps from the index in terms of the view to that of the model.
  size_t ViewToModel(size_t view_index) const;

  void SetRowPadding(views::DistanceMetric distance_metric);
  int GetRowHeight() const { return row_height_; }

  bool GetSelectOnRemove() const;
  void SetSelectOnRemove(bool select_on_remove);

  // WARNING: this function forces a sort on every paint, and is therefore
  // expensive! It assumes you are calling SchedulePaint() at intervals for
  // the whole table. If your model is properly notifying the table, this is
  // not needed. This is only used in th extremely rare case, where between the
  // time the SchedulePaint() is called and the paint is processed, the
  // underlying data may change. Also, this only works if the number of rows
  // remains the same.
  bool GetSortOnPaint() const;
  void SetSortOnPaint(bool sort_on_paint);

  // TODO(crbug.com/406294165): Experimental, do not use in prod until bug is
  // fixed. If enabled, hovering over a row causes the row's background color to
  // change.
  void SetMouseHoveringEnabled(bool enabled);

  // Returns true if it was manually enabled via SetMouseHoveringEnabled().
  bool IsHoverEffectEnabled() const;

  // Updates whether table rows will render with alternating colors. Enabling
  // only works on macOS, other platforms results in a no-op.
  void SetAlternatingRowColorsEnabled(
      base::PassKey<task_manager::TaskManagerView> key,
      bool enabled);
  void SetAlternatingRowColorsEnabledForTesting(bool enabled);

  // Returns the proper ax sort direction.
  ax::mojom::SortDirection GetFirstSortDescriptorDirection() const;

  // Updates the relative bounds of the virtual accessibility children created
  // in RebuildVirtualAccessibilityChildren(). This function is public so that
  // the table's |header_| can trigger an update when its visible bounds are
  // changed, because its accessibility information is also contained in the
  // table's virtual accessibility children.
  void UpdateVirtualAccessibilityChildrenBounds();

  // Returns the virtual accessibility view corresponding to the specified cell.
  // |row| should be a view index, not a model index.
  // |visible_column_index| indexes into |visible_columns_|.
  AXVirtualView* GetVirtualAccessibilityCell(size_t row,
                                             size_t visible_column_index) const;

  bool header_row_is_active() const { return header_row_is_active_; }

  void SetHeaderStyle(const TableHeaderStyle& style);
  const TableHeaderStyle& header_style() const { return header_style_; }

  void SetTableStyle(const TableStyle& style);
  const TableStyle& table_style() const { return table_style_; }

  ui::ColorId BackgroundColorId() const;
  ui::ColorId BackgroundAlternateColorId() const;
  ui::ColorId BackgroundSelectedFocusedColorId() const;
  ui::ColorId BackgroundSelectedUnfocusedColorId() const;

  // View overrides:
  void Layout(PassKey) override;
  gfx::Size CalculatePreferredSize(
      const SizeBounds& /*available_size*/) const override;
  bool GetNeedsNotificationWhenVisibleBoundsChange() const override;
  void OnVisibleBoundsChanged() override;
  bool OnKeyPressed(const ui::KeyEvent& event) override;
  bool OnMousePressed(const ui::MouseEvent& event) override;
  void OnMouseEntered(const ui::MouseEvent& event) override;
  void OnMouseMoved(const ui::MouseEvent& event) override;
  void OnMouseExited(const ui::MouseEvent& event) override;
  void OnGestureEvent(ui::GestureEvent* event) override;
  std::u16string GetRenderedTooltipText(const gfx::Point& p) const override;
  bool HandleAccessibleAction(const ui::AXActionData& action_data) override;
  void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
  void OnThemeChanged() override;

  // ui::TableModelObserver overrides:
  void OnModelChanged() override;
  void OnItemsChanged(size_t start, size_t length) override;
  void OnItemsAdded(size_t start, size_t length) override;
  void OnItemsRemoved(size_t start, size_t length) override;
  void OnItemsMoved(size_t old_start, size_t length, size_t new_start) override;

 protected:
  // View overrides:
  gfx::Point GetKeyboardContextMenuLocation() override;
  void OnFocus() override;
  void OnBlur() override;
  void OnPaint(gfx::Canvas* canvas) override;

 private:
  friend class TableViewTestHelper;
  friend class TaskManagerView;

  class HighlightPathGenerator;
  struct GroupSortHelper;
  struct SortHelper;

  // Used during painting to determine the range of cell's that need to be
  // painted.
  // NOTE: the row indices returned by this are in terms of the view and column
  // indices in terms of |visible_columns_|.
  struct VIEWS_EXPORT PaintRegion {
    PaintRegion();
    ~PaintRegion();

    size_t min_row = 0;
    size_t max_row = 0;
    size_t min_column = 0;
    size_t max_column = 0;
  };

  void OnPaintImpl(gfx::Canvas* canvas);

  // Draws a string with the desired parameters in an efficient way by reusing
  // RenderTexts for each cell.
  void DrawString(gfx::Canvas* canvas,
                  const std::u16string& text,
                  SkColor color,
                  const gfx::Rect& text_bounds,
                  int flags,
                  size_t row,
                  size_t col);

  // Updates |render_text| from the specified parameters.
  void UpdateRenderText(const gfx::Rect& rect,
                        const std::u16string& text,
                        int flags,
                        SkColor color,
                        gfx::RenderText* render_text);

  // Returns the horizontal margin between the bounds of a cell and its
  // contents.
  int GetCellMargin() const;

  // Returns the horizontal spacing between elements (grouper, icon, and text)
  // in a cell.
  int GetCellElementSpacing() const;

  // Does the actual sort and updates the mappings (|view_to_model_| and
  // |model_to_view_|) appropriately. If |schedule_paint| is true,
  // schedules a paint. This should be true, unless called from
  // OnPaint.
  void SortItemsAndUpdateMapping(bool schedule_paint);

  // Used to sort the two rows. Returns a value < 0, == 0 or > 0 indicating
  // whether the row2 comes before row1, row2 is the same as row1 or row1 comes
  // after row2. This invokes CompareValues on the model with the sorted column.
  int CompareRows(size_t model_row1, size_t model_row2);

  // Returns the bounds of the specified row.
  gfx::Rect GetRowBounds(size_t row) const;

  // Returns the bounds of the specified cell. |visible_column_index| indexes
  // into |visible_columns_|.
  gfx::Rect GetCellBounds(size_t row, size_t visible_column_index) const;

  // Returns the bounds of the active cell.
  gfx::Rect GetActiveCellBounds() const;

  // Adjusts |bounds| based on where the text should be painted. |bounds| comes
  // from GetCellBounds() and |visible_column_index| is the corresponding column
  // (in terms of |visible_columns_|).
  void AdjustCellBoundsForText(size_t visible_column_index,
                               gfx::Rect* bounds) const;

  // Creates |header_| if necessary.
  void CreateHeaderIfNecessary(ScrollView* scroll_view);

  // Updates the |x| and |width| of each of the columns in |visible_columns_|.
  void UpdateVisibleColumnSizes();

  // Returns to the src icon bounds. If it exceeds the drawn boundary.It needs
  // to be clipped, and this method has done so for the caller.
  gfx::Rect GetPaintIconSrcBounds(const gfx::Size& image_size,
                                  int image_dest_width) const;

  // Returns the paint icon bounds in the cell.
  gfx::Rect GetPaintIconDestBounds(const gfx::Rect& cell_bounds,
                                   int text_bounds_x) const;

  // Returns the cell's that need to be painted for the specified region.
  // |bounds| is in terms of |this|.
  PaintRegion GetPaintRegion(const gfx::Rect& bounds) const;

  // Returns the bounds that need to be painted based on the clip set on
  // |canvas|.
  gfx::Rect GetPaintBounds(gfx::Canvas* canvas) const;

  // Invokes SchedulePaint() for the selected rows.
  void SchedulePaintForSelection();

  // Invokes SchedulePaintForRect() on the old and new hovered rows.
  // If either parameter is nullopt, paint is not scheduled for that parameter.
  void OnHoverChanged(std::optional<size_t> new_hovered_row);

  // Returns the TableColumn matching the specified id.
  ui::TableColumn FindColumnByID(int id) const;

  // Advances the active visible column (from the active visible column index)
  // in the specified direction.
  void AdvanceActiveVisibleColumn(AdvanceDirection direction);

  // Sets the selection to the specified index (in terms of the view).
  void SelectByViewIndex(std::optional<size_t> view_index);

  // Sets the selection model to |new_selection|.
  void SetSelectionModel(ui::ListSelectionModel new_selection);

  // Advances the selection (from the active index) in the specified direction.
  void AdvanceSelection(AdvanceDirection direction);

  // Sets |model| appropriately based on a event.
  void ConfigureSelectionModelForEvent(const ui::LocatedEvent& event,
                                       ui::ListSelectionModel* model) const;

  // Set the selection state of row at |view_index| to |select|, additionally
  // any other rows in the GroupRange containing |view_index| are updated as
  // well. This does not change the anchor or active index of |model|.
  void SelectRowsInRangeFrom(size_t view_index,
                             bool select,
                             ui::ListSelectionModel* model) const;

  // Returns the range of the specified model index. If a TableGrouper has not
  // been set this returns a group with a start of |model_index| and length of
  // 1.
  GroupRange GetGroupRange(size_t model_index) const;

  // Updates the accessible name for the table's views from `start_view_index`
  // up to `start_view_index` + `length`.
  void UpdateAccessibleNameForIndex(size_t start_view_index, size_t length);

  // Updates a set of accessibility views that expose the visible table contents
  // to assistive software.
  void RebuildVirtualAccessibilityChildren();

  // Clears the set of accessibility views set up in
  // RebuildVirtualAccessibilityChildren(). Useful when the model is in the
  // process of changing but the virtual accessibility children haven't been
  // updated yet, e.g. showing or hiding a column via SetColumnVisibility().
  void ClearVirtualAccessibilityChildren();

  void UpdateVirtualAccessibilityChildrenVisibilityState();

  void SetAccessibleSelectionForIndex(size_t view_index, bool selected) const;
  void SetAccessibleSelectionForRange(size_t start_view_index,
                                      size_t end_view_index,
                                      bool selected) const;
  void ClearAccessibleSelection() const;
  void UpdateAccessibleSelectionForColumnIndex(
      size_t visible_column_index) const;

  // Helper functions used in UpdateVirtualAccessibilityChildrenBounds() for
  // calculating the accessibility bounds for the header and table rows and
  // cell's.
  gfx::Rect CalculateHeaderRowAccessibilityBounds() const;
  gfx::Rect CalculateHeaderCellAccessibilityBounds(
      const size_t visible_column_index) const;
  gfx::Rect CalculateTableRowAccessibilityBounds(const size_t row_index) const;
  gfx::Rect CalculateTableCellAccessibilityBounds(
      const size_t row_index,
      const size_t visible_column_index) const;

  // Schedule a future call UpdateAccessibilityFocus if not already pending.
  void ScheduleUpdateAccessibilityFocusIfNeeded();

  // A PassKey so that no other code can call UpdateAccessibilityFocus
  // directly, only ScheduleUpdateAccessibilityFocusIfNeeded.
  class UpdateAccessibilityFocusPassKey {
   public:
    ~UpdateAccessibilityFocusPassKey() = default;

   private:
    friend void TableView::ScheduleUpdateAccessibilityFocusIfNeeded();

    // Avoid =default to disallow creation by uniform initialization.
    UpdateAccessibilityFocusPassKey() {}  // NOLINT
  };

  // Updates the internal accessibility state and fires the required
  // accessibility events to indicate to assistive software which row is active
  // and which cell is focused, if any. Don't call this directly; call
  // ScheduleUpdateAccessibilityFocusIfNeeded to ensure that only one call
  // is made and that it happens after all changes have been made.
  void UpdateAccessibilityFocus(UpdateAccessibilityFocusPassKey pass_key);

  // Returns the virtual accessibility view corresponding to the specified row.
  // |row| should be a view index into the TableView's body elements, not a
  // model index.
  AXVirtualView* GetVirtualAccessibilityBodyRow(size_t row) const;

  // Returns the virtual accessibility view corresponding to the header row, if
  // it exists.
  AXVirtualView* GetVirtualAccessibilityHeaderRow();

  // Returns the virtual accessibility view corresponding to the cell in the
  // given row at the specified column index.
  // `ax_row` should be the virtual view of either a header or body row.
  // `visible_column_index` indexes into `visible_columns_`.
  AXVirtualView* GetVirtualAccessibilityCellImpl(
      AXVirtualView* ax_row,
      size_t visible_column_index) const;

  // Creates a virtual accessibility view that is used to expose information
  // about the row at |view_index| to assistive software.
  std::unique_ptr<AXVirtualView> CreateRowAccessibilityView(size_t view_index);

  // Creates a virtual accessibility view that is used to expose information
  // about the cell at the provided coordinates |row_index| and |column_index|
  // to assistive software.
  std::unique_ptr<AXVirtualView> CreateCellAccessibilityView(
      size_t row_index,
      size_t column_index);

  // Creates a virtual accessibility view that is used to expose information
  // about this header to assistive software.
  std::unique_ptr<AXVirtualView> CreateHeaderAccessibilityView();

  // Updates the accessibility data for |ax_row| to match the data in the view
  // at |view_index| in the table. Returns false if row data not changed.
  bool UpdateVirtualAccessibilityRowData(AXVirtualView* ax_row,
                                         int view_index,
                                         int model_index);

  // Installs a focus ring on the TableView.
  void InstallFocusRing();

  // Updates the focus rings of the TableView and the TableHeader if necessary.
  void UpdateFocusRings();

  // Update the accessibility name of the table header when column sorting
  // changes.
  void UpdateHeaderAXName();

  // Handles key events for keyboard navigation by cell. Returns true if the
  // event was handled.
  bool HandleKeyPressedForKeyboardNavigationByCell(const ui::KeyEvent& event);

  // Updates `scroll_offset_` and redraws the hover layer based on the rows
  // underneath the cursor.
  void SyncHoverToScroll();

  // As long as IsHoveringPossible(), guarantees that the hover layer is redrawn
  // at the current mouse location and `scroll_offset_`.
  void ForceHoverUpdate();

  // Computes the row (or all grouped rows) at the specified coordinates, and
  // updates the hover layer if necessary.
  void SetHover(gfx::Point view_coordinates);

  // Clears `hovered_rows_`, and hides the hover layer.
  void ClearHover();

  // Updates the transform of `hover_layer_` using `hovered_rows_`.
  void UpdateHoverLayer();

  // TODO(327473315): Only one of raw_ptr in this class is dangling. Find which
  // one.
  raw_ptr<ui::TableModel, LeakedDanglingUntriaged> model_ = nullptr;

  std::vector<ui::TableColumn> columns_;

  // The set of visible columns. The values of these point to |columns_|. This
  // may contain a subset of |columns_|.
  std::vector<VisibleColumn> visible_columns_;

  // The active visible column. Used for keyboard access to functionality such
  // as sorting and resizing. nullopt if no visible column is active.
  std::optional<size_t> active_visible_column_index_ = std::nullopt;

  // The header. This is only created if more than one column is specified or
  // the first column has a non-empty title.
  // TODO(327473315): Only one of raw_ptr in this class is dangling. Find which
  // one.
  raw_ptr<TableHeader, LeakedDanglingUntriaged> header_ = nullptr;

  // TableView allows using the keyboard to activate a cell or row, including
  // optionally the header row. This bool keeps track of whether the active row
  // is the header row, since the selection model doesn't support that.
  bool header_row_is_active_ = false;

  // The model index rows beneath the cursor, if the table is focused.
  std::optional<GroupRange> hovered_rows_ = std::nullopt;

  // The view index of the row underneath the cursor. Note: A single row.
  std::optional<size_t> view_index_of_row_under_cursor_ = std::nullopt;

  // If enabled, rows will alternate between kColorTableBackground and
  // kColorTableBackgroundAlternate.
  bool alternating_row_colors_ =
      PlatformStyle::kTableViewSupportsAlternatingRowColors;

  TableType table_type_ = TableType::kTextOnly;

  bool single_selection_ = true;

  // If |select_on_remove_| is true: when a selected item is removed, if the
  // removed item is not the last item, select its next one; otherwise select
  // its previous one if there is an item.
  // If |select_on_remove_| is false: when a selected item is removed, no item
  // is selected then.
  bool select_on_remove_ = true;

  // TODO(327473315): Only one of raw_ptr in this class is dangling. Find which
  // one.
  raw_ptr<TableViewObserver, LeakedDanglingUntriaged> observer_ = nullptr;
  // If |sort_on_paint_| is true, table will sort before painting.
  bool sort_on_paint_ = false;

  // The selection, in terms of the model.
  ui::ListSelectionModel selection_model_;

  gfx::FontList font_list_;

  int row_height_;

  // Width of the ScrollView at last layout. Used to determine when we should
  // invoke UpdateVisibleColumnSizes().
  int last_parent_width_ = 0;

  // The width we layout to. This may differ from |last_parent_width_|.
  int layout_width_ = 0;

  // Current sort.
  SortDescriptors sort_descriptors_;

  // Mappings used when sorted.
  std::vector<size_t> view_to_model_;
  std::vector<size_t> model_to_view_;

  // TODO(327473315): Only one of raw_ptr in this class is dangling. Find which
  // one.
  raw_ptr<TableGrouper, LeakedDanglingUntriaged> grouper_ = nullptr;

  // True if in SetVisibleColumnWidth().
  bool in_set_visible_column_width_ = false;

  // Keeps track whether a call to UpdateAccessibilityFocus is already
  // pending or not.
  bool update_accessibility_focus_pending_ = false;

  // Draws the Grouper if one is present, and set to true.
  bool grouper_visible_ = true;

  // Customization for the header. Includes options such as padding.
  TableHeaderStyle header_style_;

  // Customization for the table.
  TableStyle table_style_;

  // TODO(crbug.com/388086397): Enable by mouse hovering by default when color
  // tokens are refined on all platforms.
  bool hovering_enabled_ = false;

  // Hover Layer used to highlight a row based on mouse cursor position.
  ui::Layer hover_layer_{ui::LAYER_SOLID_COLOR};

  // RenderText cache from row,col.
  std::vector<std::vector<std::unique_ptr<gfx::RenderText>>> render_text_cache_;

  // Callback subscriptions.
  base::CallbackListSubscription on_scroll_view_scrolled_;

  // Last received offset from the on_scroll_view_scrolled_ callback
  gfx::Point scroll_offset_{0, 0};

  // Weak pointer factory, enables using PostTask safely.
  base::WeakPtrFactory<TableView> weak_factory_;
};

BEGIN_VIEW_BUILDER(VIEWS_EXPORT, TableView, View)
VIEW_BUILDER_PROPERTY(std::optional<size_t>, ActiveVisibleColumnIndex)
VIEW_BUILDER_PROPERTY(const std::vector<ui::TableColumn>&,
                      Columns,
                      std::vector<ui::TableColumn>)
VIEW_BUILDER_PROPERTY(ui::TableModel*, Model)
VIEW_BUILDER_PROPERTY(TableType, TableType)
VIEW_BUILDER_PROPERTY(bool, SingleSelection)
VIEW_BUILDER_PROPERTY(TableGrouper*, Grouper)
VIEW_BUILDER_PROPERTY(TableViewObserver*, Observer)
VIEW_BUILDER_PROPERTY(bool, SelectOnRemove)
VIEW_BUILDER_PROPERTY(bool, SortOnPaint)
VIEW_BUILDER_METHOD(SetColumnVisibility, int, bool)
VIEW_BUILDER_METHOD(SetVisibleColumnWidth, int, int)
END_VIEW_BUILDER

}  // namespace views

DEFINE_VIEW_BUILDER(VIEWS_EXPORT, views::TableView)

namespace base {

// Allow use of ScopedObservation with TableView, which requires use of
// SetObserver and only supports a single TableViewObserver at a time.
template <>
struct ScopedObservationTraits<views::TableView, views::TableViewObserver> {
  static void AddObserver(views::TableView* source,
                          views::TableViewObserver* observer) {
    CHECK(!source->GetObserver())
        << "TableView does not support multiple observers";
    source->SetObserver(observer);
  }
  static void RemoveObserver(views::TableView* source,
                             views::TableViewObserver* observer) {
    CHECK_EQ(source->GetObserver(), observer)
        << "TableView does not support multiple observers";
    source->SetObserver(nullptr);
  }
};

}  // namespace base

#endif  // UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_H_