ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
View.c File Reference
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <Objectively.h>
#include "Log.h"
#include "View.h"
#include "ViewController.h"
#include "WindowController.h"
#include "Window.h"

Go to the source code of this file.

Data Structures

struct  Overflow
 

Macros

#define _Class   _View
 

Functions

static void _applyThemeIfNeeded (View *view, ident data)
 ViewEnumerator adapter for applyThemeIfNeeded.
 
static bool _bind (View *self, const Inlet *inlets, const Dictionary *dictionary)
 
static void _draw (View *view, ident data)
 ViewEnumerator adapter for draw.
 
static Set * _select (View *self, const char *rule)
 
Class * _View (void)
 
static bool acceptsKeyResponder (const View *self)
 
static bool acceptsTouchResponder (const View *self)
 
static void addClassName (View *self, const char *className)
 
static void addSubview (View *self, View *subview)
 
static void addSubviewRelativeTo (View *self, View *subview, View *other, ViewPosition position)
 
static View * ancestorWithIdentifier (const View *self, const char *identifier)
 
static void applyStyle (View *self, const Style *style)
 
static void applyTheme (View *self, const Theme *theme)
 
static void applyThemeIfNeeded (View *self, const Theme *theme)
 
static void attachStylesheet (View *self, SDL_Window *window)
 
static void awakeWithCharacters (View *self, const char *chars)
 
static void awakeWithData (View *self, const Data *data)
 
static void awakeWithDictionary (View *self, const Dictionary *dictionary)
 
static void awakeWithResource (View *self, const Resource *resource)
 
static void awakeWithResourceName (View *self, const char *name)
 
static void becomeKeyResponder (View *self)
 
static void becomeTouchResponder (View *self)
 
static SDL_Rect bounds (const View *self)
 
static void bringSubviewToFront (View *self, View *subview)
 
static void clearWarnings (const View *self, WarningType type)
 
static bool clearWarnings_predicate (const ident obj, ident data)
 Filter Predicate for clearWarnings.
 
static SDL_Rect clippingFrame (const View *self)
 
static bool containsPoint (const View *self, const SDL_Point *point)
 
static void cornerCutPoints (SDL_Point *points, const SDL_Rect *rect, const ViewCornerCut *cut)
 Writes the four corners of rect, inset by cut, in clockwise order.
 
static void dealloc (Object *self)
 
static int depth (const View *self)
 
static View * descendantWithIdentifier (const View *self, const char *identifier)
 
static String * description (const Object *self)
 
static void detachStylesheet (View *self, SDL_Window *window)
 
static void didMoveToWindow (View *self, SDL_Window *window)
 
static bool didReceiveEvent (const View *self, const SDL_Event *event)
 
static void draw (View *self, Renderer *renderer)
 
static void emitViewEvent (View *self, ViewEvent code, ident data)
 
static void enumerate (View *self, ViewEnumerator enumerator, ident data)
 
static void enumerateAdjacent (const View *self, ViewEnumerator enumerator, ident data)
 
static void enumerateAncestors (const View *self, ViewEnumerator enumerator, ident data)
 
static void enumerateDescendants (const View *self, ViewEnumerator enumerator, ident data)
 
static void enumerateSelection (View *self, const char *rule, ViewEnumerator enumerator, ident data)
 
static void enumerateSiblings (const View *self, ViewEnumerator enumerator, ident data)
 
static void enumerateSubviews (const View *self, ViewEnumerator enumerator, ident data)
 
static void enumerateSuperview (const View *self, ViewEnumerator enumerator, ident data)
 
static void enumerateVisible (View *self, ViewEnumerator enumerator, ident data)
 
static bool filterViewEvents (void *data, SDL_Event *event)
 
static bool hasClassName (const View *self, const char *className)
 
static bool hasClassName_predicate (const ident obj, ident data)
 Predicate for hasClassName.
 
static bool hasOverflow (const View *self)
 
static void hasOverflow_enumerate (View *view, ident data)
 ViewEnumerator for hasOverflow.
 
static View * hitTest (const View *self, const SDL_Point *point)
 
static View * init (View *self)
 
static void initialize (Class *clazz)
 
static View * initWithFrame (View *self, const SDL_Rect *frame)
 
static void invalidateStyle (View *self)
 
static void invalidateStyle_enumerate (View *view, ident data)
 ViewEnumerator for invalidateStyle.
 
static bool isContainer (const View *self)
 
static bool isDescendantOfView (const View *self, const View *view)
 
static bool isKeyResponder (const View *self)
 
static bool isTouchResponder (const View *self)
 
static bool isVisible (const View *self)
 
static void layoutIfNeeded (View *self)
 
static void layoutIfNeeded_enumerate (View *subview, ident data)
 ViewEnumerator for layoutIfNeeded recursion.
 
static void layoutSubviews (View *self)
 
static void layoutWithConstraint (View *self, ViewConstraint width, ViewConstraint height)
 
static void layoutWithSize (View *self, const SDL_Size *size)
 
static bool matchesSelector (const View *self, const SimpleSelector *simpleSelector)
 
static void moveToWindow (View *self, SDL_Window *window)
 
static void moveToWindow_enumerate (View *subview, ident data)
 ViewEnumerator for moveToWindow recursion.
 
void MVC_InvalidateRenderFrames (void)
 Invalidates every View's cached View::renderFrame and View::clippingFrame.
 
static void nullifySuperview (View *subview, ident data)
 ViewEnumerator to null out superview pointers during parent dealloc.
 
static String * path (const View *self)
 
static void removeAllClassNames (View *self)
 
static void removeAllSubviews (View *self)
 
static void removeAllSubviews_enumerate (const Array *array, ident obj, ident data)
 ArrayEnumerator for removeAllSubviews.
 
static void removeClassName (View *self, const char *className)
 
static void removeFromSuperview (View *self)
 
static void removeSubview (View *self, View *subview)
 
static void render (View *self, Renderer *renderer)
 
static void renderDeviceDidReset (View *self)
 
static void renderDeviceDidReset_enumerate (View *subview, ident data)
 ViewEnumerator for renderDeviceDidReset recursion.
 
static void renderDeviceWillReset (View *self)
 
static void renderDeviceWillReset_enumerate (View *subview, ident data)
 ViewEnumerator for renderDeviceWillReset recursion.
 
static SDL_Rect renderFrame (const View *self)
 
static void replaceSubview (View *self, View *subview, View *replacement)
 
static void resignKeyResponder (View *self)
 
static void resignTouchResponder (View *self)
 
static void resize (View *self, const SDL_Size *size)
 
static void resolve (View *self, Outlet *outlets)
 
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 that axis's autoresizing bit; otherwise returns the value unmodified.
 
static void respondToEvent (View *self, const SDL_Event *event)
 
static View * selectFirst (View *self, const char *rule)
 
static void setNeedsApplyTheme (View *self)
 
static void setNeedsLayout (View *self)
 
static void setVisibility (View *self, ViewVisibility visibility)
 
static SDL_Size size (const View *self)
 
static SDL_Size sizeThatContains (const View *self)
 
static SDL_Size sizeThatFills (const View *self)
 
static SDL_Size sizeThatFits (const View *self)
 
static SDL_Size sizeThatSatisfies (View *self, ViewConstraint width, ViewConstraint height)
 
static void sizeToContain (View *self)
 
static void sizeToFill (View *self)
 
static void sizeToFit (View *self)
 
static void sizeToSatisfy (View *self, ViewConstraint width, ViewConstraint height)
 
static View * subviewWithIdentifier (const View *self, const char *identifier)
 
static void updateBindings (View *self, ident data)
 
static void updateBindings_enumerate (View *subview, ident data)
 ViewEnumerator for updateBindings recursion.
 
static SDL_Rect viewport (const View *self)
 
static View * viewWithCharacters (const char *chars, Outlet *outlets)
 
static View * viewWithData (const Data *data, Outlet *outlets)
 
static View * viewWithDictionary (const Dictionary *dictionary, Outlet *outlets)
 
static View * viewWithResource (const Resource *resource, Outlet *outlets)
 
static View * viewWithResourceName (const char *name, Outlet *outlets)
 
static Array * visibleSubviews (const View *self)
 
static bool visibleSubviews_filter (ident obj, ident data)
 Predicate for visibleSubviews.
 
static void warn (View *self, WarningType type, const char *fmt,...)
 
static void willMoveToWindow (View *self, SDL_Window *window)
 

Variables

static unsigned _renderFrameGeneration
 The render frame generation; per-View renderFrame and clippingFrame caches are valid only while their generation matches this. Zero disables caching entirely, for callers that never invalidate (e.g. unit tests).
 
Uint32 MVC_NOTIFICATION_EVENT
 
Uint32 MVC_VIEW_EVENT
 
const EnumName ViewAlignmentNames []
 
const EnumName ViewAutoresizingNames []
 
const EnumName ViewPointerEventsNames []
 
const EnumName ViewVisibilityNames []
 

Macro Definition Documentation

◆ _Class

#define _Class   _View

Definition at line 92 of file View.c.

Function Documentation

◆ _applyThemeIfNeeded()

static void _applyThemeIfNeeded ( View *  view,
ident  data 
)
static

ViewEnumerator adapter for applyThemeIfNeeded.

