ObjectivelyMVC 0.1.0
Object oriented MVC framework for OpenGL, SDL2 and GNU C
DebugViewController.c
Go to the documentation of this file.
1/*
2 * ObjectivelyMVC: Object oriented MVC framework for OpenGL, SDL2 and GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 *
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 *
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include <assert.h>
25
26#include <Objectively/MutableString.h>
27
28#include "DebugViewController.h"
29#include "WindowController.h"
30
31#include "debug.css.h"
32#include "debug.json.h"
33
34#define _Class _DebugViewController
35
36#pragma mark - Selectors
37
41static size_t selectors_numberOfRows(const TableView *tableView) {
42
43 const DebugViewController *this = tableView->dataSource.self;
44 if (this->debug) {
45 return this->debug->computedStyle->selectors->count;
46 } else {
47 return 0;
48 }
49}
50
54static ident selectors_valueForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row) {
55
56 const DebugViewController *this = tableView->dataSource.self;
57 if (this->debug) {
58 return $(this->debug->computedStyle->selectors, objectAtIndex, row);
59 } else {
60 return NULL;
61 }
62}
63
67static TableCellView *selectors_cellForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row) {
68
69 const Selector *selector = tableView->dataSource.valueForColumnAndRow(tableView, column, row);
70 assert(selector);
71
72 TableCellView *cell = $(alloc(TableCellView), initWithFrame, NULL);
73 $(cell->text, setText, selector->rule);
74
75 return cell;
76}
77
78#pragma mark - Computed Style
79
83static size_t computedStyle_numberOfRows(const TableView *tableView) {
84
85 const DebugViewController *this = tableView->dataSource.self;
86 if (this->debug) {
87 return this->debug->computedStyle->attributes->count;
88 } else {
89 return 0;
90 }
91}
92
96static ident computedStyle_valueForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row) {
97
98 ident value = NULL;
99
100 const DebugViewController *this = tableView->dataSource.self;
101 if (this->debug) {
102
103 Array *array;
104 if (strcmp("Attribute", column->identifier) == 0) {
105 array = $(this->debug->computedStyle->attributes, allKeys);
106 } else {
107 array = $(this->debug->computedStyle->attributes, allObjects);
108 }
109
110 value = $(array, objectAtIndex, row);
111 release(array);
112 }
113
114 return value;
115}
116
120static TableCellView *computedStyle_cellForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row) {
121
122 ident value = tableView->dataSource.valueForColumnAndRow(tableView, column, row);
123 assert(value);
124
125 TableCellView *cell = $(alloc(TableCellView), initWithFrame, NULL);
126 String *description = $((Object *) value, description);
127 $(cell->text, setText, description->chars);
128 release(description);
129
130 return cell;
131}
132
133#pragma mark - Warnings
134
138static size_t warnings_numberOfRows(const TableView *tableView) {
139
140 const DebugViewController *this = tableView->dataSource.self;
141 if (this->debug) {
142 return this->debug->warnings->array.count;
143 } else {
144 return 0;
145 }
146}
147
151static ident warnings_valueForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row) {
152
153 ident value = NULL;
154
155 const DebugViewController *this = tableView->dataSource.self;
156 if (this->debug) {
157 value = $((Array *) this->debug->warnings, objectAtIndex, row);
158 }
159
160 return value;
161}
162
166static TableCellView *warnings_cellForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row) {
167
168 ident value = tableView->dataSource.valueForColumnAndRow(tableView, column, row);
169 assert(value);
170
171 TableCellView *cell = $(alloc(TableCellView), initWithFrame, NULL);
172 $(cell->text, setText, ((String *) value)->chars);
173
174 return cell;
175}
176
177#pragma mark - ViewController
178
182static void loadView(ViewController *self) {
183
184 super(ViewController, self, loadView);
185
187
188 Outlet outlets[] = MakeOutlets(
189 MakeOutlet("statistics", &this->statistics),
190 MakeOutlet("description", &this->description),
191 MakeOutlet("path", &this->path),
192 MakeOutlet("selectors", &this->selectors),
193 MakeOutlet("computedStyle", &this->computedStyle),
194 MakeOutlet("warnings", &this->warnings)
195 );
196
197 View *view = $$(View, viewWithCharacters, (char *) debug_json, outlets);
198 view->stylesheet = $$(Stylesheet, stylesheetWithCharacters, (char *) debug_css);
199
200 $(self, setView, view);
201 release(view);
202
203 this->selectors->dataSource.self = self;
204 this->selectors->dataSource.numberOfRows = selectors_numberOfRows;
205 this->selectors->dataSource.valueForColumnAndRow = selectors_valueForColumnAndRow;
206 this->selectors->delegate.self = self;
207 this->selectors->delegate.cellForColumnAndRow = selectors_cellForColumnAndRow;
208
209 this->computedStyle->dataSource.self = self;
210 this->computedStyle->dataSource.numberOfRows = computedStyle_numberOfRows;
211 this->computedStyle->dataSource.valueForColumnAndRow = computedStyle_valueForColumnAndRow;
212 this->computedStyle->delegate.self = self;
213 this->computedStyle->delegate.cellForColumnAndRow = computedStyle_cellForColumnAndRow;
214
215 this->warnings->dataSource.self = self;
216 this->warnings->dataSource.numberOfRows = warnings_numberOfRows;
217 this->warnings->dataSource.valueForColumnAndRow = warnings_valueForColumnAndRow;
218 this->warnings->delegate.self = self;
219 this->warnings->delegate.cellForColumnAndRow = warnings_cellForColumnAndRow;
220}
221
222#pragma mark - DebugViewController
223
227static void debugEnumerate(View *view, ident data) {
228
229 DebugViewController *this = data;
230
231 if ($(view, isVisible)) {
232 this->visibleViews++;
233 }
234
235 if (view == this->debug) {
236 const SDL_Rect frame = $(view, renderFrame);
237
238 $(this->renderer, setClippingFrame, NULL);
239 $(this->renderer, setDrawColor, &MakeColor(0x22, 0x66, 0x99, 0x88));
240 $(this->renderer, drawRectFilled, &frame);
241 $(this->renderer, setDrawColor, &Colors.White);
242 }
243
244 const Array *warnings = (Array *) view->warnings;
245 if (warnings->count) {
246 const SDL_Rect frame = $(view, renderFrame);
247
248 $(this->renderer, setClippingFrame, NULL);
249 $(this->renderer, setDrawColor, &Colors.DarkGoldenRod);
250 $(this->renderer, drawRect, &frame);
251 $(this->renderer, setDrawColor, &Colors.White);
252 }
253}
254
259static void debug(DebugViewController *self, const View *view, Renderer *renderer) {
260
261 if (view != self->debug) {
262 self->debug = view;
263
264 if (self->debug) {
265 self->root = self->debug;
266 while (self->root->superview) {
267 self->root = self->root->superview;
268 }
269
270 String *path = $(self->debug, path);
271 $(self->path, setText, path->chars);
272 release(path);
273
274 String *description = $((Object *) view, description);
275 $(self->description, setText, description->chars);
276 release(description);
277 } else {
278 $(self->path, setText, NULL);
279 $(self->description, setText, NULL);
280 }
281
282 $(self->selectors, reloadData);
283 $((View *) self->selectors, sizeToFit);
284
285 $(self->computedStyle, reloadData);
286 $((View *) self->computedStyle, sizeToFit);
287
288 $(self->warnings, reloadData);
289 $((View *) self->warnings, sizeToFit);
290 }
291
292 self->renderer = renderer;
293 assert(self->renderer);
294
295 self->visibleViews = 0;
296
297 if (self->root) {
298 $((View *) self->root, enumerate, debugEnumerate, self);
299 }
300
301 self->frames++;
302 if (SDL_GetTicks() - self->timestamp >= 1000) {
303
304 $(self->statistics, setTextWithFormat, "%d views, %dfps", self->visibleViews, self->frames);
305
306 self->timestamp = SDL_GetTicks();
307 self->frames = 0;
308 }
309}
310
316 return (DebugViewController *) super(ViewController, self, init);
317}
318
319#pragma mark - Class lifecycle
320
324static void initialize(Class *clazz) {
325
326 ((ViewControllerInterface *) clazz->interface)->loadView = loadView;
327
328 ((DebugViewControllerInterface *) clazz->interface)->debug = debug;
329 ((DebugViewControllerInterface *) clazz->interface)->init = init;
330}
331
337 static Class *clazz;
338 static Once once;
339
340 do_once(&once, {
341 clazz = _initialize(&(const ClassDef) {
342 .name = "DebugViewController",
343 .superclass = _ViewController(),
344 .instanceSize = sizeof(DebugViewController),
345 .interfaceOffset = offsetof(DebugViewController, interface),
346 .interfaceSize = sizeof(DebugViewControllerInterface),
348 });
349 });
350
351 return clazz;
352}
353
354#undef _Class
static void debugEnumerate(View *view, ident data)
static TableCellView * selectors_cellForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row)
static ident warnings_valueForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row)
static ident computedStyle_valueForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row)
static TableCellView * warnings_cellForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row)
static size_t computedStyle_numberOfRows(const TableView *tableView)
static TableCellView * computedStyle_cellForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row)
static size_t selectors_numberOfRows(const TableView *tableView)
static void initialize(Class *clazz)
static ident selectors_valueForColumnAndRow(const TableView *tableView, const TableColumn *column, size_t row)
static size_t warnings_numberOfRows(const TableView *tableView)
The DebugViewController type.
static String * description(const Object *self)
Definition: Label.c:47
#define MakeOutlet(identifier, view)
Creates an Outlet with the specified parameters.
Definition: View+JSON.h:230
#define MakeOutlets(...)
Creates a NULL-termianted array of Outlets.
Definition: View+JSON.h:235
A WindowController manages a ViewController and its descendants within an SDL_Window.
Box * initWithFrame(Box *self, const SDL_Rect *frame)
Initializes this Box with the given frame.
Definition: Box.c:92
void reloadData(CollectionView *self)
Reloads this CollectionView's visible items.
CollectionView * init(CollectionView *self, const SDL_Rect *frame)
Initializes this CollectionView with the specified frame and style.
W3C Color constants.
Definition: Colors.h:37
SDL_Color DarkGoldenRod
Definition: Colors.h:63
SDL_Color White
Definition: Colors.h:185
#define MakeColor(r, g, b, a)
Creates an SDL_Color with the given components.
Definition: Colors.h:195
The DebugViewController type.
Class * _DebugViewController(void)
The DebugViewController archetype.
TableView * selectors
The CSS selectors matching the View.
const View * debug
The View to debug.
TableView * computedStyle
The computed style of the View.
int visibleViews
The count of visibile Views.
Renderer * renderer
A weak referece to the current WindowController's renderer.
TableView * warnings
The warnings generated by the View.
void debug(DebugViewController *self, const View *view, Renderer *renderer)
Debugs the given View.
Text * description
The View description.
const View * root
The root ancestor of the debug View.
Text * path
The path to the debug View.
Outlets enable outbound data binding of Views through JSON.
Definition: View+JSON.h:200
The Renderer is responsible for rasterizing the View hierarchy of a WindowController.
Definition: Renderer.h:50
void setClippingFrame(Renderer *self, const SDL_Rect *clippingFrame)
Sets the clipping frame for draw operations.
Definition: Renderer.c:260
void drawRectFilled(const Renderer *self, const SDL_Rect *rect)
Fills a rectangle using glRecti.
Definition: Renderer.c:144
void drawRect(const Renderer *self, const SDL_Rect *rect)
Draws a rectangle using GL_LINE_LOOP.
Definition: Renderer.c:118
void setDrawColor(Renderer *self, const SDL_Color *color)
Sets the primary color for drawing operations.
Definition: Renderer.c:281
Selectors are comprised of one or more SelectorSequences.
Definition: Selector.h:49
char * rule
The rule, as provided by the user.
Definition: Selector.h:70
Stylesheets are comprised of Selectors and Styles.
Definition: Stylesheet.h:44
Stylesheet * stylesheetWithCharacters(const char *chars)
Instantiates a new Stylesheet with the given CSS definitions.
Definition: Stylesheet.c:206
Each row in a TableView is comprised of TableCellViews.
Definition: TableCellView.h:41
Text * text
The text.
Definition: TableCellView.h:57
Columns provide alignment, spacing and sorting hints for TableView instances.
Definition: TableColumn.h:45
char * identifier
The identifier.
Definition: TableColumn.h:66
ident self
The data source self-reference.
Definition: TableView.h:61
ident(* valueForColumnAndRow)(const TableView *tableView, const TableColumn *column, size_t row)
Called by the TableView for the associated value of a cell.
Definition: TableView.h:76
TableViews provide sortable, tabular presentations of data.
Definition: TableView.h:122
TableViewDataSource dataSource
The data source.
Definition: TableView.h:148
void setTextWithFormat(Text *self, const char *fmt,...)
Sets this Text's text with the given format string.
Definition: Text.c:289
void setText(Text *self, const char *text)
Sets this Text's text.
Definition: Text.c:261
A ViewController manages a View and its descendants.
Class * _ViewController(void)
The ViewController archetype.
void loadView(ViewController *self)
Loads this ViewController's View.
void setView(ViewController *self, View *view)
Sets this ViewController's View.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition: View.h:133
Stylesheet * stylesheet
An optional Stylesheet.
Definition: View.h:247
String * path(const View *self)
Definition: View.c:1091
_Bool isVisible(const View *self)
Definition: View.c:869
View * superview
The super View.
Definition: View.h:258
MutableArray * warnings
The warnings this View generated.
Definition: View.h:270
View * viewWithCharacters(const char *chars, Outlet *outlets)
Instantiates a View initialized with the given null-terminated JSON C string.
Definition: View.c:1558
SDL_Rect renderFrame(const View *self)
Definition: View.c:1275
void enumerate(const View *self, ViewEnumerator enumerator, ident data)
void sizeToFit(View *self)
Resizes this View to fit its subviews.
Definition: View.c:1496