merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / control / calendar.cxx
blobb9a2c8b54fb4c028a9f7dd5426933b7ad5e33f35
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: calendar.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #ifndef _APP_HXX
35 #include <vcl/svapp.hxx>
36 #endif
37 #ifndef _TABLE_HXX
38 #include <tools/table.hxx>
39 #endif
40 #ifndef _HELP_HXX
41 #include <vcl/help.hxx>
42 #endif
43 #ifndef _MENU_HXX
44 #include <vcl/menu.hxx>
45 #endif
46 #ifndef _DECOVIEW_HXX
47 #include <vcl/decoview.hxx>
48 #endif
49 #ifndef _FLOATWIN_HXX
50 #include <vcl/floatwin.hxx>
51 #endif
52 #ifndef _BUTTON_HXX
53 #include <vcl/button.hxx>
54 #endif
55 #ifndef _FIXED_HXX
56 #include <vcl/fixed.hxx>
57 #endif
58 #include <unotools/calendarwrapper.hxx>
59 #include <unotools/localedatawrapper.hxx>
60 #include <com/sun/star/i18n/Weekdays.hpp>
61 #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
62 #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
64 #define _SV_CALENDAR_CXX
65 #include <svtools/svtools.hrc>
66 #include <svtools/svtdata.hxx>
67 #include <calendar.hxx>
69 // =======================================================================
71 #define DAY_OFFX 4
72 #define DAY_OFFY 2
73 #define MONTH_BORDERX 4
74 #define MONTH_OFFY 3
75 #define WEEKNUMBER_OFFX 4
76 #define WEEKDAY_OFFY 3
77 #define TITLE_OFFY 3
78 #define TITLE_BORDERY 2
79 #define SPIN_OFFX 4
80 #define SPIN_OFFY TITLE_BORDERY
82 #define WEEKNUMBER_HEIGHT 85
84 #define CALENDAR_HITTEST_DAY ((USHORT)0x0001)
85 #define CALENDAR_HITTEST_WEEK ((USHORT)0x0002)
86 #define CALENDAR_HITTEST_MONTHTITLE ((USHORT)0x0004)
87 #define CALENDAR_HITTEST_PREV ((USHORT)0x0008)
88 #define CALENDAR_HITTEST_NEXT ((USHORT)0x0010)
89 #define CALENDAR_HITTEST_OUTSIDE ((USHORT)0x1000)
91 #define MENU_YEAR_COUNT 3
93 #define TABLE_DATE_SELECTED ((void*)0x00000001)
95 using namespace ::com::sun::star;
97 // =======================================================================
99 struct ImplDateInfo
101 XubString maText;
102 Color* mpTextColor;
103 Color* mpFrameColor;
104 USHORT mnFlags;
106 ImplDateInfo( const XubString& rText ) :
107 maText( rText )
108 { mpTextColor = mpFrameColor = NULL; mnFlags = 0; }
109 ~ImplDateInfo() { delete mpTextColor; delete mpFrameColor; }
112 DECLARE_TABLE( ImplDateTable, ImplDateInfo* )
114 // =======================================================================
116 static void ImplCalendarSelectDate( Table* pTable, const Date& rDate, BOOL bSelect )
118 if ( bSelect )
119 pTable->Insert( rDate.GetDate(), TABLE_DATE_SELECTED );
120 else
121 pTable->Remove( rDate.GetDate() );
124 // -----------------------------------------------------------------------
126 static void ImplCalendarSelectDateRange( Table* pTable,
127 const Date& rStartDate,
128 const Date& rEndDate,
129 BOOL bSelect )
131 Date aStartDate = rStartDate;
132 Date aEndDate = rEndDate;
133 if ( aStartDate > aEndDate )
135 Date aTempDate = aStartDate;
136 aStartDate = aEndDate;
137 aEndDate = aTempDate;
140 if ( bSelect )
142 while ( aStartDate <= aEndDate )
144 pTable->Insert( aStartDate.GetDate(), TABLE_DATE_SELECTED );
145 aStartDate++;
148 else
150 void* p = pTable->First();
151 while ( p )
153 Date aDate( pTable->GetCurKey() );
154 if ( aDate > aEndDate )
155 break;
157 if ( aDate >= aStartDate )
158 pTable->Remove( aDate.GetDate() );
159 else
160 p = pTable->Next();
165 // -----------------------------------------------------------------------
167 static void ImplCalendarUnSelectDateRange( Table* pTable,
168 Table* pOldTable,
169 const Date& rStartDate,
170 const Date& rEndDate )
172 Date aStartDate = rStartDate;
173 Date aEndDate = rEndDate;
174 if ( aStartDate > aEndDate )
176 Date aTempDate = aStartDate;
177 aStartDate = aEndDate;
178 aEndDate = aTempDate;
181 void* p = pTable->First();
182 while ( p )
184 Date aDate( pTable->GetCurKey() );
185 if ( aDate > aEndDate )
186 break;
188 if ( aDate >= aStartDate )
189 pTable->Remove( aDate.GetDate() );
190 else
191 p = pTable->Next();
194 p = pOldTable->First();
195 while ( p )
197 Date aDate( pOldTable->GetCurKey() );
198 if ( aDate > aEndDate )
199 break;
200 if ( aDate >= aStartDate )
201 pTable->Insert( aDate.GetDate(), TABLE_DATE_SELECTED );
203 p = pOldTable->Next();
207 // -----------------------------------------------------------------------
209 inline void ImplCalendarClearSelectDate( Table* pTable )
211 pTable->Clear();
214 // =======================================================================
216 void Calendar::ImplInit( WinBits nWinStyle )
218 mpDateTable = NULL;
219 mpSelectTable = new Table;
220 mpOldSelectTable = NULL;
221 mpRestoreSelectTable = NULL;
222 mpStandardColor = NULL;
223 mpSaturdayColor = NULL;
224 mpSundayColor = NULL;
225 mnDayCount = 0;
226 mnWinStyle = nWinStyle;
227 mnFirstYear = 0;
228 mnLastYear = 0;
229 mnRequestYear = 0;
230 mbCalc = TRUE;
231 mbFormat = TRUE;
232 mbDrag = FALSE;
233 mbSelection = FALSE;
234 mbMultiSelection = FALSE;
235 mbWeekSel = FALSE;
236 mbUnSel = FALSE;
237 mbMenuDown = FALSE;
238 mbSpinDown = FALSE;
239 mbPrevIn = FALSE;
240 mbNextIn = FALSE;
241 mbDirect = FALSE;
242 mbInSelChange = FALSE;
243 mbTravelSelect = FALSE;
244 mbScrollDateRange = FALSE;
245 mbSelLeft = FALSE;
246 mbAllSel = FALSE;
247 mbDropPos = FALSE;
249 ::rtl::OUString aGregorian( RTL_CONSTASCII_USTRINGPARAM( "gregorian"));
250 maCalendarWrapper.loadCalendar( aGregorian,
251 Application::GetAppLocaleDataWrapper().getLocale());
252 if (maCalendarWrapper.getUniqueID() != aGregorian)
254 #ifdef DBG_UTIL
255 ByteString aMsg( "Calendar::ImplInit: No ``gregorian'' calendar available for locale ``");
256 lang::Locale aLoc( Application::GetAppLocaleDataWrapper().getLocale());
257 aMsg += ByteString( String( aLoc.Language), RTL_TEXTENCODING_UTF8);
258 aMsg += '-';
259 aMsg += ByteString( String( aLoc.Country), RTL_TEXTENCODING_UTF8);
260 aMsg += "'' and other calendars aren't supported. Using en-US fallback.";
261 DBG_ERRORFILE( aMsg.GetBuffer());
262 #endif
263 /* If we ever wanted to support other calendars than Gregorian a lot of
264 * rewrite would be necessary to internally replace use of class Date
265 * with proper class CalendarWrapper methods, get rid of fixed 12
266 * months, fixed 7 days, ... */
267 maCalendarWrapper.loadCalendar( aGregorian, lang::Locale(
268 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "en")),
269 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "US")),
270 ::rtl::OUString()));
273 SetFirstDate( maCurDate );
274 ImplCalendarSelectDate( mpSelectTable, maCurDate, TRUE );
276 // Sonstige Strings erzeugen
277 maDayText = XubString( SvtResId( STR_SVT_CALENDAR_DAY ) );
278 maWeekText = XubString( SvtResId( STR_SVT_CALENDAR_WEEK ) );
280 // Tagestexte anlegen
281 for ( USHORT i = 0; i < 31; i++ )
282 mpDayText[i] = new UniString( UniString::CreateFromInt32( i+1 ) );
284 maDragScrollTimer.SetTimeoutHdl( STATIC_LINK( this, Calendar, ScrollHdl ) );
285 maDragScrollTimer.SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
286 mnDragScrollHitTest = 0;
288 ImplInitSettings();
291 // -----------------------------------------------------------------------
293 void Calendar::ImplInitSettings()
295 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
296 maSelColor = rStyleSettings.GetHighlightTextColor();
297 SetPointFont( rStyleSettings.GetToolFont() );
298 SetTextColor( rStyleSettings.GetFieldTextColor() );
299 SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
302 // -----------------------------------------------------------------------
304 Calendar::Calendar( Window* pParent, WinBits nWinStyle ) :
305 Control( pParent, nWinStyle & (WB_TABSTOP | WB_GROUP | WB_BORDER | WB_3DLOOK | WB_RANGESELECT | WB_MULTISELECT) ),
306 maCalendarWrapper( Application::GetAppLocaleDataWrapper().getServiceFactory() ),
307 maOldFormatFirstDate( 0, 0, 1900 ),
308 maOldFormatLastDate( 0, 0, 1900 ),
309 maFirstDate( 0, 0, 1900 ),
310 maOldFirstDate( 0, 0, 1900 ),
311 maOldCurDate( 0, 0, 1900 ),
312 maAnchorDate( maCurDate ),
313 maDropDate( 0, 0, 1900 )
315 ImplInit( nWinStyle );
318 // -----------------------------------------------------------------------
320 Calendar::Calendar( Window* pParent, const ResId& rResId ) :
321 Control( pParent, rResId ),
322 maCalendarWrapper( Application::GetAppLocaleDataWrapper().getServiceFactory() ),
323 maOldFormatFirstDate( 0, 0, 1900 ),
324 maOldFormatLastDate( 0, 0, 1900 ),
325 maFirstDate( 0, 0, 1900 ),
326 maOldFirstDate( 0, 0, 1900 ),
327 maOldCurDate( 0, 0, 1900 ),
328 maAnchorDate( maCurDate ),
329 maDropDate( 0, 0, 1900 )
331 ImplInit( rResId.GetWinBits() );
334 // -----------------------------------------------------------------------
336 Calendar::~Calendar()
338 delete mpStandardColor;
339 delete mpSaturdayColor;
340 delete mpSundayColor;
342 if ( mpDateTable )
344 ImplDateInfo* pDateInfo = mpDateTable->First();
345 while ( pDateInfo )
347 delete pDateInfo;
348 pDateInfo = mpDateTable->Next();
351 delete mpDateTable;
354 delete mpSelectTable;
355 if ( mpOldSelectTable )
356 delete mpOldSelectTable;
357 if ( mpRestoreSelectTable )
358 delete mpRestoreSelectTable;
360 for ( USHORT i = 0; i < 31; i++ )
361 delete mpDayText[i];
364 // -----------------------------------------------------------------------
366 void Calendar::SetMinimumNumberOfDaysInWeek( sal_Int16 nDays )
368 ImplUpdate( TRUE );
369 maCalendarWrapper.setMinimumNumberOfDaysForFirstWeek( nDays);
372 // -----------------------------------------------------------------------
374 void Calendar::SetWeekStart( sal_Int16 nDay )
376 ImplUpdate( TRUE );
377 switch (nDay)
379 case i18n::Weekdays::SUNDAY :
380 case i18n::Weekdays::MONDAY :
381 case i18n::Weekdays::TUESDAY :
382 case i18n::Weekdays::WEDNESDAY :
383 case i18n::Weekdays::THURSDAY :
384 case i18n::Weekdays::FRIDAY :
385 case i18n::Weekdays::SATURDAY :
386 ; // nothing
387 default:
388 DBG_ERRORFILE("Calendar::SetWeekStart: unknown value for setFirstDayOfWeek() of a Gregorian calendar");
389 nDay = i18n::Weekdays::SUNDAY;
391 maCalendarWrapper.setFirstDayOfWeek( nDay);
394 // -----------------------------------------------------------------------
396 DayOfWeek Calendar::ImplGetWeekStart() const
398 // Map i18n::Weekdays to Date DayOfWeek
399 DayOfWeek eDay;
400 sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
401 switch (nDay)
403 case i18n::Weekdays::SUNDAY :
404 eDay = SUNDAY;
405 break;
406 case i18n::Weekdays::MONDAY :
407 eDay = MONDAY;
408 break;
409 case i18n::Weekdays::TUESDAY :
410 eDay = TUESDAY;
411 break;
412 case i18n::Weekdays::WEDNESDAY :
413 eDay = WEDNESDAY;
414 break;
415 case i18n::Weekdays::THURSDAY :
416 eDay = THURSDAY;
417 break;
418 case i18n::Weekdays::FRIDAY :
419 eDay = FRIDAY;
420 break;
421 case i18n::Weekdays::SATURDAY :
422 eDay = SATURDAY;
423 break;
424 default:
425 DBG_ERRORFILE("Calendar::ImplGetWeekStart: broken i18n Gregorian calendar (getFirstDayOfWeek())");
426 eDay = SUNDAY;
428 return eDay;
431 // -----------------------------------------------------------------------
433 void Calendar::ImplGetWeekFont( Font& rFont ) const
435 // Wochennummer geben wir in WEEKNUMBER_HEIGHT%-Fonthoehe aus
436 Size aFontSize = rFont.GetSize();
437 aFontSize.Height() *= WEEKNUMBER_HEIGHT;
438 aFontSize.Height() /= 100;
439 rFont.SetSize( aFontSize );
440 rFont.SetWeight( WEIGHT_NORMAL );
443 // -----------------------------------------------------------------------
445 void Calendar::ImplFormat()
447 if ( !mbFormat )
448 return;
450 if ( mbCalc )
452 Size aOutSize = GetOutputSizePixel();
454 if ( (aOutSize.Width() <= 1) || (aOutSize.Height() <= 1) )
455 return;
457 XubString a99Text( XubString( RTL_CONSTASCII_USTRINGPARAM( "99" ) ) );
459 Font aOldFont = GetFont();
461 // Wochenanzeige beruecksichtigen
462 if ( mnWinStyle & WB_WEEKNUMBER )
464 Font aTempFont = aOldFont;
465 ImplGetWeekFont( aTempFont );
466 SetFont( aTempFont );
467 mnWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
468 SetFont( aOldFont );
470 else
471 mnWeekWidth = 0;
473 if ( mnWinStyle & WB_BOLDTEXT )
475 Font aFont = aOldFont;
476 if ( aFont.GetWeight() < WEIGHT_BOLD )
477 aFont.SetWeight( WEIGHT_BOLD );
478 else
479 aFont.SetWeight( WEIGHT_NORMAL );
480 SetFont( aFont );
483 long n99TextWidth = GetTextWidth( a99Text );
484 long nTextHeight = GetTextHeight();
486 // Breiten und X-Positionen berechnen
487 mnDayWidth = n99TextWidth+DAY_OFFX;
488 mnMonthWidth = mnDayWidth*7;
489 mnMonthWidth += mnWeekWidth;
490 mnMonthWidth += MONTH_BORDERX*2;
491 mnMonthPerLine = aOutSize.Width() / mnMonthWidth;
492 if ( !mnMonthPerLine )
493 mnMonthPerLine = 1;
494 long nOver = ((aOutSize.Width()-(mnMonthPerLine*mnMonthWidth)) / mnMonthPerLine);
495 mnMonthWidth += nOver;
496 mnDaysOffX = MONTH_BORDERX;
497 mnDaysOffX += nOver/2;
498 mnDaysOffX += mnWeekWidth;
500 // Hoehen und Y-Positionen berechnen
501 mnDayHeight = nTextHeight + DAY_OFFY;
502 mnWeekDayOffY = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
503 mnDaysOffY = mnWeekDayOffY + nTextHeight + WEEKDAY_OFFY;
504 mnMonthHeight = (mnDayHeight*6) + mnDaysOffY;
505 mnMonthHeight += MONTH_OFFY;
506 mnLines = aOutSize.Height() / mnMonthHeight;
507 if ( !mnLines )
508 mnLines = 1;
509 mnMonthHeight += (aOutSize.Height()-(mnLines*mnMonthHeight)) / mnLines;
511 // Spinfelder berechnen
512 long nSpinSize = nTextHeight+TITLE_BORDERY-SPIN_OFFY;
513 maPrevRect.Left() = SPIN_OFFX;
514 maPrevRect.Top() = SPIN_OFFY;
515 maPrevRect.Right() = maPrevRect.Left()+nSpinSize;
516 maPrevRect.Bottom() = maPrevRect.Top()+nSpinSize;
517 maNextRect.Left() = aOutSize.Width()-SPIN_OFFX-nSpinSize-1;
518 maNextRect.Top() = SPIN_OFFY;
519 maNextRect.Right() = maNextRect.Left()+nSpinSize;
520 maNextRect.Bottom() = maNextRect.Top()+nSpinSize;
522 if ( mnWinStyle & WB_BOLDTEXT )
523 SetFont( aOldFont );
525 // Calculate DayOfWeekText (gets displayed in a narrow font)
526 maDayOfWeekText.Erase();
527 long nStartOffX = 0;
528 sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
529 for ( sal_Int16 nDayOfWeek = 0; nDayOfWeek < 7; nDayOfWeek++ )
531 // Use first character of full name, since the abbreviated name may
532 // be roman digits or similar in some locales. Proper
533 // implementation would need narrow one letter month names defined
534 // in locale data.
535 String aDayOfWeek( maCalendarWrapper.getDisplayName(
536 i18n::CalendarDisplayIndex::DAY, nDay, 1).GetChar(0));
537 long nOffX = (mnDayWidth-GetTextWidth( aDayOfWeek ))/2;
538 if ( mnWinStyle & WB_BOLDTEXT )
539 nOffX++;
540 if ( !nDayOfWeek )
541 nStartOffX = nOffX;
542 else
543 nOffX -= nStartOffX;
544 nOffX += nDayOfWeek * mnDayWidth;
545 mnDayOfWeekAry[nDayOfWeek] = nOffX;
546 maDayOfWeekText += aDayOfWeek;
547 nDay++;
548 nDay %= 7;
551 mbCalc = FALSE;
554 // Anzahl Tage berechnen
556 DayOfWeek eStartDay = ImplGetWeekStart();
558 USHORT nWeekDay;
559 Date aTempDate = GetFirstMonth();
560 maFirstDate = aTempDate;
561 nWeekDay = (USHORT)aTempDate.GetDayOfWeek();
562 nWeekDay = (nWeekDay+(7-(USHORT)eStartDay)) % 7;
563 maFirstDate -= (ULONG)nWeekDay;
564 mnDayCount = nWeekDay;
565 USHORT nDaysInMonth;
566 USHORT nMonthCount = (USHORT)(mnMonthPerLine*mnLines);
567 for ( USHORT i = 0; i < nMonthCount; i++ )
569 nDaysInMonth = aTempDate.GetDaysInMonth();
570 mnDayCount += nDaysInMonth;
571 aTempDate += nDaysInMonth;
573 Date aTempDate2 = aTempDate;
574 aTempDate2--;
575 nDaysInMonth = aTempDate2.GetDaysInMonth();
576 aTempDate2 -= nDaysInMonth-1;
577 nWeekDay = (USHORT)aTempDate2.GetDayOfWeek();
578 nWeekDay = (nWeekDay+(7-(USHORT)eStartDay)) % 7;
579 mnDayCount += 42-nDaysInMonth-nWeekDay;
581 // Farben festlegen
582 maOtherColor = Color( COL_LIGHTGRAY );
583 if ( maOtherColor.IsRGBEqual( GetBackground().GetColor() ) )
584 maOtherColor.SetColor( COL_GRAY );
586 Date aLastDate = GetLastDate();
587 if ( (maOldFormatLastDate != aLastDate) ||
588 (maOldFormatFirstDate != maFirstDate) )
590 maOldFormatFirstDate = maFirstDate;
591 maOldFormatLastDate = aLastDate;
592 DateRangeChanged();
595 // DateInfo besorgen
596 USHORT nNewFirstYear = maFirstDate.GetYear();
597 USHORT nNewLastYear = GetLastDate().GetYear();
598 if ( mnFirstYear )
600 if ( nNewFirstYear < mnFirstYear )
602 for ( mnRequestYear = nNewFirstYear; mnRequestYear < mnFirstYear; mnRequestYear++ )
603 RequestDateInfo();
604 mnFirstYear = nNewFirstYear;
606 if ( nNewLastYear > mnLastYear )
608 for ( mnRequestYear = mnLastYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
609 RequestDateInfo();
610 mnLastYear = nNewLastYear;
613 else
615 for ( mnRequestYear = nNewFirstYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
616 RequestDateInfo();
617 mnFirstYear = nNewFirstYear;
618 mnLastYear = nNewLastYear;
620 mnRequestYear = 0;
622 mbFormat = FALSE;
625 // -----------------------------------------------------------------------
627 USHORT Calendar::ImplHitTest( const Point& rPos, Date& rDate ) const
629 if ( mbFormat )
630 return 0;
632 if ( maPrevRect.IsInside( rPos ) )
633 return CALENDAR_HITTEST_PREV;
634 else if ( maNextRect.IsInside( rPos ) )
635 return CALENDAR_HITTEST_NEXT;
637 long nX;
638 long nY;
639 long nOffX;
640 long nYMonth;
641 USHORT nDay;
642 DayOfWeek eStartDay = ImplGetWeekStart();
644 rDate = GetFirstMonth();
645 nY = 0;
646 for ( long i = 0; i < mnLines; i++ )
648 if ( rPos.Y() < nY )
649 return 0;
651 nX = 0;
652 nYMonth = nY+mnMonthHeight;
653 for ( long j = 0; j < mnMonthPerLine; j++ )
655 if ( (rPos.X() < nX) && (rPos.Y() < nYMonth) )
656 return 0;
658 USHORT nDaysInMonth = rDate.GetDaysInMonth();
660 // Entsprechender Monat gefunden
661 if ( (rPos.X() > nX) && (rPos.Y() < nYMonth) &&
662 (rPos.X() < nX+mnMonthWidth) )
664 if ( rPos.Y() < (nY+(TITLE_BORDERY*2)+mnDayHeight))
665 return CALENDAR_HITTEST_MONTHTITLE;
666 else
668 long nDayX = nX+mnDaysOffX;
669 long nDayY = nY+mnDaysOffY;
670 if ( rPos.Y() < nDayY )
671 return 0;
672 USHORT nDayIndex = (USHORT)rDate.GetDayOfWeek();
673 nDayIndex = (nDayIndex+(7-(USHORT)eStartDay)) % 7;
674 if ( (i == 0) && (j == 0) )
676 Date aTempDate = rDate;
677 aTempDate -= nDayIndex;
678 for ( nDay = 0; nDay < nDayIndex; nDay++ )
680 nOffX = nDayX + (nDay*mnDayWidth);
681 if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
682 (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
684 rDate = aTempDate;
685 rDate += nDay;
686 return CALENDAR_HITTEST_DAY;
690 for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
692 if ( rPos.Y() < nDayY )
694 rDate += nDayIndex;
695 return 0;
697 nOffX = nDayX + (nDayIndex*mnDayWidth);
698 if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
699 (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
701 rDate += nDay-1;
702 return CALENDAR_HITTEST_DAY;
704 if ( nDayIndex == 6 )
706 nDayIndex = 0;
707 nDayY += mnDayHeight;
709 else
710 nDayIndex++;
712 if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
714 USHORT nWeekDay = (USHORT)rDate.GetDayOfWeek();
715 nWeekDay = (nWeekDay+(7-(USHORT)eStartDay)) % 7;
716 USHORT nDayCount = 42-nDaysInMonth-nWeekDay;
717 Date aTempDate = rDate;
718 aTempDate += nDaysInMonth;
719 for ( nDay = 1; nDay <= nDayCount; nDay++ )
721 if ( rPos.Y() < nDayY )
723 rDate += nDayIndex;
724 return 0;
726 nOffX = nDayX + (nDayIndex*mnDayWidth);
727 if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
728 (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
730 rDate = aTempDate;
731 rDate += nDay-1;
732 return CALENDAR_HITTEST_DAY;
734 if ( nDayIndex == 6 )
736 nDayIndex = 0;
737 nDayY += mnDayHeight;
739 else
740 nDayIndex++;
746 rDate += nDaysInMonth;
747 nX += mnMonthWidth;
750 nY += mnMonthHeight;
753 return 0;
756 // -----------------------------------------------------------------------
758 static void ImplDrawSpinArrow( OutputDevice* pDev, const Rectangle& rRect,
759 BOOL bPrev )
761 long i;
762 long n;
763 long nLines;
764 long nHeight = rRect.GetHeight();
765 long nWidth = rRect.GetWidth();
766 if ( nWidth < nHeight )
767 n = nWidth;
768 else
769 n = nHeight;
770 if ( !(n & 0x01) )
771 n--;
772 nLines = n/2;
774 Rectangle aRect( Point( rRect.Left()+(nWidth/2)-(nLines/2),
775 rRect.Top()+(nHeight/2) ),
776 Size( 1, 1 ) );
777 if ( !bPrev )
779 aRect.Left() += nLines;
780 aRect.Right() += nLines;
783 pDev->DrawRect( aRect );
784 for ( i = 0; i < nLines; i++ )
786 if ( bPrev )
788 aRect.Left()++;
789 aRect.Right()++;
791 else
793 aRect.Left()--;
794 aRect.Right()--;
796 aRect.Top()--;
797 aRect.Bottom()++;
798 pDev->DrawRect( aRect );
802 // -----------------------------------------------------------------------
804 void Calendar::ImplDrawSpin( BOOL bDrawPrev, BOOL bDrawNext )
806 if ( !bDrawPrev && !bDrawNext )
807 return;
809 SetLineColor();
810 SetFillColor( GetSettings().GetStyleSettings().GetButtonTextColor() );
811 if ( bDrawPrev )
813 Rectangle aOutRect = maPrevRect;
814 aOutRect.Left() += 3;
815 aOutRect.Top() += 3;
816 aOutRect.Right() -= 3;
817 aOutRect.Bottom() -= 3;
818 ImplDrawSpinArrow( this, aOutRect, TRUE );
820 if ( bDrawNext )
822 Rectangle aOutRect = maNextRect;
823 aOutRect.Left() += 3;
824 aOutRect.Top() += 3;
825 aOutRect.Right() -= 3;
826 aOutRect.Bottom() -= 3;
827 ImplDrawSpinArrow( this, aOutRect, FALSE );
831 // -----------------------------------------------------------------------
833 void Calendar::ImplDrawDate( long nX, long nY,
834 USHORT nDay, USHORT nMonth, USHORT nYear,
835 DayOfWeek eDayOfWeek,
836 BOOL bBack, BOOL bOther, ULONG nToday )
838 ImplDateInfo* pDateInfo;
839 Color* pTextColor = NULL;
840 const String& rDay = *(mpDayText[nDay-1]);
841 Rectangle aDateRect( nX, nY, nX+mnDayWidth-1, nY+mnDayHeight-1 );
843 BOOL bSel = FALSE;
844 BOOL bFocus = FALSE;
845 // Aktueller Tag
846 if ( (nDay == maCurDate.GetDay()) &&
847 (nMonth == maCurDate.GetMonth()) &&
848 (nYear == maCurDate.GetYear()) )
849 bFocus = TRUE;
850 if ( mpSelectTable )
852 if ( mpSelectTable->IsKeyValid( Date( nDay, nMonth, nYear ).GetDate() ) )
853 bSel = TRUE;
856 // Dateinfo ermitteln
857 if ( mpDateTable )
859 pDateInfo = mpDateTable->Get( Date( nDay, nMonth, nYear ).GetDate() );
860 if ( !pDateInfo )
861 pDateInfo = mpDateTable->Get( Date( nDay, nMonth, 0 ).GetDate() );
863 else
864 pDateInfo = NULL;
866 // Textfarbe ermitteln
867 if ( bSel )
868 pTextColor = &maSelColor;
869 else if ( bOther )
870 pTextColor = &maOtherColor;
871 else
873 if ( pDateInfo && pDateInfo->mpTextColor )
874 pTextColor = pDateInfo->mpTextColor;
875 else
877 if ( eDayOfWeek == SATURDAY )
878 pTextColor = mpSaturdayColor;
879 else if ( eDayOfWeek == SUNDAY )
880 pTextColor = mpSundayColor;
881 if ( !pTextColor )
882 pTextColor = mpStandardColor;
886 if ( bFocus )
887 HideFocus();
889 // Font ermitteln
890 Font aOldFont = GetFont();
891 BOOL bBoldFont = FALSE;
892 if ( (mnWinStyle & WB_BOLDTEXT) &&
893 pDateInfo && (pDateInfo->mnFlags & DIB_BOLD) )
895 bBoldFont = TRUE;
896 Font aFont = aOldFont;
897 if ( aFont.GetWeight() < WEIGHT_BOLD )
898 aFont.SetWeight( WEIGHT_BOLD );
899 else
900 aFont.SetWeight( WEIGHT_NORMAL );
901 SetFont( aFont );
904 // Hintergrund ausgeben
905 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
906 if ( bSel || bBack )
908 if ( bSel )
910 SetLineColor();
911 SetFillColor( rStyleSettings.GetHighlightColor() );
912 DrawRect( aDateRect );
914 else
915 Erase( aDateRect );
918 // Text ausgeben
919 long nTextX = nX+(mnDayWidth-GetTextWidth( rDay ))-(DAY_OFFX/2);
920 long nTextY = nY+(mnDayHeight-GetTextHeight())/2;
921 if ( pTextColor )
923 Color aOldColor = GetTextColor();
924 SetTextColor( *pTextColor );
925 DrawText( Point( nTextX, nTextY ), rDay );
926 SetTextColor( aOldColor );
928 else
929 DrawText( Point( nTextX, nTextY ), rDay );
931 // Heute
932 Date aTodayDate( maCurDate );
933 if ( nToday )
934 aTodayDate.SetDate( nToday );
935 else
936 aTodayDate = Date();
937 if ( (nDay == aTodayDate.GetDay()) &&
938 (nMonth == aTodayDate.GetMonth()) &&
939 (nYear == aTodayDate.GetYear()) )
941 SetLineColor( rStyleSettings.GetWindowTextColor() );
942 SetFillColor();
943 DrawRect( aDateRect );
946 // Evt. DateInfo ausgeben
947 if ( (mnWinStyle & WB_FRAMEINFO) && pDateInfo && pDateInfo->mpFrameColor )
949 SetLineColor( *(pDateInfo->mpFrameColor) );
950 SetFillColor();
951 Rectangle aFrameRect( aDateRect );
952 aFrameRect.Left()++;
953 aFrameRect.Top()++;
954 long nFrameWidth = aFrameRect.GetWidth();
955 long nFrameHeight = aFrameRect.GetHeight();
956 long nFrameOff;
957 if ( nFrameWidth < nFrameHeight )
959 nFrameOff = nFrameHeight-nFrameWidth;
960 aFrameRect.Top() += nFrameOff/2;
961 nFrameOff %= 2;
962 aFrameRect.Bottom() -= nFrameOff;
964 else if ( nFrameWidth > nFrameHeight )
966 nFrameOff = nFrameWidth-nFrameHeight;
967 aFrameRect.Left() += nFrameOff/2;
968 nFrameOff %= 2;
969 aFrameRect.Right() -= nFrameOff;
971 DrawEllipse( aFrameRect );
974 // Evt. noch FocusRect
975 if ( bFocus && HasFocus() )
976 ShowFocus( aDateRect );
978 if( mbDropPos && maDropDate == Date( nDay, nMonth, nYear ) )
979 ImplInvertDropPos();
981 if ( bBoldFont )
982 SetFont( aOldFont );
985 // -----------------------------------------------------------------------
987 void Calendar::ImplDraw( BOOL bPaint )
989 ImplFormat();
991 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
992 Size aOutSize = GetOutputSizePixel();
993 long i;
994 long j;
995 long nX;
996 long nY;
997 long nDeltaX;
998 long nDeltaY;
999 long nDayX;
1000 long nDayY;
1001 ULONG nToday = Date().GetDate();
1002 USHORT nDay;
1003 USHORT nMonth;
1004 USHORT nYear;
1005 Date aDate = GetFirstMonth();
1006 DayOfWeek eStartDay = ImplGetWeekStart();
1008 HideFocus();
1010 nY = 0;
1011 for ( i = 0; i < mnLines; i++ )
1013 // Titleleiste ausgeben
1014 SetLineColor();
1015 SetFillColor( rStyleSettings.GetFaceColor() );
1016 Rectangle aTitleRect( 0, nY, aOutSize.Width()-1, nY+mnDayHeight-DAY_OFFY+TITLE_BORDERY*2 );
1017 if ( !bPaint )
1019 Rectangle aTempRect( 1, aTitleRect.Top()+TITLE_BORDERY,
1020 aOutSize.Width()-2,
1021 aTitleRect.Bottom()-TITLE_BORDERY );
1022 if ( !i )
1024 aTempRect.Left() = maPrevRect.Right()+1;
1025 aTempRect.Right() = maNextRect.Left()-1;
1027 DrawRect( aTempRect );
1029 else
1031 DrawRect( aTitleRect );
1032 Point aTopLeft1( aTitleRect.Left(), aTitleRect.Top() );
1033 Point aTopLeft2( aTitleRect.Left(), aTitleRect.Top()+1 );
1034 Point aBottomRight1( aTitleRect.Right(), aTitleRect.Bottom() );
1035 Point aBottomRight2( aTitleRect.Right(), aTitleRect.Bottom()-1 );
1036 SetLineColor( rStyleSettings.GetDarkShadowColor() );
1037 DrawLine( aTopLeft1, Point( aBottomRight1.X(), aTopLeft1.Y() ) );
1038 SetLineColor( rStyleSettings.GetLightColor() );
1039 DrawLine( aTopLeft2, Point( aBottomRight2.X(), aTopLeft2.Y() ) );
1040 DrawLine( aTopLeft2, Point( aTopLeft2.X(), aBottomRight2.Y() ) );
1041 SetLineColor( rStyleSettings.GetShadowColor() );
1042 DrawLine( Point( aTopLeft2.X(), aBottomRight2.Y() ), aBottomRight2 );
1043 DrawLine( Point( aBottomRight2.X(), aTopLeft2.Y() ), aBottomRight2 );
1044 SetLineColor( rStyleSettings.GetDarkShadowColor() );
1045 DrawLine( Point( aTopLeft1.X(), aBottomRight1.Y() ), aBottomRight1 );
1047 Point aSepPos1( 0, aTitleRect.Top()+TITLE_BORDERY );
1048 Point aSepPos2( 0, aTitleRect.Bottom()-TITLE_BORDERY );
1049 for ( j = 0; j < mnMonthPerLine-1; j++ )
1051 aSepPos1.X() += mnMonthWidth-1;
1052 aSepPos2.X() = aSepPos1.X();
1053 SetLineColor( rStyleSettings.GetShadowColor() );
1054 DrawLine( aSepPos1, aSepPos2 );
1055 aSepPos1.X()++;
1056 aSepPos2.X() = aSepPos1.X();
1057 SetLineColor( rStyleSettings.GetLightColor() );
1058 DrawLine( aSepPos1, aSepPos2 );
1061 nX = 0;
1062 for ( j = 0; j < mnMonthPerLine; j++ )
1064 nMonth = aDate.GetMonth();
1065 nYear = aDate.GetYear();
1067 // Monat in der Titleleiste ausgeben
1068 nDeltaX = nX;
1069 nDeltaY = nY+TITLE_BORDERY;
1070 String aMonthText( maCalendarWrapper.getDisplayName(
1071 i18n::CalendarDisplayIndex::MONTH, nMonth-1, 1));
1072 aMonthText += ' ';
1073 aMonthText += String::CreateFromInt64( nYear );
1074 long nMonthTextWidth = GetTextWidth( aMonthText );
1075 long nMonthOffX1 = 0;
1076 long nMonthOffX2 = 0;
1077 if ( i == 0 )
1079 if ( j == 0 )
1080 nMonthOffX1 = maPrevRect.Right()+1;
1081 if ( j == mnMonthPerLine-1 )
1082 nMonthOffX2 = aOutSize.Width()-maNextRect.Left()+1;
1084 long nMaxMonthWidth = mnMonthWidth-nMonthOffX1-nMonthOffX2-4;
1085 if ( nMonthTextWidth > nMaxMonthWidth )
1087 // Abbreviated month name.
1088 aMonthText = maCalendarWrapper.getDisplayName(
1089 i18n::CalendarDisplayIndex::MONTH, nMonth-1, 0);
1090 aMonthText += ' ';
1091 aMonthText += String::CreateFromInt64( nYear );
1092 nMonthTextWidth = GetTextWidth( aMonthText );
1094 long nTempOff = (mnMonthWidth-nMonthTextWidth+1)/2;
1095 if ( nTempOff < nMonthOffX1 )
1096 nDeltaX += nMonthOffX1+1;
1097 else
1099 if ( nTempOff+nMonthTextWidth > mnMonthWidth-nMonthOffX2 )
1100 nDeltaX += mnMonthWidth-nMonthOffX2-nMonthTextWidth;
1101 else
1102 nDeltaX += nTempOff;
1104 SetTextColor( rStyleSettings.GetButtonTextColor() );
1105 DrawText( Point( nDeltaX, nDeltaY ), aMonthText );
1106 SetTextColor( rStyleSettings.GetWindowTextColor() );
1108 // Weekleiste ausgeben
1109 if ( bPaint )
1111 nDayX = nX+mnDaysOffX;
1112 nDayY = nY+mnWeekDayOffY;
1113 nDeltaY = nDayY + mnDayHeight;
1114 SetLineColor( rStyleSettings.GetWindowTextColor() );
1115 Point aStartPos( nDayX, nDeltaY );
1116 if ( mnWinStyle & WB_WEEKNUMBER )
1117 aStartPos.X() -= WEEKNUMBER_OFFX-2;
1118 DrawLine( aStartPos, Point( nDayX+(7*mnDayWidth), nDeltaY ) );
1119 DrawTextArray( Point( nDayX+mnDayOfWeekAry[0], nDayY ), maDayOfWeekText, &(mnDayOfWeekAry[1]) );
1122 // Week-Numbers ausgeben
1123 if ( mnWinStyle & WB_WEEKNUMBER )
1125 nDayX = nX+mnDaysOffX;
1126 nDayY = nY+mnWeekDayOffY;
1127 nDeltaY = nDayY + mnDayHeight;
1128 long nMonthHeight = mnDayHeight*6;
1129 if ( bPaint )
1130 DrawLine( Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY ), Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY+nMonthHeight ) );
1131 else
1132 Erase( Rectangle( nDayX-mnWeekWidth-WEEKNUMBER_OFFX, nDeltaY, nDayX-WEEKNUMBER_OFFX-1, nDeltaY+nMonthHeight ) );
1134 Font aOldFont = GetFont();
1135 Font aTempFont = aOldFont;
1136 ImplGetWeekFont( aTempFont );
1137 SetFont( aTempFont );
1138 nDayX -= mnWeekWidth;
1139 nDayY = nY+mnDaysOffY;
1140 maCalendarWrapper.setGregorianDateTime( aDate);
1141 for ( USHORT nWeekCount = 0; nWeekCount < 6; nWeekCount++ )
1143 sal_Int16 nWeek = maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
1144 String aWeekText( String::CreateFromInt32( nWeek));
1145 long nOffX = (mnWeekWidth-WEEKNUMBER_OFFX)-GetTextWidth( aWeekText );
1146 long nOffY = (mnDayHeight-GetTextHeight())/2;
1147 DrawText( Point( nDayX+nOffX, nDayY+nOffY ), aWeekText );
1148 nDayY += mnDayHeight;
1149 maCalendarWrapper.addValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, 7);
1151 SetFont( aOldFont );
1154 // Tage ausgeben
1155 USHORT nDaysInMonth = aDate.GetDaysInMonth();
1156 nDayX = nX+mnDaysOffX;
1157 nDayY = nY+mnDaysOffY;
1158 if ( !bPaint )
1160 Rectangle aClearRect( nDayX, nDayY,
1161 nDayX+(7*mnDayWidth)-1, nDayY+(6*mnDayHeight)-1 );
1162 Erase( aClearRect );
1164 USHORT nDayIndex = (USHORT)aDate.GetDayOfWeek();
1165 nDayIndex = (nDayIndex+(7-(USHORT)eStartDay)) % 7;
1166 if ( (i == 0) && (j == 0) )
1168 Date aTempDate = aDate;
1169 aTempDate -= nDayIndex;
1170 for ( nDay = 0; nDay < nDayIndex; nDay++ )
1172 nDeltaX = nDayX + (nDay*mnDayWidth);
1173 ImplDrawDate( nDeltaX, nDayY, nDay+aTempDate.GetDay(),
1174 aTempDate.GetMonth(), aTempDate.GetYear(),
1175 (DayOfWeek)((nDay+(USHORT)eStartDay)%7), FALSE, TRUE, nToday );
1178 for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
1180 nDeltaX = nDayX + (nDayIndex*mnDayWidth);
1181 ImplDrawDate( nDeltaX, nDayY, nDay, nMonth, nYear,
1182 (DayOfWeek)((nDayIndex+(USHORT)eStartDay)%7),
1183 FALSE, FALSE, nToday );
1184 if ( nDayIndex == 6 )
1186 nDayIndex = 0;
1187 nDayY += mnDayHeight;
1189 else
1190 nDayIndex++;
1192 if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
1194 USHORT nWeekDay = (USHORT)aDate.GetDayOfWeek();
1195 nWeekDay = (nWeekDay+(7-(USHORT)eStartDay)) % 7;
1196 USHORT nDayCount = 42-nDaysInMonth-nWeekDay;
1197 Date aTempDate = aDate;
1198 aTempDate += nDaysInMonth;
1199 for ( nDay = 1; nDay <= nDayCount; nDay++ )
1201 nDeltaX = nDayX + (nDayIndex*mnDayWidth);
1202 ImplDrawDate( nDeltaX, nDayY, nDay,
1203 aTempDate.GetMonth(), aTempDate.GetYear(),
1204 (DayOfWeek)((nDayIndex+(USHORT)eStartDay)%7),
1205 FALSE, TRUE, nToday );
1206 if ( nDayIndex == 6 )
1208 nDayIndex = 0;
1209 nDayY += mnDayHeight;
1211 else
1212 nDayIndex++;
1216 aDate += nDaysInMonth;
1217 nX += mnMonthWidth;
1220 nY += mnMonthHeight;
1223 // Spin-Buttons zeichnen
1224 if ( bPaint )
1225 ImplDrawSpin();
1228 // -----------------------------------------------------------------------
1230 void Calendar::ImplUpdateDate( const Date& rDate )
1232 if ( IsReallyVisible() && IsUpdateMode() )
1234 Rectangle aDateRect( GetDateRect( rDate ) );
1235 if ( !aDateRect.IsEmpty() )
1237 BOOL bOther = (rDate < GetFirstMonth()) || (rDate > GetLastMonth());
1238 ImplDrawDate( aDateRect.Left(), aDateRect.Top(),
1239 rDate.GetDay(), rDate.GetMonth(), rDate.GetYear(),
1240 rDate.GetDayOfWeek(), TRUE, bOther );
1245 // -----------------------------------------------------------------------
1247 void Calendar::ImplUpdateSelection( Table* pOld )
1249 Table* pNew = mpSelectTable;
1250 void* p;
1251 ULONG nKey;
1253 p = pOld->First();
1254 while ( p )
1256 nKey = pOld->GetCurKey();
1257 if ( !pNew->Get( nKey ) )
1259 Date aTempDate( nKey );
1260 ImplUpdateDate( aTempDate );
1263 p = pOld->Next();
1266 p = pNew->First();
1267 while ( p )
1269 nKey = pNew->GetCurKey();
1270 if ( !pOld->Get( nKey ) )
1272 Date aTempDate( nKey );
1273 ImplUpdateDate( aTempDate );
1276 p = pNew->Next();
1280 // -----------------------------------------------------------------------
1282 void Calendar::ImplMouseSelect( const Date& rDate, USHORT nHitTest,
1283 BOOL bMove, BOOL bExpand, BOOL bExtended )
1285 Table* pOldSel = new Table( *mpSelectTable );
1286 Date aOldDate = maCurDate;
1287 Date aTempDate = rDate;
1289 if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
1290 aTempDate--;
1292 if ( mbMultiSelection )
1294 maCurDate = aTempDate;
1295 mbSelLeft = aTempDate < maAnchorDate;
1297 if ( bMove )
1299 if ( mbSelLeft )
1301 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), aTempDate );
1302 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, maAnchorDate, Date( 31, 12, 9999 ) );
1304 else
1306 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), maAnchorDate );
1307 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, aTempDate, Date( 31, 12, 9999 ) );
1309 ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, !mbUnSel );
1311 else
1313 if ( bExpand )
1315 if ( !bExtended )
1317 if ( mbSelLeft )
1319 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aTempDate, FALSE );
1320 ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), FALSE );
1322 else
1324 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, FALSE );
1325 ImplCalendarSelectDateRange( mpSelectTable, aTempDate, Date( 31, 12, 9999 ), FALSE );
1328 ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, TRUE );
1330 else if ( bExtended && !(mnWinStyle & WB_RANGESELECT) )
1332 maAnchorDate = aTempDate;
1333 if ( IsDateSelected( aTempDate ) )
1335 mbUnSel = TRUE;
1336 ImplCalendarSelectDate( mpSelectTable, aTempDate, FALSE );
1338 else
1340 ImplCalendarSelectDate( mpSelectTable, aTempDate, TRUE );
1343 else
1345 maAnchorDate = aTempDate;
1346 ImplCalendarClearSelectDate( mpSelectTable );
1347 ImplCalendarSelectDate( mpSelectTable, aTempDate, TRUE );
1350 mpRestoreSelectTable = new Table( *mpSelectTable );
1353 else
1355 if ( aTempDate < maCurDate )
1356 mbSelLeft = TRUE;
1357 else
1358 mbSelLeft = FALSE;
1359 if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
1360 aTempDate = maOldCurDate;
1361 if ( !bMove )
1362 maAnchorDate = aTempDate;
1363 if ( aTempDate != maCurDate )
1365 maCurDate = aTempDate;
1366 ImplCalendarSelectDate( mpSelectTable, aOldDate, FALSE );
1367 ImplCalendarSelectDate( mpSelectTable, maCurDate, TRUE );
1371 BOOL bNewSel = *pOldSel != *mpSelectTable;
1372 if ( (maCurDate != aOldDate) || bNewSel )
1374 if ( bNewSel )
1376 mbInSelChange = TRUE;
1377 SelectionChanging();
1378 mbInSelChange = FALSE;
1380 HideFocus();
1381 if ( bNewSel )
1382 ImplUpdateSelection( pOldSel );
1383 if ( !bNewSel || !pOldSel->Get( aOldDate.GetDate() ) )
1384 ImplUpdateDate( aOldDate );
1385 // Damit Focus-Rechteck auch wieder neu ausgegeben wird
1386 if ( HasFocus() || !bNewSel || !mpSelectTable->Get( maCurDate.GetDate() ) )
1387 ImplUpdateDate( maCurDate );
1389 delete pOldSel;
1392 // -----------------------------------------------------------------------
1394 void Calendar::ImplUpdate( BOOL bCalcNew )
1396 if ( IsReallyVisible() && IsUpdateMode() )
1398 if ( bCalcNew && !mbCalc )
1399 Invalidate();
1400 else if ( !mbFormat && !mbCalc )
1402 if ( mbDirect )
1404 mbFormat = TRUE;
1405 ImplDraw( FALSE );
1406 return;
1408 else
1409 Invalidate();
1413 if ( bCalcNew )
1414 mbCalc = TRUE;
1415 mbFormat = TRUE;
1418 // -----------------------------------------------------------------------
1420 void Calendar::ImplInvertDropPos()
1422 Rectangle aRect = GetDateRect( maDropDate );//this is one Pixel to width and one to heigh
1423 aRect.Bottom() = aRect.Top()+mnDayHeight-1;
1424 aRect.Right() = aRect.Left()+mnDayWidth-1;
1425 Invert( aRect );
1428 // -----------------------------------------------------------------------
1430 void Calendar::ImplScroll( BOOL bPrev )
1432 Date aNewFirstMonth = GetFirstMonth();
1433 if ( bPrev )
1435 aNewFirstMonth--;
1436 aNewFirstMonth -= aNewFirstMonth.GetDaysInMonth()-1;
1438 else
1439 aNewFirstMonth += aNewFirstMonth.GetDaysInMonth();
1440 mbDirect = TRUE;
1441 SetFirstDate( aNewFirstMonth );
1442 mbDirect = FALSE;
1445 // -----------------------------------------------------------------------
1447 void Calendar::ImplShowMenu( const Point& rPos, const Date& rDate )
1449 EndSelection();
1451 Date aOldFirstDate = GetFirstMonth();
1452 PopupMenu aPopupMenu;
1453 PopupMenu* pYearPopupMenus[MENU_YEAR_COUNT];
1454 USHORT nMonthOff;
1455 USHORT nCurItemId;
1456 USHORT nYear = rDate.GetYear()-1;
1457 USHORT i;
1458 USHORT j;
1459 USHORT nYearIdCount = 1000;
1461 nMonthOff = (rDate.GetYear()-aOldFirstDate.GetYear())*12;
1462 if ( aOldFirstDate.GetMonth() < rDate.GetMonth() )
1463 nMonthOff += rDate.GetMonth()-aOldFirstDate.GetMonth();
1464 else
1465 nMonthOff -= aOldFirstDate.GetMonth()-rDate.GetMonth();
1467 // Menu aufbauen (Jahre mit verschiedenen Monaten aufnehmen)
1468 for ( i = 0; i < MENU_YEAR_COUNT; i++ )
1470 pYearPopupMenus[i] = new PopupMenu;
1471 for ( j = 1; j <= 12; j++ )
1472 pYearPopupMenus[i]->InsertItem( nYearIdCount+j,
1473 maCalendarWrapper.getDisplayName(
1474 i18n::CalendarDisplayIndex::MONTH, j-1, 1));
1475 aPopupMenu.InsertItem( 10+i, UniString::CreateFromInt32( nYear+i ) );
1476 aPopupMenu.SetPopupMenu( 10+i, pYearPopupMenus[i] );
1477 nYearIdCount += 1000;
1480 mbMenuDown = TRUE;
1481 nCurItemId = aPopupMenu.Execute( this, rPos );
1482 mbMenuDown = FALSE;
1484 // Menu zerstoeren
1485 aPopupMenu.SetPopupMenu( 2, NULL );
1486 for ( i = 0; i < MENU_YEAR_COUNT; i++ )
1488 aPopupMenu.SetPopupMenu( 10+i, NULL );
1489 delete pYearPopupMenus[i];
1492 if ( nCurItemId )
1494 USHORT nTempMonthOff = nMonthOff % 12;
1495 USHORT nTempYearOff = nMonthOff / 12;
1496 USHORT nNewMonth = nCurItemId % 1000;
1497 USHORT nNewYear = nYear+((nCurItemId-1000)/1000);
1498 if ( nTempMonthOff < nNewMonth )
1499 nNewMonth = nNewMonth - nTempMonthOff;
1500 else
1502 nNewYear--;
1503 nNewMonth = 12-(nTempMonthOff-nNewMonth);
1505 nNewYear = nNewYear - nTempYearOff;
1506 SetFirstDate( Date( 1, nNewMonth, nNewYear ) );
1510 // -----------------------------------------------------------------------
1512 void Calendar::ImplTracking( const Point& rPos, BOOL bRepeat )
1514 Date aTempDate = maCurDate;
1515 USHORT nHitTest = ImplHitTest( rPos, aTempDate );
1517 if ( mbSpinDown )
1519 mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
1520 mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
1522 if ( bRepeat && (mbPrevIn || mbNextIn) )
1524 mbScrollDateRange = TRUE;
1525 ImplScroll( mbPrevIn );
1526 mbScrollDateRange = FALSE;
1529 else
1530 ImplMouseSelect( aTempDate, nHitTest, TRUE, FALSE, FALSE );
1533 // -----------------------------------------------------------------------
1535 void Calendar::ImplEndTracking( BOOL bCancel )
1537 BOOL bSelection = mbSelection;
1538 BOOL bSpinDown = mbSpinDown;
1540 mbDrag = FALSE;
1541 mbSelection = FALSE;
1542 mbMultiSelection = FALSE;
1543 mbUnSel = FALSE;
1544 mbSpinDown = FALSE;
1545 mbPrevIn = FALSE;
1546 mbNextIn = FALSE;
1548 if ( bCancel )
1550 if ( maOldFirstDate != maFirstDate )
1551 SetFirstDate( maOldFirstDate );
1553 if ( !bSpinDown )
1555 Table* pOldSel = new Table( *mpSelectTable );
1556 Date aOldDate = maCurDate;
1557 maCurDate = maOldCurDate;
1558 *mpSelectTable = *mpOldSelectTable;
1559 HideFocus();
1560 ImplUpdateSelection( pOldSel );
1561 if ( !pOldSel->Get( aOldDate.GetDate() ) )
1562 ImplUpdateDate( aOldDate );
1563 // Damit Focus-Rechteck auch wieder neu ausgegeben wird
1564 if ( HasFocus() || !mpSelectTable->Get( maCurDate.GetDate() ) )
1565 ImplUpdateDate( maCurDate );
1566 delete pOldSel;
1570 if ( !bSpinDown )
1572 if ( !bCancel )
1574 // Feststellen, ob wir sichtbaren Bereich scrollen sollen
1575 ULONG nSelCount = mpSelectTable->Count();
1576 if ( nSelCount )
1578 Date aFirstSelDate( mpSelectTable->GetObjectKey( 0 ) );
1579 Date aLastSelDate( mpSelectTable->GetObjectKey( nSelCount-1 ) );
1580 if ( aLastSelDate < GetFirstMonth() )
1581 ImplScroll( TRUE );
1582 else if ( GetLastMonth() < aFirstSelDate )
1583 ImplScroll( FALSE );
1587 if ( mbAllSel ||
1588 (!bCancel && ((maCurDate != maOldCurDate) || (*mpOldSelectTable != *mpSelectTable))) )
1589 Select();
1591 if ( !bSelection && (mnWinStyle & WB_TABSTOP) && !bCancel )
1592 GrabFocus();
1594 delete mpOldSelectTable;
1595 mpOldSelectTable = NULL;
1596 delete mpRestoreSelectTable;
1597 mpRestoreSelectTable = NULL;
1601 // -----------------------------------------------------------------------
1603 IMPL_STATIC_LINK( Calendar, ScrollHdl, Timer*, EMPTYARG )
1605 BOOL bPrevIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_PREV) != 0;
1606 BOOL bNextIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_NEXT) != 0;
1607 if( bNextIn || bPrevIn )
1609 pThis->mbScrollDateRange = TRUE;
1610 pThis->ImplScroll( bPrevIn );
1611 pThis->mbScrollDateRange = FALSE;
1613 return 0;
1616 // -----------------------------------------------------------------------
1618 void Calendar::MouseButtonDown( const MouseEvent& rMEvt )
1620 if ( rMEvt.IsLeft() && !mbMenuDown )
1622 Date aTempDate = maCurDate;
1623 USHORT nHitTest = ImplHitTest( rMEvt.GetPosPixel(), aTempDate );
1624 if ( nHitTest )
1626 if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
1627 ImplShowMenu( rMEvt.GetPosPixel(), aTempDate );
1628 else
1630 maOldFirstDate = maFirstDate;
1632 mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
1633 mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
1634 if ( mbPrevIn || mbNextIn )
1636 mbSpinDown = TRUE;
1637 mbScrollDateRange = TRUE;
1638 ImplScroll( mbPrevIn );
1639 mbScrollDateRange = FALSE;
1640 // Hier muss BUTTONREPEAT stehen, also nicht wieder
1641 // auf SCROLLREPEAT aendern, sondern mit TH abklaeren,
1642 // warum es evtl. anders sein sollte (71775)
1643 StartTracking( STARTTRACK_BUTTONREPEAT );
1645 else
1647 if ( (rMEvt.GetClicks() == 2) && (nHitTest & CALENDAR_HITTEST_DAY) )
1648 DoubleClick();
1649 else
1651 if ( mpOldSelectTable )
1652 delete mpOldSelectTable;
1653 maOldCurDate = maCurDate;
1654 mpOldSelectTable = new Table( *mpSelectTable );
1656 if ( !mbSelection )
1658 mbDrag = TRUE;
1659 StartTracking();
1662 mbMultiSelection = (mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT)) != 0;
1663 if ( (nHitTest & CALENDAR_HITTEST_DAY) && mbMultiSelection )
1664 mbWeekSel = TRUE;
1665 else
1666 mbWeekSel = FALSE;
1667 ImplMouseSelect( aTempDate, nHitTest, FALSE, rMEvt.IsShift(), rMEvt.IsMod1() );
1673 return;
1676 Control::MouseButtonDown( rMEvt );
1679 // -----------------------------------------------------------------------
1681 void Calendar::MouseButtonUp( const MouseEvent& rMEvt )
1683 if ( rMEvt.IsLeft() && mbSelection )
1684 ImplEndTracking( FALSE );
1685 else
1686 Control::MouseButtonUp( rMEvt );
1689 // -----------------------------------------------------------------------
1691 void Calendar::MouseMove( const MouseEvent& rMEvt )
1693 if ( mbSelection && rMEvt.GetButtons() )
1694 ImplTracking( rMEvt.GetPosPixel(), FALSE );
1695 else
1696 Control::MouseMove( rMEvt );
1699 // -----------------------------------------------------------------------
1701 void Calendar::Tracking( const TrackingEvent& rTEvt )
1703 Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1705 if ( rTEvt.IsTrackingEnded() )
1706 ImplEndTracking( rTEvt.IsTrackingCanceled() );
1707 else
1708 ImplTracking( aMousePos, rTEvt.IsTrackingRepeat() );
1711 // -----------------------------------------------------------------------
1713 void Calendar::KeyInput( const KeyEvent& rKEvt )
1715 Date aNewDate = maCurDate;
1716 BOOL bMultiSel = (mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) != 0;
1717 BOOL bExpand = rKEvt.GetKeyCode().IsShift();
1718 BOOL bExtended = rKEvt.GetKeyCode().IsMod1();
1720 switch ( rKEvt.GetKeyCode().GetCode() )
1722 case KEY_HOME:
1723 aNewDate.SetDay( 1 );
1724 break;
1726 case KEY_END:
1727 aNewDate.SetDay( aNewDate.GetDaysInMonth() );
1728 break;
1730 case KEY_LEFT:
1731 aNewDate--;
1732 break;
1734 case KEY_RIGHT:
1735 aNewDate++;
1736 break;
1738 case KEY_UP:
1739 aNewDate -= 7;
1740 break;
1742 case KEY_DOWN:
1743 aNewDate += 7;
1744 break;
1746 case KEY_PAGEUP:
1748 Date aTempDate = aNewDate;
1749 aTempDate -= aNewDate.GetDay()+1;
1750 aNewDate -= aTempDate.GetDaysInMonth();
1752 break;
1754 case KEY_PAGEDOWN:
1755 aNewDate += aNewDate.GetDaysInMonth();
1756 break;
1758 case KEY_SPACE:
1759 if ( bMultiSel && !(mnWinStyle & WB_RANGESELECT) )
1761 if ( !bExpand )
1763 BOOL bDateSel = IsDateSelected( maCurDate );
1764 SelectDate( maCurDate, !bDateSel );
1765 mbSelLeft = FALSE;
1766 SelectionChanging();
1767 mbTravelSelect = TRUE;
1768 Select();
1769 mbTravelSelect = FALSE;
1772 else
1773 Control::KeyInput( rKEvt );
1774 break;
1776 default:
1777 Control::KeyInput( rKEvt );
1778 break;
1781 if ( aNewDate != maCurDate )
1783 if ( bMultiSel && bExpand )
1785 Table* pOldSel = new Table( *mpSelectTable );
1786 Date aOldAnchorDate = maAnchorDate;
1787 mbSelLeft = aNewDate < maAnchorDate;
1788 if ( !bExtended )
1790 if ( mbSelLeft )
1792 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aNewDate, FALSE );
1793 ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), FALSE );
1795 else
1797 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, FALSE );
1798 ImplCalendarSelectDateRange( mpSelectTable, aNewDate, Date( 31, 12, 9999 ), FALSE );
1801 ImplCalendarSelectDateRange( mpSelectTable, aNewDate, maAnchorDate, TRUE );
1802 mbDirect = TRUE;
1803 SetCurDate( aNewDate );
1804 mbDirect = FALSE;
1805 maAnchorDate = aOldAnchorDate;
1806 mbInSelChange = TRUE;
1807 SelectionChanging();
1808 mbInSelChange = FALSE;
1809 ImplUpdateSelection( pOldSel );
1810 delete pOldSel;
1812 else
1814 if ( mnWinStyle & WB_RANGESELECT )
1816 SetNoSelection();
1817 SelectDate( aNewDate, TRUE );
1819 mbDirect = TRUE;
1820 SetCurDate( aNewDate );
1821 mbDirect = FALSE;
1823 mbTravelSelect = TRUE;
1824 Select();
1825 mbTravelSelect = FALSE;
1829 // -----------------------------------------------------------------------
1831 void Calendar::Paint( const Rectangle& )
1833 ImplDraw( TRUE );
1836 // -----------------------------------------------------------------------
1838 void Calendar::GetFocus()
1840 ImplUpdateDate( maCurDate );
1841 Control::GetFocus();
1844 // -----------------------------------------------------------------------
1846 void Calendar::LoseFocus()
1848 HideFocus();
1849 Control::LoseFocus();
1852 // -----------------------------------------------------------------------
1854 void Calendar::Resize()
1856 ImplUpdate( TRUE );
1857 Control::Resize();
1860 // -----------------------------------------------------------------------
1862 void Calendar::RequestHelp( const HelpEvent& rHEvt )
1864 if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1866 Date aDate = maCurDate;
1867 if ( GetDate( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ), aDate ) )
1869 Rectangle aDateRect = GetDateRect( aDate );
1870 Point aPt = OutputToScreenPixel( aDateRect.TopLeft() );
1871 aDateRect.Left() = aPt.X();
1872 aDateRect.Top() = aPt.Y();
1873 aPt = OutputToScreenPixel( aDateRect.BottomRight() );
1874 aDateRect.Right() = aPt.X();
1875 aDateRect.Bottom() = aPt.Y();
1877 if ( (rHEvt.GetMode() & HELPMODE_BALLOON) || (mnWinStyle & WB_QUICKHELPSHOWSDATEINFO) )
1879 ImplDateInfo* pInfo;
1880 if ( mpDateTable )
1882 pInfo = mpDateTable->Get( aDate.GetDate() );
1883 if ( !pInfo )
1884 pInfo = mpDateTable->Get( Date( aDate.GetDay(), aDate.GetMonth(), 0 ).GetDate() );
1886 else
1887 pInfo = NULL;
1888 if ( pInfo )
1890 XubString aStr = pInfo->maText;
1891 if ( aStr.Len() )
1893 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aDateRect, aStr );
1894 return;
1899 if ( rHEvt.GetMode() & HELPMODE_QUICK )
1901 maCalendarWrapper.setGregorianDateTime( aDate);
1902 USHORT nWeek = (USHORT) maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
1903 USHORT nMonth = aDate.GetMonth();
1904 XubString aStr( maDayText );
1905 aStr.AppendAscii( ": " );
1906 aStr.Append( XubString::CreateFromInt32( aDate.GetDayOfYear() ) );
1907 aStr.AppendAscii( " / " );
1908 aStr.Append( maWeekText );
1909 aStr.AppendAscii( ": " );
1910 aStr.Append( XubString::CreateFromInt32( nWeek ) );
1911 // Evt. noch Jahr hinzufuegen, wenn es nicht das gleiche ist
1912 if ( (nMonth == 12) && (nWeek == 1) )
1914 aStr.AppendAscii( ", " );
1915 aStr.Append( XubString::CreateFromInt32( aDate.GetYear()+1 ) );
1917 else if ( (nMonth == 1) && (nWeek > 50) )
1919 aStr.AppendAscii( ", " );
1920 aStr.Append( XubString::CreateFromInt32( aDate.GetYear()-1 ) );
1922 Help::ShowQuickHelp( this, aDateRect, aStr );
1923 return;
1928 Control::RequestHelp( rHEvt );
1931 // -----------------------------------------------------------------------
1933 void Calendar::Command( const CommandEvent& rCEvt )
1935 if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
1937 if ( !mbSelection && rCEvt.IsMouseEvent() )
1939 Date aTempDate = maCurDate;
1940 USHORT nHitTest = ImplHitTest( rCEvt.GetMousePosPixel(), aTempDate );
1941 if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
1943 ImplShowMenu( rCEvt.GetMousePosPixel(), aTempDate );
1944 return;
1948 else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
1950 const CommandWheelData* pData = rCEvt.GetWheelData();
1951 if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
1953 long nNotchDelta = pData->GetNotchDelta();
1954 if ( nNotchDelta < 0 )
1956 while ( nNotchDelta < 0 )
1958 ImplScroll( TRUE );
1959 nNotchDelta++;
1962 else
1964 while ( nNotchDelta > 0 )
1966 ImplScroll( FALSE );
1967 nNotchDelta--;
1971 return;
1975 Control::Command( rCEvt );
1978 // -----------------------------------------------------------------------
1980 void Calendar::StateChanged( StateChangedType nType )
1982 Control::StateChanged( nType );
1984 if ( nType == STATE_CHANGE_INITSHOW )
1985 ImplFormat();
1988 // -----------------------------------------------------------------------
1990 void Calendar::DataChanged( const DataChangedEvent& rDCEvt )
1992 Control::DataChanged( rDCEvt );
1994 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1995 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1996 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1997 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1999 ImplInitSettings();
2000 Invalidate();
2004 // -----------------------------------------------------------------------
2006 void Calendar::SelectionChanging()
2008 maSelectionChangingHdl.Call( this );
2011 // -----------------------------------------------------------------------
2013 void Calendar::DateRangeChanged()
2015 maDateRangeChangedHdl.Call( this );
2018 // -----------------------------------------------------------------------
2020 void Calendar::RequestDateInfo()
2022 maRequestDateInfoHdl.Call( this );
2025 // -----------------------------------------------------------------------
2027 void Calendar::DoubleClick()
2029 maDoubleClickHdl.Call( this );
2032 // -----------------------------------------------------------------------
2034 void Calendar::Select()
2036 maSelectHdl.Call( this );
2039 // -----------------------------------------------------------------------
2041 void Calendar::SelectDate( const Date& rDate, BOOL bSelect )
2043 if ( !rDate.IsValid() )
2044 return;
2046 Table* pOldSel;
2048 if ( !mbInSelChange )
2049 pOldSel = new Table( *mpSelectTable );
2050 else
2051 pOldSel = NULL;
2053 ImplCalendarSelectDate( mpSelectTable, rDate, bSelect );
2055 if ( pOldSel )
2057 ImplUpdateSelection( pOldSel );
2058 delete pOldSel;
2062 // -----------------------------------------------------------------------
2064 void Calendar::SelectDateRange( const Date& rStartDate, const Date& rEndDate,
2065 BOOL bSelect )
2067 if ( !rStartDate.IsValid() || !rEndDate.IsValid() )
2068 return;
2070 Table* pOldSel;
2072 if ( !mbInSelChange )
2073 pOldSel = new Table( *mpSelectTable );
2074 else
2075 pOldSel = NULL;
2077 ImplCalendarSelectDateRange( mpSelectTable, rStartDate, rEndDate, bSelect );
2079 if ( pOldSel )
2081 ImplUpdateSelection( pOldSel );
2082 delete pOldSel;
2086 // -----------------------------------------------------------------------
2088 void Calendar::SetNoSelection()
2090 Table* pOldSel;
2092 if ( !mbInSelChange )
2093 pOldSel = new Table( *mpSelectTable );
2094 else
2095 pOldSel = NULL;
2097 ImplCalendarClearSelectDate( mpSelectTable );
2099 if ( pOldSel )
2101 ImplUpdateSelection( pOldSel );
2102 delete pOldSel;
2106 // -----------------------------------------------------------------------
2108 BOOL Calendar::IsDateSelected( const Date& rDate ) const
2110 return mpSelectTable->IsKeyValid( rDate.GetDate() );
2113 // -----------------------------------------------------------------------
2115 ULONG Calendar::GetSelectDateCount() const
2117 return mpSelectTable->Count();
2120 // -----------------------------------------------------------------------
2122 Date Calendar::GetSelectDate( ULONG nIndex ) const
2124 if ( nIndex < mpSelectTable->Count() )
2125 return Date( mpSelectTable->GetObjectKey( nIndex ) );
2126 else
2128 Date aDate( 0, 0, 0 );
2129 return aDate;
2133 // -----------------------------------------------------------------------
2135 void Calendar::SetCurDate( const Date& rNewDate )
2137 if ( !rNewDate.IsValid() )
2138 return;
2140 if ( maCurDate != rNewDate )
2142 BOOL bUpdate = IsVisible() && IsUpdateMode();
2143 Date aOldDate = maCurDate;
2144 maCurDate = rNewDate;
2145 maAnchorDate = maCurDate;
2147 if ( !(mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) )
2149 ImplCalendarSelectDate( mpSelectTable, aOldDate, FALSE );
2150 ImplCalendarSelectDate( mpSelectTable, maCurDate, TRUE );
2152 else if ( !HasFocus() )
2153 bUpdate = FALSE;
2155 // Aktuelles Datum noch in den sichtbaren Bereich verschieben
2156 if ( mbFormat || (maCurDate < GetFirstMonth()) )
2157 SetFirstDate( maCurDate );
2158 else if ( maCurDate > GetLastMonth() )
2160 Date aTempDate = GetLastMonth();
2161 long nDateOff = maCurDate-aTempDate;
2162 if ( nDateOff < 365 )
2164 Date aFirstDate = GetFirstMonth();
2165 aFirstDate += aFirstDate.GetDaysInMonth();
2166 aTempDate++;
2167 while ( nDateOff > aTempDate.GetDaysInMonth() )
2169 aFirstDate += aFirstDate.GetDaysInMonth();
2170 long nDaysInMonth = aTempDate.GetDaysInMonth();
2171 aTempDate += nDaysInMonth;
2172 nDateOff -= nDaysInMonth;
2174 SetFirstDate( aFirstDate );
2176 else
2177 SetFirstDate( maCurDate );
2179 else
2181 if ( bUpdate )
2183 HideFocus();
2184 ImplUpdateDate( aOldDate );
2185 ImplUpdateDate( maCurDate );
2191 // -----------------------------------------------------------------------
2193 void Calendar::SetFirstDate( const Date& rNewFirstDate )
2195 if ( maFirstDate != rNewFirstDate )
2197 maFirstDate = Date( 1, rNewFirstDate.GetMonth(), rNewFirstDate.GetYear() );
2198 mbDropPos = FALSE;
2199 ImplUpdate();
2203 // -----------------------------------------------------------------------
2205 Date Calendar::GetFirstMonth() const
2207 if ( maFirstDate.GetDay() > 1 )
2209 if ( maFirstDate.GetMonth() == 12 )
2210 return Date( 1, 1, maFirstDate.GetYear()+1 );
2211 else
2212 return Date( 1, maFirstDate.GetMonth()+1, maFirstDate.GetYear() );
2214 else
2215 return maFirstDate;
2218 // -----------------------------------------------------------------------
2220 Date Calendar::GetLastMonth() const
2222 Date aDate = GetFirstMonth();
2223 USHORT nMonthCount = GetMonthCount();
2224 for ( USHORT i = 0; i < nMonthCount; i++ )
2225 aDate += aDate.GetDaysInMonth();
2226 aDate--;
2227 return aDate;
2230 // -----------------------------------------------------------------------
2232 USHORT Calendar::GetMonthCount() const
2234 if ( mbFormat )
2235 return 1;
2236 else
2237 return (USHORT)(mnMonthPerLine*mnLines);
2240 // -----------------------------------------------------------------------
2242 BOOL Calendar::GetDropDate( Date& rDate ) const
2244 if( mbDropPos )
2246 rDate = maDropDate;
2247 return TRUE;
2249 return FALSE;
2252 // -----------------------------------------------------------------------
2254 BOOL Calendar::GetDate( const Point& rPos, Date& rDate ) const
2256 Date aDate = maCurDate;
2257 USHORT nHitTest = ImplHitTest( rPos, aDate );
2258 if ( nHitTest & CALENDAR_HITTEST_DAY )
2260 rDate = aDate;
2261 return TRUE;
2263 else
2264 return FALSE;
2267 // -----------------------------------------------------------------------
2269 Rectangle Calendar::GetDateRect( const Date& rDate ) const
2271 Rectangle aRect;
2273 if ( mbFormat || (rDate < maFirstDate) || (rDate > (maFirstDate+mnDayCount)) )
2274 return aRect;
2276 long nX;
2277 long nY;
2278 ULONG nDaysOff;
2279 USHORT nDayIndex;
2280 Date aDate = GetFirstMonth();
2282 if ( rDate < aDate )
2284 aRect = GetDateRect( aDate );
2285 nDaysOff = aDate-rDate;
2286 nX = (long)(nDaysOff*mnDayWidth);
2287 aRect.Left() -= nX;
2288 aRect.Right() -= nX;
2289 return aRect;
2291 else
2293 Date aLastDate = GetLastMonth();
2294 if ( rDate > aLastDate )
2296 USHORT nWeekDay = (USHORT)aLastDate.GetDayOfWeek();
2297 nWeekDay = (nWeekDay+(7-(USHORT)ImplGetWeekStart())) % 7;
2298 aLastDate -= nWeekDay;
2299 aRect = GetDateRect( aLastDate );
2300 nDaysOff = rDate-aLastDate;
2301 nDayIndex = 0;
2302 for ( USHORT i = 0; i <= nDaysOff; i++ )
2304 if ( aLastDate == rDate )
2306 aRect.Left() += nDayIndex*mnDayWidth;
2307 aRect.Right() = aRect.Left()+mnDayWidth;
2308 return aRect;
2310 if ( nDayIndex == 6 )
2312 nDayIndex = 0;
2313 aRect.Top() += mnDayHeight;
2314 aRect.Bottom() += mnDayHeight;
2316 else
2317 nDayIndex++;
2318 aLastDate++;
2323 nY = 0;
2324 for ( long i = 0; i < mnLines; i++ )
2326 nX = 0;
2327 for ( long j = 0; j < mnMonthPerLine; j++ )
2329 USHORT nDaysInMonth = aDate.GetDaysInMonth();
2331 // Monat gerufen
2332 if ( (aDate.GetMonth() == rDate.GetMonth()) &&
2333 (aDate.GetYear() == rDate.GetYear()) )
2335 long nDayX = nX+mnDaysOffX;
2336 long nDayY = nY+mnDaysOffY;
2337 nDayIndex = (USHORT)aDate.GetDayOfWeek();
2338 nDayIndex = (nDayIndex+(7-(USHORT)ImplGetWeekStart())) % 7;
2339 for ( USHORT nDay = 1; nDay <= nDaysInMonth; nDay++ )
2341 if ( nDay == rDate.GetDay() )
2343 aRect.Left() = nDayX + (nDayIndex*mnDayWidth);
2344 aRect.Top() = nDayY;
2345 aRect.Right() = aRect.Left()+mnDayWidth;
2346 aRect.Bottom() = aRect.Top()+mnDayHeight;
2347 break;
2349 if ( nDayIndex == 6 )
2351 nDayIndex = 0;
2352 nDayY += mnDayHeight;
2354 else
2355 nDayIndex++;
2359 aDate += nDaysInMonth;
2360 nX += mnMonthWidth;
2363 nY += mnMonthHeight;
2366 return aRect;
2369 // -----------------------------------------------------------------------
2371 void Calendar::SetStandardColor( const Color& rColor )
2373 if ( mpStandardColor )
2374 *mpStandardColor = rColor;
2375 else
2376 mpStandardColor = new Color( rColor );
2377 ImplUpdate();
2380 // -----------------------------------------------------------------------
2382 void Calendar::SetSaturdayColor( const Color& rColor )
2384 if ( mpSaturdayColor )
2385 *mpSaturdayColor = rColor;
2386 else
2387 mpSaturdayColor = new Color( rColor );
2388 ImplUpdate();
2391 // -----------------------------------------------------------------------
2393 void Calendar::SetSundayColor( const Color& rColor )
2395 if ( mpSundayColor )
2396 *mpSundayColor = rColor;
2397 else
2398 mpSundayColor = new Color( rColor );
2399 ImplUpdate();
2402 // -----------------------------------------------------------------------
2404 void Calendar::AddDateInfo( const Date& rDate, const String& rText,
2405 const Color* pTextColor, const Color* pFrameColor,
2406 USHORT nFlags )
2408 if ( !mpDateTable )
2409 mpDateTable = new ImplDateTable( 256, 256 );
2411 BOOL bChanged = FALSE;
2412 ULONG nKey = rDate.GetDate();
2413 ImplDateInfo* pDateInfo = mpDateTable->Get( nKey );
2414 if ( pDateInfo )
2415 pDateInfo->maText = rText;
2416 else
2418 pDateInfo = new ImplDateInfo( rText );
2419 mpDateTable->Insert( nKey, pDateInfo );
2421 if ( pTextColor )
2423 if ( pDateInfo->mpTextColor )
2425 if ( *(pDateInfo->mpTextColor) != *pTextColor )
2427 *(pDateInfo->mpTextColor) = *pTextColor;
2428 bChanged = TRUE;
2431 else
2433 pDateInfo->mpTextColor = new Color( *pTextColor );
2434 bChanged = TRUE;
2437 else
2439 if ( pDateInfo->mpTextColor )
2441 delete pDateInfo->mpTextColor;
2442 pDateInfo->mpTextColor = NULL;
2443 bChanged = TRUE;
2446 if ( pFrameColor )
2448 if ( pDateInfo->mpFrameColor )
2450 if ( *(pDateInfo->mpFrameColor) != *pFrameColor )
2452 *(pDateInfo->mpFrameColor) = *pFrameColor;
2453 bChanged = TRUE;
2456 else
2458 pDateInfo->mpFrameColor = new Color( *pFrameColor );
2459 bChanged = TRUE;
2462 else
2464 if ( pDateInfo->mpFrameColor )
2466 delete pDateInfo->mpFrameColor;
2467 pDateInfo->mpFrameColor = NULL;
2468 bChanged = TRUE;
2471 if ( pDateInfo->mnFlags != nFlags )
2473 pDateInfo->mnFlags = nFlags;
2474 bChanged = TRUE;
2477 if ( bChanged )
2478 ImplUpdateDate( rDate );
2481 // -----------------------------------------------------------------------
2483 void Calendar::RemoveDateInfo( const Date& rDate )
2485 if ( mpDateTable )
2487 ImplDateInfo* pDateInfo = mpDateTable->Remove( rDate.GetDate() );
2488 if ( pDateInfo )
2490 delete pDateInfo;
2491 ImplUpdateDate( rDate );
2496 // -----------------------------------------------------------------------
2498 void Calendar::ClearDateInfo()
2500 if ( mpDateTable )
2502 ImplDateInfo* pDateInfo = mpDateTable->First();
2503 while ( pDateInfo )
2505 ULONG nKey = mpDateTable->GetCurKey();
2506 mpDateTable->Remove( nKey );
2507 Date aDate( nKey );
2508 ImplUpdateDate( aDate );
2509 delete pDateInfo;
2510 pDateInfo = mpDateTable->First();
2512 delete mpDateTable;
2513 mpDateTable = NULL;
2517 // -----------------------------------------------------------------------
2519 XubString Calendar::GetDateInfoText( const Date& rDate )
2521 XubString aRet;
2522 if ( mpDateTable )
2524 ULONG nKey = rDate.GetDate();
2525 ImplDateInfo* pDateInfo = mpDateTable->Get( nKey );
2526 if ( pDateInfo )
2527 aRet = pDateInfo->maText;
2529 return aRet;
2532 // -----------------------------------------------------------------------
2534 BOOL Calendar::ShowDropPos( const Point& rPos, Date& rDate )
2536 Date aTempDate = maCurDate;
2537 mnDragScrollHitTest = ImplHitTest( rPos, aTempDate );
2539 if ( mnDragScrollHitTest )
2541 if ( mnDragScrollHitTest & (CALENDAR_HITTEST_PREV | CALENDAR_HITTEST_NEXT) )
2543 if ( !maDragScrollTimer.IsActive() )
2544 maDragScrollTimer.Start();
2546 else
2548 maDragScrollTimer.Stop();
2549 if ( mnDragScrollHitTest & CALENDAR_HITTEST_DAY )
2551 if ( !mbDropPos || (aTempDate != maDropDate) )
2553 if( mbDropPos )
2554 ImplInvertDropPos();
2555 maDropDate = aTempDate;
2556 mbDropPos = TRUE;
2557 ImplInvertDropPos();
2560 rDate = maDropDate;
2561 return TRUE;
2565 else
2566 maDragScrollTimer.Stop();
2568 HideDropPos();
2569 return FALSE;
2572 // -----------------------------------------------------------------------
2574 void Calendar::HideDropPos()
2576 if ( mbDropPos )
2578 ImplInvertDropPos();
2579 mbDropPos = FALSE;
2583 // -----------------------------------------------------------------------
2585 void Calendar::StartSelection()
2587 if ( mpOldSelectTable )
2588 delete mpOldSelectTable;
2589 maOldCurDate = maCurDate;
2590 mpOldSelectTable = new Table( *mpSelectTable );
2592 mbSelection = TRUE;
2595 // -----------------------------------------------------------------------
2597 void Calendar::EndSelection()
2599 if ( mbDrag || mbSpinDown || mbSelection )
2601 if ( !mbSelection )
2602 ReleaseMouse();
2604 mbDrag = FALSE;
2605 mbSelection = FALSE;
2606 mbMultiSelection = FALSE;
2607 mbSpinDown = FALSE;
2608 mbPrevIn = FALSE;
2609 mbNextIn = FALSE;
2613 // -----------------------------------------------------------------------
2615 Size Calendar::CalcWindowSizePixel( long nCalcMonthPerLine,
2616 long nCalcLines ) const
2618 XubString a99Text( XubString( RTL_CONSTASCII_USTRINGPARAM( "99" ) ) );
2619 Font aOldFont = GetFont();
2621 // Wochenanzeige beruecksichtigen
2622 long nWeekWidth;
2623 if ( mnWinStyle & WB_WEEKNUMBER )
2625 Font aTempFont = aOldFont;
2626 ImplGetWeekFont( aTempFont );
2627 ((Calendar*)this)->SetFont( aTempFont );
2628 nWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
2629 ((Calendar*)this)->SetFont( aOldFont );
2631 else
2632 nWeekWidth = 0;
2634 if ( mnWinStyle & WB_BOLDTEXT )
2636 Font aFont = aOldFont;
2637 if ( aFont.GetWeight() < WEIGHT_BOLD )
2638 aFont.SetWeight( WEIGHT_BOLD );
2639 else
2640 aFont.SetWeight( WEIGHT_NORMAL );
2641 ((Calendar*)this)->SetFont( aFont );
2644 Size aSize;
2645 long n99TextWidth = GetTextWidth( a99Text );
2646 long nTextHeight = GetTextHeight();
2648 if ( mnWinStyle & WB_BOLDTEXT )
2649 ((Calendar*)this)->SetFont( aOldFont );
2651 aSize.Width() += ((n99TextWidth+DAY_OFFX)*7) + nWeekWidth;
2652 aSize.Width() += MONTH_BORDERX*2;
2653 aSize.Width() *= nCalcMonthPerLine;
2655 aSize.Height() = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
2656 aSize.Height() += nTextHeight + WEEKDAY_OFFY;
2657 aSize.Height() += ((nTextHeight+DAY_OFFY)*6);
2658 aSize.Height() += MONTH_OFFY;
2659 aSize.Height() *= nCalcLines;
2661 return aSize;
2664 // =======================================================================
2666 #define CALFIELD_EXTRA_BUTTON_WIDTH 14
2667 #define CALFIELD_EXTRA_BUTTON_HEIGHT 8
2668 #define CALFIELD_SEP_X 6
2669 #define CALFIELD_BORDERLINE_X 5
2670 #define CALFIELD_BORDER_YTOP 4
2671 #define CALFIELD_BORDER_Y 5
2673 // =======================================================================
2675 class ImplCFieldFloatWin : public FloatingWindow
2677 private:
2678 Calendar* mpCalendar;
2679 PushButton* mpTodayBtn;
2680 PushButton* mpNoneBtn;
2681 FixedLine* mpFixedLine;
2683 public:
2684 ImplCFieldFloatWin( Window* pParent );
2685 ~ImplCFieldFloatWin();
2687 void SetCalendar( Calendar* pCalendar )
2688 { mpCalendar = pCalendar; }
2690 PushButton* EnableTodayBtn( BOOL bEnable );
2691 PushButton* EnableNoneBtn( BOOL bEnable );
2692 void ArrangeButtons();
2694 long Notify( NotifyEvent& rNEvt );
2697 // -----------------------------------------------------------------------
2699 ImplCFieldFloatWin::ImplCFieldFloatWin( Window* pParent ) :
2700 FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW )
2702 mpCalendar = NULL;
2703 mpTodayBtn = NULL;
2704 mpNoneBtn = NULL;
2705 mpFixedLine = NULL;
2708 // -----------------------------------------------------------------------
2710 ImplCFieldFloatWin::~ImplCFieldFloatWin()
2712 delete mpTodayBtn;
2713 delete mpNoneBtn;
2714 delete mpFixedLine;
2717 // -----------------------------------------------------------------------
2719 PushButton* ImplCFieldFloatWin::EnableTodayBtn( BOOL bEnable )
2721 if ( bEnable )
2723 if ( !mpTodayBtn )
2725 mpTodayBtn = new PushButton( this, WB_NOPOINTERFOCUS );
2726 XubString aTodayText( SvtResId( STR_SVT_CALENDAR_TODAY ) );
2727 mpTodayBtn->SetText( aTodayText );
2728 Size aSize;
2729 aSize.Width() = mpTodayBtn->GetCtrlTextWidth( mpTodayBtn->GetText() );
2730 aSize.Height() = mpTodayBtn->GetTextHeight();
2731 aSize.Width() += CALFIELD_EXTRA_BUTTON_WIDTH;
2732 aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
2733 mpTodayBtn->SetSizePixel( aSize );
2734 mpTodayBtn->Show();
2737 else
2739 if ( mpTodayBtn )
2741 delete mpTodayBtn;
2742 mpTodayBtn = NULL;
2746 return mpTodayBtn;
2749 // -----------------------------------------------------------------------
2751 PushButton* ImplCFieldFloatWin::EnableNoneBtn( BOOL bEnable )
2753 if ( bEnable )
2755 if ( !mpNoneBtn )
2757 mpNoneBtn = new PushButton( this, WB_NOPOINTERFOCUS );
2758 XubString aNoneText( SvtResId( STR_SVT_CALENDAR_NONE ) );
2759 mpNoneBtn->SetText( aNoneText );
2760 Size aSize;
2761 aSize.Width() = mpNoneBtn->GetCtrlTextWidth( mpNoneBtn->GetText() );
2762 aSize.Height() = mpNoneBtn->GetTextHeight();
2763 aSize.Width() += CALFIELD_EXTRA_BUTTON_WIDTH;
2764 aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
2765 mpNoneBtn->SetSizePixel( aSize );
2766 mpNoneBtn->Show();
2769 else
2771 if ( mpNoneBtn )
2773 delete mpNoneBtn;
2774 mpNoneBtn = NULL;
2778 return mpNoneBtn;
2781 // -----------------------------------------------------------------------
2783 void ImplCFieldFloatWin::ArrangeButtons()
2785 long nBtnHeight = 0;
2786 long nBtnWidth = 0;
2787 Size aOutSize = GetOutputSizePixel();
2788 if ( mpTodayBtn && mpNoneBtn )
2790 Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
2791 Size aNoneBtnSize = mpNoneBtn->GetSizePixel();
2792 if ( aTodayBtnSize.Width() < aNoneBtnSize.Width() )
2793 aTodayBtnSize.Width() = aNoneBtnSize.Width();
2794 else
2795 aNoneBtnSize.Width() = aTodayBtnSize.Width();
2796 if ( aTodayBtnSize.Height() < aNoneBtnSize.Height() )
2797 aTodayBtnSize.Height() = aNoneBtnSize.Height();
2798 else
2799 aNoneBtnSize.Height() = aTodayBtnSize.Height();
2801 nBtnWidth = aTodayBtnSize.Width() + aNoneBtnSize.Width() + CALFIELD_SEP_X;
2802 nBtnHeight = aTodayBtnSize.Height();
2803 long nX = (aOutSize.Width()-nBtnWidth)/2;
2804 long nY = aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP;
2805 mpTodayBtn->SetPosSizePixel( Point( nX, nY ), aTodayBtnSize );
2806 nX += aTodayBtnSize.Width() + CALFIELD_SEP_X;
2807 mpNoneBtn->SetPosSizePixel( Point( nX, nY ), aNoneBtnSize );
2809 else if ( mpTodayBtn )
2811 Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
2812 nBtnWidth = aTodayBtnSize.Width();
2813 nBtnHeight = aTodayBtnSize.Height();
2814 mpTodayBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
2816 else if ( mpNoneBtn )
2818 Size aNoneBtnSize = mpNoneBtn->GetSizePixel();
2819 nBtnWidth = aNoneBtnSize.Width();
2820 nBtnHeight = aNoneBtnSize.Height();
2821 mpNoneBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
2824 if ( nBtnHeight )
2826 if ( !mpFixedLine )
2828 mpFixedLine = new FixedLine( this );
2829 mpFixedLine->Show();
2831 long nLineWidth = aOutSize.Width()-(CALFIELD_BORDERLINE_X*2);
2832 mpFixedLine->SetPosSizePixel( (aOutSize.Width()-nLineWidth)/2, aOutSize.Height()+((CALFIELD_BORDER_YTOP-2)/2),
2833 nLineWidth, 2, WINDOW_POSSIZE_POSSIZE );
2834 aOutSize.Height() += nBtnHeight + (CALFIELD_BORDER_Y*2) + CALFIELD_BORDER_YTOP;
2835 SetOutputSizePixel( aOutSize );
2837 else
2839 if ( mpFixedLine )
2841 delete mpFixedLine;
2842 mpFixedLine = NULL;
2847 // -----------------------------------------------------------------------
2849 long ImplCFieldFloatWin::Notify( NotifyEvent& rNEvt )
2851 if ( rNEvt.GetType() == EVENT_KEYINPUT )
2853 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
2854 if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
2855 mpCalendar->Select();
2858 return FloatingWindow::Notify( rNEvt );
2861 // =======================================================================
2863 CalendarField::CalendarField( Window* pParent, WinBits nWinStyle ) :
2864 DateField( pParent, nWinStyle ),
2865 maDefaultDate( 0, 0, 0 )
2867 mpFloatWin = NULL;
2868 mpCalendar = NULL;
2869 mnCalendarStyle = 0;
2870 mbToday = FALSE;
2871 mbNone = FALSE;
2874 // -----------------------------------------------------------------------
2876 CalendarField::CalendarField( Window* pParent, const ResId& rResId ) :
2877 DateField( pParent, rResId ),
2878 maDefaultDate( 0, 0, 0 )
2880 mpFloatWin = NULL;
2881 mpCalendar = NULL;
2882 mnCalendarStyle = 0;
2883 mbToday = FALSE;
2884 mbNone = FALSE;
2887 // -----------------------------------------------------------------------
2889 CalendarField::~CalendarField()
2891 if ( mpFloatWin )
2893 delete mpCalendar;
2894 delete mpFloatWin;
2898 // -----------------------------------------------------------------------
2900 IMPL_LINK( CalendarField, ImplSelectHdl, Calendar*, pCalendar )
2902 if ( !pCalendar->IsTravelSelect() )
2904 mpFloatWin->EndPopupMode();
2905 EndDropDown();
2906 GrabFocus();
2907 Date aNewDate = mpCalendar->GetSelectDate( 0 );
2908 if ( IsEmptyDate() || ( aNewDate != GetDate() ) )
2910 SetDate( aNewDate );
2911 SetModifyFlag();
2912 Modify();
2914 Select();
2916 return 0;
2919 // -----------------------------------------------------------------------
2921 IMPL_LINK( CalendarField, ImplClickHdl, PushButton*, pBtn )
2923 mpFloatWin->EndPopupMode();
2924 EndDropDown();
2925 GrabFocus();
2927 if ( pBtn == mpTodayBtn )
2929 Date aToday;
2930 if ( (aToday != GetDate()) || IsEmptyDate() )
2932 SetDate( aToday );
2933 SetModifyFlag();
2934 Modify();
2937 else if ( pBtn == mpNoneBtn )
2939 if ( !IsEmptyDate() )
2941 SetEmptyDate();
2942 SetModifyFlag();
2943 Modify();
2946 Select();
2948 return 0;
2951 // -----------------------------------------------------------------------
2953 IMPL_LINK( CalendarField, ImplPopupModeEndHdl, FloatingWindow*, EMPTYARG )
2955 EndDropDown();
2956 GrabFocus();
2957 mpCalendar->EndSelection();
2958 return 0;
2961 // -----------------------------------------------------------------------
2963 void CalendarField::Select()
2965 maSelectHdl.Call( this );
2968 // -----------------------------------------------------------------------
2970 BOOL CalendarField::ShowDropDown( BOOL bShow )
2972 if ( bShow )
2974 Calendar* pCalendar = GetCalendar();
2976 Date aDate = GetDate();
2977 if ( IsEmptyDate() || !aDate.IsValid() )
2979 if ( maDefaultDate.IsValid() )
2980 aDate = maDefaultDate;
2981 else
2982 aDate = Date();
2984 if ( pCalendar->GetStyle() & (WB_RANGESELECT | WB_MULTISELECT) )
2986 pCalendar->SetNoSelection();
2987 pCalendar->SelectDate( aDate );
2989 pCalendar->SetCurDate( aDate );
2990 Point aPos( GetParent()->OutputToScreenPixel( GetPosPixel() ) );
2991 Rectangle aRect( aPos, GetSizePixel() );
2992 aRect.Bottom() -= 1;
2993 mpCalendar->SetOutputSizePixel( mpCalendar->CalcWindowSizePixel() );
2994 mpFloatWin->SetOutputSizePixel( mpCalendar->GetSizePixel() );
2995 mpFloatWin->SetCalendar( mpCalendar );
2996 mpTodayBtn = mpFloatWin->EnableTodayBtn( mbToday );
2997 mpNoneBtn = mpFloatWin->EnableNoneBtn( mbNone );
2998 if ( mpTodayBtn )
2999 mpTodayBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
3000 if ( mpNoneBtn )
3001 mpNoneBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
3002 mpFloatWin->ArrangeButtons();
3003 mpCalendar->EnableCallEverySelect();
3004 mpCalendar->StartSelection();
3005 mpCalendar->GrabFocus();
3006 mpCalendar->Show();
3007 mpFloatWin->StartPopupMode( aRect, FLOATWIN_POPUPMODE_NOFOCUSCLOSE|FLOATWIN_POPUPMODE_DOWN );
3009 else
3011 mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
3012 mpCalendar->EndSelection();
3013 EndDropDown();
3015 return TRUE;
3018 // -----------------------------------------------------------------------
3020 Calendar* CalendarField::CreateCalendar( Window* pParent )
3022 return new Calendar( pParent, mnCalendarStyle | WB_TABSTOP );
3025 // -----------------------------------------------------------------------
3027 Calendar* CalendarField::GetCalendar()
3029 if ( !mpFloatWin )
3031 mpFloatWin = new ImplCFieldFloatWin( this );
3032 mpFloatWin->SetPopupModeEndHdl( LINK( this, CalendarField, ImplPopupModeEndHdl ) );
3033 mpCalendar = CreateCalendar( mpFloatWin );
3034 mpCalendar->SetPosPixel( Point() );
3035 mpCalendar->SetSelectHdl( LINK( this, CalendarField, ImplSelectHdl ) );
3038 return mpCalendar;
3041 // -----------------------------------------------------------------------
3043 void CalendarField::StateChanged( StateChangedType nStateChange )
3045 DateField::StateChanged( nStateChange );
3047 if ( ( nStateChange == STATE_CHANGE_STYLE ) && GetSubEdit() )
3049 WinBits nAllAlignmentBits = ( WB_LEFT | WB_CENTER | WB_RIGHT | WB_TOP | WB_VCENTER | WB_BOTTOM );
3050 WinBits nMyAlignment = GetStyle() & nAllAlignmentBits;
3051 GetSubEdit()->SetStyle( ( GetSubEdit()->GetStyle() & ~nAllAlignmentBits ) | nMyAlignment );