1 // Copyright 2020 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 
5 #ifndef UI_VIEWS_METADATA_VIEW_FACTORY_H_
6 #define UI_VIEWS_METADATA_VIEW_FACTORY_H_
7 
8 #include <functional>
9 #include <map>
10 #include <memory>
11 #include <utility>
12 
13 #include "base/strings/string16.h"
14 #include "ui/base/class_property.h"
15 #include "ui/views/metadata/type_conversion.h"
16 #include "ui/views/metadata/view_factory_internal.h"
17 #include "ui/views/views_export.h"
18 
19 namespace views {
20 
21 template <typename Builder>
22 class BaseViewBuilderT : public internal::ViewBuilderCore {
23  public:
24   using ViewClass_ = typename internal::ViewClassTrait<Builder>::ViewClass_;
BaseViewBuilderT()25   BaseViewBuilderT() { view_ = std::make_unique<ViewClass_>(); }
BaseViewBuilderT(ViewClass_ * root_view)26   explicit BaseViewBuilderT(ViewClass_* root_view) : root_view_(root_view) {}
27   BaseViewBuilderT(BaseViewBuilderT&&) = default;
28   BaseViewBuilderT& operator=(BaseViewBuilderT&&) = default;
29   ~BaseViewBuilderT() override = default;
30 
CopyAddressTo(ViewClass_ ** view_address)31   Builder& CopyAddressTo(ViewClass_** view_address) {
32     *view_address = view_ ? view_.get() : root_view_;
33     return *static_cast<Builder*>(this);
34   }
35 
36   template <typename Child>
AddChild(Child & child)37   Builder& AddChild(Child& child) {
38     children_.push_back(child);
39     return *static_cast<Builder*>(this);
40   }
41 
AddChildren(const std::initializer_list<std::reference_wrapper<internal::ViewBuilderCore>> & children)42   Builder& AddChildren(
43       const std::initializer_list<
44           std::reference_wrapper<internal::ViewBuilderCore>>& children) {
45     children_.insert(children_.end(), children.begin(), children.end());
46     return *static_cast<Builder*>(this);
47   }
48 
Build()49   std::unique_ptr<ViewClass_> Build() {
50     DCHECK(!root_view_) << "Root view specified. Use BuildChildren() instead.";
51     DCHECK(view_);
52     SetProperties(view_.get());
53     CreateChildren(view_.get());
54     return std::move(view_);
55   }
56 
BuildChildren()57   void BuildChildren() {
58     DCHECK(!view_) << "Default constructor called. Use Build() instead.";
59     DCHECK(root_view_);
60     SetProperties(root_view_);
61     CreateChildren(root_view_);
62   }
63 
64   template <typename T>
SetProperty(const ui::ClassProperty<T> * property,metadata::ArgType<T> value)65   Builder& SetProperty(const ui::ClassProperty<T>* property,
66                        metadata::ArgType<T> value) {
67     auto setter =
68         std::make_unique<internal::ClassPropertyValueSetter<ViewClass_, T>>(
69             property, value);
70     internal::ViewBuilderCore::AddPropertySetter(std::move(setter));
71     return *static_cast<Builder*>(this);
72   }
73 
74   template <typename T>
SetProperty(const ui::ClassProperty<T * > * property,metadata::ArgType<T> value)75   Builder& SetProperty(const ui::ClassProperty<T*>* property,
76                        metadata::ArgType<T> value) {
77     auto setter =
78         std::make_unique<internal::ClassPropertyMoveSetter<ViewClass_, T>>(
79             property, value);
80     internal::ViewBuilderCore::AddPropertySetter(std::move(setter));
81     return *static_cast<Builder*>(this);
82   }
83 
84   template <typename T>
SetProperty(const ui::ClassProperty<T * > * property,T && value)85   Builder& SetProperty(const ui::ClassProperty<T*>* property, T&& value) {
86     auto setter =
87         std::make_unique<internal::ClassPropertyMoveSetter<ViewClass_, T>>(
88             property, std::move(value));
89     internal::ViewBuilderCore::AddPropertySetter(std::move(setter));
90     return *static_cast<Builder*>(this);
91   }
92 
93  protected:
DoBuild()94   std::unique_ptr<View> DoBuild() override { return Build(); }
95 
96   // Owned and meaningful during the Builder building process. Its
97   // ownership will be transferred out upon Build() call.
98   std::unique_ptr<ViewClass_> view_;
99 
100   // Unowned root view. Used for creating a builder with an existing root
101   // instance.
102   ViewClass_* root_view_ = nullptr;
103 };
104 
105 }  // namespace views
106 
107 // Example of builder class generated by the following macros.
108 //
109 // template <typename Builder, typename ViewClass>
110 // class ViewBuilderT : public BaseViewBuilderT<Builder, ViewClass> {
111 //  public:
112 //   ViewBuilderT() = default;
113 //   ViewBuilderT(const ViewBuilderT&) = default;
114 //   ~ViewBuilderT() override = default;
115 //   ViewBuilderT& operator=(const ViewBuilderT&) = default;
116 //
117 //   Builder& SetEnabled(bool value) {
118 //     auto setter = std::make_unique<
119 //         PropertySetter<ViewClass, bool, decltype(&ViewClass::SetEnabled),
120 //         &ViewClass::SetEnabled>>(value);
121 //     ViewBuilderCore::AddPropertySetter(std::move(setter));
122 //     return *static_cast<Builder*>(this);
123 //   }
124 //
125 //   Builder& SetVisible(bool value) {
126 //     auto setter = std::make_unique<
127 //         PropertySetter<ViewClass, bool, &ViewClass::SetVisible>>(value);
128 //     ViewBuilderCore::AddPropertySetter(std::move(setter));
129 //     return *static_cast<Builder*>(this);
130 //   }
131 // };
132 //
133 // class VIEWS_EXPORT ViewBuilderTest
134 //     : public ViewBuilderT<ViewBuilderTest, View> {};
135 //
136 // template <typename Builder, typename ViewClass>
137 // class LabelButtonBuilderT : public ViewBuilderT<Builder, ViewClass> {
138 //  public:
139 //   LabelButtonBuilderT() = default;
140 //   LabelButtonBuilderT(LabelButtonBuilderT&&) = default;
141 //   ~LabelButtonBuilderT() override = default;
142 //   LabelButtonBuilderT& operator=(LabelButtonBuilderT&&) = default;
143 //
144 //   Builder& SetIsDefault(bool value) {
145 //     auto setter = std::make_unique<
146 //         PropertySetter<ViewClass, bool, decltype(&ViewClass::SetIsDefault),
147 //         &ViewClass::SetIsDefault>>(value);
148 //     ViewBuilderCore::AddPropertySetter(std::move(setter));
149 //     return *static_cast<Builder*>(this);
150 //   }
151 // };
152 //
153 // class VIEWS_EXPORT LabelButtonBuilder
154 //     : public LabelButtonBuilderT<LabelButtonBuilder, LabelButton> {};
155 
156 // BEGIN_VIEW_BUILDER, END_VIEW_BUILDER and VIEW_BUILDER_XXXX macros should
157 // be placed into the same namespace as the 'view_class' parameter.
158 
159 #define BEGIN_VIEW_BUILDER(export, view_class, ancestor)                    \
160   template <typename BuilderT>                                              \
161   class export view_class##BuilderT : public ancestor##BuilderT<BuilderT> { \
162    private:                                                                 \
163     using ViewClass_ = view_class;                                          \
164                                                                             \
165    public:                                                                  \
166     view_class##BuilderT() = default;                                       \
167     explicit view_class##BuilderT(                                          \
168         typename ::views::internal::ViewClassTrait<BuilderT>::ViewClass_*   \
169             root_view)                                                      \
170         : ancestor##BuilderT<BuilderT>(root_view) {}                        \
171     view_class##BuilderT(view_class##BuilderT&&) = default;                 \
172     view_class##BuilderT& operator=(view_class##BuilderT&&) = default;      \
173     ~view_class##BuilderT() override = default;
174 
175 #define VIEW_BUILDER_PROPERTY(property_type, property_name)                   \
176   BuilderT& Set##property_name(                                               \
177       ::views::metadata::ArgType<property_type> value) {                      \
178     auto setter = std::make_unique<::views::internal::PropertySetter<         \
179         ViewClass_, property_type, decltype(&ViewClass_::Set##property_name), \
180         &ViewClass_::Set##property_name>>(std::move(value));                  \
181     ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(setter)); \
182     return *static_cast<BuilderT*>(this);                                     \
183   }
184 
185 #define VIEW_BUILDER_METHOD(method_name)                                      \
186   BuilderT& method_name() {                                                   \
187     auto caller = std::make_unique<::views::internal::ClassMethodCaller<      \
188         ViewClass_, decltype(&ViewClass_::method_name),                       \
189         &ViewClass_::method_name>>();                                         \
190     ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(caller)); \
191     return *static_cast<BuilderT*>(this);                                     \
192   }
193 
194 #define VIEW_BUILDER_VIEW_TYPE_PROPERTY(property_type, property_name)         \
195   BuilderT& Set##property_name(                                               \
196       std::reference_wrapper<::views::internal::ViewBuilderCore> value) {     \
197     auto setter = std::make_unique<::views::internal::ViewBuilderSetter<      \
198         ViewClass_, property_type,                                            \
199         decltype(&ViewClass_::Set##property_name<property_type>),             \
200         &ViewClass_::Set##property_name<property_type>>>(value);              \
201     ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(setter)); \
202     return *static_cast<BuilderT*>(this);                                     \
203   }
204 
205 #define VIEW_BUILDER_VIEW_PROPERTY(property_type, property_name)              \
206   BuilderT& Set##property_name(                                               \
207       std::reference_wrapper<::views::internal::ViewBuilderCore> value) {     \
208     auto setter = std::make_unique<::views::internal::ViewBuilderSetter<      \
209         ViewClass_, property_type, decltype(&ViewClass_::Set##property_name), \
210         &ViewClass_::Set##property_name>>(value);                             \
211     ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(setter)); \
212     return *static_cast<BuilderT*>(this);                                     \
213   }
214 
215 #define VIEW_BUILDER_PROPERTY_DEFAULT(property_type, property_name, default)  \
216   BuilderT& Set##property_name(                                               \
217       ::views::metadata::ArgType<property_type> value = default) {            \
218     auto setter = std::make_unique<::views::internal::PropertySetter<         \
219         ViewClass_, property_type, decltype(&ViewClass_::Set##property_name), \
220         &ViewClass_::Set##property_name>>(std::move(value));                  \
221     ::views::internal::ViewBuilderCore::AddPropertySetter(std::move(setter)); \
222     return *static_cast<BuilderT*>(this);                                     \
223   }
224 
225 // Turn off clang-format due to it messing up the following macro. Places the
226 // semi-colon on a separate line.
227 // clang-format off
228 
229 #define END_VIEW_BUILDER };
230 
231 // Unlike the above macros, DEFINE_VIEW_BUILDER must be placed in the global
232 // namespace. Unless 'view_class' is already in the 'views' namespace, it should
233 // be fully qualified with the namespace in which it lives.
234 
235 #define DEFINE_VIEW_BUILDER(export, view_class)                      \
236 namespace views {                                                    \
237   template <>                                                        \
238   class export Builder<view_class>                                   \
239       : public view_class##BuilderT<Builder<view_class>> {           \
240    private:                                                          \
241     using ViewClass_ = view_class;                                   \
242    public:                                                           \
243     Builder<ViewClass_>() = default;                                 \
244     explicit Builder<ViewClass_>(ViewClass_* root_view)              \
245         : view_class##BuilderT<Builder<ViewClass_>>(root_view) {}    \
246     Builder<ViewClass_>(Builder&&) = default;                        \
247     Builder<ViewClass_>& operator=(Builder<ViewClass_>&&) = default; \
248     ~Builder<ViewClass_>() = default;                                \
249   };                                                                 \
250 }  // namespace views
251 
252 // clang-format on
253 
254 #endif  // UI_VIEWS_METADATA_VIEW_FACTORY_H_
255