ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
View Struct Reference

Views are the fundamental building blocks of ObjectivelyMVC user interfaces. More...

#include <View.h>

Inheritance diagram for View:
Box CollectionItemView Control ImageView Label Option PageView ProgressBar ScrollBar ScrollView SlideShowView StackView TabView TableCellView Text

Public Member Functions

Class * _View (void)
 The View archetype.
 
bool acceptsKeyResponder (const View *self)
 
bool acceptsTouchResponder (const View *self)
 
void addClassName (View *self, const char *className)
 Adds the given class name to this View.
 
void addSubview (View *self, View *subview)
 Adds a subview to this view, to be drawn above its siblings.
 
void addSubviewRelativeTo (View *self, View *subview, View *other, ViewPosition position)
 Adds a subview to this view, positioned relatively to other.
 
 ancestorWithIdentifier (const View *self, const char *identifier)
 
void applyStyle (View *self, const Style *style)
 Applies the given Style to this View.
 
void applyTheme (View *self, const Theme *theme)
 Applies the given Theme to this View.
 
void applyThemeIfNeeded (View *self, const Theme *theme)
 Recursively applies the Theme to this View and its subviews.
 
void attachStylesheet (View *self, SDL_Window *window)
 Attaches this View's Stylesheet to the Theme associated with the given window.
 
void awakeWithCharacters (View *self, const char *chars)
 Wakes this View with the given null-terminated JSON C string.
 
void awakeWithData (View *self, const Data *data)
 Wakes this View with the specified JSON Data.
 
void awakeWithDictionary (View *, const Dictionary *)
 Wakes this View with the specified Dictionary.
 
void awakeWithResource (View *self, const Resource *resource)
 Wakes this View with the specified Resource.
 
void awakeWithResourceName (View *self, const char *name)
 Wakes this View with the Resource by the specified name.
 
void becomeKeyResponder (View *self)
 Become the key responder in the View hierarchy.
 
void becomeTouchResponder (View *self)
 Become the touch responder in the View hierarchy.
 
bool bind (View *self, const Inlet *inlets, const Dictionary *dictionary)
 Performs data binding for the Inlets described in dictionary.
 
SDL_Rect bounds (const View *self)
 
void bringSubviewToFront (View *self, View *subview)
 Brings the specified subview to the front.
 
void clearWarnings (const View *self, WarningType type)
 Clears this View's Warnings matching the given level.
 
SDL_Rect clippingFrame (const View *self)
 
bool containsPoint (const View *self, const SDL_Point *point)
 
int depth (const View *self)
 
 descendantWithIdentifier (const View *self, const char *identifier)
 
void detachStylesheet (View *self, SDL_Window *window)
 Detaches this View's Stylesheet from the Theme associated with the given window.
 
void didMoveToWindow (View *self, SDL_Window *window)
 Informs this View that it has been added to the View hierachy of the given window.
 
bool didReceiveEvent (const View *self, const SDL_Event *event)
 
void draw (View *self, Renderer *renderer)
 Draws this View.
 
void emitViewEvent (View *self, ViewEvent code, ident data)
 Emits a ViewEvent originating from this View.
 
void enumerate (const View *self, ViewEnumerator enumerator, ident data)
 
void enumerate (View *self, ViewEnumerator enumerator, ident data)
 Enumerates this View and its descendants, applying enumerator to each.
 
void enumerateAdjacent (const View *self, ViewEnumerator enumerator, ident data)
 Enumerates adjacent siblings of this View, applying enumerator to each.
 
void enumerateAncestors (const View *self, ViewEnumerator enumerator, ident data)
 Enumerates all ancestors of this View, applying enumerator to each.
 
void enumerateDescendants (const View *self, ViewEnumerator enumerator, ident data)
 Enumerates all descendants of this View, applying enumerator to each.
 
void enumerateSelection (View *self, const char *rule, ViewEnumerator enumerator, ident data)
 Enumerates all Views in the selection matched by rule, applying enumerator to each.
 
void enumerateSiblings (const View *self, ViewEnumerator enumerator, ident data)
 Enumerates all siblings of this View, applying enumerator to each.
 
void enumerateSubviews (const View *self, ViewEnumerator enumerator, ident data)
 Enumerates all subviews of this View, applying enumerator to each.
 
void enumerateSuperview (const View *self, ViewEnumerator enumerator, ident data)
 Enumerates the superview of this View, if any, applying enumerator to it.
 
void enumerateVisible (const View *self, ViewEnumerator enumerator, ident data)
 
void enumerateVisible (View *self, ViewEnumerator enumerator, ident data)
 Enumerates this View and its visible descendants, applying enumerator to each.
 
bool hasClassName (const View *self, cosnt char *className)
 
bool hasOverflow (const View *self)
 
View * hitTest (const View *self, const SDL_Point *point)
 Performs a hit test against this View and its descendants for the given point.
 
View * init (View *self)
 Initializes this View.
 
View * initWithFrame (View *self, const SDL_Rect *frame)
 Initializes this View with the specified frame.
 
void invalidateStyle (View *self)
 Invalidates the computed Style for this View and its descendants.
 
bool isContainer (const View *self)
 
bool isDescendantOfView (const View *self, const View *view)
 
bool isKeyResponder (const View *self)
 
bool isTouchResponder (const View *self)
 
bool isVisible (const View *self)
 
void layoutIfNeeded (View *self)
 Recursively updates the layout of this View and its subviews.
 
 layoutSubviews (View *self)
 Arranges this View's immediate subviews within its (already final) frame.
 
void layoutWithConstraint (View *self, ViewConstraint width, ViewConstraint height)
 Resolves this View's size against the given ViewConstraints, then arranges it.
 
void layoutWithSize (View *self, const SDL_Size *size)
 Resizes this View to the given size, then arranges it.
 
bool matchesSelector (const View *self, const SimpleSelector *simpleSelector)
 
void moveToWindow (View *self, SDL_Window *window)
 Moves this View to the View hierarchy of the given window.
 
String * path (const View *self)
 
void removeAllClassNames (View *self)
 Removes all class names from this View.
 
void removeAllSubviews (View *self)
 Removes all subviews from this View.
 
void removeClassName (View *self, const char *className)
 Removes the given class name to this View.
 
void removeFromSuperview (View *self)
 Removes this View from its superview.
 
void removeSubview (View *self, View *subview)
 Removes the given subview from this View.
 
void render (View *self, Renderer *renderer)
 Renders this View using the given renderer.
 
void renderDeviceDidReset (View *self)
 Informs this View that the render device has reset.
 
void renderDeviceWillReset (View *self)
 Informs this View that the render device will reset.
 
SDL_Rect renderFrame (const View *self)
 
void replaceSubview (View *self, View *subview, View *replacement)
 Replaces the specified subview with the given replacement.
 
void resignKeyResponder (View *self)
 Resigns key responder priority.
 
void resignTouchResponder (View *self)
 Resigns touch responder priority.
 
void resize (View *self, const SDL_Size *size)
 Resizes this View to the specified size.
 
void resolve (View *self, Outlet *outlets)
 Resolves the given Outlets from this View's hierarchy.
 
void respondToEvent (View *self, const SDL_Event *event)
 Responds to the specified event.
 
Set * select (View *self, const char *rule)
 Resolves all descendants (including this View) that match the given Selector rule.
 
View * selectFirst (View *self, const char *rule)
 Resolves the first descendant View that matches the given Selector rule.
 
void setNeedsApplyTheme (View *self)
 Marks this View as needing Theme application before it is next drawn.
 
void setNeedsLayout (View *self)
 Marks this View as needing layout before it is next drawn.
 
void setVisibility (View *self, ViewVisibility visibility)
 Sets this View's visibility.
 
SDL_Size size (const View *self)
 
SDL_Size sizeThastFills (const View *self)
 
SDL_Size sizeThatContains (const View *self)
 
SDL_Size sizeThatFills (const View *self)
 
void sizeThatFits (const View *self)
 
SDL_Size sizeThatSatisfies (View *self, ViewConstraint width, ViewConstraint height)
 Resolves the size this View wants to be, within the offered ViewConstraints.
 
void sizeToContain (View *self)
 Resizes this View to contain its subviews.
 
void sizeToFill (View *self)
 Resizes this View to fill its superview.
 
void sizeToFit (View *self)
 Resizes this View to fit its subviews.
 
void sizeToSatisfy (View *self, ViewConstraint width, ViewConstraint height)
 Resizes this View to satisfy the given ViewConstraints.
 
 subviewWithIdentifier (const View *self, const char *identifier)
 
void updateBindings (View *self, ident data)
 Updates data bindings, prompting the appropriate layout changes.
 
SDL_Rect viewport (const View *self)
 
View * viewWithCharacters (const char *chars, Outlet *outlets)
 Instantiates a View initialized with the given null-terminated JSON C string.
 
View * viewWithData (const Data *data, Outlet *outlets)
 Instantiates a View initialized with the contents of data.
 
View * viewWithDictionary (const Dictionary *dictionary, Outlet *outlets)
 Instantiates a View initialized with the attributes described in dictionary.
 
View * viewWithResource (const Resource *resource, Outlet *outlets)
 Instantiates a View initialized with the JSON data in resource.
 
View * viewWithResourceName (const char *name, Outlet *outlets)
 Instantiates a View initialized with the JSON Resource with the specified name.
 
Array * visibleSubviews (const View *self)
 
void warn (View *self, ViewWarningType type, const char *fmt,...)
 
void warn (View *self, WarningType level, const char *fmt,...)
 Appends a warning for this View.
 
void willMoveToWindow (View *self, SDL_Window *window)
 Informs this View that it will be added to the View hierarchy for the given window.
 

Data Fields

ViewAlignment alignment
 The alignment.
 
int autoresizingMask
 The ViewAutoresizing bitmask.
 
SDL_Color backgroundColor
 The background color.
 
int backgroundGradientAngle
 The angle of the background gradient, in degrees, clockwise from south: 0 (the default) fills downwards, 90 to the right, 180 upwards.
 
SDL_Color backgroundGradientColor
 The far color of the background gradient, which runs from View::backgroundColor.
 
SDL_Color borderColor
 The border color.
 
int borderRadius
 The corner radius applied to the background, border and bevel.
 
int borderWidth
 The border width.
 
Set * classNames
 The class names.
 
bool clipsSubviews
 If true, subviews will be clipped to this View's frame.
 
Style * computedStyle
 The computed Style of this View.
 
ViewCornerCut cornerCut
 The horizontal inset of each corner of the background and border.
 
char * identifier
 An optional identifier.
 
SDL_Size maxSize
 The maximum size this View may be resized to during layout.
 
SDL_Size minSize
 The minimum size this View may be resized to during layout.
 
bool needsApplyTheme
 If true, this View will apply the Theme before it is drawn.
 
bool needsLayout
 If true, this View will layout its subviews before it is drawn.
 
View * nextResponder
 The next responder, or event handler, in the chain.
 
Object object
 The superclass.
 
ViewPadding padding
 The padding.
 
ViewPointerEvents pointerEvents
 Whether this View is the result of a hit test; its subviews always are.
 
bool stretch
 Whether this View takes a share of the space its StackView leaves along its axis.
 
Style * style
 The element-level Style of this View.
 
Stylesheet * stylesheet
 An optional Stylesheet.
 
Array * subviews
 The immediate subviews.
 
View * superview
 The super View.
 
ViewController * viewController
 The ViewController.
 
ViewVisibility visibility
 Whether this View is drawn, and contributes to its superview's size.
 
Array * warnings
 The Warnings this View generated.
 
SDL_Window * window
 The window.
 

Protected Attributes

ViewInterface * interface [0]
 The interface type.
 

Detailed Description

Views are the fundamental building blocks of ObjectivelyMVC user interfaces.

Views provide organization and coordination of layout, drawing and event handling. Views maintain hierarchical relationships among other Views, whereby each View's parent, or superview, dictates where it will be drawn on the screen, which events it will be eligible to receive, etc.

Definition at line 225 of file View.h.

Member Function Documentation

