"Fossies" - the Fresh Open Source Software Archive

Member "opengroupware-5.5rc3/WebUI/Scheduler/OGoSchedulerViews/SkyMonthRepetition.m" (5 Dec 2015, 22389 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 "SkyMonthRepetition.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-2007 SKYRIX Software AG
    3   Copyright (C) 2007      Helge Hess
    4 
    5   This file is part of OpenGroupware.org.
    6 
    7   OGo is free software; you can redistribute it and/or modify it under
    8   the terms of the GNU Lesser General Public License as published by the
    9   Free Software Foundation; either version 2, or (at your option) any
   10   later version.
   11 
   12   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
   13   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
   15   License for more details.
   16 
   17   You should have received a copy of the GNU Lesser General Public
   18   License along with OGo; see the file COPYING.  If not, write to the
   19   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
   20   02111-1307, USA.
   21 */
   22 
   23 #include <NGObjWeb/WODynamicElement.h>
   24 
   25 @interface SkyMonthRepetition : WODynamicElement
   26 {
   27 @protected
   28   WOAssociation *year;       // year
   29   WOAssociation *month;      // month
   30   WOAssociation *timeZone;   // timeZone
   31   WOAssociation *firstDay;   // 0 - Sunday .. 6 - Saturday (default:1)
   32   WOAssociation *tableTags;  // make table tags
   33 
   34   WOAssociation *startDate;  // current begin of day
   35   WOAssociation *endDate;    // current end of day
   36   WOAssociation *isInMonth;  // is day in wanted month
   37 
   38   WOElement     *template;
   39 
   40   // extra attributes forwarded to table data
   41 }
   42 
   43 @end /* SkyMonthRepetition */
   44 
   45 @interface SkyMonthLabel : WODynamicElement
   46 {
   47 @protected
   48   WOAssociation *orientation;
   49   // left/top | top | right/top | right | right/bottom | bottom | left/bottom
   50   // left
   51   WOAssociation *dayOfWeek;
   52   // set if orientation is top or bottom
   53   WOAssociation *weekOfYear;
   54   // set if orientation is left or right
   55   WOAssociation *colspan;
   56   // set if orientation is header
   57   WOElement     *template;
   58 }
   59 @end /* SkyMonthLabel */
   60 
   61 @interface SkyMonthCell : WODynamicElement
   62 {
   63 @protected
   64   WOElement *template;
   65 }
   66 @end /* SkyMonthCell */
   67 
   68 
   69 #include "common.h"
   70 
   71 #if APPLE_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
   72 @interface NSCalendarDate(UsedPrivates)
   73 - (id)initWithTimeIntervalSince1970:(NSTimeInterval)_interval;
   74 @end
   75 #endif
   76 
   77 @implementation SkyMonthRepetition
   78 
   79 - (id)initWithName:(NSString *)_name
   80   associations:(NSDictionary*)_config
   81   template:(WOElement *)_t
   82 {
   83   if ((self = [super initWithName:_name associations:_config template:_t])) {
   84     self->year       = OWGetProperty(_config, @"year");
   85     self->month      = OWGetProperty(_config, @"month");
   86     self->timeZone   = OWGetProperty(_config, @"timeZone");
   87     self->firstDay   = OWGetProperty(_config, @"firstDay");
   88     self->tableTags  = OWGetProperty(_config, @"tableTags");
   89     
   90     self->startDate  = OWGetProperty(_config, @"startDate");
   91     self->endDate    = OWGetProperty(_config, @"endDate");
   92     self->isInMonth  = OWGetProperty(_config, @"isInMonth");
   93 
   94     self->template = [_t retain];
   95   }
   96   return self;
   97 }
   98 
   99 - (void)dealloc {
  100   [self->year      release];
  101   [self->month     release];
  102   [self->timeZone  release];
  103   [self->firstDay  release];
  104   [self->tableTags release];
  105   [self->startDate release];
  106   [self->endDate   release];
  107   [self->isInMonth release];
  108   [self->template  release];
  109   [super dealloc];
  110 }
  111 
  112 /* accessors */
  113 
  114 - (id)template {
  115   return self->template;
  116 }
  117 
  118 /* processing requests */
  119 
  120 static inline void
  121 _applyDate(SkyMonthRepetition *self, WOComponent *sComponent,
  122            NSCalendarDate *day)
  123 {
  124   unsigned m;
  125 
  126   m = [self->month unsignedIntValueInComponent:sComponent];
  127   
  128   if (self->startDate != nil)
  129     [self->startDate setValue:[day beginOfDay] inComponent:sComponent];
  130   if (self->endDate != nil)
  131     [self->endDate setValue:[day endOfDay] inComponent:sComponent];
  132   
  133   if (self->isInMonth) {
  134     [self->isInMonth setBoolValue:([day monthOfYear] == m) ? YES : NO
  135          inComponent:sComponent];
  136   }
  137 }
  138 
  139 static inline void
  140 _generateCell(SkyMonthRepetition *self, WOResponse *response,
  141               WOContext *ctx, NSString *key, NSString *value,
  142               NSCalendarDate *dateId)
  143 {
  144   NSDictionary *d = [[NSDictionary alloc] initWithObjects:&value forKeys:&key
  145                       count:1];
  146   [ctx takeValue:d forKey:@"SkyMonthRepetition"];
  147   [d release]; d = nil;
  148   
  149   [ctx appendElementIDComponent:key];
  150   if (dateId != nil) {
  151     NSString *eid;
  152     char buf[32 /* space for ulonglong */];
  153     
  154     sprintf(buf, "%d", (unsigned)[dateId timeIntervalSince1970]);
  155     eid = [[NSString alloc] initWithCString:buf];
  156     [ctx appendElementIDComponent:eid];
  157     [eid release];
  158   }
  159   
  160   [self->template appendToResponse:response inContext:ctx];
  161   
  162   if (dateId != nil)
  163     [ctx deleteLastElementIDComponent];
  164   [ctx deleteLastElementIDComponent];
  165 }
  166 static inline void
  167 _takeValuesInCell(SkyMonthRepetition *self, WORequest *request,
  168                   WOContext *ctx, NSString *key, NSString *value,
  169                   NSCalendarDate *dateId)
  170 {
  171   [ctx takeValue:
  172          [NSDictionary dictionaryWithObject:value forKey:key]
  173        forKey:@"SkyMonthRepetition"];
  174   
  175   [ctx appendElementIDComponent:key];
  176   if (dateId) {
  177     [ctx appendElementIDComponent:
  178            [NSString stringWithFormat:@"%d",
  179                        (unsigned)[dateId timeIntervalSince1970]]];
  180   }
  181   
  182   [self->template takeValuesFromRequest:request inContext:ctx];
  183 
  184   if (dateId)
  185     [ctx deleteLastElementIDComponent];
  186   [ctx deleteLastElementIDComponent];
  187 }
  188 
  189 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
  190   // TODO: split up this huge method
  191   WOComponent    *sComponent;
  192   unsigned       y, m, first;
  193   unsigned       count = 0;
  194   NSTimeZone     *tz;
  195   BOOL           useTableTags;
  196   BOOL           hasHeader      = NO;
  197   BOOL           hasLeftTop     = NO;
  198   BOOL           hasLeft        = NO;
  199   BOOL           hasTop         = NO;
  200   BOOL           hasRightTop    = NO;
  201   BOOL           hasRight       = NO;
  202   BOOL           hasLeftBottom  = NO;
  203   BOOL           hasBottom      = NO;
  204   BOOL           hasRightBottom = NO;
  205   BOOL           hasCell        = NO;
  206   
  207   NSCalendarDate *day;
  208 
  209   sComponent = [_ctx component];
  210   y  = [self->year unsignedIntValueInComponent:sComponent];
  211   m  = [self->month unsignedIntValueInComponent:sComponent];
  212   tz = [self->timeZone valueInComponent:sComponent];
  213 
  214   first = (self->firstDay) 
  215     ? [self->firstDay unsignedIntValueInComponent:sComponent]
  216     : 1; // Monday
  217 
  218   useTableTags = (self->tableTags) 
  219     ? [self->tableTags boolValueInComponent:sComponent]
  220     : YES;
  221 
  222   day = [NSCalendarDate dateWithYear:y month:m day:1
  223                         hour:0 minute:0 second:0 timeZone:tz];
  224 
  225   { // computing last day and following days
  226     unsigned dow;
  227     int dif;
  228 
  229     count = [day numberOfDaysInMonth];
  230 
  231     dow = [[day lastDayOfMonth] dayOfWeek];
  232     dif = first - dow - 1; // overview stopps 1 day before the first weekday
  233                            // --> e.g.: repetition starts monday, ends sunday
  234     dif = (dif < 0) ? dif + 7 : dif;
  235     count += dif;
  236   }
  237 
  238   { // computing leading days
  239     unsigned dow; // dayOfWeek
  240     int dif;
  241 
  242     dow = [day dayOfWeek];
  243 
  244     dif = first - dow;
  245     dif = (dif > 0) ? dif - 7 : dif;
  246 
  247     day = [day dateByAddingYears:0 months:0 days:dif];
  248     count -= dif;
  249   }
  250 
  251   { // query mode ... testing orientations
  252     NSEnumerator *queryE;
  253     NSString     *orient;
  254     // only query mode .. no value setting
  255     [_ctx takeValue:
  256           [NSDictionary dictionaryWithObjectsAndKeys:
  257                         [NSMutableArray array],
  258                         @"query", nil]
  259           forKey:@"SkyMonthRepetition"];
  260     [self->template appendToResponse:_response inContext:_ctx];
  261 
  262     queryE = [[[_ctx objectForKey:@"SkyMonthRepetition"] objectForKey:@"query"]
  263                      objectEnumerator];
  264 
  265     while ((orient = [queryE nextObject]) != nil) {
  266       if ((!hasHeader) && ([orient isEqualToString:@"header"]))
  267         hasHeader = YES;
  268       if ((!hasCell) && ([orient isEqualToString:@"cell"]))
  269         hasCell = YES;
  270       if ((!hasLeftTop) && ([orient isEqualToString:@"left/top"]))
  271         hasLeftTop = YES;
  272       if ((!hasLeftBottom) && ([orient isEqualToString:@"left/bottom"]))
  273         hasLeftBottom = YES;
  274       if ((!hasLeft) && ([orient isEqualToString:@"left"]))
  275         hasLeft = YES;
  276       if ((!hasTop) && ([orient isEqualToString:@"top"]))
  277         hasTop = YES;
  278       if ((!hasRightTop) && ([orient isEqualToString:@"right/top"]))
  279         hasRightTop = YES;
  280       if ((!hasRight) && ([orient isEqualToString:@"right"]))
  281         hasRight = YES;
  282       if ((!hasRightBottom) && ([orient isEqualToString:@"right/bottom"]))
  283         hasRightBottom = YES;
  284       if ((!hasBottom) && ([orient isEqualToString:@"bottom"]))
  285         hasBottom = YES;
  286     }
  287 
  288     [_ctx takeValue:nil forKey:@"SkyMonthRepetition"];
  289   }
  290   
  291   // open table
  292   if (useTableTags) {
  293     [_response appendContentString:@"<table"];
  294     [self appendExtraAttributesToResponse:_response inContext:_ctx];
  295     [_response appendContentString:@">\n"];
  296   }
  297 
  298   // generating head
  299   if (hasHeader) {
  300     int width = 7;
  301     if ((hasLeft) || (hasLeftTop) || (hasLeftBottom))
  302       width++;
  303     if ((hasRight) || (hasRightTop) || (hasRightBottom))
  304       width++;
  305 
  306     [_response appendContentString:@"<tr>"];
  307     
  308     _generateCell(self, _response, _ctx, @"header",
  309                   [NSString stringWithFormat:@"%d", width], nil);
  310 
  311     [_response appendContentString:@"</tr>"];
  312   }
  313 
  314   // generating top
  315   if ((hasTop) || (hasLeftTop) || (hasRightTop)) {
  316     [_response appendContentString:@"<tr>"];
  317 
  318     if (hasLeftTop)
  319       _generateCell(self, _response, _ctx, @"left/top", @"--", nil);
  320     else if ((hasLeft) || (hasLeftBottom))
  321       [_response appendContentString:@"<td></td>"];
  322     
  323     if (hasTop) {
  324       unsigned dOW = first; // dayOfWeek
  325       int cnt;
  326       
  327       for (cnt = 0; cnt < 7; cnt++) {
  328         NSString *k;
  329         k = [[NSString alloc] initWithFormat:@"%i", dOW];
  330         _generateCell(self, _response, _ctx, @"top", k, nil);
  331         [k release];
  332         
  333         dOW = (dOW == 6) ? 0 : (dOW + 1);
  334       }
  335     }
  336     else {
  337       [_response appendContentString:
  338                  @"<td></td><td></td><td></td><td></td>"
  339                  @"<td></td><td></td><td></td>"];
  340     }
  341     
  342     if (hasRightTop)
  343       _generateCell(self, _response, _ctx, @"right/top", @"--", nil);
  344     else if (hasRight)
  345       [_response appendContentString:@"<td></td>"]; 
  346 
  347     [_response appendContentString:@"</tr>"];
  348   }
  349   
  350   // generating content
  351   if (count > 0) {
  352     int      cnt;
  353     unsigned dow;
  354     
  355     dow = [day dayOfWeek];
  356 
  357     for (cnt = 0; cnt < count; cnt++) {
  358       // building HTML
  359       // append table row
  360       if (dow == first) {
  361         [_response appendContentString:@"<tr>"];
  362         // generate left border
  363         if (hasLeft) {
  364           NSCalendarDate *tmp;
  365           // jump to the middle of the week
  366           tmp = [day dateByAddingYears:0 months:0 days:3];
  367           
  368           _generateCell(self, _response, _ctx, @"left",
  369                         [NSString stringWithFormat:@"%i", [tmp weekOfYear]],
  370                         nil);
  371         }
  372         else if ((hasLeftTop) || (hasLeftBottom))
  373           [_response appendContentString:@"<td></td>"];
  374       }
  375       
  376       // set values
  377       _applyDate(self, sComponent, day);
  378       
  379       // append child elements
  380       if (hasCell)
  381         _generateCell(self, _response, _ctx, @"cell", @"--", day);
  382       else
  383         [_response appendContentString:@"<td></td>"];
  384       
  385       // next day
  386       day = [day tomorrow];
  387       dow = (dow == 6) ? 0 : (dow + 1);
  388 
  389       // close table row tag
  390       if (dow == first) {
  391         [_response appendContentString:@"</tr>\n"];
  392         // generate right border
  393         if (hasRight) {
  394           _generateCell(self, _response, _ctx, @"right",
  395                         [NSString stringWithFormat:@"%i", [day weekOfYear]],
  396             nil);
  397         }
  398         else if ((hasRightTop) || (hasRightBottom))
  399           [_response appendContentString:@"<td></td>"];
  400       }
  401     }
  402   }
  403 
  404   // generating footer
  405   if ((hasBottom) || (hasLeftBottom) || (hasRightBottom)) {
  406     unsigned dOW = first; // dayOfWeek
  407     int cnt;
  408 
  409     [_response appendContentString:@"<tr>"];
  410 
  411     if (hasLeftBottom)
  412       _generateCell(self, _response, _ctx, @"left/bottom", @"--", nil);
  413     else if ((hasLeft) || (hasLeftTop))
  414       [_response appendContentString:@"<td></td>"];
  415 
  416     if (hasBottom) {
  417       for (cnt = 0; cnt < 7; cnt++) {
  418         _generateCell(self, _response, _ctx, @"bottom",
  419                       [NSString stringWithFormat:@"%i", dOW], nil);
  420         dOW = (dOW == 6) ? 0 : (dOW + 1);
  421       }
  422     }
  423     else {
  424       [_response appendContentString:
  425                  @"<td></td><td></td><td></td><td></td>"
  426                  @"<td></td><td></td><td></td>"];
  427     }
  428 
  429     if (hasRightBottom)
  430       _generateCell(self, _response, _ctx, @"right/bottom", @"--", nil);
  431     else if ((hasRight) || (hasRightTop))
  432       [_response appendContentString:@"<td></td>"]; 
  433 
  434     [_response appendContentString:@"</tr>"];
  435   }
  436 
  437   // close table
  438   if (useTableTags)
  439     [_response appendContentString:@"</table>"];
  440       
  441 }
  442 
  443 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
  444   WOComponent    *sComponent;
  445   unsigned       y, m, first;
  446   unsigned       count = 0;
  447   NSTimeZone     *tz = nil;
  448   NSCalendarDate *day;
  449   
  450   sComponent = [_ctx component];
  451   y  = [self->year unsignedIntValueInComponent:sComponent];
  452   m  = [self->month unsignedIntValueInComponent:sComponent];
  453   tz = [self->timeZone valueInComponent:sComponent];
  454   
  455   first = (self->firstDay) 
  456     ? [self->firstDay unsignedIntValueInComponent:sComponent]
  457     : 1; // Monday
  458 
  459   day = [NSCalendarDate dateWithYear:y month:m day:1
  460                         hour:0 minute:0 second:0 timeZone:tz];
  461 
  462   { // computing last day and following days
  463     unsigned dow;
  464     int dif;
  465 
  466     count = [day numberOfDaysInMonth];
  467 
  468     dow = [[day lastDayOfMonth] dayOfWeek];
  469     dif = first - dow - 1; // overview stopps 1 day before the first weekday
  470                            // --> e.g.: repetition starts monday, ends sunday
  471     dif = (dif < 0) ? dif + 7 : dif;
  472     count += dif;
  473   }
  474 
  475   { // computing leading days
  476     unsigned dow; // dayOfWeek
  477     int dif;
  478 
  479     dow = [day dayOfWeek];
  480 
  481     dif = first - dow;
  482     dif = (dif > 0) ? dif - 7 : dif;
  483 
  484     day   =  [day dateByAddingYears:0 months:0 days:dif];
  485     count -= dif;
  486   }
  487   
  488   /* take values */
  489   
  490   if (count > 0) {
  491     int      cnt;
  492 
  493     for (cnt = 0; cnt < count; cnt++) {
  494       // set values
  495       _applyDate(self, sComponent, day);
  496       
  497       // month cell
  498       _takeValuesInCell(self, _req, _ctx, @"cell", @"--", day);
  499 
  500       // next day
  501       day = [day tomorrow];
  502     }
  503   }
  504 }
  505 
  506 - (id)invokeActionForRequest:(WORequest *)_request inContext:(WOContext *)_ctx{
  507   WOComponent     *sComponent;
  508   id              result = nil;
  509   NSString        *ident;
  510   NSString        *orient;
  511   
  512   sComponent = [_ctx component];
  513   
  514   if ((orient = [_ctx currentElementID]) == nil) {
  515     [[_ctx session]
  516            logWithFormat:@"%@: MISSING ORIENTATION ID in URL !", self];
  517     return nil;
  518   }
  519 
  520   [_ctx consumeElementID];
  521   [_ctx appendElementIDComponent:orient];
  522     
  523   [_ctx takeValue:
  524           [NSDictionary dictionaryWithObjectsAndKeys:
  525           @"--", orient, nil]
  526     forKey:@"SkyMonthRepetition"];
  527 
  528   if (![orient isEqualToString:@"cell"]) {
  529     /* orientation is *not* 'cell' (some label) */
  530     result = [self->template invokeActionForRequest:_request inContext:_ctx];
  531   }
  532   else if ((ident = [_ctx currentElementID])) {
  533     /* orientation is 'cell' */
  534     NSCalendarDate *day;
  535     int ti;
  536     
  537     [_ctx consumeElementID]; // consume date-id
  538     [_ctx appendElementIDComponent:ident];
  539       
  540     ti = [ident intValue];
  541 
  542     // TODO: rewrite for MacOSX
  543     day = [[NSCalendarDate alloc] initWithTimeIntervalSince1970:ti];
  544     day = [day autorelease];
  545     [day setTimeZone:[self->timeZone valueInComponent:sComponent]];
  546     //NSLog(@"made date '%@' from ident '%@'", day, ident);
  547       
  548     // set values
  549     _applyDate(self, sComponent, day);
  550       
  551     result = [self->template invokeActionForRequest:_request inContext:_ctx];
  552       
  553     [_ctx deleteLastElementIDComponent];
  554   }
  555   else {
  556     /* orientation is 'cell' */
  557     [[_ctx session] logWithFormat:@"%@: MISSING DATE ID in 'cell' URL !",self];
  558   }
  559   [_ctx deleteLastElementIDComponent];
  560   
  561   return result;
  562 }
  563 
  564 @end /* SkyMonthRepetition */
  565 
  566 
  567 @implementation SkyMonthLabel
  568 
  569 - (id)initWithName:(NSString *)_name
  570   associations:(NSDictionary*)_config
  571   template:(WOElement *)_t
  572 {
  573   if ((self = [super initWithName:_name associations:_config template:_t])) {
  574     self->orientation = OWGetProperty(_config, @"orientation");
  575     self->dayOfWeek   = OWGetProperty(_config, @"dayOfWeek");
  576     self->weekOfYear  = OWGetProperty(_config, @"weekOfYear");
  577     self->colspan     = OWGetProperty(_config, @"colspan");
  578 
  579     self->template = [_t retain];
  580   }
  581   return self;
  582 }
  583 
  584 - (void)dealloc {
  585   [self->orientation release];
  586   [self->dayOfWeek   release];
  587   [self->weekOfYear  release];
  588   [self->colspan     release];
  589   [self->template    release];
  590   [super dealloc];
  591 }
  592 
  593 /* processing requests */
  594 
  595 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
  596   id tmp;
  597   NSDictionary *op;
  598   NSString     *orient;
  599   BOOL         isEdge;
  600   
  601   orient = [self->orientation valueInComponent:[_ctx component]];
  602   isEdge = [orient rangeOfString:@"/"].length > 0;
  603 
  604   op  = [_ctx objectForKey:@"SkyMonthRepetition"];
  605   if ((tmp = [op objectForKey:orient]) == nil)
  606     return;
  607   
  608   if (!isEdge) {
  609       [_ctx appendElementIDComponent:orient];
  610       [self->template takeValuesFromRequest:_req inContext:_ctx];
  611       [_ctx deleteLastElementIDComponent];
  612   }
  613   else
  614     [self->template takeValuesFromRequest:_req inContext:_ctx];
  615 }
  616 
  617 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
  618   id tmp;
  619   NSDictionary *op;
  620   NSString     *orient;
  621   BOOL         isEdge;
  622   id           result;
  623   
  624   orient = [self->orientation valueInComponent:[_ctx component]];
  625   isEdge = [orient rangeOfString:@"/"].length > 0;
  626 
  627   op  = [_ctx objectForKey:@"SkyMonthRepetition"];
  628   if ((tmp = [op objectForKey:orient]) == nil)
  629     return nil;
  630   
  631   if (isEdge)
  632     return [self->template invokeActionForRequest:_req inContext:_ctx];
  633   
  634   tmp = [_ctx currentElementID];
  635   [_ctx consumeElementID];
  636   [_ctx appendElementIDComponent:tmp];
  637       
  638   if ([orient isEqualToString:@"top"] ||
  639       [orient isEqualToString:@"bottom"]) {
  640     [self->dayOfWeek setIntValue:[tmp intValue] inComponent:[_ctx component]];
  641   }
  642   else if ([orient isEqualToString:@"left"] ||
  643        [orient isEqualToString:@"right"]) {
  644     [self->weekOfYear setIntValue:[tmp intValue] inComponent:[_ctx component]];
  645   }
  646   else if ([orient isEqualToString:@"header"]) {
  647     [self->colspan setIntValue:[tmp intValue] inComponent:[_ctx component]];
  648   }
  649       
  650   result = [self->template invokeActionForRequest:_req inContext:_ctx];
  651 
  652   [_ctx deleteLastElementIDComponent];
  653   return result;
  654 }
  655 
  656 /* response generation */
  657 
  658 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
  659   NSDictionary *op;
  660   id       tmp;
  661   NSString *orient;
  662   BOOL     isEdge;
  663   int      cols = -1;
  664 
  665   orient = [self->orientation valueInComponent:[_ctx component]];
  666   isEdge = [orient rangeOfString:@"/"].length > 0;
  667   
  668   op = [_ctx objectForKey:@"SkyMonthRepetition"];
  669   if ((tmp = [op objectForKey:@"query"])) {
  670     [tmp addObject:orient];
  671   }
  672   else if ((tmp = [op objectForKey:orient])) {
  673     if (!isEdge) {
  674       if ([orient isEqualToString:@"top"] ||
  675           [orient isEqualToString:@"bottom"]) {
  676         [self->dayOfWeek setIntValue:[tmp intValue]
  677              inComponent:[_ctx component]];
  678       }
  679       else if ([orient isEqualToString:@"left"] ||
  680                [orient isEqualToString:@"right"]) {
  681         [self->weekOfYear setIntValue:[tmp intValue]
  682              inComponent:[_ctx component]];
  683       } else if ([orient isEqualToString:@"header"]) {
  684         [self->colspan setIntValue:[tmp intValue]
  685              inComponent:[_ctx component]];
  686         cols = [tmp intValue];
  687       }
  688     }
  689     
  690     [_response appendContentString:@"<td"];
  691 
  692     if (cols != -1) {
  693       NSString *colStr =
  694         [NSString stringWithFormat:@" COLSPAN=\"%d\"", cols];
  695       
  696       [_response appendContentString:colStr];
  697     }
  698     
  699     [self appendExtraAttributesToResponse:_response inContext:_ctx];
  700     [_response appendContentString:@">"];
  701       
  702     if (!isEdge)
  703       [_ctx appendElementIDComponent:[tmp stringValue]];
  704 
  705     [self->template appendToResponse:_response inContext:_ctx];
  706     
  707     if (!isEdge)
  708       [_ctx deleteLastElementIDComponent];
  709 
  710       // close table data tag
  711     [_response appendContentString:@"</td>"];
  712   }
  713 }
  714 
  715 @end /* SkyMonthLabel */
  716 
  717 
  718 @implementation SkyMonthCell
  719 
  720 - (id)initWithName:(NSString *)_name
  721   associations:(NSDictionary*)_config
  722   template:(WOElement *)_t
  723 {
  724   if ((self = [super initWithName:_name associations:_config template:_t])) {
  725     self->template = [_t retain];
  726   }
  727   return self;
  728 }
  729 
  730 - (void)dealloc {
  731   [self->template release];
  732   [super dealloc];
  733 }
  734 
  735 /* processing requests */
  736 
  737 - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
  738   NSDictionary *op;
  739   id tmp;
  740   
  741   op  = [_ctx objectForKey:@"SkyMonthRepetition"];
  742   if ((tmp = [op objectForKey:@"cell"]) != nil)
  743     [self->template takeValuesFromRequest:_req inContext:_ctx];
  744 }
  745 
  746 - (id)invokeActionForRequest:(WORequest *)_req inContext:(WOContext *)_ctx {
  747   NSDictionary *op;
  748   id tmp;
  749   
  750   op  = [_ctx objectForKey:@"SkyMonthRepetition"];
  751   if ((tmp = [op objectForKey:@"cell"]) == nil)
  752     return nil;
  753 
  754   return [self->template invokeActionForRequest:_req inContext:_ctx];
  755 }
  756 
  757 /* generating response */
  758 
  759 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
  760   NSDictionary *op;
  761   id tmp;
  762   
  763   op = [_ctx objectForKey:@"SkyMonthRepetition"];
  764   if ((tmp = [op objectForKey:@"query"])) {
  765     [tmp addObject:@"cell"];
  766     return;
  767   }
  768   
  769   if ((tmp = [op objectForKey:@"cell"])) {
  770     // append table date, forwarding extra attributes
  771     [_response appendContentString:@"<td"];
  772     [self appendExtraAttributesToResponse:_response inContext:_ctx];
  773     [_response appendContentString:@">"];
  774     // append child
  775     [self->template appendToResponse:_response inContext:_ctx];
  776     // close table data tag
  777     [_response appendContentString:@"</td>"];
  778   }
  779 }
  780 
  781 @end /* SkyMonthCell */