2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
6 #include <exec/types.h>
7 #include <utility/date.h>
8 #include <libraries/mui.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>
24 #include "calendar_private.h"
26 #define CELL_EXTRAWIDTH 6
27 #define CELL_EXTRAHEIGHT 4
29 STRPTR def_daylabels
[] =
40 /*** Methods ****************************************************************/
42 IPTR
Calendar__OM_NEW(Class
*cl
, Object
*obj
, struct opSet
*msg
)
44 struct Calendar_DATA
*data
;
47 obj
= (Object
*)DoSuperMethodA(cl
, obj
, (Msg
)msg
);
50 data
= INST_DATA(cl
, obj
);
52 data
->daylabels
= (STRPTR
*)GetTagData(MUIA_Calendar_DayLabels
, 0, msg
->ops_AttrList
);
55 struct Locale
*locale
;
58 locale
= LocaleBase
? OpenLocale(NULL
) : NULL
;
60 data
->daylabels
= data
->defdaylabels
;
61 for(i
= 0; i
< 12; i
++)
65 data
->defdaylabels
[i
] = GetLocaleStr(locale
, ABDAY_1
+ i
);
66 data
->firstweekday
= locale
->loc_CalendarType
;
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
;
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
;
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
;
119 secs
= Date2Amiga(&cd2
);
120 secs
+= 24 * 60 * 60; /* day++ */
122 Amiga2Date(secs
, &cd2
);
124 if (cd2
.month
!= cd
->month
) break;
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 const struct TagItem
*tags
= msg
->ops_AttrList
;
140 old_clockdata
= data
->clockdata
;
142 while ((tag
= NextTagItem(&tags
)) != NULL
)
146 case MUIA_Calendar_Date
:
147 data
->clockdata
= *(struct ClockData
*)tag
->ti_Data
;
151 case MUIA_Calendar_Year
:
152 data
->clockdata
.year
= tag
->ti_Data
;
156 case MUIA_Calendar_Month
:
157 data
->clockdata
.month
= tag
->ti_Data
;
161 case MUIA_Calendar_Month0
:
162 data
->clockdata
.month
= tag
->ti_Data
+ 1;
166 case MUIA_Calendar_MonthDay
:
167 data
->clockdata
.mday
= tag
->ti_Data
;
171 case MUIA_Calendar_MonthDay0
:
172 data
->clockdata
.mday
= tag
->ti_Data
+ 1;
176 } /* switch(tag->ti_Tag) */
178 } /* while ((tag = NextTagItem(&tags)) != NULL) */
182 struct ClockData cd2
;
185 cd2
= data
->clockdata
;
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
);
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
);
220 switch(msg
->opg_AttrID
)
222 case MUIA_Calendar_Date
:
223 *(struct ClockData
**)msg
->opg_Storage
= &data
->clockdata
;
226 case MUIA_Calendar_MonthDay
:
227 *msg
->opg_Storage
= data
->clockdata
.mday
;
230 case MUIA_Calendar_MonthDay0
:
231 *msg
->opg_Storage
= data
->clockdata
.mday
- 1;
234 case MUIA_Calendar_Month
:
235 *msg
->opg_Storage
= data
->clockdata
.month
;
238 case MUIA_Calendar_Month0
:
239 *msg
->opg_Storage
= data
->clockdata
.month
- 1;
242 case MUIA_Calendar_Year
:
243 *msg
->opg_Storage
= data
->clockdata
.year
;
247 retval
= DoSuperMethodA(cl
, obj
, (Msg
)msg
);
256 IPTR
Calendar__MUIM_Setup(Class
*cl
, Object
*obj
, struct MUIP_Setup
*msg
)
258 struct Calendar_DATA
*data
= INST_DATA(cl
, obj
);
262 if (!DoSuperMethodA(cl
, obj
, (Msg
)msg
)) return FALSE
;
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
++)
285 w
= TextLength(&rp
, s
, strlen(s
));
286 if (w
> data
->cellwidth
) data
->cellwidth
= w
;
291 data
->cellwidth
+= CELL_EXTRAWIDTH
;
293 data
->base_cellwidth
= data
->cellwidth
;
294 data
->base_cellheight
= data
->cellheight
;
296 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) &data
->ehn
);
302 IPTR
Calendar__MUIM_Cleanup(Class
*cl
, Object
*obj
, struct MUIP_Cleanup
*msg
)
304 struct Calendar_DATA
*data
= INST_DATA(cl
, obj
);
306 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) &data
->ehn
);
308 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
312 IPTR
Calendar__MUIM_AskMinMax(Class
*cl
, Object
*obj
, struct MUIP_AskMinMax
*msg
)
314 struct Calendar_DATA
*data
= INST_DATA(cl
, obj
);
316 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
318 msg
->MinMaxInfo
->MinWidth
+= data
->cellwidth
* 7 + 2;
319 msg
->MinMaxInfo
->MinHeight
+= data
->cellheight
* 7 + 1;
320 msg
->MinMaxInfo
->DefWidth
+= data
->cellwidth
* 7 + 2;
321 msg
->MinMaxInfo
->DefHeight
+= data
->cellheight
* 7 + 1;
322 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
323 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
330 IPTR
Calendar__MUIM_Draw(Class
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
332 struct Calendar_DATA
*data
= INST_DATA(cl
, obj
);
333 struct Region
*region
;
334 struct Rectangle rect
;
336 WORD x
, y
, offx
, offy
, day
, mdays
;
338 x
= (_mwidth(obj
) - 2) / 7;
339 y
= x
* data
->base_cellheight
/ data
->base_cellwidth
;
341 data
->cellheight
= (_mheight(obj
) - 1) / 7;
342 data
->cellwidth
= data
->cellheight
* data
->base_cellwidth
/ data
->base_cellheight
;
344 if ((data
->cellwidth
> x
) || (data
->cellheight
> y
))
347 data
->cellheight
= y
;
350 offx
= _mleft(obj
) + (_mwidth(obj
) - data
->cellwidth
* 7 - 2) / 2 + 1;
351 offy
= _mtop(obj
) + (_mheight(obj
) - data
->cellheight
* 7 - 1) / 2;
353 region
= NewRegion();
356 rect
.MinX
= _left(obj
);
357 rect
.MinY
= _top(obj
);
358 rect
.MaxX
= _right(obj
);
359 rect
.MaxY
= _bottom(obj
);
361 OrRectRegion(region
, &rect
);
363 rect
.MinX
= offx
- 1;
365 rect
.MaxX
= offx
+ data
->cellwidth
* 7;
366 rect
.MaxY
= offy
+ data
->cellheight
* 7;
368 ClearRectRegion(region
, &rect
);
370 clip
= MUI_AddClipRegion(muiRenderInfo(obj
), region
);
373 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
377 MUI_RemoveClipRegion(muiRenderInfo(obj
), clip
);
380 if (!(msg
->flags
& (MADF_DRAWOBJECT
| MADF_DRAWUPDATE
))) return 0;
383 (data
->clockdata
.wday
- (data
->clockdata
.mday
- 1) % 7 + 7) % 7;
385 mdays
= NumMonthDays(&data
->clockdata
);
387 //kprintf("actdate = %d.%d.%d wday = %d\n", data->clockdata.mday, data->clockdata.month, data->clockdata.year, data->clockdata.wday);
389 //kprintf("mwday = %d mdays = %d\n", data->mwday, mdays);
391 day
= data
->firstweekday
- data
->mwday
+ 1 - 7;
392 if (day
> -6) day
-= 7;
394 SetFont(_rp(obj
), _font(obj
));
395 SetDrMd(_rp(obj
), JAM1
);
397 if (!(msg
->flags
& MADF_DRAWUPDATE
))
399 SetAPen(_rp(obj
), _dri(obj
)->dri_Pens
[SHADOWPEN
]);
400 Move(_rp(obj
), offx
- 1,
402 Draw(_rp(obj
), offx
- 1,
403 offy
+ data
->cellheight
* 7);
404 Draw(_rp(obj
), offx
+ data
->cellwidth
* 7,
405 offy
+ data
->cellheight
* 7);
406 Draw(_rp(obj
), offx
+ data
->cellwidth
* 7,
410 for(y
= 0; y
< 7; y
++)
412 if (!y
&& (msg
->flags
& MADF_DRAWUPDATE
))
418 for(x
= 0; x
< 7; x
++)
423 if (data
->old_mday
&& (day
!= data
->old_mday
) && (day
!= data
->clockdata
.mday
))
430 if (day
== data
->clockdata
.mday
)
432 SetAPen(_rp(obj
), _pens(obj
)[MPEN_FILL
]);
436 SetAPen(_rp(obj
), _dri(obj
)->dri_Pens
[y
? SHINEPEN
: SHADOWPEN
]);
439 RectFill(_rp(obj
), x
* data
->cellwidth
+ 1 + offx
,
440 y
* data
->cellheight
+ 1 + offy
,
441 x
* data
->cellwidth
+ data
->cellwidth
- 2 + offx
,
442 y
* data
->cellheight
+ data
->cellheight
- 2 + offy
);
444 SetAPen(_rp(obj
), _dri(obj
)->dri_Pens
[SHADOWPEN
]);
445 Move(_rp(obj
), x
* data
->cellwidth
+ offx
,
446 y
* data
->cellheight
+ offy
);
447 Draw(_rp(obj
), x
* data
->cellwidth
+ data
->cellwidth
- 1 + offx
,
448 y
* data
->cellheight
+ offy
);
449 Draw(_rp(obj
), x
* data
->cellwidth
+ data
->cellwidth
- 1 + offx
,
450 y
* data
->cellheight
+ data
->cellheight
- 1 + offy
);
451 Draw(_rp(obj
), x
* data
->cellwidth
+ offx
,
452 y
* data
->cellheight
+ data
->cellheight
- 1 + offy
);
453 Draw(_rp(obj
), x
* data
->cellwidth
+ offx
,
454 y
* data
->cellheight
+ offy
);
458 if ((day
>= 1) && (day
<= mdays
))
460 sprintf(buf
, "%d", day
);
461 SetSoftStyle(_rp(obj
), FS_NORMAL
, AskSoftStyle(_rp(obj
)));
462 SetAPen(_rp(obj
), _dri(obj
)->dri_Pens
[day
== data
->clockdata
.mday
? SHADOWPEN
: FILLTEXTPEN
]);
468 SetSoftStyle(_rp(obj
), FSF_BOLD
, AskSoftStyle(_rp(obj
)));
469 SetAPen(_rp(obj
), _dri(obj
)->dri_Pens
[SHINEPEN
]);
471 text
= data
->daylabels
[(x
+ data
->firstweekday
) % 7];
478 tw
= TextLength(_rp(obj
), text
, strlen(text
));
479 tx
= offx
+ x
* data
->cellwidth
+ (data
->cellwidth
- tw
) / 2;
480 ty
= offy
+ y
* data
->cellheight
+ (data
->cellheight
- _font(obj
)->tf_YSize
) / 2;
482 Move(_rp(obj
), tx
, ty
+ _font(obj
)->tf_Baseline
);
483 Text(_rp(obj
), text
, strlen(text
));
488 } /* for(x = 0; x < 7; x++) */
490 } /* for(y = 0; y < 7; y++) */
496 static WORD
DayUnderMouse(Object
*obj
, struct Calendar_DATA
*data
, struct IntuiMessage
*imsg
)
498 WORD x
, y
, offx
, offy
, i
;
500 offx
= (_mwidth(obj
) - data
->cellwidth
* 7 - 2) / 2 + 1;
501 offy
= (_mheight(obj
) - data
->cellheight
* 7 - 1) / 2 + data
->cellheight
;
503 x
= imsg
->MouseX
- _mleft(obj
) - offx
;
504 y
= imsg
->MouseY
- _mtop(obj
) - offy
;
508 if (x
>= data
->cellwidth
* 7) x
= data
->cellwidth
* 7 - 1;
509 if (y
>= data
->cellheight
* 6) y
= data
->cellheight
* 6 - 1;
511 x
/= data
->cellwidth
;
512 y
/= data
->cellheight
;
514 i
= data
->firstweekday
- data
->mwday
+ 1;
523 else if (i
> NumMonthDays(&data
->clockdata
))
525 i
= NumMonthDays(&data
->clockdata
);
532 #define _between(a,x,b) ((x)>=(a) && (x)<=(b))
535 IPTR
Calendar__MUIM_HandleEvent(Class
*cl
, Object
*obj
, struct MUIP_HandleEvent
*msg
)
537 struct Calendar_DATA
*data
= INST_DATA(cl
, obj
);
539 if (msg
->muikey
!= MUIKEY_NONE
)
541 UWORD day
= data
->clockdata
.mday
;
548 set(obj
, MUIA_Calendar_MonthDay
, day
- 1);
549 return MUI_EventHandlerRC_Eat
;
554 if (day
< NumMonthDays(&data
->clockdata
))
556 set(obj
, MUIA_Calendar_MonthDay
, day
+ 1);
557 return MUI_EventHandlerRC_Eat
;
563 UWORD newday
= (day
> 7) ? day
- 7 : 1;
567 set(obj
, MUIA_Calendar_MonthDay
, newday
);
568 return MUI_EventHandlerRC_Eat
;
575 UWORD newday
= (day
< NumMonthDays(&data
->clockdata
) - 7) ?
576 day
+ 7 : NumMonthDays(&data
->clockdata
);
580 set(obj
, MUIA_Calendar_MonthDay
, newday
);
581 return MUI_EventHandlerRC_Eat
;
587 case MUIKEY_LINESTART
:
590 set(obj
, MUIA_Calendar_MonthDay
, 1);
591 return MUI_EventHandlerRC_Eat
;
597 if (day
!= NumMonthDays(&data
->clockdata
))
599 set(obj
, MUIA_Calendar_MonthDay
, NumMonthDays(&data
->clockdata
));
600 return MUI_EventHandlerRC_Eat
;
608 WORD x1
= _mleft(obj
) + (_mwidth(obj
) - data
->cellwidth
* 7 - 2) / 2 + 1;
609 WORD y1
= _mtop(obj
) + (_mheight(obj
) - data
->cellheight
* 7 - 1) / 2 + data
->cellheight
;
610 WORD x2
= x1
+ data
->cellwidth
* 7 - 1;
611 WORD y2
= y1
+ data
->cellheight
* 6 - 1;
614 BOOL in
= _between(x1
, msg
->imsg
->MouseX
, x2
) && _between(y1
, msg
->imsg
->MouseY
, y2
);
616 switch(msg
->imsg
->Class
)
618 case IDCMP_MOUSEBUTTONS
:
619 switch(msg
->imsg
->Code
)
624 day
= DayUnderMouse(obj
, data
, msg
->imsg
);
625 if (day
!= data
->clockdata
.mday
)
627 set(obj
, MUIA_Calendar_MonthDay
, day
);
629 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
630 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
631 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
637 if (data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
)
639 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
640 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
641 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
648 case IDCMP_MOUSEMOVE
:
649 if (data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
)
651 day
= DayUnderMouse(obj
, data
, msg
->imsg
);
652 if (day
!= data
->clockdata
.mday
)
654 set(obj
, MUIA_Calendar_MonthDay
, day
);
660 } /* switch(msg->imsg->Class) */
662 } /* if (msg->muikey == MUIKEY_NONE) */