◆ _View()

Class * _View ( void  )

The View archetype.

Returns
The View Class.

Definition at line 2336 of file View.c.

2336 {
2337 static Class *clazz;
2338 static Once once;
2339
2340 do_once(&once, {
2341 clazz = _initialize(&(const ClassDef) {
2342 .name = "View",
2343 .superclass = _Object(),
2344 .instanceSize = sizeof(View),
2345 .interfaceSize = sizeof(ViewInterface),
2346 .initialize = initialize,
2347 });
2348 });
2349
2350 return clazz;
2351}
static void initialize(Class *clazz)
Definition AtlasImage.c:74
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:225

◆ acceptsKeyResponder()

bool acceptsKeyResponder ( const View *  self)
Parameters
selfThe View.
Returns
True if this View can become the key responder, false otherwise.

Definition at line 69 of file Control.c.

69 {
70
71 Control *this = (Control *) self;
72
73 return (this->state & ControlStateDisabled) == 0;
74}
@ ControlStateDisabled
Definition Control.h:70
Controls are Views which capture and respond to events.
Definition Control.h:83

◆ acceptsTouchResponder()

bool acceptsTouchResponder ( const View *  self)
Parameters
selfThe View.
Returns
True if this View can become the touch responder, false otherwise.

Definition at line 79 of file Control.c.

79 {
80
81 Control *this = (Control *) self;
82
83 return (this->state & ControlStateDisabled) == 0;
84}

◆ addClassName()

void addClassName ( View *  self,
const char *  className 
)

Adds the given class name to this View.

Parameters
selfThe View.
classNameThe class name.

Definition at line 183 of file View.c.

183 {
184
185 if (className) {
186
187 String *string = $$(String, stringWithCharacters, className);
188 assert(string);
189
190 $(self->classNames, addObject, string);
191 release(string);
192
193 $(self, invalidateStyle);
194 }
195}
void invalidateStyle(View *self)
Invalidates the computed Style for this View and its descendants.
Definition View.c:1092
Set * classNames
The class names.
Definition View.h:293

◆ addSubview()

void addSubview ( View *  self,
View *  subview 
)

Adds a subview to this view, to be drawn above its siblings.

Parameters
selfThe View.
subviewThe subview to add.
Remarks
This method is equivalent to $(view, addSubviewRelativeTo, subview, NULL, OrderSame).

Definition at line 49 of file PageView.c.

49 {
50
51 super(View, self, addSubview, subview);
52
53 PageView *this = (PageView *) self;
54
56
57 if (this->currentPage == NULL) {
58 $(this, setCurrentPage, subview);
59 }
60}
static void setCurrentPage(PageView *self, View *currentPage)
Definition PageView.c:130
@ ViewVisibilityHidden
Definition View.h:122
PageViews manage their subviews as pages in a book.
Definition PageView.h:60
void setVisibility(View *self, ViewVisibility visibility)
Sets this View's visibility.
Definition View.c:1834
void addSubview(View *self, View *subview)
Adds a subview to this view, to be drawn above its siblings.
Definition PageView.c:49

◆ addSubviewRelativeTo()

void addSubviewRelativeTo ( View *  self,
View *  subview,
View *  other,
ViewPosition  position 
)

Adds a subview to this view, positioned relatively to other.

Parameters
selfThe View.
subviewThe subview to add.
otherAn optional View to position subview relative to.
positionThe relative position.

Definition at line 209 of file View.c.

209 {
210
211 assert(subview);
212 assert(subview != other);
213
214 retain(subview);
215
216 $(subview, removeFromSuperview);
217
218 if (other && other->superview == self) {
219
220 const Array *subviews = (Array *) self->subviews;
221 const ssize_t index = $(subviews, indexOfObject, other);
222
223 if (position == ViewPositionAfter) {
224 if (index == (ssize_t) (subviews->count - 1)) {
225 $(self->subviews, addObject, subview);
226 } else {
227 $(self->subviews, insertObjectAtIndex, subview, index + 1);
228 }
229 } else {
230 $(self->subviews, insertObjectAtIndex, subview, index);
231 }
232 } else {
233 $(self->subviews, addObject, subview);
234 }
235
236 release(subview);
237
238 subview->superview = self;
239
240 $(subview, moveToWindow, self->window);
241
242 $(subview, invalidateStyle);
243
244 $(self, setNeedsLayout);
245}
@ ViewPositionAfter
Definition View.h:212
View * superview
The super View.
Definition View.h:454
Array * subviews
The immediate subviews.
Definition View.h:448
void setNeedsLayout(View *self)
Marks this View as needing layout before it is next drawn.
Definition View.c:1865
SDL_Window * window
The window.
Definition View.h:480
void removeFromSuperview(View *self)
Removes this View from its superview.
Definition View.c:1462
void moveToWindow(View *self, SDL_Window *window)
Moves this View to the View hierarchy of the given window.
Definition View.c:1351

◆ ancestorWithIdentifier()

ancestorWithIdentifier ( const View *  self,
const char *  identifier 
)
Parameters
selfThe View.
identifierThe identifier.
Returns
The nearest ancestor View matching the given identifier.

Definition at line 251 of file View.c.

251 {
252
253 assert(identifier);
254
255 View *view = (View *) self;
256 while (view) {
257 if (view->identifier) {
258 if (strcmp(identifier, view->identifier) == 0) {
259 return view;
260 }
261 }
262 view = view->superview;
263 }
264
265 return NULL;
266}
char * identifier
An optional identifier.
Definition View.h:333

◆ applyStyle()

void applyStyle ( View *  self,
const Style *  style 
)

Applies the given Style to this View.

Parameters
selfThe View.
styleThe Style.

Definition at line 59 of file CollectionView.c.

59 {
60
61 super(View, self, applyStyle, style);
62
63 CollectionView *this = (CollectionView *) self;
64
65 const Inlet inlets[] = MakeInlets(
66 MakeInlet("axis", InletTypeEnum, &this->axis, (ident) CollectionViewAxisNames),
67 MakeInlet("item-size", InletTypeSize, &this->itemSize, NULL),
68 MakeInlet("item-spacing", InletTypeSize, &this->itemSpacing, NULL)
69 );
70
71 $(self, bind, inlets, (Dictionary *) style->attributes);
72}
const EnumName CollectionViewAxisNames[]
@ InletTypeEnum
Definition View+JSON.h:75
@ InletTypeSize
Definition View+JSON.h:104
#define MakeInlets(...)
Creates a null-termianted array of Inlets.
Definition View+JSON.h:215
#define MakeInlet(name, type, dest, data)
Creates an Inlet with the specified parameters.
Definition View+JSON.h:210
CollectionViews display items in a grid.
Inlets enable inbound data binding of View attributes through JSON.
Definition View+JSON.h:149
Dictionary * attributes
Definition Style.h:59
Style * style
The element-level Style of this View.
Definition View.h:425
void applyStyle(View *self, const Style *style)
Applies the given Style to this View.
bool bind(View *self, const Inlet *inlets, const Dictionary *dictionary)
Performs data binding for the Inlets described in dictionary.

◆ applyTheme()

void applyTheme ( View *  self,
const Theme *  theme 
)

Applies the given Theme to this View.

Parameters
selfThe View.
themeThe Theme.

Definition at line 335 of file View.c.

335 {
336
337 assert(theme);
338
340 assert(computedStyle);
341
342 if (self->needsApplyStyle || !$(self->computedStyle, isComputedEqual, computedStyle)) {
343
344 release(self->computedStyle);
345 self->computedStyle = retain(computedStyle);
346
348 $(self, applyStyle, self->computedStyle);
349
350 self->needsApplyStyle = false;
351 }
352
353 release(computedStyle);
354}
static bool isComputedEqual(const Style *self, const Style *other)
Definition Style.c:433
static void addAttributes(Style *self, const Dictionary *attributes)
Definition Style.c:221
static Theme * theme(SDL_Window *window)
Definition Theme.c:295
static Style * computeStyle(const Theme *self, const View *view)
Definition Theme.c:223
The Style type.
Definition Style.h:43
Style * computedStyle
The computed Style of this View.
Definition View.h:314

◆ applyThemeIfNeeded()

void applyThemeIfNeeded ( View *  self,
const Theme *  theme 
)

Recursively applies the Theme to this View and its subviews.

Parameters
selfThe View.
themeThe Theme.

Definition at line 369 of file View.c.

369 {
370
371 assert(theme);
372
373 if (!self->needsApplyTheme && !self->needsApplyThemeSubviews) {
374 return;
375 }
376
377 // Cleared before descending so that any re-invalidation during the traversal
378 // propagates fresh subtree flags and survives to the next frame.
379 self->needsApplyThemeSubviews = false;
380
382
383 if (self->needsApplyTheme) {
384
386
387 $(self, applyTheme, theme);
388
389 self->needsApplyTheme = false;
390 }
391}
static void _applyThemeIfNeeded(View *view, ident data)
ViewEnumerator adapter for applyThemeIfNeeded.
Definition View.c:365
@ WarningTypeStyle
Definition Warning.h:34
bool needsApplyTheme
If true, this View will apply the Theme before it is drawn.
Definition View.h:353
void clearWarnings(const View *self, WarningType type)
Clears this View's Warnings matching the given level.
Definition View.c:598
void applyTheme(View *self, const Theme *theme)
Applies the given Theme to this View.
Definition View.c:335
void enumerateSubviews(const View *self, ViewEnumerator enumerator, ident data)
Enumerates all subviews of this View, applying enumerator to each.
Definition View.c:904

◆ attachStylesheet()

void attachStylesheet ( View *  self,
SDL_Window *  window 
)

Attaches this View's Stylesheet to the Theme associated with the given window.

Parameters
selfThe View.
windowThe window.

Definition at line 397 of file View.c.

397 {
398
399 assert(window);
400
401 if (self->stylesheet) {
402 Theme *theme = $$(Theme, theme, window);
403 if (theme) {
404 $(theme, addStylesheet, self->stylesheet);
405 }
406 }
407}
static void addStylesheet(Theme *self, Stylesheet *stylesheet)
Definition Theme.c:59
The Theme type.
Definition Theme.h:54
Stylesheet * stylesheet
An optional Stylesheet.
Definition View.h:443

◆ awakeWithCharacters()

void awakeWithCharacters ( View *  self,
const char *  chars 
)

Wakes this View with the given null-terminated JSON C string.

Parameters
selfThe View.
charsA null-terminated JSON C string describing this View.
Remarks
This is a convenience method for View::awakeWithDictionary.

Definition at line 413 of file View.c.

413 {
414
415 Data *data = $$(Data, dataWithConstMemory, (uint8_t *) chars, strlen(chars));
416
417 $(self, awakeWithData, data);
418
419 release(data);
420}
void awakeWithData(View *self, const Data *data)
Wakes this View with the specified JSON Data.
Definition View.c:426

◆ awakeWithData()

void awakeWithData ( View *  self,
const Data *  data 
)

Wakes this View with the specified JSON Data.

Parameters
selfThe View.
dataThe JSON Data containing properties describing this View.
Remarks
This is a convenience method for View::awakeWithDictionary.

Definition at line 426 of file View.c.

426 {
427
428 JSONContext *ctx = $(alloc(JSONContext), init);
429 Dictionary *dictionary = $(ctx, objectFromData, data, 0);
430
431 if (dictionary) {
432 $(self, awakeWithDictionary, dictionary);
433 release(dictionary);
434 } else {
435 MVC_LogError("Failed to parse JSON for %s\n", classnameof(self));
436 }
437
438 release(ctx);
439}
#define MVC_LogError(fmt,...)
Definition Log.h:57
void awakeWithDictionary(View *, const Dictionary *)
Wakes this View with the specified Dictionary.
Definition Box.c:50
View * init(View *self)
Initializes this View.
Definition Box.c:67

◆ awakeWithDictionary()

void awakeWithDictionary ( View *  self,
const Dictionary *  dictionary 
)

Wakes this View with the specified Dictionary.

