home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.1 (Developer) [x86] / NeXT Step 3.1 Intel dev.cdr.dmg / NextDeveloper / Examples / IndexingKit / ToDoList / CalendarView.m < prev    next >
Encoding:
Text File  |  1993-02-16  |  15.3 KB  |  653 lines

  1. /*
  2. CalendarView.m - Copyright (c) 1992 NeXT Computer, Inc.
  3.  
  4. You may freely copy, distribute and reuse the code in this example.
  5. NeXT Computer, Inc. disclaims any warranty of any kind, expressed or implied, 
  6. as to its fitness for any particular use.
  7. */
  8.  
  9. #import    <ansi/ansi.h>
  10. #import    <bsd/libc.h>
  11. #import <appkit/appkit.h> 
  12. #import <dpsclient/psops.h> 
  13. #import "CalendarView.h"
  14.  
  15. #define NROWS        6
  16. #define NCOLS        7
  17. #define VIEW_BORDER    3.0
  18. #define CELL_SPACE    0.0 /* 2 */
  19. #define ITEM_SPACE    2.0
  20. #define TEXT_OFFSET    5.0
  21. #define YEAR_RANGE    10
  22. #define BACK_YEARS    3
  23.  
  24. static char *monthStrings[] = { 
  25.     "January", "February", "March", "April", "May", "June",
  26.     "July", "August", "September", "October", "November", "December" };
  27.     
  28. static char *dayStrings[] = { 
  29.     "S", "M", "T", "W", "T", "F","S" };
  30.     
  31. static char *dayNumStrings[] = { 
  32.     "1", "2", "3", "4", "5", "6","7","8","9","10",
  33.     "11", "12", "13", "14", "15", "16","17","18","19","20",
  34.     "21", "22", "23", "24", "25", "26","27","28","29","30",
  35.         "31" };
  36.  
  37. char        myTimeZone[10];
  38.  
  39. /* compare two times of hh:mm for a <= b */
  40. int timeLessThanOrEqual(lhour, ghour, lmin, gmin)
  41.     int    lhour;
  42.     int    ghour;
  43.     int    lmin;
  44.     int    gmin;
  45. {
  46.     if (lhour > ghour)
  47.     return FALSE;
  48.     if ((lhour == ghour) && (lmin > gmin))
  49.     return FALSE;
  50.     return TRUE;
  51. }
  52.  
  53. int    todayDay()
  54. {
  55.     time_t    t;
  56.     struct tm    *tp;
  57.     
  58.     time(&t);
  59.     tp = localtime(&t);
  60.     return (tp->tm_mday);
  61. }
  62.  
  63. int isToday(year, month, day)
  64.     int year;
  65.     int month;
  66.     int day;
  67. {
  68.     time_t    t;
  69.     struct tm    *tp;
  70.     
  71.     year -= 1900;
  72.     month--;
  73.     time(&t);
  74.     tp = localtime(&t);
  75.     if ((year == tp->tm_year) && (month == tp->tm_mon) && (day == tp->tm_mday)) {
  76.     return (1);
  77.     } else {
  78.     return (0);
  79.     }
  80.     return (tp->tm_mday);
  81.  
  82. }
  83.  
  84. int isThisMonthAndYear(year, month)
  85.     int year;
  86.     int month;
  87. {
  88.     time_t    t;
  89.     struct tm    *tp;
  90.     
  91.     year -= 1900;
  92.     month--;
  93.     time(&t);
  94.     tp = localtime(&t);
  95.     if ((year == tp->tm_year) && (month == tp->tm_mon)) {
  96.     return (1);
  97.     } else {
  98.     return (0);
  99.     }
  100.     return (tp->tm_mday);
  101.  
  102. }
  103.  
  104. void copyTime(dest, destZone, source)
  105.     struct tm    *dest;
  106.     char    *destZone;
  107.     struct tm    *source;
  108. {
  109.     dest->tm_sec    = source->tm_sec;
  110.     dest->tm_min    = source->tm_min;
  111.     dest->tm_hour   = source->tm_hour;
  112.     dest->tm_mday   = source->tm_mday;
  113.     dest->tm_mon    = source->tm_mon;
  114.     dest->tm_year   = source->tm_year;
  115.     dest->tm_wday   = source->tm_wday;
  116.     dest->tm_yday   = source->tm_yday;
  117.     dest->tm_isdst  = source->tm_isdst;
  118.     dest->tm_gmtoff = source->tm_gmtoff;
  119.     if (source->tm_zone != NULL)
  120.     strcpy(destZone, source->tm_zone);
  121.     dest->tm_zone = destZone;
  122. }
  123.     
  124. time_t myMakeTime(ntp)
  125.     struct tm    *ntp;
  126. {
  127.     time_t    t;
  128.     struct tm    *tp;
  129.     int        saveHour;
  130.     
  131.     saveHour = ntp->tm_hour;
  132.     t = mktime(ntp);
  133.     tp = localtime(&t);
  134.     copyTime(ntp, myTimeZone, tp);
  135.     ntp->tm_hour = saveHour;
  136.     t = mktime(ntp);
  137.     tp = localtime(&t);
  138.     copyTime(ntp, myTimeZone, tp);
  139.     return t;
  140. }
  141.  
  142. void getTime(ntp)
  143.     struct tm    *ntp;
  144. {
  145.     time_t    t;
  146.     struct tm    *tp;
  147.     
  148.     time(&t);
  149.     tp = localtime(&t);
  150.     copyTime(ntp, myTimeZone, tp);
  151. }
  152.  
  153. void myLocalTime(ntp, t)
  154.     struct tm    *ntp;
  155.     time_t    *t;
  156. {
  157.     struct tm    *tp;
  158.     
  159.     tp = localtime(t);
  160.     copyTime(ntp, myTimeZone, tp);
  161. }
  162.  
  163. int weekDayOfFirstDayOfMonth(ntp)
  164.     struct tm    *ntp;
  165. {
  166.     struct tm    *tp;
  167.     time_t    t;
  168.     struct tm    mt;
  169.     char    tz[10];
  170.     
  171.     copyTime(&mt, tz, ntp); 
  172.     mt.tm_mday = 1;   
  173.     mt.tm_hour = 8;   
  174.     t = mktime(&mt);
  175.     tp = localtime(&t);
  176.     return tp->tm_wday;
  177. }
  178.                
  179. @interface LabelCell:Cell
  180. {
  181. }
  182. - drawSelf:(NXRect const *)r inView:controlView;
  183. @end
  184.  
  185. @implementation LabelCell
  186.  
  187. - drawInside:(NXRect const *)r inView:controlView
  188. {
  189.     float    w;
  190.     
  191.     w = [support    getWidthOf:contents];
  192.     [support    set];
  193.     PSmoveto(r->origin.x + r->size.width/2.0 - w/2.0, r->size.height - TEXT_OFFSET);
  194.     if (cFlags1.state)
  195.     PSsetgray(NX_DKGRAY);
  196.     else
  197.     PSsetgray(NX_BLACK);
  198.     PSshow(contents);
  199.     return self;
  200. }
  201.  
  202. - drawSelf:(NXRect const *)r inView:controlView
  203. {
  204.     [self    drawInside:r inView:controlView];
  205.     return self;
  206. }
  207.  
  208. @end
  209.  
  210. @interface DayCell:Cell
  211. {
  212.     BOOL        isDimmed;
  213. }
  214.  
  215. - drawSelf:(NXRect const *)r inView:controlView;
  216. - setDimmed:(BOOL)theValue;
  217.  
  218. @end
  219.  
  220. @implementation DayCell
  221.  
  222. - setDimmed:(BOOL)theValue
  223. {
  224.     isDimmed = theValue;
  225.     return self;
  226. }
  227.  
  228. - drawInside:(NXRect const *)r inView:controlView
  229. {
  230.     float    w;
  231.     
  232.     if (cFlags1.disabled) {
  233.     NXDrawGrayBezel(r, r);
  234.     } else {
  235.     NXDrawWhiteBezel(r, r);
  236.     if (cFlags1.highlighted  || cFlags1.state)
  237.         NXHighlightRect(r);
  238.     w = [support    getWidthOf:contents];
  239.     [support    set];
  240.     PSmoveto(/* X */ r->origin.x + r->size.width/2.0 - w/2.0,
  241.           /* Y */ r->origin.y + r->size.height - TEXT_OFFSET);
  242.     if (isDimmed)
  243.         PSsetgray(NX_DKGRAY);
  244.     else
  245.         PSsetgray(NX_BLACK);
  246.     PSshow(contents);
  247.     }
  248.     return self;
  249. }
  250.  
  251. - drawSelf:(NXRect const *)r inView:controlView
  252. {
  253.     [self    drawInside:r inView:controlView];
  254.     return self;
  255. }
  256.  
  257. - highlight:(NXRect const *)r inView:controlView lit:(BOOL)flag
  258. {
  259.     if (cFlags1.highlighted != flag) {
  260.     cFlags1.highlighted = flag;
  261.     if (!flag && cFlags1.state)
  262.         return self;
  263.     NXHighlightRect(r);
  264.     }
  265.     return self;
  266. }
  267.  
  268. - read:(NXTypedStream*)s
  269. {
  270.     [super    read:s];
  271.     NXReadTypes(s,"i", &isDimmed);
  272.     return self;    
  273. }
  274.  
  275. - write:(NXTypedStream*)s
  276. {
  277.     [super    write:s];
  278.     NXWriteTypes(s,"i", &isDimmed);
  279.     return self;    
  280. }
  281.  
  282. @end
  283.  
  284. @implementation CalendarView
  285.  
  286. - initFrame:(NXRect const *)r
  287. {
  288.     NXRect    matrixRect;
  289.     NXSize    size;
  290.     int        i;
  291.     char    buf[10];
  292.     float    pos;
  293.     id        theCell;
  294.     
  295.     [super    initFrame:r];
  296.     matrixRect = *r;
  297.     viewRect   = *r;
  298.     matrixRect.size.height -= VIEW_BORDER * 2;
  299.     matrixRect.size.width -= VIEW_BORDER * 2;
  300.     cellSize.width  = floor((matrixRect.size.width - (CELL_SPACE * (NCOLS-1)))  / NCOLS);
  301.     cellSize.height = floor((matrixRect.size.height  - (CELL_SPACE * (NCOLS-1))) / (NROWS+2));
  302.     matrixRect.size.width   = cellSize.width * NCOLS;
  303.     matrixRect.size.height  = NROWS * cellSize.height;
  304.     //[self    sizeTo:matrixRect.size.width + (2 * VIEW_BORDER) :r->size.height];
  305.     bounds.size.width = matrixRect.size.width + (2 * VIEW_BORDER);
  306.     bounds.size.height = r->size.height;
  307.     frame.size.width = matrixRect.size.width + (2 * VIEW_BORDER);
  308.     frame.size.height = r->size.height;
  309.     viewRect = bounds;
  310.     
  311.     monthMatrix    = [[Matrix    alloc] initFrame:&matrixRect 
  312.                         mode:NX_RADIOMODE
  313.             cellClass:[DayCell    class] 
  314.             numRows:NROWS 
  315.             numCols:NCOLS];
  316.     size.width  = CELL_SPACE;
  317.     size.height = CELL_SPACE;
  318.     [monthMatrix    setBackgroundGray:NX_BLACK];
  319.     [monthMatrix    setIntercell:&size];
  320.     [monthMatrix    setCellSize:&cellSize];
  321.     [monthMatrix    setEmptySelectionEnabled:NO];
  322.     [self        addSubview:monthMatrix];
  323.     [monthMatrix    moveTo:VIEW_BORDER:VIEW_BORDER];
  324.     [monthMatrix    setTarget:self];
  325.     [monthMatrix    setAction:@selector(dayChanged:)];
  326.     
  327.     
  328.     monthPl = [[PopUpList alloc] init];
  329.     for (i = 0; i<12; i++) {
  330.      [monthPl    addItem:monthStrings[i]];
  331.     }
  332.     monthButton = NXCreatePopUpListButton(monthPl);
  333.     [self    addSubview:monthButton];
  334.     [monthPl    setTarget:self];
  335.     [monthPl    setAction:@selector(dateChanged:)];
  336.                   
  337.     getTime(&theTime);
  338.     yearPl = [[PopUpList alloc] init];
  339.     yearBase = theTime.tm_year - BACK_YEARS;
  340.     for (i = 0; i<YEAR_RANGE; i++) {
  341.         sprintf(buf, "%d", theTime.tm_year+1900+i-BACK_YEARS);
  342.      [yearPl    addItem:buf];
  343.     }
  344.     yearButton = NXCreatePopUpListButton(yearPl);
  345.     [self    addSubview:yearButton];
  346.     [yearPl    setTarget:self];
  347.     [yearPl    setAction:@selector(dateChanged:)];
  348.     [self    setFonts];
  349.     [self    setupButtons];
  350.     sprintf(buf, "%d", theTime.tm_year+1900);
  351.     [yearButton    setTitle:buf];
  352.     
  353.     pos = matrixRect.size.height;
  354.     matrixRect.size.height = cellSize.height - (2 * ITEM_SPACE) - VIEW_BORDER; 
  355.     dayLabelMatrix    = [[Matrix alloc]    initFrame:&matrixRect  
  356.                         mode:NX_TRACKMODE
  357.             cellClass:[LabelCell    class] 
  358.             numRows:1 
  359.             numCols:NCOLS];
  360.     size.width  = CELL_SPACE;
  361.     size.height = CELL_SPACE;
  362.     [dayLabelMatrix     setBackgroundGray:NX_LTGRAY];
  363.     [dayLabelMatrix     setIntercell:&size];
  364.     size.width  = cellSize.width;
  365.     size.height = matrixRect.size.height;
  366.     [dayLabelMatrix    setCellSize:&size];
  367.     [self        addSubview:dayLabelMatrix];
  368.     [dayLabelMatrix    moveTo:VIEW_BORDER :pos + ITEM_SPACE + VIEW_BORDER];
  369.     for (i = 0; i<NCOLS; i++) {
  370.     theCell = [dayLabelMatrix    cellAt:0:i];
  371.         [theCell    setStringValue:dayStrings[i]];
  372.         [theCell    setFont:buttonFont];
  373.     [theCell    setState:(((i == 0) || (i == 6)) ? 1 : 0)];
  374.     }
  375.     [monthButton    setTitle:monthStrings[theTime.tm_mon]];
  376.     [self    loadMatrix];
  377.     useDelegate = NO;
  378.     return self;
  379. }
  380.  
  381. - setDelegate:anObject
  382. {
  383.     delegate = anObject;
  384.     useDelegate = YES;
  385.     return self;
  386. }
  387.  
  388. - setDoDelegate:anObject
  389. {
  390.     delegate = anObject;
  391.     return self;
  392. }
  393.  
  394. -(BOOL)useDelegate
  395. {
  396.     return (useDelegate);
  397. }
  398.  
  399. /*
  400. ** Check for correct view type and to see of delegate outlet not yet set.
  401. ** If so check for object in responder chain the responds to takeStringFrom:
  402. ** and set that object as our delegate.  However of the object has a superview
  403. ** that is of type CalendarView do not set delegate. 
  404. */ 
  405. - (BOOL)acceptsFirstResponder
  406. {
  407.     id    temp;
  408.     
  409.     if ([self    useDelegate] == YES) {
  410.     return NO;
  411.     }
  412.     
  413.     temp = [window    firstResponder];
  414.     while (temp) {
  415.     if ([temp    respondsTo:@selector(takeStringValueFrom:)]) {
  416.         [self    setDoDelegate:temp];
  417.         temp = nil;
  418.     } else {
  419.         temp = [temp    nextResponder];
  420.     }
  421.     }
  422.     return YES;
  423. }
  424.  
  425. - setFonts
  426. {
  427.     int    i;
  428.     
  429.     if (cellFont == NULL) {
  430.     [cellFont    free];
  431.     [buttonFont    free];
  432.     }
  433.     cellFont = [Font    newFont:"Helvetica"
  434.                         size: (((MIN(cellSize.width, cellSize.height) 
  435.                    - (TEXT_OFFSET * 2)) /2.0) * 2.0) 
  436.             style:0 
  437.             matrix:NX_FLIPPEDMATRIX];
  438.     buttonFont = [Font    newFont:"Helvetica-Bold"
  439.                         size: (((MIN(cellSize.width, cellSize.height) 
  440.                    - (TEXT_OFFSET * 2)) /2.0) * 2.0) 
  441.             style:0 
  442.             matrix:NX_FLIPPEDMATRIX];
  443.     for (i = 0; i < NCOLS; i++)
  444.     [[dayLabelMatrix    cellAt:0:i]    setFont:buttonFont];
  445.     return self;
  446. }
  447.  
  448. - setupButtons
  449. {
  450.     NXRect    f;
  451.     char    buf[20];
  452.     
  453.     strcpy(buf, [monthButton    title]);
  454.     [monthButton    setTitle:"0000000001"];
  455.     [monthButton    setFont:buttonFont];
  456.     [monthPl        setFont:buttonFont];
  457.     [monthButton    sizeToFit];
  458.     [monthButton    setTitle:buf];
  459.     [monthButton    getFrame:&f];
  460.     [monthButton    moveTo:VIEW_BORDER+ITEM_SPACE 
  461.                   :viewRect.size.height - f.size.height - VIEW_BORDER - ITEM_SPACE];
  462.     strcpy(buf, [yearButton    title]);
  463.     [yearButton    setTitle:"00001"];
  464.     [yearButton        setFont:buttonFont];
  465.     [yearPl        setFont:buttonFont];
  466.     [yearButton        sizeToFit];
  467.     [yearButton        setTitle:buf];
  468.     [yearButton        getFrame:&f];
  469.     [yearButton        moveTo:viewRect.size.width - f.size.width - VIEW_BORDER - ITEM_SPACE 
  470.                       :viewRect.size.height - f.size.height - VIEW_BORDER - ITEM_SPACE];
  471.     return self;
  472. }
  473.  
  474. - drawSelf:(const NXRect *)rects :(int)rectCount
  475. {
  476.     PSsetgray(NX_DKGRAY);
  477.     NXRectFill(rects);
  478.     NXDrawGroove(rects, rects);
  479.     return self;
  480. }
  481.  
  482. int lastDay(month, year)
  483.     int    month;
  484.     int    year;
  485. {
  486.     switch (month) {
  487.         case 1:
  488.         if (((year % 4) == 0) && ((year % 400) != 0))
  489.             return 29;
  490.         else
  491.             return 28;
  492.     case 3:
  493.     case 5:
  494.     case 8:
  495.     case 10:
  496.         return 30;
  497.     default:
  498.         return 31;
  499.     }
  500. }
  501.  
  502. - loadMatrix
  503. {
  504.     int        row;
  505.     int        col;
  506.     int        fDay;
  507.     int        lDay;
  508.     int        day = 0;
  509.     int        passedFirstDay = FALSE;
  510.     id        theCell;
  511.  
  512.     fDay = weekDayOfFirstDayOfMonth(&theTime);
  513.     lDay = lastDay(theTime.tm_mon, theTime.tm_year);
  514.     for (row = 0; row < NROWS; row++) {
  515.     for (col = 0; col < NCOLS; col++) {
  516.         theCell = [monthMatrix    cellAt:row:col];
  517.         if ((col == fDay) && (!passedFirstDay))
  518.         passedFirstDay = TRUE;
  519.         [theCell    setDimmed:(((col == 0) || (col == 6)) ? YES : NO)];
  520.         if ((passedFirstDay) && (day < lDay)) {
  521.         [theCell    setEnabled:YES];
  522.         [theCell    setStringValue:dayNumStrings[day++]];
  523.         [theCell    setFont:cellFont];
  524.         if (day == theTime.tm_mday)
  525.             [monthMatrix    selectCellAt:row:col];    
  526.         } else {
  527.         [theCell    setEnabled:NO];
  528.         }
  529.     }
  530.     }
  531.     [monthMatrix    display];
  532.     return self;
  533. }
  534.  
  535. - (const char *)stringValue
  536. {
  537.     strftime(tbuf, 50, "%d-%B-%Y", &theTime);
  538.     return (tbuf);
  539. }
  540.  
  541. - dateChanged:sender
  542. {
  543.     int        lDay;
  544.     int        temp;
  545.     
  546.     temp = [monthPl    indexOfItem:[monthPl    selectedItem]];
  547.     if (temp != -1)
  548.     theTime.tm_mon = temp;
  549.     temp = [yearPl    indexOfItem:[yearPl    selectedItem]];
  550.     if (temp != -1)
  551.     theTime.tm_year = temp + yearBase;
  552.     lDay = lastDay(theTime.tm_mon, theTime.tm_year);
  553.     if (theTime.tm_mday > lDay) 
  554.     theTime.tm_mday = lDay;
  555.     
  556.     t = myMakeTime(&theTime);
  557.     [self    loadMatrix];
  558.     if (useDelegate == YES) {
  559.     if ([delegate    respondsTo:sel_getUid("dateDidChange:")])
  560.         [delegate    perform:sel_getUid("dateDidChange:") with:self];
  561.     } else {
  562.     [delegate    takeStringValueFrom:self];
  563.     }
  564.     return self;
  565. }
  566.  
  567. - dayChanged:sender
  568. {
  569.     theTime.tm_mday = [[monthMatrix    selectedCell]    intValue];
  570.     t = myMakeTime(&theTime);
  571.     if (useDelegate == YES) {
  572.     if ([delegate    respondsTo:sel_getUid("dateDidChange:")])
  573.         [delegate    perform:sel_getUid("dateDidChange:") with:self];
  574.     } else {
  575.     [delegate    takeStringValueFrom:self];
  576.     }
  577.     return self;
  578. }
  579.  
  580. - (struct tm *)currentDate
  581. {
  582.     return (&theTime);
  583. }
  584.  
  585. - setCurrentDate:(struct tm *)theDate
  586. {
  587.     char    buf[20];
  588.     
  589.     if (![self canDraw])
  590.     return self;
  591.     if (theDate->tm_year >= (yearBase + YEAR_RANGE)) {
  592.     NXRunAlertPanel("Alert",  "Year is out of range in setCurrentDate", 0, 0, 0);    
  593.     return self;
  594.     }
  595.     copyTime(&theTime, timeZone, *theDate);
  596.     [monthButton    setTitle:monthStrings[theTime.tm_mon]];
  597.     sprintf(buf, "%d", theTime.tm_year+1900);
  598.     [yearButton        setTitle:buf];
  599.     [self        loadMatrix];
  600.     return self;
  601. }
  602.  
  603. - sizeTo:(NXCoord)width :(NXCoord)height
  604. {
  605.     NXSize    matrixSize;
  606.     NXSize    size;
  607.     float    pos;
  608.     
  609.     matrixSize.height = height  - (VIEW_BORDER * 2);
  610.     matrixSize.width =  width - (VIEW_BORDER * 2);
  611.     cellSize.width  = floor((matrixSize.width - (CELL_SPACE * (NCOLS-1)))  / NCOLS);
  612.     cellSize.height = floor((matrixSize.height  - (CELL_SPACE * (NCOLS-1))) / (NROWS+2));
  613.     matrixSize.width   = cellSize.width * NCOLS;
  614.     matrixSize.height  = NROWS * cellSize.height;
  615.     [super    sizeTo:matrixSize.width + (2 * VIEW_BORDER) :height];
  616.     viewRect = bounds;
  617.     [monthMatrix    setCellSize:&cellSize];
  618.     [monthMatrix    moveTo:VIEW_BORDER:VIEW_BORDER];
  619.     [monthMatrix    sizeTo:matrixSize.width :matrixSize.height]; 
  620.     
  621.     pos = matrixSize.height;
  622.     matrixSize.height = cellSize.height - (2 * ITEM_SPACE) - VIEW_BORDER; 
  623.     size.width  = cellSize.width;
  624.     size.height = matrixSize.height;
  625.     [dayLabelMatrix    setCellSize:&size];
  626.     [dayLabelMatrix    moveTo:VIEW_BORDER :pos + ITEM_SPACE + VIEW_BORDER];
  627.     [dayLabelMatrix    sizeTo:matrixSize.width :matrixSize.height]; 
  628.     [self    setFonts];
  629.     [self    setupButtons];
  630.     [self    loadMatrix];
  631.     return self;
  632. }
  633.  
  634. - read:(NXTypedStream*)s
  635. {
  636.     [super    read:s];
  637.     NXReadTypes(s,"@@@@@@@@@i", &delegate, &monthButton, &monthPl, &yearButton, &yearPl, &monthMatrix, &dayLabelMatrix, &cellFont, &buttonFont, &useDelegate);
  638.     getTime(&theTime);
  639.     yearBase = theTime.tm_year - BACK_YEARS;
  640.     [self    setCurrentDate:&theTime];
  641.     return self;    
  642. }
  643.  
  644. - write:(NXTypedStream*)s
  645. {
  646.     [super    write:s];
  647.     NXWriteTypes(s,"@@@@@@@@@i", &delegate, &monthButton, &monthPl, &yearButton, &yearPl, &monthMatrix, &dayLabelMatrix, &cellFont, &buttonFont, &useDelegate);
  648.     return self;    
  649. }
  650.  
  651.  
  652. @end
  653.