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

Go to the source code of this file.

Macros

#define _Class   _WindowController
 

Functions

Class * _WindowController (void)
 
static void dealloc (Object *self)
 
static void debug (WindowController *self)
 
static void enumerateKeyResponders (View *view, ident data)
 ViewEnumerator for finding the next key responder.
 
static void initialize (Class *clazz)
 
static WindowControllerinitWithDevice (WindowController *self, RenderDevice *device)
 
static ViewkeyResponder (const WindowController *self)
 
static Array * keyResponders (const WindowController *self)
 
static void mouseMotion_enumerate (View *view, ident data)
 ViewEnumerator for SDL_EVENT_MOUSE_MOTION.
 
static ViewnextKeyResponder (const WindowController *self, View *keyResponder)
 
static ViewpreviousKeyResponder (const WindowController *self, View *keyResponder)
 
static void render (WindowController *self)
 
static void renderTo (WindowController *self, CommandBuffer *commands, Framebuffer *framebuffer)
 
static void respondToEvent (WindowController *self, const SDL_Event *event)
 
static void setTheme (WindowController *self, Theme *theme)
 
static void setViewController (WindowController *self, ViewController *viewController)
 
static void setWindow (WindowController *self, SDL_Window *window)
 
static void toggleDebugger (WindowController *self)
 
static ViewtouchResponder (const WindowController *self)
 
static ViewtouchTarget (const WindowController *self, const SDL_Event *event)
 
static WindowControllerwindowController (SDL_Window *window)
 

Macro Definition Documentation

◆ _Class

#define _Class   _WindowController

Definition at line 31 of file WindowController.c.

Function Documentation

◆ _WindowController()

Class * _WindowController ( void  )

Definition at line 536 of file WindowController.c.

536 {
537 static Class *clazz;
538 static Once once;
539
540 do_once(&once, {
541 clazz = _initialize(&(const ClassDef) {
542 .name = "WindowController",
543 .superclass = _Object(),
544 .instanceSize = sizeof(WindowController),
545 .interfaceOffset = offsetof(WindowController, interface),
546 .interfaceSize = sizeof(WindowControllerInterface),
548 });
549 });
550
551 return clazz;
552}
static void initialize(Class *clazz)
A WindowController manages a ViewController and its descendants within an SDL_Window.

◆ dealloc()

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

Definition at line 58 of file WindowController.c.

58 {
59
60 WindowController *this = (WindowController *) self;
61
62 release(this->debugViewController);
63 release(this->renderer);
64 release(this->theme);
65 release(this->viewController);
66
67 super(Object, self, dealloc);
68}
static Theme * theme(SDL_Window *window)
Definition Theme.c:143
static void dealloc(Object *self)

◆ debug()

static void debug ( WindowController self)
static

Definition at line 76 of file WindowController.c.

76 {
77
78 if (self->viewController && self->debugViewController) {
79
80 ViewController *debugViewController = (ViewController *) self->debugViewController;
81
82 float mx, my;
83 SDL_GetMouseState(&mx, &my);
84 SDL_Point point = MakePoint(mx, my);
85
86 View *view = $(self->viewController->view, hitTest, &point);
87 if (view) {
88 $(self->debugViewController, debug, view, self->renderer);
89 }
90
91 $(debugViewController->view, applyThemeIfNeeded, self->theme);
92 $(debugViewController->view, layoutIfNeeded);
93 $(debugViewController->view, draw, self->renderer);
94 }
95}
static void layoutIfNeeded(View *self)
Definition View.c:1115
static void draw(View *self, Renderer *renderer)
Definition View.c:720
static View * hitTest(const View *self, const SDL_Point *point)
Definition View.c:954
static void applyThemeIfNeeded(View *self, const Theme *theme)
Definition View.c:317
static void debug(WindowController *self)
A ViewController manages a View and its descendants.
View * view
The main view.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:134
ViewController * viewController
The ViewController.
Theme * theme
The Theme.
Renderer * renderer
The Renderer.
DebugViewController * debugViewController
The DebugViewController.

◆ enumerateKeyResponders()

static void enumerateKeyResponders ( View view,
ident  data 
)
static

ViewEnumerator for finding the next key responder.

Definition at line 108 of file WindowController.c.

108 {
109
110 if ($(view, acceptsKeyResponder) && $(view, isVisible)) {
111 $((Array *) data, addObject, view);
112 }
113}
static bool acceptsKeyResponder(const View *self)
Definition Control.c:69
static bool isVisible(const View *self)
Definition View.c:1093

◆ initialize()

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

Definition at line 510 of file WindowController.c.

510 {
511
512 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
513
514 ((WindowControllerInterface *) clazz->interface)->debug = debug;
515 ((WindowControllerInterface *) clazz->interface)->keyResponder = keyResponder;
516 ((WindowControllerInterface *) clazz->interface)->keyResponders = keyResponders;
517 ((WindowControllerInterface *) clazz->interface)->initWithDevice = initWithDevice;
518 ((WindowControllerInterface *) clazz->interface)->nextKeyResponder = nextKeyResponder;
519 ((WindowControllerInterface *) clazz->interface)->previousKeyResponder = previousKeyResponder;
520 ((WindowControllerInterface *) clazz->interface)->render = render;
521 ((WindowControllerInterface *) clazz->interface)->renderTo = renderTo;
522 ((WindowControllerInterface *) clazz->interface)->respondToEvent = respondToEvent;
523 ((WindowControllerInterface *) clazz->interface)->setTheme = setTheme;
524 ((WindowControllerInterface *) clazz->interface)->setViewController = setViewController;
525 ((WindowControllerInterface *) clazz->interface)->setWindow = setWindow;
526 ((WindowControllerInterface *) clazz->interface)->toggleDebugger = toggleDebugger;
527 ((WindowControllerInterface *) clazz->interface)->touchResponder = touchResponder;
528 ((WindowControllerInterface *) clazz->interface)->touchTarget = touchTarget;
529 ((WindowControllerInterface *) clazz->interface)->windowController = windowController;
530}
static View * touchTarget(const WindowController *self, const SDL_Event *event)
static WindowController * initWithDevice(WindowController *self, RenderDevice *device)
static Array * keyResponders(const WindowController *self)
static void toggleDebugger(WindowController *self)
static View * keyResponder(const WindowController *self)
static void setViewController(WindowController *self, ViewController *viewController)
static void setWindow(WindowController *self, SDL_Window *window)
static View * touchResponder(const WindowController *self)
static void render(WindowController *self)
static View * previousKeyResponder(const WindowController *self, View *keyResponder)
static void setTheme(WindowController *self, Theme *theme)
static WindowController * windowController(SDL_Window *window)
static void renderTo(WindowController *self, CommandBuffer *commands, Framebuffer *framebuffer)
static View * nextKeyResponder(const WindowController *self, View *keyResponder)
static void respondToEvent(WindowController *self, const SDL_Event *event)
void render(View *self, Renderer *renderer)
Renders this View using the given renderer.
Definition Control.c:179
View * nextKeyResponder(const WindowController *self, View *keyResponder)
Finds the next available keyResponder from the given keyResponder.

◆ initWithDevice()

static WindowController * initWithDevice ( WindowController self,
RenderDevice *  device 
)
static

Definition at line 131 of file WindowController.c.

131 {
132
133 assert(device);
134
135 self = (WindowController *) super(Object, self, init);
136 if (self) {
137 self->renderer = $(alloc(Renderer), initWithDevice, device);
138 assert(self->renderer);
139
140 $(self, setWindow, device->window);
141 $(self, setViewController, NULL);
142 $(self, setTheme, NULL);
143
146 }
147
148 return self;
149}
static View * init(View *self)
Definition Box.c:67
static void renderDeviceDidReset(Font *self)
Definition Font.c:247
Renderer extends Object with ObjectivelyMVC's UI rendering layer.
Definition Renderer.h:70

◆ keyResponder()

static View * keyResponder ( const WindowController self)
static

Definition at line 101 of file WindowController.c.

101 {
102 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->window), "keyResponder", NULL);
103}
SDL_Window * window
The window.