Parameters
selfThe View.
dictionaryA Dictionary of properties describing this View.
Remarks
This method is invoked when loading via JSON. Subclasses should override this method to perform any customization based on the contents of dictionary.

Definition at line 50 of file Box.c.

50 {
51
52 super(View, self, awakeWithDictionary, dictionary);
53
54 Box *this = (Box *) self;
55
56 const Inlet inlets[] = MakeInlets(
57 MakeInlet("contentView", InletTypeView, &this->contentView, NULL),
58 MakeInlet("label", InletTypeView, &this->label, NULL)
59 );
60
61 $(self, bind, inlets, dictionary);
62}
@ InletTypeView
Definition View+JSON.h:133
A container View with a positioned Label.
Definition Box.h:44

◆ awakeWithResource()

void awakeWithResource ( View *  self,
const Resource *  resource 
)

Wakes this View with the specified Resource.

Parameters
selfThe View.
resourceA Resource providing JSON data describing this View.

Definition at line 463 of file View.c.

463 {
464
465 assert(resource);
466
467 $(self, awakeWithData, resource->data);
468}

◆ awakeWithResourceName()

void awakeWithResourceName ( View *  self,
const char *  name 
)

Wakes this View with the Resource by the specified name.

Parameters
selfThe View.
nameThe name of a Resource providing JSON data describing this View.

Definition at line 474 of file View.c.

474 {
475
476 Resource *resource = $$(Resource, resourceWithName, name);
477
478 $(self, awakeWithResource, resource);
479
480 release(resource);
481}
static String * name(const Font *self)
Definition Font.c:303
void awakeWithResource(View *self, const Resource *resource)
Wakes this View with the specified Resource.
Definition View.c:463

◆ becomeKeyResponder()

void becomeKeyResponder ( View *  self)

Become the key responder in the View hierarchy.

Parameters
selfThe View.
Remarks
Becoming the key responder gives a View priority when handling key events.

Definition at line 132 of file Control.c.

132 {
133
134 Control *this = (Control *) self;
135
136 if (!$(this, isFocused)) {
137
138 this->state |= ControlStateFocused;
139
140 $(this, stateDidChange);
141 }
142
143 super(View, self, becomeKeyResponder);
144}
static void stateDidChange(Control *self)
Definition Control.c:366
static bool isFocused(const Control *self)
Definition Control.c:342
@ ControlStateFocused
Definition Control.h:69
void becomeKeyResponder(View *self)
Become the key responder in the View hierarchy.
Definition Control.c:132

◆ becomeTouchResponder()

void becomeTouchResponder ( View *  self)

Become the touch responder in the View hierarchy.

Parameters
selfThe View.
Remarks
Becoming the touch responder gives a View priority when handling touch events.

Definition at line 511 of file View.c.

511 {
512
513 assert(self->window);
514
515 if (!$(self, isTouchResponder)) {
516 SDL_PropertiesID props = SDL_GetWindowProperties(self->window);
517
518 View *touchResponder = SDL_GetPointerProperty(props, "touchResponder", NULL);
519 if (touchResponder) {
521 }
522
523 String *path = $(self, path);
524 MVC_LogDebug("%s\n", path->chars);
525 release(path);
526
527 SDL_SetPointerProperty(props, "touchResponder", self);
528 }
529}
#define MVC_LogDebug(fmt,...)
Definition Log.h:48
static View * touchResponder(const WindowController *self)
String * path(const View *self)
Definition View.c:1378
void resignTouchResponder(View *self)
Resigns touch responder priority.
Definition View.c:1692
bool isTouchResponder(const View *self)
Definition View.c:1139

◆ bind()

bool bind ( View *  self,
const Inlet *  inlets,
const Dictionary *  dictionary 
)

Performs data binding for the Inlets described in dictionary.

Parameters
selfThe View.
inletsThe Inlets to bind.
dictionaryA Dictionary describing this View.
Returns
True if one or more Inlet was bound, false otherwise.
Remarks
Subclasses will typically call this method from View::awakeWithDictionary.

◆ bounds()

SDL_Rect bounds ( const View *  self)
Parameters
selfThe View.
Returns
The bounds (frame minus padding) of this View.

Definition at line 552 of file View.c.

552 {
553
554 const SDL_Size size = $(self, size);
555
556 const SDL_Rect bounds = {
557 .x = self->padding.left,
558 .y = self->padding.top,
559 .w = max(0, size.w - (self->padding.left + self->padding.right)),
560 .h = max(0, size.h - (self->padding.top + self->padding.bottom)),
561 };
562
563 return bounds;
564}
SDL_Rect bounds(const View *self)
Definition View.c:552
SDL_Size size(const View *self)
Definition View.c:1878
ViewPadding padding
The padding.
Definition View.h:398
int top
Definition View.h:170
int bottom
Definition View.h:170
int right
Definition View.h:170
int left
Definition View.h:170

◆ bringSubviewToFront()

void bringSubviewToFront ( View *  self,
View *  subview 
)

Brings the specified subview to the front.

Parameters
selfThe View.
subviewThe subview.

Definition at line 570 of file View.c.

570 {
571
572 assert(subview);
573
574 if (subview->superview == self) {
575
576 View *last = $((Array *) self->subviews, lastObject);
577 if (last != subview) {
578 $(self, addSubviewRelativeTo, subview, last, ViewPositionAfter);
579 }
580 }
581}
void addSubviewRelativeTo(View *self, View *subview, View *other, ViewPosition position)
Adds a subview to this view, positioned relatively to other.
Definition View.c:209

◆ clearWarnings()

void clearWarnings ( const View *  self,
WarningType  level 
)

Clears this View's Warnings matching the given level.

Parameters
selfThe View.
typeThe bitmask of WarningTypes to clear.

Definition at line 598 of file View.c.

598 {
599 $(self->warnings, filter, clearWarnings_predicate, &type);
600}
static bool clearWarnings_predicate(const ident obj, ident data)
Filter Predicate for clearWarnings.
Definition View.c:586
Array * warnings
The Warnings this View generated.
Definition View.h:474

◆ clippingFrame()

SDL_Rect clippingFrame ( const View *  self)
Parameters
selfThe View.
Returns
The visible portion of this View's frame, in window coordinates.
Remarks
This is equivalent to the View's renderFrame, expanded for border width, and clipped to all ancestors.

Definition at line 606 of file View.c.

606 {
607
608 View *this = (View *) self;
609
610 if (_renderFrameGeneration && this->clippingFrameCache.generation == _renderFrameGeneration) {
611 return this->clippingFrameCache.frame;
612 }
613
614 SDL_Rect frame = $(self, renderFrame);
615
616 if (self->borderWidth && self->borderColor.a) {
617 frame.x -= self->borderWidth;
618 frame.y -= self->borderWidth;
619 frame.w += self->borderWidth * 2;
620 frame.h += self->borderWidth * 2;
621 }
622
623 // The nearest clipping ancestor's clippingFrame already folds in every outer clip, so a
624 // single intersection with it is equivalent to intersecting each clipping ancestor in turn.
625 const View *superview = self->superview;
626 while (superview && !superview->clipsSubviews) {
628 }
629
630 if (superview) {
631 const SDL_Rect clippingFrame = $(superview, clippingFrame);
632 if (SDL_GetRectIntersection(&clippingFrame, &frame, &frame) == false) {
633 frame.w = frame.h = 0;
634 }
635 }
636
637 this->clippingFrameCache.frame = frame;
638 this->clippingFrameCache.generation = _renderFrameGeneration;
639
640 return frame;
641}
static unsigned _renderFrameGeneration
The render frame generation; per-View renderFrame and clippingFrame caches are valid only while their...
Definition View.c:44
bool clipsSubviews
If true, subviews will be clipped to this View's frame.
Definition View.h:309
SDL_Rect clippingFrame(const View *self)
Definition View.c:606
SDL_Color borderColor
The border color.
Definition View.h:275
int borderWidth
The border width.
Definition View.h:287
SDL_Rect renderFrame(const View *self)
Definition View.c:1629
SDL_Rect frame
The frame, relative to the superview.
Definition View.h:301

◆ containsPoint()

bool containsPoint ( const View *  self,
const SDL_Point *  point 
)
Parameters
selfThe View.
pointA point in object space.
Returns
True if the point falls within this View's clipped frame.

Definition at line 647 of file View.c.

647 {
648
649 const SDL_Rect frame = $(self, clippingFrame);
650
651 return (bool) SDL_PointInRect(point, &frame);
652}

◆ depth()

int depth ( const View *  self)
Parameters
selfThe View.
Returns
The depth of this View (ancestor depth + 1).

Definition at line 658 of file View.c.

658 {
659 return (self->superview ? $(self->superview, depth) + 1 : 0);
660}
int depth(const View *self)
Definition View.c:658

◆ descendantWithIdentifier()

descendantWithIdentifier ( const View *  self,
const char *  identifier 
)
Parameters
selfThe View.
identifierThe identifier.
Returns
The nearest descendant View matching the given identifier.

Definition at line 666 of file View.c.

666 {
667
668 assert(identifier);
669
670 if (self->identifier) {
671 if (strcmp(identifier, self->identifier) == 0) {
672 return (View *) self;
673 }
674 }
675
676 const Array *subviews = (Array *) self->subviews;
677 for (size_t i = 0; i < subviews->count; i++) {
678
679 const View *subview = subviews->elements[i];
680 View *descendant = $(subview, descendantWithIdentifier, identifier);
681 if (descendant) {
682 return descendant;
683 }
684 }
685
686 return NULL;
687}
descendantWithIdentifier(const View *self, const char *identifier)
Definition View.c:666

◆ detachStylesheet()

void detachStylesheet ( View *  self,
SDL_Window *  window 
)

Detaches this View's Stylesheet from the Theme associated with the given window.

Parameters
selfThe View.
windowThe window.

Definition at line 693 of file View.c.

693 {
694
695 assert(window);
696
697 if (self->stylesheet) {
698 Theme *theme = $$(Theme, theme, window);
699 if (theme) {
701 }
702 }
703}
static void removeStylesheet(Theme *self, Stylesheet *stylesheet)
Definition Theme.c:261

◆ didMoveToWindow()

void didMoveToWindow ( View *  self,
SDL_Window *  window 
)

Informs this View that it has been added to the View hierachy of the given window.

Parameters
selfThe View.
windowThe window, or NULL if this View has been removed from the window.

Definition at line 90 of file ImageView.c.

90 {
91
92 super(View, self, didMoveToWindow, window);
93
94 ImageView *this = (ImageView *) self;
95
96 // leaving a window resolves nothing: there is no density to resolve against, and View::dealloc
97 // moves to a NULL window, where loading an image would be worse than pointless
98 if (window == NULL) {
99 return;
100 }
101
102 if (this->imageName == NULL) {
103 return;
104 }
105
106 char *name = this->imageName;
107 this->imageName = NULL;
108
109 Theme *theme = $$(Theme, theme, window);
110 if (theme) {
111 Image *image = $(theme, image, name, SDL_GetWindowPixelDensity(window));
112 $(this, setImage, image);
113 } else {
114 Image *image = $$(Image, imageWithResourceName, name, SDL_GetWindowPixelDensity(window));
115 $(this, setImage, image);
116 release(image);
117 }
118
119 this->imageName = name;
120}
static Image * imageWithResourceName(const char *name, float pixelDensity)
Definition Image.c:74
static void setImage(ImageView *self, Image *image)
Definition ImageView.c:237
static Image * image(Theme *self, const char *name, float pixelDensity)
Definition Theme.c:82
Image loading.
Definition Image.h:41
ImageViews render an Image in the context of a View hierarchy.
Definition ImageView.h:45
void didMoveToWindow(View *self, SDL_Window *window)
Informs this View that it has been added to the View hierachy of the given window.
Definition ImageView.c:90

◆ didReceiveEvent()

bool didReceiveEvent ( const View *  self,
const SDL_Event *  event 
)
Parameters
selfThe View.
eventThe event.
Returns
True if this View received the event, false otherwise.

Definition at line 726 of file View.c.

