ObjectivelyMVC 0.1.0
Object oriented MVC framework for OpenGL, SDL2 and GNU C
View+JSON.c
Go to the documentation of this file.
1/*
2 * Objectively: Ultra-lightweight object oriented framework for GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 * 1. The origin of this software must not be misrepresented; you must not
11 * claim that you wrote the original software. If you use this software
12 * in a product, an acknowledgment in the product documentation would be
13 * appreciated but is not required.
14 * 2. Altered source versions must be plainly marked as such, and must not be
15 * misrepresented as being the original software.
16 * 3. This notice may not be removed or altered from any source distribution.
17 */
18
19#include <assert.h>
20#include <string.h>
21
22#include <Objectively.h>
23
24#include <ObjectivelyMVC.h>
25
26#define _Class _View
27
31static void bindBool(const Inlet *inlet, ident obj) {
32 *((_Bool *) inlet->dest) = cast(Boole, obj)->value;
33}
34
38static void bindCharacters(const Inlet *inlet, ident obj) {
39
40 char **dest = inlet->dest;
41
42 if (*dest) {
43 free(*dest);
44 }
45
46 *dest = strdup(cast(String, obj)->chars);
47}
48
52static void bindClassNames_enumerate(const Array *array, ident obj, ident data) {
53 $((View *) data, addClassName, cast(String, obj)->chars);
54}
55
59static void bindClassNames(const Inlet *inlet, ident obj) {
60 $(cast(Array, obj), enumerateObjects, bindClassNames_enumerate, *(View **) inlet->dest);
61}
62
66static void bindColor(const Inlet *inlet, ident obj) {
67
68 SDL_Color color = Colors.Black;
69
70 if ($((Object *) obj, isKindOfClass, _String())) {
71
72 String *string = cast(String, obj);
73 if (string->length) {
74
75 if (strcmp("none", string->chars) == 0) {
76 return;
77 }
78
79 if (string->chars[0] == '#') {
80 color = MVC_HexToRGBA(string->chars + 1);
81 } else {
82 color = MVC_ColorForName(string->chars);
83 }
84 }
85
86 } else {
87 const Array *array = cast(Array, obj);
88
89 assert(array->count == 4);
90
91 const Number *r = $(array, objectAtIndex, 0);
92 const Number *g = $(array, objectAtIndex, 1);
93 const Number *b = $(array, objectAtIndex, 2);
94 const Number *a = $(array, objectAtIndex, 3);
95
96 #define ScaleColor(c) (c > 0.0 && c < 1.0 ? c * 255 : c)
97
98 color = MakeColor(
99 ScaleColor(r->value),
100 ScaleColor(g->value),
101 ScaleColor(b->value),
102 ScaleColor(a->value)
103 );
104 }
105
106 *((SDL_Color *) inlet->dest) = color;
107}
108
112static void bindDouble(const Inlet *inlet, ident obj) {
113 *((double *) inlet->dest) = cast(Number, obj)->value;
114}
115
119static void bindEnum(const Inlet *inlet, ident obj) {
120 *((int *) inlet->dest) = valueof(inlet->data, cast(String, obj)->chars);
121}
122
126static void bindFloat(const Inlet *inlet, ident obj) {
127 *((float *) inlet->dest) = cast(Number, obj)->value;
128}
129
133static void bindFont(const Inlet *inlet, ident obj) {
134
135 release(*(Font **) inlet->dest);
136
137 // TODO
138
139 //*((Font **) inlet->dest) = $(alloc(Font), initWithName, cast(String, obj)->chars);
140}
141
145static void bindImage(const Inlet *inlet, ident obj) {
146
147 release(*(Image **) inlet->dest);
148
149 *((Image **) inlet->dest) = $(alloc(Image), initWithResourceName, cast(String, obj)->chars);
150}
151
155static void bindInteger(const Inlet *inlet, ident obj) {
156 *((int *) inlet->dest) = cast(Number, obj)->value;
157}
158
162static void bindPoint(const Inlet *inlet, ident obj) {
163
164 const Array *array = cast(Array, obj);
165
166 assert(array->count == 2);
167
168 const Number *x = $(array, objectAtIndex, 0);
169 const Number *y = $(array, objectAtIndex, 1);
170
171 *((SDL_Point *) inlet->dest) = MakePoint(x->value, y->value);
172}
173
177static void bindRectangle(const Inlet *inlet, ident obj) {
178
179 if ($((Object *) obj, isKindOfClass, _Number())) {
180 const Number *n = obj;
181
182 *((SDL_Rect *) inlet->dest) = MakeRect(n->value, n->value, n->value, n->value);
183 } else {
184 const Array *array = cast(Array, obj);
185
186 assert(array->count == 4);
187
188 const Number *x = $(array, objectAtIndex, 0);
189 const Number *y = $(array, objectAtIndex, 1);
190 const Number *w = $(array, objectAtIndex, 2);
191 const Number *h = $(array, objectAtIndex, 3);
192
193 *((SDL_Rect *) inlet->dest) = MakeRect(x->value, y->value, w->value, h->value);
194 }
195}
196
200static void bindSize(const Inlet *inlet, ident obj) {
201
202 const Array *array = cast(Array, obj);
203
204 assert(array->count == 2);
205
206 const Number *w = $(array, objectAtIndex, 0);
207 const Number *h = $(array, objectAtIndex, 1);
208
209 *((SDL_Size *) inlet->dest) = MakeSize(w->value, h->value);
210}
211
215static void bindView(const Inlet *inlet, ident obj) {
216
217 View *dest = *(View **) inlet->dest;
218
219 const Dictionary *dictionary = cast(Dictionary, obj);
220
221 const String *className = $(dictionary, objectForKeyPath, "class");
222 if (className || dest == NULL) {
223
224 Class *clazz = className ? classForName(className->chars) : _View();
225 assert(clazz);
226
227 const Class *c = clazz;
228 while (c) {
229 if (c == _View()) {
230 break;
231 }
232 c = c->def.superclass;
233 }
234 assert(c);
235
236 if (clazz != _View()) {
237 if (interfaceof(View, clazz)->init == interfaceof(View, clazz->def.superclass)->init) {
238 MVC_LogWarn("%s does not implement View::init\n", clazz->def.name);
239 }
240 }
241
242 View *view = $((View *) _alloc(clazz), init);
243 assert(view);
244
245 $(view, awakeWithDictionary, dictionary);
246
247 if (dest) {
248 if (dest->superview) {
249 $(dest->superview, replaceSubview, dest, view);
250 }
251 release(dest);
252 }
253
254 *(View **) inlet->dest = view;
255
256 } else if (dest) {
257 $(dest, awakeWithDictionary, dictionary);
258 } else {
259 MVC_LogWarn("Inlet %s has NULL destination and no className specified\n", inlet->name);
260 }
261}
262
266static void bindStyle(const Inlet *inlet, ident obj) {
267 $(cast(View, *((View **) inlet->dest))->style, addAttributes, cast(Dictionary, obj));
268}
269
273static void bindSubviews_enumerate(const Array *array, ident obj, ident data) {
274
275 View *subview = NULL;
276
277 const Inlet inlet = MakeInlet(NULL, InletTypeView, &subview, NULL);
278
279 bindView(&inlet, obj);
280
281 $(cast(View, data), addSubview, subview);
282
283 release(subview);
284}
285
289static void bindSubviews(const Inlet *inlet, ident obj) {
290 $(cast(Array, obj), enumerateObjects, bindSubviews_enumerate, *(View **) inlet->dest);
291}
292
296static void bindApplicationDefined(const Inlet *inlet, ident obj) {
297
298 assert(inlet->data);
299
300 ((InletBinding) inlet->data)(inlet, obj);
301}
302
307 bindBool,
310 bindColor,
312 bindEnum,
313 bindFloat,
314 bindFont,
315 bindImage,
317 bindPoint,
319 bindSize,
320 bindStyle,
322 bindView,
324};
325
326_Bool bindInlets(const Inlet *inlets, const Dictionary *dictionary) {
327
328 assert(inlets);
329 assert(dictionary);
330
331 _Bool didBindInlets = false;
332
333 for (const Inlet *inlet = inlets; inlet->name; inlet++) {
334 const ident obj = $(dictionary, objectForKeyPath, inlet->name);
335 if (obj) {
336 BindInlet(inlet, obj);
337 didBindInlets = true;
338 }
339 }
340
341 return didBindInlets;
342}
343
344#undef _Class
#define MVC_LogWarn(fmt,...)
Definition: Log.h:52
ObjectivelyMVC: Object oriented MVC framework for OpenGL, SDL2 and GNU C.
#define MakeSize(w, h)
Creates an SDL_Size with the given dimensions.
Definition: Types.h:79
#define MakePoint(x, y)
Creates an SDL_Point with the given coordinates.
Definition: Types.h:69
#define MakeRect(x, y, w, h)
Creates an SDL_Rect with the given origin and size.
Definition: Types.h:74
static void bindColor(const Inlet *inlet, ident obj)
InletBinding for InletTypeColor.
Definition: View+JSON.c:66
static void bindEnum(const Inlet *inlet, ident obj)
InletBinding for InletTypeEnum.
Definition: View+JSON.c:119
static void bindPoint(const Inlet *inlet, ident obj)
InletBinding for InletTypePoint.
Definition: View+JSON.c:162
static void bindApplicationDefined(const Inlet *inlet, ident obj)
InletBinding for InletTypeApplicationDefined.
Definition: View+JSON.c:296
static void bindImage(const Inlet *inlet, ident obj)
InletBinding for InletTypeImage.
Definition: View+JSON.c:145
static void bindFont(const Inlet *inlet, ident obj)
InletBinding for InletTypeFont.
Definition: View+JSON.c:133
static void bindClassNames_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for bindClassNames.
Definition: View+JSON.c:52
static void bindSubviews_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for bind subview recursion.
Definition: View+JSON.c:273
_Bool bindInlets(const Inlet *inlets, const Dictionary *dictionary)
Binds each Inlet specified in inlets to the data provided in dictionary.
Definition: View+JSON.c:326
static void bindDouble(const Inlet *inlet, ident obj)
InletBinding for InletTypeDouble.
Definition: View+JSON.c:112
static void bindClassNames(const Inlet *inlet, ident obj)
InletBinding for InletTypeClassNames.
Definition: View+JSON.c:59
static void bindInteger(const Inlet *inlet, ident obj)
InletBinding for InletTypeInteger.
Definition: View+JSON.c:155
static void bindFloat(const Inlet *inlet, ident obj)
InletBinding for InletTypeFloat.
Definition: View+JSON.c:126
#define ScaleColor(c)
static void bindRectangle(const Inlet *inlet, ident obj)
InletBinding for InletTypeRectangle.
Definition: View+JSON.c:177
static void bindSize(const Inlet *inlet, ident obj)
InletBinding for InletTypeSize.
Definition: View+JSON.c:200
static void bindBool(const Inlet *inlet, ident obj)
InletBinding for InletTypeBool.
Definition: View+JSON.c:31
static void bindView(const Inlet *inlet, ident obj)
Binds the given View with the specified Dictionary.
Definition: View+JSON.c:215
static void bindCharacters(const Inlet *inlet, ident obj)
InletBinding for InletTypeCharacters.
Definition: View+JSON.c:38
const InletBinding inletBindings[]
The array of InletBinding functions, indexed by InletType.
Definition: View+JSON.c:306
static void bindSubviews(const Inlet *inlet, ident obj)
InletBinding for InletTypeSubviews.
Definition: View+JSON.c:289
static void bindStyle(const Inlet *inlet, ident obj)
InletBinding for InletTypeStyle.
Definition: View+JSON.c:266
@ 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
void(* InletBinding)(const Inlet *inlet, ident obj)
A function pointer for Inlet binding.
Definition: View+JSON.h:186
#define MakeInlet(name, type, dest, data)
Creates an Inlet with the specified parameters.
Definition: View+JSON.h:216
CollectionView * init(CollectionView *self, const SDL_Rect *frame)
Initializes this CollectionView with the specified frame and style.
W3C Color constants.
Definition: Colors.h:37
OBJECTIVELYMVC_EXPORT SDL_Color MVC_HexToRGBA(const char *hexString)
Converts the given hexadecimal color string to an RGBA color.
Definition: Colors.c:638
#define MakeColor(r, g, b, a)
Creates an SDL_Color with the given components.
Definition: Colors.h:195
SDL_Color Black
Definition: Colors.h:46
OBJECTIVELYMVC_EXPORT SDL_Color MVC_ColorForName(const char *name)
Definition: Colors.c:180
TrueType fonts.
Definition: Font.h:63
Image loading.
Definition: Image.h:38
Image * initWithResourceName(Image *self, const char *name)
Initializes this Image, loading the Resource by the given name.
Definition: Image.c:142
Inlets enable inbound data binding of View attributes through JSON.
Definition: View+JSON.h:155
const char * name
The Inlet name, e.g. "alignment".
Definition: View+JSON.h:160
ident data
Type-specific data, e.g. an array of EnumNames.
Definition: View+JSON.h:175
ident dest
The Inlet destination.
Definition: View+JSON.h:170
The SDL_Size type.
Definition: Types.h:62
void addAttributes(Style *self, const Dictionary *attributes)
Adds or replaces the attribtues in attributes to this Style.
Definition: Style.c:119
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition: View.h:133
View * superview
The super View.
Definition: View.h:258
Class * _View(void)
The View archetype.
Definition: View.c:1769
void addSubview(View *self, View *subview)
Adds a subview to this view, to be drawn above its siblings.
Definition: PageView.c:35
void addClassName(View *self, const char *className)
Adds the given class name to this View.
Definition: View.c:120
void replaceSubview(View *self, View *subview, View *replacement)
Replaces the specified subview with the given replacement.
Definition: View.c:1302
void awakeWithDictionary(View *self, const Dictionary *dictionary)
Wakes this View with the specified Dictionary.
Definition: Box.c:50