ObjectivelyMVC 0.1.0
Object oriented MVC framework for OpenGL, SDL2 and GNU C
Macros | Functions
Slider.c File Reference
#include <assert.h>
#include <string.h>
#include "Log.h"
#include "Slider.h"

Go to the source code of this file.

Macros

#define _Class   _Slider
 

Functions

Class * _Slider (void)
 
static void awakeWithDictionary (View *self, const Dictionary *dictionary)
 
static _Bool captureEvent (Control *self, const SDL_Event *event)
 
static void dealloc (Object *self)
 
static void formatLabel (Slider *self)
 
static Viewinit (View *self)
 
static void initialize (Class *clazz)
 
static SliderinitWithFrame (Slider *self, const SDL_Rect *frame)
 
static void layoutSubviews (View *self)
 
static void render (View *self, Renderer *renderer)
 
static void setLabelFormat (Slider *self, const char *labelFormat)
 
static void setValue (Slider *self, double value)
 

Macro Definition Documentation

◆ _Class

#define _Class   _Slider

Definition at line 30 of file Slider.c.

Function Documentation

◆ _Slider()

Class * _Slider ( void  )

Definition at line 298 of file Slider.c.

298 {
299 static Class *clazz;
300 static Once once;
301
302 do_once(&once, {
303 clazz = _initialize(&(const ClassDef) {
304 .name = "Slider",
305 .superclass = _Control(),
306 .instanceSize = sizeof(Slider),
307 .interfaceOffset = offsetof(Slider, interface),
308 .interfaceSize = sizeof(SliderInterface),
310 });
311 });
312
313 return clazz;
314}
static void initialize(Class *clazz)
Definition: Slider.c:277
Class * _Control(void)
The Control archetype.
Definition: Control.c:379
A Control allowing users to drag a handle to select a numeric value.
Definition: Slider.h:62

◆ awakeWithDictionary()

static void awakeWithDictionary ( View self,
const Dictionary *  dictionary 
)
static
See also
View::awakeWithDictionary(View *, const Dictionary *)

Definition at line 55 of file Slider.c.

55 {
56
57 super(View, self, awakeWithDictionary, dictionary);
58
59 Slider *this = (Slider *) self;
60
61 double value = this->value;
62
63 const Inlet inlets[] = MakeInlets(
64 MakeInlet("bar", InletTypeView, &this->bar, NULL),
65 MakeInlet("handle", InletTypeView, &this->handle, NULL),
66 MakeInlet("label", InletTypeView, &this->label, NULL),
67 MakeInlet("labelFormat", InletTypeCharacters, &this->labelFormat, NULL),
68 MakeInlet("min", InletTypeDouble, &this->min, NULL),
69 MakeInlet("max", InletTypeDouble, &this->max, NULL),
70 MakeInlet("step", InletTypeDouble, &this->step, NULL),
71 MakeInlet("value", InletTypeDouble, &value, NULL)
72 );
73
74 $(self, bind, inlets, dictionary);
75
76 $(this, setValue, value);
77}
@ InletTypeDouble
Definition: View+JSON.h:67
@ InletTypeCharacters
Definition: View+JSON.h:52
@ 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
Inlets enable inbound data binding of View attributes through JSON.
Definition: View+JSON.h:155
void setValue(const ProgressBar *self, double value)
Sets the value, which is clamped to min and max.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition: View.h:133
_Bool bind(View *self, const Inlet *inlets, const Dictionary *dictionary)
Performs data binding for the Inlets described in dictionary.
void awakeWithDictionary(View *self, const Dictionary *dictionary)
Wakes this View with the specified Dictionary.
Definition: Box.c:50

◆ captureEvent()

static _Bool captureEvent ( Control self,
const SDL_Event *  event 
)
static
See also
Control::captureEvent(Control *, const SDL_Event *)

Definition at line 146 of file Slider.c.