726 {
727
728 if ($(self, isKeyResponder)) {
729 switch (event->type) {
730 case SDL_EVENT_KEY_DOWN:
731 case SDL_EVENT_KEY_UP:
732 case SDL_EVENT_TEXT_INPUT:
733 return true;
734 }
735 }
736
737 if ($(self, isVisible)) {
738
739 SDL_Point point;
740
741 switch (event->type) {
742 case SDL_EVENT_MOUSE_BUTTON_DOWN:
743 case SDL_EVENT_MOUSE_BUTTON_UP:
744 point = MakePoint(event->button.x, event->button.y);
745 break;
746 case SDL_EVENT_MOUSE_MOTION:
747 point = MakePoint(event->motion.x, event->motion.y);
748 break;
749 case SDL_EVENT_MOUSE_WHEEL: {
750 float mx, my;
751 SDL_GetMouseState(&mx, &my);
752 point = MakePoint(mx, my);
753 break;
754 }
755 default:
756 return false;
757 }
758
759 return $(self, containsPoint, &point);
760 }
761
762 return false;
763}
bool isKeyResponder(const View *self)
Definition View.c:1126
bool containsPoint(const View *self, const SDL_Point *point)
Definition View.c:647
bool isVisible(const View *self)
Definition View.c:1152

◆ draw()

void draw ( View *  self,
Renderer *  renderer 
)

Draws this View.

Parameters
selfThe View.
rendererThe Renderer.
Remarks
This method determines if the View is visible and dispatches Renderer::drawView before recursing down the View hierarchy. Rasterization is performed in View::render.
See also
View::render(View *, Renderer *)

Definition at line 778 of file View.c.

778 {
779
780 assert(self->window);
781
782 if (self->visibility != ViewVisibilityHidden) {
783
784 $(renderer, drawView, self);
785
786 $(self, enumerateSubviews, _draw, renderer);
787 }
788}
static void drawView(Renderer *self, View *view)
Definition Renderer.c:525
static void _draw(View *view, ident data)
ViewEnumerator adapter for draw.
Definition View.c:774
ViewVisibility visibility
Whether this View is drawn, and contributes to its superview's size.
Definition View.h:468

◆ emitViewEvent()

void emitViewEvent ( View *  self,
ViewEvent  code,
ident  data 
)

Emits a ViewEvent originating from this View.

Parameters
selfThe View.
codeThe ViewEvent code.
dataThe ViewEvent data.
Remarks
This method is used for emitting events from Views (as opposed to responding to user or system generated events). These events are propagated up the View hierarchy.

Definition at line 794 of file View.c.

794 {
795 SDL_PushEvent((SDL_Event *) &(const SDL_UserEvent) {
796 .type = MVC_VIEW_EVENT,
797 .code = code,
798 .data1 = self,
799 .data2 = data
800 });
801}
OBJECTIVELYMVC_EXPORT Uint32 MVC_VIEW_EVENT
The custom SDL_event type for View event relaying.
Definition Types.h:133

◆ enumerate() [1/2]

void enumerate ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

◆ enumerate() [2/2]

void enumerate ( View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates this View and its descendants, applying enumerator to each.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 807 of file View.c.

807 {
808
809 assert(enumerator);
810
811 enumerator(self, data);
812
813 $(self, enumerateDescendants, enumerator, data);
814}
void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
Enumerates all descendants of this View, applying enumerator to each.
Definition View.c:866

◆ enumerateAdjacent()

void enumerateAdjacent ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates adjacent siblings of this View, applying enumerator to each.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 820 of file View.c.

820 {
821
822 assert(enumerator);
823
824 if (self->superview) {
825 const Array *siblings = (Array *) self->superview->subviews;
826 const ssize_t index = $(siblings, indexOfObject, (const ident) self);
827 if (index > 0) {
828 enumerator($(siblings, objectAtIndex, index - 1), data);
829 }
830 if (index < (ssize_t) (siblings->count - 1)) {
831 enumerator($(siblings, objectAtIndex, index + 1), data);
832 }
833 }
834}

◆ enumerateAncestors()

void enumerateAncestors ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates all ancestors of this View, applying enumerator to each.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 840 of file View.c.

840 {
841
842 assert(enumerator);
843
844 for (View *view = self->superview; view; view = view->superview) {
845 enumerator(view, data);
846 }
847}

◆ enumerateDescendants()

void enumerateDescendants ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates all descendants of this View, applying enumerator to each.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 866 of file View.c.

866 {
867
868 assert(enumerator);
869
870 const Array *subviews = (Array *) self->subviews;
871 for (size_t i = 0; i < subviews->count; i++) {
872
873 View *subview = subviews->elements[i];
874 enumerator(subview, data);
875
876 $(subview, enumerateDescendants, enumerator, data);
877 }
878}

◆ enumerateSelection()

void enumerateSelection ( View *  self,
const char *  rule,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates all Views in the selection matched by rule, applying enumerator to each.

Parameters
selfThe View.
ruleThe Selector rule.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 853 of file View.c.

853 {
854
855 Selector *selector = $(alloc(Selector), initWithRule, rule);
856 assert(selector);
857
858 $(selector, enumerateSelection, self, enumerator, data);
859 release(selector);
860}
static Selector * initWithRule(Selector *self, const char *rule)
Definition Selector.c:190
Selectors are comprised of one or more SelectorSequences.
Definition Selector.h:49
void enumerateSelection(View *self, const char *rule, ViewEnumerator enumerator, ident data)
Enumerates all Views in the selection matched by rule, applying enumerator to each.
Definition View.c:853

◆ enumerateSiblings()

void enumerateSiblings ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates all siblings of this View, applying enumerator to each.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 884 of file View.c.

884 {
885
886 assert(enumerator);
887
888 if (self->superview) {
889
890 const Array *siblings = (Array *) self->superview->subviews;
891 for (size_t i = 0; i < siblings->count; i++) {
892 View *sibling = siblings->elements[i];
893 if (sibling != self) {
894 enumerator(sibling, data);
895 }
896 }
897 }
898}

◆ enumerateSubviews()

void enumerateSubviews ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates all subviews of this View, applying enumerator to each.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 904 of file View.c.

904 {
905
906 assert(enumerator);
907
908 const Array *subviews = (Array *) self->subviews;
909 for (size_t i = 0; i < subviews->count; i++) {
910 enumerator((View *) subviews->elements[i], data);
911 }
912}

◆ enumerateSuperview()

void enumerateSuperview ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates the superview of this View, if any, applying enumerator to it.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 918 of file View.c.

918 {
919
920 assert(enumerator);
921
922 if (self->superview) {
923 enumerator(self->superview, data);
924 }
925}

◆ enumerateVisible() [1/2]

void enumerateVisible ( const View *  self,
ViewEnumerator  enumerator,
ident  data 
)

◆ enumerateVisible() [2/2]

void enumerateVisible ( View *  self,
ViewEnumerator  enumerator,
ident  data 
)

Enumerates this View and its visible descendants, applying enumerator to each.

This is an optimized path for enumerating only visible subtrees.

Parameters
selfThe View.
enumeratorThe ViewEnumerator.
dataUser data.

Definition at line 931 of file View.c.

931 {
932
933 if ($(self, isVisible) == false) {
934 return;
935 }
936
937 enumerator(self, data);
938
939 const Array *subviews = (Array *) self->subviews;
940 for (size_t i = 0; i < subviews->count; i++) {
941
942 View *subview = subviews->elements[i];
943 $(subview, enumerateVisible, enumerator, data);
944 }
945}
void enumerateVisible(const View *self, ViewEnumerator enumerator, ident data)

◆ hasClassName()

bool hasClassName ( const View *  self,
cosnt char *  className 
)
Parameters
selfThe View
classNameThe class name.
Returns
True if this View has the given class name, false otherwise.

◆ hasOverflow()

bool hasOverflow ( const View *  self)
Parameters
selfThe View
Returns
True if this View's visible subviews exceed this View's bounds.

Definition at line 997 of file View.c.

997 {
998
999 Overflow overflow = {
1000 .bounds = $(self, bounds)
1001 };
1002
1003 $(self, enumerateSubviews, hasOverflow_enumerate, (ident) &overflow);
1004
1005 return overflow.hasOverflow;
1006}
static void hasOverflow_enumerate(View *view, ident data)
ViewEnumerator for hasOverflow.
Definition View.c:975
SDL_Rect bounds
Definition View.c:968
bool hasOverflow
Definition View.c:969

◆ hitTest()

View * hitTest ( const View *  self,
const SDL_Point *  point 
)

Performs a hit test against this View and its descendants for the given point.

Parameters
selfThe View.
pointThe point to test.
Returns
The furthest descendant View that contains the given point, or NULL.
Remarks
Hidden Views and Views with pointerEvents disabled are never returned, though the subviews of the latter are still tested.

Definition at line 1012 of file View.c.

1012 {
1013
1014 if (self->visibility != ViewVisibilityHidden) {
1015
1016 if ($(self, containsPoint, point)) {
1017
1018 const Array *subviews = (Array *) self->subviews;
1019 for (size_t i = subviews->count; i; i--) {
1020
1021 const View *subview = subviews->elements[i - 1];
1022 const View *view = $(subview, hitTest, point);
1023 if (view) {
1024 return (View *) view;
1025 }
1026 }
1027
1028 return self->pointerEvents == ViewPointerEventsAuto ? (View *) self : NULL;
1029 }
1030 }
1031
1032 return NULL;
1033}
@ ViewPointerEventsAuto
Definition View.h:110
View * hitTest(const View *self, const SDL_Point *point)
Performs a hit test against this View and its descendants for the given point.
Definition View.c:1012
ViewPointerEvents pointerEvents
Whether this View is the result of a hit test; its subviews always are.
Definition View.h:408

◆ init()

View * init ( View *  self)

Initializes this View.

Parameters
selfThe View.
Returns
The initialized View, or NULL on error.
Remarks
View::viewWithDictionary invokes this initializer when loading Views. Subclasses wishing to support JSON binding must override this method to call their designated initializer.

Definition at line 67 of file Box.c.

67 {
68 return (View *) $((Box *) self, initWithFrame, NULL);
69}
View * initWithFrame(View *self, const SDL_Rect *frame)
Initializes this View with the specified frame.
Definition View.c:1047

◆ initWithFrame()

View * initWithFrame ( View *  self,
const SDL_Rect *  frame 
)

Initializes this View with the specified frame.

Parameters
selfThe View.
frameThe frame.
Returns
The initialized View, or NULL on error.
Remarks
Designated initializer.

Definition at line 1047 of file View.c.

1047 {
1048
1049 self = (View *) super(Object, self, init);
1050 if (self) {
1051
1052 if (frame) {
1053 self->frame = *frame;
1054 }
1055
1056 self->classNames = $$(Set, setWithCapacity, 0);
1057 assert(self->classNames);
1058
1059 self->computedStyle = $(alloc(Style), initWithAttributes, NULL);
1060 assert(self->computedStyle);
1061
1062 self->subviews = $$(Array, arrayWithCapacity, 0);
1063 assert(self->subviews);
1064
1065 self->style = $(alloc(Style), initWithAttributes, NULL);
1066 assert(self->style);
1067
1068 self->warnings = $$(Array, arrayWithCapacity, 0);
1069 assert(self->warnings);
1070
1071 self->needsApplyTheme = true;
1072 self->needsLayout = true;
1073 }
1074
1075 return self;
1076}
static Style * initWithAttributes(Style *self, const Dictionary *attributes)
Definition Style.c:394
bool needsLayout
If true, this View will layout its subviews before it is drawn.
Definition View.h:377

◆ invalidateStyle()

void invalidateStyle ( View *  self)

Invalidates the computed Style for this View and its descendants.

Parameters
selfThe View.

Definition at line 1092 of file View.c.

1092 {
1093 $(self, enumerate, invalidateStyle_enumerate, NULL);
1094}
static void invalidateStyle_enumerate(View *view, ident data)
ViewEnumerator for invalidateStyle.
Definition View.c:1081
void enumerate(const View *self, ViewEnumerator enumerator, ident data)

◆ isContainer()

bool isContainer ( const View *  self)
Parameters
selfThe view.
Returns
True if this View's autoresizing mask includes Fit or Contain.

Definition at line 1100 of file View.c.

1100 {
1102}
@ ViewAutoresizingContain
Definition View.h:95
@ ViewAutoresizingFit
Definition View.h:94
int autoresizingMask
The ViewAutoresizing bitmask.
Definition View.h:248

◆ isDescendantOfView()

bool isDescendantOfView ( const View *  self,
const View *  view 
)
Parameters
selfThe View.
viewThe View to test against this View's hierarchy.
Returns
True if this View is a descendant of, or equal to, the given View.

Definition at line 1108 of file View.c.

1108 {
1109
1110 assert(view);
1111
1112 while (self) {
1113 if (self == view) {
1114 return true;
1115 }
1116 self = self->superview;
1117 }
1118
1119 return false;
1120}

◆ isKeyResponder()

bool isKeyResponder ( const View *  self)
Parameters
selfThe View.
Returns
True if this View is the first responder, false otherwise.

Definition at line 1126 of file View.c.

1126 {
1127
1128 if (self->window) {
1129 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->window), "keyResponder", NULL) == self;
1130 } else {
1131 return false;
1132 }
1133}

