view_model.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright (c) 2012 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. #ifndef UI_VIEWS_VIEW_MODEL_H_
  5. #define UI_VIEWS_VIEW_MODEL_H_
  6. #include <vector>
  7. #include "base/check_op.h"
  8. #include "third_party/abseil-cpp/absl/types/optional.h"
  9. #include "ui/gfx/geometry/rect.h"
  10. #include "ui/views/views_export.h"
  11. namespace views {
  12. class View;
  13. class ViewModelUtils;
  14. // Internal implementation of the templated ViewModelT class. Provides
  15. // non-templated "unsafe" methods for ViewModelT to wrap around. Any methods
  16. // that allow insertion of or access to a View* should be protected, and have a
  17. // public method in the ViewModelT subclass that provides type-safe access to
  18. // the correct View subclass.
  19. class VIEWS_EXPORT ViewModelBase {
  20. public:
  21. struct Entry {
  22. Entry() = default;
  23. View* view = nullptr;
  24. gfx::Rect ideal_bounds;
  25. };
  26. using Entries = std::vector<Entry>;
  27. ViewModelBase(const ViewModelBase&) = delete;
  28. ViewModelBase& operator=(const ViewModelBase&) = delete;
  29. ~ViewModelBase();
  30. const Entries& entries() const { return entries_; }
  31. // Removes the view at the specified index. This does not actually remove the
  32. // view from the view hierarchy.
  33. void Remove(size_t index);
  34. // Moves the view at |index| to |target_index|. |target_index| is in terms
  35. // of the model *after* the view at |index| is removed.
  36. void Move(size_t index, size_t target_index);
  37. // Variant of Move() that leaves the bounds as is. That is, after invoking
  38. // this the bounds of the view at |target_index| (and all other indices) are
  39. // exactly the same as the bounds of the view at |target_index| before
  40. // invoking this.
  41. void MoveViewOnly(size_t index, size_t target_index);
  42. // Returns the number of views.
  43. size_t view_size() const { return entries_.size(); }
  44. // Removes and deletes all the views.
  45. void Clear();
  46. void set_ideal_bounds(size_t index, const gfx::Rect& bounds) {
  47. check_index(index);
  48. entries_[index].ideal_bounds = bounds;
  49. }
  50. const gfx::Rect& ideal_bounds(size_t index) const {
  51. check_index(index);
  52. return entries_[index].ideal_bounds;
  53. }
  54. // Returns the index of the specified view, or nullopt if the view isn't in
  55. // the model.
  56. absl::optional<size_t> GetIndexOfView(const View* view) const;
  57. protected:
  58. ViewModelBase();
  59. // Returns the view at the specified index. Note: Most users should use
  60. // view_at() in the subclass, to get a view of the correct type. (Do not call
  61. // ViewAtBase then static_cast to the desired type.)
  62. View* ViewAtBase(size_t index) const {
  63. check_index(index);
  64. return entries_[index].view;
  65. }
  66. // Adds |view| to this model. This does not add |view| to a view hierarchy,
  67. // only to this model.
  68. void AddUnsafe(View* view, size_t index);
  69. private:
  70. // For access to ViewAtBase().
  71. friend class ViewModelUtils;
  72. void check_index(size_t index) const { DCHECK_LT(index, entries_.size()); }
  73. Entries entries_;
  74. };
  75. // ViewModelT is used to track an 'interesting' set of a views. Often times
  76. // during animations views are removed after a delay, which makes for tricky
  77. // coordinate conversion as you have to account for the possibility of the
  78. // indices from the model not lining up with those you expect. This class lets
  79. // you define the 'interesting' views and operate on those views.
  80. template <class T>
  81. class ViewModelT : public ViewModelBase {
  82. public:
  83. ViewModelT() = default;
  84. ViewModelT(const ViewModelT&) = delete;
  85. ViewModelT& operator=(const ViewModelT&) = delete;
  86. // Adds |view| to this model. This does not add |view| to a view hierarchy,
  87. // only to this model.
  88. void Add(T* view, size_t index) { AddUnsafe(view, index); }
  89. // Returns the view at the specified index.
  90. T* view_at(size_t index) const { return static_cast<T*>(ViewAtBase(index)); }
  91. };
  92. // ViewModel is a collection of views with no specfic type. If all views have
  93. // the same type, the use of ViewModelT is preferred so that the views can be
  94. // retrieved without potentially unsafe downcasts.
  95. using ViewModel = ViewModelT<View>;
  96. } // namespace views
  97. #endif // UI_VIEWS_VIEW_MODEL_H_