Definition at line 365 of file View.c.

365 {
366 applyThemeIfNeeded(view, (const Theme *) data);
367}
static void applyThemeIfNeeded(View *self, const Theme *theme)
Definition View.c:369
The Theme type.
Definition Theme.h:54

◆ _bind()

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

Definition at line 535 of file View.c.

535 {
536
537 if (inlets) {
538 if (bindInlets(inlets, dictionary)) {
539 $(self, setNeedsApplyTheme);
540 $(self, setNeedsLayout);
541 return true;
542 }
543 }
544
545 return false;
546}
bool bindInlets(const Inlet *inlets, const Dictionary *dictionary)
Binds each Inlet specified in inlets to the data provided in dictionary.
Definition View+JSON.c:303
static void setNeedsLayout(View *self)
Definition View.c:1865
static void setNeedsApplyTheme(View *self)
Definition View.c:1852

◆ _draw()

static void _draw ( View *  view,
ident  data 
)
static

ViewEnumerator adapter for draw.

Definition at line 774 of file View.c.

774 {
775 draw(view, (Renderer *) data);
776}
static void draw(View *self, Renderer *renderer)
Definition View.c:778
Renderer extends Object with ObjectivelyMVC's UI rendering layer.
Definition Renderer.h:75

◆ _select()

static Set * _select ( View *  self,
const char *  rule 
)
static

Definition at line 1804 of file View.c.

1804 {
1805
1806 Selector *selector = $(alloc(Selector), initWithRule, rule);
1807 assert(selector);
1808
1809 Set *selection = $(selector, select, self);
1810
1811 release(selector);
1812 return selection;
1813}
static Selector * initWithRule(Selector *self, const char *rule)
Definition Selector.c:190
Selectors are comprised of one or more SelectorSequences.
Definition Selector.h:49

◆ _View()

Class * _View ( void  )

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 View.c:2222
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:225

◆ acceptsKeyResponder()

static bool acceptsKeyResponder ( const View *  self)
static

Definition at line 167 of file View.c.

167 {
168 return false;
169}

◆ acceptsTouchResponder()

static bool acceptsTouchResponder ( const View *  self)
static

Definition at line 175 of file View.c.

175 {
176 return false;
177}

◆ addClassName()

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

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}
static void invalidateStyle(View *self)
Definition View.c:1092
Set * classNames
The class names.
Definition View.h:293

◆ addSubview()

static void addSubview ( View *  self,
View *  subview 
)
static

Definition at line 201 of file View.c.

201 {
202 $(self, addSubviewRelativeTo, subview, NULL, ViewPositionAfter);
203}
static void addSubviewRelativeTo(View *self, View *subview, View *other, ViewPosition position)
Definition View.c:209
@ ViewPositionAfter
Definition View.h:212

◆ addSubviewRelativeTo()

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

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}
static void moveToWindow(View *self, SDL_Window *window)
Definition View.c:1351
static void removeFromSuperview(View *self)
Definition View.c:1462
View * superview
The super View.
Definition View.h:454
Array * subviews
The immediate subviews.
Definition View.h:448
SDL_Window * window
The window.
Definition View.h:480

◆ ancestorWithIdentifier()

static View * ancestorWithIdentifier ( const View *  self,
const char *  identifier 
)
static

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()

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

Definition at line 272 of file View.c.

272 {
273
274 assert(style);
275
276 const Inlet inlets[] = MakeInlets(
277 MakeInlet("alignment", InletTypeEnum, &self->alignment, (ident) ViewAlignmentNames),
278 MakeInlet("autoresizing-mask", InletTypeEnum, &self->autoresizingMask, (ident) ViewAutoresizingNames),
279 MakeInlet("background-color", InletTypeColor, &self->backgroundColor, NULL),
280 MakeInlet("background-gradient-angle", InletTypeInteger, &self->backgroundGradientAngle, NULL),
281 MakeInlet("background-gradient-color", InletTypeColor, &self->backgroundGradientColor, NULL),
282 MakeInlet("border-color", InletTypeColor, &self->borderColor, NULL),
283 MakeInlet("border-radius", InletTypeInteger, &self->borderRadius, NULL),
284 MakeInlet("border-width", InletTypeInteger, &self->borderWidth, NULL),
285 MakeInlet("clips-subviews", InletTypeBool, &self->clipsSubviews, NULL),
286 MakeInlet("corner-cut", InletTypeRectangle, &self->cornerCut, NULL),
287 MakeInlet("corner-cut-top-left", InletTypeInteger, &self->cornerCut.topLeft, NULL),
288 MakeInlet("corner-cut-top-right", InletTypeInteger, &self->cornerCut.topRight, NULL),
289 MakeInlet("corner-cut-bottom-right", InletTypeInteger, &self->cornerCut.bottomRight, NULL),
290 MakeInlet("corner-cut-bottom-left", InletTypeInteger, &self->cornerCut.bottomLeft, NULL),
291 MakeInlet("height", InletTypeInteger, &self->frame.h, NULL),
292 MakeInlet("left", InletTypeInteger, &self->frame.x, NULL),
293 MakeInlet("max-height", InletTypeInteger, &self->maxSize.h, NULL),
294 MakeInlet("max-size", InletTypeSize, &self->maxSize, NULL),
295 MakeInlet("max-width", InletTypeInteger, &self->maxSize.w, NULL),
296 MakeInlet("min-height", InletTypeInteger, &self->minSize.h, NULL),
297 MakeInlet("min-size", InletTypeSize, &self->minSize, NULL),
298 MakeInlet("min-width", InletTypeInteger, &self->minSize.w, NULL),
299 MakeInlet("padding", InletTypeRectangle, &self->padding, NULL),
300 MakeInlet("padding-top", InletTypeInteger, &self->padding.top, NULL),
301 MakeInlet("padding-right", InletTypeInteger, &self->padding.right, NULL),
302 MakeInlet("padding-bottom", InletTypeInteger, &self->padding.bottom, NULL),
303 MakeInlet("padding-left", InletTypeInteger, &self->padding.left, NULL),
304 MakeInlet("pointer-events", InletTypeEnum, &self->pointerEvents, (ident) ViewPointerEventsNames),
305 MakeInlet("stretch", InletTypeBool, &self->stretch, NULL),
306 MakeInlet("top", InletTypeInteger, &self->frame.y, NULL),
307 MakeInlet("visibility", InletTypeEnum, &self->visibility, (ident) ViewVisibilityNames),
308 MakeInlet("width", InletTypeInteger, &self->frame.w, NULL)
309 );
310
311 const ViewVisibility visibility = self->visibility;
312 const bool stretch = self->stretch;
313
314 $(self, bind, inlets, style->attributes);
315
316 if ((self->visibility != visibility || self->stretch != stretch) && self->superview) {
317 $(self->superview, setNeedsLayout);
318 }
319
321 $(style->attributes, objectForKeyPath, "left")) {
322 $(self, warn, WarningTypeStyle, "`left` is overruled by the horizontal `alignment`");
323 }
324
325 if ((self->alignment & ViewAlignmentMaskVertical) &&
326 $(style->attributes, objectForKeyPath, "top")) {
327 $(self, warn, WarningTypeStyle, "`top` is overruled by the vertical `alignment`");
328 }
329}
@ InletTypeEnum
Definition View+JSON.h:75
@ InletTypeBool
Definition View+JSON.h:46
@ InletTypeInteger
Definition View+JSON.h:89
@ InletTypeColor
Definition View+JSON.h:62
@ InletTypeSize
Definition View+JSON.h:104
@ InletTypeRectangle
Definition View+JSON.h:99
#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
const EnumName ViewAlignmentNames[]
Definition View.c:63
const EnumName ViewPointerEventsNames[]
Definition View.c:52
static void warn(View *self, WarningType type, const char *fmt,...)
Definition View.c:2186
const EnumName ViewAutoresizingNames[]
Definition View.c:83
const EnumName ViewVisibilityNames[]
Definition View.c:57
ViewVisibility
Visibility constants.
Definition View.h:119
#define ViewAlignmentMaskHorizontal
Definition View.h:55
#define ViewAlignmentMaskVertical
Definition View.h:52
@ WarningTypeStyle
Definition Warning.h:34
Inlets enable inbound data binding of View attributes through JSON.
Definition View+JSON.h:149
Dictionary * attributes
Definition Style.h:59
int bottomRight
Definition View.h:192
int bottomLeft
Definition View.h:192
int topRight
Definition View.h:192
int topLeft
Definition View.h:192
bool clipsSubviews
If true, subviews will be clipped to this View's frame.
Definition View.h:309
ViewAlignment alignment
The alignment.
Definition View.h:242
ViewCornerCut cornerCut
The horizontal inset of each corner of the background and border.
Definition View.h:322
SDL_Color borderColor
The border color.
Definition View.h:275
int autoresizingMask
The ViewAutoresizing bitmask.
Definition View.h:248
ViewPointerEvents pointerEvents
Whether this View is the result of a hit test; its subviews always are.
Definition View.h:408
ViewPadding padding
The padding.
Definition View.h:398
int borderWidth
The border width.
Definition View.h:287
SDL_Size minSize
The minimum size this View may be resized to during layout.
Definition View.h:345
int backgroundGradientAngle
The angle of the background gradient, in degrees, clockwise from south: 0 (the default) fills downwar...
Definition View.h:261
ViewVisibility visibility
Whether this View is drawn, and contributes to its superview's size.
Definition View.h:468
int borderRadius
The corner radius applied to the background, border and bevel.
Definition View.h:281
SDL_Color backgroundGradientColor
The far color of the background gradient, which runs from View::backgroundColor.
Definition View.h:269
SDL_Size maxSize
The maximum size this View may be resized to during layout.
Definition View.h:339
SDL_Color backgroundColor
The background color.
Definition View.h:254
bool stretch
Whether this View takes a share of the space its StackView leaves along its axis.
Definition View.h:436
SDL_Rect frame
The frame, relative to the superview.
Definition View.h:301
int top
Definition View.h:170
int bottom
Definition View.h:170
int right
Definition View.h:170
int left
Definition View.h:170

