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 ViewancestorWithIdentifier (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 dealloc (Object *self)
 
static int depth (const View *self)
 
static ViewdescendantWithIdentifier (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 ViewhitTest (const View *self, const SDL_Point *point)
 
static Viewinit (View *self)
 
static void initialize (Class *clazz)
 
static ViewinitWithFrame (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 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.
 
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 void respondToEvent (View *self, const SDL_Event *event)
 
static ViewselectFirst (View *self, const char *rule)
 
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 void sizeToContain (View *self)
 
static void sizeToFill (View *self)
 
static void sizeToFit (View *self)
 
static ViewsubviewWithIdentifier (const View *self, const char *identifier)
 
static void updateBindings (View *self)
 
static void updateBindings_enumerate (View *subview, ident data)
 ViewEnumerator for updateBindings recursion.
 
static SDL_Rect viewport (const View *self)
 
static ViewviewWithCharacters (const char *chars, Outlet *outlets)
 
static ViewviewWithData (const Data *data, Outlet *outlets)
 
static ViewviewWithDictionary (const Dictionary *dictionary, Outlet *outlets)
 
static ViewviewWithResource (const Resource *resource, Outlet *outlets)
 
static ViewviewWithResourceName (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

Uint32 MVC_NOTIFICATION_EVENT
 
Uint32 MVC_VIEW_EVENT
 
const EnumName ViewAlignmentNames []
 
const EnumName ViewAutoresizingNames []
 

Macro Definition Documentation

◆ _Class

#define _Class   _View

Definition at line 68 of file View.c.

Function Documentation

◆ _applyThemeIfNeeded()

static void _applyThemeIfNeeded ( View view,
ident  data 
)
static

ViewEnumerator adapter for applyThemeIfNeeded.

Definition at line 313 of file View.c.

313 {
314 applyThemeIfNeeded(view, (const Theme *) data);
315}
static void applyThemeIfNeeded(View *self, const Theme *theme)
Definition View.c:317
The Theme type.
Definition Theme.h:51

◆ _bind()

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

Definition at line 475 of file View.c.

475 {
476
477 if (inlets) {
478 if (bindInlets(inlets, dictionary)) {
479 self->needsApplyTheme = true;
480 self->needsLayout = true;
481 return true;
482 }
483 }
484
485 return false;
486}
bool bindInlets(const Inlet *inlets, const Dictionary *dictionary)
Binds each Inlet specified in inlets to the data provided in dictionary.
Definition View+JSON.c:327
bool needsApplyTheme
If true, this View will apply the Theme before it is drawn.
Definition View.h:217
bool needsLayout
If true, this View will layout its subviews before it is drawn.
Definition View.h:222

◆ _draw()

static void _draw ( View view,
ident  data 
)
static

ViewEnumerator adapter for draw.

Definition at line 716 of file View.c.

716 {
717 draw(view, (Renderer *) data);
718}
static void draw(View *self, Renderer *renderer)
Definition View.c:720
Renderer extends Object with ObjectivelyMVC's UI rendering layer.
Definition Renderer.h:70

◆ _select()

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

Definition at line 1621 of file View.c.

1621 {
1622
1623 Selector *selector = $(alloc(Selector), initWithRule, rule);
1624 assert(selector);
1625
1626 Set *selection = $(selector, select, self);
1627
1628 release(selector);
1629 return selection;
1630}
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 2067 of file View.c.

2067 {
2068 static Class *clazz;
2069 static Once once;
2070
2071 do_once(&once, {
2072 clazz = _initialize(&(const ClassDef) {
2073 .name = "View",
2074 .superclass = _Object(),
2075 .instanceSize = sizeof(View),
2076 .interfaceOffset = offsetof(View, interface),
2077 .interfaceSize = sizeof(ViewInterface),
2079 });
2080 });
2081
2082 return clazz;
2083}
static void initialize(Class *clazz)
Definition View.c:1960
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:134

◆ acceptsKeyResponder()

static bool acceptsKeyResponder ( const View self)
static

Definition at line 143 of file View.c.

143 {
144 return false;
145}

◆ acceptsTouchResponder()

static bool acceptsTouchResponder ( const View self)
static

Definition at line 151 of file View.c.

151 {
152 return false;
153}

◆ addClassName()

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

Definition at line 159 of file View.c.

159 {
160
161 if (className) {
162
163 String *string = $$(String, stringWithCharacters, className);
164 assert(string);
165
166 $(self->classNames, addObject, string);
167 release(string);
168
169 $(self, invalidateStyle);
170 }
171}
static void invalidateStyle(View *self)
Definition View.c:1033
Set * classNames
The class names.
Definition View.h:176

◆ addSubview()

static void addSubview ( View self,
View subview 
)
static

Definition at line 177 of file View.c.

177 {
178 $(self, addSubviewRelativeTo, subview, NULL, ViewPositionAfter);
179}
static void addSubviewRelativeTo(View *self, View *subview, View *other, ViewPosition position)
Definition View.c:185
@ ViewPositionAfter
Definition View.h:121

◆ addSubviewRelativeTo()

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

Definition at line 185 of file View.c.

185 {
186
187 assert(subview);
188 assert(subview != other);
189
190 retain(subview);
191
192 $(subview, removeFromSuperview);
193
194 if (other && other->superview == self) {
195
196 const Array *subviews = (Array *) self->subviews;
197 const ssize_t index = $(subviews, indexOfObject, other);
198
199 if (position == ViewPositionAfter) {
200 if (index == (ssize_t) (subviews->count - 1)) {
201 $(self->subviews, addObject, subview);
202 } else {
203 $(self->subviews, insertObjectAtIndex, subview, index + 1);
204 }
205 } else {
206 $(self->subviews, insertObjectAtIndex, subview, index);
207 }
208 } else {
209 $(self->subviews, addObject, subview);
210 }
211
212 release(subview);
213
214 subview->superview = self;
215
216 $(subview, moveToWindow, self->window);
217
218 $(subview, invalidateStyle);
219
220 self->needsLayout = true;
221}
static void moveToWindow(View *self, SDL_Window *window)
Definition View.c:1262
static void removeFromSuperview(View *self)
Definition View.c:1361
View * superview
The super View.
Definition View.h:259
Array * subviews
The immediate subviews.
Definition View.h:253
SDL_Window * window
The window.
Definition View.h:277

◆ ancestorWithIdentifier()

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

Definition at line 227 of file View.c.

227 {
228
229 assert(identifier);
230
231 View *view = (View *) self;
232 while (view) {
233 if (view->identifier) {
234 if (strcmp(identifier, view->identifier) == 0) {
235 return view;
236 }
237 }
238 view = view->superview;
239 }
240
241 return NULL;
242}
char * identifier
An optional identifier.
Definition View.h:202

◆ applyStyle()

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

Definition at line 248 of file View.c.

248 {
249
250 assert(style);
251
252 const Inlet inlets[] = MakeInlets(
253 MakeInlet("alignment", InletTypeEnum, &self->alignment, (ident) ViewAlignmentNames),
254 MakeInlet("autoresizing-mask", InletTypeEnum, &self->autoresizingMask, (ident) ViewAutoresizingNames),
255 MakeInlet("background-color", InletTypeColor, &self->backgroundColor, NULL),
256 MakeInlet("border-color", InletTypeColor, &self->borderColor, NULL),
257 MakeInlet("border-width", InletTypeInteger, &self->borderWidth, NULL),
258 MakeInlet("clips-subviews", InletTypeBool, &self->clipsSubviews, NULL),
259 MakeInlet("frame", InletTypeRectangle, &self->frame, NULL),
260 MakeInlet("hidden", InletTypeBool, &self->hidden, NULL),
261 MakeInlet("height", InletTypeInteger, &self->frame.h, NULL),
262 MakeInlet("left", InletTypeInteger, &self->frame.x, NULL),
263 MakeInlet("max-height", InletTypeInteger, &self->maxSize.h, NULL),
264 MakeInlet("max-size", InletTypeSize, &self->maxSize, NULL),
265 MakeInlet("max-width", InletTypeInteger, &self->maxSize.w, NULL),
266 MakeInlet("min-height", InletTypeInteger, &self->minSize.h, NULL),
267 MakeInlet("min-size", InletTypeSize, &self->minSize, NULL),
268 MakeInlet("min-width", InletTypeInteger, &self->minSize.w, NULL),
269 MakeInlet("padding", InletTypeRectangle, &self->padding, NULL),
270 MakeInlet("padding-top", InletTypeInteger, &self->padding.top, NULL),
271 MakeInlet("padding-right", InletTypeInteger, &self->padding.right, NULL),
272 MakeInlet("padding-bottom", InletTypeInteger, &self->padding.bottom, NULL),
273 MakeInlet("padding-left", InletTypeInteger, &self->padding.left, NULL),
274 MakeInlet("top", InletTypeInteger, &self->frame.y, NULL),
275 MakeInlet("width", InletTypeInteger, &self->frame.w, NULL)
276 );
277
278 $(self, bind, inlets, style->attributes);
279}
@ InletTypeEnum
Definition View+JSON.h:75
@ InletTypeBool
Definition View+JSON.h:46
@ InletTypeInteger
Definition View+JSON.h:95
@ InletTypeColor
Definition View+JSON.h:62
@ InletTypeSize
Definition View+JSON.h:110
@ InletTypeRectangle
Definition View+JSON.h:105
#define MakeInlets(...)
Creates a null-termianted array of Inlets.
Definition View+JSON.h:221
#define MakeInlet(name, type, dest, data)
Creates an Inlet with the specified parameters.
Definition View+JSON.h:216
const EnumName ViewAlignmentNames[]
Definition View.c:39
const EnumName ViewAutoresizingNames[]
Definition View.c:59
Inlets enable inbound data binding of View attributes through JSON.
Definition View+JSON.h:155
Dictionary * attributes
Definition Style.h:59
bool clipsSubviews
If true, subviews will be clipped to this View's frame.
Definition View.h:181
ViewAlignment alignment
The alignment.
Definition View.h:150
SDL_Color borderColor
The border color.
Definition View.h:165
int autoresizingMask
The ViewAutoresizing bitmask.
Definition View.h:155
ViewPadding padding
The padding.
Definition View.h:234
int borderWidth
The border width.
Definition View.h:170
SDL_Size minSize
The minimum size this View may be resized to during layout.
Definition View.h:212
SDL_Size maxSize
The maximum size this View may be resized to during layout.
Definition View.h:207
SDL_Color backgroundColor
The background color.
Definition View.h:160
SDL_Rect frame
The frame, relative to the superview.
Definition View.h:191
bool hidden
If true, this View is not drawn.
Definition View.h:196
int top
Definition View.h:101
int bottom
Definition View.h:101
int right
Definition View.h:101
int left
Definition View.h:101

◆ applyTheme()

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

Definition at line 285 of file View.c.

285 {
286
287 assert(theme);
288
289 Style *computedStyle = $(theme, computeStyle, self);
290 assert(computedStyle);
291
292 if (!$(self->computedStyle, isComputedEqual, computedStyle)) {
293
294 release(self->computedStyle);
295 self->computedStyle = retain(computedStyle);
296
298 $(self, applyStyle, self->computedStyle);
299 }
300
301 release(computedStyle);
302}
static bool isComputedEqual(const Style *self, const Style *other)
Definition Style.c:331
static void addAttributes(Style *self, const Dictionary *attributes)
Definition Style.c:119
static Theme * theme(SDL_Window *window)
Definition Theme.c:143
static Style * computeStyle(const Theme *self, const View *view)
Definition Theme.c:103
static void applyStyle(View *self, const Style *style)
Definition View.c:248
The Style type.
Definition Style.h:43
Style * style
The element-level Style of this View.
Definition View.h:241
Style * computedStyle
The computed Style of this View.
Definition View.h:186

◆ applyThemeIfNeeded()

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

Definition at line 317 of file View.c.

317 {
318
319 assert(theme);
320
322
323 if (self->needsApplyTheme) {
324
326
327 $(self, applyTheme, theme);
328
329 self->needsApplyTheme = false;
330 }
331}
static void clearWarnings(const View *self, WarningType type)
Definition View.c:538
static void enumerateSubviews(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:846
static void applyTheme(View *self, const Theme *theme)
Definition View.c:285
static void _applyThemeIfNeeded(View *view, ident data)
ViewEnumerator adapter for applyThemeIfNeeded.
Definition View.c:313
@ WarningTypeStyle
Definition Warning.h:34

◆ attachStylesheet()

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

Definition at line 337 of file View.c.

337 {
338
339 assert(window);
340
341 if (self->stylesheet) {
342 Theme *theme = $$(Theme, theme, window);
343 if (theme) {
344 $(theme, addStylesheet, self->stylesheet);
345 }
346 }
347}
static void addStylesheet(Theme *self, Stylesheet *stylesheet)
Definition Theme.c:55
Stylesheet * stylesheet
An optional Stylesheet.
Definition View.h:248

◆ awakeWithCharacters()

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

Definition at line 353 of file View.c.

353 {
354
355 Data *data = $$(Data, dataWithConstMemory, (uint8_t *) chars, strlen(chars));
356
357 $(self, awakeWithData, data);
358
359 release(data);
360}
static void awakeWithData(View *self, const Data *data)
Definition View.c:366

◆ awakeWithData()

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

Definition at line 366 of file View.c.

366 {
367
368 JSONContext *ctx = $(alloc(JSONContext), init);
369 Dictionary *dictionary = $(ctx, objectFromData, data, 0);
370
371 if (dictionary) {
372 $(self, awakeWithDictionary, dictionary);
373 release(dictionary);
374 } else {
375 MVC_LogError("Failed to parse JSON for %s\n", classnameof(self));
376 }
377
378 release(ctx);
379}
#define MVC_LogError(fmt,...)
Definition Log.h:57
static View * init(View *self)
Definition View.c:981
static void awakeWithDictionary(View *self, const Dictionary *dictionary)
Definition View.c:385

◆ awakeWithDictionary()

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

Definition at line 385 of file View.c.

385 {
386
387 assert(dictionary);
388
389 const Inlet inlets[] = MakeInlets(
390 MakeInlet("identifier", InletTypeCharacters, &self->identifier, NULL),
391 MakeInlet("classNames", InletTypeClassNames, &self, NULL),
392 MakeInlet("style", InletTypeStyle, &self, NULL),
393 MakeInlet("subviews", InletTypeSubviews, &self, NULL)
394 );
395
396 $(self, bind, inlets, dictionary);
397}
@ InletTypeSubviews
Definition View+JSON.h:122
@ InletTypeStyle
Definition View+JSON.h:116
@ 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 403 of file View.c.

403 {
404
405 assert(resource);
406
407 $(self, awakeWithData, resource->data);
408}

◆ awakeWithResourceName()

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

Definition at line 414 of file View.c.

414 {
415
416 Resource *resource = $$(Resource, resourceWithName, name);
417
418 $(self, awakeWithResource, resource);
419
420 release(resource);
421}
static void awakeWithResource(View *self, const Resource *resource)
Definition View.c:403

◆ becomeKeyResponder()

static void becomeKeyResponder ( View self)
static

Definition at line 427 of file View.c.

427 {
428
429 assert(self->window);
430
431 if (!$(self, isKeyResponder)) {
432 SDL_PropertiesID props = SDL_GetWindowProperties(self->window);
433
434 View *keyResponder = SDL_GetPointerProperty(props, "keyResponder", NULL);
435 if (keyResponder) {
437 }
438
439 String *path = $(self, path);
440 MVC_LogDebug("%s\n", path->chars);
441 release(path);
442
443 SDL_SetPointerProperty(props, "keyResponder", self);
444 }
445}
#define MVC_LogDebug(fmt,...)
Definition Log.h:48
static String * path(const View *self)
Definition View.c:1277
static void resignKeyResponder(View *self)
Definition View.c:1495
static bool isKeyResponder(const View *self)
Definition View.c:1067
static View * keyResponder(const WindowController *self)

◆ becomeTouchResponder()

static void becomeTouchResponder ( View self)
static

Definition at line 451 of file View.c.

451 {
452
453 assert(self->window);
454
455 if (!$(self, isTouchResponder)) {
456 SDL_PropertiesID props = SDL_GetWindowProperties(self->window);
457
458 View *touchResponder = SDL_GetPointerProperty(props, "touchResponder", NULL);
459 if (touchResponder) {
461 }
462
463 String *path = $(self, path);
464 MVC_LogDebug("%s\n", path->chars);
465 release(path);
466
467 SDL_SetPointerProperty(props, "touchResponder", self);
468 }
469}
static bool isTouchResponder(const View *self)
Definition View.c:1080
static void resignTouchResponder(View *self)
Definition View.c:1511
static View * touchResponder(const WindowController *self)

◆ bounds()

static SDL_Rect bounds ( const View self)
static

Definition at line 492 of file View.c.

492 {
493
494 const SDL_Size size = $(self, size);
495
496 const SDL_Rect bounds = {
497 .x = self->padding.left,
498 .y = self->padding.top,
499 .w = max(0, size.w - (self->padding.left + self->padding.right)),
500 .h = max(0, size.h - (self->padding.top + self->padding.bottom)),
501 };
502
503 return bounds;
504}
static SDL_Size size(const View *self)
Definition View.c:1651
static SDL_Rect bounds(const View *self)
Definition View.c:492

◆ bringSubviewToFront()

static void bringSubviewToFront ( View self,
View subview 
)
static

Definition at line 510 of file View.c.

510 {
511
512 assert(subview);
513
514 if (subview->superview == self) {
515
516 View *last = $((Array *) self->subviews, lastObject);
517 if (last != subview) {
518 $(self, addSubviewRelativeTo, subview, last, ViewPositionAfter);
519 }
520 }
521}

◆ clearWarnings()

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

Definition at line 538 of file View.c.

538 {
539 $(self->warnings, filter, clearWarnings_predicate, &type);
540}
static bool clearWarnings_predicate(const ident obj, ident data)
Filter Predicate for clearWarnings.
Definition View.c:526
Array * warnings
The Warnings this View generated.
Definition View.h:271

◆ clearWarnings_predicate()

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

Filter Predicate for clearWarnings.

Definition at line 526 of file View.c.

526 {
527
528 const Warning *warning = obj;
529 const WarningType type = *(WarningType *) data;
530
531 return (warning->type & type) == 0;
532}
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 546 of file View.c.

546 {
547
548 SDL_Rect frame = $(self, renderFrame);
549
550 if (self->borderWidth && self->borderColor.a) {
551 for (int i = 0; i < self->borderWidth; i++) {
552 frame.x -= 1;
553 frame.y -= 1;
554 frame.w += 2;
555 frame.h += 2;
556 }
557 }
558
559 const View *superview = self->superview;
560 while (superview) {
561 if (superview->clipsSubviews) {
562 const SDL_Rect clippingFrame = $(superview, clippingFrame);
563 if (SDL_GetRectIntersection(&clippingFrame, &frame, &frame) == false) {
564
565 if (MVC_LogEnabled(SDL_LOG_PRIORITY_VERBOSE)) {
566 String *desc = $((Object *) self, description);
567 String *superdesc = $((Object *) superview, description);
568
569 MVC_LogVerbose("%s is clipped by %s\n", desc->chars, superdesc->chars);
570
571 release(desc);
572 release(superdesc);
573 }
574
575 frame.w = frame.h = 0;
576 break;
577 }
578 }
579 superview = superview->superview;
580 }
581
582 return frame;
583}
#define MVC_LogVerbose(fmt,...)
Definition Log.h:45
#define MVC_LogEnabled(priority)
Definition Log.h:39
static String * description(const Object *self)
Definition View.c:121
static SDL_Rect renderFrame(const View *self)
Definition View.c:1455
static SDL_Rect clippingFrame(const View *self)
Definition View.c:546

◆ containsPoint()

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

Definition at line 589 of file View.c.

589 {
590
591 const SDL_Rect frame = $(self, clippingFrame);
592
593 return (bool) SDL_PointInRect(point, &frame);
594}

◆ dealloc()

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

Definition at line 94 of file View.c.

94 {
95
96 View *this = (View *) self;
97
98 SDL_FilterEvents(filterViewEvents, this);
99
100 $(this, moveToWindow, NULL);
101
102 $(this, enumerateSubviews, nullifySuperview, NULL);
103
104 free(this->identifier);
105
106 release(this->classNames);
107 release(this->computedStyle);
108 release(this->style);
109 release(this->stylesheet);
110 release(this->subviews);
111 release(this->warnings);
112
113 this->superview = NULL;
114
115 super(Object, self, dealloc);
116}
static bool filterViewEvents(void *data, SDL_Event *event)
Definition View.c:75
static void nullifySuperview(View *subview, ident data)
ViewEnumerator to null out superview pointers during parent dealloc.
Definition View.c:87
static void dealloc(Object *self)
Definition View.c:94

◆ depth()

static int depth ( const View self)
static

Definition at line 600 of file View.c.

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

◆ descendantWithIdentifier()

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

Definition at line 608 of file View.c.

608 {
609
610 assert(identifier);
611
612 if (self->identifier) {
613 if (strcmp(identifier, self->identifier) == 0) {
614 return (View *) self;
615 }
616 }
617
618 const Array *subviews = (Array *) self->subviews;
619 for (size_t i = 0; i < subviews->count; i++) {
620
621 const View *subview = subviews->elements[i];
622 View *descendant = $(subview, descendantWithIdentifier, identifier);
623 if (descendant) {
624 return descendant;
625 }
626 }
627
628 return NULL;
629}
static View * descendantWithIdentifier(const View *self, const char *identifier)
Definition View.c:608

◆ description()

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

Definition at line 121 of file View.c.

121 {
122
123 View *this = (View *) self;
124 const SDL_Rect bounds = $(this, bounds);
125
126 String *classNames = $((Object *) this->classNames, description);
127 String *description = str("%s@%p %s [%d, %d, %d, %d]",
128 this->identifier ?: classnameof(self),
129 self,
130 classNames->chars,
131 bounds.x, bounds.y, bounds.w, bounds.h);
132
133 release(classNames);
134 return description;
135}

◆ detachStylesheet()

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

Definition at line 635 of file View.c.

635 {
636
637 assert(window);
638
639 if (self->stylesheet) {
640 Theme *theme = $$(Theme, theme, window);
641 if (theme) {
643 }
644 }
645}
static void removeStylesheet(Theme *self, Stylesheet *stylesheet)
Definition Theme.c:135

◆ didMoveToWindow()

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

Definition at line 651 of file View.c.

651 {
652
653 if (window) {
654 $(self, attachStylesheet, window);
655
656 if (self->superview == NULL) {
657 $(self, sizeToFill);
658 }
659
660 self->needsLayout = true;
661 }
662}
static void sizeToFill(View *self)
Definition View.c:1756
static void attachStylesheet(View *self, SDL_Window *window)
Definition View.c:337

◆ didReceiveEvent()

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

Definition at line 668 of file View.c.

668 {
669
670 if ($(self, isKeyResponder)) {
671 switch (event->type) {
672 case SDL_EVENT_KEY_DOWN:
673 case SDL_EVENT_KEY_UP:
674 case SDL_EVENT_TEXT_INPUT:
675 return true;
676 }
677 }
678
679 if ($(self, isVisible)) {
680
681 SDL_Point point;
682
683 switch (event->type) {
684 case SDL_EVENT_MOUSE_BUTTON_DOWN:
685 case SDL_EVENT_MOUSE_BUTTON_UP:
686 point = MakePoint(event->button.x, event->button.y);
687 break;
688 case SDL_EVENT_MOUSE_MOTION:
689 point = MakePoint(event->motion.x, event->motion.y);
690 break;
691 case SDL_EVENT_MOUSE_WHEEL: {
692 float mx, my;
693 SDL_GetMouseState(&mx, &my);
694 point = MakePoint(mx, my);
695 break;
696 }
697 default:
698 return false;
699 }
700
701 return $(self, containsPoint, &point);
702 }
703
704 return false;
705}
static bool isVisible(const View *self)
Definition View.c:1093
static bool containsPoint(const View *self, const SDL_Point *point)
Definition View.c:589

◆ draw()

static void draw ( View self,
Renderer renderer 
)
static

Definition at line 720 of file View.c.

720 {
721
722 assert(self->window);
723
724 if (self->hidden == false) {
725
726 $(renderer, drawView, self);
727
728 $(self, enumerateSubviews, _draw, renderer);
729 }
730}
static void drawView(Renderer *self, View *view)
Definition Renderer.c:234
static void _draw(View *view, ident data)
ViewEnumerator adapter for draw.
Definition View.c:716

◆ emitViewEvent()

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

Definition at line 736 of file View.c.

736 {
737 SDL_PushEvent((SDL_Event *) &(const SDL_UserEvent) {
738 .type = MVC_VIEW_EVENT,
739 .code = code,
740 .data1 = self,
741 .data2 = data
742 });
743}
Uint32 MVC_VIEW_EVENT
Definition View.c:37

◆ enumerate()

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

Definition at line 749 of file View.c.

749 {
750
751 assert(enumerator);
752
753 enumerator(self, data);
754
755 $(self, enumerateDescendants, enumerator, data);
756}
static void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:808

◆ enumerateAdjacent()

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

Definition at line 762 of file View.c.

762 {
763
764 assert(enumerator);
765
766 if (self->superview) {
767 const Array *siblings = (Array *) self->superview->subviews;
768 const ssize_t index = $(siblings, indexOfObject, (const ident) self);
769 if (index > 0) {
770 enumerator($(siblings, objectAtIndex, index - 1), data);
771 }
772 if (index < (ssize_t) (siblings->count - 1)) {
773 enumerator($(siblings, objectAtIndex, index + 1), data);
774 }
775 }
776}

◆ enumerateAncestors()

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

Definition at line 782 of file View.c.

782 {
783
784 assert(enumerator);
785
786 for (View *view = self->superview; view; view = view->superview) {
787 enumerator(view, data);
788 }
789}

◆ enumerateDescendants()

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

Definition at line 808 of file View.c.

808 {
809
810 assert(enumerator);
811
812 const Array *subviews = (Array *) self->subviews;
813 for (size_t i = 0; i < subviews->count; i++) {
814
815 View *subview = subviews->elements[i];
816 enumerator(subview, data);
817
818 $(subview, enumerateDescendants, enumerator, data);
819 }
820}

◆ enumerateSelection()

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

Definition at line 795 of file View.c.

795 {
796
797 Selector *selector = $(alloc(Selector), initWithRule, rule);
798 assert(selector);
799
800 $(selector, enumerateSelection, self, enumerator, data);
801 release(selector);
802}
static void enumerateSelection(View *self, const char *rule, ViewEnumerator enumerator, ident data)
Definition View.c:795

◆ enumerateSiblings()

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

Definition at line 826 of file View.c.

826 {
827
828 assert(enumerator);
829
830 if (self->superview) {
831
832 const Array *siblings = (Array *) self->superview->subviews;
833 for (size_t i = 0; i < siblings->count; i++) {
834 View *sibling = siblings->elements[i];
835 if (sibling != self) {
836 enumerator(sibling, data);
837 }
838 }
839 }
840}

◆ enumerateSubviews()

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

Definition at line 846 of file View.c.

846 {
847
848 assert(enumerator);
849
850 const Array *subviews = (Array *) self->subviews;
851 for (size_t i = 0; i < subviews->count; i++) {
852 enumerator((View *) subviews->elements[i], data);
853 }
854}

◆ enumerateSuperview()

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

Definition at line 860 of file View.c.

860 {
861
862 assert(enumerator);
863
864 if (self->superview) {
865 enumerator(self->superview, data);
866 }
867}

◆ enumerateVisible()

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

Definition at line 873 of file View.c.

873 {
874
875 if ($(self, isVisible) == false) {
876 return;
877 }
878
879 enumerator(self, data);
880
881 const Array *subviews = (Array *) self->subviews;
882 for (size_t i = 0; i < subviews->count; i++) {
883
884 View *subview = subviews->elements[i];
885 $(subview, enumerateVisible, enumerator, data);
886 }
887}
static void enumerateVisible(View *self, ViewEnumerator enumerator, ident data)
Definition View.c:873

◆ filterViewEvents()

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

SDL_EventFilter to purge any MVC_VIEW_EVENTs for this View.

Definition at line 75 of file View.c.

75 {
76
77 if (event->type == MVC_VIEW_EVENT && event->user.data1 == data) {
78 return false;
79 }
80
81 return true;
82}

◆ hasClassName()

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

Definition at line 900 of file View.c.

900 {
901
902 if (className) {
903 return $((Set *) self->classNames, containsObjectMatching, hasClassName_predicate, (ident) className);
904 }
905
906 return false;
907}
static bool hasClassName_predicate(const ident obj, ident data)
Predicate for hasClassName.
Definition View.c:892

◆ hasClassName_predicate()

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

Predicate for hasClassName.

Definition at line 892 of file View.c.

892 {
893 return strcmp(((String *) obj)->chars, (const char *) data) == 0;
894}

◆ hasOverflow()

static bool hasOverflow ( const View self)
static

Definition at line 939 of file View.c.

939 {
940
941 Overflow overflow = {
942 .bounds = $(self, bounds)
943 };
944
945 $(self, enumerateSubviews, hasOverflow_enumerate, (ident) &overflow);
946
947 return overflow.hasOverflow;
948}
static void hasOverflow_enumerate(View *view, ident data)
ViewEnumerator for hasOverflow.
Definition View.c:917
SDL_Rect bounds
Definition View.c:910
bool hasOverflow
Definition View.c:911

◆ hasOverflow_enumerate()

static void hasOverflow_enumerate ( View view,
ident  data 
)
static

ViewEnumerator for hasOverflow.

Definition at line 917 of file View.c.

917 {
918
919 Overflow *overflow = data;
920
921 if (!view->hidden) {
922
923 const SDL_Rect bounds = $(view, bounds);
924
925 if (bounds.x + bounds.w > overflow->bounds.w || bounds.y + bounds.h > overflow->bounds.h) {
926
927 overflow->hasOverflow = true;
928
929 $(view, warn, WarningTypeLayout, "Exceeds superview bounds [%d %d %d %d]",
930 overflow->bounds.x, overflow->bounds.y, overflow->bounds.w, overflow->bounds.h);
931 }
932 }
933}
static void warn(View *self, WarningType type, const char *fmt,...)
Definition View.c:1924
@ WarningTypeLayout
Definition Warning.h:35

◆ hitTest()

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

Definition at line 954 of file View.c.

954 {
955
956 if (self->hidden == false) {
957
958 if ($(self, containsPoint, point)) {
959
960 const Array *subviews = (Array *) self->subviews;
961 for (size_t i = subviews->count; i; i--) {
962
963 const View *subview = subviews->elements[i - 1];
964 const View *view = $(subview, hitTest, point);
965 if (view) {
966 return (View *) view;
967 }
968 }
969
970 return (View *) self;
971 }
972 }
973
974 return NULL;
975}
static View * hitTest(const View *self, const SDL_Point *point)
Definition View.c:954

◆ init()

static View * init ( View self)
static

Definition at line 981 of file View.c.

981 {
982 return $(self, initWithFrame, NULL);
983}
static View * initWithFrame(View *self, const SDL_Rect *frame)
Definition View.c:989

◆ initialize()

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

Definition at line 1960 of file View.c.

1960 {
1961
1962 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
1963 ((ObjectInterface *) clazz->interface)->description = description;
1964
1965 ((ViewInterface *) clazz->interface)->acceptsKeyResponder = acceptsKeyResponder;
1966 ((ViewInterface *) clazz->interface)->acceptsTouchResponder = acceptsTouchResponder;
1967 ((ViewInterface *) clazz->interface)->addClassName = addClassName;
1968 ((ViewInterface *) clazz->interface)->addSubview = addSubview;
1969 ((ViewInterface *) clazz->interface)->addSubviewRelativeTo = addSubviewRelativeTo;
1970 ((ViewInterface *) clazz->interface)->ancestorWithIdentifier = ancestorWithIdentifier;
1971 ((ViewInterface *) clazz->interface)->applyStyle = applyStyle;
1972 ((ViewInterface *) clazz->interface)->applyTheme = applyTheme;
1973 ((ViewInterface *) clazz->interface)->applyThemeIfNeeded = applyThemeIfNeeded;
1974 ((ViewInterface *) clazz->interface)->attachStylesheet = attachStylesheet;
1975 ((ViewInterface *) clazz->interface)->awakeWithCharacters = awakeWithCharacters;
1976 ((ViewInterface *) clazz->interface)->awakeWithData = awakeWithData;
1977 ((ViewInterface *) clazz->interface)->awakeWithDictionary = awakeWithDictionary;
1978 ((ViewInterface *) clazz->interface)->awakeWithResource = awakeWithResource;
1979 ((ViewInterface *) clazz->interface)->awakeWithResourceName = awakeWithResourceName;
1980 ((ViewInterface *) clazz->interface)->becomeKeyResponder = becomeKeyResponder;
1981 ((ViewInterface *) clazz->interface)->becomeTouchResponder = becomeTouchResponder;
1982 ((ViewInterface *) clazz->interface)->bind = _bind;
1983 ((ViewInterface *) clazz->interface)->bounds = bounds;
1984 ((ViewInterface *) clazz->interface)->bringSubviewToFront = bringSubviewToFront;
1985 ((ViewInterface *) clazz->interface)->clearWarnings = clearWarnings;
1986 ((ViewInterface *) clazz->interface)->clippingFrame = clippingFrame;
1987 ((ViewInterface *) clazz->interface)->containsPoint = containsPoint;
1988 ((ViewInterface *) clazz->interface)->depth = depth;
1989 ((ViewInterface *) clazz->interface)->descendantWithIdentifier = descendantWithIdentifier;
1990 ((ViewInterface *) clazz->interface)->detachStylesheet = detachStylesheet;
1991 ((ViewInterface *) clazz->interface)->didMoveToWindow = didMoveToWindow;
1992 ((ViewInterface *) clazz->interface)->didReceiveEvent = didReceiveEvent;
1993 ((ViewInterface *) clazz->interface)->draw = draw;
1994 ((ViewInterface *) clazz->interface)->emitViewEvent = emitViewEvent;
1995 ((ViewInterface *) clazz->interface)->enumerate = enumerate;
1996 ((ViewInterface *) clazz->interface)->enumerateAdjacent = enumerateAdjacent;
1997 ((ViewInterface *) clazz->interface)->enumerateAncestors = enumerateAncestors;
1998 ((ViewInterface *) clazz->interface)->enumerateDescendants = enumerateDescendants;
1999 ((ViewInterface *) clazz->interface)->enumerateSelection = enumerateSelection;
2000 ((ViewInterface *) clazz->interface)->enumerateSiblings = enumerateSiblings;
2001 ((ViewInterface *) clazz->interface)->enumerateSubviews = enumerateSubviews;
2002 ((ViewInterface *) clazz->interface)->enumerateSuperview = enumerateSuperview;
2003 ((ViewInterface *) clazz->interface)->enumerateVisible = enumerateVisible;
2004 ((ViewInterface *) clazz->interface)->hasClassName = hasClassName;
2005 ((ViewInterface *) clazz->interface)->hasOverflow = hasOverflow;
2006 ((ViewInterface *) clazz->interface)->hitTest = hitTest;
2007 ((ViewInterface *) clazz->interface)->init = init;
2008 ((ViewInterface *) clazz->interface)->initWithFrame = initWithFrame;
2009 ((ViewInterface *) clazz->interface)->invalidateStyle = invalidateStyle;
2010 ((ViewInterface *) clazz->interface)->isContainer = isContainer;
2011 ((ViewInterface *) clazz->interface)->isDescendantOfView = isDescendantOfView;
2012 ((ViewInterface *) clazz->interface)->isKeyResponder = isKeyResponder;
2013 ((ViewInterface *) clazz->interface)->isTouchResponder = isTouchResponder;
2014 ((ViewInterface *) clazz->interface)->isVisible = isVisible;
2015 ((ViewInterface *) clazz->interface)->layoutIfNeeded = layoutIfNeeded;
2016 ((ViewInterface *) clazz->interface)->layoutSubviews = layoutSubviews;
2017 ((ViewInterface *) clazz->interface)->matchesSelector = matchesSelector;
2018 ((ViewInterface *) clazz->interface)->moveToWindow = moveToWindow;
2019 ((ViewInterface *) clazz->interface)->path = path;
2020 ((ViewInterface *) clazz->interface)->removeAllClassNames = removeAllClassNames;
2021 ((ViewInterface *) clazz->interface)->removeAllSubviews = removeAllSubviews;
2022 ((ViewInterface *) clazz->interface)->removeClassName = removeClassName;
2023 ((ViewInterface *) clazz->interface)->removeFromSuperview = removeFromSuperview;
2024 ((ViewInterface *) clazz->interface)->removeSubview = removeSubview;
2025 ((ViewInterface *) clazz->interface)->render = render;
2026 ((ViewInterface *) clazz->interface)->renderDeviceDidReset = renderDeviceDidReset;
2027 ((ViewInterface *) clazz->interface)->renderDeviceWillReset = renderDeviceWillReset;
2028 ((ViewInterface *) clazz->interface)->renderFrame = renderFrame;
2029 ((ViewInterface *) clazz->interface)->replaceSubview = replaceSubview;
2030 ((ViewInterface *) clazz->interface)->resignKeyResponder = resignKeyResponder;
2031 ((ViewInterface *) clazz->interface)->resignTouchResponder = resignTouchResponder;
2032 ((ViewInterface *) clazz->interface)->resize = resize;
2033 ((ViewInterface *) clazz->interface)->resolve = resolve;
2034 ((ViewInterface *) clazz->interface)->respondToEvent = respondToEvent;
2035 ((ViewInterface *) clazz->interface)->select = _select;
2036 ((ViewInterface *) clazz->interface)->selectFirst = selectFirst;
2037 ((ViewInterface *) clazz->interface)->size = size;
2038 ((ViewInterface *) clazz->interface)->sizeThatContains = sizeThatContains;
2039 ((ViewInterface *) clazz->interface)->sizeThatFills = sizeThatFills;
2040 ((ViewInterface *) clazz->interface)->sizeThatFits = sizeThatFits;
2041 ((ViewInterface *) clazz->interface)->sizeToContain = sizeToContain;
2042 ((ViewInterface *) clazz->interface)->sizeToFill = sizeToFill;
2043 ((ViewInterface *) clazz->interface)->sizeToFit = sizeToFit;
2044 ((ViewInterface *) clazz->interface)->subviewWithIdentifier = subviewWithIdentifier;
2045 ((ViewInterface *) clazz->interface)->updateBindings = updateBindings;
2046 ((ViewInterface *) clazz->interface)->viewport = viewport;
2047 ((ViewInterface *) clazz->interface)->viewWithCharacters = viewWithCharacters;
2048 ((ViewInterface *) clazz->interface)->viewWithData = viewWithData;
2049 ((ViewInterface *) clazz->interface)->viewWithDictionary = viewWithDictionary;
2050 ((ViewInterface *) clazz->interface)->viewWithResource = viewWithResource;
2051 ((ViewInterface *) clazz->interface)->viewWithResourceName = viewWithResourceName;
2052 ((ViewInterface *) clazz->interface)->visibleSubviews = visibleSubviews;
2053 ((ViewInterface *) clazz->interface)->warn = warn;
2054 ((ViewInterface *) clazz->interface)->willMoveToWindow = willMoveToWindow;
2055
2056 MVC_NOTIFICATION_EVENT = SDL_RegisterEvents(1);
2057 assert(MVC_NOTIFICATION_EVENT != 0);
2058
2059 MVC_VIEW_EVENT = SDL_RegisterEvents(1);
2060 assert(MVC_VIEW_EVENT != 0);
2061}
static View * viewWithResource(const Resource *resource, Outlet *outlets)
Definition View.c:1880
static void removeClassName(View *self, const char *className)
Definition View.c:1344
static void addClassName(View *self, const char *className)
Definition View.c:159
static View * selectFirst(View *self, const char *rule)
Definition View.c:1636
static bool isContainer(const View *self)
Definition View.c:1041
static void didMoveToWindow(View *self, SDL_Window *window)
Definition View.c:651
static bool isDescendantOfView(const View *self, const View *view)
Definition View.c:1049
static void becomeKeyResponder(View *self)
Definition View.c:427
static void resize(View *self, const SDL_Size *size)
Definition View.c:1527
static void detachStylesheet(View *self, SDL_Window *window)
Definition View.c:635
static void layoutIfNeeded(View *self)
Definition View.c:1115
static void sizeToContain(View *self)
Definition View.c:1745
static bool acceptsKeyResponder(const View *self)
Definition View.c:143
static Set * _select(View *self, const char *rule)
Definition View.c:1621
static void enumerateAncestors(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:782
static SDL_Size sizeThatFills(const View *self)
Definition View.c:1671
static void removeAllClassNames(View *self)
Definition View.c:1318
static void removeSubview(View *self, View *subview)
Definition View.c:1372
static View * viewWithResourceName(const char *name, Outlet *outlets)
Definition View.c:1891
static void becomeTouchResponder(View *self)
Definition View.c:451
static void respondToEvent(View *self, const SDL_Event *event)
Definition View.c:1569
static void replaceSubview(View *self, View *subview, View *replacement)
Definition View.c:1482
static bool matchesSelector(const View *self, const SimpleSelector *simpleSelector)
Definition View.c:1191
static SDL_Size sizeThatFits(const View *self)
Definition View.c:1687
static void bringSubviewToFront(View *self, View *subview)
Definition View.c:510
static bool didReceiveEvent(const View *self, const SDL_Event *event)
Definition View.c:668
static View * subviewWithIdentifier(const View *self, const char *identifier)
Definition View.c:1778
static bool hasOverflow(const View *self)
Definition View.c:939
static Array * visibleSubviews(const View *self)
Definition View.c:1916
static void awakeWithCharacters(View *self, const char *chars)
Definition View.c:353
static void removeAllSubviews(View *self)
Definition View.c:1336
static SDL_Size sizeThatContains(const View *self)
Definition View.c:1659
static void render(View *self, Renderer *renderer)
Definition View.c:1392
static void awakeWithResourceName(View *self, const char *name)
Definition View.c:414
static void addSubview(View *self, View *subview)
Definition View.c:177
static View * viewWithData(const Data *data, Outlet *outlets)
Definition View.c:1844
static View * viewWithCharacters(const char *chars, Outlet *outlets)
Definition View.c:1829
static bool acceptsTouchResponder(const View *self)
Definition View.c:151
static void renderDeviceWillReset(View *self)
Definition View.c:1447
static bool _bind(View *self, const Inlet *inlets, const Dictionary *dictionary)
Definition View.c:475
static void updateBindings(View *self)
Definition View.c:1808
static void willMoveToWindow(View *self, SDL_Window *window)
Definition View.c:1946
Uint32 MVC_NOTIFICATION_EVENT
Definition View.c:36
static void renderDeviceDidReset(View *self)
Definition View.c:1432
static void enumerateSuperview(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:860
static void layoutSubviews(View *self)
Definition View.c:1133
static void enumerate(View *self, ViewEnumerator enumerator, ident data)
Definition View.c:749
static void enumerateAdjacent(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:762
static SDL_Rect viewport(const View *self)
Definition View.c:1816
static bool hasClassName(const View *self, const char *className)
Definition View.c:900
static void sizeToFit(View *self)
Definition View.c:1767
static void enumerateSiblings(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:826
static View * viewWithDictionary(const Dictionary *dictionary, Outlet *outlets)
Definition View.c:1865
static View * ancestorWithIdentifier(const View *self, const char *identifier)
Definition View.c:227
static void resolve(View *self, Outlet *outlets)
Definition View.c:1549
static void emitViewEvent(View *self, ViewEvent code, ident data)
Definition View.c:736
void updateBindings(View *self)
Updates data bindings, prompting the appropriate layout changes.
void invalidateStyle(View *self)
Invalidates the computed Style for this View and its descendants.
Definition View.c:1033
View * viewWithResource(const Resource *resource, Outlet *outlets)
Instantiates a View initialized with the JSON data in resource.
Definition View.c:1880
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:1891
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:635
SDL_Size size(const View *self)
Definition View.c:1651
View * viewWithData(const Data *data, Outlet *outlets)
Instantiates a View initialized with the contents of data.
Definition View.c:1844
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:989
View * viewWithDictionary(const Dictionary *dictionary, Outlet *outlets)
Instantiates a View initialized with the attributes described in dictionary.
Definition View.c:1865

◆ initWithFrame()

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

Definition at line 989 of file View.c.

989 {
990
991 self = (View *) super(Object, self, init);
992 if (self) {
993
994 if (frame) {
995 self->frame = *frame;
996 }
997
998 self->classNames = $$(Set, setWithCapacity, 0);
999 assert(self->classNames);
1000
1001 self->computedStyle = $(alloc(Style), initWithAttributes, NULL);
1002 assert(self->computedStyle);
1003
1004 self->subviews = $$(Array, arrayWithCapacity, 0);
1005 assert(self->subviews);
1006
1007 self->style = $(alloc(Style), initWithAttributes, NULL);
1008 assert(self->style);
1009
1010 self->warnings = $$(Array, arrayWithCapacity, 0);
1011 assert(self->warnings);
1012
1013 self->maxSize = MakeSize(INT32_MAX, INT32_MAX);
1014
1015 self->needsApplyTheme = true;
1016 self->needsLayout = true;
1017 }
1018
1019 return self;
1020}
static Style * initWithAttributes(Style *self, const Dictionary *attributes)
Definition Style.c:292

◆ invalidateStyle()

static void invalidateStyle ( View self)
static

Definition at line 1033 of file View.c.

1033 {
1034 $(self, enumerate, invalidateStyle_enumerate, NULL);
1035}
static void invalidateStyle_enumerate(View *view, ident data)
ViewEnumerator for invalidateStyle.
Definition View.c:1025

◆ invalidateStyle_enumerate()

static void invalidateStyle_enumerate ( View view,
ident  data 
)
static

ViewEnumerator for invalidateStyle.

Definition at line 1025 of file View.c.

1025 {
1026 view->needsApplyTheme = true;
1027}

◆ isContainer()

static bool isContainer ( const View self)
static

Definition at line 1041 of file View.c.

1041 {
1043}
@ ViewAutoresizingContain
Definition View.h:92
@ ViewAutoresizingFit
Definition View.h:91

◆ isDescendantOfView()

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

Definition at line 1049 of file View.c.

1049 {
1050
1051 assert(view);
1052
1053 while (self) {
1054 if (self == view) {
1055 return true;
1056 }
1057 self = self->superview;
1058 }
1059
1060 return false;
1061}

◆ isKeyResponder()

static bool isKeyResponder ( const View self)
static

Definition at line 1067 of file View.c.

1067 {
1068
1069 if (self->window) {
1070 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->window), "keyResponder", NULL) == self;
1071 } else {
1072 return false;
1073 }
1074}

◆ isTouchResponder()

static bool isTouchResponder ( const View self)
static

Definition at line 1080 of file View.c.

1080 {
1081
1082 if (self->window) {
1083 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->window), "touchResponder", NULL) == self;
1084 } else {
1085 return false;
1086 }
1087}

◆ isVisible()

static bool isVisible ( const View self)
static

Definition at line 1093 of file View.c.

1093 {
1094
1095 for (const View *view = self; view; view = view->superview) {
1096 if (view->hidden) {
1097 return false;
1098 }
1099 }
1100
1101 return true;
1102}

◆ layoutIfNeeded()

static void layoutIfNeeded ( View self)
static

Definition at line 1115 of file View.c.

1115 {
1116
1118
1119 if (self->needsLayout) {
1120
1122
1123 $(self, layoutSubviews);
1124
1125 self->needsLayout = false;
1126 }
1127}
static void layoutIfNeeded_enumerate(View *subview, ident data)
ViewEnumerator for layoutIfNeeded recursion.
Definition View.c:1107

◆ layoutIfNeeded_enumerate()

static void layoutIfNeeded_enumerate ( View subview,
ident  data 
)
static

ViewEnumerator for layoutIfNeeded recursion.

Definition at line 1107 of file View.c.

1107 {
1108 $(subview, layoutIfNeeded);
1109}

◆ layoutSubviews()

static void layoutSubviews ( View self)
static

Definition at line 1133 of file View.c.

1133 {
1134
1136 $(self, sizeToContain);
1137 } else if (self->autoresizingMask & ViewAutoresizingFit) {
1138 $(self, sizeToFit);
1139 }
1140
1141 const SDL_Rect bounds = $(self, bounds);
1142
1143 const Array *subviews = (Array *) self->subviews;
1144 for (size_t i = 0; i < subviews->count; i++) {
1145
1146 View *subview = subviews->elements[i];
1147
1148 SDL_Size subviewSize = $(subview, size);
1149
1150 if (subview->autoresizingMask & ViewAutoresizingWidth) {
1151 subviewSize.w = bounds.w;
1152 }
1153
1155 subviewSize.h = bounds.h;
1156 }
1157
1158 $(subview, resize, &subviewSize);
1159 $(subview, layoutIfNeeded);
1160
1161 switch (subview->alignment & ViewAlignmentMaskHorizontal) {
1162 case ViewAlignmentLeft:
1163 subview->frame.x = 0;
1164 break;
1166 subview->frame.x = (bounds.w - subview->frame.w) * 0.5f;
1167 break;
1168 case ViewAlignmentRight:
1169 subview->frame.x = bounds.w - subview->frame.w;
1170 break;
1171 }
1172
1173 switch (subview->alignment & ViewAlignmentMaskVertical) {
1175 subview->frame.y = 0;
1176 break;
1178 subview->frame.y = (bounds.h - subview->frame.h) * 0.5f;
1179 break;
1181 subview->frame.y = bounds.h - subview->frame.h;
1182 break;
1183 }
1184 }
1185}
#define ViewAlignmentMaskBottom
Definition View.h:46
#define ViewAlignmentMaskTop
Definition View.h:44
#define ViewAlignmentMaskMiddle
Definition View.h:45
#define ViewAlignmentMaskHorizontal
Definition View.h:55
#define ViewAlignmentMaskVertical
Definition View.h:52
@ ViewAutoresizingWidth
Definition View.h:88
@ ViewAutoresizingHeight
Definition View.h:89
@ ViewAlignmentCenter
Definition View.h:67
@ ViewAlignmentLeft
Definition View.h:66
@ ViewAlignmentRight
Definition View.h:68

◆ matchesSelector()

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

Definition at line 1191 of file View.c.

1191 {
1192
1193 assert(simpleSelector);
1194
1195 const char *pattern = simpleSelector->pattern;
1196
1197 switch (simpleSelector->type) {
1199 return false;
1200
1202 return true;
1203
1205 const Class *clazz = classForName(pattern);
1206 if (clazz) {
1207 return $((Object *) self, isKindOfClass, clazz);
1208 }
1209 }
1210 break;
1211
1213 return $(self, hasClassName, pattern);
1214
1216 if (self->identifier) {
1217 return strcmp(self->identifier, pattern) == 0;
1218 } else {
1219 return false;
1220 }
1221
1223 if (strcmp("first-child", pattern) == 0) {
1224 if (self->superview) {
1225 return $((Array *) self->superview->subviews, firstObject) == self;
1226 }
1227 } else if (strcmp("last-child", pattern) == 0) {
1228 if (self->superview) {
1229 return $((Array *) self->superview->subviews, lastObject) == self;
1230 }
1231 } else if (strcmp("nth-child(even)", pattern) == 0) {
1232 if (self->superview) {
1233 return ($((Array *) self->superview->subviews, indexOfObject, (ident) self) & 1) == 0;
1234 }
1235 } else if (strcmp("nth-child(odd)", pattern) == 0) {
1236 if (self->superview) {
1237 return $((Array *) self->superview->subviews, indexOfObject, (ident) self) & 1;
1238 }
1239 } else if (strcmp("hover", pattern) == 0) {
1240 float mx, my;
1241 SDL_GetMouseState(&mx, &my);
1242 SDL_Point point = MakePoint(mx, my);
1243 return $(self, containsPoint, &point);
1244 }
1245 break;
1246 }
1247
1248 return false;
1249}
@ 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 1262 of file View.c.

1262 {
1263
1264 $(self, willMoveToWindow, window);
1265
1266 self->window = window;
1267
1268 $(self, didMoveToWindow, window);
1269
1270 $(self, enumerateSubviews, moveToWindow_enumerate, window);
1271}
static void moveToWindow_enumerate(View *subview, ident data)
ViewEnumerator for moveToWindow recursion.
Definition View.c:1254

◆ moveToWindow_enumerate()

static void moveToWindow_enumerate ( View subview,
ident  data 
)
static

ViewEnumerator for moveToWindow recursion.

Definition at line 1254 of file View.c.

1254 {
1255 $(subview, moveToWindow, data);
1256}

◆ nullifySuperview()

static void nullifySuperview ( View subview,
ident  data 
)
static

ViewEnumerator to null out superview pointers during parent dealloc.

Definition at line 87 of file View.c.

87 {
88 subview->superview = NULL;
89}

◆ path()

static String * path ( const View self)
static

Definition at line 1277 of file View.c.

1277 {
1278
1279 Array *parts = $$(Array, array);
1280
1281 const View *view = self;
1282 while (view) {
1283
1284 Array *classNames = $((Set *) view->classNames, allObjects);
1285
1286 String *part;
1287 if (view->identifier) {
1288 part = str("#%s", view->identifier);
1289 } else if (classNames->count) {
1290 part = str(".%s", ((String *) $(classNames, firstObject))->chars);
1291 } else {
1292 part = str("%s", classnameof(view));
1293 }
1294
1295 release(classNames);
1296
1297 $(parts, insertObjectAtIndex, part, 0);
1298 release(part);
1299
1300 if (view->viewController) {
1301 break;
1302 }
1303
1304 view = view->superview;
1305 }
1306
1307 String *path = $((Array *) parts, componentsJoinedByCharacters, " > ");
1308
1309 release(parts);
1310
1311 return path;
1312}
ViewController * viewController
The ViewController.
Definition View.h:265

◆ removeAllClassNames()

static void removeAllClassNames ( View self)
static

Definition at line 1318 of file View.c.

1318 {
1319
1320 $(self->classNames, removeAllObjects);
1321
1322 $(self, invalidateStyle);
1323}

◆ removeAllSubviews()

static void removeAllSubviews ( View self)
static

Definition at line 1336 of file View.c.

1336 {
1337 $(self->subviews, removeAllObjectsWithEnumerator, removeAllSubviews_enumerate, self);
1338}
static void removeAllSubviews_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for removeAllSubviews.
Definition View.c:1328

◆ removeAllSubviews_enumerate()

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

ArrayEnumerator for removeAllSubviews.

Definition at line 1328 of file View.c.

1328 {
1329 $((View *) data, removeSubview, obj);
1330}

◆ removeClassName()

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

Definition at line 1344 of file View.c.

1344 {
1345
1346 if (className) {
1347 String *string = $$(String, stringWithCharacters, className);
1348 assert(string);
1349
1350 $(self->classNames, removeObject, string);
1351 release(string);
1352
1353 $(self, invalidateStyle);
1354 }
1355}

◆ removeFromSuperview()

static void removeFromSuperview ( View self)
static

Definition at line 1361 of file View.c.

1361 {
1362
1363 if (self->superview) {
1364 $(self->superview, removeSubview, self);
1365 }
1366}

◆ removeSubview()

static void removeSubview ( View self,
View subview 
)
static

Definition at line 1372 of file View.c.

1372 {
1373
1374 assert(subview);
1375
1376 if (subview->superview == self) {
1377
1378 subview->superview = NULL;
1379
1380 $(subview, moveToWindow, NULL);
1381
1382 $(self->subviews, removeObject, subview);
1383
1384 self->needsLayout = true;
1385 }
1386}

◆ render()

static void render ( View self,
Renderer renderer 
)
static

Definition at line 1392 of file View.c.

1392 {
1393
1394 assert(self->window);
1395
1396 if ($(self, hasClassName, "breakpoint")) {
1397 SDL_TriggerBreakpoint();
1398 }
1399
1400 if (self->backgroundColor.a) {
1401
1402 const SDL_Rect frame = $(self, renderFrame);
1403 $(renderer, drawRectFilled, &frame, &self->backgroundColor);
1404 }
1405
1406 if (self->borderWidth && self->borderColor.a) {
1407
1408 SDL_Rect frame = $(self, renderFrame);
1409 for (int i = 0; i < self->borderWidth; i++) {
1410
1411 $(renderer, drawRect, &frame, &self->borderColor);
1412
1413 frame.x -= 1;
1414 frame.y -= 1;
1415 frame.w += 2;
1416 frame.h += 2;
1417 }
1418 }
1419}
static void drawRectFilled(const Renderer *self, const SDL_Rect *rect, const SDL_Color *color)
Definition Renderer.c:188
static void drawRect(const Renderer *self, const SDL_Rect *rect, const SDL_Color *color)
Definition Renderer.c:169

◆ renderDeviceDidReset()

static void renderDeviceDidReset ( View self)
static

Definition at line 1432 of file View.c.

1432 {
1434}
static void renderDeviceDidReset_enumerate(View *subview, ident data)
ViewEnumerator for renderDeviceDidReset recursion.
Definition View.c:1424

◆ renderDeviceDidReset_enumerate()

static void renderDeviceDidReset_enumerate ( View subview,
ident  data 
)
static

ViewEnumerator for renderDeviceDidReset recursion.

Definition at line 1424 of file View.c.

1424 {
1425 $(subview, renderDeviceDidReset);
1426}

◆ renderDeviceWillReset()

static void renderDeviceWillReset ( View self)
static

Definition at line 1447 of file View.c.

1447 {
1449}
static void renderDeviceWillReset_enumerate(View *subview, ident data)
ViewEnumerator for renderDeviceWillReset recursion.
Definition View.c:1439

◆ renderDeviceWillReset_enumerate()

static void renderDeviceWillReset_enumerate ( View subview,
ident  data 
)
static

ViewEnumerator for renderDeviceWillReset recursion.

Definition at line 1439 of file View.c.

1439 {
1440 $(subview, renderDeviceWillReset);
1441}

◆ renderFrame()

static SDL_Rect renderFrame ( const View self)
static

Definition at line 1455 of file View.c.

1455 {
1456
1457 SDL_Rect frame = self->frame;
1458
1459 const View *view = self;
1460 const View *superview = view->superview;
1461 while (superview) {
1462
1463 frame.x += superview->frame.x;
1464 frame.y += superview->frame.y;
1465
1466 if (view->alignment != ViewAlignmentInternal) {
1467 frame.x += superview->padding.left;
1468 frame.y += superview->padding.top;
1469 }
1470
1471 view = superview;
1472 superview = view->superview;
1473 }
1474
1475 return frame;
1476}
@ ViewAlignmentInternal
Definition View.h:78

◆ replaceSubview()

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

Definition at line 1482 of file View.c.

1482 {
1483
1484 assert(subview);
1485 assert(replacement);
1486
1487 $(self, addSubviewRelativeTo, replacement, subview, ViewPositionAfter);
1488 $(self, removeSubview, subview);
1489}

◆ resignKeyResponder()

static void resignKeyResponder ( View self)
static

Definition at line 1495 of file View.c.

1495 {
1496
1497 if (self->window && $(self, isKeyResponder)) {
1498
1499 String *path = $(self, path);
1500 MVC_LogDebug("%s\n", path->chars);
1501 release(path);
1502
1503 SDL_SetPointerProperty(SDL_GetWindowProperties(self->window), "keyResponder", NULL);
1504 }
1505}

◆ resignTouchResponder()

static void resignTouchResponder ( View self)
static

Definition at line 1511 of file View.c.

1511 {
1512
1513 if (self->window && $(self, isTouchResponder)) {
1514
1515 String *path = $(self, path);
1516 MVC_LogDebug("%s\n", path->chars);
1517 release(path);
1518
1519 SDL_SetPointerProperty(SDL_GetWindowProperties(self->window), "touchResponder", NULL);
1520 }
1521}

◆ resize()

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

Definition at line 1527 of file View.c.

1527 {
1528
1529 const int w = clamp(size->w, self->minSize.w, self->maxSize.w);
1530 const int h = clamp(size->h, self->minSize.h, self->maxSize.h);
1531
1532 if (self->frame.w != w || self->frame.h != h) {
1533
1534 self->frame.w = w;
1535 self->frame.h = h;
1536
1537 self->needsLayout = true;
1538
1539 if (self->superview && $(self->superview, isContainer)) {
1540 self->superview->needsLayout = true;
1541 }
1542 }
1543}

◆ resolve()

static void resolve ( View self,
Outlet outlets 
)
static

Definition at line 1549 of file View.c.

1549 {
1550
1551 if (outlets) {
1552 for (Outlet *outlet = outlets; outlet->identifier; outlet++) {
1553 *outlet->view = $(self, descendantWithIdentifier, outlet->identifier);
1554 if (*outlet->view == NULL) {
1555 String *desc = $((Object *) self, description);
1556 MVC_LogError("Failed to resolve outlet '%s' for %s", outlet->identifier, desc->chars);
1557 release(desc);
1558 }
1559
1560 assert(*outlet->view);
1561 }
1562 }
1563}
Outlets enable outbound data binding of Views through JSON.
Definition View+JSON.h:200
const char * identifier
The View identifier.
Definition View+JSON.h:205

◆ respondToEvent()

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

Definition at line 1569 of file View.c.

1569 {
1570
1571 assert(event);
1572
1573 ViewEvent code = ViewEventNone;
1574
1575 switch (event->type) {
1576 case SDL_EVENT_MOUSE_BUTTON_DOWN:
1578 break;
1579 case SDL_EVENT_MOUSE_BUTTON_UP:
1581 $(self, resignTouchResponder);
1582 break;
1583 case SDL_EVENT_KEY_DOWN:
1584 code = ViewEventKeyDown;
1585 break;
1586 case SDL_EVENT_KEY_UP:
1587 code = ViewEventKeyUp;
1588 break;
1589 default:
1590 break;
1591 }
1592
1593 if (code != ViewEventNone) {
1594 $(self, emitViewEvent, code, NULL);
1595
1596 if (code == ViewEventMouseButtonUp) {
1597 if (event->button.clicks) {
1598 $(self, emitViewEvent, ViewEventClick, NULL);
1599 }
1600 }
1601 }
1602
1603 if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
1604 if ($(self, acceptsKeyResponder)) {
1605 $(self, becomeKeyResponder);
1606 return;
1607 }
1608 }
1609
1610 if (self->nextResponder) {
1611 $(self->nextResponder, respondToEvent, event);
1612 } else if (self->superview) {
1613 $(self->superview, respondToEvent, event);
1614 }
1615}
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:229

◆ selectFirst()

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

Definition at line 1636 of file View.c.

1636 {
1637
1638 Selector *selector = $(alloc(Selector), initWithRule, rule);
1639 assert(selector);
1640
1641 View *first = $(selector, selectFirst, self);
1642
1643 release(selector);
1644 return first;
1645}

◆ size()

static SDL_Size size ( const View self)
static

Definition at line 1651 of file View.c.

1651 {
1652 return MakeSize(self->frame.w, self->frame.h);
1653}

◆ sizeThatContains()

static SDL_Size sizeThatContains ( const View self)
static

Definition at line 1659 of file View.c.

1659 {
1660
1661 const SDL_Size size = $(self, size);
1662 const SDL_Size sizeThatFits = $(self, sizeThatFits);
1663
1664 return MakeSize(max(size.w, sizeThatFits.w), max(size.h, sizeThatFits.h));
1665}

◆ sizeThatFills()

static SDL_Size sizeThatFills ( const View self)
static

Definition at line 1671 of file View.c.

1671 {
1672 SDL_Size size;
1673
1674 if (self->superview == NULL) {
1675 SDL_GetWindowSize(self->window, &size.w, &size.h);
1676 } else {
1677 size = $(self->superview, size);
1678 }
1679
1680 return size;
1681}

◆ sizeThatFits()

static SDL_Size sizeThatFits ( const View self)
static

Definition at line 1687 of file View.c.

1687 {
1688
1689 SDL_Size size = $(self, size);
1690
1692 size.w = 0;
1693 }
1694
1696 size.h = 0;
1697 }
1698
1699 if ($(self, isContainer)) {
1700 size = MakeSize(0, 0);
1701
1702 Array *subviews = $(self, visibleSubviews);
1703 for (size_t i = 0; i < subviews->count; i++) {
1704
1705 const View *subview = subviews->elements[i];
1706
1707 SDL_Size subviewSize;
1709 subviewSize = $(subview, sizeThatContains);
1710 } else if (subview->autoresizingMask & ViewAutoresizingFit) {
1711 subviewSize = $(subview, sizeThatFits);
1712 } else {
1713 subviewSize = $(subview, size);
1714 }
1715
1716 SDL_Point subviewOrigin = MakePoint(0, 0);
1717 switch (subview->alignment) {
1718 case ViewAlignmentNone:
1719 subviewOrigin = MakePoint(subview->frame.x, subview->frame.y);
1720 break;
1721 default:
1722 break;
1723 }
1724
1725 size.w = max(size.w, subviewOrigin.x + subviewSize.w);
1726 size.h = max(size.h, subviewOrigin.y + subviewSize.h);
1727 }
1728
1729 size.w += self->padding.left + self->padding.right;
1730 size.h += self->padding.top + self->padding.bottom;
1731
1732 release(subviews);
1733 }
1734
1735 size.w = clamp(size.w, self->minSize.w, self->maxSize.w);
1736 size.h = clamp(size.h, self->minSize.h, self->maxSize.h);
1737
1738 return size;
1739}
@ ViewAlignmentNone
Definition View.h:62

