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