2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo 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 OGo 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 OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include <NGObjWeb/WODisplayGroup.h>
24 #import <EOControl/EOControl.h>
25 #import <Foundation/Foundation.h>
26 #import <Foundation/NSNotification.h>
29 @interface EODataSource(DGQualifierSetting)
30 - (void)setAuxiliaryQualifier:(EOQualifier *)_q;
31 - (void)setQualifier:(EOQualifier *)_q;
32 - (void)setQualifierBindings:(NSDictionary *)_bindings;
35 #if APPLE_FOUNDATION_LIBRARY || NeXT_Foundation_LIBRARY
36 @interface NSObject(Miss)
37 - (void)notImplemented:(SEL)cmd;
41 @implementation WODisplayGroup
43 static NSNumber *uint0 = nil;
44 static NSArray *uint0Array = nil;
48 uint0 = [[NSNumber alloc] initWithUnsignedInt:0];
49 if (uint0Array == nil)
50 uint0Array = [[NSArray alloc] initWithObjects:&uint0 count:1];
54 if ((self = [super init])) {
55 [self setDefaultStringMatchFormat:
56 [[self class] globalDefaultStringMatchFormat]];
57 [self setDefaultStringMatchOperator:
58 [[self class] globalDefaultStringMatchOperator]];
59 self->currentBatchIndex = 1;
65 [[NSNotificationCenter defaultCenter] removeObserver:self];
66 [self setDataSource:nil];
68 RELEASE(self->_queryMatch);
69 RELEASE(self->_queryMin);
70 RELEASE(self->_queryMax);
71 RELEASE(self->_queryOperator);
72 RELEASE(self->_queryBindings);
73 RELEASE(self->defaultStringMatchFormat);
74 RELEASE(self->defaultStringMatchOperator);
75 RELEASE(self->qualifier);
76 RELEASE(self->objects);
77 RELEASE(self->displayObjects);
78 RELEASE(self->selectionIndexes);
79 RELEASE(self->sortOrderings);
80 RELEASE(self->insertedObjectDefaults);
86 - (void)_objectsChangedInEC:(NSNotification *)_notification {
91 if ((d = [self delegate])) {
92 if ([d respondsToSelector:
93 @selector(displayGroup:shouldRedisplayForChangesInEditingContext:)]) {
94 doRedisplay = [d displayGroup:self
95 shouldRedisplayForEditingContextChangeNotification:
107 /* contents changed notification ??? */
112 - (void)setDelegate:(id)_delegate {
113 self->delegate = _delegate;
116 return self->delegate;
119 - (void)setDataSource:(EODataSource *)_ds {
120 if (_ds != self->dataSource) {
122 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
126 if ((ec = [self->dataSource editingContext])) {
127 [ec removeEditor:self];
128 if ([ec messageHandler] == self)
129 [ec setMessageHandler:nil];
131 [nc removeObserver:self
132 name:@"EOObjectsChangedInEditingContext"
137 ASSIGN(self->dataSource, _ds);
140 if ((ec = [_ds editingContext])) {
142 if ([ec messageHandler] == nil)
143 [ec setMessageHandler:self];
146 selector:@selector(_objectsChangedInEC:)
147 name:@"EOObjectsChangedInEditingContext"
152 if ([self->delegate respondsToSelector:
153 @selector(displayGroupDidChangeDataSource:)])
154 [self->delegate displayGroupDidChangeDataSource:self];
157 - (EODataSource *)dataSource {
158 return self->dataSource;
161 - (void)setSortOrderings:(NSArray *)_orderings {
162 id tmp = self->sortOrderings;
163 self->sortOrderings = [_orderings copy];
166 - (NSArray *)sortOrderings {
167 return self->sortOrderings;
170 - (void)setFetchesOnLoad:(BOOL)_flag {
171 self->flags.fetchesOnLoad = _flag ? 1 : 0;
173 - (BOOL)fetchesOnLoad {
174 return self->flags.fetchesOnLoad ? YES : NO;
177 - (void)setInsertedObjectDefaultValues:(NSDictionary *)_values {
178 id tmp = self->insertedObjectDefaults;
179 self->insertedObjectDefaults = [_values copy];
182 - (NSDictionary *)insertedObjectDefaultValues {
183 return self->insertedObjectDefaults;
186 - (void)setNumberOfObjectsPerBatch:(unsigned)_count {
187 self->numberOfObjectsPerBatch = _count;
189 - (unsigned)numberOfObjectsPerBatch {
190 return self->numberOfObjectsPerBatch;
193 - (void)setSelectsFirstObjectAfterFetch:(BOOL)_flag {
194 self->flags.selectFirstAfterFetch = _flag ? 1 : 0;
196 - (BOOL)selectsFirstObjectAfterFetch {
197 return self->flags.selectFirstAfterFetch ? YES : NO;
200 - (void)setValidatesChangesImmediatly:(BOOL)_flag {
201 self->flags.validatesChangesImmediatly = _flag ? 1 : 0;
203 - (BOOL)validatesChangesImmediatly {
204 return self->flags.validatesChangesImmediatly ? YES : NO;
209 - (BOOL)hasMultipleBatches {
210 return [self batchCount] > 1 ? YES : NO;
212 - (unsigned)batchCount {
215 doc = [[self allObjects] count];
216 nob = [self numberOfObjectsPerBatch];
220 : doc / nob + ((doc % nob) ? 1 : 0) ;
223 - (void)setCurrentBatchIndex:(unsigned)_index {
224 self->currentBatchIndex = (_index <= [self batchCount]) ? _index : 1;
226 - (unsigned)currentBatchIndex {
227 if (self->currentBatchIndex > [self batchCount])
228 self->currentBatchIndex = 1;
229 return self->currentBatchIndex;
232 - (unsigned)indexOfFirstDisplayedObject {
233 return ([self currentBatchIndex] - 1) * [self numberOfObjectsPerBatch];
236 - (unsigned)indexOfLastDisplayedObject {
237 unsigned nob = [self numberOfObjectsPerBatch];
238 unsigned cnt = [[self allObjects] count];
243 return (([self indexOfFirstDisplayedObject] + nob) < cnt)
244 ? ([self indexOfFirstDisplayedObject] + nob) - 1
248 - (id)displayNextBatch {
249 [self clearSelection];
251 self->currentBatchIndex++;
252 if (self->currentBatchIndex > [self batchCount])
253 self->currentBatchIndex = 1;
255 [self updateDisplayedObjects];
259 - (id)displayPreviousBatch {
260 [self clearSelection];
262 self->currentBatchIndex--;
263 if ([self currentBatchIndex] <= 0)
264 self->currentBatchIndex = [self batchCount];
266 [self updateDisplayedObjects];
270 - (id)displayBatchContainingSelectedObject {
271 NSLog(@"WARNING: %s not implemenented", __PRETTY_FUNCTION__);
272 [self updateDisplayedObjects];
278 - (BOOL)setSelectionIndexes:(NSArray *)_selection {
281 NSSet *before, *after;
284 if ((d = [self delegate])) {
285 if ([d respondsToSelector:
286 @selector(displayGroup:shouldChangeSelectionToIndexes:)]) {
287 ok = [d displayGroup:self shouldChangeSelectionToIndexes:_selection];
293 /* apply selection */
295 before = [NSSet setWithArray:self->selectionIndexes];
296 after = [NSSet setWithArray:_selection];
298 ASSIGN(self->selectionIndexes, _selection);
300 if (![before isEqual:after]) {
301 [d displayGroupDidChangeSelection:self];
302 [d displayGroupDidChangeSelectedObjects:self];
306 - (NSArray *)selectionIndexes {
307 return self->selectionIndexes;
310 - (BOOL)clearSelection {
311 static NSArray *emptyArray = nil;
312 if (emptyArray == nil) emptyArray = [[NSArray alloc] init];
313 return [self setSelectionIndexes:emptyArray];
319 if ([self->displayObjects count] == 0)
322 if ([self->selectionIndexes count] == 0) {
323 [self setSelectionIndexes:uint0Array];
327 idx = [[self->selectionIndexes lastObject] unsignedIntValue];
328 if (idx >= ([self->displayObjects count] - 1)) {
329 /* last object is already selected, select first one */
330 [self setSelectionIndexes:uint0Array];
334 /* select next object .. */
335 [self setSelectionIndexes:
336 [NSArray arrayWithObject:[NSNumber numberWithUnsignedInt:(idx + 1)]]];
340 - (id)selectPrevious {
343 if ([self->displayObjects count] == 0)
346 if ([self->selectionIndexes count] == 0) {
347 [self setSelectionIndexes:uint0Array];
351 idx = [[self->selectionIndexes objectAtIndex:0] unsignedIntValue];
353 /* first object is selected, now select last one */
355 sidx = [NSNumber numberWithUnsignedInt:([self->displayObjects count] - 1)];
356 [self setSelectionIndexes:[NSArray arrayWithObject:sidx]];
359 /* select previous object .. */
360 [self setSelectionIndexes:
361 [NSArray arrayWithObject:[NSNumber numberWithUnsignedInt:(idx - 1)]]];
365 - (void)setSelectedObject:(id)_obj {
366 NSLog(@"WARNING: %s not implemented.", __PRETTY_FUNCTION__);
368 - (id)selectedObject {
372 - (void)setSelectedObjects:(NSArray *)_objs {
373 [self selectObjectsIdenticalTo:_objs];
374 // NSLog(@"WARNING: %s not implemented.", __PRETTY_FUNCTION__);
376 - (NSArray *)selectedObjects {
377 NSMutableArray *result;
378 unsigned int i, sCount, oCount;
380 sCount = [self->selectionIndexes count];
381 oCount = [self->objects count];
382 result = [NSMutableArray arrayWithCapacity:sCount];
384 for (i=0; i<sCount; i++) {
387 idx = [[self->selectionIndexes objectAtIndex:i] unsignedIntValue];
389 [result addObject:[self->objects objectAtIndex:idx]];
394 /* returns YES if displayedObjects contains _obj otherwise NO */
395 - (BOOL)selectObject:(id)_obj {
399 if (![self->displayObjects containsObject:_obj])
402 idx = [self->displayObjects indexOfObject:_obj];
403 idxNumber = [NSNumber numberWithUnsignedInt:idx];
405 if ([self->selectionIndexes containsObject:idxNumber])
410 tmp = [NSMutableArray arrayWithObjects:self->selectionIndexes];
411 [tmp addObject:idxNumber];
412 [self setSelectionIndexes:tmp];
418 /* returns YES if at least one obj matches otherwise NO */
419 - (BOOL)selectObjectsIdenticalTo:(NSArray *)_objs {
420 NSMutableArray *newIndexes;
429 newIndexes = [NSMutableArray arrayWithCapacity:cnt];
431 for (i=0; i<cnt; i++) {
436 obj = [_objs objectAtIndex:i];
437 if (![self->objects containsObject:obj])
441 idx = [self->objects indexOfObject:obj];
442 idxNumber = [NSNumber numberWithUnsignedInt:idx];
444 if ([self->selectionIndexes containsObject:idxNumber])
447 [newIndexes addObject:idxNumber];
452 [newIndexes addObjectsFromArray:self->selectionIndexes];
453 [self setSelectionIndexes:newIndexes];
458 - (BOOL)selectObjectsIdenticalTo:(NSArray *)_objs
459 selectFirstOnNoMatch:(BOOL)_flag
461 if ([self selectObjectsIdenticalTo:_objs])
465 return [self selectObject:[self->displayObjects objectAtIndex:0]];
472 - (void)setObjectArray:(NSArray *)_objects {
473 ASSIGN(self->objects, _objects);
475 /* should try to restore selection */
476 [self clearSelection];
477 if ([_objects count] > 0 && [self selectsFirstObjectAfterFetch]) {
478 [self setSelectionIndexes:uint0Array];
482 - (NSArray *)allObjects {
483 return self->objects;
486 - (NSArray *)displayedObjects {
487 return self->displayObjects;
493 if ([self->delegate respondsToSelector:@selector(displayGroupShouldFetch:)]) {
494 if (![self->delegate displayGroupShouldFetch:self])
495 /* delegate rejected fetch-request */
499 objs = [[self dataSource] fetchObjects];
501 [self setObjectArray:objs];
503 if ([self->delegate respondsToSelector:
504 @selector(displayGroup:didFetchObjects:)]) {
505 [self->delegate displayGroup:self didFetchObjects:objs];
508 [self updateDisplayedObjects];
510 if ([self selectsFirstObjectAfterFetch]) {
511 [self clearSelection];
513 if ([objs count] > 0)
514 [self setSelectedObject:[objs objectAtIndex:0]];
518 - (void)updateDisplayedObjects {
519 NSArray *darray; // display objects
520 NSArray *sarray; // selected objects
522 sarray = [self selectedObjects];
524 if ([self->delegate respondsToSelector:
525 @selector(displayGroup:displayArrayForObjects:)]) {
526 darray = [self->delegate displayGroup:self
527 displayArrayForObjects:[self allObjects]];
529 darray = [darray copy];
530 RELEASE(self->displayObjects);
531 self->displayObjects = darray;
539 ao = [self allObjects];
541 /* apply qualifier */
543 if ((q = [self qualifier]))
544 ao = [ao filteredArrayUsingQualifier:q];
545 #endif // should be done in qualifyDisplayGroup
547 /* apply sort orderings */
548 if ((so = [self sortOrderings]))
549 ao = [ao sortedArrayUsingKeyOrderArray:so];
551 if (ao != self->objects)
552 [self setObjectArray:ao];
557 if ([self batchCount] > 1) {
558 unsigned first = [self indexOfFirstDisplayedObject];
559 unsigned last = [self indexOfLastDisplayedObject];
561 darray = [darray subarrayWithRange:NSMakeRange(first, last-first+1)];
565 darray = [darray copy];
566 RELEASE(self->displayObjects);
567 self->displayObjects = darray;
569 [self selectObjectsIdenticalTo:sarray];
574 - (void)setInQueryMode:(BOOL)_flag {
575 self->flags.inQueryMode = _flag ? 1 : 0;
577 - (BOOL)inQueryMode {
578 return self->flags.inQueryMode ? YES : NO;
581 - (EOQualifier *)qualifierFromQueryValues {
582 NSMutableDictionary *qm, *qmin, *qmax, *qop;
583 NSMutableArray *quals;
587 qm = [self queryMatch];
588 qmin = [self queryMin];
589 qmax = [self queryMax];
590 qop = [self queryOperator];
592 quals = [NSMutableArray arrayWithCapacity:[qm count]];
594 /* construct qualifier for all query-match entries */
596 keys = [qm keyEnumerator];
597 while ((key = [keys nextObject])) {
603 value = [qm objectForKey:key];
605 if ((op = [qop objectForKey:key]) == nil) {
606 /* default operator is equality */
608 ops = EOQualifierOperatorEqual;
610 else if ([value isKindOfClass:[NSString class]]) {
611 /* strings are treated in a special way */
614 fmt = [self defaultStringMatchFormat];
615 op = [self defaultStringMatchOperator];
616 ops = [EOQualifier operatorSelectorForString:op];
618 value = [NSString stringWithFormat:fmt, value];
621 ops = [EOQualifier operatorSelectorForString:op];
624 q = [[EOKeyValueQualifier alloc]
632 /* construct min qualifiers */
634 keys = [qmin keyEnumerator];
635 while ((key = [keys nextObject])) {
639 value = [qmin objectForKey:key];
641 q = [[EOKeyValueQualifier alloc]
643 operatorSelector:EOQualifierOperatorGreaterThan
649 /* construct max qualifiers */
651 keys = [qmax keyEnumerator];
652 while ((key = [keys nextObject])) {
656 value = [qmin objectForKey:key];
658 q = [[EOKeyValueQualifier alloc]
660 operatorSelector:EOQualifierOperatorLessThan
666 if ([quals count] == 0)
668 else if ([quals count] == 1)
669 return [quals objectAtIndex:0];
671 return AUTORELEASE([[EOAndQualifier alloc] initWithQualifierArray:quals]);
674 - (NSMutableDictionary *)queryBindings {
675 if (self->_queryBindings == nil)
676 self->_queryBindings = [[NSMutableDictionary alloc] init];
677 return self->_queryBindings;
679 - (NSMutableDictionary *)queryMatch {
680 if (self->_queryMatch == nil)
681 self->_queryMatch = [[NSMutableDictionary alloc] init];
682 return self->_queryMatch;
684 - (NSMutableDictionary *)queryMin {
685 if (self->_queryMin == nil)
686 self->_queryMin = [[NSMutableDictionary alloc] init];
687 return self->_queryMin;
689 - (NSMutableDictionary *)queryMax {
690 if (self->_queryMax == nil)
691 self->_queryMax = [[NSMutableDictionary alloc] init];
692 return self->_queryMax;
694 - (NSMutableDictionary *)queryOperator {
695 if (self->_queryOperator == nil)
696 self->_queryOperator = [[NSMutableDictionary alloc] init];
697 return self->_queryOperator;
700 - (void)setDefaultStringMatchFormat:(NSString *)_tmp {
701 ASSIGN(self->defaultStringMatchFormat, _tmp);
703 - (NSString *)defaultStringMatchFormat {
704 return self->defaultStringMatchFormat;
706 - (void)setDefaultStringMatchOperator:(NSString *)_tmp {
707 ASSIGN(self->defaultStringMatchOperator, _tmp);
709 - (NSString *)defaultStringMatchOperator {
710 return self->defaultStringMatchOperator;
712 + (NSString *)globalDefaultStringMatchFormat {
715 + (NSString *)globalDefaultStringMatchOperator {
716 return @"caseInsensitiveLike";
722 - (void)setQualifier:(EOQualifier *)_q {
723 ASSIGN(self->qualifier, _q);
725 - (EOQualifier *)qualifier {
726 return self->qualifier;
729 - (NSArray *)allQualifierOperators {
730 static NSArray *quals = nil;
732 quals = [[NSArray alloc] initWithObjects:
733 @"=", @"!=", @"<", @"<=", @">", @">=",
734 @"like", @"caseInsensitiveLike", nil];
738 - (NSArray *)stringQualifierOperators {
739 static NSArray *quals = nil;
741 quals = [[NSArray alloc] initWithObjects:
751 - (NSArray *)relationalQualifierOperators {
752 static NSArray *quals = nil;
754 quals = [[NSArray alloc] initWithObjects:
755 @"=", @"!=", @"<", @"<=", @">", @">=", nil];
760 - (void)qualifyDisplayGroup {
763 if ((q = [self qualifierFromQueryValues]))
764 [self setQualifier:q];
766 [self updateDisplayedObjects];
768 if ([self inQueryMode])
769 [self setInQueryMode:NO];
772 - (void)qualifyDataSource {
776 ds = [self dataSource];
778 if ((q = [self qualifierFromQueryValues]))
779 [self setQualifier:q];
781 if ([ds respondsToSelector:@selector(setAuxiliaryQualifier:)])
782 [ds setAuxiliaryQualifier:[self qualifier]];
783 else if ([ds respondsToSelector:@selector(setQualifier:)])
784 [ds setQualifier:[self qualifier]];
786 /* could not qualify ds */
789 if ([ds respondsToSelector:@selector(setQualifierBindings:)])
790 [ds setQualifierBindings:[self queryBindings]];
794 if ([self inQueryMode])
795 [self setInQueryMode:NO];
800 - (void)takeValue:(id)_value forKeyPath:(NSString *)_keyPath {
801 if([_keyPath hasPrefix:@"queryMatch."]) {
802 [[self queryMatch] takeValue:_value
803 forKey:[_keyPath substringFromIndex:11]];
805 else if([_keyPath hasPrefix:@"queryMax."])
806 [[self queryMax] takeValue:_value forKey:[_keyPath substringFromIndex:9]];
807 else if([_keyPath hasPrefix:@"queryMin."])
808 [[self queryMin] takeValue:_value forKey:[_keyPath substringFromIndex:9]];
809 else if([_keyPath hasPrefix:@"queryOperator."]) {
810 [[self queryOperator] takeValue:_value
811 forKey:[_keyPath substringFromIndex:14]];
814 [super takeValue:_value forKeyPath:_keyPath];
816 - (id)valueForKeyPath:(NSString *)_keyPath {
817 if ([_keyPath hasPrefix:@"queryMatch."])
818 return [[self queryMatch] valueForKey:[_keyPath substringFromIndex:11]];
819 if ([_keyPath hasPrefix:@"queryMax."])
820 return [[self queryMax] valueForKey:[_keyPath substringFromIndex:9]];
821 if ([_keyPath hasPrefix:@"queryMin."])
822 return [[self queryMin] valueForKey:[_keyPath substringFromIndex:9]];
823 if ([_keyPath hasPrefix:@"queryOperator."])
824 return [[self queryOperator] valueForKey:[_keyPath substringFromIndex:14]];
826 return [super valueForKeyPath:_keyPath];
831 - (id)initWithCoder:(NSCoder *)_coder {
832 self->dataSource = [[_coder decodeObject] retain];
833 self->delegate = [_coder decodeObject];
834 self->sortOrderings = [[_coder decodeObject] copy];
835 self->insertedObjectDefaults = [[_coder decodeObject] copy];
836 self->qualifier = [[_coder decodeObject] copy];
837 self->defaultStringMatchFormat = [[_coder decodeObject] copy];
838 self->defaultStringMatchOperator = [[_coder decodeObject] copy];
839 self->_queryBindings = [[_coder decodeObject] copy];
840 self->_queryMatch = [[_coder decodeObject] copy];
841 self->_queryMin = [[_coder decodeObject] copy];
842 self->_queryMax = [[_coder decodeObject] copy];
843 self->_queryOperator = [[_coder decodeObject] copy];
848 - (void)encodeWithCoder:(NSCoder *)_coder {
849 [_coder encodeObject:self->dataSource];
850 [_coder encodeObject:self->delegate];
851 [_coder encodeObject:self->sortOrderings];
852 [_coder encodeObject:self->insertedObjectDefaults];
853 [_coder encodeObject:self->qualifier];
854 [_coder encodeObject:self->defaultStringMatchFormat];
855 [_coder encodeObject:self->defaultStringMatchOperator];
856 [_coder encodeObject:self->_queryBindings];
857 [_coder encodeObject:self->_queryMatch];
858 [_coder encodeObject:self->_queryMin];
859 [_coder encodeObject:self->_queryMax];
860 [_coder encodeObject:self->_queryOperator];
862 [self notImplemented:_cmd];
867 - (NSString *)description {
868 return [NSString stringWithFormat:@"<0x%08X %@: ds=%@>",
869 self, NSStringFromClass([self class]),
873 @end /* WODisplayGroup */
875 @implementation WODisplayGroup(KVCArchiving)
877 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
878 if ((self = [self init])) {
881 if ((tmp = [_unarchiver decodeObjectForKey:@"formatForLikeQualifier"]))
882 [self setDefaultStringMatchFormat:tmp];
884 if ((tmp = [_unarchiver decodeObjectForKey:@"dataSource"]))
885 [self setDataSource:tmp];
887 if ((tmp = [_unarchiver decodeObjectForKey:@"numberOfObjectsPerBatch"]))
888 [self setNumberOfObjectsPerBatch:[tmp intValue]];
890 [self setFetchesOnLoad:[_unarchiver decodeBoolForKey:@"fetchesOnLoad"]];
891 [self setSelectsFirstObjectAfterFetch:
892 [_unarchiver decodeBoolForKey:@"selectsFirstObjectAfterFetch"]];
897 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
898 [_archiver encodeObject:[self defaultStringMatchFormat]
899 forKey:@"formatForLikeQualifier"];
900 [_archiver encodeObject:[self dataSource]
901 forKey:@"dataSource"];
902 [_archiver encodeObject:
903 [NSNumber numberWithUnsignedInt:[self numberOfObjectsPerBatch]]
904 forKey:@"numberOfObjectsPerBatch"];
905 [_archiver encodeBool:[self fetchesOnLoad]
906 forKey:@"fetchesOnLoad"];
907 [_archiver encodeBool:[self selectsFirstObjectAfterFetch]
908 forKey:@"selectFirstAfterFetch"];
911 @end /* KVCArchiving */
913 @implementation WODisplayGroup(EOEditorsImpl)
917 - (void)editingContextWillSaveChanges:(id)_ec {
919 - (BOOL)editorHasChangesForEditingContext:(id)_ec {
925 @end /* WODisplayGroup(EOEditorsImpl) */
927 @implementation WODisplayGroup(EOMessageHandlersImpl)
931 - (void)editingContext:(id)_ec
932 presentErrorMessage:(NSString *)_msg
936 - (BOOL)editingContext:(id)_ec
937 shouldContinueFetchingWithCurrentObjectCount:(unsigned)_oc
938 originalLimit:(unsigned)_olimit
939 objectStore:(EOObjectStore *)_store
946 @end /* WODisplayGroup(EOMessageHandlersImpl) */