◆ sizeToContain()

static void sizeToContain ( View self)
static

Definition at line 1745 of file View.c.

1745 {
1746
1747 const SDL_Size size = $(self, sizeThatContains);
1748
1749 $(self, resize, &size);
1750}

◆ sizeToFill()

static void sizeToFill ( View self)
static

Definition at line 1756 of file View.c.

1756 {
1757
1758 const SDL_Size size = $(self, sizeThatFills);
1759
1760 $(self, resize, &size);
1761}

◆ sizeToFit()

static void sizeToFit ( View self)
static

Definition at line 1767 of file View.c.

1767 {
1768
1769 const SDL_Size size = $(self, sizeThatFits);
1770
1771 $(self, resize, &size);
1772}

◆ subviewWithIdentifier()

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

Definition at line 1778 of file View.c.

1778 {
1779
1780 assert(identifier);
1781
1782 const Array *subviews = (Array *) self->subviews;
1783 for (size_t i = 0; i < subviews->count; i++) {
1784
1785 View *subview = subviews->elements[i];
1786 if (subview->identifier) {
1787
1788 if (strcmp(identifier, subview->identifier) == 0) {
1789 return subview;
1790 }
1791 }
1792 }
1793
1794 return NULL;
1795}

◆ updateBindings()

static void updateBindings ( View self)
static