◆ applyTheme()

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

Definition at line 335 of file View.c.

335 {
336
337 assert(theme);
338
339 Style *computedStyle = $(theme, computeStyle, self);
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
static void applyStyle(View *self, const Style *style)
Definition View.c:272
The Style type.
Definition Style.h:43
Style * style
The element-level Style of this View.
Definition View.h:425
Style * computedStyle
The computed Style of this View.
Definition View.h:314

◆ applyThemeIfNeeded()

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

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 clearWarnings(const View *self, WarningType type)
Definition View.c:598
static void enumerateSubviews(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:904
static void applyTheme(View *self, const Theme *theme)
Definition View.c:335
static void _applyThemeIfNeeded(View *view, ident data)
ViewEnumerator adapter for applyThemeIfNeeded.
Definition View.c:365
bool needsApplyTheme
If true, this View will apply the Theme before it is drawn.
Definition View.h:353

◆ attachStylesheet()

static void attachStylesheet ( View *  self,
SDL_Window *  window 
)
static

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
Stylesheet * stylesheet
An optional Stylesheet.
Definition View.h:443

◆ awakeWithCharacters()

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

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}
static void awakeWithData(View *self, const Data *data)
Definition View.c:426

◆ awakeWithData()

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

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
static View * init(View *self)
Definition View.c:1039
static void awakeWithDictionary(View *self, const Dictionary *dictionary)
Definition View.c:445

◆ awakeWithDictionary()

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

Definition at line 445 of file View.c.

445 {
446
447 assert(dictionary);
448
449 const Inlet inlets[] = MakeInlets(
450 MakeInlet("identifier", InletTypeCharacters, &self->identifier, NULL),
451 MakeInlet("classNames", InletTypeClassNames, &self, NULL),
452 MakeInlet("style", InletTypeStyle, &self, NULL),
453 MakeInlet("subviews", InletTypeSubviews, &self, NULL)
454 );
455
456 $(self, bind, inlets, dictionary);
457}
@ InletTypeSubviews
Definition View+JSON.h:116
@ InletTypeStyle
Definition View+JSON.h:110
@ InletTypeCharacters
Definition View+JSON.h:52
@ InletTypeClassNames
Definition View+JSON.h:57

◆ awakeWithResource()

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

Definition at line 463 of file View.c.

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

◆ awakeWithResourceName()

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

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
static void awakeWithResource(View *self, const Resource *resource)
Definition View.c:463

◆ becomeKeyResponder()

static void becomeKeyResponder ( View *  self)
static

Definition at line 487 of file View.c.

487 {
488
489 assert(self->window);
490
491 if (!$(self, isKeyResponder)) {
492 SDL_PropertiesID props = SDL_GetWindowProperties(self->window);
493
494 View *keyResponder = SDL_GetPointerProperty(props, "keyResponder", NULL);
495 if (keyResponder) {
497 }
498
499 String *path = $(self, path);
500 MVC_LogDebug("%s\n", path->chars);
501 release(path);
502
503 SDL_SetPointerProperty(props, "keyResponder", self);
504 }
505}
#define MVC_LogDebug(fmt,...)
Definition Log.h:48
static String * path(const View *self)
Definition View.c:1378
static void resignKeyResponder(View *self)
Definition View.c:1676
static bool isKeyResponder(const View *self)
Definition View.c:1126
static View * keyResponder(const WindowController *self)

◆ becomeTouchResponder()

static void becomeTouchResponder ( View *  self)
static

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}
static bool isTouchResponder(const View *self)
Definition View.c:1139
static void resignTouchResponder(View *self)
Definition View.c:1692
static View * touchResponder(const WindowController *self)

◆ bounds()

static SDL_Rect bounds ( const View *  self)
static

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}
static SDL_Size size(const View *self)
Definition View.c:1878
static SDL_Rect bounds(const View *self)
Definition View.c:552

◆ bringSubviewToFront()

static void bringSubviewToFront ( View *  self,
View *  subview 
)
static

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}

◆ clearWarnings()

static void clearWarnings ( const View *  self,
WarningType  type 
)
static

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

◆ clearWarnings_predicate()

static bool clearWarnings_predicate ( const ident  obj,
ident  data 
)
static

Filter Predicate for clearWarnings.

Definition at line 586 of file View.c.

586 {
587
588 const Warning *warning = obj;
589 const WarningType type = *(WarningType *) data;
590
591 return (warning->type & type) == 0;
592}
WarningType
Warning types.
Definition Warning.h:33
The Warning type.
Definition Warning.h:50
WarningType type
The WarningType.
Definition Warning.h:66

◆ clippingFrame()

static SDL_Rect clippingFrame ( const View *  self)
static

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) {
627 superview = superview->superview;
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
static SDL_Rect renderFrame(const View *self)
Definition View.c:1629
static SDL_Rect clippingFrame(const View *self)
Definition View.c:606

◆ containsPoint()

static bool containsPoint ( const View *  self,
const SDL_Point *  point 
)
static

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}

◆ cornerCutPoints()

static void cornerCutPoints ( SDL_Point *  points,
const SDL_Rect *  rect,
const ViewCornerCut *  cut 
)
static

Writes the four corners of rect, inset by cut, in clockwise order.

Each inset pulls its corner in along the x axis, so an inset on one of a pair of vertically adjacent corners slants the edge between them. The two insets on an edge are clamped against each other as well as the width, so however large a cut is the edge closes to a point rather than crossing over itself.

Definition at line 1496 of file View.c.

1496 {
1497
1498 const int x1 = rect->x, y1 = rect->y;
1499 const int x2 = rect->x + rect->w, y2 = rect->y + rect->h;
1500
1501 const int w = rect->w;
1502
1503 const int topLeft = clamp(cut->topLeft, 0, w);
1504 const int topRight = clamp(cut->topRight, 0, w - topLeft);
1505
1506 const int bottomLeft = clamp(cut->bottomLeft, 0, w);
1507 const int bottomRight = clamp(cut->bottomRight, 0, w - bottomLeft);
1508
1509 points[0] = MakePoint(x1 + topLeft, y1);
1510 points[1] = MakePoint(x2 - topRight, y1);
1511 points[2] = MakePoint(x2 - bottomRight, y2);
1512 points[3] = MakePoint(x1 + bottomLeft, y2);
1513}

◆ dealloc()

static void dealloc ( Object *  self)
static
See also
Object::dealloc(Object *)

Definition at line 118 of file View.c.

118 {
119
120 View *this = (View *) self;
121
122 SDL_FilterEvents(filterViewEvents, this);
123
124 $(this, moveToWindow, NULL);
125
126 $(this, enumerateSubviews, nullifySuperview, NULL);
127
128 free(this->identifier);
129
130 release(this->classNames);
131 release(this->computedStyle);
132 release(this->style);
133 release(this->stylesheet);
134 release(this->subviews);
135 release(this->warnings);
136
137 this->superview = NULL;
138
139 super(Object, self, dealloc);
140}
static bool filterViewEvents(void *data, SDL_Event *event)
Definition View.c:99
static void nullifySuperview(View *subview, ident data)
ViewEnumerator to null out superview pointers during parent dealloc.
Definition View.c:111
static void dealloc(Object *self)
Definition View.c:118

◆ depth()

static int depth ( const View *  self)
static

Definition at line 658 of file View.c.

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

◆ descendantWithIdentifier()

static View * descendantWithIdentifier ( const View *  self,
const char *  identifier 
)
static

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}
static View * descendantWithIdentifier(const View *self, const char *identifier)
Definition View.c:666

◆ description()

static String * description ( const Object *  self)
static
See also
Object::description(const Object *)

Definition at line 145 of file View.c.

145 {
146
147 View *this = (View *) self;
148 const SDL_Rect bounds = $(this, bounds);
149
150 String *classNames = $((Object *) this->classNames, description);
151 String *description = str("%s@%p %s [%d, %d, %d, %d]",
152 this->identifier ?: classnameof(self),
153 self,
154 classNames->chars,
155 bounds.x, bounds.y, bounds.w, bounds.h);
156
157 release(classNames);
158 return description;
159}
static String * description(const Object *self)
Definition View.c:145

◆ detachStylesheet()

static void detachStylesheet ( View *  self,
SDL_Window *  window 
)
static

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()

