ObjectivelyMVC
Object oriented MVC framework for SDL3 and GNU C
Loading...
Searching...
No Matches
Select.c File Reference
#include <assert.h>
#include <Objectively/Array.h>
#include "Select.h"

Go to the source code of this file.

Macros

#define _Class   _Select
 

Functions

Class * _Select (void)
 
static void addOption (Select *self, const char *title, ident value)
 
static void addOption_addSubview (const Array *array, ident obj, ident data)
 ArrayEnumerator to add Options to the stackView.
 
static void addOption_removeSubview (const Array *array, ident obj, ident data)
 ArrayEnumerator to remove Options from the stackView.
 
static bool captureEvent (Control *self, const SDL_Event *event)
 
static void dealloc (Object *self)
 
static Viewinit (View *self)
 
static void initialize (Class *clazz)
 
static SelectinitWithFrame (Select *self, const SDL_Rect *frame)
 
static void layoutSubviews (View *self)
 
static OptionoptionWithValue (const Select *self, const ident value)
 
static bool optionWithValue_predicate (ident obj, ident data)
 Predicate function for optionWithValue.
 
static void removeAllOptions (Select *self)
 
static void removeAllOptions_enumerate (const Array *array, ident obj, ident data)
 ArrayEnumerator for removeAllOptions.
 
static void removeOption (Select *self, Option *option)
 
static void removeOptionWithValue (Select *self, ident value)
 
static OptionselectedOption (const Select *self)
 
static Array * selectedOptions (const Select *self)
 
static bool selectedOptions_predicate (ident obj, ident data)
 Predicate for selectedOption and selectedOptions.
 
static void selectOption (Select *self, Option *option)
 
static void selectOption_enumerate (const Array *array, ident obj, ident data)
 ArrayEnumerator for enforcing ControlSelectionSingle.
 
static void selectOptionWithValue (Select *self, ident value)
 
static SDL_Size sizeThatFits (const View *self)
 
static void stateDidChange (Control *self)
 

Macro Definition Documentation

◆ _Class

#define _Class   _Select

Definition at line 30 of file Select.c.

Function Documentation

◆ _Select()

Class * _Select ( void  )

Definition at line 463 of file Select.c.

463 {
464 static Class *clazz;
465 static Once once;
466
467 do_once(&once, {
468 clazz = _initialize(&(const ClassDef) {
469 .name = "Select",
470 .superclass = _Control(),
471 .instanceSize = sizeof(Select),
472 .interfaceOffset = offsetof(Select, interface),
473 .interfaceSize = sizeof(SelectInterface),
475 });
476 });
477
478 return clazz;
479}
Class * _Control(void)
Definition Control.c:391
static void initialize(Class *clazz)
Definition Select.c:436
A Control allowing users to select one or more Options.
Definition Select.h:63

◆ addOption()

static void addOption ( Select self,
const char *  title,
ident  value 
)
static

Definition at line 253 of file Select.c.

253 {
254
255 Option *option = $(alloc(Option), initWithTitle, title, value);
256 assert(option);
257
258 $(self->options, addObject, option);
259
260 $((Array *) self->options, enumerate, addOption_removeSubview, self->stackView);
261
262 if (self->comparator) {
263 $(self->options, sort, self->comparator);
264 }
265
266 $((Array *) self->options, enumerate, addOption_addSubview, self->stackView);
267
269 if ($(self, selectedOption) == NULL) {
270 $(option, setSelected, true);
271 }
272 }
273
274 option->view.nextResponder = (View *) self;
275
276 release(option);
277
278 self->control.view.needsLayout = true;
279}
static Button * initWithTitle(Button *self, const char *title)
Definition Button.c:174
static void setSelected(CollectionItemView *self, bool isSelected)
@ ControlSelectionSingle
Definition Control.h:56
static Option * selectedOption(const Select *self)
Definition Select.c:419
static void addOption_removeSubview(const Array *array, ident obj, ident data)
ArrayEnumerator to remove Options from the stackView.
Definition Select.c:238
static void addOption_addSubview(const Array *array, ident obj, ident data)
ArrayEnumerator to add Options to the stackView.
Definition Select.c:245
static void enumerate(View *self, ViewEnumerator enumerator, ident data)
Definition View.c:749
View view
The superclass.
Definition Control.h:88
ControlSelection selection
The ControlSelection.
Definition Control.h:109
Select Options.
Definition Option.h:41
View view
The superclass.
Definition Option.h:46
Comparator comparator
An optional Comparator to sort Options.
Definition Select.h:79
Array * options
The Options.
Definition Select.h:89
StackView * stackView
The StackView for rendering the Options.
Definition Select.h:94
Control control
The superclass.
Definition Select.h:68
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
Definition View.h:134
View * nextResponder
The next responder, or event handler, in the chain.
Definition View.h:229
bool needsLayout
If true, this View will layout its subviews before it is drawn.
Definition View.h:222

