xref: /AOO41X/main/svtools/source/control/calendar.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 
27 #include <vcl/svapp.hxx>
28 #include <tools/table.hxx>
29 #include <vcl/help.hxx>
30 #include <vcl/menu.hxx>
31 #include <vcl/decoview.hxx>
32 #include <vcl/floatwin.hxx>
33 #include <vcl/button.hxx>
34 #include <vcl/fixed.hxx>
35 #include <unotools/calendarwrapper.hxx>
36 #include <unotools/localedatawrapper.hxx>
37 #include <com/sun/star/i18n/Weekdays.hpp>
38 #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
39 #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
40 
41 #define _SV_CALENDAR_CXX
42 #include <svtools/svtools.hrc>
43 #include <svtools/svtdata.hxx>
44 #include <svtools/calendar.hxx>
45 
46 // =======================================================================
47 
48 #define DAY_OFFX                        4
49 #define DAY_OFFY                        2
50 #define MONTH_BORDERX                   4
51 #define MONTH_OFFY                      3
52 #define WEEKNUMBER_OFFX                 4
53 #define WEEKDAY_OFFY                    3
54 #define TITLE_OFFY                      3
55 #define TITLE_BORDERY                   2
56 #define SPIN_OFFX                       4
57 #define SPIN_OFFY                       TITLE_BORDERY
58 
59 #define WEEKNUMBER_HEIGHT               85
60 
61 #define CALENDAR_HITTEST_DAY            ((sal_uInt16)0x0001)
62 #define CALENDAR_HITTEST_WEEK           ((sal_uInt16)0x0002)
63 #define CALENDAR_HITTEST_MONTHTITLE     ((sal_uInt16)0x0004)
64 #define CALENDAR_HITTEST_PREV           ((sal_uInt16)0x0008)
65 #define CALENDAR_HITTEST_NEXT           ((sal_uInt16)0x0010)
66 #define CALENDAR_HITTEST_OUTSIDE        ((sal_uInt16)0x1000)
67 
68 #define MENU_YEAR_COUNT                 3
69 
70 #define TABLE_DATE_SELECTED             ((void*)0x00000001)
71 
72 using namespace ::com::sun::star;
73 
74 // =======================================================================
75 
76 struct ImplDateInfo
77 {
78     XubString   maText;
79     Color*      mpTextColor;
80     Color*      mpFrameColor;
81     sal_uInt16      mnFlags;
82 
ImplDateInfoImplDateInfo83                 ImplDateInfo( const XubString& rText ) :
84                     maText( rText )
85                 { mpTextColor = mpFrameColor = NULL; mnFlags = 0; }
~ImplDateInfoImplDateInfo86                 ~ImplDateInfo() { delete mpTextColor; delete mpFrameColor; }
87 };
88 
DECLARE_TABLE(ImplDateTable,ImplDateInfo *)89 DECLARE_TABLE( ImplDateTable, ImplDateInfo* )
90 
91 // =======================================================================
92 
93 static void ImplCalendarSelectDate( Table* pTable, const Date& rDate, sal_Bool bSelect )
94 {
95     if ( bSelect )
96         pTable->Insert( rDate.GetDate(), TABLE_DATE_SELECTED );
97     else
98         pTable->Remove( rDate.GetDate() );
99 }
100 
101 // -----------------------------------------------------------------------
102 
ImplCalendarSelectDateRange(Table * pTable,const Date & rStartDate,const Date & rEndDate,sal_Bool bSelect)103 static void ImplCalendarSelectDateRange( Table* pTable,
104                                          const Date& rStartDate,
105                                          const Date& rEndDate,
106                                          sal_Bool bSelect )
107 {
108     Date aStartDate = rStartDate;
109     Date aEndDate = rEndDate;
110     if ( aStartDate > aEndDate )
111     {
112         Date aTempDate = aStartDate;
113         aStartDate = aEndDate;
114         aEndDate = aTempDate;
115     }
116 
117     if ( bSelect )
118     {
119         while ( aStartDate <= aEndDate )
120         {
121             pTable->Insert( aStartDate.GetDate(), TABLE_DATE_SELECTED );
122             aStartDate++;
123         }
124     }
125     else
126     {
127         void* p = pTable->First();
128         while ( p )
129         {
130             Date aDate( pTable->GetCurKey() );
131             if ( aDate > aEndDate )
132                 break;
133 
134             if ( aDate >= aStartDate )
135                 pTable->Remove( aDate.GetDate() );
136             else
137                 p = pTable->Next();
138         }
139     }
140 }
141 
142 // -----------------------------------------------------------------------
143 
ImplCalendarUnSelectDateRange(Table * pTable,Table * pOldTable,const Date & rStartDate,const Date & rEndDate)144 static void ImplCalendarUnSelectDateRange( Table* pTable,
145                                            Table* pOldTable,
146                                            const Date& rStartDate,
147                                            const Date& rEndDate )
148 {
149     Date aStartDate = rStartDate;
150     Date aEndDate = rEndDate;
151     if ( aStartDate > aEndDate )
152     {
153         Date aTempDate = aStartDate;
154         aStartDate = aEndDate;
155         aEndDate = aTempDate;
156     }
157 
158     void* p = pTable->First();
159     while ( p )
160     {
161         Date aDate( pTable->GetCurKey() );
162         if ( aDate > aEndDate )
163             break;
164 
165         if ( aDate >= aStartDate )
166             pTable->Remove( aDate.GetDate() );
167         else
168             p = pTable->Next();
169     }
170 
171     p = pOldTable->First();
172     while ( p )
173     {
174         Date aDate( pOldTable->GetCurKey() );
175         if ( aDate > aEndDate )
176             break;
177         if ( aDate >= aStartDate )
178             pTable->Insert( aDate.GetDate(), TABLE_DATE_SELECTED );
179 
180         p = pOldTable->Next();
181     }
182 }
183 
184 // -----------------------------------------------------------------------
185 
ImplCalendarClearSelectDate(Table * pTable)186 inline void ImplCalendarClearSelectDate( Table* pTable )
187 {
188     pTable->Clear();
189 }
190 
191 // =======================================================================
192 
ImplInit(WinBits nWinStyle)193 void Calendar::ImplInit( WinBits nWinStyle )
194 {
195     mpDateTable             = NULL;
196     mpSelectTable           = new Table;
197     mpOldSelectTable        = NULL;
198     mpRestoreSelectTable    = NULL;
199     mpStandardColor         = NULL;
200     mpSaturdayColor         = NULL;
201     mpSundayColor           = NULL;
202     mnDayCount              = 0;
203     mnWinStyle              = nWinStyle;
204     mnFirstYear             = 0;
205     mnLastYear              = 0;
206     mnRequestYear           = 0;
207     mbCalc                  = sal_True;
208     mbFormat                = sal_True;
209     mbDrag                  = sal_False;
210     mbSelection             = sal_False;
211     mbMultiSelection        = sal_False;
212     mbWeekSel               = sal_False;
213     mbUnSel                 = sal_False;
214     mbMenuDown              = sal_False;
215     mbSpinDown              = sal_False;
216     mbPrevIn                = sal_False;
217     mbNextIn                = sal_False;
218     mbDirect                = sal_False;
219     mbInSelChange           = sal_False;
220     mbTravelSelect          = sal_False;
221     mbScrollDateRange       = sal_False;
222     mbSelLeft               = sal_False;
223     mbAllSel                = sal_False;
224     mbDropPos               = sal_False;
225 
226     ::rtl::OUString aGregorian( RTL_CONSTASCII_USTRINGPARAM( "gregorian"));
227     maCalendarWrapper.loadCalendar( aGregorian,
228             Application::GetAppLocaleDataWrapper().getLocale());
229     if (maCalendarWrapper.getUniqueID() != aGregorian)
230     {
231 #ifdef DBG_UTIL
232         ByteString aMsg( "Calendar::ImplInit: No ``gregorian'' calendar available for locale ``");
233         lang::Locale aLoc( Application::GetAppLocaleDataWrapper().getLocale());
234         aMsg += ByteString( String( aLoc.Language), RTL_TEXTENCODING_UTF8);
235         aMsg += '-';
236         aMsg += ByteString( String( aLoc.Country), RTL_TEXTENCODING_UTF8);
237         aMsg += "'' and other calendars aren't supported. Using en-US fallback.";
238         DBG_ERRORFILE( aMsg.GetBuffer());
239 #endif
240         /* If we ever wanted to support other calendars than Gregorian a lot of
241          * rewrite would be necessary to internally replace use of class Date
242          * with proper class CalendarWrapper methods, get rid of fixed 12
243          * months, fixed 7 days, ... */
244         maCalendarWrapper.loadCalendar( aGregorian, lang::Locale(
245                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "en")),
246                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "US")),
247                     ::rtl::OUString()));
248     }
249 
250     SetFirstDate( maCurDate );
251     ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
252 
253     // Sonstige Strings erzeugen
254     maDayText = XubString( SvtResId( STR_SVT_CALENDAR_DAY ) );
255     maWeekText = XubString( SvtResId( STR_SVT_CALENDAR_WEEK ) );
256 
257     // Tagestexte anlegen
258     for ( sal_uInt16 i = 0; i < 31; i++ )
259         mpDayText[i] = new UniString( UniString::CreateFromInt32( i+1 ) );
260 
261     maDragScrollTimer.SetTimeoutHdl( STATIC_LINK( this, Calendar, ScrollHdl ) );
262     maDragScrollTimer.SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
263     mnDragScrollHitTest = 0;
264 
265     ImplInitSettings();
266 }
267 
268 // -----------------------------------------------------------------------
269 
ImplInitSettings()270 void Calendar::ImplInitSettings()
271 {
272     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
273     maSelColor = rStyleSettings.GetHighlightTextColor();
274     SetPointFont( rStyleSettings.GetToolFont() );
275     SetTextColor( rStyleSettings.GetFieldTextColor() );
276     SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
277 }
278 
279 // -----------------------------------------------------------------------
280 
Calendar(Window * pParent,WinBits nWinStyle)281 Calendar::Calendar( Window* pParent, WinBits nWinStyle ) :
282     Control( pParent, nWinStyle & (WB_TABSTOP | WB_GROUP | WB_BORDER | WB_3DLOOK | WB_RANGESELECT | WB_MULTISELECT) ),
283     maCalendarWrapper( Application::GetAppLocaleDataWrapper().getServiceFactory() ),
284     maOldFormatFirstDate( 0, 0, 1900 ),
285     maOldFormatLastDate( 0, 0, 1900 ),
286     maFirstDate( 0, 0, 1900 ),
287     maOldFirstDate( 0, 0, 1900 ),
288     maOldCurDate( 0, 0, 1900 ),
289     maAnchorDate( maCurDate ),
290     maDropDate( 0, 0, 1900 )
291 {
292     ImplInit( nWinStyle );
293 }
294 
295 // -----------------------------------------------------------------------
296 
Calendar(Window * pParent,const ResId & rResId)297 Calendar::Calendar( Window* pParent, const ResId& rResId ) :
298     Control( pParent, rResId ),
299     maCalendarWrapper( Application::GetAppLocaleDataWrapper().getServiceFactory() ),
300     maOldFormatFirstDate( 0, 0, 1900 ),
301     maOldFormatLastDate( 0, 0, 1900 ),
302     maFirstDate( 0, 0, 1900 ),
303     maOldFirstDate( 0, 0, 1900 ),
304     maOldCurDate( 0, 0, 1900 ),
305     maAnchorDate( maCurDate ),
306     maDropDate( 0, 0, 1900 )
307 {
308     ImplInit( rResId.GetWinBits() );
309 }
310 
311 // -----------------------------------------------------------------------
312 
~Calendar()313 Calendar::~Calendar()
314 {
315     delete mpStandardColor;
316     delete mpSaturdayColor;
317     delete mpSundayColor;
318 
319     if ( mpDateTable )
320     {
321         ImplDateInfo* pDateInfo = mpDateTable->First();
322         while ( pDateInfo )
323         {
324             delete pDateInfo;
325             pDateInfo = mpDateTable->Next();
326         }
327 
328         delete mpDateTable;
329     }
330 
331     delete mpSelectTable;
332     if ( mpOldSelectTable )
333         delete mpOldSelectTable;
334     if ( mpRestoreSelectTable )
335         delete mpRestoreSelectTable;
336 
337     for ( sal_uInt16 i = 0; i < 31; i++ )
338         delete mpDayText[i];
339 }
340 
341 // -----------------------------------------------------------------------
342 
SetMinimumNumberOfDaysInWeek(sal_Int16 nDays)343 void Calendar::SetMinimumNumberOfDaysInWeek( sal_Int16 nDays )
344 {
345     ImplUpdate( sal_True );
346     maCalendarWrapper.setMinimumNumberOfDaysForFirstWeek( nDays);
347 }
348 
349 // -----------------------------------------------------------------------
350 
SetWeekStart(sal_Int16 nDay)351 void Calendar::SetWeekStart( sal_Int16 nDay )
352 {
353     ImplUpdate( sal_True );
354     switch (nDay)
355     {
356         case i18n::Weekdays::SUNDAY :
357         case i18n::Weekdays::MONDAY :
358         case i18n::Weekdays::TUESDAY :
359         case i18n::Weekdays::WEDNESDAY :
360         case i18n::Weekdays::THURSDAY :
361         case i18n::Weekdays::FRIDAY :
362         case i18n::Weekdays::SATURDAY :
363             ;   // nothing
364         default:
365             DBG_ERRORFILE("Calendar::SetWeekStart: unknown value for setFirstDayOfWeek() of a Gregorian calendar");
366             nDay = i18n::Weekdays::SUNDAY;
367     }
368     maCalendarWrapper.setFirstDayOfWeek( nDay);
369 }
370 
371 // -----------------------------------------------------------------------
372 
ImplGetWeekStart() const373 DayOfWeek Calendar::ImplGetWeekStart() const
374 {
375     // Map i18n::Weekdays to Date DayOfWeek
376     DayOfWeek eDay;
377     sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
378     switch (nDay)
379     {
380         case i18n::Weekdays::SUNDAY :
381             eDay = SUNDAY;
382             break;
383         case i18n::Weekdays::MONDAY :
384             eDay = MONDAY;
385             break;
386         case i18n::Weekdays::TUESDAY :
387             eDay = TUESDAY;
388             break;
389         case i18n::Weekdays::WEDNESDAY :
390             eDay = WEDNESDAY;
391             break;
392         case i18n::Weekdays::THURSDAY :
393             eDay = THURSDAY;
394             break;
395         case i18n::Weekdays::FRIDAY :
396             eDay = FRIDAY;
397             break;
398         case i18n::Weekdays::SATURDAY :
399             eDay = SATURDAY;
400             break;
401         default:
402             DBG_ERRORFILE("Calendar::ImplGetWeekStart: broken i18n Gregorian calendar (getFirstDayOfWeek())");
403             eDay = SUNDAY;
404     }
405     return eDay;
406 }
407 
408 // -----------------------------------------------------------------------
409 
ImplGetWeekFont(Font & rFont) const410 void Calendar::ImplGetWeekFont( Font& rFont ) const
411 {
412     // Wochennummer geben wir in WEEKNUMBER_HEIGHT%-Fonthoehe aus
413     Size aFontSize = rFont.GetSize();
414     aFontSize.Height() *= WEEKNUMBER_HEIGHT;
415     aFontSize.Height() /= 100;
416     rFont.SetSize( aFontSize );
417     rFont.SetWeight( WEIGHT_NORMAL );
418 }
419 
420 // -----------------------------------------------------------------------
421 
ImplFormat()422 void Calendar::ImplFormat()
423 {
424     if ( !mbFormat )
425         return;
426 
427     if ( mbCalc )
428     {
429         Size aOutSize = GetOutputSizePixel();
430 
431         if ( (aOutSize.Width() <= 1) || (aOutSize.Height() <= 1) )
432             return;
433 
434         XubString a99Text( XubString( RTL_CONSTASCII_USTRINGPARAM( "99" ) ) );
435 
436         Font aOldFont = GetFont();
437 
438         // Wochenanzeige beruecksichtigen
439         if ( mnWinStyle & WB_WEEKNUMBER )
440         {
441             Font aTempFont = aOldFont;
442             ImplGetWeekFont( aTempFont );
443             SetFont( aTempFont );
444             mnWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
445             SetFont( aOldFont );
446         }
447         else
448             mnWeekWidth = 0;
449 
450         if ( mnWinStyle & WB_BOLDTEXT )
451         {
452             Font aFont = aOldFont;
453             if ( aFont.GetWeight() < WEIGHT_BOLD )
454                 aFont.SetWeight( WEIGHT_BOLD );
455             else
456                 aFont.SetWeight( WEIGHT_NORMAL );
457             SetFont( aFont );
458         }
459 
460         long n99TextWidth = GetTextWidth( a99Text );
461         long nTextHeight = GetTextHeight();
462 
463         // Breiten und X-Positionen berechnen
464         mnDayWidth      = n99TextWidth+DAY_OFFX;
465         mnMonthWidth    = mnDayWidth*7;
466         mnMonthWidth   += mnWeekWidth;
467         mnMonthWidth   += MONTH_BORDERX*2;
468         mnMonthPerLine  = aOutSize.Width() / mnMonthWidth;
469         if ( !mnMonthPerLine )
470             mnMonthPerLine = 1;
471         long nOver      = ((aOutSize.Width()-(mnMonthPerLine*mnMonthWidth)) / mnMonthPerLine);
472         mnMonthWidth   += nOver;
473         mnDaysOffX      = MONTH_BORDERX;
474         mnDaysOffX     += nOver/2;
475         mnDaysOffX     += mnWeekWidth;
476 
477         // Hoehen und Y-Positionen berechnen
478         mnDayHeight     = nTextHeight + DAY_OFFY;
479         mnWeekDayOffY   = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
480         mnDaysOffY      = mnWeekDayOffY + nTextHeight + WEEKDAY_OFFY;
481         mnMonthHeight   = (mnDayHeight*6) + mnDaysOffY;
482         mnMonthHeight  += MONTH_OFFY;
483         mnLines         = aOutSize.Height() / mnMonthHeight;
484         if ( !mnLines )
485             mnLines = 1;
486         mnMonthHeight  += (aOutSize.Height()-(mnLines*mnMonthHeight)) / mnLines;
487 
488         // Spinfelder berechnen
489         long nSpinSize      = nTextHeight+TITLE_BORDERY-SPIN_OFFY;
490         maPrevRect.Left()   = SPIN_OFFX;
491         maPrevRect.Top()    = SPIN_OFFY;
492         maPrevRect.Right()  = maPrevRect.Left()+nSpinSize;
493         maPrevRect.Bottom() = maPrevRect.Top()+nSpinSize;
494         maNextRect.Left()   = aOutSize.Width()-SPIN_OFFX-nSpinSize-1;
495         maNextRect.Top()    = SPIN_OFFY;
496         maNextRect.Right()  = maNextRect.Left()+nSpinSize;
497         maNextRect.Bottom() = maNextRect.Top()+nSpinSize;
498 
499         if ( mnWinStyle & WB_BOLDTEXT )
500             SetFont( aOldFont );
501 
502         // Calculate DayOfWeekText (gets displayed in a narrow font)
503         maDayOfWeekText.Erase();
504         long nStartOffX = 0;
505         sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
506         for ( sal_Int16 nDayOfWeek = 0; nDayOfWeek < 7; nDayOfWeek++ )
507         {
508             // Use first character of full name, since the abbreviated name may
509             // be roman digits or similar in some locales. Proper
510             // implementation would need narrow one letter month names defined
511             // in locale data.
512             String aDayOfWeek( maCalendarWrapper.getDisplayName(
513                         i18n::CalendarDisplayIndex::DAY, nDay, 1).GetChar(0));
514             long nOffX = (mnDayWidth-GetTextWidth( aDayOfWeek ))/2;
515             if ( mnWinStyle & WB_BOLDTEXT )
516                 nOffX++;
517             if ( !nDayOfWeek )
518                 nStartOffX = nOffX;
519             else
520                 nOffX -= nStartOffX;
521             nOffX += nDayOfWeek * mnDayWidth;
522             mnDayOfWeekAry[nDayOfWeek] = nOffX;
523             maDayOfWeekText += aDayOfWeek;
524             nDay++;
525             nDay %= 7;
526         }
527 
528         mbCalc = sal_False;
529     }
530 
531     // Anzahl Tage berechnen
532 
533     DayOfWeek eStartDay = ImplGetWeekStart();
534 
535     sal_uInt16 nWeekDay;
536     Date aTempDate = GetFirstMonth();
537     maFirstDate = aTempDate;
538     nWeekDay = (sal_uInt16)aTempDate.GetDayOfWeek();
539     nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
540     maFirstDate -= (sal_uLong)nWeekDay;
541     mnDayCount = nWeekDay;
542     sal_uInt16 nDaysInMonth;
543     sal_uInt16 nMonthCount = (sal_uInt16)(mnMonthPerLine*mnLines);
544     for ( sal_uInt16 i = 0; i < nMonthCount; i++ )
545     {
546         nDaysInMonth = aTempDate.GetDaysInMonth();
547         mnDayCount += nDaysInMonth;
548         aTempDate += nDaysInMonth;
549     }
550     Date aTempDate2 = aTempDate;
551     aTempDate2--;
552     nDaysInMonth = aTempDate2.GetDaysInMonth();
553     aTempDate2 -= nDaysInMonth-1;
554     nWeekDay = (sal_uInt16)aTempDate2.GetDayOfWeek();
555     nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
556     mnDayCount += 42-nDaysInMonth-nWeekDay;
557 
558     // Farben festlegen
559     maOtherColor = Color( COL_LIGHTGRAY );
560     if ( maOtherColor.IsRGBEqual( GetBackground().GetColor() ) )
561         maOtherColor.SetColor( COL_GRAY );
562 
563     Date aLastDate = GetLastDate();
564     if ( (maOldFormatLastDate != aLastDate) ||
565          (maOldFormatFirstDate != maFirstDate) )
566     {
567         maOldFormatFirstDate = maFirstDate;
568         maOldFormatLastDate  = aLastDate;
569         DateRangeChanged();
570     }
571 
572     // DateInfo besorgen
573     sal_uInt16 nNewFirstYear = maFirstDate.GetYear();
574     sal_uInt16 nNewLastYear = GetLastDate().GetYear();
575     if ( mnFirstYear )
576     {
577         if ( nNewFirstYear < mnFirstYear )
578         {
579             for ( mnRequestYear = nNewFirstYear; mnRequestYear < mnFirstYear; mnRequestYear++ )
580                 RequestDateInfo();
581             mnFirstYear = nNewFirstYear;
582         }
583         if ( nNewLastYear > mnLastYear )
584         {
585             for ( mnRequestYear = mnLastYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
586                 RequestDateInfo();
587             mnLastYear = nNewLastYear;
588         }
589     }
590     else
591     {
592         for ( mnRequestYear = nNewFirstYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
593             RequestDateInfo();
594         mnFirstYear = nNewFirstYear;
595         mnLastYear = nNewLastYear;
596     }
597     mnRequestYear = 0;
598 
599     mbFormat = sal_False;
600 }
601 
602 // -----------------------------------------------------------------------
603 
ImplHitTest(const Point & rPos,Date & rDate) const604 sal_uInt16 Calendar::ImplHitTest( const Point& rPos, Date& rDate ) const
605 {
606     if ( mbFormat )
607         return 0;
608 
609     if ( maPrevRect.IsInside( rPos ) )
610         return CALENDAR_HITTEST_PREV;
611     else if ( maNextRect.IsInside( rPos ) )
612         return CALENDAR_HITTEST_NEXT;
613 
614     long        nX;
615     long        nY;
616     long        nOffX;
617     long        nYMonth;
618     sal_uInt16      nDay;
619     DayOfWeek   eStartDay = ImplGetWeekStart();
620 
621     rDate = GetFirstMonth();
622     nY = 0;
623     for ( long i = 0; i < mnLines; i++ )
624     {
625         if ( rPos.Y() < nY )
626             return 0;
627 
628         nX = 0;
629         nYMonth = nY+mnMonthHeight;
630         for ( long j = 0; j < mnMonthPerLine; j++ )
631         {
632             if ( (rPos.X() < nX) && (rPos.Y() < nYMonth) )
633                 return 0;
634 
635             sal_uInt16 nDaysInMonth = rDate.GetDaysInMonth();
636 
637             // Entsprechender Monat gefunden
638             if ( (rPos.X() > nX) && (rPos.Y() < nYMonth) &&
639                  (rPos.X() < nX+mnMonthWidth) )
640             {
641                 if ( rPos.Y() < (nY+(TITLE_BORDERY*2)+mnDayHeight))
642                     return CALENDAR_HITTEST_MONTHTITLE;
643                 else
644                 {
645                     long nDayX = nX+mnDaysOffX;
646                     long nDayY = nY+mnDaysOffY;
647                     if ( rPos.Y() < nDayY )
648                         return 0;
649                     sal_uInt16 nDayIndex = (sal_uInt16)rDate.GetDayOfWeek();
650                     nDayIndex = (nDayIndex+(7-(sal_uInt16)eStartDay)) % 7;
651                     if ( (i == 0) && (j == 0) )
652                     {
653                         Date aTempDate = rDate;
654                         aTempDate -= nDayIndex;
655                         for ( nDay = 0; nDay < nDayIndex; nDay++ )
656                         {
657                             nOffX = nDayX + (nDay*mnDayWidth);
658                             if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
659                                  (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
660                             {
661                                 rDate = aTempDate;
662                                 rDate += nDay;
663                                 return CALENDAR_HITTEST_DAY;
664                             }
665                         }
666                     }
667                     for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
668                     {
669                         if ( rPos.Y() < nDayY )
670                         {
671                             rDate += nDayIndex;
672                             return 0;
673                         }
674                         nOffX = nDayX + (nDayIndex*mnDayWidth);
675                         if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
676                              (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
677                         {
678                             rDate += nDay-1;
679                             return CALENDAR_HITTEST_DAY;
680                         }
681                         if ( nDayIndex == 6 )
682                         {
683                             nDayIndex = 0;
684                             nDayY += mnDayHeight;
685                         }
686                         else
687                             nDayIndex++;
688                     }
689                     if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
690                     {
691                         sal_uInt16 nWeekDay = (sal_uInt16)rDate.GetDayOfWeek();
692                         nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
693                         sal_uInt16 nDayCount = 42-nDaysInMonth-nWeekDay;
694                         Date aTempDate = rDate;
695                         aTempDate += nDaysInMonth;
696                         for ( nDay = 1; nDay <= nDayCount; nDay++ )
697                         {
698                             if ( rPos.Y() < nDayY )
699                             {
700                                 rDate += nDayIndex;
701                                 return 0;
702                             }
703                             nOffX = nDayX + (nDayIndex*mnDayWidth);
704                             if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
705                                  (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
706                             {
707                                 rDate = aTempDate;
708                                 rDate += nDay-1;
709                                 return CALENDAR_HITTEST_DAY;
710                             }
711                             if ( nDayIndex == 6 )
712                             {
713                                 nDayIndex = 0;
714                                 nDayY += mnDayHeight;
715                             }
716                             else
717                                 nDayIndex++;
718                         }
719                     }
720                 }
721             }
722 
723             rDate += nDaysInMonth;
724             nX += mnMonthWidth;
725         }
726 
727         nY += mnMonthHeight;
728     }
729 
730     return 0;
731 }
732 
733 // -----------------------------------------------------------------------
734 
ImplDrawSpinArrow(OutputDevice * pDev,const Rectangle & rRect,sal_Bool bPrev)735 static void ImplDrawSpinArrow( OutputDevice* pDev, const Rectangle& rRect,
736                                sal_Bool bPrev )
737 {
738     long    i;
739     long    n;
740     long    nLines;
741     long    nHeight = rRect.GetHeight();
742     long    nWidth = rRect.GetWidth();
743     if ( nWidth < nHeight )
744         n = nWidth;
745     else
746         n = nHeight;
747     if ( !(n & 0x01) )
748         n--;
749     nLines = n/2;
750 
751     Rectangle aRect( Point( rRect.Left()+(nWidth/2)-(nLines/2),
752                             rRect.Top()+(nHeight/2) ),
753                      Size( 1, 1 ) );
754     if ( !bPrev )
755     {
756         aRect.Left()  += nLines;
757         aRect.Right() += nLines;
758     }
759 
760     pDev->DrawRect( aRect );
761     for ( i = 0; i < nLines; i++ )
762     {
763         if ( bPrev )
764         {
765             aRect.Left()++;
766             aRect.Right()++;
767         }
768         else
769         {
770             aRect.Left()--;
771             aRect.Right()--;
772         }
773         aRect.Top()--;
774         aRect.Bottom()++;
775         pDev->DrawRect( aRect );
776     }
777 }
778 
779 // -----------------------------------------------------------------------
780 
ImplDrawSpin(sal_Bool bDrawPrev,sal_Bool bDrawNext)781 void Calendar::ImplDrawSpin( sal_Bool bDrawPrev, sal_Bool bDrawNext )
782 {
783     if ( !bDrawPrev && !bDrawNext )
784         return;
785 
786     SetLineColor();
787     SetFillColor( GetSettings().GetStyleSettings().GetButtonTextColor() );
788     if ( bDrawPrev )
789     {
790         Rectangle aOutRect = maPrevRect;
791         aOutRect.Left()   += 3;
792         aOutRect.Top()    += 3;
793         aOutRect.Right()  -= 3;
794         aOutRect.Bottom() -= 3;
795         ImplDrawSpinArrow( this, aOutRect, sal_True );
796     }
797     if ( bDrawNext )
798     {
799         Rectangle aOutRect = maNextRect;
800         aOutRect.Left()   += 3;
801         aOutRect.Top()    += 3;
802         aOutRect.Right()  -= 3;
803         aOutRect.Bottom() -= 3;
804         ImplDrawSpinArrow( this, aOutRect, sal_False );
805     }
806 }
807 
808 // -----------------------------------------------------------------------
809 
ImplDrawDate(long nX,long nY,sal_uInt16 nDay,sal_uInt16 nMonth,sal_uInt16 nYear,DayOfWeek eDayOfWeek,sal_Bool bBack,sal_Bool bOther,sal_uLong nToday)810 void Calendar::ImplDrawDate( long nX, long nY,
811                              sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear,
812                              DayOfWeek eDayOfWeek,
813                              sal_Bool bBack, sal_Bool bOther, sal_uLong nToday )
814 {
815     ImplDateInfo*   pDateInfo;
816     Color*          pTextColor = NULL;
817     const String&   rDay = *(mpDayText[nDay-1]);
818     Rectangle       aDateRect( nX, nY, nX+mnDayWidth-1, nY+mnDayHeight-1 );
819 
820     sal_Bool bSel = sal_False;
821     sal_Bool bFocus = sal_False;
822     // Aktueller Tag
823     if ( (nDay   == maCurDate.GetDay()) &&
824          (nMonth == maCurDate.GetMonth()) &&
825          (nYear  == maCurDate.GetYear()) )
826         bFocus = sal_True;
827     if ( mpSelectTable )
828     {
829         if ( mpSelectTable->IsKeyValid( Date( nDay, nMonth, nYear ).GetDate() ) )
830             bSel = sal_True;
831     }
832 
833     // Dateinfo ermitteln
834     if ( mpDateTable )
835     {
836         pDateInfo = mpDateTable->Get( Date( nDay, nMonth, nYear ).GetDate() );
837         if ( !pDateInfo )
838             pDateInfo = mpDateTable->Get( Date( nDay, nMonth, 0 ).GetDate() );
839     }
840     else
841         pDateInfo = NULL;
842 
843     // Textfarbe ermitteln
844     if ( bSel )
845         pTextColor = &maSelColor;
846     else if ( bOther )
847         pTextColor = &maOtherColor;
848     else
849     {
850         if ( pDateInfo && pDateInfo->mpTextColor )
851             pTextColor = pDateInfo->mpTextColor;
852         else
853         {
854             if ( eDayOfWeek == SATURDAY )
855                 pTextColor = mpSaturdayColor;
856             else if ( eDayOfWeek == SUNDAY )
857                 pTextColor = mpSundayColor;
858             if ( !pTextColor )
859                 pTextColor = mpStandardColor;
860         }
861     }
862 
863     if ( bFocus )
864         HideFocus();
865 
866     // Font ermitteln
867     Font aOldFont = GetFont();
868     sal_Bool bBoldFont = sal_False;
869     if ( (mnWinStyle & WB_BOLDTEXT) &&
870          pDateInfo && (pDateInfo->mnFlags & DIB_BOLD) )
871     {
872         bBoldFont = sal_True;
873         Font aFont = aOldFont;
874         if ( aFont.GetWeight() < WEIGHT_BOLD )
875             aFont.SetWeight( WEIGHT_BOLD );
876         else
877             aFont.SetWeight( WEIGHT_NORMAL );
878         SetFont( aFont );
879     }
880 
881     // Hintergrund ausgeben
882     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
883     if ( bSel || bBack )
884     {
885         if ( bSel )
886         {
887             SetLineColor();
888             SetFillColor( rStyleSettings.GetHighlightColor() );
889             DrawRect( aDateRect );
890         }
891         else
892             Erase( aDateRect );
893     }
894 
895     // Text ausgeben
896     long nTextX = nX+(mnDayWidth-GetTextWidth( rDay ))-(DAY_OFFX/2);
897     long nTextY = nY+(mnDayHeight-GetTextHeight())/2;
898     if ( pTextColor )
899     {
900         Color aOldColor = GetTextColor();
901         SetTextColor( *pTextColor );
902         DrawText( Point( nTextX, nTextY ), rDay );
903         SetTextColor( aOldColor );
904     }
905     else
906         DrawText( Point( nTextX, nTextY ), rDay );
907 
908     // Heute
909     Date aTodayDate( maCurDate );
910     if ( nToday )
911         aTodayDate.SetDate( nToday );
912     else
913         aTodayDate = Date();
914     if ( (nDay   == aTodayDate.GetDay()) &&
915          (nMonth == aTodayDate.GetMonth()) &&
916          (nYear  == aTodayDate.GetYear()) )
917     {
918         SetLineColor( rStyleSettings.GetWindowTextColor() );
919         SetFillColor();
920         DrawRect( aDateRect );
921     }
922 
923     // Evt. DateInfo ausgeben
924     if ( (mnWinStyle & WB_FRAMEINFO) && pDateInfo && pDateInfo->mpFrameColor )
925     {
926         SetLineColor( *(pDateInfo->mpFrameColor) );
927         SetFillColor();
928         Rectangle aFrameRect( aDateRect );
929         aFrameRect.Left()++;
930         aFrameRect.Top()++;
931         long nFrameWidth = aFrameRect.GetWidth();
932         long nFrameHeight = aFrameRect.GetHeight();
933         long nFrameOff;
934         if ( nFrameWidth < nFrameHeight )
935         {
936             nFrameOff = nFrameHeight-nFrameWidth;
937             aFrameRect.Top() += nFrameOff/2;
938             nFrameOff %= 2;
939             aFrameRect.Bottom() -= nFrameOff;
940         }
941         else if ( nFrameWidth > nFrameHeight )
942         {
943             nFrameOff = nFrameWidth-nFrameHeight;
944             aFrameRect.Left() += nFrameOff/2;
945             nFrameOff %= 2;
946             aFrameRect.Right() -= nFrameOff;
947         }
948         DrawEllipse( aFrameRect );
949     }
950 
951     // Evt. noch FocusRect
952     if ( bFocus && HasFocus() )
953         ShowFocus( aDateRect );
954 
955     if( mbDropPos && maDropDate == Date( nDay, nMonth, nYear ) )
956         ImplInvertDropPos();
957 
958     if ( bBoldFont )
959         SetFont( aOldFont );
960 }
961 
962 // -----------------------------------------------------------------------
963 
ImplDraw(sal_Bool bPaint)964 void Calendar::ImplDraw( sal_Bool bPaint )
965 {
966     ImplFormat();
967 
968     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
969     Size        aOutSize = GetOutputSizePixel();
970     long        i;
971     long        j;
972     long        nX;
973     long        nY;
974     long        nDeltaX;
975     long        nDeltaY;
976     long        nDayX;
977     long        nDayY;
978     sal_uLong       nToday = Date().GetDate();
979     sal_uInt16      nDay;
980     sal_uInt16      nMonth;
981     sal_uInt16      nYear;
982     Date        aDate = GetFirstMonth();
983     DayOfWeek   eStartDay = ImplGetWeekStart();
984 
985     HideFocus();
986 
987     nY = 0;
988     for ( i = 0; i < mnLines; i++ )
989     {
990         // Titleleiste ausgeben
991         SetLineColor();
992         SetFillColor( rStyleSettings.GetFaceColor() );
993         Rectangle aTitleRect( 0, nY, aOutSize.Width()-1, nY+mnDayHeight-DAY_OFFY+TITLE_BORDERY*2 );
994         if ( !bPaint )
995         {
996             Rectangle aTempRect( 1, aTitleRect.Top()+TITLE_BORDERY,
997                                  aOutSize.Width()-2,
998                                  aTitleRect.Bottom()-TITLE_BORDERY );
999             if ( !i )
1000             {
1001                 aTempRect.Left()  = maPrevRect.Right()+1;
1002                 aTempRect.Right() = maNextRect.Left()-1;
1003             }
1004             DrawRect( aTempRect );
1005         }
1006         else
1007         {
1008             DrawRect( aTitleRect );
1009             Point aTopLeft1( aTitleRect.Left(), aTitleRect.Top() );
1010             Point aTopLeft2( aTitleRect.Left(), aTitleRect.Top()+1 );
1011             Point aBottomRight1( aTitleRect.Right(), aTitleRect.Bottom() );
1012             Point aBottomRight2( aTitleRect.Right(), aTitleRect.Bottom()-1 );
1013             SetLineColor( rStyleSettings.GetDarkShadowColor() );
1014             DrawLine( aTopLeft1, Point( aBottomRight1.X(), aTopLeft1.Y() ) );
1015             SetLineColor( rStyleSettings.GetLightColor() );
1016             DrawLine( aTopLeft2, Point( aBottomRight2.X(), aTopLeft2.Y() ) );
1017             DrawLine( aTopLeft2, Point( aTopLeft2.X(), aBottomRight2.Y() ) );
1018             SetLineColor( rStyleSettings.GetShadowColor() );
1019             DrawLine( Point( aTopLeft2.X(), aBottomRight2.Y() ), aBottomRight2 );
1020             DrawLine( Point( aBottomRight2.X(), aTopLeft2.Y() ), aBottomRight2 );
1021             SetLineColor( rStyleSettings.GetDarkShadowColor() );
1022             DrawLine( Point( aTopLeft1.X(), aBottomRight1.Y() ), aBottomRight1 );
1023         }
1024         Point aSepPos1( 0, aTitleRect.Top()+TITLE_BORDERY );
1025         Point aSepPos2( 0, aTitleRect.Bottom()-TITLE_BORDERY );
1026         for ( j = 0; j < mnMonthPerLine-1; j++ )
1027         {
1028             aSepPos1.X() += mnMonthWidth-1;
1029             aSepPos2.X() = aSepPos1.X();
1030             SetLineColor( rStyleSettings.GetShadowColor() );
1031             DrawLine( aSepPos1, aSepPos2 );
1032             aSepPos1.X()++;
1033             aSepPos2.X() = aSepPos1.X();
1034             SetLineColor( rStyleSettings.GetLightColor() );
1035             DrawLine( aSepPos1, aSepPos2 );
1036         }
1037 
1038         nX = 0;
1039         for ( j = 0; j < mnMonthPerLine; j++ )
1040         {
1041             nMonth  = aDate.GetMonth();
1042             nYear   = aDate.GetYear();
1043 
1044             // Monat in der Titleleiste ausgeben
1045             nDeltaX = nX;
1046             nDeltaY = nY+TITLE_BORDERY;
1047             String aMonthText( maCalendarWrapper.getDisplayName(
1048                         i18n::CalendarDisplayIndex::MONTH, nMonth-1, 1));
1049             aMonthText += ' ';
1050             aMonthText += String::CreateFromInt64( nYear );
1051             long nMonthTextWidth = GetTextWidth( aMonthText );
1052             long nMonthOffX1 = 0;
1053             long nMonthOffX2 = 0;
1054             if ( i == 0 )
1055             {
1056                 if ( j == 0 )
1057                     nMonthOffX1 = maPrevRect.Right()+1;
1058                 if ( j == mnMonthPerLine-1 )
1059                     nMonthOffX2 = aOutSize.Width()-maNextRect.Left()+1;
1060             }
1061             long nMaxMonthWidth = mnMonthWidth-nMonthOffX1-nMonthOffX2-4;
1062             if ( nMonthTextWidth > nMaxMonthWidth )
1063             {
1064                 // Abbreviated month name.
1065                 aMonthText  = maCalendarWrapper.getDisplayName(
1066                         i18n::CalendarDisplayIndex::MONTH, nMonth-1, 0);
1067                 aMonthText += ' ';
1068                 aMonthText += String::CreateFromInt64( nYear );
1069                 nMonthTextWidth = GetTextWidth( aMonthText );
1070             }
1071             long nTempOff = (mnMonthWidth-nMonthTextWidth+1)/2;
1072             if ( nTempOff < nMonthOffX1 )
1073                 nDeltaX += nMonthOffX1+1;
1074             else
1075             {
1076                 if ( nTempOff+nMonthTextWidth > mnMonthWidth-nMonthOffX2 )
1077                     nDeltaX += mnMonthWidth-nMonthOffX2-nMonthTextWidth;
1078                 else
1079                     nDeltaX += nTempOff;
1080             }
1081             SetTextColor( rStyleSettings.GetButtonTextColor() );
1082             DrawText( Point( nDeltaX, nDeltaY ), aMonthText );
1083             SetTextColor( rStyleSettings.GetWindowTextColor() );
1084 
1085             // Weekleiste ausgeben
1086             if ( bPaint )
1087             {
1088                 nDayX = nX+mnDaysOffX;
1089                 nDayY = nY+mnWeekDayOffY;
1090                 nDeltaY = nDayY + mnDayHeight;
1091                 SetLineColor( rStyleSettings.GetWindowTextColor() );
1092                 Point aStartPos( nDayX, nDeltaY );
1093                 if ( mnWinStyle & WB_WEEKNUMBER )
1094                     aStartPos.X() -= WEEKNUMBER_OFFX-2;
1095                 DrawLine( aStartPos, Point( nDayX+(7*mnDayWidth), nDeltaY ) );
1096                 DrawTextArray( Point( nDayX+mnDayOfWeekAry[0], nDayY ), maDayOfWeekText, &(mnDayOfWeekAry[1]) );
1097             }
1098 
1099             // Week-Numbers ausgeben
1100             if ( mnWinStyle & WB_WEEKNUMBER )
1101             {
1102                 nDayX = nX+mnDaysOffX;
1103                 nDayY = nY+mnWeekDayOffY;
1104                 nDeltaY = nDayY + mnDayHeight;
1105                 long nMonthHeight = mnDayHeight*6;
1106                 if ( bPaint )
1107                     DrawLine( Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY ), Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY+nMonthHeight ) );
1108                 else
1109                     Erase( Rectangle( nDayX-mnWeekWidth-WEEKNUMBER_OFFX, nDeltaY, nDayX-WEEKNUMBER_OFFX-1, nDeltaY+nMonthHeight ) );
1110 
1111                 Font aOldFont = GetFont();
1112                 Font aTempFont = aOldFont;
1113                 ImplGetWeekFont( aTempFont );
1114                 SetFont( aTempFont );
1115                 nDayX -= mnWeekWidth;
1116                 nDayY = nY+mnDaysOffY;
1117                 maCalendarWrapper.setGregorianDateTime( aDate);
1118                 for ( sal_uInt16 nWeekCount = 0; nWeekCount < 6; nWeekCount++ )
1119                 {
1120                     sal_Int16 nWeek = maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
1121                     String  aWeekText( String::CreateFromInt32( nWeek));
1122                     long    nOffX = (mnWeekWidth-WEEKNUMBER_OFFX)-GetTextWidth( aWeekText );
1123                     long    nOffY = (mnDayHeight-GetTextHeight())/2;
1124                     DrawText( Point( nDayX+nOffX, nDayY+nOffY ), aWeekText );
1125                     nDayY += mnDayHeight;
1126                     maCalendarWrapper.addValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, 7);
1127                 }
1128                 SetFont( aOldFont );
1129             }
1130 
1131             // Tage ausgeben
1132             sal_uInt16 nDaysInMonth = aDate.GetDaysInMonth();
1133             nDayX = nX+mnDaysOffX;
1134             nDayY = nY+mnDaysOffY;
1135             if ( !bPaint )
1136             {
1137                 Rectangle aClearRect( nDayX, nDayY,
1138                                       nDayX+(7*mnDayWidth)-1, nDayY+(6*mnDayHeight)-1 );
1139                 Erase( aClearRect );
1140             }
1141             sal_uInt16 nDayIndex = (sal_uInt16)aDate.GetDayOfWeek();
1142             nDayIndex = (nDayIndex+(7-(sal_uInt16)eStartDay)) % 7;
1143             if ( (i == 0) && (j == 0) )
1144             {
1145                 Date aTempDate = aDate;
1146                 aTempDate -= nDayIndex;
1147                 for ( nDay = 0; nDay < nDayIndex; nDay++ )
1148                 {
1149                     nDeltaX = nDayX + (nDay*mnDayWidth);
1150                     ImplDrawDate( nDeltaX, nDayY, nDay+aTempDate.GetDay(),
1151                                   aTempDate.GetMonth(), aTempDate.GetYear(),
1152                                   (DayOfWeek)((nDay+(sal_uInt16)eStartDay)%7), sal_False, sal_True, nToday );
1153                 }
1154             }
1155             for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
1156             {
1157                 nDeltaX = nDayX + (nDayIndex*mnDayWidth);
1158                 ImplDrawDate( nDeltaX, nDayY, nDay, nMonth, nYear,
1159                               (DayOfWeek)((nDayIndex+(sal_uInt16)eStartDay)%7),
1160                               sal_False, sal_False, nToday );
1161                 if ( nDayIndex == 6 )
1162                 {
1163                     nDayIndex = 0;
1164                     nDayY += mnDayHeight;
1165                 }
1166                 else
1167                     nDayIndex++;
1168             }
1169             if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
1170             {
1171                 sal_uInt16 nWeekDay = (sal_uInt16)aDate.GetDayOfWeek();
1172                 nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
1173                 sal_uInt16 nDayCount = 42-nDaysInMonth-nWeekDay;
1174                 Date aTempDate = aDate;
1175                 aTempDate += nDaysInMonth;
1176                 for ( nDay = 1; nDay <= nDayCount; nDay++ )
1177                 {
1178                     nDeltaX = nDayX + (nDayIndex*mnDayWidth);
1179                     ImplDrawDate( nDeltaX, nDayY, nDay,
1180                                   aTempDate.GetMonth(), aTempDate.GetYear(),
1181                                   (DayOfWeek)((nDayIndex+(sal_uInt16)eStartDay)%7),
1182                                   sal_False, sal_True, nToday );
1183                     if ( nDayIndex == 6 )
1184                     {
1185                         nDayIndex = 0;
1186                         nDayY += mnDayHeight;
1187                     }
1188                     else
1189                         nDayIndex++;
1190                 }
1191             }
1192 
1193             aDate += nDaysInMonth;
1194             nX += mnMonthWidth;
1195         }
1196 
1197         nY += mnMonthHeight;
1198     }
1199 
1200     // Spin-Buttons zeichnen
1201     if ( bPaint )
1202         ImplDrawSpin();
1203 }
1204 
1205 // -----------------------------------------------------------------------
1206 
ImplUpdateDate(const Date & rDate)1207 void Calendar::ImplUpdateDate( const Date& rDate )
1208 {
1209     if ( IsReallyVisible() && IsUpdateMode() )
1210     {
1211         Rectangle aDateRect( GetDateRect( rDate ) );
1212         if ( !aDateRect.IsEmpty() )
1213         {
1214             sal_Bool bOther = (rDate < GetFirstMonth()) || (rDate > GetLastMonth());
1215             ImplDrawDate( aDateRect.Left(), aDateRect.Top(),
1216                           rDate.GetDay(), rDate.GetMonth(), rDate.GetYear(),
1217                           rDate.GetDayOfWeek(), sal_True, bOther );
1218         }
1219     }
1220 }
1221 
1222 // -----------------------------------------------------------------------
1223 
ImplUpdateSelection(Table * pOld)1224 void Calendar::ImplUpdateSelection( Table* pOld )
1225 {
1226     Table*  pNew = mpSelectTable;
1227     void*   p;
1228     sal_uLong   nKey;
1229 
1230     p = pOld->First();
1231     while ( p )
1232     {
1233         nKey = pOld->GetCurKey();
1234         if ( !pNew->Get( nKey ) )
1235         {
1236             Date aTempDate( nKey );
1237             ImplUpdateDate( aTempDate );
1238         }
1239 
1240         p = pOld->Next();
1241     }
1242 
1243     p = pNew->First();
1244     while ( p )
1245     {
1246         nKey = pNew->GetCurKey();
1247         if ( !pOld->Get( nKey ) )
1248         {
1249             Date aTempDate( nKey );
1250             ImplUpdateDate( aTempDate );
1251         }
1252 
1253         p = pNew->Next();
1254     }
1255 }
1256 
1257 // -----------------------------------------------------------------------
1258 
ImplMouseSelect(const Date & rDate,sal_uInt16 nHitTest,sal_Bool bMove,sal_Bool bExpand,sal_Bool bExtended)1259 void Calendar::ImplMouseSelect( const Date& rDate, sal_uInt16 nHitTest,
1260                                 sal_Bool bMove, sal_Bool bExpand, sal_Bool bExtended )
1261 {
1262     Table*  pOldSel = new Table( *mpSelectTable );
1263     Date    aOldDate = maCurDate;
1264     Date    aTempDate = rDate;
1265 
1266     if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
1267         aTempDate--;
1268 
1269     if ( mbMultiSelection )
1270     {
1271         maCurDate = aTempDate;
1272         mbSelLeft = aTempDate < maAnchorDate;
1273 
1274         if ( bMove )
1275         {
1276             if ( mbSelLeft )
1277             {
1278                 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), aTempDate );
1279                 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, maAnchorDate, Date( 31, 12, 9999 ) );
1280             }
1281             else
1282             {
1283                 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), maAnchorDate );
1284                 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, aTempDate, Date( 31, 12, 9999 ) );
1285             }
1286             ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, !mbUnSel );
1287         }
1288         else
1289         {
1290             if ( bExpand )
1291             {
1292                 if ( !bExtended )
1293                 {
1294                     if ( mbSelLeft )
1295                     {
1296                         ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aTempDate, sal_False );
1297                         ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), sal_False );
1298                     }
1299                     else
1300                     {
1301                         ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, sal_False );
1302                         ImplCalendarSelectDateRange( mpSelectTable, aTempDate, Date( 31, 12, 9999 ), sal_False );
1303                     }
1304                 }
1305                 ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, sal_True );
1306             }
1307             else if ( bExtended && !(mnWinStyle & WB_RANGESELECT) )
1308             {
1309                 maAnchorDate = aTempDate;
1310                 if ( IsDateSelected( aTempDate ) )
1311                 {
1312                     mbUnSel = sal_True;
1313                     ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_False );
1314                 }
1315                 else
1316                 {
1317                     ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_True );
1318                 }
1319             }
1320             else
1321             {
1322                 maAnchorDate = aTempDate;
1323                 ImplCalendarClearSelectDate( mpSelectTable );
1324                 ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_True );
1325             }
1326 
1327             mpRestoreSelectTable = new Table( *mpSelectTable );
1328         }
1329     }
1330     else
1331     {
1332         if ( aTempDate < maCurDate )
1333             mbSelLeft = sal_True;
1334         else
1335             mbSelLeft = sal_False;
1336         if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
1337             aTempDate = maOldCurDate;
1338         if ( !bMove )
1339             maAnchorDate = aTempDate;
1340         if ( aTempDate != maCurDate )
1341         {
1342             maCurDate = aTempDate;
1343             ImplCalendarSelectDate( mpSelectTable, aOldDate, sal_False );
1344             ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
1345         }
1346     }
1347 
1348     sal_Bool bNewSel = *pOldSel != *mpSelectTable;
1349     if ( (maCurDate != aOldDate) || bNewSel )
1350     {
1351         if ( bNewSel )
1352         {
1353             mbInSelChange = sal_True;
1354             SelectionChanging();
1355             mbInSelChange = sal_False;
1356         }
1357         HideFocus();
1358         if ( bNewSel )
1359             ImplUpdateSelection( pOldSel );
1360         if ( !bNewSel || !pOldSel->Get( aOldDate.GetDate() ) )
1361             ImplUpdateDate( aOldDate );
1362         // Damit Focus-Rechteck auch wieder neu ausgegeben wird
1363         if ( HasFocus() || !bNewSel || !mpSelectTable->Get( maCurDate.GetDate() ) )
1364             ImplUpdateDate( maCurDate );
1365     }
1366     delete pOldSel;
1367 }
1368 
1369 // -----------------------------------------------------------------------
1370 
ImplUpdate(sal_Bool bCalcNew)1371 void Calendar::ImplUpdate( sal_Bool bCalcNew )
1372 {
1373     if ( IsReallyVisible() && IsUpdateMode() )
1374     {
1375         if ( bCalcNew && !mbCalc )
1376             Invalidate();
1377         else if ( !mbFormat && !mbCalc )
1378         {
1379             if ( mbDirect )
1380             {
1381                 mbFormat = sal_True;
1382                 ImplDraw( sal_False );
1383                 return;
1384             }
1385             else
1386                 Invalidate();
1387         }
1388     }
1389 
1390     if ( bCalcNew )
1391         mbCalc = sal_True;
1392     mbFormat = sal_True;
1393 }
1394 
1395 // -----------------------------------------------------------------------
1396 
ImplInvertDropPos()1397 void Calendar::ImplInvertDropPos()
1398 {
1399     Rectangle aRect = GetDateRect( maDropDate );//this is one Pixel to width and one to heigh
1400     aRect.Bottom() = aRect.Top()+mnDayHeight-1;
1401     aRect.Right() = aRect.Left()+mnDayWidth-1;
1402     Invert( aRect );
1403 }
1404 
1405 // -----------------------------------------------------------------------
1406 
ImplScroll(sal_Bool bPrev)1407 void Calendar::ImplScroll( sal_Bool bPrev )
1408 {
1409     Date aNewFirstMonth = GetFirstMonth();
1410     if ( bPrev )
1411     {
1412         aNewFirstMonth--;
1413         aNewFirstMonth -= aNewFirstMonth.GetDaysInMonth()-1;
1414     }
1415     else
1416         aNewFirstMonth += aNewFirstMonth.GetDaysInMonth();
1417     mbDirect = sal_True;
1418     SetFirstDate( aNewFirstMonth );
1419     mbDirect = sal_False;
1420 }
1421 
1422 // -----------------------------------------------------------------------
1423 
ImplShowMenu(const Point & rPos,const Date & rDate)1424 void Calendar::ImplShowMenu( const Point& rPos, const Date& rDate )
1425 {
1426     EndSelection();
1427 
1428     Date        aOldFirstDate = GetFirstMonth();
1429     PopupMenu   aPopupMenu;
1430     PopupMenu*  pYearPopupMenus[MENU_YEAR_COUNT];
1431     sal_uInt16      nMonthOff;
1432     sal_uInt16      nCurItemId;
1433     sal_uInt16      nYear = rDate.GetYear()-1;
1434     sal_uInt16      i;
1435     sal_uInt16      j;
1436     sal_uInt16      nYearIdCount = 1000;
1437 
1438     nMonthOff = (rDate.GetYear()-aOldFirstDate.GetYear())*12;
1439     if ( aOldFirstDate.GetMonth() < rDate.GetMonth() )
1440         nMonthOff += rDate.GetMonth()-aOldFirstDate.GetMonth();
1441     else
1442         nMonthOff -= aOldFirstDate.GetMonth()-rDate.GetMonth();
1443 
1444     // Menu aufbauen (Jahre mit verschiedenen Monaten aufnehmen)
1445     for ( i = 0; i < MENU_YEAR_COUNT; i++ )
1446     {
1447         pYearPopupMenus[i] = new PopupMenu;
1448         for ( j = 1; j <= 12; j++ )
1449             pYearPopupMenus[i]->InsertItem( nYearIdCount+j,
1450                     maCalendarWrapper.getDisplayName(
1451                         i18n::CalendarDisplayIndex::MONTH, j-1, 1));
1452         aPopupMenu.InsertItem( 10+i, UniString::CreateFromInt32( nYear+i ) );
1453         aPopupMenu.SetPopupMenu( 10+i, pYearPopupMenus[i] );
1454         nYearIdCount += 1000;
1455     }
1456 
1457     mbMenuDown = sal_True;
1458     nCurItemId = aPopupMenu.Execute( this, rPos );
1459     mbMenuDown = sal_False;
1460 
1461     // Menu zerstoeren
1462     aPopupMenu.SetPopupMenu( 2, NULL );
1463     for ( i = 0; i < MENU_YEAR_COUNT; i++ )
1464     {
1465         aPopupMenu.SetPopupMenu( 10+i, NULL );
1466         delete pYearPopupMenus[i];
1467     }
1468 
1469     if ( nCurItemId )
1470     {
1471         sal_uInt16 nTempMonthOff = nMonthOff % 12;
1472         sal_uInt16 nTempYearOff = nMonthOff / 12;
1473         sal_uInt16 nNewMonth = nCurItemId % 1000;
1474         sal_uInt16 nNewYear = nYear+((nCurItemId-1000)/1000);
1475         if ( nTempMonthOff < nNewMonth )
1476             nNewMonth = nNewMonth - nTempMonthOff;
1477         else
1478         {
1479             nNewYear--;
1480             nNewMonth = 12-(nTempMonthOff-nNewMonth);
1481         }
1482         nNewYear = nNewYear - nTempYearOff;
1483         SetFirstDate( Date( 1, nNewMonth, nNewYear ) );
1484     }
1485 }
1486 
1487 // -----------------------------------------------------------------------
1488 
ImplTracking(const Point & rPos,sal_Bool bRepeat)1489 void Calendar::ImplTracking( const Point& rPos, sal_Bool bRepeat )
1490 {
1491     Date    aTempDate = maCurDate;
1492     sal_uInt16  nHitTest = ImplHitTest( rPos, aTempDate );
1493 
1494     if ( mbSpinDown )
1495     {
1496         mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
1497         mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
1498 
1499         if ( bRepeat && (mbPrevIn || mbNextIn) )
1500         {
1501             mbScrollDateRange = sal_True;
1502             ImplScroll( mbPrevIn );
1503             mbScrollDateRange = sal_False;
1504         }
1505     }
1506     else
1507         ImplMouseSelect( aTempDate, nHitTest, sal_True, sal_False, sal_False );
1508 }
1509 
1510 // -----------------------------------------------------------------------
1511 
ImplEndTracking(sal_Bool bCancel)1512 void Calendar::ImplEndTracking( sal_Bool bCancel )
1513 {
1514     sal_Bool bSelection = mbSelection;
1515     sal_Bool bSpinDown = mbSpinDown;
1516 
1517     mbDrag              = sal_False;
1518     mbSelection         = sal_False;
1519     mbMultiSelection    = sal_False;
1520     mbUnSel             = sal_False;
1521     mbSpinDown          = sal_False;
1522     mbPrevIn            = sal_False;
1523     mbNextIn            = sal_False;
1524 
1525     if ( bCancel )
1526     {
1527         if ( maOldFirstDate != maFirstDate )
1528             SetFirstDate( maOldFirstDate );
1529 
1530         if ( !bSpinDown )
1531         {
1532             Table*  pOldSel = new Table( *mpSelectTable );
1533             Date    aOldDate = maCurDate;
1534             maCurDate       = maOldCurDate;
1535             *mpSelectTable  = *mpOldSelectTable;
1536             HideFocus();
1537             ImplUpdateSelection( pOldSel );
1538             if ( !pOldSel->Get( aOldDate.GetDate() ) )
1539                 ImplUpdateDate( aOldDate );
1540             // Damit Focus-Rechteck auch wieder neu ausgegeben wird
1541             if ( HasFocus() || !mpSelectTable->Get( maCurDate.GetDate() ) )
1542                 ImplUpdateDate( maCurDate );
1543             delete pOldSel;
1544         }
1545     }
1546 
1547     if ( !bSpinDown )
1548     {
1549         if ( !bCancel )
1550         {
1551             // Feststellen, ob wir sichtbaren Bereich scrollen sollen
1552             sal_uLong nSelCount = mpSelectTable->Count();
1553             if ( nSelCount )
1554             {
1555                 Date aFirstSelDate( mpSelectTable->GetObjectKey( 0 ) );
1556                 Date aLastSelDate( mpSelectTable->GetObjectKey( nSelCount-1 ) );
1557                 if ( aLastSelDate < GetFirstMonth() )
1558                     ImplScroll( sal_True );
1559                 else if ( GetLastMonth() < aFirstSelDate )
1560                     ImplScroll( sal_False );
1561             }
1562         }
1563 
1564         if ( mbAllSel ||
1565              (!bCancel && ((maCurDate != maOldCurDate) || (*mpOldSelectTable != *mpSelectTable))) )
1566             Select();
1567 
1568         if ( !bSelection && (mnWinStyle & WB_TABSTOP) && !bCancel )
1569             GrabFocus();
1570 
1571         delete mpOldSelectTable;
1572         mpOldSelectTable = NULL;
1573         delete mpRestoreSelectTable;
1574         mpRestoreSelectTable = NULL;
1575     }
1576 }
1577 
1578 // -----------------------------------------------------------------------
1579 
IMPL_STATIC_LINK(Calendar,ScrollHdl,Timer *,EMPTYARG)1580 IMPL_STATIC_LINK( Calendar, ScrollHdl, Timer*, EMPTYARG )
1581 {
1582     sal_Bool bPrevIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_PREV) != 0;
1583     sal_Bool bNextIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_NEXT) != 0;
1584     if( bNextIn || bPrevIn )
1585     {
1586         pThis->mbScrollDateRange = sal_True;
1587         pThis->ImplScroll( bPrevIn );
1588         pThis->mbScrollDateRange = sal_False;
1589     }
1590     return 0;
1591 }
1592 
1593 // -----------------------------------------------------------------------
1594 
MouseButtonDown(const MouseEvent & rMEvt)1595 void Calendar::MouseButtonDown( const MouseEvent& rMEvt )
1596 {
1597     if ( rMEvt.IsLeft() && !mbMenuDown )
1598     {
1599         Date    aTempDate = maCurDate;
1600         sal_uInt16  nHitTest = ImplHitTest( rMEvt.GetPosPixel(), aTempDate );
1601         if ( nHitTest )
1602         {
1603             if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
1604                 ImplShowMenu( rMEvt.GetPosPixel(), aTempDate );
1605             else
1606             {
1607                 maOldFirstDate = maFirstDate;
1608 
1609                 mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
1610                 mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
1611                 if ( mbPrevIn || mbNextIn )
1612                 {
1613                     mbSpinDown = sal_True;
1614                     mbScrollDateRange = sal_True;
1615                     ImplScroll( mbPrevIn );
1616                     mbScrollDateRange = sal_False;
1617                     // Hier muss BUTTONREPEAT stehen, also nicht wieder
1618                     // auf SCROLLREPEAT aendern, sondern mit TH abklaeren,
1619                     // warum es evtl. anders sein sollte (71775)
1620                     StartTracking( STARTTRACK_BUTTONREPEAT );
1621                 }
1622                 else
1623                 {
1624                     if ( (rMEvt.GetClicks() == 2) && (nHitTest & CALENDAR_HITTEST_DAY) )
1625                         DoubleClick();
1626                     else
1627                     {
1628                         if ( mpOldSelectTable )
1629                             delete mpOldSelectTable;
1630                         maOldCurDate = maCurDate;
1631                         mpOldSelectTable = new Table( *mpSelectTable );
1632 
1633                         if ( !mbSelection )
1634                         {
1635                             mbDrag = sal_True;
1636                             StartTracking();
1637                         }
1638 
1639                         mbMultiSelection = (mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT)) != 0;
1640                         if ( (nHitTest & CALENDAR_HITTEST_DAY) && mbMultiSelection )
1641                             mbWeekSel = sal_True;
1642                         else
1643                             mbWeekSel = sal_False;
1644                         ImplMouseSelect( aTempDate, nHitTest, sal_False, rMEvt.IsShift(), rMEvt.IsMod1() );
1645                     }
1646                 }
1647             }
1648         }
1649 
1650         return;
1651     }
1652 
1653     Control::MouseButtonDown( rMEvt );
1654 }
1655 
1656 // -----------------------------------------------------------------------
1657 
MouseButtonUp(const MouseEvent & rMEvt)1658 void Calendar::MouseButtonUp( const MouseEvent& rMEvt )
1659 {
1660     if ( rMEvt.IsLeft() && mbSelection )
1661         ImplEndTracking( sal_False );
1662     else
1663         Control::MouseButtonUp( rMEvt );
1664 }
1665 
1666 // -----------------------------------------------------------------------
1667 
MouseMove(const MouseEvent & rMEvt)1668 void Calendar::MouseMove( const MouseEvent& rMEvt )
1669 {
1670     if ( mbSelection && rMEvt.GetButtons() )
1671         ImplTracking( rMEvt.GetPosPixel(), sal_False );
1672     else
1673         Control::MouseMove( rMEvt );
1674 }
1675 
1676 // -----------------------------------------------------------------------
1677 
Tracking(const TrackingEvent & rTEvt)1678 void Calendar::Tracking( const TrackingEvent& rTEvt )
1679 {
1680     Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1681 
1682     if ( rTEvt.IsTrackingEnded() )
1683         ImplEndTracking( rTEvt.IsTrackingCanceled() );
1684     else
1685         ImplTracking( aMousePos, rTEvt.IsTrackingRepeat() );
1686 }
1687 
1688 // -----------------------------------------------------------------------
1689 
KeyInput(const KeyEvent & rKEvt)1690 void Calendar::KeyInput( const KeyEvent& rKEvt )
1691 {
1692     Date    aNewDate = maCurDate;
1693     sal_Bool    bMultiSel = (mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) != 0;
1694     sal_Bool    bExpand = rKEvt.GetKeyCode().IsShift();
1695     sal_Bool    bExtended = rKEvt.GetKeyCode().IsMod1();
1696 
1697     switch ( rKEvt.GetKeyCode().GetCode() )
1698     {
1699         case KEY_HOME:
1700             aNewDate.SetDay( 1 );
1701             break;
1702 
1703         case KEY_END:
1704             aNewDate.SetDay( aNewDate.GetDaysInMonth() );
1705             break;
1706 
1707         case KEY_LEFT:
1708             aNewDate--;
1709             break;
1710 
1711         case KEY_RIGHT:
1712             aNewDate++;
1713             break;
1714 
1715         case KEY_UP:
1716             aNewDate -= 7;
1717             break;
1718 
1719         case KEY_DOWN:
1720             aNewDate += 7;
1721             break;
1722 
1723         case KEY_PAGEUP:
1724             {
1725             Date aTempDate = aNewDate;
1726             aTempDate -= aNewDate.GetDay()+1;
1727             aNewDate -= aTempDate.GetDaysInMonth();
1728             }
1729             break;
1730 
1731         case KEY_PAGEDOWN:
1732             aNewDate += aNewDate.GetDaysInMonth();
1733             break;
1734 
1735         case KEY_SPACE:
1736             if ( bMultiSel && !(mnWinStyle & WB_RANGESELECT) )
1737             {
1738                 if ( !bExpand )
1739                 {
1740                     sal_Bool bDateSel = IsDateSelected( maCurDate );
1741                     SelectDate( maCurDate, !bDateSel );
1742                     mbSelLeft = sal_False;
1743                     SelectionChanging();
1744                     mbTravelSelect = sal_True;
1745                     Select();
1746                     mbTravelSelect = sal_False;
1747                 }
1748             }
1749             else
1750                 Control::KeyInput( rKEvt );
1751             break;
1752 
1753         default:
1754             Control::KeyInput( rKEvt );
1755             break;
1756     }
1757 
1758     if ( aNewDate != maCurDate )
1759     {
1760         if ( bMultiSel && bExpand )
1761         {
1762             Table* pOldSel = new Table( *mpSelectTable );
1763             Date aOldAnchorDate = maAnchorDate;
1764             mbSelLeft = aNewDate < maAnchorDate;
1765             if ( !bExtended )
1766             {
1767                 if ( mbSelLeft )
1768                 {
1769                     ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aNewDate, sal_False );
1770                     ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), sal_False );
1771                 }
1772                 else
1773                 {
1774                     ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, sal_False );
1775                     ImplCalendarSelectDateRange( mpSelectTable, aNewDate, Date( 31, 12, 9999 ), sal_False );
1776                 }
1777             }
1778             ImplCalendarSelectDateRange( mpSelectTable, aNewDate, maAnchorDate, sal_True );
1779             mbDirect = sal_True;
1780             SetCurDate( aNewDate );
1781             mbDirect = sal_False;
1782             maAnchorDate = aOldAnchorDate;
1783             mbInSelChange = sal_True;
1784             SelectionChanging();
1785             mbInSelChange = sal_False;
1786             ImplUpdateSelection( pOldSel );
1787             delete pOldSel;
1788         }
1789         else
1790         {
1791             if ( mnWinStyle & WB_RANGESELECT )
1792             {
1793                 SetNoSelection();
1794                 SelectDate( aNewDate, sal_True );
1795             }
1796             mbDirect = sal_True;
1797             SetCurDate( aNewDate );
1798             mbDirect = sal_False;
1799         }
1800         mbTravelSelect = sal_True;
1801         Select();
1802         mbTravelSelect = sal_False;
1803     }
1804 }
1805 
1806 // -----------------------------------------------------------------------
1807 
Paint(const Rectangle &)1808 void Calendar::Paint( const Rectangle& )
1809 {
1810     ImplDraw( sal_True );
1811 }
1812 
1813 // -----------------------------------------------------------------------
1814 
GetFocus()1815 void Calendar::GetFocus()
1816 {
1817     ImplUpdateDate( maCurDate );
1818     Control::GetFocus();
1819 }
1820 
1821 // -----------------------------------------------------------------------
1822 
LoseFocus()1823 void Calendar::LoseFocus()
1824 {
1825     HideFocus();
1826     Control::LoseFocus();
1827 }
1828 
1829 // -----------------------------------------------------------------------
1830 
Resize()1831 void Calendar::Resize()
1832 {
1833     ImplUpdate( sal_True );
1834     Control::Resize();
1835 }
1836 
1837 // -----------------------------------------------------------------------
1838 
RequestHelp(const HelpEvent & rHEvt)1839 void Calendar::RequestHelp( const HelpEvent& rHEvt )
1840 {
1841     if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1842     {
1843         Date aDate = maCurDate;
1844         if ( GetDate( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ), aDate ) )
1845         {
1846             Rectangle aDateRect = GetDateRect( aDate );
1847             Point aPt = OutputToScreenPixel( aDateRect.TopLeft() );
1848             aDateRect.Left()   = aPt.X();
1849             aDateRect.Top()    = aPt.Y();
1850             aPt = OutputToScreenPixel( aDateRect.BottomRight() );
1851             aDateRect.Right()  = aPt.X();
1852             aDateRect.Bottom() = aPt.Y();
1853 
1854             if ( (rHEvt.GetMode() & HELPMODE_BALLOON) || (mnWinStyle & WB_QUICKHELPSHOWSDATEINFO) )
1855             {
1856                 ImplDateInfo* pInfo;
1857                 if ( mpDateTable )
1858                 {
1859                     pInfo = mpDateTable->Get( aDate.GetDate() );
1860                     if ( !pInfo )
1861                         pInfo = mpDateTable->Get( Date( aDate.GetDay(), aDate.GetMonth(), 0 ).GetDate() );
1862                 }
1863                 else
1864                     pInfo = NULL;
1865                 if ( pInfo )
1866                 {
1867                     XubString aStr = pInfo->maText;
1868                     if ( aStr.Len() )
1869                     {
1870                         Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aDateRect, aStr );
1871                         return;
1872                     }
1873                 }
1874             }
1875 
1876             if ( rHEvt.GetMode() & HELPMODE_QUICK )
1877             {
1878                 maCalendarWrapper.setGregorianDateTime( aDate);
1879                 sal_uInt16      nWeek = (sal_uInt16) maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
1880                 sal_uInt16      nMonth = aDate.GetMonth();
1881                 XubString   aStr( maDayText );
1882                 aStr.AppendAscii( ": " );
1883                 aStr.Append( XubString::CreateFromInt32( aDate.GetDayOfYear() ) );
1884                 aStr.AppendAscii( " / " );
1885                 aStr.Append( maWeekText );
1886                 aStr.AppendAscii( ": " );
1887                 aStr.Append( XubString::CreateFromInt32( nWeek ) );
1888                 // Evt. noch Jahr hinzufuegen, wenn es nicht das gleiche ist
1889                 if ( (nMonth == 12) && (nWeek == 1) )
1890                 {
1891                     aStr.AppendAscii( ",  " );
1892                     aStr.Append( XubString::CreateFromInt32( aDate.GetYear()+1 ) );
1893                 }
1894                 else if ( (nMonth == 1) && (nWeek > 50) )
1895                 {
1896                     aStr.AppendAscii( ", " );
1897                     aStr.Append( XubString::CreateFromInt32( aDate.GetYear()-1 ) );
1898                 }
1899                 Help::ShowQuickHelp( this, aDateRect, aStr );
1900                 return;
1901             }
1902         }
1903     }
1904 
1905     Control::RequestHelp( rHEvt );
1906 }
1907 
1908 // -----------------------------------------------------------------------
1909 
Command(const CommandEvent & rCEvt)1910 void Calendar::Command( const CommandEvent& rCEvt )
1911 {
1912     if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
1913     {
1914         if ( !mbSelection && rCEvt.IsMouseEvent() )
1915         {
1916             Date    aTempDate = maCurDate;
1917             sal_uInt16  nHitTest = ImplHitTest( rCEvt.GetMousePosPixel(), aTempDate );
1918             if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
1919             {
1920                 ImplShowMenu( rCEvt.GetMousePosPixel(), aTempDate );
1921                 return;
1922             }
1923         }
1924     }
1925     else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
1926     {
1927         const CommandWheelData* pData = rCEvt.GetWheelData();
1928         if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
1929         {
1930             long nNotchDelta = pData->GetNotchDelta();
1931             if ( nNotchDelta < 0 )
1932             {
1933                 while ( nNotchDelta < 0 )
1934                 {
1935                     ImplScroll( sal_True );
1936                     nNotchDelta++;
1937                 }
1938             }
1939             else
1940             {
1941                 while ( nNotchDelta > 0 )
1942                 {
1943                     ImplScroll( sal_False );
1944                     nNotchDelta--;
1945                 }
1946             }
1947 
1948             return;
1949         }
1950     }
1951 
1952     Control::Command( rCEvt );
1953 }
1954 
1955 // -----------------------------------------------------------------------
1956 
StateChanged(StateChangedType nType)1957 void Calendar::StateChanged( StateChangedType nType )
1958 {
1959     Control::StateChanged( nType );
1960 
1961     if ( nType == STATE_CHANGE_INITSHOW )
1962         ImplFormat();
1963 }
1964 
1965 // -----------------------------------------------------------------------
1966 
DataChanged(const DataChangedEvent & rDCEvt)1967 void Calendar::DataChanged( const DataChangedEvent& rDCEvt )
1968 {
1969     Control::DataChanged( rDCEvt );
1970 
1971     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1972          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1973          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1974           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1975     {
1976         ImplInitSettings();
1977         Invalidate();
1978     }
1979 }
1980 
1981 // -----------------------------------------------------------------------
1982 
SelectionChanging()1983 void Calendar::SelectionChanging()
1984 {
1985     maSelectionChangingHdl.Call( this );
1986 }
1987 
1988 // -----------------------------------------------------------------------
1989 
DateRangeChanged()1990 void Calendar::DateRangeChanged()
1991 {
1992     maDateRangeChangedHdl.Call( this );
1993 }
1994 
1995 // -----------------------------------------------------------------------
1996 
RequestDateInfo()1997 void Calendar::RequestDateInfo()
1998 {
1999     maRequestDateInfoHdl.Call( this );
2000 }
2001 
2002 // -----------------------------------------------------------------------
2003 
DoubleClick()2004 void Calendar::DoubleClick()
2005 {
2006     maDoubleClickHdl.Call( this );
2007 }
2008 
2009 // -----------------------------------------------------------------------
2010 
Select()2011 void Calendar::Select()
2012 {
2013     maSelectHdl.Call( this );
2014 }
2015 
2016 // -----------------------------------------------------------------------
2017 
SelectDate(const Date & rDate,sal_Bool bSelect)2018 void Calendar::SelectDate( const Date& rDate, sal_Bool bSelect )
2019 {
2020     if ( !rDate.IsValid() )
2021         return;
2022 
2023     Table* pOldSel;
2024 
2025     if ( !mbInSelChange )
2026         pOldSel = new Table( *mpSelectTable );
2027     else
2028         pOldSel = NULL;
2029 
2030     ImplCalendarSelectDate( mpSelectTable, rDate, bSelect );
2031 
2032     if ( pOldSel )
2033     {
2034         ImplUpdateSelection( pOldSel );
2035         delete pOldSel;
2036     }
2037 }
2038 
2039 // -----------------------------------------------------------------------
2040 
SelectDateRange(const Date & rStartDate,const Date & rEndDate,sal_Bool bSelect)2041 void Calendar::SelectDateRange( const Date& rStartDate, const Date& rEndDate,
2042                                 sal_Bool bSelect )
2043 {
2044     if ( !rStartDate.IsValid() || !rEndDate.IsValid() )
2045         return;
2046 
2047     Table* pOldSel;
2048 
2049     if ( !mbInSelChange )
2050         pOldSel = new Table( *mpSelectTable );
2051     else
2052         pOldSel = NULL;
2053 
2054     ImplCalendarSelectDateRange( mpSelectTable, rStartDate, rEndDate, bSelect );
2055 
2056     if ( pOldSel )
2057     {
2058         ImplUpdateSelection( pOldSel );
2059         delete pOldSel;
2060     }
2061 }
2062 
2063 // -----------------------------------------------------------------------
2064 
SetNoSelection()2065 void Calendar::SetNoSelection()
2066 {
2067     Table* pOldSel;
2068 
2069     if ( !mbInSelChange )
2070         pOldSel = new Table( *mpSelectTable );
2071     else
2072         pOldSel = NULL;
2073 
2074     ImplCalendarClearSelectDate( mpSelectTable );
2075 
2076     if ( pOldSel )
2077     {
2078         ImplUpdateSelection( pOldSel );
2079         delete pOldSel;
2080     }
2081 }
2082 
2083 // -----------------------------------------------------------------------
2084 
IsDateSelected(const Date & rDate) const2085 sal_Bool Calendar::IsDateSelected( const Date& rDate ) const
2086 {
2087     return mpSelectTable->IsKeyValid( rDate.GetDate() );
2088 }
2089 
2090 // -----------------------------------------------------------------------
2091 
GetSelectDateCount() const2092 sal_uLong Calendar::GetSelectDateCount() const
2093 {
2094     return mpSelectTable->Count();
2095 }
2096 
2097 // -----------------------------------------------------------------------
2098 
GetSelectDate(sal_uLong nIndex) const2099 Date Calendar::GetSelectDate( sal_uLong nIndex ) const
2100 {
2101     if ( nIndex < mpSelectTable->Count() )
2102         return Date( mpSelectTable->GetObjectKey( nIndex ) );
2103     else
2104     {
2105         Date aDate( 0, 0, 0 );
2106         return aDate;
2107     }
2108 }
2109 
2110 // -----------------------------------------------------------------------
2111 
SetCurDate(const Date & rNewDate)2112 void Calendar::SetCurDate( const Date& rNewDate )
2113 {
2114     if ( !rNewDate.IsValid() )
2115         return;
2116 
2117     if ( maCurDate != rNewDate )
2118     {
2119         sal_Bool bUpdate    = IsVisible() && IsUpdateMode();
2120         Date aOldDate   = maCurDate;
2121         maCurDate       = rNewDate;
2122         maAnchorDate    = maCurDate;
2123 
2124         if ( !(mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) )
2125         {
2126             ImplCalendarSelectDate( mpSelectTable, aOldDate, sal_False );
2127             ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
2128         }
2129         else if ( !HasFocus() )
2130             bUpdate = sal_False;
2131 
2132         // Aktuelles Datum noch in den sichtbaren Bereich verschieben
2133         if ( mbFormat || (maCurDate < GetFirstMonth()) )
2134             SetFirstDate( maCurDate );
2135         else if ( maCurDate > GetLastMonth() )
2136         {
2137             Date aTempDate = GetLastMonth();
2138             long nDateOff = maCurDate-aTempDate;
2139             if ( nDateOff < 365 )
2140             {
2141                 Date aFirstDate = GetFirstMonth();
2142                 aFirstDate += aFirstDate.GetDaysInMonth();
2143                 aTempDate++;
2144                 while ( nDateOff > aTempDate.GetDaysInMonth() )
2145                 {
2146                     aFirstDate += aFirstDate.GetDaysInMonth();
2147                     long nDaysInMonth = aTempDate.GetDaysInMonth();
2148                     aTempDate += nDaysInMonth;
2149                     nDateOff -= nDaysInMonth;
2150                 }
2151                 SetFirstDate( aFirstDate );
2152             }
2153             else
2154                 SetFirstDate( maCurDate );
2155         }
2156         else
2157         {
2158             if ( bUpdate )
2159             {
2160                 HideFocus();
2161                 ImplUpdateDate( aOldDate );
2162                 ImplUpdateDate( maCurDate );
2163             }
2164         }
2165     }
2166 }
2167 
2168 // -----------------------------------------------------------------------
2169 
SetFirstDate(const Date & rNewFirstDate)2170 void Calendar::SetFirstDate( const Date& rNewFirstDate )
2171 {
2172     if ( maFirstDate != rNewFirstDate )
2173     {
2174         maFirstDate = Date( 1, rNewFirstDate.GetMonth(), rNewFirstDate.GetYear() );
2175         mbDropPos = sal_False;
2176         ImplUpdate();
2177     }
2178 }
2179 
2180 // -----------------------------------------------------------------------
2181 
GetFirstMonth() const2182 Date Calendar::GetFirstMonth() const
2183 {
2184     if ( maFirstDate.GetDay() > 1 )
2185     {
2186         if ( maFirstDate.GetMonth() == 12 )
2187             return Date( 1, 1, maFirstDate.GetYear()+1 );
2188         else
2189             return Date( 1, maFirstDate.GetMonth()+1, maFirstDate.GetYear() );
2190     }
2191     else
2192         return maFirstDate;
2193 }
2194 
2195 // -----------------------------------------------------------------------
2196 
GetLastMonth() const2197 Date Calendar::GetLastMonth() const
2198 {
2199     Date aDate = GetFirstMonth();
2200     sal_uInt16 nMonthCount = GetMonthCount();
2201     for ( sal_uInt16 i = 0; i < nMonthCount; i++ )
2202         aDate += aDate.GetDaysInMonth();
2203     aDate--;
2204     return aDate;
2205 }
2206 
2207 // -----------------------------------------------------------------------
2208 
GetMonthCount() const2209 sal_uInt16 Calendar::GetMonthCount() const
2210 {
2211     if ( mbFormat )
2212         return 1;
2213     else
2214         return (sal_uInt16)(mnMonthPerLine*mnLines);
2215 }
2216 
2217 // -----------------------------------------------------------------------
2218 
GetDropDate(Date & rDate) const2219 sal_Bool Calendar::GetDropDate( Date& rDate ) const
2220 {
2221     if( mbDropPos )
2222     {
2223         rDate = maDropDate;
2224         return sal_True;
2225     }
2226     return sal_False;
2227 }
2228 
2229 // -----------------------------------------------------------------------
2230 
GetDate(const Point & rPos,Date & rDate) const2231 sal_Bool Calendar::GetDate( const Point& rPos, Date& rDate ) const
2232 {
2233     Date    aDate = maCurDate;
2234     sal_uInt16  nHitTest = ImplHitTest( rPos, aDate );
2235     if ( nHitTest & CALENDAR_HITTEST_DAY )
2236     {
2237         rDate = aDate;
2238         return sal_True;
2239     }
2240     else
2241         return sal_False;
2242 }
2243 
2244 // -----------------------------------------------------------------------
2245 
GetDateRect(const Date & rDate) const2246 Rectangle Calendar::GetDateRect( const Date& rDate ) const
2247 {
2248     Rectangle aRect;
2249 
2250     if ( mbFormat || (rDate < maFirstDate) || (rDate > (maFirstDate+mnDayCount)) )
2251         return aRect;
2252 
2253     long    nX;
2254     long    nY;
2255     sal_uLong   nDaysOff;
2256     sal_uInt16  nDayIndex;
2257     Date    aDate = GetFirstMonth();
2258 
2259     if ( rDate < aDate )
2260     {
2261         aRect = GetDateRect( aDate );
2262         nDaysOff = aDate-rDate;
2263         nX = (long)(nDaysOff*mnDayWidth);
2264         aRect.Left() -= nX;
2265         aRect.Right() -= nX;
2266         return aRect;
2267     }
2268     else
2269     {
2270         Date aLastDate = GetLastMonth();
2271         if ( rDate > aLastDate )
2272         {
2273             sal_uInt16 nWeekDay = (sal_uInt16)aLastDate.GetDayOfWeek();
2274             nWeekDay = (nWeekDay+(7-(sal_uInt16)ImplGetWeekStart())) % 7;
2275             aLastDate -= nWeekDay;
2276             aRect = GetDateRect( aLastDate );
2277             nDaysOff = rDate-aLastDate;
2278             nDayIndex = 0;
2279             for ( sal_uInt16 i = 0; i <= nDaysOff; i++ )
2280             {
2281                 if ( aLastDate == rDate )
2282                 {
2283                     aRect.Left() += nDayIndex*mnDayWidth;
2284                     aRect.Right() = aRect.Left()+mnDayWidth;
2285                     return aRect;
2286                 }
2287                 if ( nDayIndex == 6 )
2288                 {
2289                     nDayIndex = 0;
2290                     aRect.Top() += mnDayHeight;
2291                     aRect.Bottom() += mnDayHeight;
2292                 }
2293                 else
2294                     nDayIndex++;
2295                 aLastDate++;
2296             }
2297         }
2298     }
2299 
2300     nY = 0;
2301     for ( long i = 0; i < mnLines; i++ )
2302     {
2303         nX = 0;
2304         for ( long j = 0; j < mnMonthPerLine; j++ )
2305         {
2306             sal_uInt16 nDaysInMonth = aDate.GetDaysInMonth();
2307 
2308             // Monat gerufen
2309             if ( (aDate.GetMonth() == rDate.GetMonth()) &&
2310                  (aDate.GetYear() == rDate.GetYear()) )
2311             {
2312                 long nDayX = nX+mnDaysOffX;
2313                 long nDayY = nY+mnDaysOffY;
2314                 nDayIndex = (sal_uInt16)aDate.GetDayOfWeek();
2315                 nDayIndex = (nDayIndex+(7-(sal_uInt16)ImplGetWeekStart())) % 7;
2316                 for ( sal_uInt16 nDay = 1; nDay <= nDaysInMonth; nDay++ )
2317                 {
2318                     if ( nDay == rDate.GetDay() )
2319                     {
2320                         aRect.Left()    = nDayX + (nDayIndex*mnDayWidth);
2321                         aRect.Top()     = nDayY;
2322                         aRect.Right()   = aRect.Left()+mnDayWidth;
2323                         aRect.Bottom()  = aRect.Top()+mnDayHeight;
2324                         break;
2325                     }
2326                     if ( nDayIndex == 6 )
2327                     {
2328                         nDayIndex = 0;
2329                         nDayY += mnDayHeight;
2330                     }
2331                     else
2332                         nDayIndex++;
2333                 }
2334             }
2335 
2336             aDate += nDaysInMonth;
2337             nX += mnMonthWidth;
2338         }
2339 
2340         nY += mnMonthHeight;
2341     }
2342 
2343     return aRect;
2344 }
2345 
2346 // -----------------------------------------------------------------------
2347 
SetStandardColor(const Color & rColor)2348 void Calendar::SetStandardColor( const Color& rColor )
2349 {
2350     if ( mpStandardColor )
2351         *mpStandardColor = rColor;
2352     else
2353         mpStandardColor = new Color( rColor );
2354     ImplUpdate();
2355 }
2356 
2357 // -----------------------------------------------------------------------
2358 
SetSaturdayColor(const Color & rColor)2359 void Calendar::SetSaturdayColor( const Color& rColor )
2360 {
2361     if ( mpSaturdayColor )
2362         *mpSaturdayColor = rColor;
2363     else
2364         mpSaturdayColor = new Color( rColor );
2365     ImplUpdate();
2366 }
2367 
2368 // -----------------------------------------------------------------------
2369 
SetSundayColor(const Color & rColor)2370 void Calendar::SetSundayColor( const Color& rColor )
2371 {
2372     if ( mpSundayColor )
2373         *mpSundayColor = rColor;
2374     else
2375         mpSundayColor = new Color( rColor );
2376     ImplUpdate();
2377 }
2378 
2379 // -----------------------------------------------------------------------
2380 
AddDateInfo(const Date & rDate,const String & rText,const Color * pTextColor,const Color * pFrameColor,sal_uInt16 nFlags)2381 void Calendar::AddDateInfo( const Date& rDate, const String& rText,
2382                             const Color* pTextColor, const Color* pFrameColor,
2383                             sal_uInt16 nFlags )
2384 {
2385     if ( !mpDateTable )
2386         mpDateTable = new ImplDateTable( 256, 256 );
2387 
2388     sal_Bool            bChanged = sal_False;
2389     sal_uLong           nKey = rDate.GetDate();
2390     ImplDateInfo*   pDateInfo = mpDateTable->Get( nKey );
2391     if ( pDateInfo )
2392         pDateInfo->maText = rText;
2393     else
2394     {
2395         pDateInfo = new ImplDateInfo( rText );
2396         mpDateTable->Insert( nKey, pDateInfo );
2397     }
2398     if ( pTextColor )
2399     {
2400         if ( pDateInfo->mpTextColor )
2401         {
2402             if ( *(pDateInfo->mpTextColor) != *pTextColor )
2403             {
2404                 *(pDateInfo->mpTextColor) = *pTextColor;
2405                 bChanged = sal_True;
2406             }
2407         }
2408         else
2409         {
2410             pDateInfo->mpTextColor = new Color( *pTextColor );
2411             bChanged = sal_True;
2412         }
2413     }
2414     else
2415     {
2416         if ( pDateInfo->mpTextColor )
2417         {
2418             delete pDateInfo->mpTextColor;
2419             pDateInfo->mpTextColor = NULL;
2420             bChanged = sal_True;
2421         }
2422     }
2423     if ( pFrameColor )
2424     {
2425         if ( pDateInfo->mpFrameColor )
2426         {
2427             if ( *(pDateInfo->mpFrameColor) != *pFrameColor )
2428             {
2429                 *(pDateInfo->mpFrameColor) = *pFrameColor;
2430                 bChanged = sal_True;
2431             }
2432         }
2433         else
2434         {
2435             pDateInfo->mpFrameColor = new Color( *pFrameColor );
2436             bChanged = sal_True;
2437         }
2438     }
2439     else
2440     {
2441         if ( pDateInfo->mpFrameColor )
2442         {
2443             delete pDateInfo->mpFrameColor;
2444             pDateInfo->mpFrameColor = NULL;
2445             bChanged = sal_True;
2446         }
2447     }
2448     if ( pDateInfo->mnFlags != nFlags )
2449     {
2450         pDateInfo->mnFlags = nFlags;
2451         bChanged = sal_True;
2452     }
2453 
2454     if ( bChanged )
2455         ImplUpdateDate( rDate );
2456 }
2457 
2458 // -----------------------------------------------------------------------
2459 
RemoveDateInfo(const Date & rDate)2460 void Calendar::RemoveDateInfo( const Date& rDate )
2461 {
2462     if ( mpDateTable )
2463     {
2464         ImplDateInfo* pDateInfo = mpDateTable->Remove( rDate.GetDate() );
2465         if ( pDateInfo )
2466         {
2467             delete pDateInfo;
2468             ImplUpdateDate( rDate );
2469         }
2470     }
2471 }
2472 
2473 // -----------------------------------------------------------------------
2474 
ClearDateInfo()2475 void Calendar::ClearDateInfo()
2476 {
2477     if ( mpDateTable )
2478     {
2479         ImplDateInfo* pDateInfo = mpDateTable->First();
2480         while ( pDateInfo )
2481         {
2482             sal_uLong nKey = mpDateTable->GetCurKey();
2483             mpDateTable->Remove( nKey );
2484             Date aDate( nKey );
2485             ImplUpdateDate( aDate );
2486             delete pDateInfo;
2487             pDateInfo = mpDateTable->First();
2488         }
2489         delete mpDateTable;
2490         mpDateTable = NULL;
2491     }
2492 }
2493 
2494 // -----------------------------------------------------------------------
2495 
GetDateInfoText(const Date & rDate)2496 XubString Calendar::GetDateInfoText( const Date& rDate )
2497 {
2498     XubString aRet;
2499     if ( mpDateTable )
2500     {
2501         sal_uLong           nKey = rDate.GetDate();
2502         ImplDateInfo*   pDateInfo = mpDateTable->Get( nKey );
2503         if ( pDateInfo )
2504             aRet = pDateInfo->maText;
2505     }
2506     return aRet;
2507 }
2508 
2509 // -----------------------------------------------------------------------
2510 
ShowDropPos(const Point & rPos,Date & rDate)2511 sal_Bool Calendar::ShowDropPos( const Point& rPos, Date& rDate )
2512 {
2513     Date    aTempDate = maCurDate;
2514     mnDragScrollHitTest = ImplHitTest( rPos, aTempDate );
2515 
2516     if ( mnDragScrollHitTest )
2517     {
2518         if ( mnDragScrollHitTest & (CALENDAR_HITTEST_PREV | CALENDAR_HITTEST_NEXT) )
2519         {
2520             if ( !maDragScrollTimer.IsActive() )
2521                 maDragScrollTimer.Start();
2522         }
2523         else
2524         {
2525             maDragScrollTimer.Stop();
2526             if ( mnDragScrollHitTest & CALENDAR_HITTEST_DAY )
2527             {
2528                 if ( !mbDropPos || (aTempDate != maDropDate) )
2529                 {
2530                     if( mbDropPos )
2531                         ImplInvertDropPos();
2532                     maDropDate = aTempDate;
2533                     mbDropPos = sal_True;
2534                     ImplInvertDropPos();
2535                 }
2536 
2537                 rDate = maDropDate;
2538                 return sal_True;
2539             }
2540         }
2541     }
2542     else
2543         maDragScrollTimer.Stop();
2544 
2545     HideDropPos();
2546     return sal_False;
2547 }
2548 
2549 // -----------------------------------------------------------------------
2550 
HideDropPos()2551 void Calendar::HideDropPos()
2552 {
2553     if ( mbDropPos )
2554     {
2555         ImplInvertDropPos();
2556         mbDropPos = sal_False;
2557     }
2558 }
2559 
2560 // -----------------------------------------------------------------------
2561 
StartSelection()2562 void Calendar::StartSelection()
2563 {
2564     if ( mpOldSelectTable )
2565         delete mpOldSelectTable;
2566     maOldCurDate = maCurDate;
2567     mpOldSelectTable = new Table( *mpSelectTable );
2568 
2569     mbSelection = sal_True;
2570 }
2571 
2572 // -----------------------------------------------------------------------
2573 
EndSelection()2574 void Calendar::EndSelection()
2575 {
2576     if ( mbDrag || mbSpinDown || mbSelection )
2577     {
2578         if ( !mbSelection )
2579             ReleaseMouse();
2580 
2581         mbDrag              = sal_False;
2582         mbSelection         = sal_False;
2583         mbMultiSelection    = sal_False;
2584         mbSpinDown          = sal_False;
2585         mbPrevIn            = sal_False;
2586         mbNextIn            = sal_False;
2587     }
2588 }
2589 
2590 // -----------------------------------------------------------------------
2591 
CalcWindowSizePixel(long nCalcMonthPerLine,long nCalcLines) const2592 Size Calendar::CalcWindowSizePixel( long nCalcMonthPerLine,
2593                                     long nCalcLines ) const
2594 {
2595     XubString   a99Text( XubString( RTL_CONSTASCII_USTRINGPARAM( "99" ) ) );
2596     Font        aOldFont = GetFont();
2597 
2598     // Wochenanzeige beruecksichtigen
2599     long nWeekWidth;
2600     if ( mnWinStyle & WB_WEEKNUMBER )
2601     {
2602         Font aTempFont = aOldFont;
2603         ImplGetWeekFont( aTempFont );
2604         ((Calendar*)this)->SetFont( aTempFont );
2605         nWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
2606         ((Calendar*)this)->SetFont( aOldFont );
2607     }
2608     else
2609         nWeekWidth = 0;
2610 
2611     if ( mnWinStyle & WB_BOLDTEXT )
2612     {
2613         Font aFont = aOldFont;
2614         if ( aFont.GetWeight() < WEIGHT_BOLD )
2615             aFont.SetWeight( WEIGHT_BOLD );
2616         else
2617             aFont.SetWeight( WEIGHT_NORMAL );
2618         ((Calendar*)this)->SetFont( aFont );
2619     }
2620 
2621     Size    aSize;
2622     long    n99TextWidth = GetTextWidth( a99Text );
2623     long    nTextHeight = GetTextHeight();
2624 
2625     if ( mnWinStyle & WB_BOLDTEXT )
2626         ((Calendar*)this)->SetFont( aOldFont );
2627 
2628     aSize.Width()  += ((n99TextWidth+DAY_OFFX)*7) + nWeekWidth;
2629     aSize.Width()  += MONTH_BORDERX*2;
2630     aSize.Width()  *= nCalcMonthPerLine;
2631 
2632     aSize.Height()  = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
2633     aSize.Height() += nTextHeight + WEEKDAY_OFFY;
2634     aSize.Height() += ((nTextHeight+DAY_OFFY)*6);
2635     aSize.Height() += MONTH_OFFY;
2636     aSize.Height() *= nCalcLines;
2637 
2638     return aSize;
2639 }
2640 
2641 // =======================================================================
2642 
2643 #define CALFIELD_EXTRA_BUTTON_WIDTH         14
2644 #define CALFIELD_EXTRA_BUTTON_HEIGHT        8
2645 #define CALFIELD_SEP_X                      6
2646 #define CALFIELD_BORDERLINE_X               5
2647 #define CALFIELD_BORDER_YTOP                4
2648 #define CALFIELD_BORDER_Y                   5
2649 
2650 // =======================================================================
2651 
2652 class ImplCFieldFloatWin : public FloatingWindow
2653 {
2654 private:
2655     Calendar*       mpCalendar;
2656     PushButton*     mpTodayBtn;
2657     PushButton*     mpNoneBtn;
2658     FixedLine*      mpFixedLine;
2659 
2660 public:
2661                     ImplCFieldFloatWin( Window* pParent );
2662                     ~ImplCFieldFloatWin();
2663 
SetCalendar(Calendar * pCalendar)2664     void            SetCalendar( Calendar* pCalendar )
2665                         { mpCalendar = pCalendar; }
2666 
2667     PushButton*     EnableTodayBtn( sal_Bool bEnable );
2668     PushButton*     EnableNoneBtn( sal_Bool bEnable );
2669     void            ArrangeButtons();
2670 
2671     long            Notify( NotifyEvent& rNEvt );
2672 };
2673 
2674 // -----------------------------------------------------------------------
2675 
ImplCFieldFloatWin(Window * pParent)2676 ImplCFieldFloatWin::ImplCFieldFloatWin( Window* pParent ) :
2677     FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW  )
2678 {
2679     mpCalendar  = NULL;
2680     mpTodayBtn  = NULL;
2681     mpNoneBtn   = NULL;
2682     mpFixedLine = NULL;
2683 }
2684 
2685 // -----------------------------------------------------------------------
2686 
~ImplCFieldFloatWin()2687 ImplCFieldFloatWin::~ImplCFieldFloatWin()
2688 {
2689     delete mpTodayBtn;
2690     delete mpNoneBtn;
2691     delete mpFixedLine;
2692 }
2693 
2694 // -----------------------------------------------------------------------
2695 
EnableTodayBtn(sal_Bool bEnable)2696 PushButton* ImplCFieldFloatWin::EnableTodayBtn( sal_Bool bEnable )
2697 {
2698     if ( bEnable )
2699     {
2700         if ( !mpTodayBtn )
2701         {
2702             mpTodayBtn = new PushButton( this, WB_NOPOINTERFOCUS );
2703             XubString aTodayText( SvtResId( STR_SVT_CALENDAR_TODAY ) );
2704             mpTodayBtn->SetText( aTodayText );
2705             Size aSize;
2706             aSize.Width()   = mpTodayBtn->GetCtrlTextWidth( mpTodayBtn->GetText() );
2707             aSize.Height()  = mpTodayBtn->GetTextHeight();
2708             aSize.Width()  += CALFIELD_EXTRA_BUTTON_WIDTH;
2709             aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
2710             mpTodayBtn->SetSizePixel( aSize );
2711             mpTodayBtn->Show();
2712         }
2713     }
2714     else
2715     {
2716         if ( mpTodayBtn )
2717         {
2718             delete mpTodayBtn;
2719             mpTodayBtn = NULL;
2720         }
2721     }
2722 
2723     return mpTodayBtn;
2724 }
2725 
2726 // -----------------------------------------------------------------------
2727 
EnableNoneBtn(sal_Bool bEnable)2728 PushButton* ImplCFieldFloatWin::EnableNoneBtn( sal_Bool bEnable )
2729 {
2730     if ( bEnable )
2731     {
2732         if ( !mpNoneBtn )
2733         {
2734             mpNoneBtn = new PushButton( this, WB_NOPOINTERFOCUS );
2735             XubString aNoneText( SvtResId( STR_SVT_CALENDAR_NONE ) );
2736             mpNoneBtn->SetText( aNoneText );
2737             Size aSize;
2738             aSize.Width()   = mpNoneBtn->GetCtrlTextWidth( mpNoneBtn->GetText() );
2739             aSize.Height()  = mpNoneBtn->GetTextHeight();
2740             aSize.Width()  += CALFIELD_EXTRA_BUTTON_WIDTH;
2741             aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
2742             mpNoneBtn->SetSizePixel( aSize );
2743             mpNoneBtn->Show();
2744         }
2745     }
2746     else
2747     {
2748         if ( mpNoneBtn )
2749         {
2750             delete mpNoneBtn;
2751             mpNoneBtn = NULL;
2752         }
2753     }
2754 
2755     return mpNoneBtn;
2756 }
2757 
2758 // -----------------------------------------------------------------------
2759 
ArrangeButtons()2760 void ImplCFieldFloatWin::ArrangeButtons()
2761 {
2762     long nBtnHeight = 0;
2763     long nBtnWidth  = 0;
2764     Size aOutSize   = GetOutputSizePixel();
2765     if ( mpTodayBtn && mpNoneBtn )
2766     {
2767         Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
2768         Size aNoneBtnSize  = mpNoneBtn->GetSizePixel();
2769         if ( aTodayBtnSize.Width() < aNoneBtnSize.Width() )
2770             aTodayBtnSize.Width() = aNoneBtnSize.Width();
2771         else
2772             aNoneBtnSize.Width() = aTodayBtnSize.Width();
2773         if ( aTodayBtnSize.Height() < aNoneBtnSize.Height() )
2774             aTodayBtnSize.Height() = aNoneBtnSize.Height();
2775         else
2776             aNoneBtnSize.Height() = aTodayBtnSize.Height();
2777 
2778         nBtnWidth  = aTodayBtnSize.Width() + aNoneBtnSize.Width() + CALFIELD_SEP_X;
2779         nBtnHeight = aTodayBtnSize.Height();
2780         long nX = (aOutSize.Width()-nBtnWidth)/2;
2781         long nY = aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP;
2782         mpTodayBtn->SetPosSizePixel( Point( nX, nY ), aTodayBtnSize );
2783         nX += aTodayBtnSize.Width() + CALFIELD_SEP_X;
2784         mpNoneBtn->SetPosSizePixel( Point( nX, nY ), aNoneBtnSize );
2785     }
2786     else if ( mpTodayBtn )
2787     {
2788         Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
2789         nBtnWidth  = aTodayBtnSize.Width();
2790         nBtnHeight = aTodayBtnSize.Height();
2791         mpTodayBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
2792     }
2793     else if ( mpNoneBtn )
2794     {
2795         Size aNoneBtnSize  = mpNoneBtn->GetSizePixel();
2796         nBtnWidth  = aNoneBtnSize.Width();
2797         nBtnHeight = aNoneBtnSize.Height();
2798         mpNoneBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
2799     }
2800 
2801     if ( nBtnHeight )
2802     {
2803         if ( !mpFixedLine )
2804         {
2805             mpFixedLine = new FixedLine( this );
2806             mpFixedLine->Show();
2807         }
2808         long nLineWidth = aOutSize.Width()-(CALFIELD_BORDERLINE_X*2);
2809         mpFixedLine->SetPosSizePixel( (aOutSize.Width()-nLineWidth)/2, aOutSize.Height()+((CALFIELD_BORDER_YTOP-2)/2),
2810                                       nLineWidth, 2, WINDOW_POSSIZE_POSSIZE );
2811         aOutSize.Height() += nBtnHeight + (CALFIELD_BORDER_Y*2) + CALFIELD_BORDER_YTOP;
2812         SetOutputSizePixel( aOutSize );
2813     }
2814     else
2815     {
2816         if ( mpFixedLine )
2817         {
2818             delete mpFixedLine;
2819             mpFixedLine = NULL;
2820         }
2821     }
2822 }
2823 
2824 // -----------------------------------------------------------------------
2825 
Notify(NotifyEvent & rNEvt)2826 long ImplCFieldFloatWin::Notify( NotifyEvent& rNEvt )
2827 {
2828     if ( rNEvt.GetType() == EVENT_KEYINPUT )
2829     {
2830         const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
2831         if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
2832             mpCalendar->Select();
2833     }
2834 
2835     return FloatingWindow::Notify( rNEvt );
2836 }
2837 
2838 // =======================================================================
2839 
CalendarField(Window * pParent,WinBits nWinStyle)2840 CalendarField::CalendarField( Window* pParent, WinBits nWinStyle ) :
2841     DateField( pParent, nWinStyle ),
2842     maDefaultDate( 0, 0, 0 )
2843 {
2844     mpFloatWin      = NULL;
2845     mpCalendar      = NULL;
2846     mnCalendarStyle = 0;
2847     mbToday         = sal_False;
2848     mbNone          = sal_False;
2849 }
2850 
2851 // -----------------------------------------------------------------------
2852 
CalendarField(Window * pParent,const ResId & rResId)2853 CalendarField::CalendarField( Window* pParent, const ResId& rResId ) :
2854     DateField( pParent, rResId ),
2855     maDefaultDate( 0, 0, 0 )
2856 {
2857     mpFloatWin      = NULL;
2858     mpCalendar      = NULL;
2859     mnCalendarStyle = 0;
2860     mbToday         = sal_False;
2861     mbNone          = sal_False;
2862 }
2863 
2864 // -----------------------------------------------------------------------
2865 
~CalendarField()2866 CalendarField::~CalendarField()
2867 {
2868     if ( mpFloatWin )
2869     {
2870         delete mpCalendar;
2871         delete mpFloatWin;
2872     }
2873 }
2874 
2875 // -----------------------------------------------------------------------
2876 
IMPL_LINK(CalendarField,ImplSelectHdl,Calendar *,pCalendar)2877 IMPL_LINK( CalendarField, ImplSelectHdl, Calendar*, pCalendar )
2878 {
2879     if ( !pCalendar->IsTravelSelect() )
2880     {
2881         mpFloatWin->EndPopupMode();
2882         EndDropDown();
2883         GrabFocus();
2884         Date aNewDate = mpCalendar->GetSelectDate( 0 );
2885         if ( IsEmptyDate() || ( aNewDate != GetDate() ) )
2886         {
2887             SetDate( aNewDate );
2888             SetModifyFlag();
2889             Modify();
2890         }
2891         Select();
2892     }
2893     return 0;
2894 }
2895 
2896 // -----------------------------------------------------------------------
2897 
IMPL_LINK(CalendarField,ImplClickHdl,PushButton *,pBtn)2898 IMPL_LINK( CalendarField, ImplClickHdl, PushButton*, pBtn )
2899 {
2900     mpFloatWin->EndPopupMode();
2901     EndDropDown();
2902     GrabFocus();
2903 
2904     if ( pBtn == mpTodayBtn )
2905     {
2906         Date aToday;
2907         if ( (aToday != GetDate()) || IsEmptyDate() )
2908         {
2909             SetDate( aToday );
2910             SetModifyFlag();
2911             Modify();
2912         }
2913     }
2914     else if ( pBtn == mpNoneBtn )
2915     {
2916         if ( !IsEmptyDate() )
2917         {
2918             SetEmptyDate();
2919             SetModifyFlag();
2920             Modify();
2921         }
2922     }
2923     Select();
2924 
2925     return 0;
2926 }
2927 
2928 // -----------------------------------------------------------------------
2929 
IMPL_LINK(CalendarField,ImplPopupModeEndHdl,FloatingWindow *,EMPTYARG)2930 IMPL_LINK( CalendarField, ImplPopupModeEndHdl, FloatingWindow*, EMPTYARG )
2931 {
2932     EndDropDown();
2933     GrabFocus();
2934     mpCalendar->EndSelection();
2935     return 0;
2936 }
2937 
2938 // -----------------------------------------------------------------------
2939 
Select()2940 void CalendarField::Select()
2941 {
2942     maSelectHdl.Call( this );
2943 }
2944 
2945 // -----------------------------------------------------------------------
2946 
ShowDropDown(sal_Bool bShow)2947 sal_Bool CalendarField::ShowDropDown( sal_Bool bShow )
2948 {
2949     if ( bShow )
2950     {
2951         Calendar* pCalendar = GetCalendar();
2952 
2953         Date aDate = GetDate();
2954         if ( IsEmptyDate() || !aDate.IsValid() )
2955         {
2956             if ( maDefaultDate.IsValid() )
2957                 aDate = maDefaultDate;
2958             else
2959                 aDate = Date();
2960         }
2961         if ( pCalendar->GetStyle() & (WB_RANGESELECT | WB_MULTISELECT) )
2962         {
2963             pCalendar->SetNoSelection();
2964             pCalendar->SelectDate( aDate );
2965         }
2966         pCalendar->SetCurDate( aDate );
2967         Point       aPos( GetParent()->OutputToScreenPixel( GetPosPixel() ) );
2968         Rectangle   aRect( aPos, GetSizePixel() );
2969         aRect.Bottom() -= 1;
2970         mpCalendar->SetOutputSizePixel( mpCalendar->CalcWindowSizePixel() );
2971         mpFloatWin->SetOutputSizePixel( mpCalendar->GetSizePixel() );
2972         mpFloatWin->SetCalendar( mpCalendar );
2973         mpTodayBtn = mpFloatWin->EnableTodayBtn( mbToday );
2974         mpNoneBtn = mpFloatWin->EnableNoneBtn( mbNone );
2975         if ( mpTodayBtn )
2976             mpTodayBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
2977         if ( mpNoneBtn )
2978             mpNoneBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
2979         mpFloatWin->ArrangeButtons();
2980         mpCalendar->EnableCallEverySelect();
2981         mpCalendar->StartSelection();
2982         mpCalendar->GrabFocus();
2983         mpCalendar->Show();
2984         mpFloatWin->StartPopupMode( aRect, FLOATWIN_POPUPMODE_NOFOCUSCLOSE|FLOATWIN_POPUPMODE_DOWN );
2985     }
2986     else
2987     {
2988         mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
2989         mpCalendar->EndSelection();
2990         EndDropDown();
2991     }
2992     return sal_True;
2993 }
2994 
2995 // -----------------------------------------------------------------------
2996 
CreateCalendar(Window * pParent)2997 Calendar* CalendarField::CreateCalendar( Window* pParent )
2998 {
2999     return new Calendar( pParent, mnCalendarStyle | WB_TABSTOP );
3000 }
3001 
3002 // -----------------------------------------------------------------------
3003 
GetCalendar()3004 Calendar* CalendarField::GetCalendar()
3005 {
3006     if ( !mpFloatWin )
3007     {
3008         mpFloatWin = new ImplCFieldFloatWin( this );
3009         mpFloatWin->SetPopupModeEndHdl( LINK( this, CalendarField, ImplPopupModeEndHdl ) );
3010         mpCalendar = CreateCalendar( mpFloatWin );
3011         mpCalendar->SetPosPixel( Point() );
3012         mpCalendar->SetSelectHdl( LINK( this, CalendarField, ImplSelectHdl ) );
3013     }
3014 
3015     return mpCalendar;
3016 }
3017 
3018 // -----------------------------------------------------------------------
3019 
StateChanged(StateChangedType nStateChange)3020 void CalendarField::StateChanged( StateChangedType nStateChange )
3021 {
3022     DateField::StateChanged( nStateChange );
3023 
3024     if ( ( nStateChange == STATE_CHANGE_STYLE ) && GetSubEdit() )
3025     {
3026         WinBits nAllAlignmentBits = ( WB_LEFT | WB_CENTER | WB_RIGHT | WB_TOP | WB_VCENTER | WB_BOTTOM );
3027         WinBits nMyAlignment = GetStyle() & nAllAlignmentBits;
3028         GetSubEdit()->SetStyle( ( GetSubEdit()->GetStyle() & ~nAllAlignmentBits ) | nMyAlignment );
3029     }
3030 }
3031 
3032