static void didMoveToWindow ( View *  self,
SDL_Window *  window 
)
static

Definition at line 709 of file View.c.

709 {
710
711 if (window) {
712 $(self, attachStylesheet, window);
713
714 if (self->superview == NULL) {
715 $(self, sizeToFill);
716 }
717
718 $(self, setNeedsLayout);
719 }
720}
static void sizeToFill(View *self)
Definition View.c:2007
static void attachStylesheet(View *self, SDL_Window *window)
Definition View.c:397

◆ didReceiveEvent()

static bool didReceiveEvent ( const View *  self,
const SDL_Event *  event 
)
static

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}
static bool isVisible(const View *self)
Definition View.c:1152
static bool containsPoint(const View *self, const SDL_Point *point)
Definition View.c:647

◆ draw()

static void draw ( View *  self,
Renderer *  renderer 
)
static

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
@ ViewVisibilityHidden
Definition View.h:122

◆ emitViewEvent()

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

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}
Uint32 MVC_VIEW_EVENT
Definition View.c:37

◆ enumerate()

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

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}
static void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:866

◆ enumerateAdjacent()

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

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()

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

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()

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

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()

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

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 void enumerateSelection(View *self, const char *rule, ViewEnumerator enumerator, ident data)
Definition View.c:853

◆ enumerateSiblings()

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

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()

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

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()

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

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()

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

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}
static void enumerateVisible(View *self, ViewEnumerator enumerator, ident data)
Definition View.c:931

◆ filterViewEvents()

static bool filterViewEvents ( void *  data,
SDL_Event *  event 
)
static

SDL_EventFilter to purge any MVC_VIEW_EVENTs for this View.

Definition at line 99 of file View.c.

99 {
100
101 if (event->type == MVC_VIEW_EVENT && event->user.data1 == data) {
102 return false;
103 }
104
105 return true;
106}

◆ hasClassName()

static bool hasClassName ( const View *  self,
const char *  className 
)
static

Definition at line 958 of file View.c.

958 {
959
960 if (className) {
961 return $((Set *) self->classNames, containsObjectMatching, hasClassName_predicate, (ident) className);
962 }
963
964 return false;
965}
static bool hasClassName_predicate(const ident obj, ident data)
Predicate for hasClassName.
Definition View.c:950

◆ hasClassName_predicate()

static bool hasClassName_predicate ( const ident  obj,
ident  data 
)
static

Predicate for hasClassName.

Definition at line 950 of file View.c.

950 {
951 return strcmp(((String *) obj)->chars, (const char *) data) == 0;
952}

◆ hasOverflow()

static bool hasOverflow ( const View *  self)
static

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

◆ hasOverflow_enumerate()

static void hasOverflow_enumerate ( View *  view,
ident  data 
)
static

ViewEnumerator for hasOverflow.

Definition at line 975 of file View.c.

975 {
976
977 Overflow *overflow = data;
978
979 if (view->visibility != ViewVisibilityHidden) {
980
981 const SDL_Rect bounds = $(view, bounds);
982
983 if (bounds.x + bounds.w > overflow->bounds.w || bounds.y + bounds.h > overflow->bounds.h) {
984
985 overflow->hasOverflow = true;
986
987 $(view, warn, WarningTypeLayout, "Exceeds superview bounds [%d %d %d %d]",
988 overflow->bounds.x, overflow->bounds.y, overflow->bounds.w, overflow->bounds.h);
989 }
990 }
991}
@ WarningTypeLayout
Definition Warning.h:35

◆ hitTest()

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

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}
static View * hitTest(const View *self, const SDL_Point *point)
Definition View.c:1012
@ ViewPointerEventsAuto
Definition View.h:110

◆ init()

static View * init ( View *  self)
static

Definition at line 1039 of file View.c.

1039 {
1040 return $(self, initWithFrame, NULL);
1041}
static View * initWithFrame(View *self, const SDL_Rect *frame)
Definition View.c:1047

◆ initialize()

static void initialize ( Class *  clazz)
static
See also
Class::initialize(Class *)

Definition at line 2222 of file View.c.

