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