◆ keyResponders()

static Array * keyResponders ( const WindowController self)
static

Definition at line 119 of file WindowController.c.

119 {
120
121 Array *array = (Array *) $(alloc(Array), init);
123
124 return array;
125}
static void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
Definition View.c:808
static void enumerateKeyResponders(View *view, ident data)
ViewEnumerator for finding the next key responder.

◆ mouseMotion_enumerate()

static void mouseMotion_enumerate ( View view,
ident  data 
)
static

ViewEnumerator for SDL_EVENT_MOUSE_MOTION.

Definition at line 38 of file WindowController.c.

38 {
39
40 const SDL_MouseMotionEvent *event = data;
41 const SDL_Point a = MakePoint(event->x - event->xrel, event->y - event->yrel);
42 const SDL_Point b = MakePoint(event->x, event->y);
43
44 if ($(view, containsPoint, &a) && !$(view, containsPoint, &b)) {
45 $(view, emitViewEvent, ViewEventMouseLeave, NULL);
46 $(view, invalidateStyle);
47 } else if ($(view, containsPoint, &b) && !$(view, containsPoint, &a)) {
48 $(view, emitViewEvent, ViewEventMouseEnter, NULL);
49 $(view, invalidateStyle);
50 }
51}
@ ViewEventMouseEnter
The mouse has entered a View's frame.
Definition Types.h:90
@ ViewEventMouseLeave
The mouse has left a View's frame.
Definition Types.h:95
static void invalidateStyle(View *self)
Definition View.c:1033
static bool containsPoint(const View *self, const SDL_Point *point)
Definition View.c:589
static void emitViewEvent(View *self, ViewEvent code, ident data)
Definition View.c:736

◆ nextKeyResponder()

static View * nextKeyResponder ( const WindowController self,
View keyResponder 
)
static

Definition at line 188 of file WindowController.c.

188 {
189
190 View *next = NULL;
191
192 Array *array = $(self, keyResponders);
193
194 if (array->count) {
195 if (keyResponder && $(array, containsObject, keyResponder)) {
196 const ssize_t index = $(array, indexOfObject, keyResponder);
197 next = $(array, objectAtIndex, (index + 1) % array->count);
198 } else {
199 next = $(array, firstObject);
200 }
201 }
202
203 release(array);
204 return next;
205}

◆ previousKeyResponder()

static View * previousKeyResponder ( const WindowController self,
View keyResponder 
)
static

Definition at line 211 of file WindowController.c.

211 {
212
213 View *prev = NULL;
214
215 Array *array = $(self, keyResponders);
216
217 if (array->count) {
218 if (keyResponder && $(array, containsObject, keyResponder)) {
219 const ssize_t index = $(array, indexOfObject, keyResponder);
220 prev = $(array, objectAtIndex, (index + array->count - 1) % array->count);
221 } else {
222 prev = $(array, firstObject);
223 }
224 }
225
226 release(array);
227 return prev;
228}

◆ render()

static void render ( WindowController self)
static

Definition at line 155 of file WindowController.c.

155 {
156
157 assert(self->renderer);
158
159 const RenderDevice *device = self->renderer->device;
160 $(self, renderTo, device->commands, device->framebuffer);
161}
RenderDevice * device
The backing RenderDevice.
Definition Renderer.h:92

◆ renderTo()

static void renderTo ( WindowController self,
CommandBuffer *  commands,
Framebuffer *  framebuffer 
)
static

Definition at line 167 of file WindowController.c.

167 {
168
169 assert(self->renderer);
170 assert(commands);
171 assert(framebuffer);
172
173 $(self->renderer, beginFrameWith, commands, framebuffer);
174
177 $(self->viewController->view, draw, self->renderer);
178
179 $(self, debug);
180
181 $(self->renderer, endFrame);
182}
static void endFrame(Renderer *self)
Definition Renderer.c:249
static void beginFrameWith(Renderer *self, CommandBuffer *commands, Framebuffer *framebuffer)
Definition Renderer.c:96

◆ respondToEvent()

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

Definition at line 234 of file WindowController.c.