2222 {
2223
2224 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
2225 ((ObjectInterface *) clazz->interface)->description = description;
2226
2227 ((ViewInterface *) clazz->interface)->acceptsKeyResponder = acceptsKeyResponder;
2228 ((ViewInterface *) clazz->interface)->acceptsTouchResponder = acceptsTouchResponder;
2229 ((ViewInterface *) clazz->interface)->addClassName = addClassName;
2230 ((ViewInterface *) clazz->interface)->addSubview = addSubview;
2231 ((ViewInterface *) clazz->interface)->addSubviewRelativeTo = addSubviewRelativeTo;
2232 ((ViewInterface *) clazz->interface)->ancestorWithIdentifier = ancestorWithIdentifier;
2233 ((ViewInterface *) clazz->interface)->applyStyle = applyStyle;
2234 ((ViewInterface *) clazz->interface)->applyTheme = applyTheme;
2235 ((ViewInterface *) clazz->interface)->applyThemeIfNeeded = applyThemeIfNeeded;
2236 ((ViewInterface *) clazz->interface)->attachStylesheet = attachStylesheet;
2237 ((ViewInterface *) clazz->interface)->awakeWithCharacters = awakeWithCharacters;
2238 ((ViewInterface *) clazz->interface)->awakeWithData = awakeWithData;
2239 ((ViewInterface *) clazz->interface)->awakeWithDictionary = awakeWithDictionary;
2240 ((ViewInterface *) clazz->interface)->awakeWithResource = awakeWithResource;
2241 ((ViewInterface *) clazz->interface)->awakeWithResourceName = awakeWithResourceName;
2242 ((ViewInterface *) clazz->interface)->becomeKeyResponder = becomeKeyResponder;
2243 ((ViewInterface *) clazz->interface)->becomeTouchResponder = becomeTouchResponder;
2244 ((ViewInterface *) clazz->interface)->bind = _bind;
2245 ((ViewInterface *) clazz->interface)->bounds = bounds;
2246 ((ViewInterface *) clazz->interface)->bringSubviewToFront = bringSubviewToFront;
2247 ((ViewInterface *) clazz->interface)->clearWarnings = clearWarnings;
2248 ((ViewInterface *) clazz->interface)->clippingFrame = clippingFrame;
2249 ((ViewInterface *) clazz->interface)->containsPoint = containsPoint;
2250 ((ViewInterface *) clazz->interface)->depth = depth;
2251 ((ViewInterface *) clazz->interface)->descendantWithIdentifier = descendantWithIdentifier;
2252 ((ViewInterface *) clazz->interface)->detachStylesheet = detachStylesheet;
2253 ((ViewInterface *) clazz->interface)->didMoveToWindow = didMoveToWindow;
2254 ((ViewInterface *) clazz->interface)->didReceiveEvent = didReceiveEvent;
2255 ((ViewInterface *) clazz->interface)->draw = draw;
2256 ((ViewInterface *) clazz->interface)->emitViewEvent = emitViewEvent;
2257 ((ViewInterface *) clazz->interface)->enumerate = enumerate;
2258 ((ViewInterface *) clazz->interface)->enumerateAdjacent = enumerateAdjacent;
2259 ((ViewInterface *) clazz->interface)->enumerateAncestors = enumerateAncestors;
2260 ((ViewInterface *) clazz->interface)->enumerateDescendants = enumerateDescendants;
2261 ((ViewInterface *) clazz->interface)->enumerateSelection = enumerateSelection;
2262 ((ViewInterface *) clazz->interface)->enumerateSiblings = enumerateSiblings;
2263 ((ViewInterface *) clazz->interface)->enumerateSubviews = enumerateSubviews;
2264 ((ViewInterface *) clazz->interface)->enumerateSuperview = enumerateSuperview;
2265 ((ViewInterface *) clazz->interface)->enumerateVisible = enumerateVisible;
2266 ((ViewInterface *) clazz->interface)->hasClassName = hasClassName;
2267 ((ViewInterface *) clazz->interface)->hasOverflow = hasOverflow;
2268 ((ViewInterface *) clazz->interface)->hitTest = hitTest;
2269 ((ViewInterface *) clazz->interface)->init = init;
2270 ((ViewInterface *) clazz->interface)->initWithFrame = initWithFrame;
2271 ((ViewInterface *) clazz->interface)->invalidateStyle = invalidateStyle;
2272 ((ViewInterface *) clazz->interface)->isContainer = isContainer;
2273 ((ViewInterface *) clazz->interface)->isDescendantOfView = isDescendantOfView;
2274 ((ViewInterface *) clazz->interface)->isKeyResponder = isKeyResponder;
2275 ((ViewInterface *) clazz->interface)->isTouchResponder = isTouchResponder;
2276 ((ViewInterface *) clazz->interface)->isVisible = isVisible;
2277 ((ViewInterface *) clazz->interface)->layoutIfNeeded = layoutIfNeeded;
2278 ((ViewInterface *) clazz->interface)->layoutSubviews = layoutSubviews;
2279 ((ViewInterface *) clazz->interface)->layoutWithConstraint = layoutWithConstraint;
2280 ((ViewInterface *) clazz->interface)->layoutWithSize = layoutWithSize;
2281 ((ViewInterface *) clazz->interface)->matchesSelector = matchesSelector;
2282 ((ViewInterface *) clazz->interface)->moveToWindow = moveToWindow;
2283 ((ViewInterface *) clazz->interface)->path = path;
2284 ((ViewInterface *) clazz->interface)->removeAllClassNames = removeAllClassNames;
2285 ((ViewInterface *) clazz->interface)->removeAllSubviews = removeAllSubviews;
2286 ((ViewInterface *) clazz->interface)->removeClassName = removeClassName;
2287 ((ViewInterface *) clazz->interface)->removeFromSuperview = removeFromSuperview;
2288 ((ViewInterface *) clazz->interface)->removeSubview = removeSubview;
2289 ((ViewInterface *) clazz->interface)->render = render;
2290 ((ViewInterface *) clazz->interface)->renderDeviceDidReset = renderDeviceDidReset;
2291 ((ViewInterface *) clazz->interface)->renderDeviceWillReset = renderDeviceWillReset;
2292 ((ViewInterface *) clazz->interface)->renderFrame = renderFrame;
2293 ((ViewInterface *) clazz->interface)->replaceSubview = replaceSubview;
2294 ((ViewInterface *) clazz->interface)->resignKeyResponder = resignKeyResponder;
2295 ((ViewInterface *) clazz->interface)->resignTouchResponder = resignTouchResponder;
2296 ((ViewInterface *) clazz->interface)->resize = resize;
2297 ((ViewInterface *) clazz->interface)->resolve = resolve;
2298 ((ViewInterface *) clazz->interface)->respondToEvent = respondToEvent;
2299 ((ViewInterface *) clazz->interface)->select = _select;
2300 ((ViewInterface *) clazz->interface)->selectFirst = selectFirst;
2301 ((ViewInterface *) clazz->interface)->setVisibility = setVisibility;
2302 ((ViewInterface *) clazz->interface)->setNeedsApplyTheme = setNeedsApplyTheme;
2303 ((ViewInterface *) clazz->interface)->setNeedsLayout = setNeedsLayout;
2304 ((ViewInterface *) clazz->interface)->size = size;
2305 ((ViewInterface *) clazz->interface)->sizeThatContains = sizeThatContains;
2306 ((ViewInterface *) clazz->interface)->sizeThatFills = sizeThatFills;
2307 ((ViewInterface *) clazz->interface)->sizeThatFits = sizeThatFits;
2308 ((ViewInterface *) clazz->interface)->sizeThatSatisfies = sizeThatSatisfies;
2309 ((ViewInterface *) clazz->interface)->sizeToContain = sizeToContain;
2310 ((ViewInterface *) clazz->interface)->sizeToFill = sizeToFill;
2311 ((ViewInterface *) clazz->interface)->sizeToFit = sizeToFit;
2312 ((ViewInterface *) clazz->interface)->sizeToSatisfy = sizeToSatisfy;
2313 ((ViewInterface *) clazz->interface)->subviewWithIdentifier = subviewWithIdentifier;
2314 ((ViewInterface *) clazz->interface)->updateBindings = updateBindings;
2315 ((ViewInterface *) clazz->interface)->viewport = viewport;
2316 ((ViewInterface *) clazz->interface)->viewWithCharacters = viewWithCharacters;
2317 ((ViewInterface *) clazz->interface)->viewWithData = viewWithData;
2318 ((ViewInterface *) clazz->interface)->viewWithDictionary = viewWithDictionary;
2319 ((ViewInterface *) clazz->interface)->viewWithResource = viewWithResource;
2320 ((ViewInterface *) clazz->interface)->viewWithResourceName = viewWithResourceName;
2321 ((ViewInterface *) clazz->interface)->visibleSubviews = visibleSubviews;
2322 ((ViewInterface *) clazz->interface)->warn = warn;
2323 ((ViewInterface *) clazz->interface)->willMoveToWindow = willMoveToWindow;
2324
2325 MVC_NOTIFICATION_EVENT = SDL_RegisterEvents(1);
2326 assert(MVC_NOTIFICATION_EVENT != 0);
2327
2328 MVC_VIEW_EVENT = SDL_RegisterEvents(1);
2329 assert(MVC_VIEW_EVENT != 0);
2330}
static View * viewWithResource(const Resource *resource, Outlet *outlets)
Definition View.c:2142
static void removeClassName(View *self, const char *className)
Definition View.c:1445
static void addClassName(View *self, const char *className)
Definition View.c:183
static View * selectFirst(View *self, const char *rule)
Definition View.c:1819
static bool isContainer(const View *self)
Definition View.c:1100
static void didMoveToWindow(View *self, SDL_Window *window)
Definition View.c:709
static bool isDescendantOfView(const View *self, const View *view)
Definition View.c:1108
static void becomeKeyResponder(View *self)
Definition View.c:487
static void resize(View *self, const SDL_Size *size)
Definition View.c:1708
static SDL_Size sizeThatSatisfies(View *self, ViewConstraint width, ViewConstraint height)
Definition View.c:1979
static void detachStylesheet(View *self, SDL_Window *window)
Definition View.c:693
static void layoutIfNeeded(View *self)
Definition View.c:1174
static void sizeToContain(View *self)
Definition View.c:1996
static bool acceptsKeyResponder(const View *self)
Definition View.c:167
static Set * _select(View *self, const char *rule)
Definition View.c:1804
static void enumerateAncestors(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:840
static SDL_Size sizeThatFills(const View *self)
Definition View.c:1898
static void removeAllClassNames(View *self)
Definition View.c:1419
static void removeSubview(View *self, View *subview)
Definition View.c:1473
static void layoutWithConstraint(View *self, ViewConstraint width, ViewConstraint height)
Definition View.c:1254
static View * viewWithResourceName(const char *name, Outlet *outlets)
Definition View.c:2153
static void becomeTouchResponder(View *self)
Definition View.c:511
static void respondToEvent(View *self, const SDL_Event *event)
Definition View.c:1752
static void replaceSubview(View *self, View *subview, View *replacement)
Definition View.c:1663
static bool matchesSelector(const View *self, const SimpleSelector *simpleSelector)
Definition View.c:1280
static SDL_Size sizeThatFits(const View *self)
Definition View.c:1914
static void bringSubviewToFront(View *self, View *subview)
Definition View.c:570
static bool didReceiveEvent(const View *self, const SDL_Event *event)
Definition View.c:726
static View * subviewWithIdentifier(const View *self, const char *identifier)
Definition View.c:2040
static bool hasOverflow(const View *self)
Definition View.c:997
static Array * visibleSubviews(const View *self)
Definition View.c:2178
static void sizeToSatisfy(View *self, ViewConstraint width, ViewConstraint height)
Definition View.c:2029
static void awakeWithCharacters(View *self, const char *chars)
Definition View.c:413
static void updateBindings(View *self, ident data)
Definition View.c:2070
static void removeAllSubviews(View *self)
Definition View.c:1437
static SDL_Size sizeThatContains(const View *self)
Definition View.c:1886
static void render(View *self, Renderer *renderer)
Definition View.c:1519
static void setVisibility(View *self, ViewVisibility visibility)
Definition View.c:1834
static void awakeWithResourceName(View *self, const char *name)
Definition View.c:474
static void layoutWithSize(View *self, const SDL_Size *size)
Definition View.c:1267
static void addSubview(View *self, View *subview)
Definition View.c:201
static View * viewWithData(const Data *data, Outlet *outlets)
Definition View.c:2106
static View * viewWithCharacters(const char *chars, Outlet *outlets)
Definition View.c:2091
static bool acceptsTouchResponder(const View *self)
Definition View.c:175
static void renderDeviceWillReset(View *self)
Definition View.c:1621
static bool _bind(View *self, const Inlet *inlets, const Dictionary *dictionary)
Definition View.c:535
static void willMoveToWindow(View *self, SDL_Window *window)
Definition View.c:2208
Uint32 MVC_NOTIFICATION_EVENT
Definition View.c:36
static void renderDeviceDidReset(View *self)
Definition View.c:1606
static void enumerateSuperview(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:918
static void layoutSubviews(View *self)
Definition View.c:1207
static void enumerate(View *self, ViewEnumerator enumerator, ident data)
Definition View.c:807
static void enumerateAdjacent(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:820
static SDL_Rect viewport(const View *self)
Definition View.c:2078
static bool hasClassName(const View *self, const char *className)
Definition View.c:958
static void sizeToFit(View *self)
Definition View.c:2018
static void enumerateSiblings(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:884
static View * viewWithDictionary(const Dictionary *dictionary, Outlet *outlets)
Definition View.c:2127
static View * ancestorWithIdentifier(const View *self, const char *identifier)
Definition View.c:251
static void resolve(View *self, Outlet *outlets)
Definition View.c:1732
static void emitViewEvent(View *self, ViewEvent code, ident data)
Definition View.c:794
void invalidateStyle(View *self)
Invalidates the computed Style for this View and its descendants.
Definition View.c:1092
void setVisibility(View *self, ViewVisibility visibility)
Sets this View's visibility.
Definition View.c:1834
View * viewWithResource(const Resource *resource, Outlet *outlets)
Instantiates a View initialized with the JSON data in resource.
Definition View.c:2142
Array * visibleSubviews(const View *self)
Definition PageView.c:92
View * viewWithResourceName(const char *name, Outlet *outlets)
Instantiates a View initialized with the JSON Resource with the specified name.
Definition View.c:2153
void applyStyle(View *self, const Style *style)
Applies the given Style to this View.
void detachStylesheet(View *self, SDL_Window *window)
Detaches this View's Stylesheet from the Theme associated with the given window.
Definition View.c:693
void updateBindings(View *self, ident data)
Updates data bindings, prompting the appropriate layout changes.
View * viewWithData(const Data *data, Outlet *outlets)
Instantiates a View initialized with the contents of data.
Definition View.c:2106
View * init(View *self)
Initializes this View.
Definition Box.c:67
View * initWithFrame(View *self, const SDL_Rect *frame)
Initializes this View with the specified frame.
Definition View.c:1047
View * viewWithDictionary(const Dictionary *dictionary, Outlet *outlets)
Instantiates a View initialized with the attributes described in dictionary.
Definition View.c:2127

◆ initWithFrame()

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

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()

static void invalidateStyle ( View *  self)
static

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

◆ invalidateStyle_enumerate()

static void invalidateStyle_enumerate ( View *  view,
ident  data 
)
static

ViewEnumerator for invalidateStyle.

Definition at line 1081 of file View.c.

1081 {
1082
1083 view->needsApplyStyle = true;
1084
1085 $(view, setNeedsApplyTheme);
1086}

◆ isContainer()

static bool isContainer ( const View *  self)
static

Definition at line 1100 of file View.c.

1100 {
1102}
@ ViewAutoresizingContain
Definition View.h:95
@ ViewAutoresizingFit
Definition View.h:94

◆ isDescendantOfView()

static bool isDescendantOfView ( const View *  self,
const View *  view 
)
static

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()

static bool isKeyResponder ( const View *  self)
static

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()

static bool isTouchResponder ( const View *  self)
static

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()

static bool isVisible ( const View *  self)
static

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()

static void layoutIfNeeded ( View *  self)
static

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

◆ layoutIfNeeded_enumerate()

static void layoutIfNeeded_enumerate ( View *  subview,
ident  data 
)
static

ViewEnumerator for layoutIfNeeded recursion.

Definition at line 1166 of file View.c.

1166 {
1167 $(subview, layoutIfNeeded);
1168}

◆ layoutSubviews()

static void layoutSubviews ( View *  self)
static

Definition at line 1207 of file View.c.

1207 {
1208
1209 const SDL_Rect bounds = $(self, bounds);
1210
1211 const Array *subviews = (Array *) self->subviews;
1212 for (size_t i = 0; i < subviews->count; i++) {
1213
1214 View *subview = subviews->elements[i];
1215
1217 MakeConstraint(ViewConstraintEqual, bounds.w) : MakeConstraint(ViewConstraintUnspecified, 0);
1218
1220 MakeConstraint(ViewConstraintEqual, bounds.h) : MakeConstraint(ViewConstraintUnspecified, 0);
1221
1222 $(subview, layoutWithConstraint, w, h);
1223
1224 switch (subview->alignment & ViewAlignmentMaskHorizontal) {
1225 case ViewAlignmentLeft:
1226 subview->frame.x = 0;
1227 break;
1229 subview->frame.x = (bounds.w - subview->frame.w) * 0.5f;
1230 break;
1231 case ViewAlignmentRight:
1232 subview->frame.x = bounds.w - subview->frame.w;
1233 break;
1234 }
1235
1236 switch (subview->alignment & ViewAlignmentMaskVertical) {
1238 subview->frame.y = 0;
1239 break;
1241 subview->frame.y = (bounds.h - subview->frame.h) * 0.5f;
1242 break;
1244 subview->frame.y = bounds.h - subview->frame.h;
1245 break;
1246 }
1247 }
1248}
#define ViewAlignmentMaskBottom
Definition View.h:46
#define ViewAlignmentMaskTop
Definition View.h:44
#define ViewAlignmentMaskMiddle
Definition View.h:45
@ ViewAutoresizingWidth
Definition View.h:91
@ ViewAutoresizingHeight
Definition View.h:92
@ ViewAlignmentCenter
Definition View.h:70
@ ViewAlignmentLeft
Definition View.h:69
@ ViewAlignmentRight
Definition View.h:71

◆ layoutWithConstraint()

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

Definition at line 1254 of file View.c.

1254 {
1255
1256 $(self, sizeToSatisfy, width, height);
1258 $(self, layoutSubviews);
1259
1260 self->needsLayout = false;
1261}

◆ layoutWithSize()

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

Definition at line 1267 of file View.c.

1267 {
1268
1269 $(self, resize, size);
1271 $(self, layoutSubviews);
1272
1273 self->needsLayout = false;
1274}

◆ matchesSelector()

static bool matchesSelector ( const View *  self,
const SimpleSelector *  simpleSelector 
)
static

Definition at line 1280 of file View.c.

1280 {
1281
1282 assert(simpleSelector);
1283
1284 const char *pattern = simpleSelector->pattern;
1285
1286 switch (simpleSelector->type) {
1288 return false;
1289
1291 return true;
1292
1294 const Class *clazz = classForName(pattern);
1295 if (clazz) {
1296 return $((Object *) self, isKindOfClass, clazz);
1297 }
1298 }
1299 break;
1300
1302 return $(self, hasClassName, pattern);
1303
1305 if (self->identifier) {
1306 return strcmp(self->identifier, pattern) == 0;
1307 } else {
1308 return false;
1309 }
1310
1312 if (strcmp("first-child", pattern) == 0) {
1313 if (self->superview) {
1314 return $((Array *) self->superview->subviews, firstObject) == self;
1315 }
1316 } else if (strcmp("last-child", pattern) == 0) {
1317 if (self->superview) {
1318 return $((Array *) self->superview->subviews, lastObject) == self;
1319 }
1320 } else if (strcmp("nth-child(even)", pattern) == 0) {
1321 if (self->superview) {
1322 return ($((Array *) self->superview->subviews, indexOfObject, (ident) self) & 1) == 0;
1323 }
1324 } else if (strcmp("nth-child(odd)", pattern) == 0) {
1325 if (self->superview) {
1326 return $((Array *) self->superview->subviews, indexOfObject, (ident) self) & 1;
1327 }
1328 } else if (strcmp("hover", pattern) == 0) {
1329 float mx, my;
1330 SDL_GetMouseState(&mx, &my);
1331 SDL_Point point = MakePoint(mx, my);
1332 return $(self, containsPoint, &point);
1333 }
1334 break;
1335 }
1336
1337 return false;
1338}
@ SimpleSelectorTypePseudo
@ SimpleSelectorTypeId
@ SimpleSelectorTypeClass
@ SimpleSelectorTypeUniversal
@ SimpleSelectorTypeType
@ SimpleSelectorTypeNone
SimpleSelectorType type
The SimpleSelectorType.
char * pattern
The pattern, as provided by the user.

◆ moveToWindow()

static void moveToWindow ( View *  self,
SDL_Window *  window 
)
static

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
1371 $(self, enumerateSubviews, moveToWindow_enumerate, window);
1372}
static void moveToWindow_enumerate(View *subview, ident data)
ViewEnumerator for moveToWindow recursion.
Definition View.c:1343

◆ moveToWindow_enumerate()

static void moveToWindow_enumerate ( View *  subview,
ident  data 
)
static

ViewEnumerator for moveToWindow recursion.

Definition at line 1343 of file View.c.

1343 {
1344 $(subview, moveToWindow, data);
1345}

◆ MVC_InvalidateRenderFrames()

void MVC_InvalidateRenderFrames ( void  )

Invalidates every View's cached View::renderFrame and View::clippingFrame.

WindowController::renderTo invokes this after layout, before drawing, so that drawing and subsequent hit-testing observe post-layout frames; both methods memoize their result until the next invocation. Callers that mutate View frames outside of a layout pass MUST invoke this afterwards if hit-testing precision is required before the next render.

Definition at line 46 of file View.c.

46 {
47 if (++_renderFrameGeneration == 0) {
49 }
50}

◆ nullifySuperview()

static void nullifySuperview ( View *  subview,
ident  data 
)
static

ViewEnumerator to null out superview pointers during parent dealloc.

Definition at line 111 of file View.c.

111 {
112 subview->superview = NULL;
113}

◆ path()

static String * path ( const View *  self)
static

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()

static void removeAllClassNames ( View *  self)
static

Definition at line 1419 of file View.c.

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

◆ removeAllSubviews()

static void removeAllSubviews ( View *  self)
static

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

◆ removeAllSubviews_enumerate()

static void removeAllSubviews_enumerate ( const Array *  array,
ident  obj,
ident  data 
)
static

ArrayEnumerator for removeAllSubviews.

Definition at line 1429 of file View.c.

1429 {
1430 $((View *) data, removeSubview, obj);
1431}

◆ removeClassName()

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

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()

static void removeFromSuperview ( View *  self)
static

Definition at line 1462 of file View.c.

1462 {
1463
1464 if (self->superview) {
1465 $(self->superview, removeSubview, self);
1466 }
1467}

◆ removeSubview()

static void removeSubview ( View *  self,
View *  subview 
)
static

Definition at line 1473 of file View.c.

1473 {
1474
1475 assert(subview);
1476
1477 if (subview->superview == self) {
1478
1479 subview->superview = NULL;
1480
1481 $(subview, moveToWindow, NULL);
1482
1483 $(self->subviews, removeObject, subview);
1484
1485 $(self, setNeedsLayout);
1486 }
1487}

◆ render()

static void render ( View *  self,
Renderer *  renderer 
)
static

Definition at line 1519 of file View.c.

1519 {
1520
1521 assert(self->window);
1522
1523 if ($(self, hasClassName, "breakpoint")) {
1524 SDL_TriggerBreakpoint();
1525 }
1526
1527 const bool cut = !CornerCutIsEmpty(self->cornerCut);
1528
1529 if (self->backgroundColor.a || self->backgroundGradientColor.a) {
1530
1531 const SDL_Rect frame = $(self, renderFrame);
1532 const SDL_Color *gradient = self->backgroundGradientColor.a ? &self->backgroundGradientColor : NULL;
1533
1534 if (cut) {
1535 SDL_Point points[4];
1536 cornerCutPoints(points, &frame, &self->cornerCut);
1537
1538 $(renderer, drawPolygonFilled, points, lengthof(points), self->backgroundGradientAngle,
1539 &self->backgroundColor, gradient);
1540
1541 } else if (gradient) {
1542 $(renderer, drawRoundedRectGradientFilled, &frame, self->borderRadius,
1543 self->backgroundGradientAngle, &self->backgroundColor, gradient);
1544 } else if (self->borderRadius > 0) {
1545 $(renderer, drawRoundedRectFilled, &frame, self->borderRadius, &self->backgroundColor);
1546 } else {
1547 $(renderer, drawRectFilled, &frame, &self->backgroundColor);
1548 }
1549 }
1550
1551 if (self->borderWidth && self->borderColor.a) {
1552
1553 SDL_Rect frame = $(self, renderFrame);
1554
1555 if (cut) {
1556
1557 // The stroke is centered on the outline, so grow by half of it to sit outside the fill
1558 const int inset = self->borderWidth / 2;
1559
1560 frame.x -= inset;
1561 frame.y -= inset;
1562 frame.w += inset * 2;
1563 frame.h += inset * 2;
1564
1565 SDL_Point points[4];
1566 cornerCutPoints(points, &frame, &self->cornerCut);
1567
1568 $(renderer, drawPolygon, points, lengthof(points), self->borderWidth, &self->borderColor);
1569
1570 } else if (self->borderRadius > 0) {
1571
1572 // The border grows outward, so its inner edge shares the background's radius
1573 frame.x -= self->borderWidth;
1574 frame.y -= self->borderWidth;
1575 frame.w += self->borderWidth * 2;
1576 frame.h += self->borderWidth * 2;
1577
1578 $(renderer, drawRoundedRect, &frame, self->borderRadius + self->borderWidth, self->borderWidth, &self->borderColor);
1579
1580 } else {
1581
1582 for (int i = 0; i < self->borderWidth; i++) {
1583
1584 $(renderer, drawRect, &frame, &self->borderColor);
1585
1586 frame.x -= 1;
1587 frame.y -= 1;
1588 frame.w += 2;
1589 frame.h += 2;
1590 }
1591 }
1592 }
1593}
static void drawRoundedRectGradientFilled(const Renderer *self, const SDL_Rect *rect, int radius, int angle, const SDL_Color *from, const SDL_Color *to)
Definition Renderer.c:441
static void drawPolygon(const Renderer *self, const SDL_Point *points, size_t count, int width, const SDL_Color *color)
Definition Renderer.c:293
static void drawRoundedRect(const Renderer *self, const SDL_Rect *rect, int radius, int width, const SDL_Color *color)
Definition Renderer.c:407
static void drawRectFilled(const Renderer *self, const SDL_Rect *rect, const SDL_Color *color)
Definition Renderer.c:384
static void drawRect(const Renderer *self, const SDL_Rect *rect, const SDL_Color *color)
Definition Renderer.c:365
static void drawRoundedRectFilled(const Renderer *self, const SDL_Rect *rect, int radius, const SDL_Color *color)
Definition Renderer.c:424
static void drawPolygonFilled(const Renderer *self, const SDL_Point *points, size_t count, int angle, const SDL_Color *from, const SDL_Color *to)
Definition Renderer.c:310
static void cornerCutPoints(SDL_Point *points, const SDL_Rect *rect, const ViewCornerCut *cut)
Writes the four corners of rect, inset by cut, in clockwise order.
Definition View.c:1496
#define CornerCutIsEmpty(cut)
Definition View.h:204

◆ renderDeviceDidReset()

static void renderDeviceDidReset ( View *  self)
static

Definition at line 1606 of file View.c.

1606 {
1608}
static void renderDeviceDidReset_enumerate(View *subview, ident data)
ViewEnumerator for renderDeviceDidReset recursion.
Definition View.c:1598

◆ renderDeviceDidReset_enumerate()

static void renderDeviceDidReset_enumerate ( View *  subview,
ident  data 
)
static

ViewEnumerator for renderDeviceDidReset recursion.

Definition at line 1598 of file View.c.

1598 {
1599 $(subview, renderDeviceDidReset);
1600}

◆ renderDeviceWillReset()

static void renderDeviceWillReset ( View *  self)
static

Definition at line 1621 of file View.c.

1621 {
1623}
static void renderDeviceWillReset_enumerate(View *subview, ident data)
ViewEnumerator for renderDeviceWillReset recursion.
Definition View.c:1613

◆ renderDeviceWillReset_enumerate()

static void renderDeviceWillReset_enumerate ( View *  subview,
ident  data 
)
static

ViewEnumerator for renderDeviceWillReset recursion.

Definition at line 1613 of file View.c.

1613 {
1614 $(subview, renderDeviceWillReset);
1615}

◆ renderFrame()

static SDL_Rect renderFrame ( const View *  self)
static

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) {
1648 frame.x += superview->padding.left;
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

◆ replaceSubview()

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

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()

static void resignKeyResponder ( View *  self)
static

Definition at line 1676 of file View.c.

1676 {
1677
1678 if (self->window && $(self, isKeyResponder)) {
1679
1680 String *path = $(self, path);
1681 MVC_LogDebug("%s\n", path->chars);
1682 release(path);
1683
1684 SDL_SetPointerProperty(SDL_GetWindowProperties(self->window), "keyResponder", NULL);
1685 }
1686}

◆ resignTouchResponder()

static void resignTouchResponder ( View *  self)
static

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()

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

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

◆ resolve()

static void resolve ( View *  self,
Outlet *  outlets 
)
static

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}
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

◆ resolveViewConstraint()

static int resolveViewConstraint ( int  hasAutoresizingBit,
ViewConstraint  constraint,
int  intrinsic 
)
static

Resolves an axis's sizeThatFits value against an offered ViewConstraint, if the View has opted into that axis's autoresizing bit; otherwise returns the value unmodified.

Definition at line 1959 of file View.c.

1959 {
1960
1961 if (!hasAutoresizingBit) {
1962 return intrinsic;
1963 }
1964
1965 switch (constraint.mode) {
1966 case ViewConstraintEqual:
1967 return constraint.value;
1968 case ViewConstraintMax:
1969 return min(intrinsic, constraint.value);
1970 default:
1971 return intrinsic;
1972 }
1973}
int value
The constraint value; a size in pixels.
Definition View.h:157
enum ViewConstraint::@3 mode

◆ respondToEvent()

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

Definition at line 1752 of file View.c.

1752 {
1753
1754 assert(event);
1755
1756 ViewEvent code = ViewEventNone;
1757
1758 switch (event->type) {
1759 case SDL_EVENT_MOUSE_BUTTON_DOWN:
1761 break;
1762 case SDL_EVENT_MOUSE_BUTTON_UP:
1764 $(self, resignTouchResponder);
1765 break;
1766 case SDL_EVENT_KEY_DOWN:
1767 code = ViewEventKeyDown;
1768 break;
1769 case SDL_EVENT_KEY_UP:
1770 code = ViewEventKeyUp;
1771 break;
1772 default:
1773 break;
1774 }
1775
1776 if (code != ViewEventNone) {
1777 $(self, emitViewEvent, code, NULL);
1778
1779 if (code == ViewEventMouseButtonUp) {
1780 if (event->button.clicks) {
1781 $(self, emitViewEvent, ViewEventClick, NULL);
1782 }
1783 }
1784 }
1785
1786 if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
1787 if ($(self, acceptsKeyResponder)) {
1788 $(self, becomeKeyResponder);
1789 return;
1790 }
1791 }
1792
1793 if (self->nextResponder) {
1794 $(self->nextResponder, respondToEvent, event);
1795 } else if (self->superview) {
1796 $(self->superview, respondToEvent, event);
1797 }
1798}
ViewEvent
View event relay codes.
Definition Types.h:61
@ ViewEventMouseButtonUp
A View has received a mouse button up event.
Definition Types.h:85
@ ViewEventMouseButtonDown
A View has received a mouse button down event.
Definition Types.h:80
@ ViewEventNone
No event.
Definition Types.h:65
@ ViewEventKeyUp
A View has received a key up event.
Definition Types.h:75
@ ViewEventClick
A Control received one or more click events.
Definition Types.h:115
@ ViewEventKeyDown
A View has received a key down event.
Definition Types.h:70
View * nextResponder
The next responder, or event handler, in the chain.
Definition View.h:392

