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
144 if (self->max <= self->min) {
145 return 0.0;
146 }
147
148 return 100.0 * (self->value - self->min) / (self->max - self->min);
149}
150
155static void setLabelFormat(ProgressBar *self, const char *labelFormat) {
156
157 if (self->labelFormat) {
158 free(self->labelFormat);
159 }
160
161 self->labelFormat = strdup(labelFormat);
162 $(self, formatLabel);
163}
164
169static void setValue(ProgressBar *self, double value) {
170
171 value = clamp(value, self->min, self->max);
172
173 const double delta = fabs(self->value - value);
174 if (delta > __DBL_EPSILON__) {
175 self->value = value;
176
177 const SDL_Rect bounds = $((View *) self, bounds);
178 const double frac = $(self, progress) / 100.0;
179
180 self->foreground->view.frame.w = bounds.w * frac;
181 $((View *) self, setNeedsLayout);
182
183 $(self, formatLabel);
184
185 if (self->delegate.didSetValue) {
186 self->delegate.didSetValue(self, self->value);
187 }
188 }
189}
190
191#pragma mark - Class lifecycle
192
196static void initialize(Class *clazz) {
197
198 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
199
200 ((ViewInterface *) clazz->interface)->awakeWithDictionary = awakeWithDictionary;
201 ((ViewInterface *) clazz->interface)->init = init;
202
203 ((ProgressBarInterface *) clazz->interface)->formatLabel = formatLabel;
204 ((ProgressBarInterface *) clazz->interface)->initWithFrame = initWithFrame;
205 ((ProgressBarInterface *) clazz->interface)->progress = progress;
206 ((ProgressBarInterface *) clazz->interface)->setLabelFormat = setLabelFormat;
207 ((ProgressBarInterface *) clazz->interface)->setValue = setValue;
208}
209
214Class *_ProgressBar(void) {
215 static Class *clazz;
216 static Once once;
217
218 do_once(&once, {
219 clazz = _initialize(&(const ClassDef) {
220 .name = "ProgressBar",
221 .superclass = _View(),
222 .instanceSize = sizeof(ProgressBar),
223 .interfaceSize = sizeof(ProgressBarInterface),
224 .initialize = initialize,
225 });
226 });
227
228 return clazz;
229}
230
231#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:899
@ InletTypeDouble
Definition View+JSON.h:67
@ InletTypeCharacters
Definition View+JSON.h:52
@ 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
Class * _View(void)
Definition View.c:2336
static void setNeedsLayout(View *self)
Definition View.c:1865
static SDL_Rect bounds(const View *self)
Definition View.c:552
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:149
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:131
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:225
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:301
View * initWithFrame(View *self, const SDL_Rect *frame)
Initializes this View with the specified frame.
Definition View.c:1047