26#include <Objectively/Array.h>
41 memset(&this->delegate, 0,
sizeof(this->delegate));
43 release(this->options);
44 release(this->stackView);
69 const Array *options = (Array *) this->options;
70 for (
size_t i = 0; i < options->count; i++) {
72 Option *option = $(options, objectAtIndex, i);
91 View *menu = (
View *) this->stackView;
95 SDL_GetWindowSize(menu->
window, NULL, &windowHeight);
97 const int bottom = menu->
frame.y + menu->
frame.h;
98 if (bottom > windowHeight) {
99 menu->
frame.y -= (bottom - windowHeight);
100 if (menu->
frame.y < 0) {
119 const Array *options = (Array *) this->options;
120 for (
size_t i = 0; i < options->count; i++) {
122 const View *option = $(options, objectAtIndex, i);
132#pragma mark - Control
141 const Array *options = (Array *) this->options;
143 if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
150 if (event->type == SDL_EVENT_MOUSE_BUTTON_UP) {
152 self->
state &= ~ControlStateHighlighted;
154 for (
size_t i = 0; i < options->count; i++) {
156 Option *option = $(options, objectAtIndex, i);
159 if (this->delegate.didSelectOption) {
160 this->delegate.didSelectOption(
this, option);
171 if (event->type == SDL_EVENT_KEY_DOWN) {
173 switch (event->key.key) {
176 self->
state &= ~ControlStateHighlighted;
189 ssize_t index = $(options, indexOfObject, option);
190 if (event->key.key == SDLK_UP) {
191 index = (index - 1 + options->count) % options->count;
193 index = (index + 1) % options->count;
196 option = $(options, objectAtIndex, index);
199 if (this->delegate.didSelectOption) {
200 this->delegate.didSelectOption(
this, option);
220 View *stackView = (
View *) this->stackView;
279 $(self->
options, addObject, option);
313 self->
options = $$(Array, arrayWithCapacity, 8);
329 return ((
Option *) obj)->value == data;
361 if ($((Array *) self->
options, containsObject, option)) {
363 $(self->
options, removeObject, option);
368 Option *first_option = $((Array *) self->
options, firstObject);
433 return ((
Option *) obj)->isSelected;
452#pragma mark - Class lifecycle
459 ((ObjectInterface *) clazz->interface)->dealloc =
dealloc;
461 ((ViewInterface *) clazz->interface)->init =
init;
463 ((ViewInterface *) clazz->interface)->sizeThatFits =
sizeThatFits;
465 ((ControlInterface *) clazz->interface)->captureEvent =
captureEvent;
466 ((ControlInterface *) clazz->interface)->stateDidChange =
stateDidChange;
468 ((SelectInterface *) clazz->interface)->addOption =
addOption;
469 ((SelectInterface *) clazz->interface)->initWithFrame =
initWithFrame;
471 ((SelectInterface *) clazz->interface)->removeAllOptions =
removeAllOptions;
472 ((SelectInterface *) clazz->interface)->removeOption =
removeOption;
474 ((SelectInterface *) clazz->interface)->selectOption =
selectOption;
476 ((SelectInterface *) clazz->interface)->selectedOption =
selectedOption;
477 ((SelectInterface *) clazz->interface)->selectedOptions =
selectedOptions;
489 clazz = _initialize(&(
const ClassDef) {
492 .instanceSize =
sizeof(
Select),
493 .interfaceOffset = offsetof(
Select, interface),
494 .interfaceSize =
sizeof(SelectInterface),
static void setSelected(CollectionItemView *self, bool isSelected)
static bool isHighlighted(const Control *self)
@ ControlStateHighlighted
static SDL_Size size(const Image *self)
static void removeSubview(View *self, View *subview)
static void addSubview(View *self, View *subview)
static void removeOption(Select *self, Option *option)
static void selectOption(Select *self, Option *option)
static void removeAllOptions_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for removeAllOptions.
static Option * selectedOption(const Select *self)
static void selectOptionWithValue(Select *self, ident value)
static void stateDidChange(Control *self)
static View * init(View *self)
static void selectOption_enumerate(const Array *array, ident obj, ident data)
ArrayEnumerator for enforcing ControlSelectionSingle.
static void addOption_removeSubview(const Array *array, ident obj, ident data)
ArrayEnumerator to remove Options from the stackView.
static void removeOptionWithValue(Select *self, ident value)
static SDL_Size sizeThatFits(const View *self)
static bool captureEvent(Control *self, const SDL_Event *event)
static void addOption(Select *self, const char *title, ident value)
static void removeAllOptions(Select *self)
static Array * selectedOptions(const Select *self)
static bool selectedOptions_predicate(ident obj, ident data)
Predicate for selectedOption and selectedOptions.
static void dealloc(Object *self)
static void addOption_addSubview(const Array *array, ident obj, ident data)
ArrayEnumerator to add Options to the stackView.
static Select * initWithFrame(Select *self, const SDL_Rect *frame)
static void initialize(Class *clazz)
static Option * optionWithValue(const Select *self, const ident value)
static void layoutSubviews(View *self)
static bool optionWithValue_predicate(ident obj, ident data)
Predicate function for optionWithValue.
A Control allowing users to select one or more Options.
static void removeClassName(View *self, const char *className)
static void addClassName(View *self, const char *className)
static void layoutIfNeeded(View *self)
static void becomeTouchResponder(View *self)
static bool didReceiveEvent(const View *self, const SDL_Event *event)
static SDL_Rect renderFrame(const View *self)
static void enumerate(View *self, ViewEnumerator enumerator, ident data)
static void sizeToFit(View *self)
Controls are Views which capture and respond to events.
unsigned int state
The bit mask of ControlState.
ControlSelection selection
The ControlSelection.
bool isSelected
True if this Option is selected, false otherwise.
A Control allowing users to select one or more Options.
Comparator comparator
An optional Comparator to sort Options.
Array * options
The Options.
StackView * stackView
The StackView for rendering the Options.
Option * optionWithValue(const Select *self, ident value)
Control control
The superclass.
StackViews are containers that manage the arrangement of their subviews.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
View * superview
The super View.
SDL_Window * window
The window.
View * nextResponder
The next responder, or event handler, in the chain.
bool needsLayout
If true, this View will layout its subviews before it is drawn.
ViewPadding padding
The padding.
layoutSubviews(View *self)
Performs layout for this View's immediate subviews.
SDL_Rect frame
The frame, relative to the superview.
bool hidden
If true, this View is not drawn.