"Fossies" - the Fresh Open Source Software Archive 
Member "opengroupware-5.5rc3/WebUI/Common/OGoUIElements/SkyTableView.m" (5 Dec 2015, 20962 Bytes) of package /linux/privat/opengroupware-5.5rc3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Matlab source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "SkyTableView.m" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
5.5rc2_vs_5.5rc3.
1 /*
2 Copyright (C) 2000-2005 SKYRIX Software AG
3
4 This file is part of OpenGroupware.org.
5
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
9 later version.
10
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.
15
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
19 02111-1307, USA.
20 */
21
22 /*
23 > dataSource
24 > list
25 <> batchSize
26 <> selections
27
28 <> item
29 <> index
30 > identifier
31 <> previousItem
32 <> previousIndex
33
34 <> sortedKey
35 <> isDescending
36
37 < groups
38 < objectsOfGroup
39 > showGroupTitle (default: YES)
40
41 > scrollOnClient
42 <> autoScroll
43 < count // number of elements in dataSource
44
45 > sortAction
46 > sortCaseInsensitive (default: NO)
47 > showBatchResizeButtons (default: YES)
48
49 > titleString
50 > footerString
51
52 > cacheTimeout // seconds
53 */
54
55 //#define PROFILE 1
56
57 #include <OGoFoundation/OGoComponent.h>
58 #include <NGExtensions/EOCacheDataSource.h>
59 #include "common.h"
60
61 @interface SkyTableView : OGoComponent
62 {
63 @protected
64 NSArray *list;
65 EODataSource *dataSource;
66 NSMutableArray *selections;
67 id item;
68 unsigned index;
69
70 BOOL isDescending;
71 BOOL scrollOnClient;
72 int autoScroll;
73 NSString *sortedKey;
74 unsigned batchSize;
75 unsigned currentBatch;
76
77 NSString *shiftId; // used by shiftClickScript (changed never)
78 NSString *allId; // used by selectAllCheckboxScript
79
80 NSString *titleString;
81 NSString *footerString;
82
83 int indexOfFirst;
84 int indexOfLast;
85
86 // grouping
87 NSDictionary *groupingDict;
88 NSArray *groupAttributes; // array of groupNames
89 NGBitSet *showGroupSet;
90 }
91 - (void)setList:(NSArray *)_list;
92 - (NSString *)identifier;
93 @end
94
95 @interface NSDictionary(SkyTableViewGrouping)
96 - (NSArray *)flattenedArrayWithHint:(unsigned)_hint andKeys:(NSArray *)_keys;
97 - (NSArray *)attributesWithHint:(unsigned int)_hint andKeys:(NSArray *)_keys;
98 - (NGBitSet *)bitSetWithHint:(unsigned int)_hint;
99 @end
100
101 static NSString *SkyTableView_SelectAllCheckboxesScript = nil;
102 static NSString *SkyTableView_ShiftClickScript = nil;
103
104 @implementation SkyTableView
105
106 static Class EOCacheDataSourceClass = Nil;
107 static Class StrClass = Nil;
108
109 + (void)initialize {
110 NSBundle *bundle;
111 NSString *path;
112 static BOOL didInit = NO;
113 if (didInit) return;
114 didInit = YES;
115
116 StrClass = [NSString class];
117 EOCacheDataSourceClass = [EOCacheDataSource class];
118
119 bundle = [NSBundle bundleForClass:self];
120
121 path = [bundle pathForResource:@"SkyTableView_SelectAllCheckboxesScript"
122 ofType:@"js"];
123 SkyTableView_SelectAllCheckboxesScript =
124 [[StrClass alloc] initWithContentsOfFile:path];
125 if (SkyTableView_SelectAllCheckboxesScript == nil)
126 NSLog(@"WARNING: did not find checkboxes JavaScript for SkyTableView!");
127
128 path = [bundle pathForResource:@"SkyTableView_ShiftClickScript"
129 ofType:@"js"];
130 SkyTableView_ShiftClickScript =
131 [[StrClass alloc] initWithContentsOfFile:path];
132 if (SkyTableView_ShiftClickScript == nil)
133 NSLog(@"WARNING: did not find shiftclick JavaScript for SkyTableView!");
134 }
135
136 static inline NSString *_currentId(SkyTableView *self) {
137 NSArray *tmp;
138
139 tmp = [[[self context] elementID] componentsSeparatedByString:@"."];
140
141 return [tmp componentsJoinedByString:@""];
142 }
143
144 - (id)init {
145 if ((self = [super init])) {
146 self->shiftId = [_currentId(self) copy];
147 self->showGroupSet = [[NGBitSet alloc] initWithCapacity:128];
148 }
149 return self;
150 }
151
152 - (void)dealloc {
153 [self->list release];
154 [self->item release];
155 [self->dataSource release];
156 [self->selections release];
157 [self->allId release];
158 [self->shiftId release];
159 [self->sortedKey release];
160
161 [self->titleString release];
162 [self->footerString release];
163
164 [self->groupingDict release];
165 [self->groupAttributes release];
166 [self->showGroupSet release];
167
168 [super dealloc];
169 }
170
171 /* sorting */
172
173 - (void)_sortList {
174 // is only called if self->dataSource== nil
175 EOSortOrdering *so;
176 SEL sel;
177 BOOL isInsen;
178 NSArray *soArray;
179
180 BEGIN_PROFILE;
181
182 isInsen = ([self canGetValueForBinding:@"sortCaseInsensitive"])
183 ? [[self valueForBinding:@"sortCaseInsensitive"] boolValue]
184 : NO;
185
186 sel = (self->isDescending)
187 ? (isInsen) ? EOCompareCaseInsensitiveDescending : EOCompareDescending
188 : (isInsen) ? EOCompareCaseInsensitiveAscending : EOCompareAscending;
189
190 so = [EOSortOrdering sortOrderingWithKey:self->sortedKey selector:sel];
191
192 soArray = [NSArray arrayWithObject:so];
193 [self setList:[self->list sortedArrayUsingKeyOrderArray:soArray]];
194
195 END_PROFILE;
196 }
197
198 - (void)_updateFetchSpecification {
199 EOFetchSpecification *fetchSpec;
200 EOSortOrdering *so;
201 SEL sel;
202 BOOL isInsen;
203
204 if (self->sortedKey == nil)
205 return;
206
207 BEGIN_PROFILE;
208
209 isInsen = ([self canGetValueForBinding:@"sortCaseInsensitive"])
210 ? [[self valueForBinding:@"sortCaseInsensitive"] boolValue]
211 : NO;
212
213 sel = (self->isDescending)
214 ? (isInsen) ? EOCompareCaseInsensitiveDescending : EOCompareDescending
215 : (isInsen) ? EOCompareCaseInsensitiveAscending : EOCompareAscending;
216
217 so = [EOSortOrdering sortOrderingWithKey:self->sortedKey selector:sel];
218
219 if ((fetchSpec = [self->dataSource fetchSpecification]) == nil) {
220 fetchSpec = [EOFetchSpecification fetchSpecificationWithEntityName:nil
221 qualifier:nil
222 sortOrderings:
223 [NSArray arrayWithObject:so]];
224 [self->dataSource setFetchSpecification:fetchSpec];
225 }
226 else {
227 NSArray *sos = nil;
228
229 sos = [NSArray arrayWithObject:so];
230
231 if ([[fetchSpec sortOrderings] isEqual:sos] == NO) {
232 [fetchSpec setSortOrderings:[NSArray arrayWithObject:so]];
233 [self->dataSource setFetchSpecification:fetchSpec];
234 }
235 }
236
237 END_PROFILE;
238 }
239
240 - (void)_updateListFromDataSource {
241 EOFetchSpecification *fetchSpec = nil;
242 NSArray *groupings = nil;
243
244 BEGIN_PROFILE;
245
246 if (![self canGetValueForBinding:@"sortAction"])
247 [self _updateFetchSpecification];
248 else
249 [self performParentAction:[self valueForBinding:@"sortAction"]];
250
251 fetchSpec = [self->dataSource fetchSpecification];
252
253 PROFILE_CHECKPOINT("after update fspec");
254
255 if ((groupings = [fetchSpec groupings])) {
256 unsigned int cnt;
257 NSArray *tmp;
258 EOGrouping *grouping;
259 NSArray *allKeys;
260
261
262 tmp = [self->dataSource fetchObjects];
263 cnt = [tmp count];
264
265 grouping = [groupings lastObject];
266 [grouping setSortOrderings:[fetchSpec sortOrderings]];
267
268 [self->groupingDict release]; self->groupingDict = nil;
269 self->groupingDict = [[tmp arrayGroupedBy:grouping] retain];
270
271 allKeys = [self->groupingDict allKeys];
272 allKeys = [allKeys sortedArrayUsingSelector:@selector(compare:)];
273 [self->groupAttributes release]; self->groupAttributes = nil;
274 self->groupAttributes =
275 [[self->groupingDict attributesWithHint:cnt andKeys:allKeys] retain];
276
277 [self setList:[self->groupingDict flattenedArrayWithHint:[tmp count]
278 andKeys:allKeys]];
279
280 PROFILE_CHECKPOINT("after groupings");
281 }
282 else {
283 RELEASE(self->groupAttributes); self->groupAttributes = nil;
284
285 [self setList:[self->dataSource fetchObjects]];
286
287 PROFILE_CHECKPOINT("after no groupings");
288 }
289
290 END_PROFILE;
291 }
292
293 /* accessors */
294
295 - (void)setIsDescending:(BOOL)_isDescending {
296 self->isDescending = _isDescending;
297 }
298 - (BOOL)isDescending {
299 return self->isDescending;
300 }
301
302 - (void)setSortedKey:(NSString *)_sortedKey {
303 ASSIGN(self->sortedKey, _sortedKey);
304 }
305 - (NSString *)sortedKey {
306 return self->sortedKey;
307 }
308
309 - (BOOL)scrollOnClient {
310 return self->scrollOnClient;
311 }
312
313 - (int)autoScroll {
314 return self->autoScroll;
315 }
316 - (void)setAutoScroll:(int)_autoScroll {
317 self->autoScroll = _autoScroll;
318 }
319
320 - (unsigned)batchSize {
321 return self->batchSize;
322 }
323 - (void)setBatchSize:(unsigned)_batchSize {
324 self->batchSize = _batchSize;
325 }
326
327 - (void)setList:(NSArray *)_list {
328 ASSIGN(self->list, _list);
329 }
330
331 - (NSArray *)list {
332 return self->list;
333 }
334
335 - (void)setDataSource:(EODataSource *)_dataSource {
336 int cacheTimeout = -1;
337
338 if (self->dataSource == _dataSource)
339 return;
340
341 BEGIN_PROFILE;
342
343 if ([self canGetValueForBinding:@"cacheTimeout"])
344 cacheTimeout = [self intValueForBinding:@"cacheTimeout"];
345
346 // use a cacheDataSource
347 if (cacheTimeout > 0) {
348 #if DEBUG && 0
349 [self debugWithFormat:@"use cached datasource (timeout=%i)",
350 cacheTimeout];
351 #endif
352 if ([self->dataSource isKindOfClass:EOCacheDataSourceClass] &&
353 [(EOCacheDataSource *)self->dataSource source] == _dataSource) {
354 if (cacheTimeout != [(EOCacheDataSource *)self->dataSource timeout])
355 [(EOCacheDataSource *)self->dataSource setTimeout:cacheTimeout];
356 return;
357 }
358 RELEASE(self->dataSource); self->dataSource = nil;
359 self->dataSource = [[EOCacheDataSource allocWithZone:[self zone]]
360 initWithDataSource:_dataSource];
361
362 [(EOCacheDataSource *)self->dataSource setTimeout:cacheTimeout];
363 }
364 // do not use dataSource
365 else {
366 ASSIGN(self->dataSource, _dataSource);
367 }
368
369 END_PROFILE;
370 }
371
372 - (void)setSelections:(NSArray *)_selections {
373 ASSIGN(self->selections, [NSMutableArray arrayWithArray: _selections]);
374 }
375 - (NSArray *)selections {
376 return self->selections;
377 }
378
379 - (void)setItem:(id)_item {
380 [self setValue:_item forBinding:@"item"];
381 ASSIGN(self->item, _item);
382 }
383 - (id)item {
384 return self->item;
385 }
386
387 - (void)setIndex:(unsigned)_index {
388 [self setValue:[NSNumber numberWithInt:_index] forBinding:@"index"];
389 self->index = _index;
390 }
391 - (unsigned)index {
392 return self->index;
393 }
394
395 // --- grouping -----------------------------------------
396
397 - (NSArray *)groups {
398 return (self->groupAttributes)
399 ? [self->groupAttributes objectAtIndex:self->index]
400 : nil;
401 }
402
403 - (void)setGroups:(NSArray *)_groups {
404 [self setValue:[self groups] forBinding:@"groups"];
405 [self setValue:[self->groupingDict objectForKey:[self groups]]
406 forBinding:@"objectsOfGroup"];
407 }
408
409 - (BOOL)showGroup {
410 return (self->groupAttributes != nil)
411 ? [self->showGroupSet isMember:self->index]
412 : YES;
413 }
414 - (void)setShowGroup:(BOOL)_bool {
415 if (_bool)
416 [self->showGroupSet addMember:self->index];
417 else
418 [self->showGroupSet removeMember:self->index];
419 }
420
421 - (BOOL)showGroupTitle {
422 return ([self canGetValueForBinding:@"showGroupTitle"])
423 ? [[self valueForBinding:@"showGroupTitle"] boolValue]
424 : YES;
425 }
426
427 // --- checkboxes --------------------------------------
428
429 - (BOOL)isSelectAllAsCheckBox {
430 if (self->batchSize > [self->list count])
431 return YES;
432
433 return NO;
434 }
435
436 - (BOOL)isAllSelected {
437 return ([self->list count] == 0)
438 ? NO
439 : ([self->selections count] == [self->list count]);
440 }
441
442 - (id)selectAll {
443 [self->selections removeAllObjects];
444 [self->selections addObjectsFromArray:self->list];
445
446 return nil;
447 }
448
449 - (id)deselectAll {
450 [self->selections removeAllObjects];
451
452 return nil;
453 }
454
455 - (BOOL)isChecked {
456 return [self->selections containsObject:self->item];
457 }
458
459 - (void)setIsChecked:(BOOL)_flag {
460 if (_flag && ![self->selections containsObject:self->item])
461 [self->selections addObject:self->item];
462 else if (!_flag && [self->selections containsObject:self->item])
463 [self->selections removeObject:self->item];
464 }
465
466 - (BOOL)isCheckBoxes {
467 if (![[self context] isInForm])
468 return NO;
469
470 return [self hasBinding:@"selections"];
471 //return (self->selections != nil) ? YES : NO;
472 }
473
474 - (NSString *)shiftClick {
475 return [StrClass stringWithFormat:@"shiftClick%@(%d)",
476 self->shiftId, self->index];
477 }
478
479 - (NSString *)allSelect {
480 return [StrClass stringWithFormat:@"allselect%@()", self->allId];
481 }
482
483 - (NSString *)checkBoxName {
484 return [StrClass stringWithFormat:@"%@%@", self->shiftId,
485 [self identifier]];
486 }
487
488 - (NSString *)checkBoxValue {
489 return [StrClass stringWithFormat:@"%@%d", self->shiftId, self->index];
490 }
491
492 - (void)setIndexOfFirst:(int)_val {
493 self->indexOfFirst = _val;
494 }
495 - (int)indexOfFirst {
496 return self->indexOfFirst;
497 }
498 - (void)setIndexOfLast:(int)_val {
499 self->indexOfLast = _val;
500 }
501 - (int)indexOfLast {
502 return self->indexOfLast;
503 }
504
505 - (NSString *)selectAllCheckboxesScript {
506 RELEASE(self->allId); self->allId = nil;
507 self->allId = [_currentId(self) copy];
508
509 return [StrClass stringWithFormat:SkyTableView_SelectAllCheckboxesScript,
510 self->allId,
511 self->allId,
512 self->allId,
513 self->allId,
514 [self indexOfFirst],
515 [self indexOfLast] + 1,
516 self->shiftId,
517 self->allId];
518 }
519
520 - (NSString *)shiftClickScript {
521 return [StrClass stringWithFormat:SkyTableView_ShiftClickScript,
522 self->shiftId,self->shiftId, self->shiftId, self->shiftId,
523 self->shiftId,self->shiftId];
524 }
525
526 - (NSString *)markAllCheckboxName {
527 return [StrClass stringWithFormat:@"markAllCheckbox%@", self->allId];
528 }
529
530 // --- actions ------------------------------------------
531
532 - (id)tableViewSortAction {
533 NSString *parentAction = nil;
534
535 parentAction = [self valueForBinding:@"sortAction"];
536
537 if (parentAction != nil) {
538 if ([self canSetValueForBinding:@"sortedKey"])
539 [self setValue:self->sortedKey forBinding:@"sortedKey"];
540 if ([self canSetValueForBinding:@"isDescending"])
541 [self setValue:[NSNumber numberWithBool:self->isDescending]
542 forBinding:@"isDescending"];
543
544 [self performParentAction:parentAction];
545 }
546 else if (self->dataSource) {
547 [self _updateFetchSpecification];
548 }
549 else
550 [self _sortList];
551
552 return nil;
553 }
554
555 // --- syncing ------------------------------------------
556
557 - (void)setPreviousItem:(id)_previousItem {
558 [self setValue:_previousItem forBinding:@"previousItem"];
559 }
560
561 - (void)setPreviousIndex:(unsigned)_previousIndex {
562 [self setValue:[NSNumber numberWithInt:_previousIndex]
563 forBinding:@"previousIndex"];
564 }
565
566 - (void)setCurrentBatch:(unsigned)_batch {
567 self->currentBatch = _batch;
568 }
569 - (unsigned)currentBatch {
570 return self->currentBatch;
571 }
572
573 - (void)setIdentifier:(NSString *)_identifier {
574 [self setValue:_identifier forBinding:@"identifier"];
575 }
576
577 - (NSString *)identifier {
578 id tmp;
579
580 tmp = [self valueForBinding:@"identifier"];
581 return (tmp) ? tmp : [StrClass stringWithFormat:@"%d", self->index];
582 }
583
584 - (BOOL)showBatchResizeButtons {
585 if (![self canGetValueForBinding:@"showBatchResizeButtons"])
586 return YES;
587
588 return [[self valueForBinding:@"showBatchResizeButtons"] boolValue];
589 }
590
591 - (void)setTitleString:(NSString *)_titleString {
592 ASSIGN(self->titleString, _titleString);
593 }
594 - (NSString *)titleString {
595 return self->titleString;
596 }
597
598 - (void)setFooterString:(NSString *)_footerString {
599 ASSIGN(self->footerString, _footerString);
600 }
601 - (NSString *)footerString {
602 return self->footerString;
603 }
604
605 - (BOOL)hasFooterString {
606 return (self->footerString != nil) ? YES : NO;
607 }
608
609 - (BOOL)hasTitleString {
610 return (self->titleString != nil) ? YES : NO;
611 }
612
613 - (void)syncFromParent {
614 #define getVal(_a_) getBinding(self, @selector(valueForBinding:), _a_)
615
616 id tmp;
617 IMP getBinding;
618
619 BEGIN_PROFILE;
620
621 getBinding = [self methodForSelector:@selector(valueForBinding:)];
622
623 [self setDataSource:getVal(@"dataSource")];
624 [self setSelections:getVal(@"selections")];
625
626 if ([self canGetValueForBinding:@"isDescending"] &&
627 ([self canSetValueForBinding:@"isDescending"] ||
628 (self->sortedKey == nil)))
629 self->isDescending = [getVal(@"isDescending") boolValue];
630
631 if ([self canGetValueForBinding:@"sortedKey"] &&
632 ([self canSetValueForBinding:@"sortedKey"] || (self->sortedKey == nil)))
633 [self setSortedKey:getVal(@"sortedKey")];
634
635 [self setTitleString:getVal(@"titleString")];
636 [self setFooterString:getVal(@"footerString")];
637
638 if (self->dataSource) {
639 [self _updateListFromDataSource];
640 }
641 else
642 [self setList:getVal(@"list")];
643
644 [self setValue:[NSNumber numberWithInt:[self->list count]]
645 forBinding:@"count"];
646
647 self->batchSize = [getVal(@"batchSize") unsignedIntValue];
648 tmp = getVal(@"currentBatch");
649 if (tmp != nil)
650 self->currentBatch = [tmp unsignedIntValue];
651 self->scrollOnClient = [getVal(@"scrollOnClient") boolValue];
652 self->autoScroll = [getVal(@"autoScroll") intValue];
653
654 END_PROFILE;
655
656 #undef getVal
657 }
658
659 - (void)syncToParent {
660 #define setVal(_val_, _b_) \
661 if ([self canSetValueForBinding:_b_])\
662 setBinding(self, @selector(setValue:forBinding:), ((_val_)), ((_b_)))
663
664 IMP setBinding;
665
666 BEGIN_PROFILE;
667
668 setBinding = [self methodForSelector:@selector(setValue:forBinding:)];
669
670 setVal(self->selections, @"selections");
671
672 setVal(self->sortedKey, @"sortedKey");
673 setVal([NSNumber numberWithBool:self->isDescending], @"isDescending");
674 setVal([NSNumber numberWithInt:self->batchSize], @"batchSize");
675 setVal([NSNumber numberWithInt:self->currentBatch], @"currentBatch");
676 setVal([NSNumber numberWithInt:self->autoScroll], @"autoScroll");
677
678 RELEASE(self->list); self->list = nil;
679
680 END_PROFILE;
681
682 #undef setVal
683 }
684
685 // --- responder
686
687 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
688 [self syncFromParent];
689 [super takeValuesFromRequest:_req inContext:_ctx];
690 [self syncToParent];
691 }
692
693 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
694 id result;
695
696 [self syncFromParent];
697 result = [super invokeActionForRequest:_req inContext:_ctx];
698 [self syncToParent];
699
700 return result;
701 }
702
703 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
704 BEGIN_PROFILE;
705 [self syncFromParent];
706 PROFILE_CHECKPOINT("after sync from parent");
707 [super appendToResponse:_response inContext:_ctx];
708 PROFILE_CHECKPOINT("after append to response");
709 [self syncToParent];
710 END_PROFILE;
711 }
712
713 - (BOOL)synchronizesVariablesWithBindings {
714 return NO;
715 }
716
717 @end /* SkyTableView */
718
719 #define ProfileComponents NO
720
721 @implementation NSDictionary(TableView)
722
723 - (NSArray *)flattenedArrayWithHint:(unsigned int)_hint
724 andKeys:(NSArray *)_keys
725 {
726 NSMutableArray *result = nil;
727 unsigned int i, cnt;
728 NSTimeInterval st = 0.0;
729
730 if (ProfileComponents)
731 st = [[NSDate date] timeIntervalSince1970];
732
733 // should be improved
734 result = [[NSMutableArray alloc] initWithCapacity:_hint];
735
736 for (i = 0, cnt = [_keys count]; i < cnt; i++) {
737 NSString *key;
738 NSArray *tmp;
739
740 key = [_keys objectAtIndex:i];
741 tmp = [self objectForKey:key];
742 [result addObjectsFromArray:tmp];
743 }
744
745 if (ProfileComponents) {
746 NSTimeInterval diff;
747 diff = [[NSDate date] timeIntervalSince1970] - st;
748
749 printf("NSDictionary.flattenedArray: %0.4fs\n", diff);
750 }
751 return result;
752 }
753
754 - (NSArray *)attributesWithHint:(unsigned int)_hint andKeys:(NSArray *)_keys {
755 NSMutableArray *result = nil;
756 unsigned int i, cnt;
757 NSTimeInterval st = 0.0;
758
759 if (ProfileComponents)
760 st = [[NSDate date] timeIntervalSince1970];
761
762 result = [[NSMutableArray allocWithZone:[self zone]]
763 initWithCapacity:_hint+1];
764
765 for (i = 0, cnt = [_keys count]; i < cnt; i++) {
766 unsigned j, cnt2;
767 NSString *key;
768
769 key = [_keys objectAtIndex:i];
770
771 cnt2 = [[self objectForKey:key] count];
772 for (j = 0; j < cnt2; j++)
773 [result addObject:key];
774 }
775
776 if (ProfileComponents) {
777 NSTimeInterval diff;
778 diff = [[NSDate date] timeIntervalSince1970] - st;
779
780 printf("NSDictionary.attributes: %0.4fs\n", diff);
781 }
782
783 return result;
784 }
785
786 - (NGBitSet *)bitSetWithHint:(unsigned int)_hint {
787 NGBitSet *bitSet = nil;
788 NSEnumerator *keyEnum;
789 NSString *key;
790 unsigned int firstPos = 0;
791 NSTimeInterval st = 0.0;
792
793 if (ProfileComponents)
794 st = [[NSDate date] timeIntervalSince1970];
795
796 bitSet = [NGBitSet bitSetWithCapacity:_hint];
797
798 keyEnum = [self keyEnumerator];
799 while ((key = [keyEnum nextObject])) {
800 [bitSet addMember:firstPos];
801 firstPos += [[self objectForKey:key] count];
802 }
803
804 if (ProfileComponents) {
805 NSTimeInterval diff;
806 diff = [[NSDate date] timeIntervalSince1970] - st;
807
808 printf("NSDictionary.bitSet: %0.4fs\n", diff);
809 }
810
811 return bitSet;
812 }
813
814 @end /* NSDictionary(TableView) */