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 "WEContextConditional.h"
23 #include <NGObjWeb/WODynamicElement.h>
28 _______________________________
29 | MO | TU | WE | TH | FR | SA |
30 |-----------------------------|
32 | 0 | 2 | 4 | 6 | 8 | 11 |
33 |____|____|____|____|____|____|
37 | 1 | 3 | 5 | 7 | 9 | 13 |
38 |____|____|____|____|____|____|
40 Would be a nice addition:
42 -------------------------------
44 -------------------------------
45 footerRow = 0 / footerRowList = ( 0, 1, 2, 3, 4 );
46 headerRow = 0 / headerRowList = ( 0, 1, 2, 3, 4 );
49 the numbers corresponde to the indxes in the matrix (self->matrix[])
51 Note: it does support additional header and footer rows which can be used
52 to generate content above and below the view itself.
55 WeekOverview: WEWeekOverview {
58 weekStart = weekStart;
60 titleStyle = "weekview_title";
61 contentStyle = "weekview_content";
64 TitleMode: WEWeekOverviewTitleMode {};
65 InfoMode: WEWeekOverviewInfoMode {};
66 ContentMode: WEWeekOverviewContentMode {};
69 // TODO: allow stylesheet classes!
71 #define SecondsPerWeek (7 * 24 * 60 * 60)
72 #define SecondsPerDay (24 * 60 * 60)
74 @class NSMutableArray;
76 #define WEWeekOverview_TitleMode @"WEWeekOverview_TitleMode"
77 #define WEWeekOverview_TitleModeDidMatch @"WEWeekOverview_TitleModeDidMatch"
78 #define WEWeekOverview_InfoMode @"WEWeekOverview_InfoMode"
79 #define WEWeekOverview_PMInfoMode @"WEWeekOverview_PMInfoMode"
80 #define WEWeekOverview_ContentMode @"WEWeekOverview_ContentMode"
82 #define WEWeekOverview_FooterRowMode @"WEWeekOverview_FooterRowMode"
83 #define WEWeekOverview_HeaderRowMode @"WEWeekOverview_HeaderRowMode"
85 @interface WEWeekOverview : WODynamicElement
91 WOAssociation *identifier;
93 WOAssociation *dayIndex; // 0=firstDay, 1=secondDay, ..., 6=seventh day
94 WOAssociation *weekStart;
96 WOAssociation *startDateKey;
97 WOAssociation *endDateKey;
99 WOAssociation *titleStyle;
100 WOAssociation *contentStyle;
101 WOAssociation *titleColor; // DEPRECATED
102 WOAssociation *contentColor; // DEPRECATED
104 WOAssociation *width;
105 WOAssociation *border;
106 WOAssociation *cellpadding;
107 WOAssociation *cellspacing;
109 WOAssociation *footerRows; // list of elements for footer rows
110 WOAssociation *footerRow; // current element in footer row
111 WOAssociation *headerRows; // list of elements for header rows
112 WOAssociation *headerRow; // current element in header row
113 WOAssociation *colIndex; // for header/footer row
115 WOAssociation *isInfoItem; // is current item info entry
116 WOAssociation *infoItems; // current info entries
118 WOAssociation *hideWeekend; /* should Sa/So be rendered? */
121 NSMutableArray *matrix[14];
122 NSMutableArray *infos[14];
129 #include <math.h> /* Needed for floor() */
132 @interface WOContext(WEWeekOverview)
134 - (void)appendWEIntElementID:(int)_intID;
136 - (void)enterWEWOMode:(NSString *)_mode elementID:(NSString *)_eid;
137 - (void)leaveWEWOMode:(NSString *)_mode;
141 static NSString *retStrForInt(int i);
142 static NSString *WEInfoElementID = @"i";
144 @implementation WOContext(WEWeekOverview)
146 - (void)appendWEIntElementID:(int)_intID {
148 // TODO: could make the number switch in here?
150 s = retStrForInt(_intID);
151 [self appendElementIDComponent:s];
155 - (void)enterWEWOMode:(NSString *)_mode elementID:(NSString *)_eid {
156 [self setObject:@"YES" forKey:_mode];
157 [self appendElementIDComponent:_eid];
159 - (void)leaveWEWOMode:(NSString *)_mode {
160 [self deleteLastElementIDComponent]; // delete eid
161 [self removeObjectForKey:_mode];
164 @end /* WOContext(WEWeekOverview) */
166 @implementation WEWeekOverview
168 // premature: don't know a "good" count
169 static NSNumber *smap[10] = { nil,nil,nil,nil,nil,nil,nil,nil,nil,nil };
170 static Class NumClass = Nil;
171 static Class StrClass = Nil;
172 static NSArray *emptyArray = nil;
175 static BOOL didInit = NO;
180 StrClass = [NSString class];
181 NumClass = [NSNumber class];
182 for (i = 0; i < 10; i++)
183 smap[i] = [[NumClass numberWithInt:i] retain];
185 if (emptyArray == nil) emptyArray = [[NSArray alloc] init];
188 static NSNumber *numForInt(int i) {
189 if (i >= 0 && i < 10)
191 return [NumClass numberWithInt:i];
193 static NSString *retStrForInt(int i) {
205 case 10: return @"10";
206 // TODO: find useful count!
209 sprintf(buf, "%i", i);
210 return [[StrClass alloc] initWithCString:buf];
215 - (id)initWithName:(NSString *)_name
216 associations:(NSDictionary *)_config
217 template:(WOElement *)_tmp
219 if ((self = [super initWithName:_name associations:_config template:_tmp])) {
220 self->list = WOExtGetProperty(_config, @"list");
221 self->item = WOExtGetProperty(_config, @"item");
222 self->index = WOExtGetProperty(_config, @"index");
223 self->identifier = WOExtGetProperty(_config, @"identifier");
224 self->dayIndex = WOExtGetProperty(_config, @"dayIndex");
225 self->weekStart = WOExtGetProperty(_config, @"weekStart");
226 self->startDateKey = WOExtGetProperty(_config, @"startDateKey");
227 self->endDateKey = WOExtGetProperty(_config, @"endDateKey");
228 self->hideWeekend = WOExtGetProperty(_config, @"hideWeekend");
230 self->titleColor = WOExtGetProperty(_config, @"titleColor");
231 self->titleStyle = WOExtGetProperty(_config, @"titleStyle");
232 self->contentColor = WOExtGetProperty(_config, @"contentColor");
233 self->contentStyle = WOExtGetProperty(_config, @"contentStyle");
235 self->width = WOExtGetProperty(_config, @"width");
236 self->border = WOExtGetProperty(_config, @"border");
237 self->cellspacing = WOExtGetProperty(_config, @"cellspacing");
238 self->cellpadding = WOExtGetProperty(_config, @"cellpadding");
240 self->headerRows = WOExtGetProperty(_config, @"headerRows");
241 self->headerRow = WOExtGetProperty(_config, @"headerRow");
242 self->footerRows = WOExtGetProperty(_config, @"footerRows");
243 self->footerRow = WOExtGetProperty(_config, @"footerRow");
244 self->colIndex = WOExtGetProperty(_config, @"columnIndex");
247 if (self->startDateKey == nil) {
249 [[WOAssociation associationWithValue:@"startDate"] retain];
252 if (self->endDateKey == nil) {
254 [[WOAssociation associationWithValue:@"endDate"] retain];
257 if (self->width == nil)
258 self->width = [[WOAssociation associationWithValue:@"100%"] retain];
259 if (self->border == nil)
260 self->border = [[WOAssociation associationWithValue:@"0"] retain];
261 if (self->cellspacing == nil)
262 self->cellspacing = [[WOAssociation associationWithValue:@"2"] retain];
263 if (self->cellpadding == nil)
264 self->cellpadding = [[WOAssociation associationWithValue:@"5"] retain];
266 self->isInfoItem = WOExtGetProperty(_config, @"isInfoItem");
267 self->infoItems = WOExtGetProperty(_config, @"infoItems");
269 self->template = [_tmp retain];
274 - (void)resetMatrix {
277 for (i = 0; i < 14; i++) {
278 [self->matrix[i] release]; self->matrix[i] = nil;
279 [self->infos[i] release]; self->infos[i] = nil;
284 [self->hideWeekend release];
285 [self->list release];
286 [self->item release];
287 [self->index release];
288 [self->identifier release];
289 [self->dayIndex release];
290 [self->weekStart release];
291 [self->startDateKey release];
292 [self->endDateKey release];
293 [self->titleColor release];
294 [self->titleStyle release];
295 [self->contentColor release];
296 [self->contentStyle release];
297 [self->width release];
298 [self->border release];
299 [self->cellpadding release];
300 [self->cellspacing release];
301 [self->headerRows release];
302 [self->headerRow release];
303 [self->footerRows release];
304 [self->footerRow release];
305 [self->colIndex release];
306 [self->infoItems release];
307 [self->isInfoItem release];
311 [self->template release];
317 _applyIdentifier(WEWeekOverview *self, WOComponent *comp, NSString *_idx)
322 array = [self->list valueInComponent:comp];
323 count = [array count];
328 /* find subelement for unique id */
330 for (cnt = 0; cnt < count; cnt++) {
334 [self->index setUnsignedIntValue:cnt inComponent:comp];
337 [self->item setValue:[array objectAtIndex:cnt] inComponent:comp];
339 ident = [self->identifier stringValueInComponent:comp];
341 if ([ident isEqualToString:_idx]) {
342 /* found subelement with unique id */
348 @"WEWeekOverview: array did change, "
349 @"unique-id isn't contained."];
350 [self->item setValue:nil inComponent:comp];
351 [self->index setUnsignedIntValue:0 inComponent:comp];
355 _applyIndex(WEWeekOverview *self, WOComponent *comp, unsigned _idx)
360 array = [self->list valueInComponent:comp];
363 [self->index setUnsignedIntValue:_idx inComponent:comp];
365 if (self->item == nil)
368 count = [array count];
370 [self->item setValue:[array objectAtIndex:_idx] inComponent:comp];
375 @"WEWeekOverview: array did change, index is invalid."];
376 [self->item setValue:nil inComponent:comp];
377 [self->index setUnsignedIntValue:0 inComponent:comp];
380 - (void)_calcMatrixInContext:(WOContext *)_ctx {
382 NSCalendarDate *startWeek;
383 NSCalendarDate *endWeek;
387 int i, idx, idx2, cnt;
391 [_ctx removeObjectForKey:WEWeekOverview_TitleModeDidMatch];
392 [_ctx setObject:@"YES" forKey:WEWeekOverview_TitleMode];
393 [self->template appendToResponse:nil inContext:_ctx];
394 [_ctx removeObjectForKey:WEWeekOverview_TitleMode];
396 if ([_ctx objectForKey:WEWeekOverview_TitleModeDidMatch] != nil)
397 self->hasOwnTitle = YES;
399 self->hasOwnTitle = NO;
401 comp = [_ctx component];
402 array = [self->list valueInComponent:comp];
403 startKey = [self->startDateKey stringValueInComponent:comp];
404 endKey = [self->endDateKey stringValueInComponent:comp];
405 startWeek = (self->weekStart)
406 ? [self->weekStart valueInComponent:comp]
407 : [NSCalendarDate calendarDate];
408 endWeek = [startWeek addTimeInterval:SecondsPerWeek];
410 for (i = 0, cnt = [array count]; i < cnt; i++) {
412 NSCalendarDate *sd, *ed;
416 app = [array objectAtIndex:i];
417 #if 0 // hh: so muesste es eigentlich sein: !!!
418 [self->item setValue:app inComponent:comp];
420 sd = [self->startDate valueInComponent:comp]; // item.startDate;
421 ed = [self->endDate valueInComponent:comp]; // item.startDate;
424 sd = [app valueForKey:startKey]; // startDate
425 ed = [app valueForKey:endKey]; // endDate
427 if ((sd == nil) && (ed == nil)) continue;
429 diff = [(sd ? sd : ed) timeIntervalSinceDate:startWeek];
431 idx = floor((diff / SecondsPerWeek) * 14);
433 if ((self->item) && (self->isInfoItem)) {
434 [self->item setValue:app inComponent:comp];
435 isInfo = [[self->isInfoItem valueInComponent:comp] boolValue];
439 if ((0 <= idx) && (idx < 14)) {
441 if (self->infos[idx] == nil)
442 self->infos[idx] = [[NSMutableArray alloc] initWithCapacity:2];
443 [self->infos[idx] addObject:numForInt(i)];
446 if (self->matrix[idx] == nil)
447 self->matrix[idx] = [[NSMutableArray alloc] initWithCapacity:4];
448 [self->matrix[idx] addObject:numForInt(i)];
452 idx = (idx % 2) ? idx + 1: idx +2;
454 diff = [ed timeIntervalSinceDate:startWeek];
456 idx2 = floor((diff / SecondsPerWeek) * 14);
457 idx2 = (idx2 > 13) ? 13 : idx2;
459 if (idx2 < 0) continue;
461 while (idx <= idx2) {
462 idx = (idx < 0) ? 0 : idx;
464 if (self->infos[idx] == nil)
465 self->infos[idx] = [[NSMutableArray alloc] initWithCapacity:2];
467 [self->infos[idx] addObject:numForInt(i)];
470 if (self->matrix[idx] == nil)
471 self->matrix[idx] = [[NSMutableArray alloc] initWithCapacity:4];
473 [self->matrix[idx] addObject:numForInt(i)];
480 /* common template operations */
482 - (void)appendTemplateToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx
483 mode:(NSString *)_mode elementID:(NSString *)_modeId
486 [_ctx enterWEWOMode:_mode elementID:_modeId];
487 [_ctx appendWEIntElementID:_idx];
488 [self->template appendToResponse:_r inContext:_ctx];
489 [_ctx deleteLastElementIDComponent]; // delete idx
490 [_ctx leaveWEWOMode:_mode];
495 - (void)appendHeaderRowToResponse:(WOResponse *)_response
496 inContext:(WOContext *)_ctx
500 NSString *bgcolor, *style;
502 comp = [_ctx component];
504 if ([self->colIndex isValueSettable])
505 [self->colIndex setIntValue:_col inComponent:comp];
507 bgcolor = [self->contentColor stringValueInComponent:comp];
508 style = [self->contentStyle stringValueInComponent:comp];
510 [_response appendContentString:
511 @"<td valign=\"top\" align=\"left\" width=\"17%\""];
513 [_response appendContentString:@" bgcolor=\""];
514 [_response appendContentString:bgcolor];
515 [_response appendContentCharacter:'"'];
517 if ([style length] > 0) {
518 [_response appendContentString:@" class=\""];
519 [_response appendContentString:style];
520 [_response appendContentCharacter:'"'];
522 [_response appendContentCharacter:'>'];
524 [self appendTemplateToResponse:_response inContext:_ctx
525 mode:WEWeekOverview_HeaderRowMode elementID:@"h"
528 [_response appendContentString:@"</td>"];
530 - (void)appendHeaderRowToResponse:(WOResponse *)_response
531 inContext:(WOContext *)_ctx
536 if ([self->headerRow isValueSettable])
537 [self->headerRow setValue:_rowItem inComponent:[_ctx component]];
539 /* Saturday/Sunday is the 6th column */
540 cnt = (self->hideWeekend != nil)
541 ? [self->hideWeekend boolValueInComponent:[_ctx component]] ? 5 : 6
544 for (i = 0; i < cnt; i++)
545 [self appendHeaderRowToResponse:_response inContext:_ctx column:i];
547 - (void)appendHeaderRowsToResponse:(WOResponse *)_response
548 inContext:(WOContext *)_ctx
550 /* add n <tr> rows */
555 comp = [_ctx component];
556 if ((headers = [self->headerRows valueInComponent:comp]) == nil)
559 for (i = 0, cnt = [headers count]; i < cnt; i++) {
562 one = [headers objectAtIndex:i];
564 [_response appendContentString:@"<tr>"];
565 [_ctx appendElementIDComponent:@"hr"]; // header row
566 [_ctx appendWEIntElementID:i];
568 [self appendHeaderRowToResponse:_response inContext:_ctx row:one];
570 [_ctx deleteLastElementIDComponent]; // remove idx (i)
571 [_ctx deleteLastElementIDComponent]; // remove 'hr'
572 [_response appendContentString:@"</tr>"];
578 - (void)appendFooterRowToResponse:(WOResponse *)_response
579 inContext:(WOContext *)_ctx
585 comp = [_ctx component];
587 if ([self->colIndex isValueSettable])
588 [self->colIndex setIntValue:_col inComponent:comp];
590 bgcolor = [self->contentColor stringValueInComponent:comp];
592 [_response appendContentString:
593 @"<td valign=\"top\" align=\"left\" width=\"17%\""];
595 [_response appendContentString:@" bgcolor=\""];
596 [_response appendContentString:bgcolor];
597 [_response appendContentCharacter:'"'];
599 [_response appendContentCharacter:'>'];
601 [self appendTemplateToResponse:_response inContext:_ctx
602 mode:WEWeekOverview_FooterRowMode elementID:@"f"
605 [_response appendContentString:@"</td>"];
608 - (void)appendFooterRowToResponse:(WOResponse *)_response
609 inContext:(WOContext *)_ctx
612 // TODO: this method is a DUP to appendHeaderRowToResponse... => refactor
615 if ([self->footerRow isValueSettable])
616 [self->footerRow setValue:_rowItem inComponent:[_ctx component]];
618 /* Saturday/Sunday is the 6th column */
619 cnt = (self->hideWeekend != nil)
620 ? [self->hideWeekend boolValueInComponent:[_ctx component]] ? 5 : 6
623 for (i = 0; i < cnt; i++)
624 [self appendFooterRowToResponse:_response inContext:_ctx column:i];
627 - (void)appendFooterRowsToResponse:(WOResponse *)_response
628 inContext:(WOContext *)_ctx
630 // TODO: this is a copy of the head-row method!
635 comp = [_ctx component];
637 if ((footers = [self->footerRows valueInComponent:comp]) == nil)
640 for (i = 0, cnt = [footers count]; i < cnt; i++) {
644 one = [footers objectAtIndex:i];
646 [_response appendContentString:@"<tr>"];
647 [_ctx appendElementIDComponent:@"fr"];
650 [_ctx appendElementIDComponent:s];
653 [self appendFooterRowToResponse:_response inContext:_ctx row:one];
655 [_ctx deleteLastElementIDComponent]; // remove idx (i)
656 [_ctx deleteLastElementIDComponent]; // remove 'fr'
657 [_response appendContentString:@"</tr>"];
661 - (void)appendDateTitleToResponse:(WOResponse *)_response
662 inContext:(WOContext *)_ctx
666 NSString *bgcolor, *style;
668 comp = [_ctx component];
670 if ([self->dayIndex isValueSettable])
671 [self->dayIndex setIntValue:_day inComponent:comp];
673 bgcolor = [self->titleColor stringValueInComponent:comp];
674 style = [self->titleStyle stringValueInComponent:comp];
676 // TODO: use CSS for alignment, width and color
677 [_response appendContentString:
678 @"<td valign=\"top\" align=\"left\" width=\"17%\""];
679 if ([bgcolor length] > 0) {
680 [_response appendContentString:@" bgcolor=\""];
681 [_response appendContentString:bgcolor];
682 [_response appendContentCharacter:'"'];
684 if ([style length] > 0) {
685 [_response appendContentString:@" class=\""];
686 [_response appendContentString:style];
687 [_response appendContentCharacter:'"'];
689 [_response appendContentCharacter:'>'];
691 if (self->hasOwnTitle) {
692 [self appendTemplateToResponse:_response inContext:_ctx
693 mode:WEWeekOverview_TitleMode elementID:@"t"
697 NSCalendarDate *date;
700 date = (self->weekStart)
701 ? [self->weekStart valueInComponent:comp]
702 : [NSCalendarDate calendarDate];
703 date = [date addTimeInterval:_day * SecondsPerDay];
705 [_response appendContentString:
706 @"<table cellpadding=\"0\" width=\"100%\" border=\"0\" "
707 @"cellspacing=\"0\">"
709 @"<td align=\"left\" valign=\"top\">"
710 // TODO: use style for that
711 @"<font color=\"black\" size=\"+2\"><b>"];
713 s = [date descriptionWithCalendarFormat:@"%d"]; // TODO: no cal-desc!
714 [_response appendContentString:s];
716 [_response appendContentString:
718 @"<td align=\"center\" valign=\"top\">"
719 // TODO: use style for that
720 @"<font color=\"black\">"];
721 s = [date descriptionWithCalendarFormat:@"%A"]; // TODO: no cal-desc
722 [_response appendContentString:s]; // TODO: do not use cal-desc
723 [_response appendContentString:
725 @"</td></tr></table>"];
727 [_response appendContentString:@"</td>"];
730 - (void)appendContentToResponse:(WOResponse *)_response
731 inContext:(WOContext *)_ctx
737 int i, cnt, idx, count;
739 comp = [_ctx component];
740 array = [self->list valueInComponent:comp];
741 count = [array count];
743 /* idx is the dayIndex 0=1stDay ... 6=7thDay (e.g. 0=Mon ... 6=Sun) */
744 idx = (int)(_index / 2);
746 if ([self->dayIndex isValueSettable])
747 [self->dayIndex setIntValue:idx inComponent:comp];
749 if ([self->infoItems isValueSettable]) {
750 cnt = [self->infos[_index] count];
752 NSMutableArray *infoArr;
754 infoArr = [[NSMutableArray alloc] initWithCapacity:cnt];
755 for (i = 0; i < cnt; i++) {
756 idx = [[self->infos[_index] objectAtIndex:i] intValue];
760 @"WARNING: WEWeekOverview: info index out of range"];
763 [infoArr addObject:[array objectAtIndex:idx]];
765 [self->infoItems setValue:infoArr inComponent:comp];
766 [infoArr release]; infoArr = nil;
769 [self->infoItems setValue:emptyArray inComponent:comp];
772 // *** append day info
773 if ((_index % 2) == 0) {
776 [self appendTemplateToResponse:_response inContext:_ctx
777 mode:WEWeekOverview_InfoMode elementID:WEInfoElementID
780 else if (_index < 10) {
781 /* P.M. slot of Monday .. Friday */
782 [self appendTemplateToResponse:_response inContext:_ctx
783 mode:WEWeekOverview_PMInfoMode elementID:@"p"
787 // *** append day content
788 [_ctx enterWEWOMode:WEWeekOverview_ContentMode elementID:@"c"];
790 // append section id (0 = Mon AM, 1 = Mon PM, 2 = Tue AM, ...)
791 [_ctx appendWEIntElementID:_index];
793 for (i = 0, cnt = [self->matrix[_index] count]; i < cnt; i++) {
794 idx = [[self->matrix[_index] objectAtIndex:i] intValue];
797 NSLog(@"Warning! WEWeekOverview: index out of range");
801 app = [array objectAtIndex:idx];
803 if ([self->item isValueSettable])
804 [self->item setValue:app inComponent:comp];
805 if ([self->index isValueSettable])
806 [self->index setIntValue:idx inComponent:comp];
808 if (self->identifier == nil) {
811 s = retStrForInt(idx);
812 [_ctx appendElementIDComponent:s];
818 s = [self->identifier stringValueInComponent:comp];
819 [_ctx appendElementIDComponent:s];
821 [self->template appendToResponse:_response inContext:_ctx];
822 [_ctx deleteLastElementIDComponent];
825 [_response appendContentString:@" "];
827 [_ctx deleteLastElementIDComponent]; // delete section id
828 [_ctx leaveWEWOMode:WEWeekOverview_ContentMode];
831 /* processing requests */
833 - (void)takeValuesForHeaderRows:(WORequest *)_req
834 ctx:(WOContext *)_ctx
840 comp = [_ctx component];
841 if ((headers = [self->headerRows valueInComponent:comp]) == nil)
844 [_ctx setObject:@"YES" forKey:WEWeekOverview_HeaderRowMode];
845 [_ctx appendElementIDComponent:@"hr"]; // append 'hr'
846 [_ctx appendZeroElementIDComponent]; // append i
848 for (i = 0, cnt = [headers count]; i < cnt; i++) {
851 [_ctx appendElementIDComponent:@"h"]; // append 'h'
852 [_ctx appendZeroElementIDComponent]; // append c
854 if ([self->headerRow isValueSettable])
855 [self->headerRow setValue:[headers objectAtIndex:i] inComponent:comp];
857 // TODO: do not go over Saturday (6) with hideWeekend=YES
858 for (c = 0; c < 6; c++) { // go throw columns
859 if ([self->colIndex isValueSettable])
860 [self->colIndex setIntValue:c inComponent:comp];
862 [self->template takeValuesFromRequest:_req inContext:_ctx];
863 [_ctx incrementLastElementIDComponent]; // increment c
866 [_ctx deleteLastElementIDComponent]; // delete c
867 [_ctx deleteLastElementIDComponent]; // delete 'h'
868 [_ctx incrementLastElementIDComponent]; // increment i
871 [_ctx deleteLastElementIDComponent]; // remove i
872 [_ctx deleteLastElementIDComponent]; // remove 'hr'
873 [_ctx removeObjectForKey:WEWeekOverview_HeaderRowMode];
875 - (void)takeValuesForFooterRows:(WORequest *)_req
876 ctx:(WOContext *)_ctx
878 // TODO: this is a DUP of the header row
879 // we might implement that code as an internal WODynamicElement?
884 comp = [_ctx component];
885 if ((footers = [self->footerRows valueInComponent:comp]) == nil)
888 [_ctx setObject:@"YES" forKey:WEWeekOverview_FooterRowMode];
889 [_ctx appendElementIDComponent:@"hr"]; // append 'fr'
890 [_ctx appendZeroElementIDComponent]; // append i
892 for (i = 0, cnt = [footers count]; i < cnt; i++) {
894 [_ctx appendElementIDComponent:@"f"]; // append 'f'
895 [_ctx appendZeroElementIDComponent]; // append c
897 if ([self->footerRow isValueSettable])
898 [self->footerRow setValue:[footers objectAtIndex:i] inComponent:comp];
900 // TODO: do not go over Saturday (6) with hideWeekend=YES
901 for (c = 0; c < 6; c++) { // go throw columns
902 if ([self->colIndex isValueSettable])
903 [self->colIndex setIntValue:c inComponent:comp];
904 [self->template takeValuesFromRequest:_req inContext:_ctx];
905 [_ctx incrementLastElementIDComponent]; // increment c
908 [_ctx deleteLastElementIDComponent]; // delete c
909 [_ctx deleteLastElementIDComponent]; // delete 'f'
910 [_ctx incrementLastElementIDComponent]; // increment i
913 [_ctx deleteLastElementIDComponent]; // remove i
914 [_ctx deleteLastElementIDComponent]; // remove 'fr'
915 [_ctx removeObjectForKey:WEWeekOverview_FooterRowMode];
918 - (void)takeValues:(WORequest *)_req
919 mode:(NSString *)_mode modeId:(NSString *)_id
920 ctx:(WOContext *)_ctx
924 [_ctx setObject:@"YES" forKey:_mode];
925 [_ctx appendElementIDComponent:_id]; // append mode id
926 [_ctx appendZeroElementIDComponent]; // append first day (monday)
928 // TODO: do not go over Saturday (5), Sunday(6) with hideWeekend=YES
929 for (i = 0; i < 7; i++) {
930 if ([self->dayIndex isValueSettable])
931 [self->dayIndex setIntValue:i inComponent:[_ctx component]];
933 [self->template takeValuesFromRequest:_req inContext:_ctx];
934 [_ctx incrementLastElementIDComponent]; // increment day
936 [_ctx deleteLastElementIDComponent]; // delete day
937 [_ctx deleteLastElementIDComponent]; // delete title mode
938 [_ctx removeObjectForKey:_mode];
941 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
946 comp = [_ctx component];
947 array = [self->list valueInComponent:comp];
948 count = [array count];
951 [self takeValues:_req mode:WEWeekOverview_TitleMode modeId:@"t" ctx:_ctx];
954 [self takeValuesForHeaderRows:_req ctx:_ctx];
957 [self takeValues:_req mode:WEWeekOverview_InfoMode modeId:WEInfoElementID
961 [self takeValues:_req mode:WEWeekOverview_PMInfoMode modeId:@"p" ctx:_ctx];
963 [self _calcMatrixInContext:_ctx];
965 [_ctx setObject:@"YES" forKey:WEWeekOverview_ContentMode];
966 [_ctx appendElementIDComponent:@"c"]; // append content mode
967 [_ctx appendZeroElementIDComponent]; // append section-id
968 for (i = 0; i < 14; i++) {
971 cnt = [self->matrix[i] count];
973 if ((i % 2) == 0 && [self->dayIndex isValueSettable])
974 [self->dayIndex setIntValue:(int)(i / 2) inComponent:comp];
976 for (j = 0; j < cnt; j++) {
979 idx = [[self->matrix[i] objectAtIndex:j] intValue];
982 NSLog(@"Warning! WEWeekRepetition: Index is out of range");
986 _applyIndex(self, comp, idx);
988 if (self->identifier) {
989 s = [self->identifier stringValueInComponent:comp];
990 [_ctx appendElementIDComponent:s];
993 s = retStrForInt(idx);
994 [_ctx appendElementIDComponent:s];
998 [self->template takeValuesFromRequest:_req inContext:_ctx];
1000 [_ctx deleteLastElementIDComponent]; // delete index-id
1002 [_ctx incrementLastElementIDComponent]; // increase section-id
1004 [_ctx deleteLastElementIDComponent]; // delete section-id
1005 [_ctx deleteLastElementIDComponent]; // delete content mode
1006 [_ctx removeObjectForKey:WEWeekOverview_ContentMode];
1009 [self takeValuesForFooterRows:_req ctx:_ctx];
1014 - (id)invokeActionForHeader:(WORequest *)_req inContext:(WOContext *)_ctx
1018 NSString *section; // must be 'h'
1019 NSString *colIdx; // must be between 0 and 6
1023 comp = [_ctx component];
1025 section = [_ctx currentElementID];
1026 [_ctx consumeElementID];
1027 [_ctx appendElementIDComponent:section];
1028 colIdx = [_ctx currentElementID];
1029 [_ctx consumeElementID];
1030 [_ctx appendElementIDComponent:colIdx];
1032 if ([self->headerRow isValueSettable])
1033 [self->headerRow setValue:_row inComponent:comp];
1034 if ([self->dayIndex isValueSettable])
1035 [self->colIndex setIntValue:[colIdx intValue] inComponent:comp];
1037 result = [self->template invokeActionForRequest:_req inContext:_ctx];
1039 [_ctx deleteLastElementIDComponent]; // column idx
1040 [_ctx deleteLastElementIDComponent]; // section ('h')
1044 - (id)invokeActionForFooter:(WORequest *)_req inContext:(WOContext *)_ctx
1048 NSString *section; // must be 'f'
1049 NSString *colIdx; // must be between 0 and 6
1053 comp = [_ctx component];
1055 section = [_ctx currentElementID];
1056 [_ctx consumeElementID];
1057 [_ctx appendElementIDComponent:section];
1058 colIdx = [_ctx currentElementID];
1059 [_ctx consumeElementID];
1060 [_ctx appendElementIDComponent:colIdx];
1062 if ([self->footerRow isValueSettable])
1063 [self->footerRow setValue:_row inComponent:comp];
1064 if ([self->dayIndex isValueSettable])
1065 [self->colIndex setIntValue:[colIdx intValue] inComponent:comp];
1067 result = [self->template invokeActionForRequest:_req inContext:_ctx];
1069 [_ctx deleteLastElementIDComponent]; // column idx
1070 [_ctx deleteLastElementIDComponent]; // section ('f')
1075 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
1079 NSString *sectionId;
1081 cid = [_ctx currentElementID]; // get mode ("t" or "i" or "c")
1082 [_ctx consumeElementID];
1083 [_ctx appendElementIDComponent:cid];
1084 sectionId = [_ctx currentElementID]; // get section id
1085 [_ctx consumeElementID];
1086 [_ctx appendElementIDComponent:sectionId];
1088 comp = [_ctx component];
1090 if ([cid isEqualToString:@"t"] ||
1091 [cid isEqualToString:WEInfoElementID] || [cid isEqualToString:@"p"]) {
1092 if ([self->dayIndex isValueSettable])
1093 [self->dayIndex setIntValue:[sectionId intValue] inComponent:comp];
1094 result = [self->template invokeActionForRequest:_req inContext:_ctx];
1096 else if ([cid isEqualToString:@"c"]) {
1099 if ([self->dayIndex isValueSettable])
1100 [self->dayIndex setIntValue:([sectionId intValue] / 2) inComponent:comp];
1102 if ((idxId = [_ctx currentElementID])) {
1103 [_ctx consumeElementID]; // consume index-id
1104 [_ctx appendElementIDComponent:idxId];
1106 if (self->identifier)
1107 _applyIdentifier(self, comp, idxId);
1109 _applyIndex(self, comp, [idxId intValue]);
1111 result = [self->template invokeActionForRequest:_req inContext:_ctx];
1113 [_ctx deleteLastElementIDComponent]; // delete index-id
1116 else if ([cid isEqualToString:@"hr"]) {
1120 headers = [self->headerRows valueInComponent:comp];
1121 idx = [sectionId intValue];
1122 if (idx >= (int)[headers count]) {
1123 NSLog(@"WARNING! WEWeekOverview: wrong headerrow index");
1126 result = [self invokeActionForHeader:_req
1128 row:[headers objectAtIndex:idx]];
1131 else if ([cid isEqualToString:@"fr"]) {
1135 footers = [self->footerRows valueInComponent:comp];
1136 idx = [sectionId intValue];
1137 if (idx >= (int)[footers count]) {
1138 NSLog(@"WARNING! WEWeekOverview: wrong footerrow index");
1141 result = [self invokeActionForFooter:_req
1143 row:[footers objectAtIndex:idx]];
1147 NSLog(@"WARNING! WEWeekOverview: wrong section");
1149 [_ctx deleteLastElementIDComponent]; // delete section id
1150 [_ctx deleteLastElementIDComponent]; // delete mode
1155 /* generating response */
1157 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
1159 NSString *bgcolor, *style;
1160 NSString *w; // width
1161 NSString *b; // border
1162 NSString *cp; // cellpadding
1163 NSString *cs; // cellspacing
1167 [self _calcMatrixInContext:_ctx];
1169 comp = [_ctx component];
1170 w = [self->width stringValueInComponent:comp];
1171 b = [self->border stringValueInComponent:comp];
1172 cs = [self->cellspacing stringValueInComponent:comp];
1173 cp = [self->cellpadding stringValueInComponent:comp];
1175 showWeekend = (self->hideWeekend != nil)
1176 ? [self->hideWeekend boolValueInComponent:comp] ? NO : YES
1179 [_response appendContentString:
1180 @"<table border=\""];
1181 [_response appendContentString:b]; // border
1182 [_response appendContentString:@"\" cellpadding=\""];
1183 [_response appendContentString:cp]; // cellspacing
1184 [_response appendContentString:@"\" width=\""];
1185 [_response appendContentString:w]; // width
1186 [_response appendContentString:@"\" cellspacing=\""];
1187 [_response appendContentString:cs]; // cellspaing
1188 [_response appendContentString:@"\">"];
1190 /*** append title row (monday - saturday) ***/
1191 [_response appendContentString:@"<tr>"];
1192 for (i = 0; i < (showWeekend ? 6 : 5 ); i++)
1193 [self appendDateTitleToResponse:_response inContext:_ctx day:i];
1194 [_response appendContentString:@"</tr>"];
1196 /**** header rows ****/
1197 [self appendHeaderRowsToResponse:_response inContext:_ctx];
1199 /*** append AM content row + saturday ***/
1200 [_response appendContentString:@"<tr>"];
1202 /* AM weekdays content (this is count=10 because we slot 0=AM/1=PM, etc) */
1203 for (i = 0; i < 10; i = i + 2) {
1204 if ([self->dayIndex isValueSettable])
1205 [self->dayIndex setIntValue:(i / 2) inComponent:comp];
1207 [_response appendContentString:@"<td valign=\"top\""];
1208 if ((bgcolor = [self->contentColor stringValueInComponent:comp])) {
1209 [_response appendContentString:@" bgcolor=\""];
1210 [_response appendContentString:bgcolor];
1211 [_response appendContentCharacter:'"'];
1213 if ((style = [self->contentStyle stringValueInComponent:comp])) {
1214 [_response appendContentString:@" class=\""];
1215 [_response appendContentString:style];
1216 [_response appendContentCharacter:'"'];
1218 [_response appendContentCharacter:'>'];
1219 [self appendContentToResponse:_response inContext:_ctx index:i];
1220 [_response appendContentString:@"</td>"];
1222 /* saturday content */
1224 if ([self->dayIndex isValueSettable])
1225 [self->dayIndex setIntValue:5 inComponent:comp];
1227 [_response appendContentString:@"<td valign=\"top\""];
1229 if ((bgcolor = [self->contentColor stringValueInComponent:comp])) {
1230 [_response appendContentString:@" bgcolor=\""];
1231 [_response appendContentString:bgcolor];
1232 [_response appendContentCharacter:'"'];
1234 if ((style = [self->contentStyle stringValueInComponent:comp])) {
1235 [_response appendContentString:@" class=\""];
1236 [_response appendContentString:style];
1237 [_response appendContentCharacter:'"'];
1239 [_response appendContentCharacter:'>'];
1241 /* 10 is Saturday AM, 11 is Saturday PM, week overview shows them in one */
1242 [self appendContentToResponse:_response inContext:_ctx index:10];
1243 [self appendContentToResponse:_response inContext:_ctx index:11];
1244 [_response appendContentString:@"</td>"];
1247 [_response appendContentString:@"</tr>"]; /* close AM row */
1249 /*** append PM content row + sunday ***/
1250 [_response appendContentString:@"<tr>"];
1252 /* PM weekdays content */
1253 for (i = 1; i < 11; i = i + 2) {
1254 if ([self->dayIndex isValueSettable])
1255 [self->dayIndex setIntValue:(i/2) inComponent:comp];
1257 [_response appendContentString:@"<td valign=\"top\""];
1259 if (showWeekend) /* for Sunday we need an additional <tr> */
1260 [_response appendContentString:@" rowspan=\"2\""];
1262 if ((bgcolor = [self->contentColor stringValueInComponent:comp])) {
1263 [_response appendContentString:@" bgcolor=\""];
1264 [_response appendContentString:bgcolor];
1265 [_response appendContentCharacter:'"'];
1267 if ((style = [self->contentStyle stringValueInComponent:comp])) {
1268 [_response appendContentString:@" class=\""];
1269 [_response appendContentString:style];
1270 [_response appendContentCharacter:'"'];
1272 [_response appendContentCharacter:'>'];
1275 [self appendContentToResponse:_response inContext:_ctx index:i];
1276 [_response appendContentString:@"</td>"];
1281 [self appendDateTitleToResponse:_response inContext:_ctx day:6];
1282 [_response appendContentString:@"</tr>"];
1285 [_response appendContentString:@"<tr>"];
1287 if ([self->dayIndex isValueSettable])
1288 [self->dayIndex setIntValue:6 inComponent:comp];
1290 [_response appendContentString:@"<td valign=\"top\""];
1291 if ((bgcolor = [self->contentColor stringValueInComponent:comp])) {
1292 [_response appendContentString:@" bgcolor=\""];
1293 [_response appendContentString:bgcolor];
1294 [_response appendContentCharacter:'"'];
1296 [_response appendContentCharacter:'>'];
1298 /* 12 is Sunday/AM, 13 is Sunday/PM */
1299 [self appendContentToResponse:_response inContext:_ctx index:12];
1300 [self appendContentToResponse:_response inContext:_ctx index:13];
1301 [_response appendContentString:@"</td>"];
1304 [_response appendContentString:@"</tr>"]; /* close PM row */
1306 /***** footer rows *****/
1307 [self appendFooterRowsToResponse:_response inContext:_ctx];
1309 [_response appendContentString:@"</table>"];
1314 @end /* WeekOverview */
1316 @interface WEWeekOverviewTitleMode : WEContextConditional
1319 @implementation WEWeekOverviewTitleMode
1320 - (NSString *)_contextKey {
1321 return WEWeekOverview_TitleMode;
1324 - (NSString *)_didMatchKey {
1325 return WEWeekOverview_TitleModeDidMatch;
1327 @end /* WEWeekOverviewTitleMode */
1331 @interface WEWeekOverviewInfoMode : WEContextConditional
1334 @implementation WEWeekOverviewInfoMode
1335 - (NSString *)_contextKey {
1336 return WEWeekOverview_InfoMode;
1338 @end /* WEWeekOverviewInfoMode */
1342 @interface WEWeekOverviewContentMode : WEContextConditional
1345 @implementation WEWeekOverviewContentMode
1346 - (NSString *)_contextKey {
1347 return WEWeekOverview_ContentMode;
1349 @end /* WEWeekOverview_ContentMode */
1353 @interface WEWeekOverviewPMInfoMode : WEContextConditional
1356 @implementation WEWeekOverviewPMInfoMode
1357 - (NSString *)_contextKey {
1358 return WEWeekOverview_PMInfoMode;
1360 @end /* WEWeekOverviewPMInfoMode */
1362 @interface WEWeekOverviewHeaderMode : WEContextConditional
1365 @implementation WEWeekOverviewHeaderMode
1366 - (NSString *)_contextKey {
1367 return WEWeekOverview_HeaderRowMode;
1369 @end /* WEWeekOverviewHeaderMode */
1371 @interface WEWeekOverviewFooterMode : WEContextConditional
1374 @implementation WEWeekOverviewFooterMode
1375 - (NSString *)_contextKey {
1376 return WEWeekOverview_FooterRowMode;
1378 @end /* WEWeekOverviewFooterMode */