◆ addOption_addSubview()

static void addOption_addSubview ( const Array *  array,
ident  obj,
ident  data 
)
static

ArrayEnumerator to add Options to the stackView.

Definition at line 245 of file Select.c.

245 {
246 $((View *) data, addSubview, obj);
247}
static void addSubview(View *self, View *subview)
Definition PageView.c:49

◆ addOption_removeSubview()

static void addOption_removeSubview ( const Array *  array,
ident  obj,
ident  data 
)
static

ArrayEnumerator to remove Options from the stackView.

Definition at line 238 of file Select.c.

238 {
239 $((View *) data, removeSubview, obj);
240}
static void removeSubview(View *self, View *subview)
Definition PageView.c:72

◆ captureEvent()

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

Definition at line 116 of file Select.c.

116 {
117
118 Select *this = (Select *) self;
119
120 const Array *options = (Array *) this->options;
121
122 if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
123 if (self->state & ControlStateHighlighted) {
124 $((View *) self, becomeTouchResponder);
125 return true;
126 }
127 }
128
129 if (event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
130 if (self->state & ControlStateHighlighted) {
131 self->state &= ~ControlStateHighlighted;
132
133 for (size_t i = 0; i < options->count; i++) {
134
135 Option *option = $(options, objectAtIndex, i);
136 if ($((View *) option, didReceiveEvent, event)) {
137 $(this, selectOption, option);
138 if (this->delegate.didSelectOption) {
139 this->delegate.didSelectOption(this, option);
140 }
141 return true;
142 }
143 }
144 } else {
146 return true;
147 }
148 }
149
150 if (event->type == SDL_EVENT_KEY_DOWN) {
151
152 switch (event->key.key) {
153
154 case SDLK_ESCAPE:
155 self->state &= ~ControlStateHighlighted;
156 return true;
157
158 case SDLK_RETURN:
159 case SDLK_KP_ENTER:
161 return true;
162
163 case SDLK_UP:
164 case SDLK_DOWN: {
165 Option *option = $(this, selectedOption);
166 if (option) {
167
168 ssize_t index = $(options, indexOfObject, option);
169 if (event->key.key == SDLK_UP) {
170 index = (index - 1 + options->count) % options->count;
171 } else {
172 index = (index + 1) % options->count;
173 }
174
175 option = $(options, objectAtIndex, index);
176
177 $(this, selectOption, option);
178 if (this->delegate.didSelectOption) {
179 this->delegate.didSelectOption(this, option);
180 }
181 }
182 return true;
183 }
184 }
185 }
186
187 return super(Control, self, captureEvent, event);
188}
@ ControlStateHighlighted
Definition Control.h:67
static void selectOption(Select *self, Option *option)
Definition Select.c:381
static bool captureEvent(Control *self, const SDL_Event *event)
Definition Select.c:116
static void becomeTouchResponder(View *self)
Definition View.c:451
static bool didReceiveEvent(const View *self, const SDL_Event *event)
Definition View.c:668
Controls are Views which capture and respond to events.
Definition Control.h:83
unsigned int state
The bit mask of ControlState.
Definition Control.h:104

◆ dealloc()

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

Definition at line 37 of file Select.c.

37 {
38
39 Select *this = (Select *) self;
40
41 memset(&this->delegate, 0, sizeof(this->delegate));
42
43 release(this->options);
44 release(this->stackView);
45
46 super(Object, self, dealloc);
47}
static void dealloc(Object *self)
Definition Select.c:37

◆ init()

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

Definition at line 54 of file Select.c.

54 {
55 return (View *) $((Select *) self, initWithFrame, NULL);
56}
static Select * initWithFrame(Select *self, const SDL_Rect *frame)
Definition Select.c:285

◆ initialize()

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

Definition at line 436 of file Select.c.