234 {
235
236 SDL_SetPointerProperty(SDL_GetWindowProperties(self->window), "event", (ident) event);
237
238 switch (event->type) {
239 case SDL_EVENT_WINDOW_EXPOSED:
240 $(self, setWindow, self->window);
244 break;
245 case SDL_EVENT_WINDOW_MOVED:
246 case SDL_EVENT_WINDOW_RESIZED:
247 case SDL_EVENT_WINDOW_MAXIMIZED:
248 case SDL_EVENT_WINDOW_RESTORED:
249 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
250 case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
251 case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
252 case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
253 $(self, setWindow, self->window);
254 break;
255 case SDL_EVENT_WINDOW_DESTROYED:
256 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
259 break;
260 default:
261 break;
262 }
263
264 if (event->type == SDL_EVENT_MOUSE_MOTION) {
266 }
267
269
270 View *touchTarget = $(self, touchTarget, event);
271
272 switch (event->type) {
273 case SDL_EVENT_KEY_UP:
274 case SDL_EVENT_KEY_DOWN:
275 case SDL_EVENT_TEXT_INPUT:
276 if (keyResponder) {
277 $(keyResponder, respondToEvent, event);
278 } else {
279 $(self->viewController, respondToEvent, event);
280 }
281 break;
282 case SDL_EVENT_MOUSE_BUTTON_DOWN:
283 if (touchTarget) {
285 $(touchTarget, respondToEvent, event);
286 } else if (touchResponder) {
289 } else {
290 $(self->viewController, respondToEvent, event);
291 }
292
296 }
297 break;
298 case SDL_EVENT_MOUSE_BUTTON_UP:
299 if (touchResponder) {
301 } else if (touchTarget) {
302 $(touchTarget, respondToEvent, event);
303 } else {
304 $(self->viewController, respondToEvent, event);
305 }
306 break;
307 case SDL_EVENT_MOUSE_MOTION:
308 case SDL_EVENT_MOUSE_WHEEL:
309 if (touchResponder) {
311 } else if (touchTarget) {
312 $(touchTarget, respondToEvent, event);
313 } else {
314 $(self->viewController, respondToEvent, event);
315 }
316 break;
317 default:
318 $(self->viewController, respondToEvent, event);
319 break;
320 }
321
322 if (event->type == SDL_EVENT_KEY_DOWN) {
323 if (event->key.key == SDLK_TAB) {
324
325 if (event->key.mod & SDL_KMOD_SHIFT) {
327 } else {
329 }
330
331 if (keyResponder) {
333 }
334 }
335
336 if (event->key.key == SDLK_D) {
337 if (event->key.mod & SDL_KMOD_CTRL) {
338 $(self, toggleDebugger);
339 }
340 }
341 }
342
343 SDL_SetPointerProperty(SDL_GetWindowProperties(self->window), "event", NULL);
344}
static void becomeKeyResponder(View *self)
Definition Control.c:130
static void resignKeyResponder(View *self)
Definition Control.c:248
static void updateBindings(View *self)
static void renderDeviceWillReset(View *self)
Definition ImageView.c:119
static void enumerateVisible(View *self, ViewEnumerator enumerator, ident data)
Definition View.c:873
static void becomeTouchResponder(View *self)
Definition View.c:451
static void resignTouchResponder(View *self)
Definition View.c:1511
static void mouseMotion_enumerate(View *view, ident data)
ViewEnumerator for SDL_EVENT_MOUSE_MOTION.

◆ setTheme()

static void setTheme ( WindowController self,
Theme theme 
)
static

Definition at line 350 of file WindowController.c.

350 {
351
352 if (self->theme != theme || self->theme == NULL) {
353
354 release(self->theme);
355
356 if (theme) {
357 self->theme = retain(theme);
358 } else {
359 self->theme = $(alloc(Theme), init);
360 }
361 }
362
364}
The Theme type.
Definition Theme.h:51

◆ setViewController()

static void setViewController ( WindowController self,
ViewController viewController 
)
static

Definition at line 370 of file WindowController.c.

