ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
RGBColorPicker.c
Go to the documentation of this file.
1/*
2 * ObjectivelyMVC: Object oriented MVC framework for SDL3 and 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#include <math.h>
26
27#include "RGBColorPicker.h"
28
29#define _Class _RGBColorPicker
30
31#pragma mark - Delegates
32
36static void didSetComponent(Slider *slider, double value) {
37
38 RGBColorPicker *this = (RGBColorPicker *) slider->delegate.self;
39
40 const int c = round(value);
41
42 if (slider == this->redSlider) {
43 this->color.r = c;
44 } else if (slider == this->greenSlider) {
45 this->color.g = c;
46 } else if (slider == this->blueSlider) {
47 this->color.b = c;
48 } else if (slider == this->alphaSlider) {
49 this->color.a = c;
50 } else {
51 assert(false);
52 }
53
54 $((View *) this, updateBindings);
55
56 if (this->delegate.didPickColor) {
57 this->delegate.didPickColor(this, &this->color);
58 }
59}
60
61#pragma mark - Object
62
66static void dealloc(Object *self) {
67
68 RGBColorPicker *this = (RGBColorPicker *) self;
69
70 memset(&this->delegate, 0, sizeof(this->delegate));
71
72 release(this->colorView);
73 release(this->redSlider);
74 release(this->redInput);
75 release(this->greenSlider);
76 release(this->greenInput);
77 release(this->blueSlider);
78 release(this->blueInput);
79 release(this->alphaSlider);
80 release(this->alphaInput);
81 release(this->stackView);
82
83 super(Object, self, dealloc);
84}
85
86#pragma mark - View
87
91static void awakeWithDictionary(View *self, const Dictionary *dictionary) {
92
93 super(View, self, awakeWithDictionary, dictionary);
94
95 RGBColorPicker *this = (RGBColorPicker *) self;
96
97 const Inlet inlets[] = MakeInlets(
98 MakeInlet("color", InletTypeColor, &this->color, NULL),
99 MakeInlet("colorView", InletTypeView, &this->colorView, NULL),
100 MakeInlet("redSlider", InletTypeView, &this->redSlider, NULL),
101 MakeInlet("redInput", InletTypeView, &this->redInput, NULL),
102 MakeInlet("greenSlider", InletTypeView, &this->greenSlider, NULL),
103 MakeInlet("greenInput", InletTypeView, &this->greenInput, NULL),
104 MakeInlet("blueSlider", InletTypeView, &this->blueSlider, NULL),
105 MakeInlet("blueInput", InletTypeView, &this->blueInput, NULL),
106 MakeInlet("alphaSlider", InletTypeView, &this->alphaSlider, NULL),
107 MakeInlet("alphaInput", InletTypeView, &this->alphaInput, NULL),
108 MakeInlet("stackView", InletTypeView, &this->stackView, NULL)
109 );
110
111 $(self, bind, inlets, dictionary);
112}
113
117static View *init(View *self) {
118 return (View *) $((RGBColorPicker *) self, initWithFrame, NULL);
119}
120
124static void updateBindings(View *self) {
125
126 super(View, self, updateBindings);
127
128 RGBColorPicker *this = (RGBColorPicker *) self;
129
130 $(this->redSlider, setValue, this->color.r);
131 $(this->greenSlider, setValue, this->color.g);
132 $(this->blueSlider, setValue, this->color.b);
133 $(this->alphaSlider, setValue, this->color.a);
134
135 this->colorView->backgroundColor = this->color;
136}
137
138#pragma mark - RGBColorPicker
139
144static RGBColorPicker *initWithFrame(RGBColorPicker *self, const SDL_Rect *frame) {
145
146 self = (RGBColorPicker *) super(Control, self, initWithFrame, frame);
147 if (self) {
148
149 self->stackView = $(alloc(StackView), initWithFrame, NULL);
150 assert(self->stackView);
151
152 $((View *) self, addSubview, (View *) self->stackView);
153
154 self->colorView = $(alloc(View), initWithFrame, &MakeRect(0, 0, 0, 24));
155 assert(self->colorView);
156
157 $(self->colorView, addClassName, "colorView");
158 $((View *) self->stackView, addSubview, self->colorView);
159
160 self->redSlider = $(alloc(Slider), initWithFrame, NULL);
161 assert(self->redSlider);
162
163 self->redSlider->delegate.self = self;
164 self->redSlider->delegate.didSetValue = didSetComponent;
165 self->redSlider->max = 255.0;
166 $(self->redSlider, setLabelFormat, "%.0f");
167
168 self->redInput = $(alloc(Input), initWithFrame, NULL);
169 assert(self->redInput);
170
171 $(self->redInput, setControl, (Control *) self->redSlider);
172 $(self->redInput->label->text, setText, "R");
173
174 $((View *) self->stackView, addSubview, (View *) self->redInput);
175
176 self->greenSlider = $(alloc(Slider), initWithFrame, NULL);
177 assert(self->greenSlider);
178
179 self->greenSlider->delegate.self = self;
180 self->greenSlider->delegate.didSetValue = didSetComponent;
181 self->greenSlider->max = 255.0;
182 $(self->greenSlider, setLabelFormat, "%.0f");
183
184 self->greenInput = $(alloc(Input), initWithFrame, NULL);
185 assert(self->greenInput);
186
187 $(self->greenInput, setControl, (Control *) self->greenSlider);
188 $(self->greenInput->label->text, setText, "G");
189
190 $((View *) self->stackView, addSubview, (View *) self->greenInput);
191
192 self->blueSlider = $(alloc(Slider), initWithFrame, NULL);
193 assert(self->blueSlider);
194
195 self->blueSlider->delegate.self = self;
196 self->blueSlider->delegate.didSetValue = didSetComponent;
197 self->blueSlider->max = 255.0;
198 $(self->blueSlider, setLabelFormat, "%.0f");
199
200 self->blueInput = $(alloc(Input), initWithFrame, NULL);
201 assert(self->blueInput);
202
203 $(self->blueInput, setControl, (Control *) self->blueSlider);
204 $(self->blueInput->label->text, setText, "B");
205
206 $((View *) self->stackView, addSubview, (View *) self->blueInput);
207
208 self->alphaSlider = $(alloc(Slider), initWithFrame, NULL);
209 assert(self->alphaSlider);
210
211 self->alphaSlider->delegate.self = self;
212 self->alphaSlider->delegate.didSetValue = didSetComponent;
213 self->alphaSlider->max = 255.0;
214 $(self->alphaSlider, setLabelFormat, "%.0f");
215
216 self->alphaInput = $(alloc(Input), initWithFrame, NULL);
217 assert(self->alphaInput);
218
219 $(self->alphaInput, setControl, (Control *) self->alphaSlider);
220 $(self->alphaInput->label->text, setText, "A");
221
222 $((View *) self->stackView, addSubview, (View *) self->alphaInput);
223
224 $(self, setColor, &Colors.White);
225 }
226
227 return self;
228}
229
234static void setColor(RGBColorPicker *self, const SDL_Color *color) {
235
236 assert(color);
237
238 self->color = *color;
239
240 $((View *) self, updateBindings);
241}
242
243#pragma mark - Class lifecycle
244
248static void initialize(Class *clazz) {
249
250 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
251
252 ((ViewInterface *) clazz->interface)->awakeWithDictionary = awakeWithDictionary;
253 ((ViewInterface *) clazz->interface)->init = init;
254 ((ViewInterface *) clazz->interface)->updateBindings = updateBindings;
255
256 ((RGBColorPickerInterface *) clazz->interface)->initWithFrame = initWithFrame;
257 ((RGBColorPickerInterface *) clazz->interface)->setColor = setColor;
258}
259
264Class *_RGBColorPicker(void) {
265 static Class *clazz;
266 static Once once;
267
268 do_once(&once, {
269 clazz = _initialize(&(const ClassDef) {
270 .name = "RGBColorPicker",
271 .superclass = _Control(),
272 .instanceSize = sizeof(RGBColorPicker),
273 .interfaceOffset = offsetof(RGBColorPicker, interface),
274 .interfaceSize = sizeof(RGBColorPickerInterface),
276 });
277 });
278
279 return clazz;
280}
281
282#undef _Class
Class * _Control(void)
Definition Control.c:391
static void setControl(Input *self, Control *control)
Definition Input.c:113
static void addSubview(View *self, View *subview)
Definition PageView.c:49
static void setValue(ProgressBar *self, double value)
static void setLabelFormat(ProgressBar *self, const char *labelFormat)
static View * init(View *self)
static void awakeWithDictionary(View *self, const Dictionary *dictionary)
static RGBColorPicker * initWithFrame(RGBColorPicker *self, const SDL_Rect *frame)
static void dealloc(Object *self)
static void initialize(Class *clazz)
static void updateBindings(View *self)
static void setColor(RGBColorPicker *self, const SDL_Color *color)
static void didSetComponent(Slider *slider, double value)
SliderDelegate callback for color component modification.
Class * _RGBColorPicker(void)
RGB(A) color picker.
static void setText(Text *self, const char *text)
Definition Text.c:532
@ InletTypeColor
Definition View+JSON.h:62
@ InletTypeView
Definition View+JSON.h:139
#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
static void addClassName(View *self, const char *className)
Definition View.c:159
W3C Color constants.
Definition Colors.h:37
SDL_Color White
Definition Colors.h:185
Controls are Views which capture and respond to events.
Definition Control.h:83
Inlets enable inbound data binding of View attributes through JSON.
Definition View+JSON.h:155
An Input stacks a Label with a Control.
Definition Input.h:57
RGB(A) color picker.
void setColor(RGBColorPicker *self, const SDL_Color *color)
Sets the color of the RGBColorPicker.
StackView * stackView
The StackView.
SDL_Color color
The color.
ident self
The delegate self-reference.
Definition Slider.h:47
A Control allowing users to drag a handle to select a numeric value.
Definition Slider.h:62
SliderDelegate delegate
The delegate.
Definition Slider.h:83
StackViews are containers that manage the arrangement of their subviews.
Definition StackView.h:68
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:134
void updateBindings(View *self)
Updates data bindings, prompting the appropriate layout changes.