◆ selectFirst()

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

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}

◆ setNeedsApplyTheme()

static void setNeedsApplyTheme ( View *  self)
static

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()

static void setNeedsLayout ( View *  self)
static

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()

static void setVisibility ( View *  self,
ViewVisibility  visibility 
)
static

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

◆ size()

static SDL_Size size ( const View *  self)
static

Definition at line 1878 of file View.c.

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

◆ sizeThatContains()

static SDL_Size sizeThatContains ( const View *  self)
static

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}

◆ sizeThatFills()

static SDL_Size sizeThatFills ( const View *  self)
static

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()

static SDL_Size sizeThatFits ( const View *  self)
static

Definition at line 1914 of file View.c.

1914 {
1915
1916 SDL_Size size = $(self, size);
1917
1918 if ($(self, isContainer)) {
1919 size = MakeSize(0, 0);
1920
1921 Array *subviews = $(self, visibleSubviews);
1922 for (size_t i = 0; i < subviews->count; i++) {
1923
1924 View *subview = subviews->elements[i];
1925
1926 const ViewConstraint unspecified = MakeConstraint(ViewConstraintUnspecified, 0);
1927 const SDL_Size subviewSize = $(subview, sizeThatSatisfies, unspecified, unspecified);
1928
1929 SDL_Point subviewOrigin = MakePoint(0, 0);
1930 switch (subview->alignment) {
1931 case ViewAlignmentNone:
1932 subviewOrigin = MakePoint(subview->frame.x, subview->frame.y);
1933 break;
1934 default:
1935 break;
1936 }
1937
1938 size.w = max(size.w, subviewOrigin.x + subviewSize.w);
1939 size.h = max(size.h, subviewOrigin.y + subviewSize.h);
1940 }
1941
1942 size.w += self->padding.left + self->padding.right;
1943 size.h += self->padding.top + self->padding.bottom;
1944
1945 release(subviews);
1946
1947 }
1948
1949 size.w = ClampSize(size.w, self->minSize.w, self->maxSize.w);
1950 size.h = ClampSize(size.h, self->minSize.h, self->maxSize.h);
1951
1952 return size;
1953}
@ ViewAlignmentNone
Definition View.h:65