Definition at line 1808 of file View.c.

1808 {
1810}
static void updateBindings_enumerate(View *subview, ident data)
ViewEnumerator for updateBindings recursion.
Definition View.c:1800

◆ updateBindings_enumerate()

static void updateBindings_enumerate ( View subview,
ident  data 
)
static

ViewEnumerator for updateBindings recursion.

Definition at line 1800 of file View.c.

1800 {
1801 $(subview, updateBindings);
1802}

◆ viewport()

static SDL_Rect viewport ( const View self)
static

Definition at line 1816 of file View.c.

1816 {
1817
1818 assert(self->window);
1819
1820 const SDL_Rect frame = $(self, renderFrame);
1821
1822 return MVC_TransformToWindow(self->window, &frame);
1823}
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 1829 of file View.c.

1829 {
1830
1831 Data *data = $$(Data, dataWithConstMemory, (ident) chars, strlen(chars));
1832
1833 View *view = $$(View, viewWithData, data, outlets);
1834
1835 release(data);
1836
1837 return view;
1838}

◆ viewWithData()

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

Definition at line 1844 of file View.c.

1844 {
1845
1846 JSONContext *ctx = $(alloc(JSONContext), init);
1847 Dictionary *dictionary = $(ctx, objectFromData, data, 0);
1848
1849 View *view = NULL;
1850 if (dictionary) {
1851 view = $$(View, viewWithDictionary, dictionary, outlets);
1852 release(dictionary);
1853 } else {
1854 MVC_LogError("Failed to parse JSON\n");
1855 }
1856
1857 release(ctx);
1858 return view;
1859}