◆ isTouchResponder()

bool isTouchResponder ( const View *  self)
Parameters
selfThe View.
Returns
True if this View is responding to mouse and touch events, false otherwise.

Definition at line 1139 of file View.c.

1139 {
1140
1141 if (self->window) {
1142 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->window), "touchResponder", NULL) == self;
1143 } else {
1144 return false;
1145 }
1146}

◆ isVisible()

bool isVisible ( const View *  self)
Parameters
selfThe View.
Returns
True if this View is visible, false if it, or an ancestor, is hidden.

Definition at line 1152 of file View.c.

1152 {
1153
1154 for (const View *view = self; view; view = view->superview) {
1155 if (view->visibility == ViewVisibilityHidden) {
1156 return false;
1157 }
1158 }
1159
1160 return true;
1161}

◆ layoutIfNeeded()

void layoutIfNeeded ( View *  self)

Recursively updates the layout of this View and its subviews.

Parameters
selfThe View.
Remarks
Drives the two-phase layout pass for a dirty View: View::sizeThatSatisfies resolves this View's own size (bottom-up, from its subviews), if it is a container, before View::layoutSubviews arranges its subviews (top-down) using that now-final frame. This ordering guarantees every View's size is settled before any View's position is committed.

Definition at line 1174 of file View.c.

1174 {
1175
1176 if (!self->needsLayout && !self->needsLayoutSubviews) {
1177 return;
1178 }
1179
1180 // Cleared before laying out so that any re-invalidation during layout (e.g. a resize
1181 // propagating setNeedsLayout, or a widget marking a sibling) survives to the next frame.
1182 self->needsLayoutSubviews = false;
1183
1184 // Subviews first, so that a dirty descendant whose layout resizes it marks its ancestors
1185 // before their own dirty checks below run; the whole tree then converges bottom-up in a
1186 // single pass, exactly as invalidations propagate.
1188
1189 if (self->needsLayout) {
1190
1191 // No ancestor is actively arranging self right now, so there's no fresh constraint to
1192 // consult; treat an existing frame as authoritative per-axis (Equal, not Max -- see
1193 // ViewConstraintMax), leaving an axis with no frame yet Unspecified.
1194 const ViewConstraint w = self->frame.w ?
1195 MakeConstraint(ViewConstraintEqual, self->frame.w) : MakeConstraint(ViewConstraintUnspecified, 0);
1196 const ViewConstraint h = self->frame.h ?
1197 MakeConstraint(ViewConstraintEqual, self->frame.h) : MakeConstraint(ViewConstraintUnspecified, 0);
1198
1199 $(self, layoutWithConstraint, w, h);
1200 }
1201}
static void layoutIfNeeded_enumerate(View *subview, ident data)
ViewEnumerator for layoutIfNeeded recursion.
Definition View.c:1166
#define MakeConstraint(mode, value)
Definition View.h:163
A constraint offered by an ancestor View to a descendant during View::sizeThatSatisfies.
Definition View.h:131
void layoutWithConstraint(View *self, ViewConstraint width, ViewConstraint height)
Resolves this View's size against the given ViewConstraints, then arranges it.
Definition View.c:1254

◆ layoutSubviews()

layoutSubviews ( View *  self)

Arranges this View's immediate subviews within its (already final) frame.

Parameters
selfThe View.
Remarks
Subclasses may override this method to perform their own arrangement of subviews. This method is called by View::layoutIfNeeded only after a View::sizeThatSatisfies pass has already resolved self->frame; it must not perform any sizing of its own, only positioning and committing of subview frames.

Definition at line 74 of file Box.c.

74 {
75
76 super(View, self, layoutSubviews);
77
78 View *label = (View *) ((Box *) self)->label;
79 if (label->visibility != ViewVisibilityHidden) {
80
81 const SDL_Size size = $(label, sizeThatContains);
82 label->frame.y = -size.h * 0.5;
83 }
84}
layoutSubviews(View *self)
Arranges this View's immediate subviews within its (already final) frame.
Definition Box.c:74
SDL_Size sizeThatContains(const View *self)
Definition View.c:1886

◆ layoutWithConstraint()

void layoutWithConstraint ( View *  self,
ViewConstraint  width,
ViewConstraint  height 
)

Resolves this View's size against the given ViewConstraints, then arranges it.

Parameters
selfThe View.
widthThe ViewConstraint offered for this View's width.
heightThe ViewConstraint offered for this View's height.
Remarks
This is the shared tail of View::layoutIfNeeded: resolve self's size via View::sizeToSatisfy, then View::layoutSubviews, then clear needsLayout.
See also
View::layoutWithSize(View *, const SDL_Size *)

Definition at line 1254 of file View.c.

1254 {
1255
1256 $(self, sizeToSatisfy, width, height);
1258 $(self, layoutSubviews);
1259
1260 self->needsLayout = false;
1261}
@ WarningTypeLayout
Definition Warning.h:35
void sizeToSatisfy(View *self, ViewConstraint width, ViewConstraint height)
Resizes this View to satisfy the given ViewConstraints.
Definition View.c:2029

◆ layoutWithSize()

void layoutWithSize ( View *  self,
const SDL_Size *  size 
)

Resizes this View to the given size, then arranges it.

Parameters
selfThe View.
sizeThe size to resize this View to.
Remarks
Like View::layoutWithConstraint, but for a caller that has already computed this View's exact final size and must apply it verbatim – e.g. a StackView applying its distribution math to a subview.
See also
View::layoutWithConstraint(View *, ViewConstraint, ViewConstraint)

Definition at line 1267 of file View.c.

1267 {
1268
1269 $(self, resize, size);
1271 $(self, layoutSubviews);
1272
1273 self->needsLayout = false;
1274}
void resize(View *self, const SDL_Size *size)
Resizes this View to the specified size.
Definition View.c:1708

◆ matchesSelector()

bool matchesSelector ( const View *  self,
const SimpleSelector *  simpleSelector 
)
Parameters
selfThe View.
simpleSelectorThe SimpleSelector.
Returns
True if this View matches the SimpleSelector, false otherwise.

Definition at line 51 of file CollectionItemView.c.

51 {
52
53 assert(simpleSelector);
54
55 const CollectionItemView *this = (CollectionItemView *) self;
56 const char *pattern = simpleSelector->pattern;
57
58 switch (simpleSelector->type) {
60 if (strcmp("selected", pattern) == 0) {
61 return this->isSelected;
62 }
63 break;
64 default:
65 break;
66 }
67
68 return super(View, self, matchesSelector, simpleSelector);
69}
static bool isSelected(const Control *self)
Definition Control.c:358
@ SimpleSelectorTypePseudo
CollectionViewItems are a visual representation of an item within a CollectionView.
SimpleSelectorType type
The SimpleSelectorType.
char * pattern
The pattern, as provided by the user.
bool matchesSelector(const View *self, const SimpleSelector *simpleSelector)

◆ moveToWindow()

void moveToWindow ( View *  self,
SDL_Window *  window 
)

Moves this View to the View hierarchy of the given window.

Parameters
selfThe View.
windowThe window, or NULL if this View is moving from its current window.

Definition at line 1351 of file View.c.

1351 {
1352
1353 $(self, willMoveToWindow, window);
1354
1355 if (self->window && self->window != window) {
1356 SDL_PropertiesID props = SDL_GetWindowProperties(self->window);
1357
1358 if (SDL_GetPointerProperty(props, "keyResponder", NULL) == self) {
1359 SDL_SetPointerProperty(props, "keyResponder", NULL);
1360 }
1361
1362 if (SDL_GetPointerProperty(props, "touchResponder", NULL) == self) {
1363 SDL_SetPointerProperty(props, "touchResponder", NULL);
1364 }
1365 }
1366
1367 self->window = window;
1368
1369 $(self, didMoveToWindow, window);
1370
1372}
static void moveToWindow_enumerate(View *subview, ident data)
ViewEnumerator for moveToWindow recursion.
Definition View.c:1343
void willMoveToWindow(View *self, SDL_Window *window)
Informs this View that it will be added to the View hierarchy for the given window.
Definition View.c:2208

◆ path()

String * path ( const View *  self)
Parameters
selfThe View.
Returns
A unique CSS selector matching this View.

Definition at line 1378 of file View.c.

1378 {
1379
1380 Array *parts = $$(Array, array);
1381
1382 const View *view = self;
1383 while (view) {
1384
1385 Array *classNames = $((Set *) view->classNames, allObjects);
1386
1387 String *part;
1388 if (view->identifier) {
1389 part = str("#%s", view->identifier);
1390 } else if (classNames->count) {
1391 part = str(".%s", ((String *) $(classNames, firstObject))->chars);
1392 } else {
1393 part = str("%s", classnameof(view));
1394 }
1395
1396 release(classNames);
1397
1398 $(parts, insertObjectAtIndex, part, 0);
1399 release(part);
1400
1401 if (view->viewController) {
1402 break;
1403 }
1404
1405 view = view->superview;
1406 }
1407
1408 String *path = $((Array *) parts, componentsJoinedByCharacters, " > ");
1409
1410 release(parts);
1411
1412 return path;
1413}
ViewController * viewController
The ViewController.
Definition View.h:460

◆ removeAllClassNames()

void removeAllClassNames ( View *  self)

Removes all class names from this View.

Parameters
selfThe View.

Definition at line 1419 of file View.c.

1419 {
1420
1421 $(self->classNames, removeAllObjects);
1422
1423 $(self, invalidateStyle);
1424}

◆ removeAllSubviews()

void removeAllSubviews ( View *  self)

Removes all subviews from this View.

Parameters
selfThe View.

Definition at line 1437 of file View.c.

1437 {
1438 $(self->subviews, removeAllObjectsWithEnumerator, removeAllSubviews_enumerate, self);
1439}
static void removeAllSubviews_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for removeAllSubviews.
Definition View.c:1429

◆ removeClassName()

void removeClassName ( View *  self,
const char *  className 
)

Removes the given class name to this View.

Parameters
selfThe View.
classNameThe class name.

Definition at line 1445 of file View.c.

1445 {
1446
1447 if (className) {
1448 String *string = $$(String, stringWithCharacters, className);
1449 assert(string);
1450
1451 $(self->classNames, removeObject, string);
1452 release(string);
1453
1454 $(self, invalidateStyle);
1455 }
1456}

◆ removeFromSuperview()

void removeFromSuperview ( View *  self)

Removes this View from its superview.

Parameters
selfThe View.

Definition at line 1462 of file View.c.

1462 {
1463
1464 if (self->superview) {
1465 $(self->superview, removeSubview, self);
1466 }
1467}
void removeSubview(View *self, View *subview)
Removes the given subview from this View.
Definition PageView.c:72

◆ removeSubview()