146 {
147
148 Slider *this = (Slider *) self;
149
150 if (event->type == SDL_MOUSEBUTTONDOWN) {
151 if ($((View *) this->handle, didReceiveEvent, event)) {
153 }
154 }
155
156 else if (event->type == SDL_MOUSEBUTTONUP) {
157 if (self->state & ControlStateHighlighted) {
158 self->state &= ~ControlStateHighlighted;
159 }
160 }
161
162 else if (event->type == SDL_MOUSEMOTION) {
163 if (self->state & ControlStateHighlighted) {
164 const SDL_Rect frame = $((View *) this->bar, renderFrame);
165 if (frame.w) {
166
167 const double fraction = (event->motion.x - frame.x) / (double) frame.w;
168 double value = this->min + (this->max - this->min) * clamp(fraction, 0.0, 1.0);
169
170 if (this->snapToStep && this->step) {
171 value = clamp(round(value / this->step) * this->step, this->min, this->max);
172 }
173
174 const double delta = fabs(this->value - value);
175 if (delta > __DBL_EPSILON__) {
176 $(this, setValue, value);
177
178 if (this->delegate.didSetValue) {
179 this->delegate.didSetValue(this, this->value);
180 }
181 }
182
183 return true;
184 }
185 }
186 }
187
188 return super(Control, self, captureEvent, event);
189}
@ ControlStateHighlighted
Definition: Control.h:68
Controls are Views which capture events and dispatch Actions.
Definition: Control.h:83
_Bool captureEvent(Control *self, const SDL_Event *event)
Captures a given event, potentially altering the state of this Control.
Definition: Button.c:76
unsigned int state
The bit mask of ControlState.
Definition: Control.h:110
_Bool didReceiveEvent(const View *self, const SDL_Event *event)
Definition: View.c:546
SDL_Rect renderFrame(const View *self)
Definition: View.c:1275

◆ dealloc()

static void dealloc ( Object *  self)
static
See also
Object::dealloc(Object *)

Definition at line 37 of file Slider.c.

37 {
38
39 Slider *this = (Slider *) self;
40
41 release(this->bar);
42 release(this->handle);
43 release(this->label);
44
45 free(this->labelFormat);
46
47 super(Object, self, dealloc);
48}
static void dealloc(Object *self)
Definition: Slider.c:37

◆ formatLabel()

static void formatLabel ( Slider self)
static

Definition at line 197 of file Slider.c.

197 {
198
199 char text[64];
200 snprintf(text, sizeof(text), self->labelFormat, self->value);
201
202 $(self->label, setText, text);
203}
Text * label
The Text displaying the current value.
Definition: Slider.h:94
char * labelFormat
The label format, e.g. "%0.01f".
Definition: Slider.h:99
double value
The slider value.
Definition: Slider.h:119
void setText(Text *self, const char *text)
Sets this Text's text.
Definition: Text.c:261

◆ init()

static View * init ( View self)
static
See also
View::init(View *)

Definition at line 82 of file Slider.c.

82 {
83 return (View *) $((Slider *) self, initWithFrame, NULL);
84}
Box * initWithFrame(Box *self, const SDL_Rect *frame)
Initializes this Box with the given frame.
Definition: Box.c:92

◆ initialize()

static void initialize ( Class *  clazz)
static
See also
Class::initialize(Class *)

Definition at line 277 of file Slider.c.

277 {
278
279 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
280
281 ((ViewInterface *) clazz->interface)->awakeWithDictionary = awakeWithDictionary;
282 ((ViewInterface *) clazz->interface)->init = init;
283 ((ViewInterface *) clazz->interface)->layoutSubviews = layoutSubviews;
284 ((ViewInterface *) clazz->interface)->render = render;
285
286 ((ControlInterface *) clazz->interface)->captureEvent = captureEvent;
287
288 ((SliderInterface *) clazz->interface)->formatLabel = formatLabel;
289 ((SliderInterface *) clazz->interface)->initWithFrame = initWithFrame;
290 ((SliderInterface *) clazz->interface)->setValue = setValue;
291 ((SliderInterface *) clazz->interface)->setLabelFormat = setLabelFormat;
292}
CollectionView * init(CollectionView *self, const SDL_Rect *frame)
Initializes this CollectionView with the specified frame and style.
void setLabelFormat(ProgressBar *self, const char *labelFormat)
Changes this ProgressBar's label format and calls appropriate update functions.
Definition: ProgressBar.c:145
void formatLabel(ProgressBar *self)
Forces an update on this ProgressBar's label.
Definition: ProgressBar.c:90
layoutSubviews(View *self)
Performs layout for this View's immediate subviews.
Definition: Box.c:74
void render(View *self, Renderer *renderer)
Renders this View using the given renderer.
Definition: Control.c:131

◆ initWithFrame()

static Slider * initWithFrame ( Slider self,
const SDL_Rect *  frame 
)
static

Definition at line 209 of file Slider.c.

209 {
210
211 self = (Slider *) super(Control, self, initWithFrame, frame);
212 if (self) {
213
214 self->bar = $(alloc(View), initWithFrame, frame);
215 assert(self->bar);
216
217 $(self->bar, addClassName, "bar");
218
219 $((View *) self, addSubview, self->bar);
220
221 self->handle = $(alloc(Control), initWithFrame, NULL);
222 assert(self->handle);
223
224 $((View *) self->handle, addClassName, "handle");
225
226 $(self->bar, addSubview, (View *) self->handle);
227
228 self->label = $(alloc(Text), initWithText, NULL, NULL);
229 assert(self->label);
230
231 $((View *) self->label, addClassName, "label");
232
233 $((View *) self, addSubview, (View *) self->label);
234
235 $(self, setLabelFormat, "%0.1f");
236 }
237
238 return self;
239}
Label * initWithText(Label *self, const char *text, Font *font)
Initializes this Label with the given text and Font.
Definition: Label.c:96
View * bar
The slider bar.
Definition: Slider.h:78
Text rendered with TrueType fonts.
Definition: Text.h:41
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

◆ layoutSubviews()

static void layoutSubviews ( View self)
static
See also
View::layoutSubviews(View *)

Definition at line 89 of file Slider.c.

89 {
90
91 super(View, self, layoutSubviews);
92
93 Slider *this = (Slider *) self;
94
95 if (this->max > this->min) {
96
97 if (((View *) this->label)->hidden == false) {
98 int minWidth, maxWidth;
99 char text[64];
100
101 Text *label = (Text *) this->label;
102
103 snprintf(text, sizeof(text), this->labelFormat, this->min);
104 $(label->font, sizeCharacters, text, &minWidth, NULL);
105
106 snprintf(text, sizeof(text), this->labelFormat, this->max);
107 $(label->font, sizeCharacters, text, &maxWidth, NULL);
108
109 this->bar->frame.w -= max(minWidth, maxWidth) + label->view.padding.left;
110 }
111
112 const double fraction = clamp((this->value - this->min) / (this->max - this->min), 0.0, 1.0);
113 const SDL_Rect bounds = $(this->bar, bounds);
114
115 View *handle = (View *) this->handle;
116 handle->frame.x = (bounds.w * fraction) - handle->frame.w * 0.5;
117 } else {
118 MVC_LogWarn("max > min");
119 }
120}
#define MVC_LogWarn(fmt,...)
Definition: Log.h:52
void sizeCharacters(const Font *self, const char *chars, int *w, int *h)
Definition: Font.c:272
View view
The superclass.
Definition: Text.h:46
Font * font
The Font.
Definition: Text.h:64
SDL_Rect bounds(const View *self)
Definition: View.c:394
ViewPadding padding
The padding.
Definition: View.h:233
SDL_Rect frame
The frame, relative to the superview.
Definition: View.h:190
int left
Definition: View.h:100

◆ render()

static void render ( View self,
Renderer renderer 
)
static
See also
View::render(View *, Renderer *)

Definition at line 125 of file Slider.c.

125 {
126
127 super(View, self, render, renderer);
128
129 Slider *this = (Slider *) self;
130
131 const SDL_Rect frame = $(this->bar, renderFrame);
132
133 const SDL_Point points[] = {
134 { frame.x, frame.y + frame.h * 0.5 },
135 { frame.x + frame.w, frame.y + frame.h * 0.5 }
136 };
137
138 $(renderer, drawLine, points);
139}
void drawLine(const Renderer *self, const SDL_Point *points)
Draws a line segment between two points using GL_LINE_STRIP.
Definition: Renderer.c:94

◆ setLabelFormat()

static void setLabelFormat ( Slider self,
const char *  labelFormat 
)
static

Definition at line 245 of file Slider.c.

245 {
246
247 if (self->labelFormat) {
248 free(self->labelFormat);
249 }
250
251 self->labelFormat = strdup(labelFormat);
252 $(self, formatLabel);
253}

◆ setValue()

static void setValue ( Slider self,
double  value 
)
static

Definition at line 259 of file Slider.c.

259 {
260
261 value = clamp(value, self->min, self->max);
262
263 const double delta = fabs(self->value - value);
264 if (delta > __DBL_EPSILON__) {
265 self->value = value;
266 self->control.view.needsLayout = true;
267
268 $(self, formatLabel);
269 }
270}
View view
The superclass.
Definition: Control.h:88
double max
Definition: Slider.h:104
double min
The slider bounds.
Definition: Slider.h:104
Control control
The superclass.
Definition: Slider.h:67
_Bool needsLayout
If true, this View will layout its subviews before it is drawn.
Definition: View.h:221