28#include <Objectively/Hash.h>
29#include <Objectively/Array.h>
30#include <Objectively/Set.h>
36#define _Class _Selector
47 release(this->sequences);
60 return str(this->rule);
66static int hash(
const Object *self) {
70 return HashForCString(HASH_SEED, this->rule);
76static bool isEqual(
const Object *self,
const Object *other) {
78 if (super(Object, self,
isEqual, other)) {
82 if (other && $(other, isKindOfClass,
_Selector())) {
87 return strcmp(this->rule, that->
rule) == 0;
93#pragma mark - Selector
102 for (
size_t i = 0; i < selector->
sequences->count; i++) {
108 switch (simpleSelector->
type) {
118 Class *clazz = classForName(simpleSelector->
pattern);
121 if (clazz ==
_View()) {
125 clazz = clazz->def.superclass;
127 if (clazz !=
_View()) {
128 MVC_LogError(
"Class `%s` in Selector `%s` does not extend View\n",
132 MVC_LogWarn(
"Class `%s` in Selector `%s` not found\n",
156 return OrderAscending;
158 return OrderDescending;
172 Set *selection = $(self, select, view);
175 Array *array = $(selection, allObjects);
178 for (
size_t i = 0; i < array->count; i++) {
179 enumerator($(array, objectAtIndex, i), data);
195 self->
rule = strtrim(rule);
233 switch (sequence->
left) {
291static Array *
parse(
const char *rules) {
293 Array *selectors = $$(Array, arrayWithCapacity, 4);
298 const char *c = rules;
300 const size_t size = strcspn(c,
",");
302 char *rule = calloc(1,
size + 1);
305 strncpy(rule, c,
size);
310 $(selectors, addObject, selector);
316 c += strspn(c,
", \t\n");
320 return (Array *) selectors;
349 switch (sequence->
right) {
374 $(selection->
selection, addObject, view);
401 .selection = $$(Set, set),
423 switch (sequence->
right) {
448 selection->
first = view;
476 return selection.
first;
479#pragma mark - Class lifecycle
486 ((ObjectInterface *) clazz->interface)->dealloc =
dealloc;
487 ((ObjectInterface *) clazz->interface)->description =
description;
488 ((ObjectInterface *) clazz->interface)->hash =
hash;
489 ((ObjectInterface *) clazz->interface)->isEqual =
isEqual;
492 ((SelectorInterface *) clazz->interface)->compareTo =
compareTo;
493 ((SelectorInterface *) clazz->interface)->initWithRule =
initWithRule;
495 ((SelectorInterface *) clazz->interface)->parse =
parse;
496 ((SelectorInterface *) clazz->interface)->select =
_select;
497 ((SelectorInterface *) clazz->interface)->selectFirst =
selectFirst;
509 clazz = _initialize(&(
const ClassDef) {
511 .superclass = _Object(),
513 .interfaceOffset = offsetof(
Selector, interface),
514 .interfaceSize =
sizeof(SelectorInterface),
static View * init(View *self)
static SDL_Size size(const Image *self)
View logging facilities via SDL_Log.
#define MVC_LogWarn(fmt,...)
#define MVC_LogError(fmt,...)
static bool _matchesView(const View *view, Match *match)
Recursive View match predicate, invoked directly by matchesView and indirectly, via _matchesViewEnume...
static void enumerateSelection(const Selector *self, View *view, ViewEnumerator enumerator, ident data)
static bool isEqual(const Object *self, const Object *other)
static Selector * initWithRule(Selector *self, const char *rule)
static Set * _select(const Selector *self, View *view)
static int specificity(const Selector *selector)
static Order compareTo(const Selector *self, const Selector *other)
static void _matchesViewEnumerator(View *view, ident data)
ViewEnumerator adapter for _matchesView, so it may be passed to the View::enumerate* family of method...
static Array * parse(const char *rules)
static String * description(const Object *self)
static void __selectEnumerator(View *view, ident data)
ViewEnumerator adapter for __select, so it may be passed to the View::enumerate* family of methods,...
static void _selectFirstEnumerator(View *view, ident data)
ViewEnumerator adapter for _selectFirst, so it may be passed to the View::enumerate* family of method...
static void _selectFirst(Selection *selection, View *view)
Recursively selects the first View by iterating the SelectorSequences in the given Selection.
static void dealloc(Object *self)
static Set * __select(View *view, Selection *selection)
Recursively selects Views by iterating the SelectorSequences in the given Selection.
static View * selectFirst(const Selector *self, View *view)
static void initialize(Class *clazz)
static bool matchesView(const Selector *self, const View *view)
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.
static void enumerateAncestors(const View *self, ViewEnumerator enumerator, ident data)
static void enumerateSubviews(const View *self, ViewEnumerator enumerator, ident data)
static void enumerateSuperview(const View *self, ViewEnumerator enumerator, ident data)
static void enumerateAdjacent(const View *self, ViewEnumerator enumerator, ident data)
static void enumerateSiblings(const View *self, ViewEnumerator enumerator, ident data)
static void enumerateDescendants(const View *self, ViewEnumerator enumerator, ident data)
Views are the fundamental building blocks of ObjectivelyMVC user interfaces.
A context for View matching.
A context for View selection.
Selectors are comprised of one or more SelectorSequences.
int specificity
The specificity.
char * rule
The rule, as provided by the user.
bool matchesView(const Selector *self, View *view)
Array * sequences
The sequences.
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 enumerateSelection(View *self, const char *rule, ViewEnumerator enumerator, ident data)
Enumerates all Views in the selection matched by rule, applying enumerator to each.