void removeSubview ( View *  self,
View *  subview 
)

Removes the given subview from this View.

Parameters
selfThe View.
subviewThe subview.

Definition at line 72 of file PageView.c.

72 {
73
74 PageView *this = (PageView *) self;
75
76 retain(subview);
77
78 super(View, self, removeSubview, subview);
79
81
82 if (subview == this->currentPage) {
83 $(this, setCurrentPage, NULL);
84 }
85
86 release(subview);
87}
@ ViewVisibilityVisible
Definition View.h:121

◆ render()

void render ( View *  self,
Renderer *  renderer 
)

Renders this View using the given renderer.

Parameters
selfThe View.
rendererThe Renderer.
Remarks
Subclasses should override this method to perform actual drawing operations. This method is called by draw as the View hierarchy is drawn.

Definition at line 181 of file Control.c.

181 {
182
183 super(View, self, render, renderer);
184
185 Control *this = (Control *) self;
186
187 const SDL_Rect frame = $(self, renderFrame);
188
189 if (self->borderRadius > 0) {
190
191 if (this->bevel == ControlBevelInset) {
192 $(renderer, drawBevel, &frame, self->borderRadius, 1, &this->bevelDarkColor, &this->bevelLightColor);
193 } else if (this->bevel == ControlBevelOutset) {
194 $(renderer, drawBevel, &frame, self->borderRadius, 1, &this->bevelLightColor, &this->bevelDarkColor);
195 }
196
197 if (this->state & ControlStateFocused) {
198 $(renderer, drawRoundedRect, &frame, self->borderRadius, 1, &Colors.Charcoal);
199 }
200
201 } else {
202
203 if (this->bevel == ControlBevelInset) {
204
205 SDL_Point points[3];
206
207 points[0].x = frame.x;
208 points[0].y = frame.y + frame.h;
209
210 points[1].x = frame.x + frame.w;
211 points[1].y = frame.y + frame.h;
212
213 points[2].x = frame.x + frame.w;
214 points[2].y = frame.y;
215
216 $(renderer, drawLines, points, lengthof(points), &this->bevelLightColor);
217
218 points[0].x = frame.x;
219 points[0].y = frame.y + frame.h;
220
221 points[1].x = frame.x;
222 points[1].y = frame.y;
223
224 points[2].x = frame.x + frame.w;
225 points[2].y = frame.y;
226
227 $(renderer, drawLines, points, lengthof(points), &this->bevelDarkColor);
228
229 } else if (this->bevel == ControlBevelOutset) {
230
231 SDL_Point points[3];
232
233 points[0].x = frame.x;
234 points[0].y = frame.y + frame.h;
235
236 points[1].x = frame.x + frame.w;
237 points[1].y = frame.y + frame.h;
238
239 points[2].x = frame.x + frame.w;
240 points[2].y = frame.y;
241
242 $(renderer, drawLines, points, lengthof(points), &this->bevelDarkColor);
243
244 points[0].x = frame.x;
245 points[0].y = frame.y + frame.h;
246
247 points[1].x = frame.x;
248 points[1].y = frame.y;
249
250 points[2].x = frame.x + frame.w;
251 points[2].y = frame.y;
252
253 $(renderer, drawLines, points, lengthof(points), &this->bevelLightColor);
254 }
255
256 if (this->state & ControlStateFocused) {
257 $(renderer, drawRect, &frame, &Colors.Charcoal);
258 }
259 }
260}
@ ControlBevelInset
Definition Control.h:45
@ ControlBevelOutset
Definition Control.h:46
static void drawLines(const Renderer *self, const SDL_Point *points, size_t count, const SDL_Color *color)
Definition Renderer.c:277
static void drawRoundedRect(const Renderer *self, const SDL_Rect *rect, int radius, int width, const SDL_Color *color)
Definition Renderer.c:407
static void drawRect(const Renderer *self, const SDL_Rect *rect, const SDL_Color *color)
Definition Renderer.c:365
static void drawBevel(const Renderer *self, const SDL_Rect *rect, int radius, int width, const SDL_Color *topLeft, const SDL_Color *bottomRight)
Definition Renderer.c:247
W3C Color constants.
Definition Colors.h:37
SDL_Color Charcoal
Definition Colors.h:53
int borderRadius
The corner radius applied to the background, border and bevel.
Definition View.h:281
void render(View *self, Renderer *renderer)
Renders this View using the given renderer.
Definition Control.c:181

◆ renderDeviceDidReset()

void renderDeviceDidReset ( View *  self)

Informs this View that the render device has reset.

Parameters
selfThe View.
Remarks
Subclasses may override this method to allocate any OpenGL objects they require.

Definition at line 776 of file Text.c.

776 {
777
778 refreshFont((Text *) self);
779
780 $(self, sizeToFit);
781
782 super(View, self, renderDeviceDidReset);
783}
static void refreshFont(Text *self)
Re-resolves this Text's Font at the current window's pixel density. Shared by didMoveToWindow and ren...
Definition Text.c:611
Text rendered with TrueType fonts.
Definition Text.h:131
void renderDeviceDidReset(View *self)
Informs this View that the render device has reset.
Definition Text.c:776
void sizeToFit(View *self)
Resizes this View to fit its subviews.
Definition View.c:2018

◆ renderDeviceWillReset()

void renderDeviceWillReset ( View *  self)

Informs this View that the render device will reset.

Parameters
selfThe View.
Remarks
Subclasses should override this method to free any OpenGL objects they own.

Definition at line 184 of file ImageView.c.

184 {
185
186 ImageView *this = (ImageView *) self;
187
188 this->texture = release(this->texture);
189
190 if (this->image && $((Object *) this->image, isKindOfClass, _AtlasImage())) {
191 ImageAtlas *atlas = ((AtlasImage *) this->image)->atlas;
192 if (atlas) {
193 $(atlas, renderDeviceWillReset);
194 }
195 }
196
197 super(View, self, renderDeviceWillReset);
198}
Class * _AtlasImage(void)
Definition AtlasImage.c:84
static Texture * texture(ImageAtlas *self, RenderDevice *device)
Definition ImageAtlas.c:289
An Image packed into an ImageAtlas.
Definition AtlasImage.h:41
Packs many Images into one sheet, backed by one Texture.
Definition ImageAtlas.h:49
void renderDeviceWillReset(View *self)
Informs this View that the render device will reset.
Definition ImageView.c:184

◆ renderFrame()

SDL_Frame renderFrame ( const View *  self)
Parameters
selfThe View.
Returns
This View's absolute frame in the View hierarchy, in object space.

Definition at line 1629 of file View.c.

1629 {
1630
1631 View *this = (View *) self;
1632
1633 if (_renderFrameGeneration && this->renderFrameCache.generation == _renderFrameGeneration) {
1634 return this->renderFrameCache.frame;
1635 }
1636
1637 SDL_Rect frame = self->frame;
1638
1639 const View *superview = self->superview;
1640 if (superview) {
1641
1642 const SDL_Rect superFrame = $(superview, renderFrame);
1643
1644 frame.x += superFrame.x;
1645 frame.y += superFrame.y;
1646
1647 if (self->alignment != ViewAlignmentInternal) {
1649 frame.y += superview->padding.top;
1650 }
1651 }
1652
1653 this->renderFrameCache.frame = frame;
1654 this->renderFrameCache.generation = _renderFrameGeneration;
1655
1656 return frame;
1657}
@ ViewAlignmentInternal
Definition View.h:81
ViewAlignment alignment
The alignment.
Definition View.h:242

◆ replaceSubview()

void replaceSubview ( View *  self,
View *  subview,
View *  replacement 
)

Replaces the specified subview with the given replacement.

Parameters
selfThe View.
subviewThe subview to replace.
replacementThe replacement subview.

Definition at line 1663 of file View.c.

1663 {
1664
1665 assert(subview);
1666 assert(replacement);
1667
1668 $(self, addSubviewRelativeTo, replacement, subview, ViewPositionAfter);
1669 $(self, removeSubview, subview);
1670}

◆ resignKeyResponder()

void resignKeyResponder ( View *  self)

Resigns key responder priority.

Parameters
selfThe View.

Definition at line 265 of file Control.c.

265 {
266
267 Control *this = (Control *) self;
268
269 if ($(this, isHighlighted) || $(this, isFocused)) {
270
271 this->state &= ~ControlStateHighlighted;
272 this->state &= ~ControlStateFocused;
273
274 $(this, stateDidChange);
275 }
276
277 super(View, self, resignKeyResponder);
278}
static bool isHighlighted(const Control *self)
Definition Control.c:350
void resignKeyResponder(View *self)
Resigns key responder priority.
Definition Control.c:265

◆ resignTouchResponder()

void resignTouchResponder ( View *  self)

Resigns touch responder priority.

Parameters
selfThe View.

Definition at line 1692 of file View.c.

1692 {
1693
1694 if (self->window && $(self, isTouchResponder)) {
1695
1696 String *path = $(self, path);
1697 MVC_LogDebug("%s\n", path->chars);
1698 release(path);
1699
1700 SDL_SetPointerProperty(SDL_GetWindowProperties(self->window), "touchResponder", NULL);
1701 }
1702}

◆ resize()

void resize ( View *  self,
const SDL_Size *  size 
)

Resizes this View to the specified size.

If the size changes, this marks this View for layout, and also its superview when that is a container or when this View has a non-None positioning alignment, since either derives from this size.

Parameters
selfThe View.
sizeThe size to set.

Definition at line 1708 of file View.c.

1708 {
1709
1710 const int w = ClampSize(size->w, self->minSize.w, self->maxSize.w);
1711 const int h = ClampSize(size->h, self->minSize.h, self->maxSize.h);
1712
1713 if (self->frame.w != w || self->frame.h != h) {
1714
1715 self->frame.w = w;
1716 self->frame.h = h;
1717
1718 $(self, setNeedsLayout);
1719
1720 if (self->superview) {
1721 if ($(self->superview, isContainer) || self->alignment & ViewAlignmentMaskAny || self->stretch) {
1722 $(self->superview, setNeedsLayout);
1723 }
1724 }
1725 }
1726}
#define ClampSize(size, min, max)
Clamps size to min and max, where a max of zero is unbounded.
Definition View.h:103
#define ViewAlignmentMaskAny
Definition View.h:58
bool isContainer(const View *self)
Definition View.c:1100
SDL_Size minSize
The minimum size this View may be resized to during layout.
Definition View.h:345
SDL_Size maxSize
The maximum size this View may be resized to during layout.
Definition View.h:339
bool stretch
Whether this View takes a share of the space its StackView leaves along its axis.
Definition View.h:436

◆ resolve()

void resolve ( View *  self,
Outlet *  outlets 
)

Resolves the given Outlets from this View's hierarchy.

Parameters
selfThe View.
outletsThe Outlets to resolve.

Definition at line 1732 of file View.c.

1732 {
1733
1734 if (outlets) {
1735 for (Outlet *outlet = outlets; outlet->identifier; outlet++) {
1736 *outlet->view = $(self, descendantWithIdentifier, outlet->identifier);
1737 if (*outlet->view == NULL) {
1738 String *desc = $((Object *) self, description);
1739 MVC_LogError("Failed to resolve outlet '%s' for %s", outlet->identifier, desc->chars);
1740 release(desc);
1741 }
1742
1743 assert(*outlet->view);
1744 }
1745 }
1746}
static String * description(const Object *self)
Definition Label.c:47
Outlets enable outbound data binding of Views through JSON.
Definition View+JSON.h:194
const char * identifier
The View identifier.
Definition View+JSON.h:199

◆ respondToEvent()

void respondToEvent ( View *  self,
const SDL_Event *  event 
)

Responds to the specified event.

Parameters
selfThe View.
eventThe event.

Definition at line 283 of file Control.c.