436 {
437
438 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
439
440 ((ViewInterface *) clazz->interface)->init = init;
441 ((ViewInterface *) clazz->interface)->layoutSubviews = layoutSubviews;
442 ((ViewInterface *) clazz->interface)->sizeThatFits = sizeThatFits;
443
444 ((ControlInterface *) clazz->interface)->captureEvent = captureEvent;
445 ((ControlInterface *) clazz->interface)->stateDidChange = stateDidChange;
446
447 ((SelectInterface *) clazz->interface)->addOption = addOption;
448 ((SelectInterface *) clazz->interface)->initWithFrame = initWithFrame;
449 ((SelectInterface *) clazz->interface)->optionWithValue = optionWithValue;
450 ((SelectInterface *) clazz->interface)->removeAllOptions = removeAllOptions;
451 ((SelectInterface *) clazz->interface)->removeOption = removeOption;
452 ((SelectInterface *) clazz->interface)->removeOptionWithValue = removeOptionWithValue;
453 ((SelectInterface *) clazz->interface)->selectOption = selectOption;
454 ((SelectInterface *) clazz->interface)->selectOptionWithValue = selectOptionWithValue;
455 ((SelectInterface *) clazz->interface)->selectedOption = selectedOption;
456 ((SelectInterface *) clazz->interface)->selectedOptions = selectedOptions;
457}
static void removeOption(Select *self, Option *option)
Definition Select.c:338
static void selectOptionWithValue(Select *self, ident value)
Definition Select.c:401
static void stateDidChange(Control *self)
Definition Select.c:193
static View * init(View *self)
Definition Select.c:54
static void removeOptionWithValue(Select *self, ident value)
Definition Select.c:362
static SDL_Size sizeThatFits(const View *self)
Definition Select.c:92
static void addOption(Select *self, const char *title, ident value)
Definition Select.c:253
static void removeAllOptions(Select *self)
Definition Select.c:330
static Array * selectedOptions(const Select *self)
Definition Select.c:427
static Option * optionWithValue(const Select *self, const ident value)
Definition Select.c:315
static void layoutSubviews(View *self)
Definition Select.c:61
Option * optionWithValue(const Select *self, ident value)
Definition Select.c:315
layoutSubviews(View *self)
Performs layout for this View's immediate subviews.
Definition Box.c:74

◆ initWithFrame()

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

Definition at line 285 of file Select.c.

285 {
286
287 self = (Select *) super(Control, self, initWithFrame, frame);
288 if (self) {
289
291
292 self->options = $$(Array, arrayWithCapacity, 8);
293 assert(self->options);
294
295 self->stackView = $(alloc(StackView), initWithFrame, NULL);
296 assert(self->stackView);
297
298 $((View *) self, addSubview, (View *) self->stackView);
299 }
300
301 return self;
302}
StackViews are containers that manage the arrangement of their subviews.
Definition StackView.h:68

◆ layoutSubviews()

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

Definition at line 61 of file Select.c.

61 {
62
63 Select *this = (Select *) self;
64
65 Control *control = (Control *) self;
66
67 if (control->selection == ControlSelectionSingle) {
68
69 const Array *options = (Array *) this->options;
70 for (size_t i = 0; i < options->count; i++) {
71
72 Option *option = $(options, objectAtIndex, i);
73 if (option->isSelected) {
74 option->view.hidden = false;
75 } else if ($(control, isHighlighted)) {
76 option->view.hidden = false;
77 } else {
78 option->view.hidden = true;
79 }
80 }
81
82 $((View *) this->stackView, sizeToFit);
83 $((View *) this->stackView, layoutIfNeeded);
84 }
85
86 super(View, self, layoutSubviews);
87}
static bool isHighlighted(const Control *self)
Definition Control.c:327
static void layoutIfNeeded(View *self)
Definition View.c:1115
static void sizeToFit(View *self)
Definition View.c:1767
bool isSelected
True if this Option is selected, false otherwise.
Definition Option.h:57
bool hidden
If true, this View is not drawn.
Definition View.h:196

◆ optionWithValue()

static Option * optionWithValue ( const Select self,
const ident  value 
)
static

Definition at line 315 of file Select.c.

315 {
316 return $((Array *) self->options, find, optionWithValue_predicate, value);
317}
static bool optionWithValue_predicate(ident obj, ident data)
Predicate function for optionWithValue.
Definition Select.c:307

◆ optionWithValue_predicate()

static bool optionWithValue_predicate ( ident  obj,
ident  data 
)
static

Predicate function for optionWithValue.

Definition at line 307 of file Select.c.

307 {
308 return ((Option *) obj)->value == data;
309}

◆ removeAllOptions()

static void removeAllOptions ( Select self)
static

Definition at line 330 of file Select.c.

330 {
331 $((Array *) self->options, enumerate, removeAllOptions_enumerate, self);
332}
static void removeAllOptions_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for removeAllOptions.
Definition Select.c:322

◆ removeAllOptions_enumerate()

static void removeAllOptions_enumerate ( const Array *  array,
ident  obj,
ident  data 
)
static

ArrayEnumerator for removeAllOptions.

Definition at line 322 of file Select.c.

322 {
323 $((Select *) data, removeOption, obj);
324}

◆ removeOption()

static void removeOption ( Select self,
Option option 
)
static

Definition at line 338 of file Select.c.

338 {
339
340 if ($((Array *) self->options, containsObject, option)) {
341
342 $(self->options, removeObject, option);
343 $((View *) self->stackView, removeSubview, (View *) option);
344
346 if ($(self, selectedOption) == NULL) {
347 Option *first_option = $((Array *) self->options, firstObject);
348 if (first_option) {
349 $(self, selectOption, first_option);
350 }
351 }
352 }
353
354 self->control.view.needsLayout = true;
355 }
356}

