ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
HSVColorPicker.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
26#include "HSVColorPicker.h"
27
28#define _Class _HSVColorPicker
29
30#pragma mark - Delegates
31
35static void didSetComponent(Slider *slider, double value) {
36
37 HSVColorPicker *this = (HSVColorPicker *) slider->delegate.self;
38
39 if (slider == this->hueSlider) {
40 this->hue = value;
41 } else if (slider == this->saturationSlider) {
42 this->saturation = value;
43 } else if (slider == this->valueSlider) {
44 this->value = value;
45 } else {
46 assert(false);
47 }
48
49 $((View *) this, updateBindings, NULL);
50
51 if (this->delegate.didPickColor) {
52 this->delegate.didPickColor(this, this->hue, this->saturation, this->value);
53 }
54}
55
56#pragma mark - Object
57
61static void dealloc(Object *self) {
62
63 HSVColorPicker *this = (HSVColorPicker *) self;
64
65 memset(&this->delegate, 0, sizeof(this->delegate));
66
67 release(this->colorView);
68 release(this->hueSlider);
69 release(this->hueInput);
70 release(this->saturationSlider);
71 release(this->saturationInput);
72 release(this->valueSlider);
73 release(this->valueInput);
74 release(this->stackView);
75
76 super(Object, self, dealloc);
77}
78
79#pragma mark - View
80
84static void awakeWithDictionary(View *self, const Dictionary *dictionary) {
85
86 super(View, self, awakeWithDictionary, dictionary);
87
88 HSVColorPicker *this = (HSVColorPicker *) self;
89
90 const Inlet inlets[] = MakeInlets(
91 MakeInlet("colorView", InletTypeView, &this->colorView, NULL),
92 MakeInlet("hue", InletTypeDouble, &this->hue, NULL),
93 MakeInlet("saturation", InletTypeDouble, &this->saturation, NULL),
94 MakeInlet("value", InletTypeDouble, &this->value, NULL),
95 MakeInlet("hueSlider", InletTypeView, &this->hueSlider, NULL),
96 MakeInlet("hueInput", InletTypeView, &this->hueInput, NULL),
97 MakeInlet("saturationSlider", InletTypeView, &this->saturationSlider, NULL),
98 MakeInlet("saturationInput", InletTypeView, &this->saturationInput, NULL),
99 MakeInlet("valueSlider", InletTypeView, &this->valueSlider, NULL),
100 MakeInlet("valueInput", InletTypeView, &this->valueInput, NULL),
101 MakeInlet("stackView", InletTypeView, &this->stackView, NULL)
102 );
103
104 $(self, bind, inlets, dictionary);
105}
106
110static View *init(View *self) {
111 return (View *) $((HSVColorPicker *) self, initWithFrame, NULL);
112}
113
117static void updateBindings(View *self, ident data) {
118
119 super(View, self, updateBindings, data);
120
121 HSVColorPicker *this = (HSVColorPicker *) self;
122
123 $(this->hueSlider, setValue, this->hue);
124 $(this->saturationSlider, setValue, this->saturation);
125 $(this->valueSlider, setValue, this->value);
126
127 const SDL_Color color = $(this, rgbColor);
128 $(this->colorView->style, addColorAttribute, "background-color", &color);
129 $(this->colorView, invalidateStyle);
130}
131
132#pragma mark - HSVColorPicker
133
138static HSVColorPicker *initWithFrame(HSVColorPicker *self, const SDL_Rect *frame) {
139
140 self = (HSVColorPicker *) super(Control, self, initWithFrame, frame);
141 if (self) {
142
143 self->stackView = $(alloc(StackView), initWithFrame, NULL);
144 assert(self->stackView);
145
146 $((View *) self, addSubview, (View *) self->stackView);
147
148 self->colorView = $(alloc(View), initWithFrame, &MakeRect(0, 0, 0, 24));
149 assert(self->colorView);
150
151 $(self->colorView, addClassName, "colorView");
152 $((View *) self->stackView, addSubview, self->colorView);
153
154 self->hueSlider = $(alloc(Slider), initWithFrame, NULL);
155 assert(self->hueSlider);
156
157 self->hueSlider->delegate.self = self;
158 self->hueSlider->delegate.didSetValue = didSetComponent;
159 self->hueSlider->max = 360.0;
160 $(self->hueSlider, setLabelFormat, "%.0lf");
161
162 self->hueInput = $(alloc(Input), initWithFrame, NULL);
163 assert(self->hueInput);
164
165 $(self->hueInput, setControl, (Control *) self->hueSlider);
166 $(self->hueInput->label->text, setText, "H");
167
168 $((View *) self->stackView, addSubview, (View *) self->hueInput);
169
170 self->saturationSlider = $(alloc(Slider), initWithFrame, NULL);
171 assert(self->saturationSlider);
172
173 self->saturationSlider->delegate.self = self;
174 self->saturationSlider->delegate.didSetValue = didSetComponent;
175 self->saturationSlider->max = 1.0;
176 $(self->saturationSlider, setLabelFormat, "%.3f");
177
178 self->saturationInput = $(alloc(Input), initWithFrame, NULL);
179 assert(self->saturationInput);
180
181 $(self->saturationInput, setControl, (Control *) self->saturationSlider);
182 $(self->saturationInput->label->text, setText, "S");
183
184 $((View *) self->stackView, addSubview, (View *) self->saturationInput);
185
186 self->valueSlider = $(alloc(Slider), initWithFrame, NULL);
187 assert(self->valueSlider);
188
189 self->valueSlider->delegate.self = self;
190 self->valueSlider->delegate.didSetValue = didSetComponent;
191 self->valueSlider->max = 1.0;
192 $(self->valueSlider, setLabelFormat, "%.3f");
193
194 self->valueInput = $(alloc(Input), initWithFrame, NULL);
195 assert(self->valueInput);
196
197 $(self->valueInput, setControl, (Control *) self->valueSlider);
198 $(self->valueInput->label->text, setText, "V");
199
200 $((View *) self->stackView, addSubview, (View *) self->valueInput);
201
202 $(self, setColor, 0.0, 1.0, 1.0);
203 }
204
205 return self;
206}
207
212static SDL_Color rgbColor(const HSVColorPicker *self) {
213 return MVC_HSVToRGB(self->hue, self->saturation, self->value);
214}
215
220static void setColor(HSVColorPicker *self, double hue, double saturation, double value) {
221
222 self->hue = hue;
223 self->saturation = saturation;
224 self->value = value;
225
226 $((View *) self, updateBindings, NULL);
227}
228
233static void setRGBColor(HSVColorPicker *self, const SDL_Color *color) {
234
235 MVC_RGBToHSV(color, &self->hue, &self->saturation, &self->value);
236
237 $((View *) self, updateBindings, NULL);
238}
239
240#pragma mark - Class lifecycle
241
245static void initialize(Class *clazz) {
246
247 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
248
249 ((ViewInterface *) clazz->interface)->awakeWithDictionary = awakeWithDictionary;
250 ((ViewInterface *) clazz->interface)->init = init;
251 ((ViewInterface *) clazz->interface)->updateBindings = updateBindings;
252
253 ((HSVColorPickerInterface *) clazz->interface)->initWithFrame = initWithFrame;
254 ((HSVColorPickerInterface *) clazz->interface)->rgbColor = rgbColor;
255 ((HSVColorPickerInterface *) clazz->interface)->setColor = setColor;
256 ((HSVColorPickerInterface *) clazz->interface)->setRGBColor = setRGBColor;
257}
258
263Class *_HSVColorPicker(void) {
264 static Class *clazz;
265 static Once once;
266
267 do_once(&once, {
268 clazz = _initialize(&(const ClassDef) {
269 .name = "HSVColorPicker",
270 .superclass = _Control(),
271 .instanceSize = sizeof(HSVColorPicker),
272 .interfaceSize = sizeof(HSVColorPickerInterface),
273 .initialize = initialize,
274 });
275 });
276
277 return clazz;
278}
279
280#undef _Class
SDL_Color MVC_HSVToRGB(double hue, double saturation, double value)
Definition Colors.c:685
void MVC_RGBToHSV(const SDL_Color *color, double *hue, double *saturation, double *value)
Definition Colors.c:733
Class * _Control(void)
Definition Control.c:414
Class * _HSVColorPicker(void)
static View * init(View *self)
static void awakeWithDictionary(View *self, const Dictionary *dictionary)
static void setRGBColor(HSVColorPicker *self, const SDL_Color *color)
static HSVColorPicker * initWithFrame(HSVColorPicker *self, const SDL_Rect *frame)
static void setColor(HSVColorPicker *self, double hue, double saturation, double value)
static void updateBindings(View *self, ident data)
static void dealloc(Object *self)
static SDL_Color rgbColor(const HSVColorPicker *self)
static void initialize(Class *clazz)
static void didSetComponent(Slider *slider, double value)
SliderDelegate callback for color component modification.
HSV color picker.
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 void addColorAttribute(Style *self, const char *attr, const SDL_Color *color)
Definition Style.c:253
static void setText(Text *self, const char *text)
Definition Text.c:899
@ InletTypeDouble
Definition View+JSON.h:67
@ InletTypeView
Definition View+JSON.h:133
#define MakeInlets(...)
Creates a null-termianted array of Inlets.
Definition View+JSON.h:215
#define MakeInlet(name, type, dest, data)
Creates an Inlet with the specified parameters.
Definition View+JSON.h:210
static void addClassName(View *self, const char *className)
Definition View.c:183
static void invalidateStyle(View *self)
Definition View.c:1092
Controls are Views which capture and respond to events.
Definition Control.h:83
The HSVColorPicker type.
SDL_Color rgbColor(const HSVColorPicker *self)
double hue
The color components.
StackView * stackView
The StackView.
Inlets enable inbound data binding of View attributes through JSON.
Definition View+JSON.h:149
An Input stacks a Label with a Control.
Definition Input.h:57
ident self
The delegate self-reference.
Definition Slider.h:50
A Control allowing users to drag a handle to select a numeric value.
Definition Slider.h:65
SliderDelegate delegate
The delegate.
Definition Slider.h:86
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:225
void updateBindings(View *self, ident data)
Updates data bindings, prompting the appropriate layout changes.