◆ viewWithDictionary()

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

Definition at line 1865 of file View.c.

1865 {
1866
1867 View *view = NULL;
1868
1869 BindInlet(&MakeInlet(NULL, InletTypeView, &view, NULL), dictionary);
1870
1871 $(view, resolve, outlets);
1872
1873 return view;
1874}
@ InletTypeView
Definition View+JSON.h:139
#define BindInlet(inlet, obj)
Binds the Inlet to obj by invoking the appropriate InletBinding function.
Definition View+JSON.h:244

◆ viewWithResource()

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

Definition at line 1880 of file View.c.

1880 {
1881
1882 assert(resource);
1883
1884 return $$(View, viewWithData, resource->data, outlets);
1885}

◆ viewWithResourceName()

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

Definition at line 1891 of file View.c.

1891 {
1892
1893 Resource *resource = $$(Resource, resourceWithName, name);
1894
1895 View *view = $$(View, viewWithResource, resource, outlets);
1896
1897 release(resource);
1898
1899 return view;
1900}

◆ visibleSubviews()

static Array * visibleSubviews ( const View self)
static

Definition at line 1916 of file View.c.

1916 {
1917 return $((Array *) self->subviews, filteredArray, visibleSubviews_filter, NULL);
1918}
static bool visibleSubviews_filter(ident obj, ident data)
Predicate for visibleSubviews.
Definition View.c:1905