◆ removeOptionWithValue()

static void removeOptionWithValue ( Select self,
ident  value 
)
static

Definition at line 362 of file Select.c.

362 {
363
364 Option *option = (Option *) $(self, optionWithValue, value);
365 if (option) {
366 $(self, removeOption, option);
367 }
368}

◆ selectedOption()

static Option * selectedOption ( const Select self)
static

Definition at line 419 of file Select.c.

419 {
420 return $((Array *) self->options, find, selectedOptions_predicate, NULL);
421}
static bool selectedOptions_predicate(ident obj, ident data)
Predicate for selectedOption and selectedOptions.
Definition Select.c:411

◆ selectedOptions()

static Array * selectedOptions ( const Select self)
static

Definition at line 427 of file Select.c.

427 {
428 return $((Array *) self->options, filteredArray, selectedOptions_predicate, NULL);
429}

◆ selectedOptions_predicate()

static bool selectedOptions_predicate ( ident  obj,
ident  data 
)
static

Predicate for selectedOption and selectedOptions.

Definition at line 411 of file Select.c.

411 {
412 return ((Option *) obj)->isSelected;
413}

◆ selectOption()

static void selectOption ( Select self,
Option option 
)
static

Definition at line 381 of file Select.c.

381 {
382
384 $((Array *) self->options, enumerate, selectOption_enumerate, NULL);
385 }
386
387 if (option) {
388
389 if (option && option->isSelected == false) {
390 $(option, setSelected, true);
391 }
392 }
393
394 self->control.view.needsLayout = true;
395}
static void selectOption_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for enforcing ControlSelectionSingle.
Definition Select.c:373

◆ selectOption_enumerate()

static void selectOption_enumerate ( const Array *  array,
ident  obj,
ident  data 
)
static

ArrayEnumerator for enforcing ControlSelectionSingle.

Definition at line 373 of file Select.c.

373 {
374 $((Option *) obj, setSelected, false);
375}

◆ selectOptionWithValue()

static void selectOptionWithValue ( Select self,
ident  value 
)
static

Definition at line 401 of file Select.c.

401 {
402
403 Option *option = $(self, optionWithValue, value);
404
405 $(self, selectOption, option);
406}

◆ sizeThatFits()

static SDL_Size sizeThatFits ( const View self)
static
See also
View::sizeThatFits(const View *)

Definition at line 92 of file Select.c.

92 {
93
94 const Select *this = (Select *) self;
95
96 SDL_Size size = super(View, self, sizeThatFits);
97
98 const Array *options = (Array *) this->options;
99 for (size_t i = 0; i < options->count; i++) {
100
101 const View *option = $(options, objectAtIndex, i);
102 const SDL_Size optionSize = $(option, sizeThatFits);
103
104 size.w = max(size.w, optionSize.w + self->padding.left + self->padding.right);
105 size.h = max(size.h, optionSize.h + self->padding.top + self->padding.bottom);
106 }
107
108 return size;
109}
static SDL_Size size(const Image *self)
Definition Image.c:181
ViewPadding padding
The padding.
Definition View.h:234
int top
Definition View.h:101
int bottom
Definition View.h:101
int right
Definition View.h:101
int left
Definition View.h:101

◆ stateDidChange()

static void stateDidChange ( Control self)
static
See also
Control::stateDidChange(Control *)

Definition at line 193 of file Select.c.

193 {
194
195 Select *this = (Select *) self;
196
197 if (self->selection == ControlSelectionSingle) {
198
199 View *stackView = (View *) this->stackView;
200
201 if ($(self, isHighlighted)) {
202
203 const SDL_Rect renderFrame = $((View *) self, renderFrame);
204
205 stackView->frame.x = renderFrame.x + self->view.padding.left;
206 stackView->frame.y = renderFrame.y + self->view.padding.top;
207
208 View *view = (View *) self;
209
210 while (view->superview) {
211 view = view->superview;
212 }
213
214 $(stackView, addClassName, "options");
215 $(view, addSubview, stackView);
216
217 stackView->nextResponder = (View *) self;
218
219 } else {
220
221 $(stackView, removeClassName, "options");
222 $((View *) self, addSubview, stackView);
223
224 stackView->nextResponder = NULL;
225 }
226
227 $(stackView, sizeToFit);
228 }
229
230 super(Control, self, stateDidChange);
231}
static void removeClassName(View *self, const char *className)
Definition View.c:1344
static void addClassName(View *self, const char *className)
Definition View.c:159
static SDL_Rect renderFrame(const View *self)
Definition View.c:1455
View * superview
The super View.
Definition View.h:259
SDL_Rect frame
The frame, relative to the superview.
Definition View.h:191