◆ sizeThatSatisfies()

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

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

◆ sizeToContain()

static void sizeToContain ( View *  self)
static

Definition at line 1996 of file View.c.

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

◆ sizeToFill()

static void sizeToFill ( View *  self)
static

Definition at line 2007 of file View.c.

2007 {
2008
2009 const SDL_Size size = $(self, sizeThatFills);
2010
2011 $(self, resize, &size);
2012}

◆ sizeToFit()

static void sizeToFit ( View *  self)
static

Definition at line 2018 of file View.c.

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

◆ sizeToSatisfy()

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

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}

◆ subviewWithIdentifier()

static View * subviewWithIdentifier ( const View *  self,
const char *  identifier 
)
static

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()

static void updateBindings ( View *  self,
ident  data 
)
static

Definition at line 2070 of file View.c.

2070 {
2072}
static void updateBindings_enumerate(View *subview, ident data)
ViewEnumerator for updateBindings recursion.
Definition View.c:2062

◆ updateBindings_enumerate()

static void updateBindings_enumerate ( View *  subview,
ident  data 
)
static

ViewEnumerator for updateBindings recursion.

Definition at line 2062 of file View.c.

2062 {
2063 $(subview, updateBindings, data);
2064}

◆ viewport()

static SDL_Rect viewport ( const View *  self)
static

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()

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

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}

