chromium/ui/views/metadata/view_factory.h

// Copyright 2020 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_METADATA_VIEW_FACTORY_H_
#define UI_VIEWS_METADATA_VIEW_FACTORY_H_

#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string_view>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/macros/concat.h"
#include "base/memory/raw_ptr.h"
#include "ui/base/class_property.h"
#include "ui/base/metadata/base_type_conversion.h"
#include "ui/views/metadata/view_factory_internal.h"
#include "ui/views/views_export.h"

namespace views {

template <typename Builder>
class BaseViewBuilderT : public internal::ViewBuilderCore {};

}  // namespace views

// Example of builder class generated by the following macros.
//
// template <typename Builder, typename ViewClass>
// class ViewBuilderT : public BaseViewBuilderT<Builder, ViewClass> {
//  public:
//   ViewBuilderT() = default;
//   ViewBuilderT(const ViewBuilderT&&) = default;
//   ViewBuilderT& operator=(const ViewBuilderT&&) = default;
//   ~ViewBuilderT() override = default;
//
//   Builder& SetEnabled(bool value) {
//     auto setter = std::make_unique<
//         PropertySetter<ViewClass, bool, decltype(&ViewClass::SetEnabled),
//         &ViewClass::SetEnabled>>(value);
//     ViewBuilderCore::AddPropertySetter(std::move(setter));
//     return *static_cast<Builder*>(this);
//   }
//
//   Builder& SetVisible(bool value) {
//     auto setter = std::make_unique<
//         PropertySetter<ViewClass, bool, &ViewClass::SetVisible>>(value);
//     ViewBuilderCore::AddPropertySetter(std::move(setter));
//     return *static_cast<Builder*>(this);
//   }
// };
//
// class VIEWS_EXPORT ViewBuilderTest
//     : public ViewBuilderT<ViewBuilderTest, View> {};
//
// template <typename Builder, typename ViewClass>
// class LabelButtonBuilderT : public ViewBuilderT<Builder, ViewClass> {
//  public:
//   LabelButtonBuilderT() = default;
//   LabelButtonBuilderT(LabelButtonBuilderT&&) = default;
//   LabelButtonBuilderT& operator=(LabelButtonBuilderT&&) = default;
//   ~LabelButtonBuilderT() override = default;
//
//   Builder& SetIsDefault(bool value) {
//     auto setter = std::make_unique<
//         PropertySetter<ViewClass, bool, decltype(&ViewClass::SetIsDefault),
//         &ViewClass::SetIsDefault>>(value);
//     ViewBuilderCore::AddPropertySetter(std::move(setter));
//     return *static_cast<Builder*>(this);
//   }
// };
//
// class VIEWS_EXPORT LabelButtonBuilder
//     : public LabelButtonBuilderT<LabelButtonBuilder, LabelButton> {};

// The maximum number of overloaded params is 10. This should be overkill since
// a function with 10 params is well into the "suspect" territory anyway.
// TODO(kylixrd@): Evaluate whether a max of 5 may be more reasonable.
#define NUM_ARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...)
#define NUM_ARGS(...)

// This will expand the list of types into a parameter declaration list.
// eg: DECL_PARAMS(int, char, float, double) will expand to:
// int param4, char param3, float param2, double param1
#define DECL_PARAM1(type)
#define DECL_PARAM2(type, ...)
#define DECL_PARAM3(type, ...)
#define DECL_PARAM4(type, ...)
#define DECL_PARAM5(type, ...)
#define DECL_PARAM6(type, ...)
#define DECL_PARAM7(type, ...)
#define DECL_PARAM8(type, ...)
#define DECL_PARAM9(type, ...)
#define DECL_PARAM10(type, ...)
#define DECL_PARAMS(...)

// This will expand into list of parameters suitable for calling a function
// using the same param names from the above expansion.
// eg: PASS_PARAMS(int, char, float, double)
// param4, param3, param2, param1
#define PASS_PARAM1(type)
#define PASS_PARAM2(type, ...)
#define PASS_PARAM3(type, ...)
#define PASS_PARAM4(type, ...)
#define PASS_PARAM5(type, ...)
#define PASS_PARAM6(type, ...)
#define PASS_PARAM7(type, ...)
#define PASS_PARAM8(type, ...)
#define PASS_PARAM9(type, ...)
#define PASS_PARAM10(type, ...)
#define PASS_PARAMS(...)

// BEGIN_VIEW_BUILDER, END_VIEW_BUILDER and VIEW_BUILDER_XXXX macros should
// be placed into the same namespace as the 'view_class' parameter.

#define BEGIN_VIEW_BUILDER(export, view_class, ancestor)

#define VIEW_BUILDER_PROPERTY2(property_type, property_name)

#define VIEW_BUILDER_PROPERTY3(property_type, property_name, field_type)

#define GET_VB_MACRO(_1, _2, _3, macro_name, ...)
#define VIEW_BUILDER_PROPERTY(...)

// Sometimes the method being called is on the ancestor to ViewClass_. This
// macro will ensure the overload casts function correctly by specifying the
// ancestor class on which the method is declared. In most cases the following
// macro will be used.
// NOTE: See the Builder declaration for DialogDelegateView in dialog_delegate.h
//       for an example.
#define VIEW_BUILDER_OVERLOAD_METHOD_CLASS(class_name, method_name, ...)

// Unless the above scenario is in play, please favor the use of this macro for
// declaring overloaded builder methods.
#define VIEW_BUILDER_OVERLOAD_METHOD(method_name, ...)

#define VIEW_BUILDER_METHOD(method_name, ...)

// Enables exposing a template or ambiguously-named method by providing an alias
// that will be used on the Builder.
//
// Examples:
//
//   VIEW_BUILDER_METHOD_ALIAS(
//       AddTab, AddTab<View>, std::string_view, unique_ptr<View>)
//
//   VIEW_BUILDER_METHOD_ALIAS(UnambiguousName, AmbiguousName, int)
//
#define VIEW_BUILDER_METHOD_ALIAS(builder_method, view_method, ...)

#define VIEW_BUILDER_VIEW_TYPE_PROPERTY(property_type, property_name)

#define VIEW_BUILDER_VIEW_PROPERTY(property_type, property_name)

#define VIEW_BUILDER_PROPERTY_DEFAULT(property_type, property_name, default)

// Turn off clang-format due to it messing up the following macro. Places the
// semi-colon on a separate line.
// clang-format off

#define END_VIEW_BUILDER

// Unlike the above macros, DEFINE_VIEW_BUILDER must be placed in the global
// namespace. Unless 'view_class' is already in the 'views' namespace, it should
// be fully qualified with the namespace in which it lives.

#define DEFINE_VIEW_BUILDER(export, view_class)

// clang-format on

#endif  // UI_VIEWS_METADATA_VIEW_FACTORY_H_