revert between 56095 -> 55830 in arch
[AROS.git] / workbench / classes / zune / calendar / calendar.c
blobe9fa9071d741cb8abc642eb9b7609346309f585a
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <utility/date.h>
7 #include <libraries/mui.h>
9 #include <proto/alib.h>
10 #include <proto/muimaster.h>
11 #include <proto/graphics.h>
12 #include <proto/intuition.h>
13 #include <proto/utility.h>
14 #include <proto/locale.h>
15 #include <proto/timer.h>
17 #include <aros/debug.h>
18 #include <aros/asmcall.h>
20 #include <string.h>
21 #include <stdio.h>
23 #include "calendar.h"
24 #include "calendar_private.h"
26 #define CELL_EXTRAWIDTH 6
27 #define CELL_EXTRAHEIGHT 4
29 STRPTR def_daylabels[] =
31 "Sun",
32 "Mon",
33 "Tue",
34 "Wed",
35 "Thu",
36 "Fri",
37 "Sat"
40 /*** Methods ****************************************************************/
42 IPTR Calendar__OM_NEW(Class *cl, Object *obj, struct opSet *msg)
44 struct Calendar_DATA *data;
45 struct TagItem *ti;
47 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
48 if (!obj) return 0;
50 data = INST_DATA(cl, obj);
52 data->daylabels = (CONST_STRPTR *)GetTagData(MUIA_Calendar_DayLabels, 0, msg->ops_AttrList);
53 if (!data->daylabels)
55 struct Locale *locale;
56 WORD i;
58 locale = LocaleBase ? OpenLocale(NULL) : NULL;
60 data->daylabels = data->defdaylabels;
61 for(i = 0; i < 7; i++)
63 if (locale)
65 data->defdaylabels[i] = GetLocaleStr(locale, ABDAY_1 + i);
66 data->firstweekday = locale->loc_CalendarType;
68 else
70 data->defdaylabels[i] = def_daylabels[i];
71 data->firstweekday = 0;
75 if (locale) CloseLocale(locale);
78 if ((ti = FindTagItem(MUIA_Calendar_Date, msg->ops_AttrList)))
80 struct ClockData *cd = (struct ClockData *)ti->ti_Data;
82 data->clockdata = *cd;
84 else
86 struct timeval tv;
88 GetSysTime(&tv);
89 Amiga2Date(tv.tv_secs, &data->clockdata);
92 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY;
93 data->ehn.ehn_Priority = 0;
94 data->ehn.ehn_Flags = 0;
95 data->ehn.ehn_Object = obj;
96 data->ehn.ehn_Class = cl;
98 return (IPTR)obj;
102 IPTR Calendar__OM_DISPOSE(Class *cl, Object *obj, Msg msg)
104 return DoSuperMethodA(cl, obj, msg);
107 LONG NumMonthDays(struct ClockData *cd)
109 struct ClockData cd2;
110 ULONG secs;
111 LONG monthday = 28;
113 cd2 = *cd;
115 while(monthday < 32)
117 cd2.mday = monthday;
119 secs = Date2Amiga(&cd2);
120 secs += 24 * 60 * 60; /* day++ */
122 Amiga2Date(secs, &cd2);
124 if (cd2.month != cd->month) break;
126 monthday++;
129 return monthday;
132 IPTR Calendar__OM_SET(Class *cl, Object *obj, struct opSet *msg)
134 struct Calendar_DATA *data = INST_DATA(cl, obj);
135 struct ClockData old_clockdata;
136 struct TagItem *tags = msg->ops_AttrList;
137 struct TagItem *tag;
138 BOOL redraw = FALSE;
140 old_clockdata = data->clockdata;
142 while ((tag = NextTagItem(&tags)) != NULL)
144 switch(tag->ti_Tag)
146 case MUIA_Calendar_Date:
147 data->clockdata = *(struct ClockData *)tag->ti_Data;
148 redraw = TRUE;
149 break;
151 case MUIA_Calendar_Year:
152 data->clockdata.year = tag->ti_Data;
153 redraw = TRUE;
154 break;
156 case MUIA_Calendar_Month:
157 data->clockdata.month = tag->ti_Data;
158 redraw = TRUE;
159 break;
161 case MUIA_Calendar_Month0:
162 data->clockdata.month = tag->ti_Data + 1;
163 redraw = TRUE;
164 break;
166 case MUIA_Calendar_MonthDay:
167 data->clockdata.mday = tag->ti_Data;
168 redraw = TRUE;
169 break;
171 case MUIA_Calendar_MonthDay0:
172 data->clockdata.mday = tag->ti_Data + 1;
173 redraw = TRUE;
174 break;
176 } /* switch(tag->ti_Tag) */
178 } /* while ((tag = NextTagItem(&tags)) != NULL) */
180 if (redraw)
182 struct ClockData cd2;
183 ULONG secs;
185 cd2 = data->clockdata;
186 cd2.mday = 1;
188 if (data->clockdata.mday > NumMonthDays(&cd2))
190 data->clockdata.mday = NumMonthDays(&cd2);
193 secs = Date2Amiga(&data->clockdata);
195 Amiga2Date(secs, &data->clockdata);
197 if ((data->clockdata.year != old_clockdata.year) ||
198 (data->clockdata.month != old_clockdata.month) ||
199 (data->clockdata.mday != old_clockdata.mday))
201 if ((data->clockdata.year == old_clockdata.year) &&
202 (data->clockdata.month == old_clockdata.month))
204 data->old_mday = old_clockdata.mday;
206 MUI_Redraw(obj, MADF_DRAWUPDATE);
207 data->old_mday = 0;
211 return DoSuperMethodA(cl, obj, (Msg)msg);
215 IPTR Calendar__OM_GET(Class *cl, Object *obj, struct opGet *msg)
217 struct Calendar_DATA *data = INST_DATA(cl, obj);
218 IPTR retval = TRUE;
220 switch(msg->opg_AttrID)
222 case MUIA_Calendar_Date:
223 *(struct ClockData **)msg->opg_Storage = &data->clockdata;
224 break;
226 case MUIA_Calendar_MonthDay:
227 *msg->opg_Storage = data->clockdata.mday;
228 break;
230 case MUIA_Calendar_MonthDay0:
231 *msg->opg_Storage = data->clockdata.mday - 1;
232 break;
234 case MUIA_Calendar_Month:
235 *msg->opg_Storage = data->clockdata.month;
236 break;
238 case MUIA_Calendar_Month0:
239 *msg->opg_Storage = data->clockdata.month - 1;
240 break;
242 case MUIA_Calendar_Year:
243 *msg->opg_Storage = data->clockdata.year;
244 break;
246 default:
247 retval = DoSuperMethodA(cl, obj, (Msg)msg);
248 break;
252 return retval;
256 IPTR Calendar__MUIM_Setup(Class *cl, Object *obj, struct MUIP_Setup *msg)
258 struct Calendar_DATA *data = INST_DATA(cl, obj);
259 struct RastPort rp;
260 WORD i, w;
262 if (!DoSuperMethodA(cl, obj, (Msg)msg)) return FALSE;
264 InitRastPort(&rp);
265 SetFont(&rp, _font(obj));
267 data->cellheight = _font(obj)->tf_YSize + CELL_EXTRAHEIGHT;
269 SetSoftStyle(&rp, FSF_BOLD, AskSoftStyle(&rp));
271 for(i = 0; i < 7; i++)
273 w = TextLength(&rp, data->daylabels[i], strlen(data->daylabels[i]));
274 if (w > data->cellwidth) data->cellwidth = w;
277 SetSoftStyle(&rp, FS_NORMAL, AskSoftStyle(&rp));
279 for(i = 1; i <= 31; i++)
281 char s[3];
283 sprintf(s, "%d", i);
285 w = TextLength(&rp, s, strlen(s));
286 if (w > data->cellwidth) data->cellwidth = w;
289 data->cellwidth += CELL_EXTRAWIDTH;
291 data->base_cellwidth = data->cellwidth;
292 data->base_cellheight = data->cellheight;
294 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR) &data->ehn);
296 return TRUE;
300 IPTR Calendar__MUIM_Cleanup(Class *cl, Object *obj, struct MUIP_Cleanup *msg)
302 struct Calendar_DATA *data = INST_DATA(cl, obj);
304 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR) &data->ehn);
306 return DoSuperMethodA(cl, obj, (Msg)msg);
310 IPTR Calendar__MUIM_AskMinMax(Class *cl, Object *obj, struct MUIP_AskMinMax *msg)
312 struct Calendar_DATA *data = INST_DATA(cl, obj);
314 DoSuperMethodA(cl, obj, (Msg)msg);
316 msg->MinMaxInfo->MinWidth += data->cellwidth * 7 + 2;
317 msg->MinMaxInfo->MinHeight += data->cellheight * 7 + 1;
318 msg->MinMaxInfo->DefWidth += data->cellwidth * 7 + 2;
319 msg->MinMaxInfo->DefHeight += data->cellheight * 7 + 1;
320 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
321 msg->MinMaxInfo->MaxHeight = MUI_MAXMAX;
324 return TRUE;
328 IPTR Calendar__MUIM_Draw(Class *cl, Object *obj, struct MUIP_Draw *msg)
330 struct Calendar_DATA *data = INST_DATA(cl, obj);
331 struct Region *region;
332 struct Rectangle rect;
333 APTR clip = NULL;
334 WORD x, y, offx, offy, day, mdays;
336 x = (_mwidth(obj) - 2) / 7;
337 y = x * data->base_cellheight / data->base_cellwidth;
339 data->cellheight = (_mheight(obj) - 1) / 7;
340 data->cellwidth = data->cellheight * data->base_cellwidth / data->base_cellheight;
342 if ((data->cellwidth > x) || (data->cellheight > y))
344 data->cellwidth = x;
345 data->cellheight = y;
348 offx = _mleft(obj) + (_mwidth(obj) - data->cellwidth * 7 - 2) / 2 + 1;
349 offy = _mtop(obj) + (_mheight(obj) - data->cellheight * 7 - 1) / 2;
351 region = NewRegion();
352 if (region)
354 rect.MinX = _left(obj);
355 rect.MinY = _top(obj);
356 rect.MaxX = _right(obj);
357 rect.MaxY = _bottom(obj);
359 OrRectRegion(region, &rect);
361 rect.MinX = offx - 1;
362 rect.MinY = offy;
363 rect.MaxX = offx + data->cellwidth * 7;
364 rect.MaxY = offy + data->cellheight * 7;
366 ClearRectRegion(region, &rect);
368 clip = MUI_AddClipRegion(muiRenderInfo(obj), region);
371 DoSuperMethodA(cl, obj, (Msg)msg);
373 if (region)
375 MUI_RemoveClipRegion(muiRenderInfo(obj), clip);
378 if (!(msg->flags & (MADF_DRAWOBJECT | MADF_DRAWUPDATE))) return 0;
380 data->mwday =
381 (data->clockdata.wday - (data->clockdata.mday - 1) % 7 + 7) % 7;
383 mdays = NumMonthDays(&data->clockdata);
385 //kprintf("actdate = %d.%d.%d wday = %d\n", data->clockdata.mday, data->clockdata.month, data->clockdata.year, data->clockdata.wday);
387 //kprintf("mwday = %d mdays = %d\n", data->mwday, mdays);
389 day = data->firstweekday - data->mwday + 1 - 7;
390 if (day > -6) day -= 7;
392 SetFont(_rp(obj), _font(obj));
393 SetDrMd(_rp(obj), JAM1);
395 if (!(msg->flags & MADF_DRAWUPDATE))
397 SetAPen(_rp(obj), _dri(obj)->dri_Pens[SHADOWPEN]);
398 Move(_rp(obj), offx - 1,
399 offy);
400 Draw(_rp(obj), offx - 1,
401 offy + data->cellheight * 7);
402 Draw(_rp(obj), offx + data->cellwidth * 7,
403 offy + data->cellheight * 7);
404 Draw(_rp(obj), offx + data->cellwidth * 7,
405 offy);
408 for(y = 0; y < 7; y++)
410 if (!y && (msg->flags & MADF_DRAWUPDATE))
412 day += 7;
413 continue;
416 for(x = 0; x < 7; x++)
418 CONST_STRPTR text;
419 UBYTE buf[7];
421 if (data->old_mday && (day != data->old_mday) && (day != data->clockdata.mday))
423 day++;
424 continue;
427 text = NULL;
428 if (day == data->clockdata.mday)
430 SetAPen(_rp(obj), _pens(obj)[MPEN_FILL]);
432 else
434 SetAPen(_rp(obj), _dri(obj)->dri_Pens[y ? SHINEPEN : SHADOWPEN]);
437 RectFill(_rp(obj), x * data->cellwidth + 1 + offx,
438 y * data->cellheight + 1 + offy,
439 x * data->cellwidth + data->cellwidth - 2 + offx,
440 y * data->cellheight + data->cellheight - 2 + offy);
442 SetAPen(_rp(obj), _dri(obj)->dri_Pens[SHADOWPEN]);
443 Move(_rp(obj), x * data->cellwidth + offx,
444 y * data->cellheight + offy);
445 Draw(_rp(obj), x * data->cellwidth + data->cellwidth - 1 + offx,
446 y * data->cellheight + offy);
447 Draw(_rp(obj), x * data->cellwidth + data->cellwidth - 1 + offx,
448 y * data->cellheight + data->cellheight - 1 + offy);
449 Draw(_rp(obj), x * data->cellwidth + offx,
450 y * data->cellheight + data->cellheight - 1 + offy);
451 Draw(_rp(obj), x * data->cellwidth + offx,
452 y * data->cellheight + offy);
454 if (y > 0)
456 if ((day >= 1) && (day <= mdays))
458 sprintf(buf, "%d", day);
459 SetSoftStyle(_rp(obj), FS_NORMAL, AskSoftStyle(_rp(obj)));
460 SetAPen(_rp(obj), _dri(obj)->dri_Pens[day == data->clockdata.mday ? SHADOWPEN : FILLTEXTPEN]);
461 text = buf;
464 else
466 SetSoftStyle(_rp(obj), FSF_BOLD, AskSoftStyle(_rp(obj)));
467 SetAPen(_rp(obj), _dri(obj)->dri_Pens[SHINEPEN]);
469 text = data->daylabels[(x + data->firstweekday) % 7];
472 if (text)
474 WORD tx, ty, tw;
476 tw = TextLength(_rp(obj), text, strlen(text));
477 tx = offx + x * data->cellwidth + (data->cellwidth - tw) / 2;
478 ty = offy + y * data->cellheight + (data->cellheight - _font(obj)->tf_YSize) / 2;
480 Move(_rp(obj), tx, ty + _font(obj)->tf_Baseline);
481 Text(_rp(obj), text, strlen(text));
484 day++;
486 } /* for(x = 0; x < 7; x++) */
488 } /* for(y = 0; y < 7; y++) */
490 return 0;
494 static WORD DayUnderMouse(Object *obj, struct Calendar_DATA *data, struct IntuiMessage *imsg)
496 WORD x, y, offx, offy, i;
498 offx = (_mwidth(obj) - data->cellwidth * 7 - 2) / 2 + 1;
499 offy = (_mheight(obj) - data->cellheight * 7 - 1) / 2 + data->cellheight;
501 x = imsg->MouseX - _mleft(obj) - offx;
502 y = imsg->MouseY - _mtop(obj) - offy;
504 if (x < 0) x = 0;
505 if (y < 0) y = 0;
506 if (x >= data->cellwidth * 7) x = data->cellwidth * 7 - 1;
507 if (y >= data->cellheight * 6) y = data->cellheight * 6 - 1;
509 x /= data->cellwidth;
510 y /= data->cellheight;
512 i = data->firstweekday - data->mwday + 1;
513 if (i > 1) i -= 7;
515 i += y * 7 + x;
517 if (i < 1)
519 i = 1;
521 else if (i > NumMonthDays(&data->clockdata))
523 i = NumMonthDays(&data->clockdata);
526 return i;
530 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
533 IPTR Calendar__MUIM_HandleEvent(Class *cl, Object *obj, struct MUIP_HandleEvent *msg)
535 struct Calendar_DATA *data = INST_DATA(cl, obj);
537 if (msg->muikey != MUIKEY_NONE)
539 UWORD day = data->clockdata.mday;
541 switch(msg->muikey)
543 case MUIKEY_LEFT:
544 if (day > 1)
546 set(obj, MUIA_Calendar_MonthDay, day - 1);
547 return MUI_EventHandlerRC_Eat;
549 break;
551 case MUIKEY_RIGHT:
552 if (day < NumMonthDays(&data->clockdata))
554 set(obj, MUIA_Calendar_MonthDay, day + 1);
555 return MUI_EventHandlerRC_Eat;
557 break;
559 case MUIKEY_UP:
561 UWORD newday = (day > 7) ? day - 7 : 1;
563 if (newday != day)
565 set(obj, MUIA_Calendar_MonthDay, newday);
566 return MUI_EventHandlerRC_Eat;
569 break;
571 case MUIKEY_DOWN:
573 UWORD newday = (day < NumMonthDays(&data->clockdata) - 7) ?
574 day + 7 : NumMonthDays(&data->clockdata);
576 if (newday != day)
578 set(obj, MUIA_Calendar_MonthDay, newday);
579 return MUI_EventHandlerRC_Eat;
582 break;
584 case MUIKEY_TOP:
585 case MUIKEY_LINESTART:
586 if (day != 1)
588 set(obj, MUIA_Calendar_MonthDay, 1);
589 return MUI_EventHandlerRC_Eat;
591 break;
593 case MUIKEY_BOTTOM:
594 case MUIKEY_LINEEND:
595 if (day != NumMonthDays(&data->clockdata))
597 set(obj, MUIA_Calendar_MonthDay, NumMonthDays(&data->clockdata));
598 return MUI_EventHandlerRC_Eat;
600 break;
604 else
606 WORD x1 = _mleft(obj) + (_mwidth(obj) - data->cellwidth * 7 - 2) / 2 + 1;
607 WORD y1 = _mtop(obj) + (_mheight(obj) - data->cellheight * 7 - 1) / 2 + data->cellheight;
608 WORD x2 = x1 + data->cellwidth * 7 - 1;
609 WORD y2 = y1 + data->cellheight * 6 - 1;
610 WORD day;
612 BOOL in = _between(x1, msg->imsg->MouseX, x2) && _between(y1, msg->imsg->MouseY, y2);
614 switch(msg->imsg->Class)
616 case IDCMP_MOUSEBUTTONS:
617 switch(msg->imsg->Code)
619 case SELECTDOWN:
620 if (in)
622 day = DayUnderMouse(obj, data, msg->imsg);
623 if (day != data->clockdata.mday)
625 set(obj, MUIA_Calendar_MonthDay, day);
627 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
628 data->ehn.ehn_Events |= IDCMP_MOUSEMOVE;
629 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
630 return 0;
632 break;
634 case SELECTUP:
635 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
637 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
638 data->ehn.ehn_Events &= ~IDCMP_MOUSEMOVE;
639 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
640 return 0;
642 break;
644 break;
646 case IDCMP_MOUSEMOVE:
647 if (data->ehn.ehn_Events & IDCMP_MOUSEMOVE)
649 day = DayUnderMouse(obj, data, msg->imsg);
650 if (day != data->clockdata.mday)
652 set(obj, MUIA_Calendar_MonthDay, day);
654 return 0;
656 break;
658 } /* switch(msg->imsg->Class) */
660 } /* if (msg->muikey == MUIKEY_NONE) */
662 return 0;