2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include <NGObjWeb/WODisplayGroup.h>
23 #import <EOControl/EOControl.h>
24 #import <Foundation/Foundation.h>
25 #import <Foundation/NSNotification.h>
28 @interface EODataSource(DGQualifierSetting)
29 - (void)setAuxiliaryQualifier:(EOQualifier *)_q;
30 - (void)setQualifier:(EOQualifier *)_q;
31 - (void)setQualifierBindings:(NSDictionary *)_bindings;
34 #if APPLE_FOUNDATION_LIBRARY || NeXT_Foundation_LIBRARY
35 @interface NSObject(Miss)
36 - (void)notImplemented:(SEL)cmd;
40 @implementation WODisplayGroup
42 static NSNumber *uint0 = nil;
43 static NSArray *uint0Array = nil;
47 uint0 = [[NSNumber alloc] initWithUnsignedInt:0];
48 if (uint0Array == nil)
49 uint0Array = [[NSArray alloc] initWithObjects:&uint0 count:1];
53 if ((self = [super init])) {
54 [self setDefaultStringMatchFormat:
55 [[self class] globalDefaultStringMatchFormat]];
56 [self setDefaultStringMatchOperator:
57 [[self class] globalDefaultStringMatchOperator]];
58 self->currentBatchIndex = 1;
64 [[NSNotificationCenter defaultCenter] removeObserver:self];
65 [self setDataSource:nil];
67 RELEASE(self->_queryMatch);
68 RELEASE(self->_queryMin);
69 RELEASE(self->_queryMax);
70 RELEASE(self->_queryOperator);
71 RELEASE(self->_queryBindings);
72 RELEASE(self->defaultStringMatchFormat);
73 RELEASE(self->defaultStringMatchOperator);
74 RELEASE(self->qualifier);
75 RELEASE(self->objects);
76 RELEASE(self->displayObjects);
77 RELEASE(self->selectionIndexes);
78 RELEASE(self->sortOrderings);
79 RELEASE(self->insertedObjectDefaults);
85 - (void)_objectsChangedInEC:(NSNotification *)_notification {
90 if ((d = [self delegate])) {
91 if ([d respondsToSelector:
92 @selector(displayGroup:shouldRedisplayForChangesInEditingContext:)]) {
93 doRedisplay = [d displayGroup:self
94 shouldRedisplayForEditingContextChangeNotification:
106 /* contents changed notification ??? */
111 - (void)setDelegate:(id)_delegate {
112 self->delegate = _delegate;
115 return self->delegate;
118 - (void)setDataSource:(EODataSource *)_ds {
119 if (_ds != self->dataSource) {
121 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
125 if ((ec = [self->dataSource editingContext])) {
126 [ec removeEditor:self];
127 if ([ec messageHandler] == self)
128 [ec setMessageHandler:nil];
130 [nc removeObserver:self
131 name:@"EOObjectsChangedInEditingContext"
136 ASSIGN(self->dataSource, _ds);
139 if ((ec = [_ds editingContext])) {
141 if ([ec messageHandler] == nil)
142 [ec setMessageHandler:self];
145 selector:@selector(_objectsChangedInEC:)
146 name:@"EOObjectsChangedInEditingContext"
151 if ([self->delegate respondsToSelector:
152 @selector(displayGroupDidChangeDataSource:)])
153 [self->delegate displayGroupDidChangeDataSource:self];
156 - (EODataSource *)dataSource {
157 return self->dataSource;
160 - (void)setSortOrderings:(NSArray *)_orderings {
161 id tmp = self->sortOrderings;
162 self->sortOrderings = [_orderings copy];
165 - (NSArray *)sortOrderings {
166 return self->sortOrderings;
169 - (void)setFetchesOnLoad:(BOOL)_flag {
170 self->flags.fetchesOnLoad = _flag ? 1 : 0;
172 - (BOOL)fetchesOnLoad {
173 return self->flags.fetchesOnLoad ? YES : NO;
176 - (void)setInsertedObjectDefaultValues:(NSDictionary *)_values {
177 id tmp = self->insertedObjectDefaults;
178 self->insertedObjectDefaults = [_values copy];
181 - (NSDictionary *)insertedObjectDefaultValues {
182 return self->insertedObjectDefaults;
185 - (void)setNumberOfObjectsPerBatch:(unsigned)_count {
186 self->numberOfObjectsPerBatch = _count;
188 - (unsigned)numberOfObjectsPerBatch {
189 return self->numberOfObjectsPerBatch;
192 - (void)setSelectsFirstObjectAfterFetch:(BOOL)_flag {
193 self->flags.selectFirstAfterFetch = _flag ? 1 : 0;
195 - (BOOL)selectsFirstObjectAfterFetch {
196 return self->flags.selectFirstAfterFetch ? YES : NO;
199 - (void)setValidatesChangesImmediatly:(BOOL)_flag {
200 self->flags.validatesChangesImmediatly = _flag ? 1 : 0;
202 - (BOOL)validatesChangesImmediatly {
203 return self->flags.validatesChangesImmediatly ? YES : NO;
208 - (BOOL)hasMultipleBatches {
209 return [self batchCount] > 1 ? YES : NO;
211 - (unsigned)batchCount {
214 doc = [[self allObjects] count];
215 nob = [self numberOfObjectsPerBatch];
219 : doc / nob + ((doc % nob) ? 1 : 0) ;
222 - (void)setCurrentBatchIndex:(unsigned)_index {
223 self->currentBatchIndex = (_index <= [self batchCount]) ? _index : 1;
225 - (unsigned)currentBatchIndex {
226 if (self->currentBatchIndex > [self batchCount])
227 self->currentBatchIndex = 1;
228 return self->currentBatchIndex;
231 - (unsigned)indexOfFirstDisplayedObject {
232 return ([self currentBatchIndex] - 1) * [self numberOfObjectsPerBatch];
235 - (unsigned)indexOfLastDisplayedObject {
236 unsigned nob = [self numberOfObjectsPerBatch];
237 unsigned cnt = [[self allObjects] count];
242 return (([self indexOfFirstDisplayedObject] + nob) < cnt)
243 ? ([self indexOfFirstDisplayedObject] + nob) - 1
247 - (id)displayNextBatch {
248 [self clearSelection];
250 self->currentBatchIndex++;
251 if (self->currentBatchIndex > [self batchCount])
252 self->currentBatchIndex = 1;
254 [self updateDisplayedObjects];
258 - (id)displayPreviousBatch {
259 [self clearSelection];
261 self->currentBatchIndex--;
262 if ([self currentBatchIndex] <= 0)
263 self->currentBatchIndex = [self batchCount];
265 [self updateDisplayedObjects];
269 - (id)displayBatchContainingSelectedObject {
270 [self warnWithFormat:@"%s not implemenented", __PRETTY_FUNCTION__];
271 [self updateDisplayedObjects];
277 - (BOOL)setSelectionIndexes:(NSArray *)_selection {
280 NSSet *before, *after;
283 if ((d = [self delegate])) {
284 if ([d respondsToSelector:
285 @selector(displayGroup:shouldChangeSelectionToIndexes:)]) {
286 ok = [d displayGroup:self shouldChangeSelectionToIndexes:_selection];
292 /* apply selection */
294 before = [NSSet setWithArray:self->selectionIndexes];
295 after = [NSSet setWithArray:_selection];
297 ASSIGN(self->selectionIndexes, _selection);
299 if (![before isEqual:after]) {
300 [d displayGroupDidChangeSelection:self];
301 [d displayGroupDidChangeSelectedObjects:self];
305 - (NSArray *)selectionIndexes {
306 return self->selectionIndexes;
309 - (BOOL)clearSelection {
310 static NSArray *emptyArray = nil;
311 if (emptyArray == nil) emptyArray = [[NSArray alloc] init];
312 return [self setSelectionIndexes:emptyArray];
318 if ([self->displayObjects count] == 0)
321 if ([self->selectionIndexes count] == 0) {
322 [self setSelectionIndexes:uint0Array];
326 idx = [[self->selectionIndexes lastObject] unsignedIntValue];
327 if (idx >= ([self->displayObjects count] - 1)) {
328 /* last object is already selected, select first one */
329 [self setSelectionIndexes:uint0Array];
333 /* select next object .. */
334 [self setSelectionIndexes:
335 [NSArray arrayWithObject:[NSNumber numberWithUnsignedInt:(idx + 1)]]];
339 - (id)selectPrevious {
342 if ([self->displayObjects count] == 0)
345 if ([self->selectionIndexes count] == 0) {
346 [self setSelectionIndexes:uint0Array];
350 idx = [[self->selectionIndexes objectAtIndex:0] unsignedIntValue];
352 /* first object is selected, now select last one */
354 sidx = [NSNumber numberWithUnsignedInt:([self->displayObjects count] - 1)];
355 [self setSelectionIndexes:[NSArray arrayWithObject:sidx]];
358 /* select previous object .. */
359 [self setSelectionIndexes:
360 [NSArray arrayWithObject:[NSNumber numberWithUnsignedInt:(idx - 1)]]];
364 - (void)setSelectedObject:(id)_obj {
365 [self warnWithFormat:@"%s not implemented.", __PRETTY_FUNCTION__];
367 - (id)selectedObject {
371 - (void)setSelectedObjects:(NSArray *)_objs {
372 [self selectObjectsIdenticalTo:_objs];
373 // [self warnWithFormat:@"%s not implemented.", __PRETTY_FUNCTION__];
375 - (NSArray *)selectedObjects {
376 NSMutableArray *result;
377 unsigned int i, sCount, oCount;
379 sCount = [self->selectionIndexes count];
380 oCount = [self->objects count];
381 result = [NSMutableArray arrayWithCapacity:sCount];
383 for (i=0; i<sCount; i++) {
386 idx = [[self->selectionIndexes objectAtIndex:i] unsignedIntValue];
388 [result addObject:[self->objects objectAtIndex:idx]];
393 /* returns YES if displayedObjects contains _obj otherwise NO */
394 - (BOOL)selectObject:(id)_obj {
398 if (![self->displayObjects containsObject:_obj])
401 idx = [self->displayObjects indexOfObject:_obj];
402 idxNumber = [NSNumber numberWithUnsignedInt:idx];
404 if ([self->selectionIndexes containsObject:idxNumber])
409 tmp = [NSMutableArray arrayWithObjects:self->selectionIndexes];
410 [tmp addObject:idxNumber];
411 [self setSelectionIndexes:tmp];
417 /* returns YES if at least one obj matches otherwise NO */
418 - (BOOL)selectObjectsIdenticalTo:(NSArray *)_objs {
419 NSMutableArray *newIndexes;
428 newIndexes = [NSMutableArray arrayWithCapacity:cnt];
430 for (i=0; i<cnt; i++) {
435 obj = [_objs objectAtIndex:i];
436 if (![self->objects containsObject:obj])
440 idx = [self->objects indexOfObject:obj];
441 idxNumber = [NSNumber numberWithUnsignedInt:idx];
443 if ([self->selectionIndexes containsObject:idxNumber])
446 [newIndexes addObject:idxNumber];
451 [newIndexes addObjectsFromArray:self->selectionIndexes];
452 [self setSelectionIndexes:newIndexes];
457 - (BOOL)selectObjectsIdenticalTo:(NSArray *)_objs
458 selectFirstOnNoMatch:(BOOL)_flag
460 if ([self selectObjectsIdenticalTo:_objs])
464 return [self selectObject:[self->displayObjects objectAtIndex:0]];
471 - (void)setObjectArray:(NSArray *)_objects {
472 ASSIGN(self->objects, _objects);
474 /* should try to restore selection */
475 [self clearSelection];
476 if ([_objects count] > 0 && [self selectsFirstObjectAfterFetch]) {
477 [self setSelectionIndexes:uint0Array];
481 - (NSArray *)allObjects {
482 return self->objects;
485 - (NSArray *)displayedObjects {
486 return self->displayObjects;
492 if ([self->delegate respondsToSelector:@selector(displayGroupShouldFetch:)]) {
493 if (![self->delegate displayGroupShouldFetch:self])
494 /* delegate rejected fetch-request */
498 objs = [[self dataSource] fetchObjects];
500 [self setObjectArray:objs];
502 if ([self->delegate respondsToSelector:
503 @selector(displayGroup:didFetchObjects:)]) {
504 [self->delegate displayGroup:self didFetchObjects:objs];
507 [self updateDisplayedObjects];
509 if ([self selectsFirstObjectAfterFetch]) {
510 [self clearSelection];
512 if ([objs count] > 0)
513 [self setSelectedObject:[objs objectAtIndex:0]];
517 - (void)updateDisplayedObjects {
518 NSArray *darray; // display objects
519 NSArray *sarray; // selected objects
521 sarray = [self selectedObjects];
523 if ([self->delegate respondsToSelector:
524 @selector(displayGroup:displayArrayForObjects:)]) {
525 darray = [self->delegate displayGroup:self
526 displayArrayForObjects:[self allObjects]];
528 darray = [darray copy];
529 RELEASE(self->displayObjects);
530 self->displayObjects = darray;
538 ao = [self allObjects];
540 /* apply qualifier */
542 if ((q = [self qualifier]))
543 ao = [ao filteredArrayUsingQualifier:q];
544 #endif // should be done in qualifyDisplayGroup
546 /* apply sort orderings */
547 if ((so = [self sortOrderings]))
548 ao = [ao sortedArrayUsingKeyOrderArray:so];
550 if (ao != self->objects)
551 [self setObjectArray:ao];
556 if ([self batchCount] > 1) {
557 unsigned first = [self indexOfFirstDisplayedObject];
558 unsigned last = [self indexOfLastDisplayedObject];
560 darray = [darray subarrayWithRange:NSMakeRange(first, last-first+1)];
564 darray = [darray copy];
565 RELEASE(self->displayObjects);
566 self->displayObjects = darray;
568 [self selectObjectsIdenticalTo:sarray];
573 - (void)setInQueryMode:(BOOL)_flag {
574 self->flags.inQueryMode = _flag ? 1 : 0;
576 - (BOOL)inQueryMode {
577 return self->flags.inQueryMode ? YES : NO;
580 - (EOQualifier *)qualifierFromQueryValues {
581 NSMutableDictionary *qm, *qmin, *qmax, *qop;
582 NSMutableArray *quals;
586 qm = [self queryMatch];
587 qmin = [self queryMin];
588 qmax = [self queryMax];
589 qop = [self queryOperator];
591 quals = [NSMutableArray arrayWithCapacity:[qm count]];
593 /* construct qualifier for all query-match entries */
595 keys = [qm keyEnumerator];
596 while ((key = [keys nextObject])) {
602 value = [qm objectForKey:key];
604 if ((op = [qop objectForKey:key]) == nil) {
605 /* default operator is equality */
607 ops = EOQualifierOperatorEqual;
609 else if ([value isKindOfClass:[NSString class]]) {
610 /* strings are treated in a special way */
613 fmt = [self defaultStringMatchFormat];
614 op = [self defaultStringMatchOperator];
615 ops = [EOQualifier operatorSelectorForString:op];
617 value = [NSString stringWithFormat:fmt, value];
620 ops = [EOQualifier operatorSelectorForString:op];
623 q = [[EOKeyValueQualifier alloc]
631 /* construct min qualifiers */
633 keys = [qmin keyEnumerator];
634 while ((key = [keys nextObject])) {
638 value = [qmin objectForKey:key];
640 q = [[EOKeyValueQualifier alloc]
642 operatorSelector:EOQualifierOperatorGreaterThan
648 /* construct max qualifiers */
650 keys = [qmax keyEnumerator];
651 while ((key = [keys nextObject])) {
655 value = [qmin objectForKey:key];
657 q = [[EOKeyValueQualifier alloc]
659 operatorSelector:EOQualifierOperatorLessThan
665 if ([quals count] == 0)
667 else if ([quals count] == 1)
668 return [quals objectAtIndex:0];
670 return AUTORELEASE([[EOAndQualifier alloc] initWithQualifierArray:quals]);
673 - (NSMutableDictionary *)queryBindings {
674 if (self->_queryBindings == nil)
675 self->_queryBindings = [[NSMutableDictionary alloc] init];
676 return self->_queryBindings;
678 - (NSMutableDictionary *)queryMatch {
679 if (self->_queryMatch == nil)
680 self->_queryMatch = [[NSMutableDictionary alloc] init];
681 return self->_queryMatch;
683 - (NSMutableDictionary *)queryMin {
684 if (self->_queryMin == nil)
685 self->_queryMin = [[NSMutableDictionary alloc] init];
686 return self->_queryMin;
688 - (NSMutableDictionary *)queryMax {
689 if (self->_queryMax == nil)
690 self->_queryMax = [[NSMutableDictionary alloc] init];
691 return self->_queryMax;
693 - (NSMutableDictionary *)queryOperator {
694 if (self->_queryOperator == nil)
695 self->_queryOperator = [[NSMutableDictionary alloc] init];
696 return self->_queryOperator;
699 - (void)setDefaultStringMatchFormat:(NSString *)_tmp {
700 ASSIGN(self->defaultStringMatchFormat, _tmp);
702 - (NSString *)defaultStringMatchFormat {
703 return self->defaultStringMatchFormat;
705 - (void)setDefaultStringMatchOperator:(NSString *)_tmp {
706 ASSIGN(self->defaultStringMatchOperator, _tmp);
708 - (NSString *)defaultStringMatchOperator {
709 return self->defaultStringMatchOperator;
711 + (NSString *)globalDefaultStringMatchFormat {
714 + (NSString *)globalDefaultStringMatchOperator {
715 return @"caseInsensitiveLike";
721 - (void)setQualifier:(EOQualifier *)_q {
722 ASSIGN(self->qualifier, _q);
724 - (EOQualifier *)qualifier {
725 return self->qualifier;
728 - (NSArray *)allQualifierOperators {
729 static NSArray *quals = nil;
731 quals = [[NSArray alloc] initWithObjects:
732 @"=", @"!=", @"<", @"<=", @">", @">=",
733 @"like", @"caseInsensitiveLike", nil];
737 - (NSArray *)stringQualifierOperators {
738 static NSArray *quals = nil;
740 quals = [[NSArray alloc] initWithObjects:
750 - (NSArray *)relationalQualifierOperators {
751 static NSArray *quals = nil;
753 quals = [[NSArray alloc] initWithObjects:
754 @"=", @"!=", @"<", @"<=", @">", @">=", nil];
759 - (void)qualifyDisplayGroup {
762 if ((q = [self qualifierFromQueryValues]))
763 [self setQualifier:q];
765 [self updateDisplayedObjects];
767 if ([self inQueryMode])
768 [self setInQueryMode:NO];
771 - (void)qualifyDataSource {
775 ds = [self dataSource];
777 if ((q = [self qualifierFromQueryValues]))
778 [self setQualifier:q];
780 if ([ds respondsToSelector:@selector(setAuxiliaryQualifier:)])
781 [ds setAuxiliaryQualifier:[self qualifier]];
782 else if ([ds respondsToSelector:@selector(setQualifier:)])
783 [ds setQualifier:[self qualifier]];
785 /* could not qualify ds */
788 if ([ds respondsToSelector:@selector(setQualifierBindings:)])
789 [ds setQualifierBindings:[self queryBindings]];
793 if ([self inQueryMode])
794 [self setInQueryMode:NO];
799 - (void)takeValue:(id)_value forKeyPath:(NSString *)_keyPath {
800 if([_keyPath hasPrefix:@"queryMatch."]) {
801 [[self queryMatch] takeValue:_value
802 forKey:[_keyPath substringFromIndex:11]];
804 else if([_keyPath hasPrefix:@"queryMax."])
805 [[self queryMax] takeValue:_value forKey:[_keyPath substringFromIndex:9]];
806 else if([_keyPath hasPrefix:@"queryMin."])
807 [[self queryMin] takeValue:_value forKey:[_keyPath substringFromIndex:9]];
808 else if([_keyPath hasPrefix:@"queryOperator."]) {
809 [[self queryOperator] takeValue:_value
810 forKey:[_keyPath substringFromIndex:14]];
813 [super takeValue:_value forKeyPath:_keyPath];
815 - (id)valueForKeyPath:(NSString *)_keyPath {
816 if ([_keyPath hasPrefix:@"queryMatch."])
817 return [[self queryMatch] valueForKey:[_keyPath substringFromIndex:11]];
818 if ([_keyPath hasPrefix:@"queryMax."])
819 return [[self queryMax] valueForKey:[_keyPath substringFromIndex:9]];
820 if ([_keyPath hasPrefix:@"queryMin."])
821 return [[self queryMin] valueForKey:[_keyPath substringFromIndex:9]];
822 if ([_keyPath hasPrefix:@"queryOperator."])
823 return [[self queryOperator] valueForKey:[_keyPath substringFromIndex:14]];
825 return [super valueForKeyPath:_keyPath];
830 - (id)initWithCoder:(NSCoder *)_coder {
831 self->dataSource = [[_coder decodeObject] retain];
832 self->delegate = [_coder decodeObject];
833 self->sortOrderings = [[_coder decodeObject] copy];
834 self->insertedObjectDefaults = [[_coder decodeObject] copy];
835 self->qualifier = [[_coder decodeObject] copy];
836 self->defaultStringMatchFormat = [[_coder decodeObject] copy];
837 self->defaultStringMatchOperator = [[_coder decodeObject] copy];
838 self->_queryBindings = [[_coder decodeObject] copy];
839 self->_queryMatch = [[_coder decodeObject] copy];
840 self->_queryMin = [[_coder decodeObject] copy];
841 self->_queryMax = [[_coder decodeObject] copy];
842 self->_queryOperator = [[_coder decodeObject] copy];
847 - (void)encodeWithCoder:(NSCoder *)_coder {
848 [_coder encodeObject:self->dataSource];
849 [_coder encodeObject:self->delegate];
850 [_coder encodeObject:self->sortOrderings];
851 [_coder encodeObject:self->insertedObjectDefaults];
852 [_coder encodeObject:self->qualifier];
853 [_coder encodeObject:self->defaultStringMatchFormat];
854 [_coder encodeObject:self->defaultStringMatchOperator];
855 [_coder encodeObject:self->_queryBindings];
856 [_coder encodeObject:self->_queryMatch];
857 [_coder encodeObject:self->_queryMin];
858 [_coder encodeObject:self->_queryMax];
859 [_coder encodeObject:self->_queryOperator];
861 [self notImplemented:_cmd];
866 - (NSString *)description {
867 return [NSString stringWithFormat:@"<0x%08X %@: ds=%@>",
868 self, NSStringFromClass([self class]),
872 @end /* WODisplayGroup */
874 @implementation WODisplayGroup(KVCArchiving)
876 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
877 if ((self = [self init])) {
880 if ((tmp = [_unarchiver decodeObjectForKey:@"formatForLikeQualifier"]))
881 [self setDefaultStringMatchFormat:tmp];
883 if ((tmp = [_unarchiver decodeObjectForKey:@"dataSource"]))
884 [self setDataSource:tmp];
886 if ((tmp = [_unarchiver decodeObjectForKey:@"numberOfObjectsPerBatch"]))
887 [self setNumberOfObjectsPerBatch:[tmp intValue]];
889 [self setFetchesOnLoad:[_unarchiver decodeBoolForKey:@"fetchesOnLoad"]];
890 [self setSelectsFirstObjectAfterFetch:
891 [_unarchiver decodeBoolForKey:@"selectsFirstObjectAfterFetch"]];
896 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
897 [_archiver encodeObject:[self defaultStringMatchFormat]
898 forKey:@"formatForLikeQualifier"];
899 [_archiver encodeObject:[self dataSource]
900 forKey:@"dataSource"];
901 [_archiver encodeObject:
902 [NSNumber numberWithUnsignedInt:[self numberOfObjectsPerBatch]]
903 forKey:@"numberOfObjectsPerBatch"];
904 [_archiver encodeBool:[self fetchesOnLoad]
905 forKey:@"fetchesOnLoad"];
906 [_archiver encodeBool:[self selectsFirstObjectAfterFetch]
907 forKey:@"selectFirstAfterFetch"];
910 @end /* KVCArchiving */
912 @implementation WODisplayGroup(EOEditorsImpl)
916 - (void)editingContextWillSaveChanges:(id)_ec {
918 - (BOOL)editorHasChangesForEditingContext:(id)_ec {
924 @end /* WODisplayGroup(EOEditorsImpl) */
926 @implementation WODisplayGroup(EOMessageHandlersImpl)
930 - (void)editingContext:(id)_ec
931 presentErrorMessage:(NSString *)_msg
935 - (BOOL)editingContext:(id)_ec
936 shouldContinueFetchingWithCurrentObjectCount:(unsigned)_oc
937 originalLimit:(unsigned)_olimit
938 objectStore:(EOObjectStore *)_store
945 @end /* WODisplayGroup(EOMessageHandlersImpl) */