ComponentKit/Components/ImageComponentBuilder.h (130 lines of code) (raw):
/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#import <ComponentKit/CKDefines.h>
#if CK_NOT_SWIFT
#import <ComponentKit/ComponentBuilder.h>
#import <ComponentKit/CKImageComponent.h>
namespace CK {
namespace BuilderDetails {
namespace ImageComponentPropId {
constexpr static auto image = ComponentBuilderBaseSizeOnlyPropId::__max << 1;
constexpr static auto anyAttribute = image << 1;
constexpr static auto __max = image;
}
template <PropsBitmapType PropsBitmap = 0>
class __attribute__((__may_alias__)) ImageComponentBuilder
: public ComponentBuilderBaseSizeOnly<ImageComponentBuilder, PropsBitmap> {
public:
ImageComponentBuilder() = default;
~ImageComponentBuilder() = default;
/**
The image to display.
*/
auto &image(NS_RELEASES_ARGUMENT UIImage *i)
{
constexpr auto imageIsNotSet = !PropBitmap::isSet(PropsBitmap, ImageComponentPropId::image);
static_assert(imageIsNotSet, "Property 'image' is already set.");
_image = i;
return reinterpret_cast<
ImageComponentBuilder<PropsBitmap | ImageComponentPropId::image> &>(*this);
}
/**
Specifies a background color that a view for the component should have.
@param c A background color to set
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &backgroundColor(NS_RELEASES_ARGUMENT UIColor *c)
{
_attributes.insert({ @selector(setBackgroundColor:), c });
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies whether a view for the component should ignore user events.
@param enabled A Boolean value that determines whether user events are ignored
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &userInteractionEnabled(bool enabled)
{
_attributes.insert({ @selector(setUserInteractionEnabled:), enabled });
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies whether subviews of a view for the component should be confined to its bounds.
@param clip A Boolean value that determines whether subviews are confined
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &clipsToBounds(bool clip)
{
_attributes.insert({ @selector(setClipsToBounds:), clip });
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies the alpha value for this component's view.
@param a A floating-point number in the range 0.0 to 1.0, where 0.0 represents totally transparent and 1.0 represents
totally opaque.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &alpha(CGFloat a)
{
_attributes.insert({ @selector(setAlpha:), a });
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies the width of the border for this component's view.
@param w The border width. When this value is greater than 0.0, the view draws a border using the current borderColor
value.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &borderWidth(CGFloat w)
{
_attributes.insert({ CKComponentViewAttribute::LayerAttribute(@selector(setBorderWidth:)), w });
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies the color of the border for this component's view.
@param c A @c UIColor value that determines the border color. The default value of this property is an opaque black.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &borderColor(NS_RELEASES_ARGUMENT UIColor *c)
{
_attributes.insert({ CKComponentViewAttribute::LayerAttribute(@selector(setBorderColor:)), (id)c.CGColor });
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies the radius to use when drawing rounded corners for the component's view background.
@param r A floating point value that determines the radius. Setting the radius to a value greater than 0.0 causes the
view to begin drawing rounded corners on its background.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &cornerRadius(CGFloat r)
{
_attributes.insert({ CKComponentViewAttribute::LayerAttribute(@selector(setCornerRadius:)), r });
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies the action that should be sent when the user performs a single tap gesture on the component's view.
@param a A @c CKAction instance to be sent when the gesture is recognized.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &onTap(CKAction<UIGestureRecognizer *> a)
{
_attributes.insert(CKComponentTapGestureAttribute(a));
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Used to determine how a view lays out its content when its bounds change. The default is @c UIViewContentModeScaleToFill .
@param m A mode to set.
*/
auto &contentMode(UIViewContentMode m)
{
_attributes.insert({@selector(setContentMode:), m});
return *this;
}
/**
Sets a value for an arbitrary view property by specifying a selector that corresponds to the property setter and the
value.
@param attr A selector corresponding to a setter.
@param value A value to set.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &attribute(SEL attr, NS_RELEASES_ARGUMENT id value)
{
_attributes.insert({attr, value});
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Sets a value for an arbitrary view property by specifying a complete attribute descriptor and a value.
@param attr An view attribute descriptor.
@param value A value to set. Both expressions of boxable types, such as @c int or @c CGFloat, and ObjC objects are
supported.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &attribute(const CKComponentViewAttribute &attr, const CKBoxedValue &value)
{
_attributes.insert({attr, value});
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Adds a complete attribute / value pair to the component view configuration, mostly for convenience for helper
functions that return both an attribute and a value.
@param v An attribute / value pair.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &attribute(const CKComponentViewAttributeValue &v)
{
_attributes.insert(v);
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies a selector that should be sent up the responder chain when the component's view receives a 'touch up
inside' event.
@param action An selector to send.
@note Setting this property on a view that is not a @c UIControl subclass will trigger a runtime error.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &onTouchUpInside(SEL action)
{
_attributes.insert(CKComponentActionAttribute(action));
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies an action that should be sent when the component's view receives a 'touch up inside' event.
@param action An action to send.
@note Setting this property on a view that is not a @c UIControl subclass will trigger a runtime error.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &onTouchUpInside(const CKAction<UIEvent *> &action)
{
_attributes.insert(CKComponentActionAttribute(action));
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies a selector that should be sent up the responder chain when the component's view receives any event that
matches a given event mask.
@param events Events that should trigger the action.
@param action An selector to send.
@note Setting this property on a view that is not a @c UIControl subclass will trigger a runtime error.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &onControlEvents(UIControlEvents events, SEL action)
{
_attributes.insert(CKComponentActionAttribute(action, events));
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies an action that should be sent when the component's view receives any event that matches a given event mask.
@param events Events that should trigger the action.
@param action An action to send.
@note Setting this property on a view that is not a @c UIControl subclass will trigger a runtime error.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &onControlEvents(UIControlEvents events, const CKAction<UIEvent *> &action)
{
_attributes.insert(CKComponentActionAttribute(action, events));
return reinterpret_cast<ImageComponentBuilder<PropsBitmap | ImageComponentPropId::anyAttribute> &>(*this);
}
/**
Specifies a complete attribute map for a view of this component.
@param a The attribute map to set.
@note Calling this method on a builder that does not have a view class set will trigger a compilation error.
@note Calling this method on a builder that already has a complete view configuration set will trigger
a compilation error.
*/
auto &attributes(CKViewComponentAttributeValueMap a)
{
constexpr auto noAttributesSet = !PropBitmap::isSet(PropsBitmap, ImageComponentPropId::anyAttribute);
static_assert(noAttributesSet, "Setting 'attributes' overrides existing attributes.");
_attributes = std::move(a);
return reinterpret_cast<ImageComponentBuilder<PropsBitmap> &>(*this);
}
private:
friend BuilderBase<ImageComponentBuilder, PropsBitmap>;
/**
Creates a new component instance with specified properties.
@note This method must @b not be called more than once on a given component builder instance.
*/
NS_RETURNS_RETAINED auto _build() noexcept -> CKImageComponent *
{
constexpr auto imageIsSet = PropBitmap::isSet(PropsBitmap, ImageComponentPropId::image);
static_assert(imageIsSet, "Required property 'image' is not set.");
return [[CKImageComponent alloc] initWithImage:_image
attributes:std::move(_attributes)
size:this->_size];
}
private:
UIImage *_image;
CKViewComponentAttributeValueMap _attributes{};
};
}
/**
Uses a static layout with the given image size and applies additional attributes.
*/
using ImageComponentBuilder = BuilderDetails::ImageComponentBuilder<>;
}
#endif