370 {
371
372 if (self->viewController != viewController || self->viewController == NULL) {
373
374 SDL_SetPointerProperty(SDL_GetWindowProperties(self->window), "keyResponder", NULL);
375
376 if (self->viewController) {
378 $(self->viewController->view, moveToWindow, NULL);
380 }
381
382 release(self->viewController);
383
384 if (viewController) {
385 self->viewController = retain(viewController);
386 } else {
387 self->viewController = $(alloc(ViewController), init);
388 }
389
391
393 $(self->viewController->view, moveToWindow, self->window);
395 }
396}
static void moveToWindow(View *self, SDL_Window *window)
Definition View.c:1262
static void viewWillAppear(ViewController *self)
static void viewWillDisappear(ViewController *self)
static void loadViewIfNeeded(ViewController *self)
static void viewDidAppear(ViewController *self)
static void viewDidDisappear(ViewController *self)

◆ setWindow()

static void setWindow ( WindowController self,
SDL_Window *  window 
)
static

Definition at line 402 of file WindowController.c.

402 {
403
404 self->window = window;
405 assert(self->window);
406
407 SDL_PropertiesID properties = SDL_GetWindowProperties(self->window);
408
409 SDL_SetPointerProperty(properties, "windowController", self);
410 SDL_SetPointerProperty(properties, "keyResponder", NULL);
411 SDL_SetPointerProperty(properties, "touchResponder", NULL);
412
413 if (self->renderer) {
414 $(self->renderer->device, setWindow, self->window);
415 }
416
417 if (self->viewController) {
418 $(self->viewController->view, moveToWindow, self->window);
419 }
420
421 if (self->debugViewController) {
423 }
424}
ViewController viewController
The superclass.

◆ toggleDebugger()

static void toggleDebugger ( WindowController self)
static

Definition at line 430 of file WindowController.c.

430 {
431
432 if (self->debugViewController == NULL) {
433
435 assert(self->debugViewController);
436
437 ViewController *debugViewController = (ViewController *) self->debugViewController;
438
439 $(debugViewController, loadView);
440 $(debugViewController, viewWillAppear);
441 $(debugViewController->view, moveToWindow, self->window);
442 $(debugViewController, viewDidAppear);
443
444 if (self->viewController) {
445 $(self->viewController->view, addClassName, "debug");
446 }
447 } else {
448 self->debugViewController = release(self->debugViewController);
449
450 if (self->viewController) {
451 $(self->viewController->view, removeClassName, "debug");
452 }
453 }
454}
static void loadView(ViewController *self)
static void removeClassName(View *self, const char *className)
Definition View.c:1344
static void addClassName(View *self, const char *className)
Definition View.c:159
The DebugViewController type.

◆ touchResponder()

static View * touchResponder ( const WindowController self)
static

Definition at line 460 of file WindowController.c.

460 {
461 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->window), "touchResponder", NULL);
462}

◆ touchTarget()

static View * touchTarget ( const WindowController self,
const SDL_Event *  event 
)
static

Definition at line 468 of file WindowController.c.

468 {
469 SDL_Point point;
470
471 switch (event->type) {
472 case SDL_EVENT_MOUSE_BUTTON_DOWN:
473 point = MakePoint(event->button.x, event->button.y);
474 break;
475 case SDL_EVENT_MOUSE_BUTTON_UP:
476 point = MakePoint(event->button.x, event->button.y);
477 break;
478 case SDL_EVENT_MOUSE_MOTION:
479 point = MakePoint(event->motion.x, event->motion.y);
480 break;
481 case SDL_EVENT_MOUSE_WHEEL: {
482 float mx, my;
483 SDL_GetMouseState(&mx, &my);
484 point = MakePoint(mx, my);
485 break;
486 }
487 default:
488 return NULL;
489 }
490
491 return $(self->viewController->view, hitTest, &point);
492}

◆ windowController()

static WindowController * windowController ( SDL_Window *  window)
static

Definition at line 498 of file WindowController.c.

498 {
499
500 assert(window);
501
502 return SDL_GetPointerProperty(SDL_GetWindowProperties(window), "windowController", NULL);
503}