27#include <Objectively/Hash.h>
28#include <Objectively/MutableArray.h>
29#include <Objectively/MutableSet.h>
35#define _Class _Selector
46 release(this->sequences);
59 return str(this->rule);
65static int hash(
const Object *self) {
69 return HashForCString(HASH_SEED, this->rule);
75static _Bool
isEqual(
const Object *self,
const Object *other) {
77 if (super(Object, self,
isEqual, other)) {
81 if (other && $(other, isKindOfClass,
_Selector())) {
86 return strcmp(this->rule, that->
rule) == 0;
92#pragma mark - Selector
101 for (
size_t i = 0; i < selector->
sequences->count; i++) {
107 switch (simpleSelector->
type) {
117 Class *clazz = classForName(simpleSelector->
pattern);
120 if (clazz ==
_View()) {
124 clazz = clazz->def.superclass;
126 if (clazz !=
_View()) {
127 MVC_LogError(
"Class `%s` in Selector `%s` does not extend View\n",
131 MVC_LogWarn(
"Class `%s` in Selector `%s` not found\n",
154 return OrderAscending;
156 return OrderDescending;
170 Set *selection = $(self,
select, view);
173 Array *array = $(selection, allObjects);
176 for (
size_t i = 0; i < array->count; i++) {
177 enumerator($(array, objectAtIndex, i), data);
193 self->
rule = strtrim(rule);
223 switch (sequence->
left) {
274static Array *
parse(
const char *rules) {
276 MutableArray *selectors = $$(MutableArray, arrayWithCapacity, 4);
281 const char *c = rules;
283 const size_t size = strcspn(c,
",");
285 char *rule = calloc(1,
size + 1);
288 strncpy(rule, c,
size);
293 $(selectors, addObject, selector);
299 c += strspn(c,
", \t\n");
303 return (Array *) selectors;
324 switch (sequence->
right) {
349 $(selection->
selection, addObject, view);
370 .selection = $$(MutableSet, set)
374#pragma mark - Class lifecycle
381 ((ObjectInterface *) clazz->interface)->dealloc =
dealloc;
382 ((ObjectInterface *) clazz->interface)->description =
description;
383 ((ObjectInterface *) clazz->interface)->hash =
hash;
384 ((ObjectInterface *) clazz->interface)->isEqual =
isEqual;
387 ((SelectorInterface *) clazz->interface)->compareTo =
compareTo;
388 ((SelectorInterface *) clazz->interface)->initWithRule =
initWithRule;
390 ((SelectorInterface *) clazz->interface)->parse =
parse;
391 ((SelectorInterface *) clazz->interface)->select =
_select;
403 clazz = _initialize(&(
const ClassDef) {
405 .superclass = _Object(),
407 .interfaceOffset = offsetof(
Selector, interface),
408 .interfaceSize =
sizeof(SelectorInterface),
View logging facilities via SDL_Log.
#define MVC_LogWarn(fmt,...)
#define MVC_LogError(fmt,...)
static _Bool _matchesView(const View *view, Match *match)
ViewEnumerator for matchesView.
static Set * _select(const Selector *self, View *view)
static int specificity(const Selector *selector)
static String * description(const Object *self)
static _Bool isEqual(const Object *self, const Object *other)
static void dealloc(Object *self)
static Set * __select(View *view, Selection *selection)
Recursively selects Views by iterating the SelectorSequences in the given Selection.
static void initialize(Class *clazz)
static int hash(const Object *self)
@ SequenceCombinatorTerminal
@ SequenceCombinatorAdjacent
@ SequenceCombinatorChild
@ SequenceCombinatorDescendent
@ SequenceCombinatorSibling
@ SimpleSelectorTypePseudo
@ SimpleSelectorTypeClass
void(* ViewEnumerator)(View *view, ident data)
A function type for View enumeration.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
CollectionView * init(CollectionView *self, const SDL_Rect *frame)
Initializes this CollectionView with the specified frame and style.
SDL_Size size(const Image *self)
A context for View matching.
A context for View selection.
Selectors are comprised of one or more SelectorSequences.
Selector * initWithRule(Selector *self, const char *rule)
Initializes this Selector with the given rule.
Order compareTo(const Selector *self, const Selector *other)
Compares this Selector to other, ordering by specificity.
Class * _Selector(void)
The Selector archetype.
int specificity
The specificity.
_Bool matchesView(const Selector *self, View *view)
void enumerateSelection(const Selector *self, View *view, ViewEnumerator enumerator, ident data)
Selects from view and applies the given ViewEnumerator to all matched Views.
Array * select(const Selector *self, View *view)
char * rule
The rule, as provided by the user.
Array * sequences
The sequences.
Array * parse(const char *rules)
Parses the null-terminated C string of Selector rules into an Array of Selectors.
SelectorSequences are comprised of one or more SimpleSelectors.
SequenceCombinator left
The combinators.
Array * simpleSelectors
The SimpleSelectors comprising this SelectorSequence.
SimpleSelectorType type
The SimpleSelectorType.
char * pattern
The pattern, as provided by the user.
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
void enumerateSuperview(const View *self, ViewEnumerator enumerator, ident data)
Enumerates the superview of this View, if any, applying enumerator to it.
Class * _View(void)
The View archetype.
void enumerateAncestors(const View *self, ViewEnumerator enumerator, ident data)
Enumerates all ancestors of this View, applying enumerator to each.
void enumerateSiblings(const View *self, ViewEnumerator enumerator, ident data)
Enumerates all siblings of this View, applying enumerator to each.
void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
Enumerates all descendants of this View, applying enumerator to each.
void enumerateAdjacent(const View *self, ViewEnumerator enumerator, ident data)
Enumerates adjacent siblings of this View, applying enumerator to each.
void enumerateSubviews(const View *self, ViewEnumerator enumerator, ident data)
Enumerates all subviews of this View, applying enumerator to each.