283 {
284
285 Control *this = (Control *) self;
286
287 retain(self);
288
289 const ControlState state = (ControlState) this->state;
290 if (!(state & ControlStateDisabled)) {
291 if ($(this, captureEvent, event)) {
292 if (this->state != state) {
293 $(this, stateDidChange);
294 }
295 release(self);
296 return;
297 }
298 }
299
300 super(View, self, respondToEvent, event);
301
302 release(self);
303}
static bool captureEvent(Control *self, const SDL_Event *event)
Definition Button.c:78
ControlState
Control states, which are bit-masked.
Definition Control.h:65
void respondToEvent(View *self, const SDL_Event *event)
Responds to the specified event.
Definition Control.c:283

◆ select()

Set * select ( View *  self,
const char *  rule 
)

Resolves all descendants (including this View) that match the given Selector rule.

Parameters
selfThe View.
ruleThe Selector rule.
Returns
The Set of selected descendant Views.

◆ selectFirst()

View * selectFirst ( View *  self,
const char *  rule 
)

Resolves the first descendant View that matches the given Selector rule.

Parameters
selfThe View.
ruleThe Selector rule.
Returns
The matched View, or NULL.

Definition at line 1819 of file View.c.

1819 {
1820
1821 Selector *selector = $(alloc(Selector), initWithRule, rule);
1822 assert(selector);
1823
1824 View *first = $(selector, selectFirst, self);
1825
1826 release(selector);
1827 return first;
1828}
View * selectFirst(View *self, const char *rule)
Resolves the first descendant View that matches the given Selector rule.
Definition View.c:1819

◆ setNeedsApplyTheme()

void setNeedsApplyTheme ( View *  self)

Marks this View as needing Theme application before it is next drawn.

Parameters
selfThe View.
Remarks
Callers MUST use this method rather than assigning needsApplyTheme directly: it propagates needsApplyThemeSubviews to ancestors, which View::applyThemeIfNeeded requires in order to find this View. A View flagged by direct assignment MAY be skipped.

Definition at line 1852 of file View.c.

1852 {
1853
1854 self->needsApplyTheme = true;
1855
1856 for (View *view = self->superview; view && !view->needsApplyThemeSubviews; view = view->superview) {
1857 view->needsApplyThemeSubviews = true;
1858 }
1859}

◆ setNeedsLayout()

void setNeedsLayout ( View *  self)

Marks this View as needing layout before it is next drawn.

Parameters
selfThe View.
Remarks
Callers MUST use this method rather than assigning needsLayout directly: it propagates needsLayoutSubviews to ancestors, which View::layoutIfNeeded requires in order to find this View. A View flagged by direct assignment MAY be skipped.

Definition at line 1865 of file View.c.

1865 {
1866
1867 self->needsLayout = true;
1868
1869 for (View *view = self->superview; view && !view->needsLayoutSubviews; view = view->superview) {
1870 view->needsLayoutSubviews = true;
1871 }
1872}

◆ setVisibility()

void setVisibility ( View *  self,
ViewVisibility  visibility 
)

Sets this View's visibility.

Parameters
selfThe View.
visibilityThe visibility.
Remarks
Callers MUST use this method rather than assigning View::visibility directly: it marks the superview needsLayout if it is a container, and writes View::style so that the choice outlives the next Style applied.

Definition at line 1834 of file View.c.

1834 {
1835
1836 if (self->visibility != visibility) {
1837
1838 self->visibility = visibility;
1839
1840 $(self->style, addEnumAttribute, "visibility", ViewVisibilityNames, visibility);
1841
1842 if (self->superview && $(self->superview, isContainer)) {
1843 $(self->superview, setNeedsLayout);
1844 }
1845 }
1846}
static void addEnumAttribute(Style *self, const char *attr, const EnumName *names, int value)
Definition Style.c:288
OBJECTIVELYMVC_EXPORT const EnumName ViewVisibilityNames[]
Definition View.h:126

◆ size()

SDL_Size size ( const View *  self)
Parameters
selfThe View.
Returns
The size of this View's frame.

Definition at line 1878 of file View.c.

1878 {
1879 return MakeSize(self->frame.w, self->frame.h);
1880}

◆ sizeThastFills()

SDL_Size sizeThastFills ( const View *  self)

◆ sizeThatContains()

SDL_Size sizeThatContains ( const View *  self)
Parameters
selfThe View.
Returns
An SDL_Size that contains this View's subviews.
Remarks
The returned size is greater than or equal to View::sizeThatFits.

Definition at line 1886 of file View.c.

1886 {
1887
1888 const SDL_Size size = $(self, size);
1889 const SDL_Size sizeThatFits = $(self, sizeThatFits);
1890
1891 return MakeSize(max(size.w, sizeThatFits.w), max(size.h, sizeThatFits.h));
1892}
void sizeThatFits(const View *self)
Definition Select.c:113

◆ sizeThatFills()

SDL_Size sizeThatFills ( const View *  self)
Parameters
selfThe View.
Returns
An SDL_Size that fills this View's superview.

Definition at line 1898 of file View.c.

1898 {
1899 SDL_Size size;
1900
1901 if (self->superview == NULL) {
1902 SDL_GetWindowSize(self->window, &size.w, &size.h);
1903 } else {
1904 size = $(self->superview, size);
1905 }
1906
1907 return size;
1908}

◆ sizeThatFits()

SDL_Size sizeThatFits ( const View *  self)
Parameters
selfThe View.
Returns
An SDL_Size that fits this View's subviews.
Remarks
The default implementation returns this View's current size if it is not a container. If it is a container, it instead returns the smallest size that fits all of its subviews, each measured via View::sizeThatSatisfies with ViewConstraintUnspecified for both axes. Subclasses with their own sizing logic (e.g. Text, TableView) should override this method.

Definition at line 113 of file Select.c.

113 {
114
115 const Select *this = (Select *) self;
116
117 SDL_Size size = super(View, self, sizeThatFits);
118
119 const Array *options = (Array *) this->options;
120 for (size_t i = 0; i < options->count; i++) {
121
122 const View *option = $(options, objectAtIndex, i);
123 const SDL_Size optionSize = $(option, sizeThatFits);
124
125 size.w = max(size.w, optionSize.w + self->padding.left + self->padding.right);
126 size.h = max(size.h, optionSize.h + self->padding.top + self->padding.bottom);
127 }
128
129 return size;
130}
A Control allowing users to select one or more Options.
Definition Select.h:63

◆ sizeThatSatisfies()

SDL_Size sizeThatSatisfies ( View *  self,
ViewConstraint  width,
ViewConstraint  height 
)

Resolves the size this View wants to be, within the offered ViewConstraints.

Parameters
selfThe View.
widthThe ViewConstraint offered for this View's width.
heightThe ViewConstraint offered for this View's height.
Returns
The resolved size.
Remarks
Computes this View's sizeThatFits and resolves it against the offered ViewConstraints for any axis on which this View has ViewAutoresizingWidth or ViewAutoresizingHeight set.

Definition at line 1979 of file View.c.

1979 {
1980
1981 SDL_Size size = $(self, sizeThatFits);
1982
1985
1986 size.w = ClampSize(size.w, self->minSize.w, self->maxSize.w);
1987 size.h = ClampSize(size.h, self->minSize.h, self->maxSize.h);
1988
1989 return size;
1990}
static int resolveViewConstraint(int hasAutoresizingBit, ViewConstraint constraint, int intrinsic)
Resolves an axis's sizeThatFits value against an offered ViewConstraint, if the View has opted into t...
Definition View.c:1959
@ ViewAutoresizingWidth
Definition View.h:91
@ ViewAutoresizingHeight
Definition View.h:92

◆ sizeToContain()

void sizeToContain ( View *  self)

Resizes this View to contain its subviews.

Parameters
selfThe View.
See also
View::sizeThatContains(const View *)

Definition at line 1996 of file View.c.

1996 {
1997
1998 const SDL_Size size = $(self, sizeThatContains);
1999
2000 $(self, resize, &size);
2001}

◆ sizeToFill()

void sizeToFill ( View *  self)

Resizes this View to fill its superview.

Parameters
selfThe View.
See also
View::sizeThatFills(const View *)

Definition at line 2007 of file View.c.

2007 {
2008
2009 const SDL_Size size = $(self, sizeThatFills);
2010
2011 $(self, resize, &size);
2012}
SDL_Size sizeThatFills(const View *self)
Definition View.c:1898

◆ sizeToFit()

void sizeToFit ( View *  self)

Resizes this View to fit its subviews.

Parameters
selfThe View.
See also
View::sizeThatFits(const View *)

Definition at line 2018 of file View.c.

2018 {
2019
2020 const SDL_Size size = $(self, sizeThatFits);
2021
2022 $(self, resize, &size);
2023}

◆ sizeToSatisfy()

void sizeToSatisfy ( View *  self,
ViewConstraint  width,
ViewConstraint  height 
)

Resizes this View to satisfy the given ViewConstraints.

Parameters
selfThe View.
widthThe ViewConstraint offered for this View's width.
heightThe ViewConstraint offered for this View's height.
See also
View::sizeThatSatisfies(View *, ViewConstraint, ViewConstraint)

Definition at line 2029 of file View.c.

2029 {
2030
2031 const SDL_Size size = $(self, sizeThatSatisfies, width, height);
2032
2033 $(self, resize, &size);
2034}
SDL_Size sizeThatSatisfies(View *self, ViewConstraint width, ViewConstraint height)
Resolves the size this View wants to be, within the offered ViewConstraints.
Definition View.c:1979

◆ subviewWithIdentifier()

View * subviewWithIdentifier ( const View *  self,
const char *  identifier 
)
Parameters
selfThe View.
identifierThe identifier.
Returns
The first subview matching the given identifier.

Definition at line 2040 of file View.c.

2040 {
2041
2042 assert(identifier);
2043
2044 const Array *subviews = (Array *) self->subviews;
2045 for (size_t i = 0; i < subviews->count; i++) {
2046
2047 View *subview = subviews->elements[i];
2048 if (subview->identifier) {
2049
2050 if (strcmp(identifier, subview->identifier) == 0) {
2051 return subview;
2052 }
2053 }
2054 }
2055
2056 return NULL;
2057}

◆ updateBindings()

void updateBindings ( View *  self,
ident  data 
)

Updates data bindings, prompting the appropriate layout changes.

The default implementation recurses over this View's subviews, passing data through unchanged. Subclasses SHOULD override this method to refresh any data sources they rely on, and MUST call super to continue the recursion.

Parameters
selfThe View.
dataApplication-defined data, or NULL.
Remarks
The framework always passes NULL: on ViewController::addChildViewController and on pixel density changes, meaning "refresh from configuration." An application MAY pass its own data to hand transient state – a simulation frame, say – to an entire View hierarchy at once, without holding a reference to every View that consumes it. Since a non-NULL payload MAY arrive as often as every frame, expensive work SHOULD stay behind the NULL case.

Definition at line 117 of file HSVColorPicker.c.

117 {
118
119 super(View, self, updateBindings, data);
120
121 HSVColorPicker *this = (HSVColorPicker *) self;
122
123 $(this->hueSlider, setValue, this->hue);
124 $(this->saturationSlider, setValue, this->saturation);
125 $(this->valueSlider, setValue, this->value);
126
127 const SDL_Color color = $(this, rgbColor);
128 $(this->colorView->style, addColorAttribute, "background-color", &color);
129 $(this->colorView, invalidateStyle);
130}
static SDL_Color rgbColor(const HSVColorPicker *self)
static void setValue(ProgressBar *self, double value)
static void addColorAttribute(Style *self, const char *attr, const SDL_Color *color)
Definition Style.c:253
The HSVColorPicker type.
void updateBindings(View *self, ident data)
Updates data bindings, prompting the appropriate layout changes.

◆ viewport()

SDL_Rect viewport ( const View *  self)
Parameters
selfThe View.
Returns
The OpenGL viewport for this View.

Definition at line 2078 of file View.c.

2078 {
2079
2080 assert(self->window);
2081
2082 const SDL_Rect frame = $(self, renderFrame);
2083
2084 return MVC_TransformToWindow(self->window, &frame);
2085}
SDL_Rect MVC_TransformToWindow(SDL_Window *window, const SDL_Rect *rect)
Transforms the specified rectangle to normalized device coordinates in window.
Definition Window.c:29

