GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svtools / source / control / calendar.cxx
blobc82664055cf0a244d4cd9306245a976a1b8acb3d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <rtl/strbuf.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/help.hxx>
24 #include <vcl/menu.hxx>
25 #include <vcl/decoview.hxx>
26 #include <vcl/floatwin.hxx>
27 #include <vcl/button.hxx>
28 #include <vcl/fixed.hxx>
29 #include <comphelper/processfactory.hxx>
30 #include <unotools/calendarwrapper.hxx>
31 #include <unotools/localedatawrapper.hxx>
32 #include <com/sun/star/i18n/Weekdays.hpp>
33 #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
34 #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
36 #include <svtools/svtools.hrc>
37 #include <svtools/svtresid.hxx>
38 #include <svtools/calendar.hxx>
40 // =======================================================================
42 #define DAY_OFFX 4
43 #define DAY_OFFY 2
44 #define MONTH_BORDERX 4
45 #define MONTH_OFFY 3
46 #define WEEKNUMBER_OFFX 4
47 #define WEEKDAY_OFFY 3
48 #define TITLE_OFFY 3
49 #define TITLE_BORDERY 2
50 #define SPIN_OFFX 4
51 #define SPIN_OFFY TITLE_BORDERY
53 #define WEEKNUMBER_HEIGHT 85
55 #define CALENDAR_HITTEST_DAY ((sal_uInt16)0x0001)
56 #define CALENDAR_HITTEST_MONTHTITLE ((sal_uInt16)0x0004)
57 #define CALENDAR_HITTEST_PREV ((sal_uInt16)0x0008)
58 #define CALENDAR_HITTEST_NEXT ((sal_uInt16)0x0010)
60 #define MENU_YEAR_COUNT 3
62 using namespace ::com::sun::star;
64 // =======================================================================
66 static void ImplCalendarSelectDate( IntDateSet* pTable, const Date& rDate, sal_Bool bSelect )
68 if ( bSelect )
69 pTable->insert( rDate.GetDate() );
70 else
71 pTable->erase( rDate.GetDate() );
74 // -----------------------------------------------------------------------
76 static void ImplCalendarSelectDateRange( IntDateSet* pTable,
77 const Date& rStartDate,
78 const Date& rEndDate,
79 sal_Bool bSelect )
81 Date aStartDate = rStartDate;
82 Date aEndDate = rEndDate;
83 if ( aStartDate > aEndDate )
85 Date aTempDate = aStartDate;
86 aStartDate = aEndDate;
87 aEndDate = aTempDate;
90 if ( bSelect )
92 while ( aStartDate <= aEndDate )
94 pTable->insert( aStartDate.GetDate() );
95 aStartDate++;
98 else
100 for ( IntDateSet::const_iterator it = pTable->begin(); it != pTable->end(); )
102 Date aDate( *it );
103 if ( aDate > aEndDate )
104 break;
106 if ( aDate >= aStartDate )
107 pTable->erase( it++ );
108 else
109 ++it;
114 // -----------------------------------------------------------------------
116 static void ImplCalendarUnSelectDateRange( IntDateSet* pTable,
117 IntDateSet* pOldTable,
118 const Date& rStartDate,
119 const Date& rEndDate )
121 Date aStartDate = rStartDate;
122 Date aEndDate = rEndDate;
123 if ( aStartDate > aEndDate )
125 Date aTempDate = aStartDate;
126 aStartDate = aEndDate;
127 aEndDate = aTempDate;
130 for ( IntDateSet::const_iterator it = pTable->begin(); it != pTable->end(); )
132 Date aDate( *it );
133 if ( aDate > aEndDate )
134 break;
136 if ( aDate >= aStartDate )
137 pTable->erase( it++ );
138 else
139 ++it;
142 for ( IntDateSet::const_iterator it = pOldTable->begin(); it != pOldTable->end(); ++it )
144 Date aDate( *it );
145 if ( aDate > aEndDate )
146 break;
147 if ( aDate >= aStartDate )
148 pTable->insert( aDate.GetDate() );
152 // -----------------------------------------------------------------------
154 inline void ImplCalendarClearSelectDate( IntDateSet* pTable )
156 pTable->clear();
159 // =======================================================================
161 void Calendar::ImplInit( WinBits nWinStyle )
163 mpSelectTable = new IntDateSet;
164 mpOldSelectTable = NULL;
165 mpRestoreSelectTable = NULL;
166 mpStandardColor = NULL;
167 mpSaturdayColor = NULL;
168 mpSundayColor = NULL;
169 mnDayCount = 0;
170 mnWinStyle = nWinStyle;
171 mnFirstYear = 0;
172 mnLastYear = 0;
173 mnRequestYear = 0;
174 mbCalc = sal_True;
175 mbFormat = sal_True;
176 mbDrag = sal_False;
177 mbSelection = sal_False;
178 mbMultiSelection = sal_False;
179 mbWeekSel = sal_False;
180 mbUnSel = sal_False;
181 mbMenuDown = sal_False;
182 mbSpinDown = sal_False;
183 mbPrevIn = sal_False;
184 mbNextIn = sal_False;
185 mbDirect = sal_False;
186 mbInSelChange = sal_False;
187 mbTravelSelect = sal_False;
188 mbScrollDateRange = sal_False;
189 mbSelLeft = sal_False;
190 mbAllSel = sal_False;
191 mbDropPos = sal_False;
193 OUString aGregorian( "gregorian");
194 maCalendarWrapper.loadCalendar( aGregorian,
195 Application::GetAppLocaleDataWrapper().getLanguageTag().getLocale());
196 if (maCalendarWrapper.getUniqueID() != aGregorian)
198 SAL_WARN( "svtools.control", "Calendar::ImplInit: No ``gregorian'' calendar available for locale ``"
199 << Application::GetAppLocaleDataWrapper().getLanguageTag().getBcp47()
200 << "'' and other calendars aren't supported. Using en-US fallback." );
202 /* If we ever wanted to support other calendars than Gregorian a lot of
203 * rewrite would be necessary to internally replace use of class Date
204 * with proper class CalendarWrapper methods, get rid of fixed 12
205 * months, fixed 7 days, ... */
206 maCalendarWrapper.loadCalendar( aGregorian, lang::Locale( "en", "US", ""));
209 SetFirstDate( maCurDate );
210 ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
212 // Sonstige Strings erzeugen
213 maDayText = SVT_RESSTR(STR_SVT_CALENDAR_DAY);
214 maWeekText = SVT_RESSTR(STR_SVT_CALENDAR_WEEK);
216 // Tagestexte anlegen
217 for (sal_Int32 i = 0; i < 31; ++i)
218 maDayTexts[i] = OUString::number(i+1);
220 maDragScrollTimer.SetTimeoutHdl( STATIC_LINK( this, Calendar, ScrollHdl ) );
221 maDragScrollTimer.SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
222 mnDragScrollHitTest = 0;
224 ImplInitSettings();
227 // -----------------------------------------------------------------------
229 void Calendar::ImplInitSettings()
231 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
232 maSelColor = rStyleSettings.GetHighlightTextColor();
233 SetPointFont( rStyleSettings.GetToolFont() );
234 SetTextColor( rStyleSettings.GetFieldTextColor() );
235 SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
238 // -----------------------------------------------------------------------
240 Calendar::Calendar( Window* pParent, WinBits nWinStyle ) :
241 Control( pParent, nWinStyle & (WB_TABSTOP | WB_GROUP | WB_BORDER | WB_3DLOOK | WB_RANGESELECT | WB_MULTISELECT) ),
242 maCalendarWrapper( Application::GetAppLocaleDataWrapper().getComponentContext() ),
243 maOldFormatFirstDate( 0, 0, 1900 ),
244 maOldFormatLastDate( 0, 0, 1900 ),
245 maFirstDate( 0, 0, 1900 ),
246 maOldFirstDate( 0, 0, 1900 ),
247 maCurDate( Date::SYSTEM ),
248 maOldCurDate( 0, 0, 1900 ),
249 maAnchorDate( maCurDate ),
250 maDropDate( 0, 0, 1900 )
252 ImplInit( nWinStyle );
255 // -----------------------------------------------------------------------
257 Calendar::~Calendar()
259 delete mpStandardColor;
260 delete mpSaturdayColor;
261 delete mpSundayColor;
263 delete mpSelectTable;
264 delete mpOldSelectTable;
265 delete mpRestoreSelectTable;
268 // -----------------------------------------------------------------------
270 DayOfWeek Calendar::ImplGetWeekStart() const
272 // Map i18n::Weekdays to Date DayOfWeek
273 DayOfWeek eDay;
274 sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
275 switch (nDay)
277 case i18n::Weekdays::SUNDAY :
278 eDay = SUNDAY;
279 break;
280 case i18n::Weekdays::MONDAY :
281 eDay = MONDAY;
282 break;
283 case i18n::Weekdays::TUESDAY :
284 eDay = TUESDAY;
285 break;
286 case i18n::Weekdays::WEDNESDAY :
287 eDay = WEDNESDAY;
288 break;
289 case i18n::Weekdays::THURSDAY :
290 eDay = THURSDAY;
291 break;
292 case i18n::Weekdays::FRIDAY :
293 eDay = FRIDAY;
294 break;
295 case i18n::Weekdays::SATURDAY :
296 eDay = SATURDAY;
297 break;
298 default:
299 SAL_WARN( "svtools.control", "Calendar::ImplGetWeekStart: broken i18n Gregorian calendar (getFirstDayOfWeek())");
300 eDay = SUNDAY;
302 return eDay;
305 // -----------------------------------------------------------------------
307 void Calendar::ImplGetWeekFont( Font& rFont ) const
309 // Wochennummer geben wir in WEEKNUMBER_HEIGHT%-Fonthoehe aus
310 Size aFontSize = rFont.GetSize();
311 aFontSize.Height() *= WEEKNUMBER_HEIGHT;
312 aFontSize.Height() /= 100;
313 rFont.SetSize( aFontSize );
314 rFont.SetWeight( WEIGHT_NORMAL );
317 // -----------------------------------------------------------------------
319 void Calendar::ImplFormat()
321 if ( !mbFormat )
322 return;
324 if ( mbCalc )
326 Size aOutSize = GetOutputSizePixel();
328 if ( (aOutSize.Width() <= 1) || (aOutSize.Height() <= 1) )
329 return;
331 OUString a99Text("99");
333 Font aOldFont = GetFont();
335 // Wochenanzeige beruecksichtigen
336 if ( mnWinStyle & WB_WEEKNUMBER )
338 Font aTempFont = aOldFont;
339 ImplGetWeekFont( aTempFont );
340 SetFont( aTempFont );
341 mnWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
342 SetFont( aOldFont );
344 else
345 mnWeekWidth = 0;
347 if ( mnWinStyle & WB_BOLDTEXT )
349 Font aFont = aOldFont;
350 if ( aFont.GetWeight() < WEIGHT_BOLD )
351 aFont.SetWeight( WEIGHT_BOLD );
352 else
353 aFont.SetWeight( WEIGHT_NORMAL );
354 SetFont( aFont );
357 long n99TextWidth = GetTextWidth( a99Text );
358 long nTextHeight = GetTextHeight();
360 // Breiten und X-Positionen berechnen
361 mnDayWidth = n99TextWidth+DAY_OFFX;
362 mnMonthWidth = mnDayWidth*7;
363 mnMonthWidth += mnWeekWidth;
364 mnMonthWidth += MONTH_BORDERX*2;
365 mnMonthPerLine = aOutSize.Width() / mnMonthWidth;
366 if ( !mnMonthPerLine )
367 mnMonthPerLine = 1;
368 long nOver = ((aOutSize.Width()-(mnMonthPerLine*mnMonthWidth)) / mnMonthPerLine);
369 mnMonthWidth += nOver;
370 mnDaysOffX = MONTH_BORDERX;
371 mnDaysOffX += nOver/2;
372 mnDaysOffX += mnWeekWidth;
374 // Hoehen und Y-Positionen berechnen
375 mnDayHeight = nTextHeight + DAY_OFFY;
376 mnWeekDayOffY = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
377 mnDaysOffY = mnWeekDayOffY + nTextHeight + WEEKDAY_OFFY;
378 mnMonthHeight = (mnDayHeight*6) + mnDaysOffY;
379 mnMonthHeight += MONTH_OFFY;
380 mnLines = aOutSize.Height() / mnMonthHeight;
381 if ( !mnLines )
382 mnLines = 1;
383 mnMonthHeight += (aOutSize.Height()-(mnLines*mnMonthHeight)) / mnLines;
385 // Spinfelder berechnen
386 long nSpinSize = nTextHeight+TITLE_BORDERY-SPIN_OFFY;
387 maPrevRect.Left() = SPIN_OFFX;
388 maPrevRect.Top() = SPIN_OFFY;
389 maPrevRect.Right() = maPrevRect.Left()+nSpinSize;
390 maPrevRect.Bottom() = maPrevRect.Top()+nSpinSize;
391 maNextRect.Left() = aOutSize.Width()-SPIN_OFFX-nSpinSize-1;
392 maNextRect.Top() = SPIN_OFFY;
393 maNextRect.Right() = maNextRect.Left()+nSpinSize;
394 maNextRect.Bottom() = maNextRect.Top()+nSpinSize;
396 if ( mnWinStyle & WB_BOLDTEXT )
397 SetFont( aOldFont );
399 // Calculate DayOfWeekText (gets displayed in a narrow font)
400 maDayOfWeekText = "";
401 long nStartOffX = 0;
402 sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
403 for ( sal_Int16 nDayOfWeek = 0; nDayOfWeek < 7; nDayOfWeek++ )
405 // Use narrow name.
406 OUString aDayOfWeek( maCalendarWrapper.getDisplayName(
407 i18n::CalendarDisplayIndex::DAY, nDay, 2));
408 long nOffX = (mnDayWidth-GetTextWidth( aDayOfWeek ))/2;
409 if ( mnWinStyle & WB_BOLDTEXT )
410 nOffX++;
411 if ( !nDayOfWeek )
412 nStartOffX = nOffX;
413 else
414 nOffX -= nStartOffX;
415 nOffX += nDayOfWeek * mnDayWidth;
416 mnDayOfWeekAry[nDayOfWeek] = nOffX;
417 maDayOfWeekText += aDayOfWeek;
418 nDay++;
419 nDay %= 7;
422 mbCalc = sal_False;
425 // Anzahl Tage berechnen
427 DayOfWeek eStartDay = ImplGetWeekStart();
429 sal_uInt16 nWeekDay;
430 Date aTempDate = GetFirstMonth();
431 maFirstDate = aTempDate;
432 nWeekDay = (sal_uInt16)aTempDate.GetDayOfWeek();
433 nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
434 maFirstDate -= (sal_uLong)nWeekDay;
435 mnDayCount = nWeekDay;
436 sal_uInt16 nDaysInMonth;
437 sal_uInt16 nMonthCount = (sal_uInt16)(mnMonthPerLine*mnLines);
438 for ( sal_uInt16 i = 0; i < nMonthCount; i++ )
440 nDaysInMonth = aTempDate.GetDaysInMonth();
441 mnDayCount += nDaysInMonth;
442 aTempDate += nDaysInMonth;
444 Date aTempDate2 = aTempDate;
445 aTempDate2--;
446 nDaysInMonth = aTempDate2.GetDaysInMonth();
447 aTempDate2 -= nDaysInMonth-1;
448 nWeekDay = (sal_uInt16)aTempDate2.GetDayOfWeek();
449 nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
450 mnDayCount += 42-nDaysInMonth-nWeekDay;
452 // Farben festlegen
453 maOtherColor = Color( COL_LIGHTGRAY );
454 if ( maOtherColor.IsRGBEqual( GetBackground().GetColor() ) )
455 maOtherColor.SetColor( COL_GRAY );
457 Date aLastDate = GetLastDate();
458 if ( (maOldFormatLastDate != aLastDate) ||
459 (maOldFormatFirstDate != maFirstDate) )
461 maOldFormatFirstDate = maFirstDate;
462 maOldFormatLastDate = aLastDate;
463 DateRangeChanged();
466 // DateInfo besorgen
467 sal_uInt16 nNewFirstYear = maFirstDate.GetYear();
468 sal_uInt16 nNewLastYear = GetLastDate().GetYear();
469 if ( mnFirstYear )
471 if ( nNewFirstYear < mnFirstYear )
473 for ( mnRequestYear = nNewFirstYear; mnRequestYear < mnFirstYear; mnRequestYear++ )
474 RequestDateInfo();
475 mnFirstYear = nNewFirstYear;
477 if ( nNewLastYear > mnLastYear )
479 for ( mnRequestYear = mnLastYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
480 RequestDateInfo();
481 mnLastYear = nNewLastYear;
484 else
486 for ( mnRequestYear = nNewFirstYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
487 RequestDateInfo();
488 mnFirstYear = nNewFirstYear;
489 mnLastYear = nNewLastYear;
491 mnRequestYear = 0;
493 mbFormat = sal_False;
496 // -----------------------------------------------------------------------
498 sal_uInt16 Calendar::ImplHitTest( const Point& rPos, Date& rDate ) const
500 if ( mbFormat )
501 return 0;
503 if ( maPrevRect.IsInside( rPos ) )
504 return CALENDAR_HITTEST_PREV;
505 else if ( maNextRect.IsInside( rPos ) )
506 return CALENDAR_HITTEST_NEXT;
508 long nX;
509 long nY;
510 long nOffX;
511 long nYMonth;
512 sal_uInt16 nDay;
513 DayOfWeek eStartDay = ImplGetWeekStart();
515 rDate = GetFirstMonth();
516 nY = 0;
517 for ( long i = 0; i < mnLines; i++ )
519 if ( rPos.Y() < nY )
520 return 0;
522 nX = 0;
523 nYMonth = nY+mnMonthHeight;
524 for ( long j = 0; j < mnMonthPerLine; j++ )
526 if ( (rPos.X() < nX) && (rPos.Y() < nYMonth) )
527 return 0;
529 sal_uInt16 nDaysInMonth = rDate.GetDaysInMonth();
531 // Entsprechender Monat gefunden
532 if ( (rPos.X() > nX) && (rPos.Y() < nYMonth) &&
533 (rPos.X() < nX+mnMonthWidth) )
535 if ( rPos.Y() < (nY+(TITLE_BORDERY*2)+mnDayHeight))
536 return CALENDAR_HITTEST_MONTHTITLE;
537 else
539 long nDayX = nX+mnDaysOffX;
540 long nDayY = nY+mnDaysOffY;
541 if ( rPos.Y() < nDayY )
542 return 0;
543 sal_uInt16 nDayIndex = (sal_uInt16)rDate.GetDayOfWeek();
544 nDayIndex = (nDayIndex+(7-(sal_uInt16)eStartDay)) % 7;
545 if ( (i == 0) && (j == 0) )
547 Date aTempDate = rDate;
548 aTempDate -= nDayIndex;
549 for ( nDay = 0; nDay < nDayIndex; nDay++ )
551 nOffX = nDayX + (nDay*mnDayWidth);
552 if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
553 (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
555 rDate = aTempDate;
556 rDate += nDay;
557 return CALENDAR_HITTEST_DAY;
561 for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
563 if ( rPos.Y() < nDayY )
565 rDate += nDayIndex;
566 return 0;
568 nOffX = nDayX + (nDayIndex*mnDayWidth);
569 if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
570 (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
572 rDate += nDay-1;
573 return CALENDAR_HITTEST_DAY;
575 if ( nDayIndex == 6 )
577 nDayIndex = 0;
578 nDayY += mnDayHeight;
580 else
581 nDayIndex++;
583 if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
585 sal_uInt16 nWeekDay = (sal_uInt16)rDate.GetDayOfWeek();
586 nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
587 sal_uInt16 nDayCount = 42-nDaysInMonth-nWeekDay;
588 Date aTempDate = rDate;
589 aTempDate += nDaysInMonth;
590 for ( nDay = 1; nDay <= nDayCount; nDay++ )
592 if ( rPos.Y() < nDayY )
594 rDate += nDayIndex;
595 return 0;
597 nOffX = nDayX + (nDayIndex*mnDayWidth);
598 if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
599 (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
601 rDate = aTempDate;
602 rDate += nDay-1;
603 return CALENDAR_HITTEST_DAY;
605 if ( nDayIndex == 6 )
607 nDayIndex = 0;
608 nDayY += mnDayHeight;
610 else
611 nDayIndex++;
617 rDate += nDaysInMonth;
618 nX += mnMonthWidth;
621 nY += mnMonthHeight;
624 return 0;
627 // -----------------------------------------------------------------------
629 static void ImplDrawSpinArrow( OutputDevice* pDev, const Rectangle& rRect,
630 sal_Bool bPrev )
632 long i;
633 long n;
634 long nLines;
635 long nHeight = rRect.GetHeight();
636 long nWidth = rRect.GetWidth();
637 if ( nWidth < nHeight )
638 n = nWidth;
639 else
640 n = nHeight;
641 if ( !(n & 0x01) )
642 n--;
643 nLines = n/2;
645 Rectangle aRect( Point( rRect.Left()+(nWidth/2)-(nLines/2),
646 rRect.Top()+(nHeight/2) ),
647 Size( 1, 1 ) );
648 if ( !bPrev )
650 aRect.Left() += nLines;
651 aRect.Right() += nLines;
654 pDev->DrawRect( aRect );
655 for ( i = 0; i < nLines; i++ )
657 if ( bPrev )
659 aRect.Left()++;
660 aRect.Right()++;
662 else
664 aRect.Left()--;
665 aRect.Right()--;
667 aRect.Top()--;
668 aRect.Bottom()++;
669 pDev->DrawRect( aRect );
673 // -----------------------------------------------------------------------
675 void Calendar::ImplDrawSpin( sal_Bool bDrawPrev, sal_Bool bDrawNext )
677 if ( !bDrawPrev && !bDrawNext )
678 return;
680 SetLineColor();
681 SetFillColor( GetSettings().GetStyleSettings().GetButtonTextColor() );
682 if ( bDrawPrev )
684 Rectangle aOutRect = maPrevRect;
685 aOutRect.Left() += 3;
686 aOutRect.Top() += 3;
687 aOutRect.Right() -= 3;
688 aOutRect.Bottom() -= 3;
689 ImplDrawSpinArrow( this, aOutRect, sal_True );
691 if ( bDrawNext )
693 Rectangle aOutRect = maNextRect;
694 aOutRect.Left() += 3;
695 aOutRect.Top() += 3;
696 aOutRect.Right() -= 3;
697 aOutRect.Bottom() -= 3;
698 ImplDrawSpinArrow( this, aOutRect, sal_False );
702 // -----------------------------------------------------------------------
704 void Calendar::ImplDrawDate( long nX, long nY,
705 sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear,
706 DayOfWeek eDayOfWeek,
707 sal_Bool bBack, sal_Bool bOther, sal_uLong nToday )
709 Color* pTextColor = NULL;
710 const OUString& rDay = maDayTexts[nDay-1];
711 Rectangle aDateRect( nX, nY, nX+mnDayWidth-1, nY+mnDayHeight-1 );
713 sal_Bool bSel = sal_False;
714 sal_Bool bFocus = sal_False;
715 // Aktueller Tag
716 if ( (nDay == maCurDate.GetDay()) &&
717 (nMonth == maCurDate.GetMonth()) &&
718 (nYear == maCurDate.GetYear()) )
719 bFocus = sal_True;
720 if ( mpSelectTable )
722 if ( mpSelectTable->find( Date( nDay, nMonth, nYear ).GetDate() ) != mpSelectTable->end() )
723 bSel = sal_True;
726 // Textfarbe ermitteln
727 if ( bSel )
728 pTextColor = &maSelColor;
729 else if ( bOther )
730 pTextColor = &maOtherColor;
731 else
733 if ( eDayOfWeek == SATURDAY )
734 pTextColor = mpSaturdayColor;
735 else if ( eDayOfWeek == SUNDAY )
736 pTextColor = mpSundayColor;
737 if ( !pTextColor )
738 pTextColor = mpStandardColor;
741 if ( bFocus )
742 HideFocus();
744 // Font ermitteln
745 Font aOldFont = GetFont();
746 sal_Bool bBoldFont = sal_False;
748 // Hintergrund ausgeben
749 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
750 if ( bSel || bBack )
752 if ( bSel )
754 SetLineColor();
755 SetFillColor( rStyleSettings.GetHighlightColor() );
756 DrawRect( aDateRect );
758 else
759 Erase( aDateRect );
762 // Text ausgeben
763 long nTextX = nX+(mnDayWidth-GetTextWidth( rDay ))-(DAY_OFFX/2);
764 long nTextY = nY+(mnDayHeight-GetTextHeight())/2;
765 if ( pTextColor )
767 Color aOldColor = GetTextColor();
768 SetTextColor( *pTextColor );
769 DrawText( Point( nTextX, nTextY ), rDay );
770 SetTextColor( aOldColor );
772 else
773 DrawText( Point( nTextX, nTextY ), rDay );
775 // Heute
776 Date aTodayDate( maCurDate );
777 if ( nToday )
778 aTodayDate.SetDate( nToday );
779 else
780 aTodayDate = Date( Date::SYSTEM );
781 if ( (nDay == aTodayDate.GetDay()) &&
782 (nMonth == aTodayDate.GetMonth()) &&
783 (nYear == aTodayDate.GetYear()) )
785 SetLineColor( rStyleSettings.GetWindowTextColor() );
786 SetFillColor();
787 DrawRect( aDateRect );
790 // Evt. noch FocusRect
791 if ( bFocus && HasFocus() )
792 ShowFocus( aDateRect );
794 if( mbDropPos && maDropDate == Date( nDay, nMonth, nYear ) )
795 ImplInvertDropPos();
797 if ( bBoldFont )
798 SetFont( aOldFont );
801 // -----------------------------------------------------------------------
803 void Calendar::ImplDraw( sal_Bool bPaint )
805 ImplFormat();
807 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
808 Size aOutSize = GetOutputSizePixel();
809 long i;
810 long j;
811 long nX;
812 long nY;
813 long nDeltaX;
814 long nDeltaY;
815 long nDayX;
816 long nDayY;
817 sal_uLong nToday = Date( Date::SYSTEM ).GetDate();
818 sal_uInt16 nDay;
819 sal_uInt16 nMonth;
820 sal_uInt16 nYear;
821 Date aDate = GetFirstMonth();
822 DayOfWeek eStartDay = ImplGetWeekStart();
824 HideFocus();
826 nY = 0;
827 for ( i = 0; i < mnLines; i++ )
829 // Titleleiste ausgeben
830 SetLineColor();
831 SetFillColor( rStyleSettings.GetFaceColor() );
832 Rectangle aTitleRect( 0, nY, aOutSize.Width()-1, nY+mnDayHeight-DAY_OFFY+TITLE_BORDERY*2 );
833 if ( !bPaint )
835 Rectangle aTempRect( 1, aTitleRect.Top()+TITLE_BORDERY,
836 aOutSize.Width()-2,
837 aTitleRect.Bottom()-TITLE_BORDERY );
838 if ( !i )
840 aTempRect.Left() = maPrevRect.Right()+1;
841 aTempRect.Right() = maNextRect.Left()-1;
843 DrawRect( aTempRect );
845 else
847 DrawRect( aTitleRect );
848 Point aTopLeft1( aTitleRect.Left(), aTitleRect.Top() );
849 Point aTopLeft2( aTitleRect.Left(), aTitleRect.Top()+1 );
850 Point aBottomRight1( aTitleRect.Right(), aTitleRect.Bottom() );
851 Point aBottomRight2( aTitleRect.Right(), aTitleRect.Bottom()-1 );
852 SetLineColor( rStyleSettings.GetDarkShadowColor() );
853 DrawLine( aTopLeft1, Point( aBottomRight1.X(), aTopLeft1.Y() ) );
854 SetLineColor( rStyleSettings.GetLightColor() );
855 DrawLine( aTopLeft2, Point( aBottomRight2.X(), aTopLeft2.Y() ) );
856 DrawLine( aTopLeft2, Point( aTopLeft2.X(), aBottomRight2.Y() ) );
857 SetLineColor( rStyleSettings.GetShadowColor() );
858 DrawLine( Point( aTopLeft2.X(), aBottomRight2.Y() ), aBottomRight2 );
859 DrawLine( Point( aBottomRight2.X(), aTopLeft2.Y() ), aBottomRight2 );
860 SetLineColor( rStyleSettings.GetDarkShadowColor() );
861 DrawLine( Point( aTopLeft1.X(), aBottomRight1.Y() ), aBottomRight1 );
863 Point aSepPos1( 0, aTitleRect.Top()+TITLE_BORDERY );
864 Point aSepPos2( 0, aTitleRect.Bottom()-TITLE_BORDERY );
865 for ( j = 0; j < mnMonthPerLine-1; j++ )
867 aSepPos1.X() += mnMonthWidth-1;
868 aSepPos2.X() = aSepPos1.X();
869 SetLineColor( rStyleSettings.GetShadowColor() );
870 DrawLine( aSepPos1, aSepPos2 );
871 aSepPos1.X()++;
872 aSepPos2.X() = aSepPos1.X();
873 SetLineColor( rStyleSettings.GetLightColor() );
874 DrawLine( aSepPos1, aSepPos2 );
877 nX = 0;
878 for ( j = 0; j < mnMonthPerLine; j++ )
880 nMonth = aDate.GetMonth();
881 nYear = aDate.GetYear();
883 // Monat in der Titleleiste ausgeben
884 nDeltaX = nX;
885 nDeltaY = nY+TITLE_BORDERY;
886 OUString aMonthText( maCalendarWrapper.getDisplayName(
887 i18n::CalendarDisplayIndex::MONTH, nMonth-1, 1));
888 aMonthText += " ";
889 aMonthText += OUString::number(nYear);
890 long nMonthTextWidth = GetTextWidth( aMonthText );
891 long nMonthOffX1 = 0;
892 long nMonthOffX2 = 0;
893 if ( i == 0 )
895 if ( j == 0 )
896 nMonthOffX1 = maPrevRect.Right()+1;
897 if ( j == mnMonthPerLine-1 )
898 nMonthOffX2 = aOutSize.Width()-maNextRect.Left()+1;
900 long nMaxMonthWidth = mnMonthWidth-nMonthOffX1-nMonthOffX2-4;
901 if ( nMonthTextWidth > nMaxMonthWidth )
903 // Abbreviated month name.
904 aMonthText = maCalendarWrapper.getDisplayName(
905 i18n::CalendarDisplayIndex::MONTH, nMonth-1, 0);
906 aMonthText += " ";
907 aMonthText += OUString::number(nYear);
908 nMonthTextWidth = GetTextWidth( aMonthText );
910 long nTempOff = (mnMonthWidth-nMonthTextWidth+1)/2;
911 if ( nTempOff < nMonthOffX1 )
912 nDeltaX += nMonthOffX1+1;
913 else
915 if ( nTempOff+nMonthTextWidth > mnMonthWidth-nMonthOffX2 )
916 nDeltaX += mnMonthWidth-nMonthOffX2-nMonthTextWidth;
917 else
918 nDeltaX += nTempOff;
920 SetTextColor( rStyleSettings.GetButtonTextColor() );
921 DrawText( Point( nDeltaX, nDeltaY ), aMonthText );
922 SetTextColor( rStyleSettings.GetWindowTextColor() );
924 // Weekleiste ausgeben
925 if ( bPaint )
927 nDayX = nX+mnDaysOffX;
928 nDayY = nY+mnWeekDayOffY;
929 nDeltaY = nDayY + mnDayHeight;
930 SetLineColor( rStyleSettings.GetWindowTextColor() );
931 Point aStartPos( nDayX, nDeltaY );
932 if ( mnWinStyle & WB_WEEKNUMBER )
933 aStartPos.X() -= WEEKNUMBER_OFFX-2;
934 DrawLine( aStartPos, Point( nDayX+(7*mnDayWidth), nDeltaY ) );
935 DrawTextArray( Point( nDayX+mnDayOfWeekAry[0], nDayY ), maDayOfWeekText, &(mnDayOfWeekAry[1]) );
938 // Week-Numbers ausgeben
939 if ( mnWinStyle & WB_WEEKNUMBER )
941 nDayX = nX+mnDaysOffX;
942 nDayY = nY+mnWeekDayOffY;
943 nDeltaY = nDayY + mnDayHeight;
944 long nMonthHeight = mnDayHeight*6;
945 if ( bPaint )
946 DrawLine( Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY ), Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY+nMonthHeight ) );
947 else
948 Erase( Rectangle( nDayX-mnWeekWidth-WEEKNUMBER_OFFX, nDeltaY, nDayX-WEEKNUMBER_OFFX-1, nDeltaY+nMonthHeight ) );
950 Font aOldFont = GetFont();
951 Font aTempFont = aOldFont;
952 ImplGetWeekFont( aTempFont );
953 SetFont( aTempFont );
954 nDayX -= mnWeekWidth;
955 nDayY = nY+mnDaysOffY;
956 maCalendarWrapper.setGregorianDateTime( aDate);
957 for ( sal_uInt16 nWeekCount = 0; nWeekCount < 6; nWeekCount++ )
959 sal_Int32 nWeek = maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
960 OUString aWeekText(OUString::number(nWeek));
961 long nOffX = (mnWeekWidth-WEEKNUMBER_OFFX)-GetTextWidth( aWeekText );
962 long nOffY = (mnDayHeight-GetTextHeight())/2;
963 DrawText( Point( nDayX+nOffX, nDayY+nOffY ), aWeekText );
964 nDayY += mnDayHeight;
965 maCalendarWrapper.addValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, 7);
967 SetFont( aOldFont );
970 // Tage ausgeben
971 sal_uInt16 nDaysInMonth = aDate.GetDaysInMonth();
972 nDayX = nX+mnDaysOffX;
973 nDayY = nY+mnDaysOffY;
974 if ( !bPaint )
976 Rectangle aClearRect( nDayX, nDayY,
977 nDayX+(7*mnDayWidth)-1, nDayY+(6*mnDayHeight)-1 );
978 Erase( aClearRect );
980 sal_uInt16 nDayIndex = (sal_uInt16)aDate.GetDayOfWeek();
981 nDayIndex = (nDayIndex+(7-(sal_uInt16)eStartDay)) % 7;
982 if ( (i == 0) && (j == 0) )
984 Date aTempDate = aDate;
985 aTempDate -= nDayIndex;
986 for ( nDay = 0; nDay < nDayIndex; nDay++ )
988 nDeltaX = nDayX + (nDay*mnDayWidth);
989 ImplDrawDate( nDeltaX, nDayY, nDay+aTempDate.GetDay(),
990 aTempDate.GetMonth(), aTempDate.GetYear(),
991 (DayOfWeek)((nDay+(sal_uInt16)eStartDay)%7), sal_False, sal_True, nToday );
994 for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
996 nDeltaX = nDayX + (nDayIndex*mnDayWidth);
997 ImplDrawDate( nDeltaX, nDayY, nDay, nMonth, nYear,
998 (DayOfWeek)((nDayIndex+(sal_uInt16)eStartDay)%7),
999 sal_False, sal_False, nToday );
1000 if ( nDayIndex == 6 )
1002 nDayIndex = 0;
1003 nDayY += mnDayHeight;
1005 else
1006 nDayIndex++;
1008 if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
1010 sal_uInt16 nWeekDay = (sal_uInt16)aDate.GetDayOfWeek();
1011 nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
1012 sal_uInt16 nDayCount = 42-nDaysInMonth-nWeekDay;
1013 Date aTempDate = aDate;
1014 aTempDate += nDaysInMonth;
1015 for ( nDay = 1; nDay <= nDayCount; nDay++ )
1017 nDeltaX = nDayX + (nDayIndex*mnDayWidth);
1018 ImplDrawDate( nDeltaX, nDayY, nDay,
1019 aTempDate.GetMonth(), aTempDate.GetYear(),
1020 (DayOfWeek)((nDayIndex+(sal_uInt16)eStartDay)%7),
1021 sal_False, sal_True, nToday );
1022 if ( nDayIndex == 6 )
1024 nDayIndex = 0;
1025 nDayY += mnDayHeight;
1027 else
1028 nDayIndex++;
1032 aDate += nDaysInMonth;
1033 nX += mnMonthWidth;
1036 nY += mnMonthHeight;
1039 // Spin-Buttons zeichnen
1040 if ( bPaint )
1041 ImplDrawSpin();
1044 // -----------------------------------------------------------------------
1046 void Calendar::ImplUpdateDate( const Date& rDate )
1048 if ( IsReallyVisible() && IsUpdateMode() )
1050 Rectangle aDateRect( GetDateRect( rDate ) );
1051 if ( !aDateRect.IsEmpty() )
1053 sal_Bool bOther = (rDate < GetFirstMonth()) || (rDate > GetLastMonth());
1054 ImplDrawDate( aDateRect.Left(), aDateRect.Top(),
1055 rDate.GetDay(), rDate.GetMonth(), rDate.GetYear(),
1056 rDate.GetDayOfWeek(), sal_True, bOther );
1061 // -----------------------------------------------------------------------
1063 void Calendar::ImplUpdateSelection( IntDateSet* pOld )
1065 IntDateSet* pNew = mpSelectTable;
1067 for ( IntDateSet::const_iterator it = pOld->begin(); it != pOld->end(); ++it )
1069 sal_uLong nKey = *it;
1070 if ( pNew->find( nKey ) == pNew->end() )
1072 Date aTempDate( nKey );
1073 ImplUpdateDate( aTempDate );
1077 for ( IntDateSet::const_iterator it = pNew->begin(); it != pNew->end(); ++it )
1079 sal_uLong nKey = *it;
1080 if ( pOld->find( nKey ) == pOld->end() )
1082 Date aTempDate( nKey );
1083 ImplUpdateDate( aTempDate );
1088 // -----------------------------------------------------------------------
1090 void Calendar::ImplMouseSelect( const Date& rDate, sal_uInt16 nHitTest,
1091 sal_Bool bMove, sal_Bool bExpand, sal_Bool bExtended )
1093 IntDateSet* pOldSel = new IntDateSet( *mpSelectTable );
1094 Date aOldDate = maCurDate;
1095 Date aTempDate = rDate;
1097 if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
1098 aTempDate--;
1100 if ( mbMultiSelection )
1102 maCurDate = aTempDate;
1103 mbSelLeft = aTempDate < maAnchorDate;
1105 if ( bMove )
1107 if ( mbSelLeft )
1109 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), aTempDate );
1110 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, maAnchorDate, Date( 31, 12, 9999 ) );
1112 else
1114 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), maAnchorDate );
1115 ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, aTempDate, Date( 31, 12, 9999 ) );
1117 ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, !mbUnSel );
1119 else
1121 if ( bExpand )
1123 if ( !bExtended )
1125 if ( mbSelLeft )
1127 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aTempDate, sal_False );
1128 ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), sal_False );
1130 else
1132 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, sal_False );
1133 ImplCalendarSelectDateRange( mpSelectTable, aTempDate, Date( 31, 12, 9999 ), sal_False );
1136 ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, sal_True );
1138 else if ( bExtended && !(mnWinStyle & WB_RANGESELECT) )
1140 maAnchorDate = aTempDate;
1141 if ( IsDateSelected( aTempDate ) )
1143 mbUnSel = sal_True;
1144 ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_False );
1146 else
1148 ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_True );
1151 else
1153 maAnchorDate = aTempDate;
1154 ImplCalendarClearSelectDate( mpSelectTable );
1155 ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_True );
1158 mpRestoreSelectTable = new IntDateSet( *mpSelectTable );
1161 else
1163 if ( aTempDate < maCurDate )
1164 mbSelLeft = sal_True;
1165 else
1166 mbSelLeft = sal_False;
1167 if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
1168 aTempDate = maOldCurDate;
1169 if ( !bMove )
1170 maAnchorDate = aTempDate;
1171 if ( aTempDate != maCurDate )
1173 maCurDate = aTempDate;
1174 ImplCalendarSelectDate( mpSelectTable, aOldDate, sal_False );
1175 ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
1179 sal_Bool bNewSel = *pOldSel != *mpSelectTable;
1180 if ( (maCurDate != aOldDate) || bNewSel )
1182 if ( bNewSel )
1184 mbInSelChange = sal_True;
1185 SelectionChanging();
1186 mbInSelChange = sal_False;
1188 HideFocus();
1189 if ( bNewSel )
1190 ImplUpdateSelection( pOldSel );
1191 if ( !bNewSel || pOldSel->find( aOldDate.GetDate() ) == pOldSel->end() )
1192 ImplUpdateDate( aOldDate );
1193 // Damit Focus-Rechteck auch wieder neu ausgegeben wird
1194 if ( HasFocus() || !bNewSel
1195 || mpSelectTable->find( maCurDate.GetDate() ) == mpSelectTable->end() )
1196 ImplUpdateDate( maCurDate );
1198 delete pOldSel;
1201 // -----------------------------------------------------------------------
1203 void Calendar::ImplUpdate( sal_Bool bCalcNew )
1205 if ( IsReallyVisible() && IsUpdateMode() )
1207 if ( bCalcNew && !mbCalc )
1208 Invalidate();
1209 else if ( !mbFormat && !mbCalc )
1211 if ( mbDirect )
1213 mbFormat = sal_True;
1214 ImplDraw( sal_False );
1215 return;
1217 else
1218 Invalidate();
1222 if ( bCalcNew )
1223 mbCalc = sal_True;
1224 mbFormat = sal_True;
1227 // -----------------------------------------------------------------------
1229 void Calendar::ImplInvertDropPos()
1231 Rectangle aRect = GetDateRect( maDropDate );//this is one Pixel to width and one to heigh
1232 aRect.Bottom() = aRect.Top()+mnDayHeight-1;
1233 aRect.Right() = aRect.Left()+mnDayWidth-1;
1234 Invert( aRect );
1237 // -----------------------------------------------------------------------
1239 void Calendar::ImplScroll( sal_Bool bPrev )
1241 Date aNewFirstMonth = GetFirstMonth();
1242 if ( bPrev )
1244 aNewFirstMonth--;
1245 aNewFirstMonth -= aNewFirstMonth.GetDaysInMonth()-1;
1247 else
1248 aNewFirstMonth += aNewFirstMonth.GetDaysInMonth();
1249 mbDirect = sal_True;
1250 SetFirstDate( aNewFirstMonth );
1251 mbDirect = sal_False;
1254 // -----------------------------------------------------------------------
1256 void Calendar::ImplShowMenu( const Point& rPos, const Date& rDate )
1258 EndSelection();
1260 Date aOldFirstDate = GetFirstMonth();
1261 PopupMenu aPopupMenu;
1262 PopupMenu* pYearPopupMenus[MENU_YEAR_COUNT];
1263 sal_uInt16 nMonthOff;
1264 sal_uInt16 nCurItemId;
1265 sal_uInt16 nYear = rDate.GetYear()-1;
1266 sal_uInt16 i;
1267 sal_uInt16 j;
1268 sal_uInt16 nYearIdCount = 1000;
1270 nMonthOff = (rDate.GetYear()-aOldFirstDate.GetYear())*12;
1271 if ( aOldFirstDate.GetMonth() < rDate.GetMonth() )
1272 nMonthOff += rDate.GetMonth()-aOldFirstDate.GetMonth();
1273 else
1274 nMonthOff -= aOldFirstDate.GetMonth()-rDate.GetMonth();
1276 // Menu aufbauen (Jahre mit verschiedenen Monaten aufnehmen)
1277 for ( i = 0; i < MENU_YEAR_COUNT; i++ )
1279 pYearPopupMenus[i] = new PopupMenu;
1280 for ( j = 1; j <= 12; j++ )
1281 pYearPopupMenus[i]->InsertItem( nYearIdCount+j,
1282 maCalendarWrapper.getDisplayName(
1283 i18n::CalendarDisplayIndex::MONTH, j-1, 1));
1284 aPopupMenu.InsertItem( 10+i, OUString::number( nYear+i ) );
1285 aPopupMenu.SetPopupMenu( 10+i, pYearPopupMenus[i] );
1286 nYearIdCount += 1000;
1289 mbMenuDown = sal_True;
1290 nCurItemId = aPopupMenu.Execute( this, rPos );
1291 mbMenuDown = sal_False;
1293 // Menu zerstoeren
1294 aPopupMenu.SetPopupMenu( 2, NULL );
1295 for ( i = 0; i < MENU_YEAR_COUNT; i++ )
1297 aPopupMenu.SetPopupMenu( 10+i, NULL );
1298 delete pYearPopupMenus[i];
1301 if ( nCurItemId )
1303 sal_uInt16 nTempMonthOff = nMonthOff % 12;
1304 sal_uInt16 nTempYearOff = nMonthOff / 12;
1305 sal_uInt16 nNewMonth = nCurItemId % 1000;
1306 sal_uInt16 nNewYear = nYear+((nCurItemId-1000)/1000);
1307 if ( nTempMonthOff < nNewMonth )
1308 nNewMonth = nNewMonth - nTempMonthOff;
1309 else
1311 nNewYear--;
1312 nNewMonth = 12-(nTempMonthOff-nNewMonth);
1314 nNewYear = nNewYear - nTempYearOff;
1315 SetFirstDate( Date( 1, nNewMonth, nNewYear ) );
1319 // -----------------------------------------------------------------------
1321 void Calendar::ImplTracking( const Point& rPos, sal_Bool bRepeat )
1323 Date aTempDate = maCurDate;
1324 sal_uInt16 nHitTest = ImplHitTest( rPos, aTempDate );
1326 if ( mbSpinDown )
1328 mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
1329 mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
1331 if ( bRepeat && (mbPrevIn || mbNextIn) )
1333 mbScrollDateRange = sal_True;
1334 ImplScroll( mbPrevIn );
1335 mbScrollDateRange = sal_False;
1338 else
1339 ImplMouseSelect( aTempDate, nHitTest, sal_True, sal_False, sal_False );
1342 // -----------------------------------------------------------------------
1344 void Calendar::ImplEndTracking( sal_Bool bCancel )
1346 sal_Bool bSelection = mbSelection;
1347 sal_Bool bSpinDown = mbSpinDown;
1349 mbDrag = sal_False;
1350 mbSelection = sal_False;
1351 mbMultiSelection = sal_False;
1352 mbUnSel = sal_False;
1353 mbSpinDown = sal_False;
1354 mbPrevIn = sal_False;
1355 mbNextIn = sal_False;
1357 if ( bCancel )
1359 if ( maOldFirstDate != maFirstDate )
1360 SetFirstDate( maOldFirstDate );
1362 if ( !bSpinDown )
1364 IntDateSet* pOldSel = new IntDateSet( *mpSelectTable );
1365 Date aOldDate = maCurDate;
1366 maCurDate = maOldCurDate;
1367 *mpSelectTable = *mpOldSelectTable;
1368 HideFocus();
1369 ImplUpdateSelection( pOldSel );
1370 if ( pOldSel->find( aOldDate.GetDate() ) == pOldSel->end() )
1371 ImplUpdateDate( aOldDate );
1372 // Damit Focus-Rechteck auch wieder neu ausgegeben wird
1373 if ( HasFocus() || mpSelectTable->find( maCurDate.GetDate() ) == mpSelectTable->end() )
1374 ImplUpdateDate( maCurDate );
1375 delete pOldSel;
1379 if ( !bSpinDown )
1381 if ( !bCancel )
1383 // Feststellen, ob wir sichtbaren Bereich scrollen sollen
1384 sal_uLong nSelCount = mpSelectTable->size();
1385 if ( nSelCount )
1387 Date aFirstSelDate( *mpSelectTable->begin() );
1388 Date aLastSelDate( *mpSelectTable->rbegin() );
1389 if ( aLastSelDate < GetFirstMonth() )
1390 ImplScroll( sal_True );
1391 else if ( GetLastMonth() < aFirstSelDate )
1392 ImplScroll( sal_False );
1396 if ( mbAllSel ||
1397 (!bCancel && ((maCurDate != maOldCurDate) || (*mpOldSelectTable != *mpSelectTable))) )
1398 Select();
1400 if ( !bSelection && (mnWinStyle & WB_TABSTOP) && !bCancel )
1401 GrabFocus();
1403 delete mpOldSelectTable;
1404 mpOldSelectTable = NULL;
1405 delete mpRestoreSelectTable;
1406 mpRestoreSelectTable = NULL;
1410 // -----------------------------------------------------------------------
1412 IMPL_STATIC_LINK( Calendar, ScrollHdl, Timer*, EMPTYARG )
1414 sal_Bool bPrevIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_PREV) != 0;
1415 sal_Bool bNextIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_NEXT) != 0;
1416 if( bNextIn || bPrevIn )
1418 pThis->mbScrollDateRange = sal_True;
1419 pThis->ImplScroll( bPrevIn );
1420 pThis->mbScrollDateRange = sal_False;
1422 return 0;
1425 // -----------------------------------------------------------------------
1427 void Calendar::MouseButtonDown( const MouseEvent& rMEvt )
1429 if ( rMEvt.IsLeft() && !mbMenuDown )
1431 Date aTempDate = maCurDate;
1432 sal_uInt16 nHitTest = ImplHitTest( rMEvt.GetPosPixel(), aTempDate );
1433 if ( nHitTest )
1435 if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
1436 ImplShowMenu( rMEvt.GetPosPixel(), aTempDate );
1437 else
1439 maOldFirstDate = maFirstDate;
1441 mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
1442 mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
1443 if ( mbPrevIn || mbNextIn )
1445 mbSpinDown = sal_True;
1446 mbScrollDateRange = sal_True;
1447 ImplScroll( mbPrevIn );
1448 mbScrollDateRange = sal_False;
1449 // Hier muss BUTTONREPEAT stehen, also nicht wieder
1450 // auf SCROLLREPEAT aendern, sondern mit TH abklaeren,
1451 // warum es evtl. anders sein sollte (71775)
1452 StartTracking( STARTTRACK_BUTTONREPEAT );
1454 else
1456 if ( (rMEvt.GetClicks() == 2) && (nHitTest & CALENDAR_HITTEST_DAY) )
1457 DoubleClick();
1458 else
1460 if ( mpOldSelectTable )
1461 delete mpOldSelectTable;
1462 maOldCurDate = maCurDate;
1463 mpOldSelectTable = new IntDateSet( *mpSelectTable );
1465 if ( !mbSelection )
1467 mbDrag = sal_True;
1468 StartTracking();
1471 mbMultiSelection = (mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT)) != 0;
1472 if ( (nHitTest & CALENDAR_HITTEST_DAY) && mbMultiSelection )
1473 mbWeekSel = sal_True;
1474 else
1475 mbWeekSel = sal_False;
1476 ImplMouseSelect( aTempDate, nHitTest, sal_False, rMEvt.IsShift(), rMEvt.IsMod1() );
1482 return;
1485 Control::MouseButtonDown( rMEvt );
1488 // -----------------------------------------------------------------------
1490 void Calendar::MouseButtonUp( const MouseEvent& rMEvt )
1492 if ( rMEvt.IsLeft() && mbSelection )
1493 ImplEndTracking( sal_False );
1494 else
1495 Control::MouseButtonUp( rMEvt );
1498 // -----------------------------------------------------------------------
1500 void Calendar::MouseMove( const MouseEvent& rMEvt )
1502 if ( mbSelection && rMEvt.GetButtons() )
1503 ImplTracking( rMEvt.GetPosPixel(), sal_False );
1504 else
1505 Control::MouseMove( rMEvt );
1508 // -----------------------------------------------------------------------
1510 void Calendar::Tracking( const TrackingEvent& rTEvt )
1512 Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
1514 if ( rTEvt.IsTrackingEnded() )
1515 ImplEndTracking( rTEvt.IsTrackingCanceled() );
1516 else
1517 ImplTracking( aMousePos, rTEvt.IsTrackingRepeat() );
1520 // -----------------------------------------------------------------------
1522 void Calendar::KeyInput( const KeyEvent& rKEvt )
1524 Date aNewDate = maCurDate;
1525 sal_Bool bMultiSel = (mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) != 0;
1526 sal_Bool bExpand = rKEvt.GetKeyCode().IsShift();
1527 sal_Bool bExtended = rKEvt.GetKeyCode().IsMod1();
1529 switch ( rKEvt.GetKeyCode().GetCode() )
1531 case KEY_HOME:
1532 aNewDate.SetDay( 1 );
1533 break;
1535 case KEY_END:
1536 aNewDate.SetDay( aNewDate.GetDaysInMonth() );
1537 break;
1539 case KEY_LEFT:
1540 aNewDate--;
1541 break;
1543 case KEY_RIGHT:
1544 aNewDate++;
1545 break;
1547 case KEY_UP:
1548 aNewDate -= 7;
1549 break;
1551 case KEY_DOWN:
1552 aNewDate += 7;
1553 break;
1555 case KEY_PAGEUP:
1557 Date aTempDate = aNewDate;
1558 aTempDate -= aNewDate.GetDay()+1;
1559 aNewDate -= aTempDate.GetDaysInMonth();
1561 break;
1563 case KEY_PAGEDOWN:
1564 aNewDate += aNewDate.GetDaysInMonth();
1565 break;
1567 case KEY_SPACE:
1568 if ( bMultiSel && !(mnWinStyle & WB_RANGESELECT) )
1570 if ( !bExpand )
1572 sal_Bool bDateSel = IsDateSelected( maCurDate );
1573 SelectDate( maCurDate, !bDateSel );
1574 mbSelLeft = sal_False;
1575 SelectionChanging();
1576 mbTravelSelect = sal_True;
1577 Select();
1578 mbTravelSelect = sal_False;
1581 else
1582 Control::KeyInput( rKEvt );
1583 break;
1585 default:
1586 Control::KeyInput( rKEvt );
1587 break;
1590 if ( aNewDate != maCurDate )
1592 if ( bMultiSel && bExpand )
1594 IntDateSet* pOldSel = new IntDateSet( *mpSelectTable );
1595 Date aOldAnchorDate = maAnchorDate;
1596 mbSelLeft = aNewDate < maAnchorDate;
1597 if ( !bExtended )
1599 if ( mbSelLeft )
1601 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aNewDate, sal_False );
1602 ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), sal_False );
1604 else
1606 ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, sal_False );
1607 ImplCalendarSelectDateRange( mpSelectTable, aNewDate, Date( 31, 12, 9999 ), sal_False );
1610 ImplCalendarSelectDateRange( mpSelectTable, aNewDate, maAnchorDate, sal_True );
1611 mbDirect = sal_True;
1612 SetCurDate( aNewDate );
1613 mbDirect = sal_False;
1614 maAnchorDate = aOldAnchorDate;
1615 mbInSelChange = sal_True;
1616 SelectionChanging();
1617 mbInSelChange = sal_False;
1618 ImplUpdateSelection( pOldSel );
1619 delete pOldSel;
1621 else
1623 if ( mnWinStyle & WB_RANGESELECT )
1625 SetNoSelection();
1626 SelectDate( aNewDate, sal_True );
1628 mbDirect = sal_True;
1629 SetCurDate( aNewDate );
1630 mbDirect = sal_False;
1632 mbTravelSelect = sal_True;
1633 Select();
1634 mbTravelSelect = sal_False;
1638 // -----------------------------------------------------------------------
1640 void Calendar::Paint( const Rectangle& )
1642 ImplDraw( sal_True );
1645 // -----------------------------------------------------------------------
1647 void Calendar::GetFocus()
1649 ImplUpdateDate( maCurDate );
1650 Control::GetFocus();
1653 // -----------------------------------------------------------------------
1655 void Calendar::LoseFocus()
1657 HideFocus();
1658 Control::LoseFocus();
1661 // -----------------------------------------------------------------------
1663 void Calendar::Resize()
1665 ImplUpdate( sal_True );
1666 Control::Resize();
1669 // -----------------------------------------------------------------------
1671 void Calendar::RequestHelp( const HelpEvent& rHEvt )
1673 if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
1675 Date aDate = maCurDate;
1676 if ( GetDate( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ), aDate ) )
1678 Rectangle aDateRect = GetDateRect( aDate );
1679 Point aPt = OutputToScreenPixel( aDateRect.TopLeft() );
1680 aDateRect.Left() = aPt.X();
1681 aDateRect.Top() = aPt.Y();
1682 aPt = OutputToScreenPixel( aDateRect.BottomRight() );
1683 aDateRect.Right() = aPt.X();
1684 aDateRect.Bottom() = aPt.Y();
1686 if ( rHEvt.GetMode() & HELPMODE_QUICK )
1688 maCalendarWrapper.setGregorianDateTime( aDate);
1689 sal_uInt16 nWeek = (sal_uInt16) maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
1690 sal_uInt16 nMonth = aDate.GetMonth();
1691 OUString aStr( maDayText );
1692 aStr += ": ";
1693 aStr += OUString::number(aDate.GetDayOfYear());
1694 aStr += " / ";
1695 aStr += maWeekText;
1696 aStr += ": ";
1697 aStr += OUString::number(nWeek);
1698 // Evt. noch Jahr hinzufuegen, wenn es nicht das gleiche ist
1699 if ( (nMonth == 12) && (nWeek == 1) )
1701 aStr += ", ";
1702 aStr += OUString::number(aDate.GetYear()+1);
1704 else if ( (nMonth == 1) && (nWeek > 50) )
1706 aStr += ", ";
1707 aStr += OUString::number(aDate.GetYear()-1);
1709 Help::ShowQuickHelp( this, aDateRect, aStr );
1710 return;
1715 Control::RequestHelp( rHEvt );
1718 // -----------------------------------------------------------------------
1720 void Calendar::Command( const CommandEvent& rCEvt )
1722 if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
1724 if ( !mbSelection && rCEvt.IsMouseEvent() )
1726 Date aTempDate = maCurDate;
1727 sal_uInt16 nHitTest = ImplHitTest( rCEvt.GetMousePosPixel(), aTempDate );
1728 if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
1730 ImplShowMenu( rCEvt.GetMousePosPixel(), aTempDate );
1731 return;
1735 else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
1737 const CommandWheelData* pData = rCEvt.GetWheelData();
1738 if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
1740 long nNotchDelta = pData->GetNotchDelta();
1741 if ( nNotchDelta < 0 )
1743 while ( nNotchDelta < 0 )
1745 ImplScroll( sal_True );
1746 nNotchDelta++;
1749 else
1751 while ( nNotchDelta > 0 )
1753 ImplScroll( sal_False );
1754 nNotchDelta--;
1758 return;
1762 Control::Command( rCEvt );
1765 // -----------------------------------------------------------------------
1767 void Calendar::StateChanged( StateChangedType nType )
1769 Control::StateChanged( nType );
1771 if ( nType == STATE_CHANGE_INITSHOW )
1772 ImplFormat();
1775 // -----------------------------------------------------------------------
1777 void Calendar::DataChanged( const DataChangedEvent& rDCEvt )
1779 Control::DataChanged( rDCEvt );
1781 if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
1782 (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
1783 ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
1784 (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
1786 ImplInitSettings();
1787 Invalidate();
1791 // -----------------------------------------------------------------------
1793 void Calendar::SelectionChanging()
1795 maSelectionChangingHdl.Call( this );
1798 // -----------------------------------------------------------------------
1800 void Calendar::DateRangeChanged()
1802 maDateRangeChangedHdl.Call( this );
1805 // -----------------------------------------------------------------------
1807 void Calendar::RequestDateInfo()
1809 maRequestDateInfoHdl.Call( this );
1812 // -----------------------------------------------------------------------
1814 void Calendar::DoubleClick()
1816 maDoubleClickHdl.Call( this );
1819 // -----------------------------------------------------------------------
1821 void Calendar::Select()
1823 maSelectHdl.Call( this );
1826 // -----------------------------------------------------------------------
1828 void Calendar::SelectDate( const Date& rDate, sal_Bool bSelect )
1830 if ( !rDate.IsValidAndGregorian() )
1831 return;
1833 IntDateSet* pOldSel;
1835 if ( !mbInSelChange )
1836 pOldSel = new IntDateSet( *mpSelectTable );
1837 else
1838 pOldSel = NULL;
1840 ImplCalendarSelectDate( mpSelectTable, rDate, bSelect );
1842 if ( pOldSel )
1844 ImplUpdateSelection( pOldSel );
1845 delete pOldSel;
1849 // -----------------------------------------------------------------------
1851 void Calendar::SetNoSelection()
1853 IntDateSet* pOldSel;
1855 if ( !mbInSelChange )
1856 pOldSel = new IntDateSet( *mpSelectTable );
1857 else
1858 pOldSel = NULL;
1860 ImplCalendarClearSelectDate( mpSelectTable );
1862 if ( pOldSel )
1864 ImplUpdateSelection( pOldSel );
1865 delete pOldSel;
1869 // -----------------------------------------------------------------------
1871 sal_Bool Calendar::IsDateSelected( const Date& rDate ) const
1873 return mpSelectTable->find( rDate.GetDate() ) != mpSelectTable->end();
1876 // -----------------------------------------------------------------------
1878 Date Calendar::GetFirstSelectedDate() const
1880 if ( !mpSelectTable->empty() )
1881 return Date( *mpSelectTable->begin() );
1882 else
1884 Date aDate( 0, 0, 0 );
1885 return aDate;
1889 // -----------------------------------------------------------------------
1891 void Calendar::SetCurDate( const Date& rNewDate )
1893 if ( !rNewDate.IsValidAndGregorian() )
1894 return;
1896 if ( maCurDate != rNewDate )
1898 sal_Bool bUpdate = IsVisible() && IsUpdateMode();
1899 Date aOldDate = maCurDate;
1900 maCurDate = rNewDate;
1901 maAnchorDate = maCurDate;
1903 if ( !(mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) )
1905 ImplCalendarSelectDate( mpSelectTable, aOldDate, sal_False );
1906 ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
1908 else if ( !HasFocus() )
1909 bUpdate = sal_False;
1911 // Aktuelles Datum noch in den sichtbaren Bereich verschieben
1912 if ( mbFormat || (maCurDate < GetFirstMonth()) )
1913 SetFirstDate( maCurDate );
1914 else if ( maCurDate > GetLastMonth() )
1916 Date aTempDate = GetLastMonth();
1917 long nDateOff = maCurDate-aTempDate;
1918 if ( nDateOff < 365 )
1920 Date aFirstDate = GetFirstMonth();
1921 aFirstDate += aFirstDate.GetDaysInMonth();
1922 aTempDate++;
1923 while ( nDateOff > aTempDate.GetDaysInMonth() )
1925 aFirstDate += aFirstDate.GetDaysInMonth();
1926 long nDaysInMonth = aTempDate.GetDaysInMonth();
1927 aTempDate += nDaysInMonth;
1928 nDateOff -= nDaysInMonth;
1930 SetFirstDate( aFirstDate );
1932 else
1933 SetFirstDate( maCurDate );
1935 else
1937 if ( bUpdate )
1939 HideFocus();
1940 ImplUpdateDate( aOldDate );
1941 ImplUpdateDate( maCurDate );
1947 // -----------------------------------------------------------------------
1949 void Calendar::SetFirstDate( const Date& rNewFirstDate )
1951 if ( maFirstDate != rNewFirstDate )
1953 maFirstDate = Date( 1, rNewFirstDate.GetMonth(), rNewFirstDate.GetYear() );
1954 mbDropPos = sal_False;
1955 ImplUpdate();
1959 // -----------------------------------------------------------------------
1961 Date Calendar::GetFirstMonth() const
1963 if ( maFirstDate.GetDay() > 1 )
1965 if ( maFirstDate.GetMonth() == 12 )
1966 return Date( 1, 1, maFirstDate.GetYear()+1 );
1967 else
1968 return Date( 1, maFirstDate.GetMonth()+1, maFirstDate.GetYear() );
1970 else
1971 return maFirstDate;
1974 // -----------------------------------------------------------------------
1976 Date Calendar::GetLastMonth() const
1978 Date aDate = GetFirstMonth();
1979 sal_uInt16 nMonthCount = GetMonthCount();
1980 for ( sal_uInt16 i = 0; i < nMonthCount; i++ )
1981 aDate += aDate.GetDaysInMonth();
1982 aDate--;
1983 return aDate;
1986 // -----------------------------------------------------------------------
1988 sal_uInt16 Calendar::GetMonthCount() const
1990 if ( mbFormat )
1991 return 1;
1992 else
1993 return (sal_uInt16)(mnMonthPerLine*mnLines);
1996 // -----------------------------------------------------------------------
1998 sal_Bool Calendar::GetDate( const Point& rPos, Date& rDate ) const
2000 Date aDate = maCurDate;
2001 sal_uInt16 nHitTest = ImplHitTest( rPos, aDate );
2002 if ( nHitTest & CALENDAR_HITTEST_DAY )
2004 rDate = aDate;
2005 return sal_True;
2007 else
2008 return sal_False;
2011 // -----------------------------------------------------------------------
2013 Rectangle Calendar::GetDateRect( const Date& rDate ) const
2015 Rectangle aRect;
2017 if ( mbFormat || (rDate < maFirstDate) || (rDate > (maFirstDate+mnDayCount)) )
2018 return aRect;
2020 long nX;
2021 long nY;
2022 sal_uLong nDaysOff;
2023 sal_uInt16 nDayIndex;
2024 Date aDate = GetFirstMonth();
2026 if ( rDate < aDate )
2028 aRect = GetDateRect( aDate );
2029 nDaysOff = aDate-rDate;
2030 nX = (long)(nDaysOff*mnDayWidth);
2031 aRect.Left() -= nX;
2032 aRect.Right() -= nX;
2033 return aRect;
2035 else
2037 Date aLastDate = GetLastMonth();
2038 if ( rDate > aLastDate )
2040 sal_uInt16 nWeekDay = (sal_uInt16)aLastDate.GetDayOfWeek();
2041 nWeekDay = (nWeekDay+(7-(sal_uInt16)ImplGetWeekStart())) % 7;
2042 aLastDate -= nWeekDay;
2043 aRect = GetDateRect( aLastDate );
2044 nDaysOff = rDate-aLastDate;
2045 nDayIndex = 0;
2046 for ( sal_uInt16 i = 0; i <= nDaysOff; i++ )
2048 if ( aLastDate == rDate )
2050 aRect.Left() += nDayIndex*mnDayWidth;
2051 aRect.Right() = aRect.Left()+mnDayWidth;
2052 return aRect;
2054 if ( nDayIndex == 6 )
2056 nDayIndex = 0;
2057 aRect.Top() += mnDayHeight;
2058 aRect.Bottom() += mnDayHeight;
2060 else
2061 nDayIndex++;
2062 aLastDate++;
2067 nY = 0;
2068 for ( long i = 0; i < mnLines; i++ )
2070 nX = 0;
2071 for ( long j = 0; j < mnMonthPerLine; j++ )
2073 sal_uInt16 nDaysInMonth = aDate.GetDaysInMonth();
2075 // Monat gerufen
2076 if ( (aDate.GetMonth() == rDate.GetMonth()) &&
2077 (aDate.GetYear() == rDate.GetYear()) )
2079 long nDayX = nX+mnDaysOffX;
2080 long nDayY = nY+mnDaysOffY;
2081 nDayIndex = (sal_uInt16)aDate.GetDayOfWeek();
2082 nDayIndex = (nDayIndex+(7-(sal_uInt16)ImplGetWeekStart())) % 7;
2083 for ( sal_uInt16 nDay = 1; nDay <= nDaysInMonth; nDay++ )
2085 if ( nDay == rDate.GetDay() )
2087 aRect.Left() = nDayX + (nDayIndex*mnDayWidth);
2088 aRect.Top() = nDayY;
2089 aRect.Right() = aRect.Left()+mnDayWidth;
2090 aRect.Bottom() = aRect.Top()+mnDayHeight;
2091 break;
2093 if ( nDayIndex == 6 )
2095 nDayIndex = 0;
2096 nDayY += mnDayHeight;
2098 else
2099 nDayIndex++;
2103 aDate += nDaysInMonth;
2104 nX += mnMonthWidth;
2107 nY += mnMonthHeight;
2110 return aRect;
2113 // -----------------------------------------------------------------------
2115 void Calendar::StartSelection()
2117 if ( mpOldSelectTable )
2118 delete mpOldSelectTable;
2119 maOldCurDate = maCurDate;
2120 mpOldSelectTable = new IntDateSet( *mpSelectTable );
2122 mbSelection = sal_True;
2125 // -----------------------------------------------------------------------
2127 void Calendar::EndSelection()
2129 if ( mbDrag || mbSpinDown || mbSelection )
2131 if ( !mbSelection )
2132 ReleaseMouse();
2134 mbDrag = sal_False;
2135 mbSelection = sal_False;
2136 mbMultiSelection = sal_False;
2137 mbSpinDown = sal_False;
2138 mbPrevIn = sal_False;
2139 mbNextIn = sal_False;
2143 // -----------------------------------------------------------------------
2145 Size Calendar::CalcWindowSizePixel( long nCalcMonthPerLine,
2146 long nCalcLines ) const
2148 OUString a99Text("99");
2149 Font aOldFont = GetFont();
2151 // Wochenanzeige beruecksichtigen
2152 long nWeekWidth;
2153 if ( mnWinStyle & WB_WEEKNUMBER )
2155 Font aTempFont = aOldFont;
2156 ImplGetWeekFont( aTempFont );
2157 ((Calendar*)this)->SetFont( aTempFont );
2158 nWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
2159 ((Calendar*)this)->SetFont( aOldFont );
2161 else
2162 nWeekWidth = 0;
2164 if ( mnWinStyle & WB_BOLDTEXT )
2166 Font aFont = aOldFont;
2167 if ( aFont.GetWeight() < WEIGHT_BOLD )
2168 aFont.SetWeight( WEIGHT_BOLD );
2169 else
2170 aFont.SetWeight( WEIGHT_NORMAL );
2171 ((Calendar*)this)->SetFont( aFont );
2174 Size aSize;
2175 long n99TextWidth = GetTextWidth( a99Text );
2176 long nTextHeight = GetTextHeight();
2178 if ( mnWinStyle & WB_BOLDTEXT )
2179 ((Calendar*)this)->SetFont( aOldFont );
2181 aSize.Width() += ((n99TextWidth+DAY_OFFX)*7) + nWeekWidth;
2182 aSize.Width() += MONTH_BORDERX*2;
2183 aSize.Width() *= nCalcMonthPerLine;
2185 aSize.Height() = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
2186 aSize.Height() += nTextHeight + WEEKDAY_OFFY;
2187 aSize.Height() += ((nTextHeight+DAY_OFFY)*6);
2188 aSize.Height() += MONTH_OFFY;
2189 aSize.Height() *= nCalcLines;
2191 return aSize;
2194 // =======================================================================
2196 #define CALFIELD_EXTRA_BUTTON_WIDTH 14
2197 #define CALFIELD_EXTRA_BUTTON_HEIGHT 8
2198 #define CALFIELD_SEP_X 6
2199 #define CALFIELD_BORDERLINE_X 5
2200 #define CALFIELD_BORDER_YTOP 4
2201 #define CALFIELD_BORDER_Y 5
2203 // =======================================================================
2205 class ImplCFieldFloatWin : public FloatingWindow
2207 private:
2208 Calendar* mpCalendar;
2209 PushButton* mpTodayBtn;
2210 PushButton* mpNoneBtn;
2211 FixedLine* mpFixedLine;
2213 public:
2214 ImplCFieldFloatWin( Window* pParent );
2215 ~ImplCFieldFloatWin();
2217 void SetCalendar( Calendar* pCalendar )
2218 { mpCalendar = pCalendar; }
2220 PushButton* EnableTodayBtn( sal_Bool bEnable );
2221 PushButton* EnableNoneBtn( sal_Bool bEnable );
2222 void ArrangeButtons();
2224 long Notify( NotifyEvent& rNEvt );
2227 // -----------------------------------------------------------------------
2229 ImplCFieldFloatWin::ImplCFieldFloatWin( Window* pParent ) :
2230 FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW )
2232 mpCalendar = NULL;
2233 mpTodayBtn = NULL;
2234 mpNoneBtn = NULL;
2235 mpFixedLine = NULL;
2238 // -----------------------------------------------------------------------
2240 ImplCFieldFloatWin::~ImplCFieldFloatWin()
2242 delete mpTodayBtn;
2243 delete mpNoneBtn;
2244 delete mpFixedLine;
2247 // -----------------------------------------------------------------------
2249 PushButton* ImplCFieldFloatWin::EnableTodayBtn( sal_Bool bEnable )
2251 if ( bEnable )
2253 if ( !mpTodayBtn )
2255 mpTodayBtn = new PushButton( this, WB_NOPOINTERFOCUS );
2256 OUString aTodayText(SVT_RESSTR(STR_SVT_CALENDAR_TODAY));
2257 mpTodayBtn->SetText( aTodayText );
2258 Size aSize;
2259 aSize.Width() = mpTodayBtn->GetCtrlTextWidth( mpTodayBtn->GetText() );
2260 aSize.Height() = mpTodayBtn->GetTextHeight();
2261 aSize.Width() += CALFIELD_EXTRA_BUTTON_WIDTH;
2262 aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
2263 mpTodayBtn->SetSizePixel( aSize );
2264 mpTodayBtn->Show();
2267 else
2269 if ( mpTodayBtn )
2271 delete mpTodayBtn;
2272 mpTodayBtn = NULL;
2276 return mpTodayBtn;
2279 // -----------------------------------------------------------------------
2281 PushButton* ImplCFieldFloatWin::EnableNoneBtn( sal_Bool bEnable )
2283 if ( bEnable )
2285 if ( !mpNoneBtn )
2287 mpNoneBtn = new PushButton( this, WB_NOPOINTERFOCUS );
2288 OUString aNoneText(SVT_RESSTR(STR_SVT_CALENDAR_NONE));
2289 mpNoneBtn->SetText( aNoneText );
2290 Size aSize;
2291 aSize.Width() = mpNoneBtn->GetCtrlTextWidth( mpNoneBtn->GetText() );
2292 aSize.Height() = mpNoneBtn->GetTextHeight();
2293 aSize.Width() += CALFIELD_EXTRA_BUTTON_WIDTH;
2294 aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
2295 mpNoneBtn->SetSizePixel( aSize );
2296 mpNoneBtn->Show();
2299 else
2301 if ( mpNoneBtn )
2303 delete mpNoneBtn;
2304 mpNoneBtn = NULL;
2308 return mpNoneBtn;
2311 // -----------------------------------------------------------------------
2313 void ImplCFieldFloatWin::ArrangeButtons()
2315 long nBtnHeight = 0;
2316 long nBtnWidth = 0;
2317 Size aOutSize = GetOutputSizePixel();
2318 if ( mpTodayBtn && mpNoneBtn )
2320 Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
2321 Size aNoneBtnSize = mpNoneBtn->GetSizePixel();
2322 if ( aTodayBtnSize.Width() < aNoneBtnSize.Width() )
2323 aTodayBtnSize.Width() = aNoneBtnSize.Width();
2324 else
2325 aNoneBtnSize.Width() = aTodayBtnSize.Width();
2326 if ( aTodayBtnSize.Height() < aNoneBtnSize.Height() )
2327 aTodayBtnSize.Height() = aNoneBtnSize.Height();
2328 else
2329 aNoneBtnSize.Height() = aTodayBtnSize.Height();
2331 nBtnWidth = aTodayBtnSize.Width() + aNoneBtnSize.Width() + CALFIELD_SEP_X;
2332 nBtnHeight = aTodayBtnSize.Height();
2333 long nX = (aOutSize.Width()-nBtnWidth)/2;
2334 long nY = aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP;
2335 mpTodayBtn->SetPosSizePixel( Point( nX, nY ), aTodayBtnSize );
2336 nX += aTodayBtnSize.Width() + CALFIELD_SEP_X;
2337 mpNoneBtn->SetPosSizePixel( Point( nX, nY ), aNoneBtnSize );
2339 else if ( mpTodayBtn )
2341 Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
2342 nBtnWidth = aTodayBtnSize.Width();
2343 nBtnHeight = aTodayBtnSize.Height();
2344 mpTodayBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
2346 else if ( mpNoneBtn )
2348 Size aNoneBtnSize = mpNoneBtn->GetSizePixel();
2349 nBtnWidth = aNoneBtnSize.Width();
2350 nBtnHeight = aNoneBtnSize.Height();
2351 mpNoneBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
2354 if ( nBtnHeight )
2356 if ( !mpFixedLine )
2358 mpFixedLine = new FixedLine( this );
2359 mpFixedLine->Show();
2361 long nLineWidth = aOutSize.Width()-(CALFIELD_BORDERLINE_X*2);
2362 mpFixedLine->setPosSizePixel( (aOutSize.Width()-nLineWidth)/2, aOutSize.Height()+((CALFIELD_BORDER_YTOP-2)/2),
2363 nLineWidth, 2, WINDOW_POSSIZE_POSSIZE );
2364 aOutSize.Height() += nBtnHeight + (CALFIELD_BORDER_Y*2) + CALFIELD_BORDER_YTOP;
2365 SetOutputSizePixel( aOutSize );
2367 else
2369 if ( mpFixedLine )
2371 delete mpFixedLine;
2372 mpFixedLine = NULL;
2377 // -----------------------------------------------------------------------
2379 long ImplCFieldFloatWin::Notify( NotifyEvent& rNEvt )
2381 if ( rNEvt.GetType() == EVENT_KEYINPUT )
2383 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
2384 if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
2385 mpCalendar->Select();
2388 return FloatingWindow::Notify( rNEvt );
2391 // =======================================================================
2393 CalendarField::CalendarField( Window* pParent, WinBits nWinStyle ) :
2394 DateField( pParent, nWinStyle ),
2395 maDefaultDate( 0, 0, 0 )
2397 mpFloatWin = NULL;
2398 mpCalendar = NULL;
2399 mnCalendarStyle = 0;
2400 mbToday = sal_False;
2401 mbNone = sal_False;
2404 // -----------------------------------------------------------------------
2406 CalendarField::~CalendarField()
2408 if ( mpFloatWin )
2410 delete mpCalendar;
2411 delete mpFloatWin;
2415 // -----------------------------------------------------------------------
2417 IMPL_LINK( CalendarField, ImplSelectHdl, Calendar*, pCalendar )
2419 if ( !pCalendar->IsTravelSelect() )
2421 mpFloatWin->EndPopupMode();
2422 EndDropDown();
2423 GrabFocus();
2424 Date aNewDate = mpCalendar->GetFirstSelectedDate();
2425 if ( IsEmptyDate() || ( aNewDate != GetDate() ) )
2427 SetDate( aNewDate );
2428 SetModifyFlag();
2429 Modify();
2431 Select();
2433 return 0;
2436 // -----------------------------------------------------------------------
2438 IMPL_LINK( CalendarField, ImplClickHdl, PushButton*, pBtn )
2440 mpFloatWin->EndPopupMode();
2441 EndDropDown();
2442 GrabFocus();
2444 if ( pBtn == mpTodayBtn )
2446 Date aToday( Date::SYSTEM );
2447 if ( (aToday != GetDate()) || IsEmptyDate() )
2449 SetDate( aToday );
2450 SetModifyFlag();
2451 Modify();
2454 else if ( pBtn == mpNoneBtn )
2456 if ( !IsEmptyDate() )
2458 SetEmptyDate();
2459 SetModifyFlag();
2460 Modify();
2463 Select();
2465 return 0;
2468 // -----------------------------------------------------------------------
2470 IMPL_LINK_NOARG(CalendarField, ImplPopupModeEndHdl)
2472 EndDropDown();
2473 GrabFocus();
2474 mpCalendar->EndSelection();
2475 return 0;
2478 // -----------------------------------------------------------------------
2480 void CalendarField::Select()
2482 maSelectHdl.Call( this );
2485 // -----------------------------------------------------------------------
2487 sal_Bool CalendarField::ShowDropDown( sal_Bool bShow )
2489 if ( bShow )
2491 Calendar* pCalendar = GetCalendar();
2493 Date aDate = GetDate();
2494 if ( IsEmptyDate() || !aDate.IsValidAndGregorian() )
2496 if ( maDefaultDate.IsValidAndGregorian() )
2497 aDate = maDefaultDate;
2498 else
2499 aDate = Date( Date::SYSTEM );
2501 if ( pCalendar->GetStyle() & (WB_RANGESELECT | WB_MULTISELECT) )
2503 pCalendar->SetNoSelection();
2504 pCalendar->SelectDate( aDate );
2506 pCalendar->SetCurDate( aDate );
2507 Point aPos( GetParent()->OutputToScreenPixel( GetPosPixel() ) );
2508 Rectangle aRect( aPos, GetSizePixel() );
2509 aRect.Bottom() -= 1;
2510 mpCalendar->SetOutputSizePixel( mpCalendar->CalcWindowSizePixel() );
2511 mpFloatWin->SetOutputSizePixel( mpCalendar->GetSizePixel() );
2512 mpFloatWin->SetCalendar( mpCalendar );
2513 mpTodayBtn = mpFloatWin->EnableTodayBtn( mbToday );
2514 mpNoneBtn = mpFloatWin->EnableNoneBtn( mbNone );
2515 if ( mpTodayBtn )
2516 mpTodayBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
2517 if ( mpNoneBtn )
2518 mpNoneBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
2519 mpFloatWin->ArrangeButtons();
2520 mpCalendar->EnableCallEverySelect();
2521 mpCalendar->StartSelection();
2522 mpCalendar->GrabFocus();
2523 mpCalendar->Show();
2524 mpFloatWin->StartPopupMode( aRect, FLOATWIN_POPUPMODE_NOFOCUSCLOSE|FLOATWIN_POPUPMODE_DOWN );
2526 else
2528 mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
2529 mpCalendar->EndSelection();
2530 EndDropDown();
2532 return sal_True;
2535 // -----------------------------------------------------------------------
2537 Calendar* CalendarField::CreateCalendar( Window* pParent )
2539 return new Calendar( pParent, mnCalendarStyle | WB_TABSTOP );
2542 // -----------------------------------------------------------------------
2544 Calendar* CalendarField::GetCalendar()
2546 if ( !mpFloatWin )
2548 mpFloatWin = new ImplCFieldFloatWin( this );
2549 mpFloatWin->SetPopupModeEndHdl( LINK( this, CalendarField, ImplPopupModeEndHdl ) );
2550 mpCalendar = CreateCalendar( mpFloatWin );
2551 mpCalendar->SetPosPixel( Point() );
2552 mpCalendar->SetSelectHdl( LINK( this, CalendarField, ImplSelectHdl ) );
2555 return mpCalendar;
2558 // -----------------------------------------------------------------------
2560 void CalendarField::StateChanged( StateChangedType nStateChange )
2562 DateField::StateChanged( nStateChange );
2564 if ( ( nStateChange == STATE_CHANGE_STYLE ) && GetSubEdit() )
2566 WinBits nAllAlignmentBits = ( WB_LEFT | WB_CENTER | WB_RIGHT | WB_TOP | WB_VCENTER | WB_BOTTOM );
2567 WinBits nMyAlignment = GetStyle() & nAllAlignmentBits;
2568 GetSubEdit()->SetStyle( ( GetSubEdit()->GetStyle() & ~nAllAlignmentBits ) | nMyAlignment );
2572 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */