summaryrefslogtreecommitdiff
path: root/svtools/source/control/calendar.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/control/calendar.cxx')
-rw-r--r--svtools/source/control/calendar.cxx3037
1 files changed, 3037 insertions, 0 deletions
diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx
new file mode 100644
index 000000000000..4a0bc4112264
--- /dev/null
+++ b/svtools/source/control/calendar.cxx
@@ -0,0 +1,3037 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svtools.hxx"
+
+#include <vcl/svapp.hxx>
+#include <tools/table.hxx>
+#include <vcl/help.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/button.hxx>
+#include <vcl/fixed.hxx>
+#include <unotools/calendarwrapper.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <com/sun/star/i18n/Weekdays.hpp>
+#include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
+#include <com/sun/star/i18n/CalendarFieldIndex.hpp>
+
+#define _SV_CALENDAR_CXX
+#include <svtools/svtools.hrc>
+#include <svtools/svtdata.hxx>
+#include <svtools/calendar.hxx>
+
+// =======================================================================
+
+#define DAY_OFFX 4
+#define DAY_OFFY 2
+#define MONTH_BORDERX 4
+#define MONTH_OFFY 3
+#define WEEKNUMBER_OFFX 4
+#define WEEKDAY_OFFY 3
+#define TITLE_OFFY 3
+#define TITLE_BORDERY 2
+#define SPIN_OFFX 4
+#define SPIN_OFFY TITLE_BORDERY
+
+#define WEEKNUMBER_HEIGHT 85
+
+#define CALENDAR_HITTEST_DAY ((sal_uInt16)0x0001)
+#define CALENDAR_HITTEST_WEEK ((sal_uInt16)0x0002)
+#define CALENDAR_HITTEST_MONTHTITLE ((sal_uInt16)0x0004)
+#define CALENDAR_HITTEST_PREV ((sal_uInt16)0x0008)
+#define CALENDAR_HITTEST_NEXT ((sal_uInt16)0x0010)
+#define CALENDAR_HITTEST_OUTSIDE ((sal_uInt16)0x1000)
+
+#define MENU_YEAR_COUNT 3
+
+#define TABLE_DATE_SELECTED ((void*)0x00000001)
+
+using namespace ::com::sun::star;
+
+// =======================================================================
+
+struct ImplDateInfo
+{
+ XubString maText;
+ Color* mpTextColor;
+ Color* mpFrameColor;
+ sal_uInt16 mnFlags;
+
+ ImplDateInfo( const XubString& rText ) :
+ maText( rText )
+ { mpTextColor = mpFrameColor = NULL; mnFlags = 0; }
+ ~ImplDateInfo() { delete mpTextColor; delete mpFrameColor; }
+};
+
+DECLARE_TABLE( ImplDateTable, ImplDateInfo* )
+
+// =======================================================================
+
+static void ImplCalendarSelectDate( Table* pTable, const Date& rDate, sal_Bool bSelect )
+{
+ if ( bSelect )
+ pTable->Insert( rDate.GetDate(), TABLE_DATE_SELECTED );
+ else
+ pTable->Remove( rDate.GetDate() );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalendarSelectDateRange( Table* pTable,
+ const Date& rStartDate,
+ const Date& rEndDate,
+ sal_Bool bSelect )
+{
+ Date aStartDate = rStartDate;
+ Date aEndDate = rEndDate;
+ if ( aStartDate > aEndDate )
+ {
+ Date aTempDate = aStartDate;
+ aStartDate = aEndDate;
+ aEndDate = aTempDate;
+ }
+
+ if ( bSelect )
+ {
+ while ( aStartDate <= aEndDate )
+ {
+ pTable->Insert( aStartDate.GetDate(), TABLE_DATE_SELECTED );
+ aStartDate++;
+ }
+ }
+ else
+ {
+ void* p = pTable->First();
+ while ( p )
+ {
+ Date aDate( pTable->GetCurKey() );
+ if ( aDate > aEndDate )
+ break;
+
+ if ( aDate >= aStartDate )
+ pTable->Remove( aDate.GetDate() );
+ else
+ p = pTable->Next();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCalendarUnSelectDateRange( Table* pTable,
+ Table* pOldTable,
+ const Date& rStartDate,
+ const Date& rEndDate )
+{
+ Date aStartDate = rStartDate;
+ Date aEndDate = rEndDate;
+ if ( aStartDate > aEndDate )
+ {
+ Date aTempDate = aStartDate;
+ aStartDate = aEndDate;
+ aEndDate = aTempDate;
+ }
+
+ void* p = pTable->First();
+ while ( p )
+ {
+ Date aDate( pTable->GetCurKey() );
+ if ( aDate > aEndDate )
+ break;
+
+ if ( aDate >= aStartDate )
+ pTable->Remove( aDate.GetDate() );
+ else
+ p = pTable->Next();
+ }
+
+ p = pOldTable->First();
+ while ( p )
+ {
+ Date aDate( pOldTable->GetCurKey() );
+ if ( aDate > aEndDate )
+ break;
+ if ( aDate >= aStartDate )
+ pTable->Insert( aDate.GetDate(), TABLE_DATE_SELECTED );
+
+ p = pOldTable->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+inline void ImplCalendarClearSelectDate( Table* pTable )
+{
+ pTable->Clear();
+}
+
+// =======================================================================
+
+void Calendar::ImplInit( WinBits nWinStyle )
+{
+ mpDateTable = NULL;
+ mpSelectTable = new Table;
+ mpOldSelectTable = NULL;
+ mpRestoreSelectTable = NULL;
+ mpStandardColor = NULL;
+ mpSaturdayColor = NULL;
+ mpSundayColor = NULL;
+ mnDayCount = 0;
+ mnWinStyle = nWinStyle;
+ mnFirstYear = 0;
+ mnLastYear = 0;
+ mnRequestYear = 0;
+ mbCalc = sal_True;
+ mbFormat = sal_True;
+ mbDrag = sal_False;
+ mbSelection = sal_False;
+ mbMultiSelection = sal_False;
+ mbWeekSel = sal_False;
+ mbUnSel = sal_False;
+ mbMenuDown = sal_False;
+ mbSpinDown = sal_False;
+ mbPrevIn = sal_False;
+ mbNextIn = sal_False;
+ mbDirect = sal_False;
+ mbInSelChange = sal_False;
+ mbTravelSelect = sal_False;
+ mbScrollDateRange = sal_False;
+ mbSelLeft = sal_False;
+ mbAllSel = sal_False;
+ mbDropPos = sal_False;
+
+ ::rtl::OUString aGregorian( RTL_CONSTASCII_USTRINGPARAM( "gregorian"));
+ maCalendarWrapper.loadCalendar( aGregorian,
+ Application::GetAppLocaleDataWrapper().getLocale());
+ if (maCalendarWrapper.getUniqueID() != aGregorian)
+ {
+#ifdef DBG_UTIL
+ ByteString aMsg( "Calendar::ImplInit: No ``gregorian'' calendar available for locale ``");
+ lang::Locale aLoc( Application::GetAppLocaleDataWrapper().getLocale());
+ aMsg += ByteString( String( aLoc.Language), RTL_TEXTENCODING_UTF8);
+ aMsg += '-';
+ aMsg += ByteString( String( aLoc.Country), RTL_TEXTENCODING_UTF8);
+ aMsg += "'' and other calendars aren't supported. Using en-US fallback.";
+ DBG_ERRORFILE( aMsg.GetBuffer());
+#endif
+ /* If we ever wanted to support other calendars than Gregorian a lot of
+ * rewrite would be necessary to internally replace use of class Date
+ * with proper class CalendarWrapper methods, get rid of fixed 12
+ * months, fixed 7 days, ... */
+ maCalendarWrapper.loadCalendar( aGregorian, lang::Locale(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "en")),
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "US")),
+ ::rtl::OUString()));
+ }
+
+ SetFirstDate( maCurDate );
+ ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
+
+ // Sonstige Strings erzeugen
+ maDayText = XubString( SvtResId( STR_SVT_CALENDAR_DAY ) );
+ maWeekText = XubString( SvtResId( STR_SVT_CALENDAR_WEEK ) );
+
+ // Tagestexte anlegen
+ for ( sal_uInt16 i = 0; i < 31; i++ )
+ mpDayText[i] = new UniString( UniString::CreateFromInt32( i+1 ) );
+
+ maDragScrollTimer.SetTimeoutHdl( STATIC_LINK( this, Calendar, ScrollHdl ) );
+ maDragScrollTimer.SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
+ mnDragScrollHitTest = 0;
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplInitSettings()
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ maSelColor = rStyleSettings.GetHighlightTextColor();
+ SetPointFont( rStyleSettings.GetToolFont() );
+ SetTextColor( rStyleSettings.GetFieldTextColor() );
+ SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
+}
+
+// -----------------------------------------------------------------------
+
+Calendar::Calendar( Window* pParent, WinBits nWinStyle ) :
+ Control( pParent, nWinStyle & (WB_TABSTOP | WB_GROUP | WB_BORDER | WB_3DLOOK | WB_RANGESELECT | WB_MULTISELECT) ),
+ maCalendarWrapper( Application::GetAppLocaleDataWrapper().getServiceFactory() ),
+ maOldFormatFirstDate( 0, 0, 1900 ),
+ maOldFormatLastDate( 0, 0, 1900 ),
+ maFirstDate( 0, 0, 1900 ),
+ maOldFirstDate( 0, 0, 1900 ),
+ maOldCurDate( 0, 0, 1900 ),
+ maAnchorDate( maCurDate ),
+ maDropDate( 0, 0, 1900 )
+{
+ ImplInit( nWinStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Calendar::Calendar( Window* pParent, const ResId& rResId ) :
+ Control( pParent, rResId ),
+ maCalendarWrapper( Application::GetAppLocaleDataWrapper().getServiceFactory() ),
+ maOldFormatFirstDate( 0, 0, 1900 ),
+ maOldFormatLastDate( 0, 0, 1900 ),
+ maFirstDate( 0, 0, 1900 ),
+ maOldFirstDate( 0, 0, 1900 ),
+ maOldCurDate( 0, 0, 1900 ),
+ maAnchorDate( maCurDate ),
+ maDropDate( 0, 0, 1900 )
+{
+ ImplInit( rResId.GetWinBits() );
+}
+
+// -----------------------------------------------------------------------
+
+Calendar::~Calendar()
+{
+ delete mpStandardColor;
+ delete mpSaturdayColor;
+ delete mpSundayColor;
+
+ if ( mpDateTable )
+ {
+ ImplDateInfo* pDateInfo = mpDateTable->First();
+ while ( pDateInfo )
+ {
+ delete pDateInfo;
+ pDateInfo = mpDateTable->Next();
+ }
+
+ delete mpDateTable;
+ }
+
+ delete mpSelectTable;
+ if ( mpOldSelectTable )
+ delete mpOldSelectTable;
+ if ( mpRestoreSelectTable )
+ delete mpRestoreSelectTable;
+
+ for ( sal_uInt16 i = 0; i < 31; i++ )
+ delete mpDayText[i];
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetMinimumNumberOfDaysInWeek( sal_Int16 nDays )
+{
+ ImplUpdate( sal_True );
+ maCalendarWrapper.setMinimumNumberOfDaysForFirstWeek( nDays);
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetWeekStart( sal_Int16 nDay )
+{
+ ImplUpdate( sal_True );
+ switch (nDay)
+ {
+ case i18n::Weekdays::SUNDAY :
+ case i18n::Weekdays::MONDAY :
+ case i18n::Weekdays::TUESDAY :
+ case i18n::Weekdays::WEDNESDAY :
+ case i18n::Weekdays::THURSDAY :
+ case i18n::Weekdays::FRIDAY :
+ case i18n::Weekdays::SATURDAY :
+ ; // nothing
+ default:
+ DBG_ERRORFILE("Calendar::SetWeekStart: unknown value for setFirstDayOfWeek() of a Gregorian calendar");
+ nDay = i18n::Weekdays::SUNDAY;
+ }
+ maCalendarWrapper.setFirstDayOfWeek( nDay);
+}
+
+// -----------------------------------------------------------------------
+
+DayOfWeek Calendar::ImplGetWeekStart() const
+{
+ // Map i18n::Weekdays to Date DayOfWeek
+ DayOfWeek eDay;
+ sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
+ switch (nDay)
+ {
+ case i18n::Weekdays::SUNDAY :
+ eDay = SUNDAY;
+ break;
+ case i18n::Weekdays::MONDAY :
+ eDay = MONDAY;
+ break;
+ case i18n::Weekdays::TUESDAY :
+ eDay = TUESDAY;
+ break;
+ case i18n::Weekdays::WEDNESDAY :
+ eDay = WEDNESDAY;
+ break;
+ case i18n::Weekdays::THURSDAY :
+ eDay = THURSDAY;
+ break;
+ case i18n::Weekdays::FRIDAY :
+ eDay = FRIDAY;
+ break;
+ case i18n::Weekdays::SATURDAY :
+ eDay = SATURDAY;
+ break;
+ default:
+ DBG_ERRORFILE("Calendar::ImplGetWeekStart: broken i18n Gregorian calendar (getFirstDayOfWeek())");
+ eDay = SUNDAY;
+ }
+ return eDay;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplGetWeekFont( Font& rFont ) const
+{
+ // Wochennummer geben wir in WEEKNUMBER_HEIGHT%-Fonthoehe aus
+ Size aFontSize = rFont.GetSize();
+ aFontSize.Height() *= WEEKNUMBER_HEIGHT;
+ aFontSize.Height() /= 100;
+ rFont.SetSize( aFontSize );
+ rFont.SetWeight( WEIGHT_NORMAL );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplFormat()
+{
+ if ( !mbFormat )
+ return;
+
+ if ( mbCalc )
+ {
+ Size aOutSize = GetOutputSizePixel();
+
+ if ( (aOutSize.Width() <= 1) || (aOutSize.Height() <= 1) )
+ return;
+
+ XubString a99Text( XubString( RTL_CONSTASCII_USTRINGPARAM( "99" ) ) );
+
+ Font aOldFont = GetFont();
+
+ // Wochenanzeige beruecksichtigen
+ if ( mnWinStyle & WB_WEEKNUMBER )
+ {
+ Font aTempFont = aOldFont;
+ ImplGetWeekFont( aTempFont );
+ SetFont( aTempFont );
+ mnWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
+ SetFont( aOldFont );
+ }
+ else
+ mnWeekWidth = 0;
+
+ if ( mnWinStyle & WB_BOLDTEXT )
+ {
+ Font aFont = aOldFont;
+ if ( aFont.GetWeight() < WEIGHT_BOLD )
+ aFont.SetWeight( WEIGHT_BOLD );
+ else
+ aFont.SetWeight( WEIGHT_NORMAL );
+ SetFont( aFont );
+ }
+
+ long n99TextWidth = GetTextWidth( a99Text );
+ long nTextHeight = GetTextHeight();
+
+ // Breiten und X-Positionen berechnen
+ mnDayWidth = n99TextWidth+DAY_OFFX;
+ mnMonthWidth = mnDayWidth*7;
+ mnMonthWidth += mnWeekWidth;
+ mnMonthWidth += MONTH_BORDERX*2;
+ mnMonthPerLine = aOutSize.Width() / mnMonthWidth;
+ if ( !mnMonthPerLine )
+ mnMonthPerLine = 1;
+ long nOver = ((aOutSize.Width()-(mnMonthPerLine*mnMonthWidth)) / mnMonthPerLine);
+ mnMonthWidth += nOver;
+ mnDaysOffX = MONTH_BORDERX;
+ mnDaysOffX += nOver/2;
+ mnDaysOffX += mnWeekWidth;
+
+ // Hoehen und Y-Positionen berechnen
+ mnDayHeight = nTextHeight + DAY_OFFY;
+ mnWeekDayOffY = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
+ mnDaysOffY = mnWeekDayOffY + nTextHeight + WEEKDAY_OFFY;
+ mnMonthHeight = (mnDayHeight*6) + mnDaysOffY;
+ mnMonthHeight += MONTH_OFFY;
+ mnLines = aOutSize.Height() / mnMonthHeight;
+ if ( !mnLines )
+ mnLines = 1;
+ mnMonthHeight += (aOutSize.Height()-(mnLines*mnMonthHeight)) / mnLines;
+
+ // Spinfelder berechnen
+ long nSpinSize = nTextHeight+TITLE_BORDERY-SPIN_OFFY;
+ maPrevRect.Left() = SPIN_OFFX;
+ maPrevRect.Top() = SPIN_OFFY;
+ maPrevRect.Right() = maPrevRect.Left()+nSpinSize;
+ maPrevRect.Bottom() = maPrevRect.Top()+nSpinSize;
+ maNextRect.Left() = aOutSize.Width()-SPIN_OFFX-nSpinSize-1;
+ maNextRect.Top() = SPIN_OFFY;
+ maNextRect.Right() = maNextRect.Left()+nSpinSize;
+ maNextRect.Bottom() = maNextRect.Top()+nSpinSize;
+
+ if ( mnWinStyle & WB_BOLDTEXT )
+ SetFont( aOldFont );
+
+ // Calculate DayOfWeekText (gets displayed in a narrow font)
+ maDayOfWeekText.Erase();
+ long nStartOffX = 0;
+ sal_Int16 nDay = maCalendarWrapper.getFirstDayOfWeek();
+ for ( sal_Int16 nDayOfWeek = 0; nDayOfWeek < 7; nDayOfWeek++ )
+ {
+ // Use first character of full name, since the abbreviated name may
+ // be roman digits or similar in some locales. Proper
+ // implementation would need narrow one letter month names defined
+ // in locale data.
+ String aDayOfWeek( maCalendarWrapper.getDisplayName(
+ i18n::CalendarDisplayIndex::DAY, nDay, 1).GetChar(0));
+ long nOffX = (mnDayWidth-GetTextWidth( aDayOfWeek ))/2;
+ if ( mnWinStyle & WB_BOLDTEXT )
+ nOffX++;
+ if ( !nDayOfWeek )
+ nStartOffX = nOffX;
+ else
+ nOffX -= nStartOffX;
+ nOffX += nDayOfWeek * mnDayWidth;
+ mnDayOfWeekAry[nDayOfWeek] = nOffX;
+ maDayOfWeekText += aDayOfWeek;
+ nDay++;
+ nDay %= 7;
+ }
+
+ mbCalc = sal_False;
+ }
+
+ // Anzahl Tage berechnen
+
+ DayOfWeek eStartDay = ImplGetWeekStart();
+
+ sal_uInt16 nWeekDay;
+ Date aTempDate = GetFirstMonth();
+ maFirstDate = aTempDate;
+ nWeekDay = (sal_uInt16)aTempDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
+ maFirstDate -= (sal_uLong)nWeekDay;
+ mnDayCount = nWeekDay;
+ sal_uInt16 nDaysInMonth;
+ sal_uInt16 nMonthCount = (sal_uInt16)(mnMonthPerLine*mnLines);
+ for ( sal_uInt16 i = 0; i < nMonthCount; i++ )
+ {
+ nDaysInMonth = aTempDate.GetDaysInMonth();
+ mnDayCount += nDaysInMonth;
+ aTempDate += nDaysInMonth;
+ }
+ Date aTempDate2 = aTempDate;
+ aTempDate2--;
+ nDaysInMonth = aTempDate2.GetDaysInMonth();
+ aTempDate2 -= nDaysInMonth-1;
+ nWeekDay = (sal_uInt16)aTempDate2.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
+ mnDayCount += 42-nDaysInMonth-nWeekDay;
+
+ // Farben festlegen
+ maOtherColor = Color( COL_LIGHTGRAY );
+ if ( maOtherColor.IsRGBEqual( GetBackground().GetColor() ) )
+ maOtherColor.SetColor( COL_GRAY );
+
+ Date aLastDate = GetLastDate();
+ if ( (maOldFormatLastDate != aLastDate) ||
+ (maOldFormatFirstDate != maFirstDate) )
+ {
+ maOldFormatFirstDate = maFirstDate;
+ maOldFormatLastDate = aLastDate;
+ DateRangeChanged();
+ }
+
+ // DateInfo besorgen
+ sal_uInt16 nNewFirstYear = maFirstDate.GetYear();
+ sal_uInt16 nNewLastYear = GetLastDate().GetYear();
+ if ( mnFirstYear )
+ {
+ if ( nNewFirstYear < mnFirstYear )
+ {
+ for ( mnRequestYear = nNewFirstYear; mnRequestYear < mnFirstYear; mnRequestYear++ )
+ RequestDateInfo();
+ mnFirstYear = nNewFirstYear;
+ }
+ if ( nNewLastYear > mnLastYear )
+ {
+ for ( mnRequestYear = mnLastYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
+ RequestDateInfo();
+ mnLastYear = nNewLastYear;
+ }
+ }
+ else
+ {
+ for ( mnRequestYear = nNewFirstYear; mnRequestYear < nNewLastYear; mnRequestYear++ )
+ RequestDateInfo();
+ mnFirstYear = nNewFirstYear;
+ mnLastYear = nNewLastYear;
+ }
+ mnRequestYear = 0;
+
+ mbFormat = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 Calendar::ImplHitTest( const Point& rPos, Date& rDate ) const
+{
+ if ( mbFormat )
+ return 0;
+
+ if ( maPrevRect.IsInside( rPos ) )
+ return CALENDAR_HITTEST_PREV;
+ else if ( maNextRect.IsInside( rPos ) )
+ return CALENDAR_HITTEST_NEXT;
+
+ long nX;
+ long nY;
+ long nOffX;
+ long nYMonth;
+ sal_uInt16 nDay;
+ DayOfWeek eStartDay = ImplGetWeekStart();
+
+ rDate = GetFirstMonth();
+ nY = 0;
+ for ( long i = 0; i < mnLines; i++ )
+ {
+ if ( rPos.Y() < nY )
+ return 0;
+
+ nX = 0;
+ nYMonth = nY+mnMonthHeight;
+ for ( long j = 0; j < mnMonthPerLine; j++ )
+ {
+ if ( (rPos.X() < nX) && (rPos.Y() < nYMonth) )
+ return 0;
+
+ sal_uInt16 nDaysInMonth = rDate.GetDaysInMonth();
+
+ // Entsprechender Monat gefunden
+ if ( (rPos.X() > nX) && (rPos.Y() < nYMonth) &&
+ (rPos.X() < nX+mnMonthWidth) )
+ {
+ if ( rPos.Y() < (nY+(TITLE_BORDERY*2)+mnDayHeight))
+ return CALENDAR_HITTEST_MONTHTITLE;
+ else
+ {
+ long nDayX = nX+mnDaysOffX;
+ long nDayY = nY+mnDaysOffY;
+ if ( rPos.Y() < nDayY )
+ return 0;
+ sal_uInt16 nDayIndex = (sal_uInt16)rDate.GetDayOfWeek();
+ nDayIndex = (nDayIndex+(7-(sal_uInt16)eStartDay)) % 7;
+ if ( (i == 0) && (j == 0) )
+ {
+ Date aTempDate = rDate;
+ aTempDate -= nDayIndex;
+ for ( nDay = 0; nDay < nDayIndex; nDay++ )
+ {
+ nOffX = nDayX + (nDay*mnDayWidth);
+ if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
+ (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
+ {
+ rDate = aTempDate;
+ rDate += nDay;
+ return CALENDAR_HITTEST_DAY;
+ }
+ }
+ }
+ for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
+ {
+ if ( rPos.Y() < nDayY )
+ {
+ rDate += nDayIndex;
+ return 0;
+ }
+ nOffX = nDayX + (nDayIndex*mnDayWidth);
+ if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
+ (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
+ {
+ rDate += nDay-1;
+ return CALENDAR_HITTEST_DAY;
+ }
+ if ( nDayIndex == 6 )
+ {
+ nDayIndex = 0;
+ nDayY += mnDayHeight;
+ }
+ else
+ nDayIndex++;
+ }
+ if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
+ {
+ sal_uInt16 nWeekDay = (sal_uInt16)rDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
+ sal_uInt16 nDayCount = 42-nDaysInMonth-nWeekDay;
+ Date aTempDate = rDate;
+ aTempDate += nDaysInMonth;
+ for ( nDay = 1; nDay <= nDayCount; nDay++ )
+ {
+ if ( rPos.Y() < nDayY )
+ {
+ rDate += nDayIndex;
+ return 0;
+ }
+ nOffX = nDayX + (nDayIndex*mnDayWidth);
+ if ( (rPos.Y() >= nDayY) && (rPos.Y() < nDayY+mnDayHeight) &&
+ (rPos.X() >= nOffX) && (rPos.X() < nOffX+mnDayWidth) )
+ {
+ rDate = aTempDate;
+ rDate += nDay-1;
+ return CALENDAR_HITTEST_DAY;
+ }
+ if ( nDayIndex == 6 )
+ {
+ nDayIndex = 0;
+ nDayY += mnDayHeight;
+ }
+ else
+ nDayIndex++;
+ }
+ }
+ }
+ }
+
+ rDate += nDaysInMonth;
+ nX += mnMonthWidth;
+ }
+
+ nY += mnMonthHeight;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplDrawSpinArrow( OutputDevice* pDev, const Rectangle& rRect,
+ sal_Bool bPrev )
+{
+ long i;
+ long n;
+ long nLines;
+ long nHeight = rRect.GetHeight();
+ long nWidth = rRect.GetWidth();
+ if ( nWidth < nHeight )
+ n = nWidth;
+ else
+ n = nHeight;
+ if ( !(n & 0x01) )
+ n--;
+ nLines = n/2;
+
+ Rectangle aRect( Point( rRect.Left()+(nWidth/2)-(nLines/2),
+ rRect.Top()+(nHeight/2) ),
+ Size( 1, 1 ) );
+ if ( !bPrev )
+ {
+ aRect.Left() += nLines;
+ aRect.Right() += nLines;
+ }
+
+ pDev->DrawRect( aRect );
+ for ( i = 0; i < nLines; i++ )
+ {
+ if ( bPrev )
+ {
+ aRect.Left()++;
+ aRect.Right()++;
+ }
+ else
+ {
+ aRect.Left()--;
+ aRect.Right()--;
+ }
+ aRect.Top()--;
+ aRect.Bottom()++;
+ pDev->DrawRect( aRect );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplDrawSpin( sal_Bool bDrawPrev, sal_Bool bDrawNext )
+{
+ if ( !bDrawPrev && !bDrawNext )
+ return;
+
+ SetLineColor();
+ SetFillColor( GetSettings().GetStyleSettings().GetButtonTextColor() );
+ if ( bDrawPrev )
+ {
+ Rectangle aOutRect = maPrevRect;
+ aOutRect.Left() += 3;
+ aOutRect.Top() += 3;
+ aOutRect.Right() -= 3;
+ aOutRect.Bottom() -= 3;
+ ImplDrawSpinArrow( this, aOutRect, sal_True );
+ }
+ if ( bDrawNext )
+ {
+ Rectangle aOutRect = maNextRect;
+ aOutRect.Left() += 3;
+ aOutRect.Top() += 3;
+ aOutRect.Right() -= 3;
+ aOutRect.Bottom() -= 3;
+ ImplDrawSpinArrow( this, aOutRect, sal_False );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::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 )
+{
+ ImplDateInfo* pDateInfo;
+ Color* pTextColor = NULL;
+ const String& rDay = *(mpDayText[nDay-1]);
+ Rectangle aDateRect( nX, nY, nX+mnDayWidth-1, nY+mnDayHeight-1 );
+
+ sal_Bool bSel = sal_False;
+ sal_Bool bFocus = sal_False;
+ // Aktueller Tag
+ if ( (nDay == maCurDate.GetDay()) &&
+ (nMonth == maCurDate.GetMonth()) &&
+ (nYear == maCurDate.GetYear()) )
+ bFocus = sal_True;
+ if ( mpSelectTable )
+ {
+ if ( mpSelectTable->IsKeyValid( Date( nDay, nMonth, nYear ).GetDate() ) )
+ bSel = sal_True;
+ }
+
+ // Dateinfo ermitteln
+ if ( mpDateTable )
+ {
+ pDateInfo = mpDateTable->Get( Date( nDay, nMonth, nYear ).GetDate() );
+ if ( !pDateInfo )
+ pDateInfo = mpDateTable->Get( Date( nDay, nMonth, 0 ).GetDate() );
+ }
+ else
+ pDateInfo = NULL;
+
+ // Textfarbe ermitteln
+ if ( bSel )
+ pTextColor = &maSelColor;
+ else if ( bOther )
+ pTextColor = &maOtherColor;
+ else
+ {
+ if ( pDateInfo && pDateInfo->mpTextColor )
+ pTextColor = pDateInfo->mpTextColor;
+ else
+ {
+ if ( eDayOfWeek == SATURDAY )
+ pTextColor = mpSaturdayColor;
+ else if ( eDayOfWeek == SUNDAY )
+ pTextColor = mpSundayColor;
+ if ( !pTextColor )
+ pTextColor = mpStandardColor;
+ }
+ }
+
+ if ( bFocus )
+ HideFocus();
+
+ // Font ermitteln
+ Font aOldFont = GetFont();
+ sal_Bool bBoldFont = sal_False;
+ if ( (mnWinStyle & WB_BOLDTEXT) &&
+ pDateInfo && (pDateInfo->mnFlags & DIB_BOLD) )
+ {
+ bBoldFont = sal_True;
+ Font aFont = aOldFont;
+ if ( aFont.GetWeight() < WEIGHT_BOLD )
+ aFont.SetWeight( WEIGHT_BOLD );
+ else
+ aFont.SetWeight( WEIGHT_NORMAL );
+ SetFont( aFont );
+ }
+
+ // Hintergrund ausgeben
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ if ( bSel || bBack )
+ {
+ if ( bSel )
+ {
+ SetLineColor();
+ SetFillColor( rStyleSettings.GetHighlightColor() );
+ DrawRect( aDateRect );
+ }
+ else
+ Erase( aDateRect );
+ }
+
+ // Text ausgeben
+ long nTextX = nX+(mnDayWidth-GetTextWidth( rDay ))-(DAY_OFFX/2);
+ long nTextY = nY+(mnDayHeight-GetTextHeight())/2;
+ if ( pTextColor )
+ {
+ Color aOldColor = GetTextColor();
+ SetTextColor( *pTextColor );
+ DrawText( Point( nTextX, nTextY ), rDay );
+ SetTextColor( aOldColor );
+ }
+ else
+ DrawText( Point( nTextX, nTextY ), rDay );
+
+ // Heute
+ Date aTodayDate( maCurDate );
+ if ( nToday )
+ aTodayDate.SetDate( nToday );
+ else
+ aTodayDate = Date();
+ if ( (nDay == aTodayDate.GetDay()) &&
+ (nMonth == aTodayDate.GetMonth()) &&
+ (nYear == aTodayDate.GetYear()) )
+ {
+ SetLineColor( rStyleSettings.GetWindowTextColor() );
+ SetFillColor();
+ DrawRect( aDateRect );
+ }
+
+ // Evt. DateInfo ausgeben
+ if ( (mnWinStyle & WB_FRAMEINFO) && pDateInfo && pDateInfo->mpFrameColor )
+ {
+ SetLineColor( *(pDateInfo->mpFrameColor) );
+ SetFillColor();
+ Rectangle aFrameRect( aDateRect );
+ aFrameRect.Left()++;
+ aFrameRect.Top()++;
+ long nFrameWidth = aFrameRect.GetWidth();
+ long nFrameHeight = aFrameRect.GetHeight();
+ long nFrameOff;
+ if ( nFrameWidth < nFrameHeight )
+ {
+ nFrameOff = nFrameHeight-nFrameWidth;
+ aFrameRect.Top() += nFrameOff/2;
+ nFrameOff %= 2;
+ aFrameRect.Bottom() -= nFrameOff;
+ }
+ else if ( nFrameWidth > nFrameHeight )
+ {
+ nFrameOff = nFrameWidth-nFrameHeight;
+ aFrameRect.Left() += nFrameOff/2;
+ nFrameOff %= 2;
+ aFrameRect.Right() -= nFrameOff;
+ }
+ DrawEllipse( aFrameRect );
+ }
+
+ // Evt. noch FocusRect
+ if ( bFocus && HasFocus() )
+ ShowFocus( aDateRect );
+
+ if( mbDropPos && maDropDate == Date( nDay, nMonth, nYear ) )
+ ImplInvertDropPos();
+
+ if ( bBoldFont )
+ SetFont( aOldFont );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplDraw( sal_Bool bPaint )
+{
+ ImplFormat();
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Size aOutSize = GetOutputSizePixel();
+ long i;
+ long j;
+ long nX;
+ long nY;
+ long nDeltaX;
+ long nDeltaY;
+ long nDayX;
+ long nDayY;
+ sal_uLong nToday = Date().GetDate();
+ sal_uInt16 nDay;
+ sal_uInt16 nMonth;
+ sal_uInt16 nYear;
+ Date aDate = GetFirstMonth();
+ DayOfWeek eStartDay = ImplGetWeekStart();
+
+ HideFocus();
+
+ nY = 0;
+ for ( i = 0; i < mnLines; i++ )
+ {
+ // Titleleiste ausgeben
+ SetLineColor();
+ SetFillColor( rStyleSettings.GetFaceColor() );
+ Rectangle aTitleRect( 0, nY, aOutSize.Width()-1, nY+mnDayHeight-DAY_OFFY+TITLE_BORDERY*2 );
+ if ( !bPaint )
+ {
+ Rectangle aTempRect( 1, aTitleRect.Top()+TITLE_BORDERY,
+ aOutSize.Width()-2,
+ aTitleRect.Bottom()-TITLE_BORDERY );
+ if ( !i )
+ {
+ aTempRect.Left() = maPrevRect.Right()+1;
+ aTempRect.Right() = maNextRect.Left()-1;
+ }
+ DrawRect( aTempRect );
+ }
+ else
+ {
+ DrawRect( aTitleRect );
+ Point aTopLeft1( aTitleRect.Left(), aTitleRect.Top() );
+ Point aTopLeft2( aTitleRect.Left(), aTitleRect.Top()+1 );
+ Point aBottomRight1( aTitleRect.Right(), aTitleRect.Bottom() );
+ Point aBottomRight2( aTitleRect.Right(), aTitleRect.Bottom()-1 );
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ DrawLine( aTopLeft1, Point( aBottomRight1.X(), aTopLeft1.Y() ) );
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( aTopLeft2, Point( aBottomRight2.X(), aTopLeft2.Y() ) );
+ DrawLine( aTopLeft2, Point( aTopLeft2.X(), aBottomRight2.Y() ) );
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( aTopLeft2.X(), aBottomRight2.Y() ), aBottomRight2 );
+ DrawLine( Point( aBottomRight2.X(), aTopLeft2.Y() ), aBottomRight2 );
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ DrawLine( Point( aTopLeft1.X(), aBottomRight1.Y() ), aBottomRight1 );
+ }
+ Point aSepPos1( 0, aTitleRect.Top()+TITLE_BORDERY );
+ Point aSepPos2( 0, aTitleRect.Bottom()-TITLE_BORDERY );
+ for ( j = 0; j < mnMonthPerLine-1; j++ )
+ {
+ aSepPos1.X() += mnMonthWidth-1;
+ aSepPos2.X() = aSepPos1.X();
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( aSepPos1, aSepPos2 );
+ aSepPos1.X()++;
+ aSepPos2.X() = aSepPos1.X();
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( aSepPos1, aSepPos2 );
+ }
+
+ nX = 0;
+ for ( j = 0; j < mnMonthPerLine; j++ )
+ {
+ nMonth = aDate.GetMonth();
+ nYear = aDate.GetYear();
+
+ // Monat in der Titleleiste ausgeben
+ nDeltaX = nX;
+ nDeltaY = nY+TITLE_BORDERY;
+ String aMonthText( maCalendarWrapper.getDisplayName(
+ i18n::CalendarDisplayIndex::MONTH, nMonth-1, 1));
+ aMonthText += ' ';
+ aMonthText += String::CreateFromInt64( nYear );
+ long nMonthTextWidth = GetTextWidth( aMonthText );
+ long nMonthOffX1 = 0;
+ long nMonthOffX2 = 0;
+ if ( i == 0 )
+ {
+ if ( j == 0 )
+ nMonthOffX1 = maPrevRect.Right()+1;
+ if ( j == mnMonthPerLine-1 )
+ nMonthOffX2 = aOutSize.Width()-maNextRect.Left()+1;
+ }
+ long nMaxMonthWidth = mnMonthWidth-nMonthOffX1-nMonthOffX2-4;
+ if ( nMonthTextWidth > nMaxMonthWidth )
+ {
+ // Abbreviated month name.
+ aMonthText = maCalendarWrapper.getDisplayName(
+ i18n::CalendarDisplayIndex::MONTH, nMonth-1, 0);
+ aMonthText += ' ';
+ aMonthText += String::CreateFromInt64( nYear );
+ nMonthTextWidth = GetTextWidth( aMonthText );
+ }
+ long nTempOff = (mnMonthWidth-nMonthTextWidth+1)/2;
+ if ( nTempOff < nMonthOffX1 )
+ nDeltaX += nMonthOffX1+1;
+ else
+ {
+ if ( nTempOff+nMonthTextWidth > mnMonthWidth-nMonthOffX2 )
+ nDeltaX += mnMonthWidth-nMonthOffX2-nMonthTextWidth;
+ else
+ nDeltaX += nTempOff;
+ }
+ SetTextColor( rStyleSettings.GetButtonTextColor() );
+ DrawText( Point( nDeltaX, nDeltaY ), aMonthText );
+ SetTextColor( rStyleSettings.GetWindowTextColor() );
+
+ // Weekleiste ausgeben
+ if ( bPaint )
+ {
+ nDayX = nX+mnDaysOffX;
+ nDayY = nY+mnWeekDayOffY;
+ nDeltaY = nDayY + mnDayHeight;
+ SetLineColor( rStyleSettings.GetWindowTextColor() );
+ Point aStartPos( nDayX, nDeltaY );
+ if ( mnWinStyle & WB_WEEKNUMBER )
+ aStartPos.X() -= WEEKNUMBER_OFFX-2;
+ DrawLine( aStartPos, Point( nDayX+(7*mnDayWidth), nDeltaY ) );
+ DrawTextArray( Point( nDayX+mnDayOfWeekAry[0], nDayY ), maDayOfWeekText, &(mnDayOfWeekAry[1]) );
+ }
+
+ // Week-Numbers ausgeben
+ if ( mnWinStyle & WB_WEEKNUMBER )
+ {
+ nDayX = nX+mnDaysOffX;
+ nDayY = nY+mnWeekDayOffY;
+ nDeltaY = nDayY + mnDayHeight;
+ long nMonthHeight = mnDayHeight*6;
+ if ( bPaint )
+ DrawLine( Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY ), Point( nDayX-WEEKNUMBER_OFFX+2, nDeltaY+nMonthHeight ) );
+ else
+ Erase( Rectangle( nDayX-mnWeekWidth-WEEKNUMBER_OFFX, nDeltaY, nDayX-WEEKNUMBER_OFFX-1, nDeltaY+nMonthHeight ) );
+
+ Font aOldFont = GetFont();
+ Font aTempFont = aOldFont;
+ ImplGetWeekFont( aTempFont );
+ SetFont( aTempFont );
+ nDayX -= mnWeekWidth;
+ nDayY = nY+mnDaysOffY;
+ maCalendarWrapper.setGregorianDateTime( aDate);
+ for ( sal_uInt16 nWeekCount = 0; nWeekCount < 6; nWeekCount++ )
+ {
+ sal_Int16 nWeek = maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
+ String aWeekText( String::CreateFromInt32( nWeek));
+ long nOffX = (mnWeekWidth-WEEKNUMBER_OFFX)-GetTextWidth( aWeekText );
+ long nOffY = (mnDayHeight-GetTextHeight())/2;
+ DrawText( Point( nDayX+nOffX, nDayY+nOffY ), aWeekText );
+ nDayY += mnDayHeight;
+ maCalendarWrapper.addValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, 7);
+ }
+ SetFont( aOldFont );
+ }
+
+ // Tage ausgeben
+ sal_uInt16 nDaysInMonth = aDate.GetDaysInMonth();
+ nDayX = nX+mnDaysOffX;
+ nDayY = nY+mnDaysOffY;
+ if ( !bPaint )
+ {
+ Rectangle aClearRect( nDayX, nDayY,
+ nDayX+(7*mnDayWidth)-1, nDayY+(6*mnDayHeight)-1 );
+ Erase( aClearRect );
+ }
+ sal_uInt16 nDayIndex = (sal_uInt16)aDate.GetDayOfWeek();
+ nDayIndex = (nDayIndex+(7-(sal_uInt16)eStartDay)) % 7;
+ if ( (i == 0) && (j == 0) )
+ {
+ Date aTempDate = aDate;
+ aTempDate -= nDayIndex;
+ for ( nDay = 0; nDay < nDayIndex; nDay++ )
+ {
+ nDeltaX = nDayX + (nDay*mnDayWidth);
+ ImplDrawDate( nDeltaX, nDayY, nDay+aTempDate.GetDay(),
+ aTempDate.GetMonth(), aTempDate.GetYear(),
+ (DayOfWeek)((nDay+(sal_uInt16)eStartDay)%7), sal_False, sal_True, nToday );
+ }
+ }
+ for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
+ {
+ nDeltaX = nDayX + (nDayIndex*mnDayWidth);
+ ImplDrawDate( nDeltaX, nDayY, nDay, nMonth, nYear,
+ (DayOfWeek)((nDayIndex+(sal_uInt16)eStartDay)%7),
+ sal_False, sal_False, nToday );
+ if ( nDayIndex == 6 )
+ {
+ nDayIndex = 0;
+ nDayY += mnDayHeight;
+ }
+ else
+ nDayIndex++;
+ }
+ if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
+ {
+ sal_uInt16 nWeekDay = (sal_uInt16)aDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(sal_uInt16)eStartDay)) % 7;
+ sal_uInt16 nDayCount = 42-nDaysInMonth-nWeekDay;
+ Date aTempDate = aDate;
+ aTempDate += nDaysInMonth;
+ for ( nDay = 1; nDay <= nDayCount; nDay++ )
+ {
+ nDeltaX = nDayX + (nDayIndex*mnDayWidth);
+ ImplDrawDate( nDeltaX, nDayY, nDay,
+ aTempDate.GetMonth(), aTempDate.GetYear(),
+ (DayOfWeek)((nDayIndex+(sal_uInt16)eStartDay)%7),
+ sal_False, sal_True, nToday );
+ if ( nDayIndex == 6 )
+ {
+ nDayIndex = 0;
+ nDayY += mnDayHeight;
+ }
+ else
+ nDayIndex++;
+ }
+ }
+
+ aDate += nDaysInMonth;
+ nX += mnMonthWidth;
+ }
+
+ nY += mnMonthHeight;
+ }
+
+ // Spin-Buttons zeichnen
+ if ( bPaint )
+ ImplDrawSpin();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplUpdateDate( const Date& rDate )
+{
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ Rectangle aDateRect( GetDateRect( rDate ) );
+ if ( !aDateRect.IsEmpty() )
+ {
+ sal_Bool bOther = (rDate < GetFirstMonth()) || (rDate > GetLastMonth());
+ ImplDrawDate( aDateRect.Left(), aDateRect.Top(),
+ rDate.GetDay(), rDate.GetMonth(), rDate.GetYear(),
+ rDate.GetDayOfWeek(), sal_True, bOther );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplUpdateSelection( Table* pOld )
+{
+ Table* pNew = mpSelectTable;
+ void* p;
+ sal_uLong nKey;
+
+ p = pOld->First();
+ while ( p )
+ {
+ nKey = pOld->GetCurKey();
+ if ( !pNew->Get( nKey ) )
+ {
+ Date aTempDate( nKey );
+ ImplUpdateDate( aTempDate );
+ }
+
+ p = pOld->Next();
+ }
+
+ p = pNew->First();
+ while ( p )
+ {
+ nKey = pNew->GetCurKey();
+ if ( !pOld->Get( nKey ) )
+ {
+ Date aTempDate( nKey );
+ ImplUpdateDate( aTempDate );
+ }
+
+ p = pNew->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplMouseSelect( const Date& rDate, sal_uInt16 nHitTest,
+ sal_Bool bMove, sal_Bool bExpand, sal_Bool bExtended )
+{
+ Table* pOldSel = new Table( *mpSelectTable );
+ Date aOldDate = maCurDate;
+ Date aTempDate = rDate;
+
+ if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
+ aTempDate--;
+
+ if ( mbMultiSelection )
+ {
+ maCurDate = aTempDate;
+ mbSelLeft = aTempDate < maAnchorDate;
+
+ if ( bMove )
+ {
+ if ( mbSelLeft )
+ {
+ ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), aTempDate );
+ ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, maAnchorDate, Date( 31, 12, 9999 ) );
+ }
+ else
+ {
+ ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, Date( 1, 1, 0 ), maAnchorDate );
+ ImplCalendarUnSelectDateRange( mpSelectTable, mpRestoreSelectTable, aTempDate, Date( 31, 12, 9999 ) );
+ }
+ ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, !mbUnSel );
+ }
+ else
+ {
+ if ( bExpand )
+ {
+ if ( !bExtended )
+ {
+ if ( mbSelLeft )
+ {
+ ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aTempDate, sal_False );
+ ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), sal_False );
+ }
+ else
+ {
+ ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, sal_False );
+ ImplCalendarSelectDateRange( mpSelectTable, aTempDate, Date( 31, 12, 9999 ), sal_False );
+ }
+ }
+ ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, sal_True );
+ }
+ else if ( bExtended && !(mnWinStyle & WB_RANGESELECT) )
+ {
+ maAnchorDate = aTempDate;
+ if ( IsDateSelected( aTempDate ) )
+ {
+ mbUnSel = sal_True;
+ ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_False );
+ }
+ else
+ {
+ ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_True );
+ }
+ }
+ else
+ {
+ maAnchorDate = aTempDate;
+ ImplCalendarClearSelectDate( mpSelectTable );
+ ImplCalendarSelectDate( mpSelectTable, aTempDate, sal_True );
+ }
+
+ mpRestoreSelectTable = new Table( *mpSelectTable );
+ }
+ }
+ else
+ {
+ if ( aTempDate < maCurDate )
+ mbSelLeft = sal_True;
+ else
+ mbSelLeft = sal_False;
+ if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
+ aTempDate = maOldCurDate;
+ if ( !bMove )
+ maAnchorDate = aTempDate;
+ if ( aTempDate != maCurDate )
+ {
+ maCurDate = aTempDate;
+ ImplCalendarSelectDate( mpSelectTable, aOldDate, sal_False );
+ ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
+ }
+ }
+
+ sal_Bool bNewSel = *pOldSel != *mpSelectTable;
+ if ( (maCurDate != aOldDate) || bNewSel )
+ {
+ if ( bNewSel )
+ {
+ mbInSelChange = sal_True;
+ SelectionChanging();
+ mbInSelChange = sal_False;
+ }
+ HideFocus();
+ if ( bNewSel )
+ ImplUpdateSelection( pOldSel );
+ if ( !bNewSel || !pOldSel->Get( aOldDate.GetDate() ) )
+ ImplUpdateDate( aOldDate );
+ // Damit Focus-Rechteck auch wieder neu ausgegeben wird
+ if ( HasFocus() || !bNewSel || !mpSelectTable->Get( maCurDate.GetDate() ) )
+ ImplUpdateDate( maCurDate );
+ }
+ delete pOldSel;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplUpdate( sal_Bool bCalcNew )
+{
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( bCalcNew && !mbCalc )
+ Invalidate();
+ else if ( !mbFormat && !mbCalc )
+ {
+ if ( mbDirect )
+ {
+ mbFormat = sal_True;
+ ImplDraw( sal_False );
+ return;
+ }
+ else
+ Invalidate();
+ }
+ }
+
+ if ( bCalcNew )
+ mbCalc = sal_True;
+ mbFormat = sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplInvertDropPos()
+{
+ Rectangle aRect = GetDateRect( maDropDate );//this is one Pixel to width and one to heigh
+ aRect.Bottom() = aRect.Top()+mnDayHeight-1;
+ aRect.Right() = aRect.Left()+mnDayWidth-1;
+ Invert( aRect );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplScroll( sal_Bool bPrev )
+{
+ Date aNewFirstMonth = GetFirstMonth();
+ if ( bPrev )
+ {
+ aNewFirstMonth--;
+ aNewFirstMonth -= aNewFirstMonth.GetDaysInMonth()-1;
+ }
+ else
+ aNewFirstMonth += aNewFirstMonth.GetDaysInMonth();
+ mbDirect = sal_True;
+ SetFirstDate( aNewFirstMonth );
+ mbDirect = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplShowMenu( const Point& rPos, const Date& rDate )
+{
+ EndSelection();
+
+ Date aOldFirstDate = GetFirstMonth();
+ PopupMenu aPopupMenu;
+ PopupMenu* pYearPopupMenus[MENU_YEAR_COUNT];
+ sal_uInt16 nMonthOff;
+ sal_uInt16 nCurItemId;
+ sal_uInt16 nYear = rDate.GetYear()-1;
+ sal_uInt16 i;
+ sal_uInt16 j;
+ sal_uInt16 nYearIdCount = 1000;
+
+ nMonthOff = (rDate.GetYear()-aOldFirstDate.GetYear())*12;
+ if ( aOldFirstDate.GetMonth() < rDate.GetMonth() )
+ nMonthOff += rDate.GetMonth()-aOldFirstDate.GetMonth();
+ else
+ nMonthOff -= aOldFirstDate.GetMonth()-rDate.GetMonth();
+
+ // Menu aufbauen (Jahre mit verschiedenen Monaten aufnehmen)
+ for ( i = 0; i < MENU_YEAR_COUNT; i++ )
+ {
+ pYearPopupMenus[i] = new PopupMenu;
+ for ( j = 1; j <= 12; j++ )
+ pYearPopupMenus[i]->InsertItem( nYearIdCount+j,
+ maCalendarWrapper.getDisplayName(
+ i18n::CalendarDisplayIndex::MONTH, j-1, 1));
+ aPopupMenu.InsertItem( 10+i, UniString::CreateFromInt32( nYear+i ) );
+ aPopupMenu.SetPopupMenu( 10+i, pYearPopupMenus[i] );
+ nYearIdCount += 1000;
+ }
+
+ mbMenuDown = sal_True;
+ nCurItemId = aPopupMenu.Execute( this, rPos );
+ mbMenuDown = sal_False;
+
+ // Menu zerstoeren
+ aPopupMenu.SetPopupMenu( 2, NULL );
+ for ( i = 0; i < MENU_YEAR_COUNT; i++ )
+ {
+ aPopupMenu.SetPopupMenu( 10+i, NULL );
+ delete pYearPopupMenus[i];
+ }
+
+ if ( nCurItemId )
+ {
+ sal_uInt16 nTempMonthOff = nMonthOff % 12;
+ sal_uInt16 nTempYearOff = nMonthOff / 12;
+ sal_uInt16 nNewMonth = nCurItemId % 1000;
+ sal_uInt16 nNewYear = nYear+((nCurItemId-1000)/1000);
+ if ( nTempMonthOff < nNewMonth )
+ nNewMonth = nNewMonth - nTempMonthOff;
+ else
+ {
+ nNewYear--;
+ nNewMonth = 12-(nTempMonthOff-nNewMonth);
+ }
+ nNewYear = nNewYear - nTempYearOff;
+ SetFirstDate( Date( 1, nNewMonth, nNewYear ) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplTracking( const Point& rPos, sal_Bool bRepeat )
+{
+ Date aTempDate = maCurDate;
+ sal_uInt16 nHitTest = ImplHitTest( rPos, aTempDate );
+
+ if ( mbSpinDown )
+ {
+ mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
+ mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
+
+ if ( bRepeat && (mbPrevIn || mbNextIn) )
+ {
+ mbScrollDateRange = sal_True;
+ ImplScroll( mbPrevIn );
+ mbScrollDateRange = sal_False;
+ }
+ }
+ else
+ ImplMouseSelect( aTempDate, nHitTest, sal_True, sal_False, sal_False );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplEndTracking( sal_Bool bCancel )
+{
+ sal_Bool bSelection = mbSelection;
+ sal_Bool bSpinDown = mbSpinDown;
+
+ mbDrag = sal_False;
+ mbSelection = sal_False;
+ mbMultiSelection = sal_False;
+ mbUnSel = sal_False;
+ mbSpinDown = sal_False;
+ mbPrevIn = sal_False;
+ mbNextIn = sal_False;
+
+ if ( bCancel )
+ {
+ if ( maOldFirstDate != maFirstDate )
+ SetFirstDate( maOldFirstDate );
+
+ if ( !bSpinDown )
+ {
+ Table* pOldSel = new Table( *mpSelectTable );
+ Date aOldDate = maCurDate;
+ maCurDate = maOldCurDate;
+ *mpSelectTable = *mpOldSelectTable;
+ HideFocus();
+ ImplUpdateSelection( pOldSel );
+ if ( !pOldSel->Get( aOldDate.GetDate() ) )
+ ImplUpdateDate( aOldDate );
+ // Damit Focus-Rechteck auch wieder neu ausgegeben wird
+ if ( HasFocus() || !mpSelectTable->Get( maCurDate.GetDate() ) )
+ ImplUpdateDate( maCurDate );
+ delete pOldSel;
+ }
+ }
+
+ if ( !bSpinDown )
+ {
+ if ( !bCancel )
+ {
+ // Feststellen, ob wir sichtbaren Bereich scrollen sollen
+ sal_uLong nSelCount = mpSelectTable->Count();
+ if ( nSelCount )
+ {
+ Date aFirstSelDate( mpSelectTable->GetObjectKey( 0 ) );
+ Date aLastSelDate( mpSelectTable->GetObjectKey( nSelCount-1 ) );
+ if ( aLastSelDate < GetFirstMonth() )
+ ImplScroll( sal_True );
+ else if ( GetLastMonth() < aFirstSelDate )
+ ImplScroll( sal_False );
+ }
+ }
+
+ if ( mbAllSel ||
+ (!bCancel && ((maCurDate != maOldCurDate) || (*mpOldSelectTable != *mpSelectTable))) )
+ Select();
+
+ if ( !bSelection && (mnWinStyle & WB_TABSTOP) && !bCancel )
+ GrabFocus();
+
+ delete mpOldSelectTable;
+ mpOldSelectTable = NULL;
+ delete mpRestoreSelectTable;
+ mpRestoreSelectTable = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_STATIC_LINK( Calendar, ScrollHdl, Timer*, EMPTYARG )
+{
+ sal_Bool bPrevIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_PREV) != 0;
+ sal_Bool bNextIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_NEXT) != 0;
+ if( bNextIn || bPrevIn )
+ {
+ pThis->mbScrollDateRange = sal_True;
+ pThis->ImplScroll( bPrevIn );
+ pThis->mbScrollDateRange = sal_False;
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && !mbMenuDown )
+ {
+ Date aTempDate = maCurDate;
+ sal_uInt16 nHitTest = ImplHitTest( rMEvt.GetPosPixel(), aTempDate );
+ if ( nHitTest )
+ {
+ if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
+ ImplShowMenu( rMEvt.GetPosPixel(), aTempDate );
+ else
+ {
+ maOldFirstDate = maFirstDate;
+
+ mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
+ mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
+ if ( mbPrevIn || mbNextIn )
+ {
+ mbSpinDown = sal_True;
+ mbScrollDateRange = sal_True;
+ ImplScroll( mbPrevIn );
+ mbScrollDateRange = sal_False;
+ // Hier muss BUTTONREPEAT stehen, also nicht wieder
+ // auf SCROLLREPEAT aendern, sondern mit TH abklaeren,
+ // warum es evtl. anders sein sollte (71775)
+ StartTracking( STARTTRACK_BUTTONREPEAT );
+ }
+ else
+ {
+ if ( (rMEvt.GetClicks() == 2) && (nHitTest & CALENDAR_HITTEST_DAY) )
+ DoubleClick();
+ else
+ {
+ if ( mpOldSelectTable )
+ delete mpOldSelectTable;
+ maOldCurDate = maCurDate;
+ mpOldSelectTable = new Table( *mpSelectTable );
+
+ if ( !mbSelection )
+ {
+ mbDrag = sal_True;
+ StartTracking();
+ }
+
+ mbMultiSelection = (mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT)) != 0;
+ if ( (nHitTest & CALENDAR_HITTEST_DAY) && mbMultiSelection )
+ mbWeekSel = sal_True;
+ else
+ mbWeekSel = sal_False;
+ ImplMouseSelect( aTempDate, nHitTest, sal_False, rMEvt.IsShift(), rMEvt.IsMod1() );
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
+ Control::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && mbSelection )
+ ImplEndTracking( sal_False );
+ else
+ Control::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( mbSelection && rMEvt.GetButtons() )
+ ImplTracking( rMEvt.GetPosPixel(), sal_False );
+ else
+ Control::MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::Tracking( const TrackingEvent& rTEvt )
+{
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ if ( rTEvt.IsTrackingEnded() )
+ ImplEndTracking( rTEvt.IsTrackingCanceled() );
+ else
+ ImplTracking( aMousePos, rTEvt.IsTrackingRepeat() );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::KeyInput( const KeyEvent& rKEvt )
+{
+ Date aNewDate = maCurDate;
+ sal_Bool bMultiSel = (mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) != 0;
+ sal_Bool bExpand = rKEvt.GetKeyCode().IsShift();
+ sal_Bool bExtended = rKEvt.GetKeyCode().IsMod1();
+
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_HOME:
+ aNewDate.SetDay( 1 );
+ break;
+
+ case KEY_END:
+ aNewDate.SetDay( aNewDate.GetDaysInMonth() );
+ break;
+
+ case KEY_LEFT:
+ aNewDate--;
+ break;
+
+ case KEY_RIGHT:
+ aNewDate++;
+ break;
+
+ case KEY_UP:
+ aNewDate -= 7;
+ break;
+
+ case KEY_DOWN:
+ aNewDate += 7;
+ break;
+
+ case KEY_PAGEUP:
+ {
+ Date aTempDate = aNewDate;
+ aTempDate -= aNewDate.GetDay()+1;
+ aNewDate -= aTempDate.GetDaysInMonth();
+ }
+ break;
+
+ case KEY_PAGEDOWN:
+ aNewDate += aNewDate.GetDaysInMonth();
+ break;
+
+ case KEY_SPACE:
+ if ( bMultiSel && !(mnWinStyle & WB_RANGESELECT) )
+ {
+ if ( !bExpand )
+ {
+ sal_Bool bDateSel = IsDateSelected( maCurDate );
+ SelectDate( maCurDate, !bDateSel );
+ mbSelLeft = sal_False;
+ SelectionChanging();
+ mbTravelSelect = sal_True;
+ Select();
+ mbTravelSelect = sal_False;
+ }
+ }
+ else
+ Control::KeyInput( rKEvt );
+ break;
+
+ default:
+ Control::KeyInput( rKEvt );
+ break;
+ }
+
+ if ( aNewDate != maCurDate )
+ {
+ if ( bMultiSel && bExpand )
+ {
+ Table* pOldSel = new Table( *mpSelectTable );
+ Date aOldAnchorDate = maAnchorDate;
+ mbSelLeft = aNewDate < maAnchorDate;
+ if ( !bExtended )
+ {
+ if ( mbSelLeft )
+ {
+ ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), aNewDate, sal_False );
+ ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), sal_False );
+ }
+ else
+ {
+ ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, sal_False );
+ ImplCalendarSelectDateRange( mpSelectTable, aNewDate, Date( 31, 12, 9999 ), sal_False );
+ }
+ }
+ ImplCalendarSelectDateRange( mpSelectTable, aNewDate, maAnchorDate, sal_True );
+ mbDirect = sal_True;
+ SetCurDate( aNewDate );
+ mbDirect = sal_False;
+ maAnchorDate = aOldAnchorDate;
+ mbInSelChange = sal_True;
+ SelectionChanging();
+ mbInSelChange = sal_False;
+ ImplUpdateSelection( pOldSel );
+ delete pOldSel;
+ }
+ else
+ {
+ if ( mnWinStyle & WB_RANGESELECT )
+ {
+ SetNoSelection();
+ SelectDate( aNewDate, sal_True );
+ }
+ mbDirect = sal_True;
+ SetCurDate( aNewDate );
+ mbDirect = sal_False;
+ }
+ mbTravelSelect = sal_True;
+ Select();
+ mbTravelSelect = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::Paint( const Rectangle& )
+{
+ ImplDraw( sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::GetFocus()
+{
+ ImplUpdateDate( maCurDate );
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::LoseFocus()
+{
+ HideFocus();
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::Resize()
+{
+ ImplUpdate( sal_True );
+ Control::Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
+ {
+ Date aDate = maCurDate;
+ if ( GetDate( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ), aDate ) )
+ {
+ Rectangle aDateRect = GetDateRect( aDate );
+ Point aPt = OutputToScreenPixel( aDateRect.TopLeft() );
+ aDateRect.Left() = aPt.X();
+ aDateRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aDateRect.BottomRight() );
+ aDateRect.Right() = aPt.X();
+ aDateRect.Bottom() = aPt.Y();
+
+ if ( (rHEvt.GetMode() & HELPMODE_BALLOON) || (mnWinStyle & WB_QUICKHELPSHOWSDATEINFO) )
+ {
+ ImplDateInfo* pInfo;
+ if ( mpDateTable )
+ {
+ pInfo = mpDateTable->Get( aDate.GetDate() );
+ if ( !pInfo )
+ pInfo = mpDateTable->Get( Date( aDate.GetDay(), aDate.GetMonth(), 0 ).GetDate() );
+ }
+ else
+ pInfo = NULL;
+ if ( pInfo )
+ {
+ XubString aStr = pInfo->maText;
+ if ( aStr.Len() )
+ {
+ Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aDateRect, aStr );
+ return;
+ }
+ }
+ }
+
+ if ( rHEvt.GetMode() & HELPMODE_QUICK )
+ {
+ maCalendarWrapper.setGregorianDateTime( aDate);
+ sal_uInt16 nWeek = (sal_uInt16) maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
+ sal_uInt16 nMonth = aDate.GetMonth();
+ XubString aStr( maDayText );
+ aStr.AppendAscii( ": " );
+ aStr.Append( XubString::CreateFromInt32( aDate.GetDayOfYear() ) );
+ aStr.AppendAscii( " / " );
+ aStr.Append( maWeekText );
+ aStr.AppendAscii( ": " );
+ aStr.Append( XubString::CreateFromInt32( nWeek ) );
+ // Evt. noch Jahr hinzufuegen, wenn es nicht das gleiche ist
+ if ( (nMonth == 12) && (nWeek == 1) )
+ {
+ aStr.AppendAscii( ", " );
+ aStr.Append( XubString::CreateFromInt32( aDate.GetYear()+1 ) );
+ }
+ else if ( (nMonth == 1) && (nWeek > 50) )
+ {
+ aStr.AppendAscii( ", " );
+ aStr.Append( XubString::CreateFromInt32( aDate.GetYear()-1 ) );
+ }
+ Help::ShowQuickHelp( this, aDateRect, aStr );
+ return;
+ }
+ }
+ }
+
+ Control::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
+ {
+ if ( !mbSelection && rCEvt.IsMouseEvent() )
+ {
+ Date aTempDate = maCurDate;
+ sal_uInt16 nHitTest = ImplHitTest( rCEvt.GetMousePosPixel(), aTempDate );
+ if ( nHitTest & CALENDAR_HITTEST_MONTHTITLE )
+ {
+ ImplShowMenu( rCEvt.GetMousePosPixel(), aTempDate );
+ return;
+ }
+ }
+ }
+ else if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if ( pData->GetMode() == COMMAND_WHEEL_SCROLL )
+ {
+ long nNotchDelta = pData->GetNotchDelta();
+ if ( nNotchDelta < 0 )
+ {
+ while ( nNotchDelta < 0 )
+ {
+ ImplScroll( sal_True );
+ nNotchDelta++;
+ }
+ }
+ else
+ {
+ while ( nNotchDelta > 0 )
+ {
+ ImplScroll( sal_False );
+ nNotchDelta--;
+ }
+ }
+
+ return;
+ }
+ }
+
+ Control::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplFormat();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SelectionChanging()
+{
+ maSelectionChangingHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::DateRangeChanged()
+{
+ maDateRangeChangedHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::RequestDateInfo()
+{
+ maRequestDateInfoHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SelectDate( const Date& rDate, sal_Bool bSelect )
+{
+ if ( !rDate.IsValid() )
+ return;
+
+ Table* pOldSel;
+
+ if ( !mbInSelChange )
+ pOldSel = new Table( *mpSelectTable );
+ else
+ pOldSel = NULL;
+
+ ImplCalendarSelectDate( mpSelectTable, rDate, bSelect );
+
+ if ( pOldSel )
+ {
+ ImplUpdateSelection( pOldSel );
+ delete pOldSel;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SelectDateRange( const Date& rStartDate, const Date& rEndDate,
+ sal_Bool bSelect )
+{
+ if ( !rStartDate.IsValid() || !rEndDate.IsValid() )
+ return;
+
+ Table* pOldSel;
+
+ if ( !mbInSelChange )
+ pOldSel = new Table( *mpSelectTable );
+ else
+ pOldSel = NULL;
+
+ ImplCalendarSelectDateRange( mpSelectTable, rStartDate, rEndDate, bSelect );
+
+ if ( pOldSel )
+ {
+ ImplUpdateSelection( pOldSel );
+ delete pOldSel;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetNoSelection()
+{
+ Table* pOldSel;
+
+ if ( !mbInSelChange )
+ pOldSel = new Table( *mpSelectTable );
+ else
+ pOldSel = NULL;
+
+ ImplCalendarClearSelectDate( mpSelectTable );
+
+ if ( pOldSel )
+ {
+ ImplUpdateSelection( pOldSel );
+ delete pOldSel;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Calendar::IsDateSelected( const Date& rDate ) const
+{
+ return mpSelectTable->IsKeyValid( rDate.GetDate() );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uLong Calendar::GetSelectDateCount() const
+{
+ return mpSelectTable->Count();
+}
+
+// -----------------------------------------------------------------------
+
+Date Calendar::GetSelectDate( sal_uLong nIndex ) const
+{
+ if ( nIndex < mpSelectTable->Count() )
+ return Date( mpSelectTable->GetObjectKey( nIndex ) );
+ else
+ {
+ Date aDate( 0, 0, 0 );
+ return aDate;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetCurDate( const Date& rNewDate )
+{
+ if ( !rNewDate.IsValid() )
+ return;
+
+ if ( maCurDate != rNewDate )
+ {
+ sal_Bool bUpdate = IsVisible() && IsUpdateMode();
+ Date aOldDate = maCurDate;
+ maCurDate = rNewDate;
+ maAnchorDate = maCurDate;
+
+ if ( !(mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) )
+ {
+ ImplCalendarSelectDate( mpSelectTable, aOldDate, sal_False );
+ ImplCalendarSelectDate( mpSelectTable, maCurDate, sal_True );
+ }
+ else if ( !HasFocus() )
+ bUpdate = sal_False;
+
+ // Aktuelles Datum noch in den sichtbaren Bereich verschieben
+ if ( mbFormat || (maCurDate < GetFirstMonth()) )
+ SetFirstDate( maCurDate );
+ else if ( maCurDate > GetLastMonth() )
+ {
+ Date aTempDate = GetLastMonth();
+ long nDateOff = maCurDate-aTempDate;
+ if ( nDateOff < 365 )
+ {
+ Date aFirstDate = GetFirstMonth();
+ aFirstDate += aFirstDate.GetDaysInMonth();
+ aTempDate++;
+ while ( nDateOff > aTempDate.GetDaysInMonth() )
+ {
+ aFirstDate += aFirstDate.GetDaysInMonth();
+ long nDaysInMonth = aTempDate.GetDaysInMonth();
+ aTempDate += nDaysInMonth;
+ nDateOff -= nDaysInMonth;
+ }
+ SetFirstDate( aFirstDate );
+ }
+ else
+ SetFirstDate( maCurDate );
+ }
+ else
+ {
+ if ( bUpdate )
+ {
+ HideFocus();
+ ImplUpdateDate( aOldDate );
+ ImplUpdateDate( maCurDate );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetFirstDate( const Date& rNewFirstDate )
+{
+ if ( maFirstDate != rNewFirstDate )
+ {
+ maFirstDate = Date( 1, rNewFirstDate.GetMonth(), rNewFirstDate.GetYear() );
+ mbDropPos = sal_False;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Date Calendar::GetFirstMonth() const
+{
+ if ( maFirstDate.GetDay() > 1 )
+ {
+ if ( maFirstDate.GetMonth() == 12 )
+ return Date( 1, 1, maFirstDate.GetYear()+1 );
+ else
+ return Date( 1, maFirstDate.GetMonth()+1, maFirstDate.GetYear() );
+ }
+ else
+ return maFirstDate;
+}
+
+// -----------------------------------------------------------------------
+
+Date Calendar::GetLastMonth() const
+{
+ Date aDate = GetFirstMonth();
+ sal_uInt16 nMonthCount = GetMonthCount();
+ for ( sal_uInt16 i = 0; i < nMonthCount; i++ )
+ aDate += aDate.GetDaysInMonth();
+ aDate--;
+ return aDate;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 Calendar::GetMonthCount() const
+{
+ if ( mbFormat )
+ return 1;
+ else
+ return (sal_uInt16)(mnMonthPerLine*mnLines);
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Calendar::GetDropDate( Date& rDate ) const
+{
+ if( mbDropPos )
+ {
+ rDate = maDropDate;
+ return sal_True;
+ }
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Calendar::GetDate( const Point& rPos, Date& rDate ) const
+{
+ Date aDate = maCurDate;
+ sal_uInt16 nHitTest = ImplHitTest( rPos, aDate );
+ if ( nHitTest & CALENDAR_HITTEST_DAY )
+ {
+ rDate = aDate;
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Calendar::GetDateRect( const Date& rDate ) const
+{
+ Rectangle aRect;
+
+ if ( mbFormat || (rDate < maFirstDate) || (rDate > (maFirstDate+mnDayCount)) )
+ return aRect;
+
+ long nX;
+ long nY;
+ sal_uLong nDaysOff;
+ sal_uInt16 nDayIndex;
+ Date aDate = GetFirstMonth();
+
+ if ( rDate < aDate )
+ {
+ aRect = GetDateRect( aDate );
+ nDaysOff = aDate-rDate;
+ nX = (long)(nDaysOff*mnDayWidth);
+ aRect.Left() -= nX;
+ aRect.Right() -= nX;
+ return aRect;
+ }
+ else
+ {
+ Date aLastDate = GetLastMonth();
+ if ( rDate > aLastDate )
+ {
+ sal_uInt16 nWeekDay = (sal_uInt16)aLastDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(sal_uInt16)ImplGetWeekStart())) % 7;
+ aLastDate -= nWeekDay;
+ aRect = GetDateRect( aLastDate );
+ nDaysOff = rDate-aLastDate;
+ nDayIndex = 0;
+ for ( sal_uInt16 i = 0; i <= nDaysOff; i++ )
+ {
+ if ( aLastDate == rDate )
+ {
+ aRect.Left() += nDayIndex*mnDayWidth;
+ aRect.Right() = aRect.Left()+mnDayWidth;
+ return aRect;
+ }
+ if ( nDayIndex == 6 )
+ {
+ nDayIndex = 0;
+ aRect.Top() += mnDayHeight;
+ aRect.Bottom() += mnDayHeight;
+ }
+ else
+ nDayIndex++;
+ aLastDate++;
+ }
+ }
+ }
+
+ nY = 0;
+ for ( long i = 0; i < mnLines; i++ )
+ {
+ nX = 0;
+ for ( long j = 0; j < mnMonthPerLine; j++ )
+ {
+ sal_uInt16 nDaysInMonth = aDate.GetDaysInMonth();
+
+ // Monat gerufen
+ if ( (aDate.GetMonth() == rDate.GetMonth()) &&
+ (aDate.GetYear() == rDate.GetYear()) )
+ {
+ long nDayX = nX+mnDaysOffX;
+ long nDayY = nY+mnDaysOffY;
+ nDayIndex = (sal_uInt16)aDate.GetDayOfWeek();
+ nDayIndex = (nDayIndex+(7-(sal_uInt16)ImplGetWeekStart())) % 7;
+ for ( sal_uInt16 nDay = 1; nDay <= nDaysInMonth; nDay++ )
+ {
+ if ( nDay == rDate.GetDay() )
+ {
+ aRect.Left() = nDayX + (nDayIndex*mnDayWidth);
+ aRect.Top() = nDayY;
+ aRect.Right() = aRect.Left()+mnDayWidth;
+ aRect.Bottom() = aRect.Top()+mnDayHeight;
+ break;
+ }
+ if ( nDayIndex == 6 )
+ {
+ nDayIndex = 0;
+ nDayY += mnDayHeight;
+ }
+ else
+ nDayIndex++;
+ }
+ }
+
+ aDate += nDaysInMonth;
+ nX += mnMonthWidth;
+ }
+
+ nY += mnMonthHeight;
+ }
+
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetStandardColor( const Color& rColor )
+{
+ if ( mpStandardColor )
+ *mpStandardColor = rColor;
+ else
+ mpStandardColor = new Color( rColor );
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetSaturdayColor( const Color& rColor )
+{
+ if ( mpSaturdayColor )
+ *mpSaturdayColor = rColor;
+ else
+ mpSaturdayColor = new Color( rColor );
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetSundayColor( const Color& rColor )
+{
+ if ( mpSundayColor )
+ *mpSundayColor = rColor;
+ else
+ mpSundayColor = new Color( rColor );
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::AddDateInfo( const Date& rDate, const String& rText,
+ const Color* pTextColor, const Color* pFrameColor,
+ sal_uInt16 nFlags )
+{
+ if ( !mpDateTable )
+ mpDateTable = new ImplDateTable( 256, 256 );
+
+ sal_Bool bChanged = sal_False;
+ sal_uLong nKey = rDate.GetDate();
+ ImplDateInfo* pDateInfo = mpDateTable->Get( nKey );
+ if ( pDateInfo )
+ pDateInfo->maText = rText;
+ else
+ {
+ pDateInfo = new ImplDateInfo( rText );
+ mpDateTable->Insert( nKey, pDateInfo );
+ }
+ if ( pTextColor )
+ {
+ if ( pDateInfo->mpTextColor )
+ {
+ if ( *(pDateInfo->mpTextColor) != *pTextColor )
+ {
+ *(pDateInfo->mpTextColor) = *pTextColor;
+ bChanged = sal_True;
+ }
+ }
+ else
+ {
+ pDateInfo->mpTextColor = new Color( *pTextColor );
+ bChanged = sal_True;
+ }
+ }
+ else
+ {
+ if ( pDateInfo->mpTextColor )
+ {
+ delete pDateInfo->mpTextColor;
+ pDateInfo->mpTextColor = NULL;
+ bChanged = sal_True;
+ }
+ }
+ if ( pFrameColor )
+ {
+ if ( pDateInfo->mpFrameColor )
+ {
+ if ( *(pDateInfo->mpFrameColor) != *pFrameColor )
+ {
+ *(pDateInfo->mpFrameColor) = *pFrameColor;
+ bChanged = sal_True;
+ }
+ }
+ else
+ {
+ pDateInfo->mpFrameColor = new Color( *pFrameColor );
+ bChanged = sal_True;
+ }
+ }
+ else
+ {
+ if ( pDateInfo->mpFrameColor )
+ {
+ delete pDateInfo->mpFrameColor;
+ pDateInfo->mpFrameColor = NULL;
+ bChanged = sal_True;
+ }
+ }
+ if ( pDateInfo->mnFlags != nFlags )
+ {
+ pDateInfo->mnFlags = nFlags;
+ bChanged = sal_True;
+ }
+
+ if ( bChanged )
+ ImplUpdateDate( rDate );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::RemoveDateInfo( const Date& rDate )
+{
+ if ( mpDateTable )
+ {
+ ImplDateInfo* pDateInfo = mpDateTable->Remove( rDate.GetDate() );
+ if ( pDateInfo )
+ {
+ delete pDateInfo;
+ ImplUpdateDate( rDate );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ClearDateInfo()
+{
+ if ( mpDateTable )
+ {
+ ImplDateInfo* pDateInfo = mpDateTable->First();
+ while ( pDateInfo )
+ {
+ sal_uLong nKey = mpDateTable->GetCurKey();
+ mpDateTable->Remove( nKey );
+ Date aDate( nKey );
+ ImplUpdateDate( aDate );
+ delete pDateInfo;
+ pDateInfo = mpDateTable->First();
+ }
+ delete mpDateTable;
+ mpDateTable = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString Calendar::GetDateInfoText( const Date& rDate )
+{
+ XubString aRet;
+ if ( mpDateTable )
+ {
+ sal_uLong nKey = rDate.GetDate();
+ ImplDateInfo* pDateInfo = mpDateTable->Get( nKey );
+ if ( pDateInfo )
+ aRet = pDateInfo->maText;
+ }
+ return aRet;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Calendar::ShowDropPos( const Point& rPos, Date& rDate )
+{
+ Date aTempDate = maCurDate;
+ mnDragScrollHitTest = ImplHitTest( rPos, aTempDate );
+
+ if ( mnDragScrollHitTest )
+ {
+ if ( mnDragScrollHitTest & (CALENDAR_HITTEST_PREV | CALENDAR_HITTEST_NEXT) )
+ {
+ if ( !maDragScrollTimer.IsActive() )
+ maDragScrollTimer.Start();
+ }
+ else
+ {
+ maDragScrollTimer.Stop();
+ if ( mnDragScrollHitTest & CALENDAR_HITTEST_DAY )
+ {
+ if ( !mbDropPos || (aTempDate != maDropDate) )
+ {
+ if( mbDropPos )
+ ImplInvertDropPos();
+ maDropDate = aTempDate;
+ mbDropPos = sal_True;
+ ImplInvertDropPos();
+ }
+
+ rDate = maDropDate;
+ return sal_True;
+ }
+ }
+ }
+ else
+ maDragScrollTimer.Stop();
+
+ HideDropPos();
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::HideDropPos()
+{
+ if ( mbDropPos )
+ {
+ ImplInvertDropPos();
+ mbDropPos = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::StartSelection()
+{
+ if ( mpOldSelectTable )
+ delete mpOldSelectTable;
+ maOldCurDate = maCurDate;
+ mpOldSelectTable = new Table( *mpSelectTable );
+
+ mbSelection = sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::EndSelection()
+{
+ if ( mbDrag || mbSpinDown || mbSelection )
+ {
+ if ( !mbSelection )
+ ReleaseMouse();
+
+ mbDrag = sal_False;
+ mbSelection = sal_False;
+ mbMultiSelection = sal_False;
+ mbSpinDown = sal_False;
+ mbPrevIn = sal_False;
+ mbNextIn = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size Calendar::CalcWindowSizePixel( long nCalcMonthPerLine,
+ long nCalcLines ) const
+{
+ XubString a99Text( XubString( RTL_CONSTASCII_USTRINGPARAM( "99" ) ) );
+ Font aOldFont = GetFont();
+
+ // Wochenanzeige beruecksichtigen
+ long nWeekWidth;
+ if ( mnWinStyle & WB_WEEKNUMBER )
+ {
+ Font aTempFont = aOldFont;
+ ImplGetWeekFont( aTempFont );
+ ((Calendar*)this)->SetFont( aTempFont );
+ nWeekWidth = GetTextWidth( a99Text )+WEEKNUMBER_OFFX;
+ ((Calendar*)this)->SetFont( aOldFont );
+ }
+ else
+ nWeekWidth = 0;
+
+ if ( mnWinStyle & WB_BOLDTEXT )
+ {
+ Font aFont = aOldFont;
+ if ( aFont.GetWeight() < WEIGHT_BOLD )
+ aFont.SetWeight( WEIGHT_BOLD );
+ else
+ aFont.SetWeight( WEIGHT_NORMAL );
+ ((Calendar*)this)->SetFont( aFont );
+ }
+
+ Size aSize;
+ long n99TextWidth = GetTextWidth( a99Text );
+ long nTextHeight = GetTextHeight();
+
+ if ( mnWinStyle & WB_BOLDTEXT )
+ ((Calendar*)this)->SetFont( aOldFont );
+
+ aSize.Width() += ((n99TextWidth+DAY_OFFX)*7) + nWeekWidth;
+ aSize.Width() += MONTH_BORDERX*2;
+ aSize.Width() *= nCalcMonthPerLine;
+
+ aSize.Height() = nTextHeight + TITLE_OFFY + (TITLE_BORDERY*2);
+ aSize.Height() += nTextHeight + WEEKDAY_OFFY;
+ aSize.Height() += ((nTextHeight+DAY_OFFY)*6);
+ aSize.Height() += MONTH_OFFY;
+ aSize.Height() *= nCalcLines;
+
+ return aSize;
+}
+
+// =======================================================================
+
+#define CALFIELD_EXTRA_BUTTON_WIDTH 14
+#define CALFIELD_EXTRA_BUTTON_HEIGHT 8
+#define CALFIELD_SEP_X 6
+#define CALFIELD_BORDERLINE_X 5
+#define CALFIELD_BORDER_YTOP 4
+#define CALFIELD_BORDER_Y 5
+
+// =======================================================================
+
+class ImplCFieldFloatWin : public FloatingWindow
+{
+private:
+ Calendar* mpCalendar;
+ PushButton* mpTodayBtn;
+ PushButton* mpNoneBtn;
+ FixedLine* mpFixedLine;
+
+public:
+ ImplCFieldFloatWin( Window* pParent );
+ ~ImplCFieldFloatWin();
+
+ void SetCalendar( Calendar* pCalendar )
+ { mpCalendar = pCalendar; }
+
+ PushButton* EnableTodayBtn( sal_Bool bEnable );
+ PushButton* EnableNoneBtn( sal_Bool bEnable );
+ void ArrangeButtons();
+
+ long Notify( NotifyEvent& rNEvt );
+};
+
+// -----------------------------------------------------------------------
+
+ImplCFieldFloatWin::ImplCFieldFloatWin( Window* pParent ) :
+ FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW )
+{
+ mpCalendar = NULL;
+ mpTodayBtn = NULL;
+ mpNoneBtn = NULL;
+ mpFixedLine = NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplCFieldFloatWin::~ImplCFieldFloatWin()
+{
+ delete mpTodayBtn;
+ delete mpNoneBtn;
+ delete mpFixedLine;
+}
+
+// -----------------------------------------------------------------------
+
+PushButton* ImplCFieldFloatWin::EnableTodayBtn( sal_Bool bEnable )
+{
+ if ( bEnable )
+ {
+ if ( !mpTodayBtn )
+ {
+ mpTodayBtn = new PushButton( this, WB_NOPOINTERFOCUS );
+ XubString aTodayText( SvtResId( STR_SVT_CALENDAR_TODAY ) );
+ mpTodayBtn->SetText( aTodayText );
+ Size aSize;
+ aSize.Width() = mpTodayBtn->GetCtrlTextWidth( mpTodayBtn->GetText() );
+ aSize.Height() = mpTodayBtn->GetTextHeight();
+ aSize.Width() += CALFIELD_EXTRA_BUTTON_WIDTH;
+ aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
+ mpTodayBtn->SetSizePixel( aSize );
+ mpTodayBtn->Show();
+ }
+ }
+ else
+ {
+ if ( mpTodayBtn )
+ {
+ delete mpTodayBtn;
+ mpTodayBtn = NULL;
+ }
+ }
+
+ return mpTodayBtn;
+}
+
+// -----------------------------------------------------------------------
+
+PushButton* ImplCFieldFloatWin::EnableNoneBtn( sal_Bool bEnable )
+{
+ if ( bEnable )
+ {
+ if ( !mpNoneBtn )
+ {
+ mpNoneBtn = new PushButton( this, WB_NOPOINTERFOCUS );
+ XubString aNoneText( SvtResId( STR_SVT_CALENDAR_NONE ) );
+ mpNoneBtn->SetText( aNoneText );
+ Size aSize;
+ aSize.Width() = mpNoneBtn->GetCtrlTextWidth( mpNoneBtn->GetText() );
+ aSize.Height() = mpNoneBtn->GetTextHeight();
+ aSize.Width() += CALFIELD_EXTRA_BUTTON_WIDTH;
+ aSize.Height() += CALFIELD_EXTRA_BUTTON_HEIGHT;
+ mpNoneBtn->SetSizePixel( aSize );
+ mpNoneBtn->Show();
+ }
+ }
+ else
+ {
+ if ( mpNoneBtn )
+ {
+ delete mpNoneBtn;
+ mpNoneBtn = NULL;
+ }
+ }
+
+ return mpNoneBtn;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplCFieldFloatWin::ArrangeButtons()
+{
+ long nBtnHeight = 0;
+ long nBtnWidth = 0;
+ Size aOutSize = GetOutputSizePixel();
+ if ( mpTodayBtn && mpNoneBtn )
+ {
+ Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
+ Size aNoneBtnSize = mpNoneBtn->GetSizePixel();
+ if ( aTodayBtnSize.Width() < aNoneBtnSize.Width() )
+ aTodayBtnSize.Width() = aNoneBtnSize.Width();
+ else
+ aNoneBtnSize.Width() = aTodayBtnSize.Width();
+ if ( aTodayBtnSize.Height() < aNoneBtnSize.Height() )
+ aTodayBtnSize.Height() = aNoneBtnSize.Height();
+ else
+ aNoneBtnSize.Height() = aTodayBtnSize.Height();
+
+ nBtnWidth = aTodayBtnSize.Width() + aNoneBtnSize.Width() + CALFIELD_SEP_X;
+ nBtnHeight = aTodayBtnSize.Height();
+ long nX = (aOutSize.Width()-nBtnWidth)/2;
+ long nY = aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP;
+ mpTodayBtn->SetPosSizePixel( Point( nX, nY ), aTodayBtnSize );
+ nX += aTodayBtnSize.Width() + CALFIELD_SEP_X;
+ mpNoneBtn->SetPosSizePixel( Point( nX, nY ), aNoneBtnSize );
+ }
+ else if ( mpTodayBtn )
+ {
+ Size aTodayBtnSize = mpTodayBtn->GetSizePixel();
+ nBtnWidth = aTodayBtnSize.Width();
+ nBtnHeight = aTodayBtnSize.Height();
+ mpTodayBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
+ }
+ else if ( mpNoneBtn )
+ {
+ Size aNoneBtnSize = mpNoneBtn->GetSizePixel();
+ nBtnWidth = aNoneBtnSize.Width();
+ nBtnHeight = aNoneBtnSize.Height();
+ mpNoneBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) );
+ }
+
+ if ( nBtnHeight )
+ {
+ if ( !mpFixedLine )
+ {
+ mpFixedLine = new FixedLine( this );
+ mpFixedLine->Show();
+ }
+ long nLineWidth = aOutSize.Width()-(CALFIELD_BORDERLINE_X*2);
+ mpFixedLine->SetPosSizePixel( (aOutSize.Width()-nLineWidth)/2, aOutSize.Height()+((CALFIELD_BORDER_YTOP-2)/2),
+ nLineWidth, 2, WINDOW_POSSIZE_POSSIZE );
+ aOutSize.Height() += nBtnHeight + (CALFIELD_BORDER_Y*2) + CALFIELD_BORDER_YTOP;
+ SetOutputSizePixel( aOutSize );
+ }
+ else
+ {
+ if ( mpFixedLine )
+ {
+ delete mpFixedLine;
+ mpFixedLine = NULL;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long ImplCFieldFloatWin::Notify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
+ mpCalendar->Select();
+ }
+
+ return FloatingWindow::Notify( rNEvt );
+}
+
+// =======================================================================
+
+CalendarField::CalendarField( Window* pParent, WinBits nWinStyle ) :
+ DateField( pParent, nWinStyle ),
+ maDefaultDate( 0, 0, 0 )
+{
+ mpFloatWin = NULL;
+ mpCalendar = NULL;
+ mnCalendarStyle = 0;
+ mbToday = sal_False;
+ mbNone = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+CalendarField::CalendarField( Window* pParent, const ResId& rResId ) :
+ DateField( pParent, rResId ),
+ maDefaultDate( 0, 0, 0 )
+{
+ mpFloatWin = NULL;
+ mpCalendar = NULL;
+ mnCalendarStyle = 0;
+ mbToday = sal_False;
+ mbNone = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+CalendarField::~CalendarField()
+{
+ if ( mpFloatWin )
+ {
+ delete mpCalendar;
+ delete mpFloatWin;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( CalendarField, ImplSelectHdl, Calendar*, pCalendar )
+{
+ if ( !pCalendar->IsTravelSelect() )
+ {
+ mpFloatWin->EndPopupMode();
+ EndDropDown();
+ GrabFocus();
+ Date aNewDate = mpCalendar->GetSelectDate( 0 );
+ if ( IsEmptyDate() || ( aNewDate != GetDate() ) )
+ {
+ SetDate( aNewDate );
+ SetModifyFlag();
+ Modify();
+ }
+ Select();
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( CalendarField, ImplClickHdl, PushButton*, pBtn )
+{
+ mpFloatWin->EndPopupMode();
+ EndDropDown();
+ GrabFocus();
+
+ if ( pBtn == mpTodayBtn )
+ {
+ Date aToday;
+ if ( (aToday != GetDate()) || IsEmptyDate() )
+ {
+ SetDate( aToday );
+ SetModifyFlag();
+ Modify();
+ }
+ }
+ else if ( pBtn == mpNoneBtn )
+ {
+ if ( !IsEmptyDate() )
+ {
+ SetEmptyDate();
+ SetModifyFlag();
+ Modify();
+ }
+ }
+ Select();
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( CalendarField, ImplPopupModeEndHdl, FloatingWindow*, EMPTYARG )
+{
+ EndDropDown();
+ GrabFocus();
+ mpCalendar->EndSelection();
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void CalendarField::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool CalendarField::ShowDropDown( sal_Bool bShow )
+{
+ if ( bShow )
+ {
+ Calendar* pCalendar = GetCalendar();
+
+ Date aDate = GetDate();
+ if ( IsEmptyDate() || !aDate.IsValid() )
+ {
+ if ( maDefaultDate.IsValid() )
+ aDate = maDefaultDate;
+ else
+ aDate = Date();
+ }
+ if ( pCalendar->GetStyle() & (WB_RANGESELECT | WB_MULTISELECT) )
+ {
+ pCalendar->SetNoSelection();
+ pCalendar->SelectDate( aDate );
+ }
+ pCalendar->SetCurDate( aDate );
+ Point aPos( GetParent()->OutputToScreenPixel( GetPosPixel() ) );
+ Rectangle aRect( aPos, GetSizePixel() );
+ aRect.Bottom() -= 1;
+ mpCalendar->SetOutputSizePixel( mpCalendar->CalcWindowSizePixel() );
+ mpFloatWin->SetOutputSizePixel( mpCalendar->GetSizePixel() );
+ mpFloatWin->SetCalendar( mpCalendar );
+ mpTodayBtn = mpFloatWin->EnableTodayBtn( mbToday );
+ mpNoneBtn = mpFloatWin->EnableNoneBtn( mbNone );
+ if ( mpTodayBtn )
+ mpTodayBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
+ if ( mpNoneBtn )
+ mpNoneBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) );
+ mpFloatWin->ArrangeButtons();
+ mpCalendar->EnableCallEverySelect();
+ mpCalendar->StartSelection();
+ mpCalendar->GrabFocus();
+ mpCalendar->Show();
+ mpFloatWin->StartPopupMode( aRect, FLOATWIN_POPUPMODE_NOFOCUSCLOSE|FLOATWIN_POPUPMODE_DOWN );
+ }
+ else
+ {
+ mpFloatWin->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
+ mpCalendar->EndSelection();
+ EndDropDown();
+ }
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+Calendar* CalendarField::CreateCalendar( Window* pParent )
+{
+ return new Calendar( pParent, mnCalendarStyle | WB_TABSTOP );
+}
+
+// -----------------------------------------------------------------------
+
+Calendar* CalendarField::GetCalendar()
+{
+ if ( !mpFloatWin )
+ {
+ mpFloatWin = new ImplCFieldFloatWin( this );
+ mpFloatWin->SetPopupModeEndHdl( LINK( this, CalendarField, ImplPopupModeEndHdl ) );
+ mpCalendar = CreateCalendar( mpFloatWin );
+ mpCalendar->SetPosPixel( Point() );
+ mpCalendar->SetSelectHdl( LINK( this, CalendarField, ImplSelectHdl ) );
+ }
+
+ return mpCalendar;
+}
+
+// -----------------------------------------------------------------------
+
+void CalendarField::StateChanged( StateChangedType nStateChange )
+{
+ DateField::StateChanged( nStateChange );
+
+ if ( ( nStateChange == STATE_CHANGE_STYLE ) && GetSubEdit() )
+ {
+ WinBits nAllAlignmentBits = ( WB_LEFT | WB_CENTER | WB_RIGHT | WB_TOP | WB_VCENTER | WB_BOTTOM );
+ WinBits nMyAlignment = GetStyle() & nAllAlignmentBits;
+ GetSubEdit()->SetStyle( ( GetSubEdit()->GetStyle() & ~nAllAlignmentBits ) | nMyAlignment );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */