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