◆ visibleSubviews_filter()

static bool visibleSubviews_filter ( ident  obj,
ident  data 
)
static

Predicate for visibleSubviews.

Definition at line 1905 of file View.c.

1905 {
1906
1907 const View *view = (View *) obj;
1908
1909 return view->hidden == false && view->alignment != ViewAlignmentInternal;
1910}

◆ warn()

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

Definition at line 1924 of file View.c.

1924 {
1925
1926 va_list args;
1927 va_start(args, fmt);
1928
1929 Warning *warning = $(alloc(Warning), initWithVaList, type, fmt, args);
1930
1931 va_end(args);
1932
1933 String *description = $((Object *) self, description);
1934 MVC_LogWarn("%s:: %s\n", description->chars, warning->message->chars);
1935 release(description);
1936
1937 $(self->warnings, addObject, warning);
1938
1939 release(warning);
1940}
#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 1946 of file View.c.

1946 {
1947
1948 if (self->window) {
1949 $(self, resignKeyResponder);
1950 $(self, resignTouchResponder);
1951 $(self, detachStylesheet, self->window);
1952 }
1953}

Variable Documentation

◆ 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:77
@ ViewAlignmentBottomLeft
Definition View.h:75
@ ViewAlignmentMiddleCenter
Definition View.h:73
@ ViewAlignmentTopCenter
Definition View.h:70
@ ViewAlignmentTopRight
Definition View.h:71
@ ViewAlignmentMiddleRight
Definition View.h:74
@ ViewAlignmentTopLeft
Definition View.h:69
@ ViewAlignmentTop
Definition View.h:63
@ ViewAlignmentMiddleLeft
Definition View.h:72
@ ViewAlignmentBottom
Definition View.h:65
@ ViewAlignmentMiddle
Definition View.h:64
@ ViewAlignmentBottomCenter
Definition View.h:76

Definition at line 39 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:87
@ ViewAutoresizingFill
Definition View.h:90

Definition at line 59 of file View.c.