◆ viewWithData()

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

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}

◆ viewWithDictionary()

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

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}
@ InletTypeView
Definition View+JSON.h:133
#define BindInlet(inlet, obj)
Binds the Inlet to obj by invoking the appropriate InletBinding function.
Definition View+JSON.h:238

◆ viewWithResource()

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

Definition at line 2142 of file View.c.

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

◆ viewWithResourceName()

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

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}

◆ visibleSubviews()

static Array * visibleSubviews ( const View *  self)
static

Definition at line 2178 of file View.c.

2178 {
2179 return $((Array *) self->subviews, filteredArray, visibleSubviews_filter, NULL);
2180}
static bool visibleSubviews_filter(ident obj, ident data)
Predicate for visibleSubviews.
Definition View.c:2167

◆ visibleSubviews_filter()

static bool visibleSubviews_filter ( ident  obj,
ident  data 
)
static

Predicate for visibleSubviews.

Definition at line 2167 of file View.c.

2167 {
2168
2169 const View *view = (View *) obj;
2170
2172}

◆ warn()

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

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
String * message
The message.
Definition Warning.h:71

◆ willMoveToWindow()

static void willMoveToWindow ( View *  self,
SDL_Window *  window 
)
static

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}

Variable Documentation

◆ _renderFrameGeneration

unsigned _renderFrameGeneration
static

The render frame generation; per-View renderFrame and clippingFrame caches are valid only while their generation matches this. Zero disables caching entirely, for callers that never invalidate (e.g. unit tests).

Definition at line 44 of file View.c.

◆ MVC_NOTIFICATION_EVENT

Uint32 MVC_NOTIFICATION_EVENT

Definition at line 36 of file View.c.

◆ MVC_VIEW_EVENT

Uint32 MVC_VIEW_EVENT

Definition at line 37 of file View.c.

◆ ViewAlignmentNames

const EnumName ViewAlignmentNames[]
Initial value:
= MakeEnumNames(
MakeEnumAlias(ViewAlignmentNone, none),
MakeEnumAlias(ViewAlignmentTop, top),
MakeEnumAlias(ViewAlignmentMiddle, middle),
MakeEnumAlias(ViewAlignmentBottom, bottom),
MakeEnumAlias(ViewAlignmentLeft, left),
MakeEnumAlias(ViewAlignmentCenter, center),
MakeEnumAlias(ViewAlignmentRight, right),
MakeEnumAlias(ViewAlignmentTopLeft, top-left),
MakeEnumAlias(ViewAlignmentTopCenter, top-center),
MakeEnumAlias(ViewAlignmentTopRight, top-right),
MakeEnumAlias(ViewAlignmentMiddleLeft, middle-left),
MakeEnumAlias(ViewAlignmentMiddleCenter, middle-center),
MakeEnumAlias(ViewAlignmentMiddleRight, middle-right),
MakeEnumAlias(ViewAlignmentBottomLeft, bottom-left),
MakeEnumAlias(ViewAlignmentBottomCenter, bottom-center),
MakeEnumAlias(ViewAlignmentBottomRight, bottom-right),
MakeEnumAlias(ViewAlignmentInternal, internal)
)
@ ViewAlignmentBottomRight
Definition View.h:80
@ ViewAlignmentBottomLeft
Definition View.h:78
@ ViewAlignmentMiddleCenter
Definition View.h:76
@ ViewAlignmentTopCenter
Definition View.h:73
@ ViewAlignmentTopRight
Definition View.h:74
@ ViewAlignmentMiddleRight
Definition View.h:77
@ ViewAlignmentTopLeft
Definition View.h:72
@ ViewAlignmentTop
Definition View.h:66
@ ViewAlignmentMiddleLeft
Definition View.h:75
@ ViewAlignmentBottom
Definition View.h:68
@ ViewAlignmentMiddle
Definition View.h:67
@ ViewAlignmentBottomCenter
Definition View.h:79

Definition at line 63 of file View.c.

◆ ViewAutoresizingNames

const EnumName ViewAutoresizingNames[]
Initial value:
= MakeEnumNames(
MakeEnumAlias(ViewAutoresizingNone, none),
MakeEnumAlias(ViewAutoresizingWidth, width),
MakeEnumAlias(ViewAutoresizingHeight, height),
MakeEnumAlias(ViewAutoresizingFill, fill),
MakeEnumAlias(ViewAutoresizingFit, fit),
MakeEnumAlias(ViewAutoresizingContain, contain)
)
@ ViewAutoresizingNone
Definition View.h:90
@ ViewAutoresizingFill
Definition View.h:93

Definition at line 83 of file View.c.

◆ ViewPointerEventsNames

const EnumName ViewPointerEventsNames[]
Initial value:
= MakeEnumNames(
MakeEnumAlias(ViewPointerEventsAuto, auto),
MakeEnumAlias(ViewPointerEventsNone, none)
)
@ ViewPointerEventsNone
Definition View.h:111

Definition at line 52 of file View.c.

◆ ViewVisibilityNames

const EnumName ViewVisibilityNames[]
Initial value:
= MakeEnumNames(
MakeEnumAlias(ViewVisibilityUnspecified, unspecified),
MakeEnumAlias(ViewVisibilityVisible, visible),
MakeEnumAlias(ViewVisibilityHidden, hidden)
)
@ ViewVisibilityUnspecified
Definition View.h:120
@ ViewVisibilityVisible
Definition View.h:121

Definition at line 57 of file View.c.