◆ viewWithCharacters()

View * viewWithCharacters ( const char *  chars,
Outlet *  outlets 
)

Instantiates a View initialized with the given null-terminated JSON C string.

Parameters
charsA null-terminated JSON C string describing a View.
outletsAn optional array of Outlets to resolve.
Returns
The initialized View, or NULL on error.

Definition at line 2091 of file View.c.

2091 {
2092
2093 Data *data = $$(Data, dataWithConstMemory, (ident) chars, strlen(chars));
2094
2095 View *view = $$(View, viewWithData, data, outlets);
2096
2097 release(data);
2098
2099 return view;
2100}
View * viewWithData(const Data *data, Outlet *outlets)
Instantiates a View initialized with the contents of data.
Definition View.c:2106

◆ viewWithData()

View * viewWithData ( const Data *  data,
Outlet *  outlets 
)

Instantiates a View initialized with the contents of data.

Parameters
dataA Data containing JSON describing a View.
outletsAn optional array of Outlets to resolve.
Returns
The initialized View, or NULL on error.

Definition at line 2106 of file View.c.

2106 {
2107
2108 JSONContext *ctx = $(alloc(JSONContext), init);
2109 Dictionary *dictionary = $(ctx, objectFromData, data, 0);
2110
2111 View *view = NULL;
2112 if (dictionary) {
2113 view = $$(View, viewWithDictionary, dictionary, outlets);
2114 release(dictionary);
2115 } else {
2116 MVC_LogError("Failed to parse JSON\n");
2117 }
2118
2119 release(ctx);
2120 return view;
2121}
View * viewWithDictionary(const Dictionary *dictionary, Outlet *outlets)
Instantiates a View initialized with the attributes described in dictionary.
Definition View.c:2127

◆ viewWithDictionary()

View * viewWithDictionary ( const Dictionary *  dictionary,
Outlet *  outlets 
)

Instantiates a View initialized with the attributes described in dictionary.

Parameters
dictionaryA Dictionary describing a View.
outletsAn optional array of Outlets to resolve.
Returns
The initialized View, or NULL on error.
See also
View::initWithDictionary(View *, const Dictionary *, Outlet *outlets)

Definition at line 2127 of file View.c.

2127 {
2128
2129 View *view = NULL;
2130
2131 BindInlet(&MakeInlet(NULL, InletTypeView, &view, NULL), dictionary);
2132
2133 $(view, resolve, outlets);
2134
2135 return view;
2136}
#define BindInlet(inlet, obj)
Binds the Inlet to obj by invoking the appropriate InletBinding function.
Definition View+JSON.h:238
void resolve(View *self, Outlet *outlets)
Resolves the given Outlets from this View's hierarchy.
Definition View.c:1732

◆ viewWithResource()

View * viewWithResource ( const Resource *  resource,
Outlet *  outlets 
)

Instantiates a View initialized with the JSON data in resource.

Parameters
resourceA Resource containing JSON describing a View.
outletsAn optional array of Outlets to resolve.
Returns
The initialized View, or NULL on error.
See also
View::initWithData(View *, const Data *, Outlet *outlets)

Definition at line 2142 of file View.c.

2142 {
2143
2144 assert(resource);
2145
2146 return $$(View, viewWithData, resource->data, outlets);
2147}

◆ viewWithResourceName()

View * viewWithResourceName ( const char *  name,
Outlet *  outlets 
)

Instantiates a View initialized with the JSON Resource with the specified name.

Parameters
nameThe name of a JSON Resource describing a View.
outletsAn optional array of Outlets to resolve.
Returns
The initialized View, or NULL on error.
See also
View::initWithResource(View *, const Dictionary *, Outlet *outlets)

Definition at line 2153 of file View.c.

2153 {
2154
2155 Resource *resource = $$(Resource, resourceWithName, name);
2156
2157 View *view = $$(View, viewWithResource, resource, outlets);
2158
2159 release(resource);
2160
2161 return view;
2162}
View * viewWithResource(const Resource *resource, Outlet *outlets)
Instantiates a View initialized with the JSON data in resource.
Definition View.c:2142

◆ visibleSubviews()

Array * visibleSubviews ( const View *  self)
Parameters
selfThe View.
Returns
An Array of this View's visible subviews.
Remarks
The returned Array excludes that specify ViewAlignmentInternal.

Definition at line 92 of file PageView.c.

92 {
93 return $$(Array, arrayWithArray, (Array *) self->subviews);
94}

◆ warn() [1/2]

void warn ( View *  self,
ViewWarningType  type,
const char *  fmt,
  ... 
)

◆ warn() [2/2]

void warn ( View *  self,
WarningType  level,
const char *  fmt,
  ... 
)

Appends a warning for this View.

Parameters
selfThe View.
levelThe WarningType.
fmtThe format string.

Definition at line 2186 of file View.c.

2186 {
2187
2188 va_list args;
2189 va_start(args, fmt);
2190
2191 Warning *warning = $(alloc(Warning), initWithVaList, type, fmt, args);
2192
2193 va_end(args);
2194
2195 String *description = $((Object *) self, description);
2196 MVC_LogWarn("%s:: %s\n", description->chars, warning->message->chars);
2197 release(description);
2198
2199 $(self->warnings, addObject, warning);
2200
2201 release(warning);
2202}
#define MVC_LogWarn(fmt,...)
Definition Log.h:54
static Warning * initWithVaList(Warning *self, WarningType type, const char *fmt, va_list args)
Definition Warning.c:66
The Warning type.
Definition Warning.h:50
String * message
The message.
Definition Warning.h:71

◆ willMoveToWindow()

void willMoveToWindow ( View *  self,
SDL_Window *  window 
)

Informs this View that it will be added to the View hierarchy for the given window.

Parameters
selfThe View.
windowThe window, or NULL if this View will be removed from the window.

Definition at line 2208 of file View.c.

2208 {
2209
2210 if (self->window) {
2211 $(self, resignKeyResponder);
2212 $(self, resignTouchResponder);
2213 $(self, detachStylesheet, self->window);
2214 }
2215}
void detachStylesheet(View *self, SDL_Window *window)
Detaches this View's Stylesheet from the Theme associated with the given window.
Definition View.c:693

Field Documentation

◆ alignment

ViewAlignment View::alignment

The alignment.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 242 of file View.h.

◆ autoresizingMask

int View::autoresizingMask

The ViewAutoresizing bitmask.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 248 of file View.h.

◆ backgroundColor

SDL_Color View::backgroundColor

The background color.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 254 of file View.h.

◆ backgroundGradientAngle

int View::backgroundGradientAngle

The angle of the background gradient, in degrees, clockwise from south: 0 (the default) fills downwards, 90 to the right, 180 upwards.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 261 of file View.h.

◆ backgroundGradientColor

SDL_Color View::backgroundGradientColor

The far color of the background gradient, which runs from View::backgroundColor.

Remarks
The gradient is drawn only when this color has a non-zero alpha; otherwise the background is a flat View::backgroundColor.
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 269 of file View.h.

◆ borderColor

SDL_Color View::borderColor

The border color.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 275 of file View.h.

◆ borderRadius

int View::borderRadius

The corner radius applied to the background, border and bevel.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 281 of file View.h.

◆ borderWidth

int View::borderWidth

The border width.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 287 of file View.h.

◆ classNames

Set* View::classNames

The class names.

See also
Style

Definition at line 293 of file View.h.

◆ clipsSubviews

bool View::clipsSubviews

If true, subviews will be clipped to this View's frame.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 309 of file View.h.

◆ computedStyle

Style* View::computedStyle

The computed Style of this View.

Definition at line 314 of file View.h.

◆ cornerCut

ViewCornerCut View::cornerCut

The horizontal inset of each corner of the background and border.

Remarks
A View with any corner inset is drawn as a polygon rather than through the rounded rectangle shader, so View::borderRadius does not apply to it.
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 322 of file View.h.

◆ frame

SDL_Rect View::frame

The frame, relative to the superview.

Definition at line 301 of file View.h.

◆ generation

unsigned View::generation

Definition at line 302 of file View.h.

◆ identifier

char* View::identifier

An optional identifier.

Remarks
Identifiers are commonly used to resolve Outlets when loading Views via JSON.

Definition at line 333 of file View.h.

◆ interface

ViewInterface* View::interface[0]
protected

The interface type.

Definition at line 236 of file View.h.

◆ maxSize

SDL_Size View::maxSize

The maximum size this View may be resized to during layout.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 339 of file View.h.

◆ minSize

SDL_Size View::minSize

The minimum size this View may be resized to during layout.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 345 of file View.h.

◆ needsApplyTheme

bool View::needsApplyTheme

If true, this View will apply the Theme before it is drawn.

Remarks
Set this via View::setNeedsApplyTheme, which propagates needsApplyThemeSubviews to ancestors; a direct write does not, and the View MAY be skipped by View::applyThemeIfNeeded.

Definition at line 353 of file View.h.

◆ needsLayout

bool View::needsLayout

If true, this View will layout its subviews before it is drawn.

Remarks
Set this via View::setNeedsLayout, which propagates needsLayoutSubviews to ancestors; a direct write does not, and the View MAY be skipped by View::layoutIfNeeded.

Definition at line 377 of file View.h.

◆ nextResponder

View* View::nextResponder

The next responder, or event handler, in the chain.

Remarks
By default, Views propagate events to their superview. If this member is not NULL, events will instead be propagated to this View.

Definition at line 392 of file View.h.

◆ object

Object View::object

The superclass.

Definition at line 230 of file View.h.

◆ padding

ViewPadding View::padding

The padding.

Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 398 of file View.h.

◆ pointerEvents

ViewPointerEvents View::pointerEvents

Whether this View is the result of a hit test; its subviews always are.

Remarks
An overlay that is drawn but never interacted with, such as a full-window HUD or console layer stacked above interactive content, SHOULD be none so that clicks pass through it to whatever lies beneath. Styled as pointer-events.
See also
View::hitTest(const View *, const SDL_Point *)
Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 408 of file View.h.

◆ stretch

bool View::stretch

Whether this View takes a share of the space its StackView leaves along its axis.

Remarks
A StackView gives each subview the size of its content along its axis. The subviews that stretch share whatever remains of the StackView's bounds, so that one child, such as a page beneath a row of tabs, can fill a StackView that is itself sized by its superview. Outside of a StackView, this has no effect. Styled as stretch.
See also
StackView::layoutSubviews(View *)
Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 436 of file View.h.

◆ style

Style* View::style

The element-level Style of this View.

Remarks
Attributes in this Style are local to this View, and override any Attributes matched via Selector. That is, it is always the last Style added to the computed Style.

Definition at line 425 of file View.h.

◆ stylesheet

Stylesheet* View::stylesheet

An optional Stylesheet.

Remarks
If set, this Stylesheet is added to or removed from the current Theme when this View is added to or removed from a valid View hierarchy.

Definition at line 443 of file View.h.

◆ subviews

Array* View::subviews

The immediate subviews.

Definition at line 448 of file View.h.

◆ superview

View* View::superview

The super View.

Remarks
This reference is not retained.

Definition at line 454 of file View.h.

◆ viewController

ViewController* View::viewController

The ViewController.

Remarks
This is NULL unless the View is the immediate view of a ViewController.

Definition at line 460 of file View.h.

◆ visibility

ViewVisibility View::visibility

Whether this View is drawn, and contributes to its superview's size.

Remarks
unspecified is visible.
See also
View::setVisibility(View *, ViewVisibility)
Remarks
Styled. Set from a Style, and overwritten by the next one applied. Assign View::style, or a stylesheet rule, rather than this field.

Definition at line 468 of file View.h.

◆ warnings

Array* View::warnings

The Warnings this View generated.

Remarks
These are optionally displayed by the DebugViewController.

Definition at line 474 of file View.h.

◆ window

SDL_Window* View::window

The window.

Remarks
This is NULL until the View has been added to a WindowController.

Definition at line 480 of file View.h.


The documentation for this struct was generated from the following files: