ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
ProgressBar.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#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29
30#include "ProgressBar.h"
31
32#define _Class _ProgressBar
33
34#pragma mark - Object
35
39static void dealloc(Object *self) {
40
41 ProgressBar *this = (ProgressBar *) self;
42
43 memset(&this->delegate, 0, sizeof(this->delegate));
44
45 release(this->background);
46 release(this->foreground);
47 release(this->label);
48
49 free(this->labelFormat);
50
51 super(Object, self, dealloc);
52}
53
54#pragma mark - View
55
59static void awakeWithDictionary(View *self, const Dictionary *dictionary) {
60
61 super(View, self, awakeWithDictionary, dictionary);
62
63 ProgressBar *this = (ProgressBar *) self;
64
65 double value = this->value;
66
67 const Inlet inlets[] = MakeInlets(
68 MakeInlet("background", InletTypeView, &this->background, NULL),
69 MakeInlet("foreground", InletTypeView, &this->foreground, NULL),
70 MakeInlet("label", InletTypeView, &this->label, NULL),
71 MakeInlet("labelFormat", InletTypeCharacters, &this->labelFormat, NULL),
72 MakeInlet("min", InletTypeDouble, &this->min, NULL),
73 MakeInlet("max", InletTypeDouble, &this->max, NULL),
74 MakeInlet("value", InletTypeDouble, &value, NULL)
75 );
76
77 $(self, bind, inlets, dictionary);
78
79 $(this, setValue, value);
80}
81
85static View *init(View *self) {
86 return (View *) $((ProgressBar *) self, initWithFrame, NULL);
87}
88
89#pragma mark - ProgressBar
90
95static void formatLabel(ProgressBar *self) {
96
97 char text[128];
98 snprintf(text, sizeof(text), self->labelFormat, self->value);
99
100 $(self->label, setText, text);
101}
102
107static ProgressBar *initWithFrame(ProgressBar *self, const SDL_Rect *frame) {
108
109 self = (ProgressBar *) super(View, self, initWithFrame, frame);
110 if (self) {
111
112 self->background = $(alloc(ImageView), initWithFrame, NULL);
113 assert(self->background);
114
115 $((View *) self->background, addClassName, "background");
116 $((View *) self, addSubview, (View *) self->background);
117
118 self->foreground = $(alloc(ImageView), initWithFrame, NULL);
119 assert(self->foreground);
120
121 $((View *) self->foreground, addClassName, "foreground");
122 $((View *) self, addSubview, (View *) self->foreground);
123
124 self->label = $(alloc(Text), initWithText, NULL, NULL);
125 assert(self->label);
126
127 $((View *) self, addSubview, (View *) self->label);
128
129 $(self, setLabelFormat, "%0.0lf%%");
130
131 self->value = -1.0;
132 self->max = 100.0;
133 }
134
135 return self;
136}
137
142static double progress(const ProgressBar *self) {
143 return 100.0 * self->value / (self->max - self->min);
144}
145
150static void setLabelFormat(ProgressBar *self, const char *labelFormat) {
151
152 if (self->labelFormat) {
153 free(self->labelFormat);
154 }
155
156 self->labelFormat = strdup(labelFormat);
157 $(self, formatLabel);
158}
159
164static void setValue(ProgressBar *self, double value) {
165
166 value = clamp(value, self->min, self->max);
167
168 const double delta = fabs(self->value - value);
169 if (delta > __DBL_EPSILON__) {
170 self->value = value;
171
172 const SDL_Rect bounds = $((View *) self, bounds);
173 const double frac = self->value / (self->max - self->min);
174
175 self->foreground->view.frame.w = bounds.w * frac;
176 self->view.needsLayout = true;
177
178 $(self, formatLabel);
179
180 if (self->delegate.didSetValue) {
181 self->delegate.didSetValue(self, self->value);
182 }
183 }
184}
185
186#pragma mark - Class lifecycle
187
191static void initialize(Class *clazz) {
192
193 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
194
195 ((ViewInterface *) clazz->interface)->awakeWithDictionary = awakeWithDictionary;
196 ((ViewInterface *) clazz->interface)->init = init;
197
198 ((ProgressBarInterface *) clazz->interface)->formatLabel = formatLabel;
199 ((ProgressBarInterface *) clazz->interface)->initWithFrame = initWithFrame;
200 ((ProgressBarInterface *) clazz->interface)->progress = progress;
201 ((ProgressBarInterface *) clazz->interface)->setLabelFormat = setLabelFormat;
202 ((ProgressBarInterface *) clazz->interface)->setValue = setValue;
203}
204
209Class *_ProgressBar(void) {
210 static Class *clazz;
211 static Once once;
212
213 do_once(&once, {
214 clazz = _initialize(&(const ClassDef) {
215 .name = "ProgressBar",
216 .superclass = _View(),
217 .instanceSize = sizeof(ProgressBar),
218 .interfaceOffset = offsetof(ProgressBar, interface),
219 .interfaceSize = sizeof(ProgressBarInterface),
221 });
222 });
223
224 return clazz;
225}
226
227#undef _Class
static Label * initWithText(Label *self, const char *text, Font *font)
Definition Label.c:97
static void addSubview(View *self, View *subview)
Definition PageView.c:49
static View * init(View *self)
Definition ProgressBar.c:85
static void awakeWithDictionary(View *self, const Dictionary *dictionary)
Definition ProgressBar.c:59
static void setValue(ProgressBar *self, double value)
Class * _ProgressBar(void)
static void dealloc(Object *self)
Definition ProgressBar.c:39
static double progress(const ProgressBar *self)
static void setLabelFormat(ProgressBar *self, const char *labelFormat)
static void initialize(Class *clazz)
static ProgressBar * initWithFrame(ProgressBar *self, const SDL_Rect *frame)
static void formatLabel(ProgressBar *self)
Definition ProgressBar.c:95
A Progress bar.
static void setText(Text *self, const char *text)
Definition Text.c:532
@ 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
static void addClassName(View *self, const char *className)
Definition View.c:159
Class * _View(void)
Definition View.c:2067
static SDL_Rect bounds(const View *self)
Definition View.c:492
ImageViews render an Image in the context of a View hierarchy.
Definition ImageView.h:45
Inlets enable inbound data binding of View attributes through JSON.
Definition View+JSON.h:155
The ProgressBar type.
Definition ProgressBar.h:61
double min
The progress bounds.
double value
The progress value.
Text * label
The progress Text.
Definition ProgressBar.h:94
ImageView * background
The background ImageView.
Definition ProgressBar.h:78
double progress(const ProgressBar *self)
char * labelFormat
The Label format, e.g. "%0.0lf".
Definition ProgressBar.h:99
Text rendered with TrueType fonts.
Definition Text.h:69
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:134
bool needsLayout
If true, this View will layout its subviews before it is drawn.
Definition View.h:222
void awakeWithDictionary(View *, const Dictionary *)
Wakes this View with the specified Dictionary.
Definition Box.c:50
SDL_Rect frame
The frame, relative to the superview.
Definition View.h:191
View * initWithFrame(View *self, const SDL_Rect *frame)
Initializes this View with the specified frame.
Definition View.c:989