26#include <Objectively/String.h>
32#define _Class _WindowController
34#pragma mark - Delegates
41 const SDL_MouseMotionEvent *
event = data;
42 const SDL_Point a = MakePoint(event->x - event->xrel, event->y - event->yrel);
43 const SDL_Point b = MakePoint(event->x, event->y);
63 release(this->debugViewController);
64 release(this->renderer);
66 release(this->viewController);
71#pragma mark - WindowController
84 SDL_GetMouseState(&mx, &my);
85 SDL_Point point = MakePoint(mx, my);
106 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->
window),
"keyResponder", NULL);
115 $((Array *) data, addObject, view);
125 Array *array = (Array *) $(alloc(Array),
init);
165 $(self,
renderTo, device->commands, device->framebuffer);
204 const ssize_t index = $(array, indexOfObject,
keyResponder);
205 next = $(array, objectAtIndex, (index + 1) % array->count);
207 next = $(array, firstObject);
227 const ssize_t index = $(array, indexOfObject,
keyResponder);
228 prev = $(array, objectAtIndex, (index + array->count - 1) % array->count);
230 prev = $(array, firstObject);
250 if (event->type >= SDL_EVENT_WINDOW_FIRST && event->type <= SDL_EVENT_WINDOW_LAST) {
251 if (event->window.windowID != SDL_GetWindowID(self->
window)) {
256 SDL_SetPointerProperty(SDL_GetWindowProperties(self->
window),
"event", (ident) event);
258 switch (event->type) {
259 case SDL_EVENT_WINDOW_MOVED:
260 case SDL_EVENT_WINDOW_RESIZED:
261 case SDL_EVENT_WINDOW_MAXIMIZED:
262 case SDL_EVENT_WINDOW_RESTORED:
263 case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
266 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
267 case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
268 case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: {
285 case SDL_EVENT_WINDOW_DESTROYED:
286 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
295 if (event->type == SDL_EVENT_MOUSE_MOTION) {
303 switch (event->type) {
304 case SDL_EVENT_KEY_UP:
305 case SDL_EVENT_KEY_DOWN:
306 case SDL_EVENT_TEXT_INPUT:
313 case SDL_EVENT_MOUSE_BUTTON_DOWN:
329 case SDL_EVENT_MOUSE_BUTTON_UP:
338 case SDL_EVENT_MOUSE_MOTION:
339 case SDL_EVENT_MOUSE_WHEEL:
353 if (event->type == SDL_EVENT_KEY_DOWN) {
354 if (event->key.key == SDLK_TAB || event->key.key == SDLK_KP_TAB) {
359 const bool consumed = current && current ==
keyResponder &&
360 $((Object *) current, isKindOfClass,
_TextView()) &&
361 ((
TextView *) current)->isEditable &&
365 if (event->key.mod & SDL_KMOD_SHIFT) {
377 if (event->key.key == SDLK_D) {
378 if (event->key.mod & SDL_KMOD_CTRL) {
384 SDL_SetPointerProperty(SDL_GetWindowProperties(self->
window),
"event", NULL);
395 release(self->
theme);
415 SDL_SetPointerProperty(SDL_GetWindowProperties(self->
window),
"keyResponder", NULL);
425 if (viewController) {
449 SDL_PropertiesID properties = SDL_GetWindowProperties(self->
window);
451 SDL_SetPointerProperty(properties,
"windowController", self);
452 SDL_SetPointerProperty(properties,
"keyResponder", NULL);
453 SDL_SetPointerProperty(properties,
"touchResponder", NULL);
503 return SDL_GetPointerProperty(SDL_GetWindowProperties(self->
window),
"touchResponder", NULL);
513 switch (event->type) {
514 case SDL_EVENT_MOUSE_BUTTON_DOWN:
515 point = MakePoint(event->button.x, event->button.y);
517 case SDL_EVENT_MOUSE_BUTTON_UP:
518 point = MakePoint(event->button.x, event->button.y);
520 case SDL_EVENT_MOUSE_MOTION:
521 point = MakePoint(event->motion.x, event->motion.y);
523 case SDL_EVENT_MOUSE_WHEEL: {
525 SDL_GetMouseState(&mx, &my);
526 point = MakePoint(mx, my);
544 return SDL_GetPointerProperty(SDL_GetWindowProperties(window),
"windowController", NULL);
547#pragma mark - Class lifecycle
554 ((ObjectInterface *) clazz->interface)->dealloc =
dealloc;
556 ((WindowControllerInterface *) clazz->interface)->debug =
debug;
557 ((WindowControllerInterface *) clazz->interface)->keyResponder =
keyResponder;
558 ((WindowControllerInterface *) clazz->interface)->keyResponders =
keyResponders;
559 ((WindowControllerInterface *) clazz->interface)->initWithDevice =
initWithDevice;
562 ((WindowControllerInterface *) clazz->interface)->
render =
render;
563 ((WindowControllerInterface *) clazz->interface)->renderTo =
renderTo;
564 ((WindowControllerInterface *) clazz->interface)->respondToEvent =
respondToEvent;
565 ((WindowControllerInterface *) clazz->interface)->setTheme =
setTheme;
566 ((WindowControllerInterface *) clazz->interface)->setViewController =
setViewController;
567 ((WindowControllerInterface *) clazz->interface)->setWindow =
setWindow;
568 ((WindowControllerInterface *) clazz->interface)->toggleDebugger =
toggleDebugger;
569 ((WindowControllerInterface *) clazz->interface)->touchResponder =
touchResponder;
570 ((WindowControllerInterface *) clazz->interface)->touchTarget =
touchTarget;
571 ((WindowControllerInterface *) clazz->interface)->windowController =
windowController;
583 clazz = _initialize(&(
const ClassDef) {
584 .name =
"WindowController",
585 .superclass = _Object(),
587 .interfaceSize =
sizeof(WindowControllerInterface),
static View * init(View *self)
static void becomeKeyResponder(View *self)
static bool acceptsKeyResponder(const View *self)
static void resignKeyResponder(View *self)
static bool isDisabled(const Control *self)
static void loadView(ViewController *self)
static void updateBindings(View *self, ident data)
static void renderDeviceWillReset(ImageAtlas *self)
View logging facilities via SDL_Log.
static void endFrame(Renderer *self)
static void beginFrameWith(Renderer *self, CommandBuffer *commands, Framebuffer *framebuffer)
static void renderDeviceDidReset(Renderer *self)
A Control for presenting and capturing user-provied Text.
static Theme * theme(SDL_Window *window)
@ ViewEventMouseEnter
The mouse has entered a View's frame.
@ ViewEventMouseLeave
The mouse has left a View's frame.
static void removeClassName(View *self, const char *className)
static void addClassName(View *self, const char *className)
static void layoutIfNeeded(View *self)
static void enumerateVisible(View *self, ViewEnumerator enumerator, ident data)
static void draw(View *self, Renderer *renderer)
void MVC_InvalidateRenderFrames(void)
Invalidates every View's cached View::renderFrame and View::clippingFrame.
static void becomeTouchResponder(View *self)
static bool isVisible(const View *self)
static void resignTouchResponder(View *self)
static void invalidateStyle(View *self)
static void moveToWindow(View *self, SDL_Window *window)
static View * hitTest(const View *self, const SDL_Point *point)
static void applyThemeIfNeeded(View *self, const Theme *theme)
static bool containsPoint(const View *self, const SDL_Point *point)
static void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
static void emitViewEvent(View *self, ViewEvent code, ident data)
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)
static View * touchTarget(const WindowController *self, const SDL_Event *event)
static void enumerateKeyResponders(View *view, ident data)
ViewEnumerator for finding the next key responder.
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)
Class * _WindowController(void)
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 debug(WindowController *self)
static void setTheme(WindowController *self, Theme *theme)
static void dealloc(Object *self)
static WindowController * windowController(SDL_Window *window)
static void initialize(Class *clazz)
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)
static void mouseMotion_enumerate(View *view, ident data)
ViewEnumerator for SDL_EVENT_MOUSE_MOTION.
A WindowController manages a ViewController and its descendants within an SDL_Window.
Controls are Views which capture and respond to events.
The DebugViewController type.
ViewController viewController
The superclass.
Renderer extends Object with ObjectivelyMVC's UI rendering layer.
RenderDevice * device
The backing RenderDevice.
A Control for presenting and capturing user-provied Text.
A ViewController manages a View and its descendants.
View * view
The main view.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
void render(View *self, Renderer *renderer)
Renders this View using the given renderer.
A WindowController manages a ViewController and its descendants within an SDL_Window.
ViewController * viewController
The ViewController.
View * nextKeyResponder(const WindowController *self, View *keyResponder)
Finds the next available keyResponder from the given keyResponder.
SDL_Window * window
The window.
Renderer * renderer
The Renderer.
DebugViewController * debugViewController
The DebugViewController.