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