summaryrefslogtreecommitdiff
path: root/svtools/source/control
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/control')
-rwxr-xr-xsvtools/source/control/asynclink.cxx139
-rwxr-xr-xsvtools/source/control/calendar.cxx3035
-rwxr-xr-xsvtools/source/control/calendar.src74
-rwxr-xr-xsvtools/source/control/collatorres.cxx126
-rwxr-xr-xsvtools/source/control/ctrlbox.cxx1505
-rwxr-xr-xsvtools/source/control/ctrlbox.src232
-rwxr-xr-xsvtools/source/control/ctrltool.cxx1011
-rwxr-xr-xsvtools/source/control/ctrltool.src144
-rwxr-xr-xsvtools/source/control/filectrl.cxx231
-rwxr-xr-xsvtools/source/control/filectrl.src50
-rwxr-xr-xsvtools/source/control/filectrl2.cxx94
-rw-r--r--svtools/source/control/fileurlbox.cxx124
-rw-r--r--svtools/source/control/fixedhyper.cxx233
-rwxr-xr-xsvtools/source/control/fmtfield.cxx1398
-rwxr-xr-xsvtools/source/control/headbar.cxx1651
-rw-r--r--svtools/source/control/hyperlabel.cxx270
-rwxr-xr-xsvtools/source/control/indexentryres.cxx131
-rwxr-xr-xsvtools/source/control/inettbc.cxx1365
-rwxr-xr-xsvtools/source/control/prgsbar.cxx258
-rwxr-xr-xsvtools/source/control/roadmap.cxx1018
-rwxr-xr-xsvtools/source/control/ruler.cxx3185
-rwxr-xr-xsvtools/source/control/scriptedtext.cxx392
-rwxr-xr-xsvtools/source/control/scrwin.cxx572
-rwxr-xr-xsvtools/source/control/stdctrl.cxx96
-rwxr-xr-xsvtools/source/control/stdmenu.cxx510
-rwxr-xr-xsvtools/source/control/svxbox.cxx617
-rwxr-xr-xsvtools/source/control/tabbar.cxx2745
-rwxr-xr-xsvtools/source/control/taskbar.cxx589
-rwxr-xr-xsvtools/source/control/taskbox.cxx349
-rwxr-xr-xsvtools/source/control/taskmisc.cxx377
-rwxr-xr-xsvtools/source/control/taskstat.cxx653
-rw-r--r--svtools/source/control/toolbarmenu.cxx1805
-rw-r--r--svtools/source/control/toolbarmenuacc.cxx1003
-rw-r--r--svtools/source/control/toolbarmenuimp.hxx314
-rw-r--r--svtools/source/control/urlcontrol.cxx95
-rw-r--r--svtools/source/control/valueacc.cxx1258
-rwxr-xr-xsvtools/source/control/valueimp.hxx330
-rw-r--r--svtools/source/control/valueset.cxx2758
38 files changed, 30737 insertions, 0 deletions
diff --git a/svtools/source/control/asynclink.cxx b/svtools/source/control/asynclink.cxx
new file mode 100755
index 000000000000..7231470528d5
--- /dev/null
+++ b/svtools/source/control/asynclink.cxx
@@ -0,0 +1,139 @@
+/*************************************************************************
+ *
+ * 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 <svtools/asynclink.hxx>
+#include <vos/mutex.hxx>
+#include <tools/debug.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/svapp.hxx>
+
+//--------------------------------------------------------------------
+namespace svtools {
+
+void AsynchronLink::CreateMutex()
+{
+ if( !_pMutex ) _pMutex = new vos::OMutex;
+}
+
+void AsynchronLink::Call( void* pObj, sal_Bool
+#ifdef DBG_UTIL
+bAllowDoubles
+#endif
+, sal_Bool bUseTimer )
+{
+#ifdef DBG_UTIL
+ if ( bUseTimer || !_bInCall )
+ DBG_WARNING( "Recursives Call. Eher ueber Timer. TLX Fragen" );
+#endif
+ if( _aLink.IsSet() )
+ {
+ _pArg = pObj;
+ DBG_ASSERT( bAllowDoubles ||
+ ( !_nEventId && ( !_pTimer || !_pTimer->IsActive() ) ),
+ "Schon ein Call unterwegs" );
+ if( _nEventId )
+ {
+ if( _pMutex ) _pMutex->acquire();
+ Application::RemoveUserEvent( _nEventId );
+ if( _pMutex ) _pMutex->release();
+ }
+ if( _pTimer )_pTimer->Stop();
+ if( bUseTimer )
+ {
+ if( !_pTimer )
+ {
+ _pTimer = new Timer;
+ _pTimer->SetTimeout( 0 );
+ _pTimer->SetTimeoutHdl( STATIC_LINK(
+ this, AsynchronLink, HandleCall) );
+ }
+ _pTimer->Start();
+ }
+ else
+ {
+ if( _pMutex ) _pMutex->acquire();
+ Application::PostUserEvent( _nEventId, STATIC_LINK( this, AsynchronLink, HandleCall), 0 );
+ if( _pMutex ) _pMutex->release();
+ }
+ }
+}
+
+AsynchronLink::~AsynchronLink()
+{
+ if( _nEventId )
+ {
+ Application::RemoveUserEvent( _nEventId );
+ }
+ delete _pTimer;
+ if( _pDeleted ) *_pDeleted = sal_True;
+ delete _pMutex;
+}
+
+IMPL_STATIC_LINK( AsynchronLink, HandleCall, void*, EMPTYARG )
+{
+ if( pThis->_pMutex ) pThis->_pMutex->acquire();
+ pThis->_nEventId = 0;
+ if( pThis->_pMutex ) pThis->_pMutex->release();
+ pThis->Call_Impl( pThis->_pArg );
+ return 0;
+}
+
+void AsynchronLink::ForcePendingCall()
+{
+ ClearPendingCall();
+ Call_Impl( _pArg );
+}
+
+void AsynchronLink::ClearPendingCall()
+{
+ if( _pMutex ) _pMutex->acquire();
+ if( _nEventId )
+ {
+ Application::RemoveUserEvent( _nEventId );
+ _nEventId = 0;
+ }
+ if( _pMutex ) _pMutex->release();
+ if( _pTimer ) _pTimer->Stop();
+}
+
+void AsynchronLink::Call_Impl( void* pArg )
+{
+ _bInCall = sal_True;
+ sal_Bool bDeleted = sal_False;
+ _pDeleted = &bDeleted;
+ _aLink.Call( pArg );
+ if( !bDeleted )
+ {
+ _bInCall = sal_False;
+ _pDeleted = 0;
+ }
+}
+
+}
diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx
new file mode 100755
index 000000000000..17790d1ad4c8
--- /dev/null
+++ b/svtools/source/control/calendar.cxx
@@ -0,0 +1,3035 @@
+/*************************************************************************
+ *
+ * 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 );
+ }
+}
+
diff --git a/svtools/source/control/calendar.src b/svtools/source/control/calendar.src
new file mode 100755
index 000000000000..4dd31765a5c1
--- /dev/null
+++ b/svtools/source/control/calendar.src
@@ -0,0 +1,74 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include <svtools/svtools.hrc>
+String STR_SVT_CALENDAR_DAY
+{
+ Text [ en-US ] = "Day" ;
+};
+String STR_SVT_CALENDAR_WEEK
+{
+ Text [ en-US ] = "Week" ;
+};
+String STR_SVT_CALENDAR_TODAY
+{
+ Text [ en-US ] = "Today" ;
+};
+String STR_SVT_CALENDAR_NONE
+{
+ Text [ en-US ] = "None" ;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svtools/source/control/collatorres.cxx b/svtools/source/control/collatorres.cxx
new file mode 100755
index 000000000000..4514ec918b24
--- /dev/null
+++ b/svtools/source/control/collatorres.cxx
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * 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 <svtools/svtdata.hxx>
+#include <svtools/svtools.hrc>
+#include <svtools/collatorres.hxx>
+
+// -------------------------------------------------------------------------
+//
+// wrapper for locale specific translations data of collator algorithm
+//
+// -------------------------------------------------------------------------
+
+class CollatorRessourceData
+{
+ friend class CollatorRessource;
+ private: /* data */
+ String ma_Name;
+ String ma_Translation;
+ private: /* member functions */
+ CollatorRessourceData () {}
+ public:
+ CollatorRessourceData ( const String &r_Algorithm, const String &r_Translation)
+ : ma_Name (r_Algorithm), ma_Translation (r_Translation) {}
+
+ const String& GetAlgorithm () const { return ma_Name; }
+
+ const String& GetTranslation () const { return ma_Translation; }
+
+ ~CollatorRessourceData () {}
+
+ CollatorRessourceData& operator= (const CollatorRessourceData& r_From)
+ {
+ ma_Name = r_From.GetAlgorithm();
+ ma_Translation = r_From.GetTranslation();
+ return *this;
+ }
+};
+
+// -------------------------------------------------------------------------
+//
+// implementation of the collator-algorithm-name translation
+//
+// -------------------------------------------------------------------------
+
+#define COLLATOR_RESSOURCE_COUNT (STR_SVT_COLLATE_END - STR_SVT_COLLATE_START + 1)
+
+CollatorRessource::CollatorRessource()
+{
+ mp_Data = new CollatorRessourceData[COLLATOR_RESSOURCE_COUNT];
+
+ #define ASCSTR(str) String(RTL_CONSTASCII_USTRINGPARAM(str))
+ #define RESSTR(rid) String(SvtResId(rid))
+
+
+ mp_Data[0] = CollatorRessourceData (ASCSTR("alphanumeric"), RESSTR(STR_SVT_COLLATE_ALPHANUMERIC));
+ mp_Data[1] = CollatorRessourceData (ASCSTR("charset"), RESSTR(STR_SVT_COLLATE_CHARSET));
+ mp_Data[2] = CollatorRessourceData (ASCSTR("dict"), RESSTR(STR_SVT_COLLATE_DICTIONARY));
+ mp_Data[3] = CollatorRessourceData (ASCSTR("normal"), RESSTR(STR_SVT_COLLATE_NORMAL));
+ mp_Data[4] = CollatorRessourceData (ASCSTR("pinyin"), RESSTR(STR_SVT_COLLATE_PINYIN));
+ mp_Data[5] = CollatorRessourceData (ASCSTR("radical"), RESSTR(STR_SVT_COLLATE_RADICAL));
+ mp_Data[6] = CollatorRessourceData (ASCSTR("stroke"), RESSTR(STR_SVT_COLLATE_STROKE));
+ mp_Data[7] = CollatorRessourceData (ASCSTR("unicode"), RESSTR(STR_SVT_COLLATE_UNICODE));
+ mp_Data[8] = CollatorRessourceData (ASCSTR("zhuyin"), RESSTR(STR_SVT_COLLATE_ZHUYIN));
+ mp_Data[9] = CollatorRessourceData (ASCSTR("phonebook"), RESSTR(STR_SVT_COLLATE_PHONEBOOK));
+ mp_Data[10] = CollatorRessourceData (ASCSTR("phonetic (alphanumeric first)"), RESSTR(STR_SVT_COLLATE_PHONETIC_F));
+ mp_Data[11] = CollatorRessourceData (ASCSTR("phonetic (alphanumeric last)"), RESSTR(STR_SVT_COLLATE_PHONETIC_L));
+}
+
+CollatorRessource::~CollatorRessource()
+{
+ delete[] mp_Data;
+}
+
+const String&
+CollatorRessource::GetTranslation (const String &r_Algorithm)
+{
+ xub_StrLen nIndex = r_Algorithm.Search('.');
+ String aLocaleFreeAlgorithm;
+
+ if (nIndex == STRING_NOTFOUND)
+ {
+ aLocaleFreeAlgorithm = r_Algorithm;
+ }
+ else
+ {
+ nIndex += 1;
+ aLocaleFreeAlgorithm = String(r_Algorithm, nIndex, r_Algorithm.Len() - nIndex);
+ }
+
+ for (sal_uInt32 i = 0; i < COLLATOR_RESSOURCE_COUNT; i++)
+ {
+ if (aLocaleFreeAlgorithm == mp_Data[i].GetAlgorithm())
+ return mp_Data[i].GetTranslation();
+ }
+
+ return r_Algorithm;
+}
+
diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx
new file mode 100755
index 000000000000..219b5428edeb
--- /dev/null
+++ b/svtools/source/control/ctrlbox.cxx
@@ -0,0 +1,1505 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _CTRLBOX_CXX
+#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/field.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotools/charclass.hxx>
+
+#include <svtools/svtdata.hxx>
+#include <svtools/svtools.hrc>
+#include <svtools/ctrlbox.hxx>
+#include <svtools/ctrltool.hxx>
+
+#include <vcl/i18nhelp.hxx>
+
+#define IMGTEXTSPACE 2
+#define EXTRAFONTSIZE 5
+
+static sal_Unicode aImplSymbolFontText[] = {0xF021,0xF032,0xF043,0xF054,0xF065,0xF076,0xF0B7,0xF0C8,0};
+static sal_Unicode aImplStarSymbolText[] = {0x2706,0x2704,0x270D,0xE033,0x2211,0x2288,0};
+
+// ========================================================================
+// ColorListBox
+// ========================================================================
+
+// --------------------
+// - ImplColorListData -
+// --------------------
+
+struct ImplColorListData
+{
+ Color aColor;
+ sal_Bool bColor;
+
+ ImplColorListData() : aColor( COL_BLACK ) { bColor = sal_False; }
+ ImplColorListData( const Color& rColor ) : aColor( rColor ) { bColor = sal_True; }
+};
+
+DECLARE_LIST( ImpColorList, ImplColorListData* )
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::ImplInit()
+{
+ pColorList = new ImpColorList( 256, 64 );
+ aImageSize.Width() = GetTextWidth( XubString( RTL_CONSTASCII_USTRINGPARAM( "xxx" ) ) );
+ aImageSize.Height() = GetTextHeight();
+ aImageSize.Height() -= 2;
+
+ EnableUserDraw( sal_True );
+ SetUserItemSize( aImageSize );
+}
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::ImplDestroyColorEntries()
+{
+ for ( sal_uInt16 n = (sal_uInt16) pColorList->Count(); n; )
+ {
+ ImplColorListData* pData = pColorList->GetObject( --n );
+ delete pData;
+ }
+ pColorList->Clear();
+}
+
+// -----------------------------------------------------------------------
+
+ColorListBox::ColorListBox( Window* pParent, WinBits nWinStyle ) :
+ ListBox( pParent, nWinStyle )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+ColorListBox::ColorListBox( Window* pParent, const ResId& rResId ) :
+ ListBox( pParent, rResId )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+ColorListBox::~ColorListBox()
+{
+ ImplDestroyColorEntries();
+ delete pColorList;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ColorListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
+{
+ nPos = ListBox::InsertEntry( rStr, nPos );
+ if ( nPos != LISTBOX_ERROR )
+ {
+ ImplColorListData* pData = new ImplColorListData;
+ pColorList->Insert( pData, nPos );
+ }
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ColorListBox::InsertEntry( const Color& rColor, const XubString& rStr,
+ sal_uInt16 nPos )
+{
+ nPos = ListBox::InsertEntry( rStr, nPos );
+ if ( nPos != LISTBOX_ERROR )
+ {
+ ImplColorListData* pData = new ImplColorListData( rColor );
+ pColorList->Insert( pData, nPos );
+ }
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::InsertAutomaticEntry()
+{
+ // insert the "Automatic"-entry always on the first position
+ InsertEntry( Color( COL_AUTO ), SvtResId( STR_SVT_AUTOMATIC_COLOR ), 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::RemoveEntry( sal_uInt16 nPos )
+{
+ ListBox::RemoveEntry( nPos );
+ delete pColorList->Remove( nPos );
+}
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::Clear()
+{
+ ImplDestroyColorEntries();
+ ListBox::Clear();
+}
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::CopyEntries( const ColorListBox& rBox )
+{
+ // Liste leeren
+ ImplDestroyColorEntries();
+
+ // Daten kopieren
+ sal_uInt16 nCount = (sal_uInt16) rBox.pColorList->Count();
+ for ( sal_uInt16 n = 0; n < nCount; n++ )
+ {
+ ImplColorListData* pData = rBox.pColorList->GetObject( n );
+ sal_uInt16 nPos = InsertEntry( rBox.GetEntry( n ), LISTBOX_APPEND );
+ if ( nPos != LISTBOX_ERROR )
+ pColorList->Insert( new ImplColorListData( *pData ), nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ColorListBox::GetEntryPos( const Color& rColor ) const
+{
+ for( sal_uInt16 n = (sal_uInt16) pColorList->Count(); n; )
+ {
+ ImplColorListData* pData = pColorList->GetObject( --n );
+ if ( pData->bColor && ( pData->aColor == rColor ) )
+ return n;
+ }
+ return LISTBOX_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+Color ColorListBox::GetEntryColor( sal_uInt16 nPos ) const
+{
+ Color aColor;
+ ImplColorListData* pData = pColorList->GetObject( nPos );
+ if ( pData && pData->bColor )
+ aColor = pData->aColor;
+ return aColor;
+}
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::UserDraw( const UserDrawEvent& rUDEvt )
+{
+ ImplColorListData* pData = pColorList->GetObject( rUDEvt.GetItemId() );
+ if ( pData )
+ {
+ if ( pData->bColor )
+ {
+ Point aPos( rUDEvt.GetRect().TopLeft() );
+ aPos.X() += 2;
+ aPos.Y() += ( rUDEvt.GetRect().GetHeight() - aImageSize.Height() ) / 2;
+ rUDEvt.GetDevice()->Push();
+ rUDEvt.GetDevice()->SetFillColor( pData->aColor );
+ rUDEvt.GetDevice()->SetLineColor( rUDEvt.GetDevice()->GetTextColor() );
+ rUDEvt.GetDevice()->DrawRect( Rectangle( aPos, aImageSize ) );
+ rUDEvt.GetDevice()->Pop();
+ ListBox::DrawEntry( rUDEvt, sal_False, sal_True, sal_False );
+ }
+ else
+ ListBox::DrawEntry( rUDEvt, sal_False, sal_True, sal_True );
+ }
+ else
+ ListBox::DrawEntry( rUDEvt, sal_True, sal_True, sal_False );
+}
+
+// =======================================================================
+// LineListBox
+// =======================================================================
+
+// -------------------
+// - ImpListListData -
+// -------------------
+
+struct ImpLineListData
+{
+ long nLine1;
+ long nLine2;
+ long nDistance;
+};
+
+DECLARE_LIST( ImpLineList, ImpLineListData* )
+
+// -----------------------------------------------------------------------
+
+inline const Color& LineListBox::GetPaintColor( void ) const
+{
+ return maPaintCol;
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::ImpGetLine( long nLine1, long nLine2, long nDistance,
+ Bitmap& rBmp, XubString& rStr )
+{
+ Size aSize = GetOutputSizePixel();
+ aSize.Width() -= 20;
+ aSize.Width() -= aTxtSize.Width();
+ aSize.Height() = aTxtSize.Height();
+
+ // SourceUnit nach Twips
+ if ( eSourceUnit == FUNIT_POINT )
+ {
+ nLine1 *= 20;
+ nLine2 *= 20;
+ nDistance *= 20;
+ }
+ else if ( eSourceUnit == FUNIT_MM )
+ {
+ nLine1 *= 14440;
+ nLine1 /= 254;
+ nLine2 *= 14440;
+ nLine2 /= 254;
+ nDistance *= 14440;
+ nDistance /= 254;
+ }
+
+ // Linien malen
+ aSize = aVirDev.PixelToLogic( aSize );
+ long nPix = aVirDev.PixelToLogic( Size( 0, 1 ) ).Height();
+ long n1 = nLine1 / 100;
+ long n2 = nLine2 / 100;
+ long nDist = nDistance / 100;
+ n1 += nPix-1;
+ n1 -= n1%nPix;
+ if ( n2 )
+ {
+ nDist += nPix-1;
+ nDist -= nDist%nPix;
+ n2 += nPix-1;
+ n2 -= n2%nPix;
+ }
+ long nVirHeight = n1+nDist+n2;
+ if ( nVirHeight > aSize.Height() )
+ aSize.Height() = nVirHeight;
+ // negative Breiten muss und darf man nicht painten
+ if ( aSize.Width() > 0 )
+ {
+ Size aVirSize = aVirDev.LogicToPixel( aSize );
+ if ( aVirDev.GetOutputSizePixel() != aVirSize )
+ aVirDev.SetOutputSizePixel( aVirSize );
+ aVirDev.SetFillColor( GetSettings().GetStyleSettings().GetFieldColor() );
+ aVirDev.DrawRect( Rectangle( Point(), aSize ) );
+
+ aVirDev.SetFillColor( GetPaintColor() );
+ aVirDev.DrawRect( Rectangle( 0, 0, aSize.Width(), n1-nPix ) );
+ if ( n2 )
+ {
+ aVirDev.DrawRect( Rectangle( 0, n1+nDist,
+ aSize.Width(), n1+nDist+n2-nPix ) );
+ }
+ rBmp = aVirDev.GetBitmap( Point(), Size( aSize.Width(), n1+nDist+n2 ) );
+ }
+ // Twips nach Unit
+ if ( eUnit == FUNIT_POINT )
+ {
+ nLine1 /= 20;
+ nLine2 /= 20;
+ nDistance /= 20;
+ rStr.AssignAscii( " pt" );
+ }
+ else if ( eUnit == FUNIT_MM )
+ {
+ nLine1 *= 254;
+ nLine1 /= 14400;
+ nLine2 *= 254;
+ nLine2 /= 14400;
+ nDistance *= 254;
+ nDistance /= 14400;
+ rStr.AssignAscii( " mm" );
+ }
+
+ String aNum( GetSettings().GetLocaleI18nHelper().GetNum( nLine1+nLine2+nDistance, 2 ) );
+ rStr.Insert( aNum, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::ImplInit()
+{
+ aTxtSize.Width() = GetTextWidth( XubString( RTL_CONSTASCII_USTRINGPARAM( "99,99 mm" ) ) );
+ aTxtSize.Height() = GetTextHeight();
+ pLineList = new ImpLineList;
+ eUnit = FUNIT_POINT;
+ eSourceUnit = FUNIT_POINT;
+
+ aVirDev.SetLineColor();
+ aVirDev.SetMapMode( MapMode( MAP_TWIP ) );
+
+ UpdatePaintLineColor();
+}
+
+// -----------------------------------------------------------------------
+
+LineListBox::LineListBox( Window* pParent, WinBits nWinStyle ) :
+ ListBox( pParent, nWinStyle ),
+ aColor( COL_BLACK ),
+ maPaintCol( COL_BLACK )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+LineListBox::LineListBox( Window* pParent, const ResId& rResId ) :
+ ListBox( pParent, rResId ),
+ aColor( COL_BLACK ),
+ maPaintCol( COL_BLACK )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+LineListBox::~LineListBox()
+{
+ sal_uLong n = 0;
+ sal_uLong nCount = pLineList->Count();
+ while ( n < nCount )
+ {
+ ImpLineListData* pData = pLineList->GetObject( n );
+ if ( pData )
+ delete pData;
+ n++;
+ }
+ delete pLineList;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 LineListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
+{
+ nPos = ListBox::InsertEntry( rStr, nPos );
+ if ( nPos != LISTBOX_ERROR )
+ pLineList->Insert( NULL, nPos );
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 LineListBox::InsertEntry( long nLine1, long nLine2, long nDistance,
+ sal_uInt16 nPos )
+{
+ XubString aStr;
+ Bitmap aBmp;
+ ImpGetLine( nLine1, nLine2, nDistance, aBmp, aStr );
+ nPos = ListBox::InsertEntry( aStr, aBmp, nPos );
+ if ( nPos != LISTBOX_ERROR )
+ {
+ ImpLineListData* pData = new ImpLineListData;
+ pData->nLine1 = nLine1;
+ pData->nLine2 = nLine2;
+ pData->nDistance = nDistance;
+ pLineList->Insert( pData, nPos );
+ }
+
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::RemoveEntry( sal_uInt16 nPos )
+{
+ ListBox::RemoveEntry( nPos );
+ ImpLineListData* pData = pLineList->Remove( nPos );
+ if ( pData )
+ delete pData;
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::Clear()
+{
+ sal_uLong n = 0;
+ sal_uLong nCount = pLineList->Count();
+ while ( n < nCount )
+ {
+ ImpLineListData* pData = pLineList->GetObject( n );
+ if ( pData )
+ delete pData;
+ n++;
+ }
+
+ pLineList->Clear();
+ ListBox::Clear();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 LineListBox::GetEntryPos( long nLine1, long nLine2,
+ long nDistance ) const
+{
+ sal_uLong n = 0;
+ sal_uLong nCount = pLineList->Count();
+ while ( n < nCount )
+ {
+ ImpLineListData* pData = pLineList->GetObject( n );
+ if ( pData )
+ {
+ if ( (pData->nLine1 == nLine1) &&
+ (pData->nLine2 == nLine2) &&
+ (pData->nDistance == nDistance) )
+ return (sal_uInt16)n;
+ }
+
+ n++;
+ }
+
+ return LISTBOX_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+long LineListBox::GetEntryLine1( sal_uInt16 nPos ) const
+{
+ ImpLineListData* pData = pLineList->GetObject( nPos );
+ if ( pData )
+ return pData->nLine1;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long LineListBox::GetEntryLine2( sal_uInt16 nPos ) const
+{
+ ImpLineListData* pData = pLineList->GetObject( nPos );
+ if ( pData )
+ return pData->nLine2;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long LineListBox::GetEntryDistance( sal_uInt16 nPos ) const
+{
+ ImpLineListData* pData = pLineList->GetObject( nPos );
+ if ( pData )
+ return pData->nDistance;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::UpdateLineColors( void )
+{
+ if( UpdatePaintLineColor() )
+ {
+ sal_uLong nCount = pLineList->Count();
+ if( !nCount )
+ return;
+
+ XubString aStr;
+ Bitmap aBmp;
+
+ // exchange entries which containing lines
+ SetUpdateMode( sal_False );
+
+ sal_uInt16 nSelEntry = GetSelectEntryPos();
+ for( sal_uLong n = 0 ; n < nCount ; ++n )
+ {
+ ImpLineListData* pData = pLineList->GetObject( n );
+ if( pData )
+ {
+ // exchange listbox data
+ ListBox::RemoveEntry( sal_uInt16( n ) );
+ ImpGetLine( pData->nLine1, pData->nLine2, pData->nDistance, aBmp, aStr );
+ ListBox::InsertEntry( aStr, aBmp, sal_uInt16( n ) );
+ }
+ }
+
+ if( nSelEntry != LISTBOX_ENTRY_NOTFOUND )
+ SelectEntryPos( nSelEntry );
+
+ SetUpdateMode( sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool LineListBox::UpdatePaintLineColor( void )
+{
+ sal_Bool bRet = sal_True;
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+ Color aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor );
+
+ bRet = aNewCol != maPaintCol;
+
+ if( bRet )
+ maPaintCol = aNewCol;
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ListBox::DataChanged( rDCEvt );
+
+ if( ( rDCEvt.GetType() == DATACHANGED_SETTINGS ) && ( rDCEvt.GetFlags() & SETTINGS_STYLE ) )
+ UpdateLineColors();
+}
+
+// ===================================================================
+// FontNameBox
+// ===================================================================
+
+struct ImplFontNameListData
+{
+ FontInfo maInfo;
+ sal_uInt16 mnType;
+
+ ImplFontNameListData( const FontInfo& rInfo,
+ sal_uInt16 nType ) :
+ maInfo( rInfo ),
+ mnType( nType )
+ {}
+};
+
+DECLARE_LIST( ImplFontList, ImplFontNameListData* )
+
+// -------------------------------------------------------------------
+
+FontNameBox::FontNameBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ InitBitmaps();
+ mpFontList = NULL;
+ mbWYSIWYG = sal_False;
+ mbSymbols = sal_False;
+}
+
+// -------------------------------------------------------------------
+
+FontNameBox::FontNameBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( pParent, rResId )
+{
+ InitBitmaps();
+ mpFontList = NULL;
+ mbWYSIWYG = sal_False;
+ mbSymbols = sal_False;
+}
+
+// -------------------------------------------------------------------
+
+FontNameBox::~FontNameBox()
+{
+ ImplDestroyFontList();
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ ComboBox::DataChanged( rDCEvt );
+
+ if( rDCEvt.GetType() == DATACHANGED_SETTINGS && ( rDCEvt.GetFlags() & SETTINGS_STYLE ) )
+ InitBitmaps();
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::InitBitmaps( void )
+{
+ sal_Bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
+
+ maImagePrinterFont = Image( SvtResId( bHC? RID_IMG_PRINTERFONT_HC : RID_IMG_PRINTERFONT ) );
+ maImageBitmapFont = Image( SvtResId( bHC? RID_IMG_BITMAPFONT_HC : RID_IMG_BITMAPFONT ) );
+ maImageScalableFont = Image( SvtResId( bHC? RID_IMG_SCALABLEFONT_HC : RID_IMG_SCALABLEFONT ) );
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::ImplDestroyFontList()
+{
+ if ( mpFontList )
+ {
+ ImplFontNameListData* pInfo = mpFontList->First();
+ while ( pInfo )
+ {
+ delete pInfo;
+ pInfo = mpFontList->Next();
+ }
+ delete mpFontList;
+ }
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::Fill( const FontList* pList )
+{
+ // store old text and clear box
+ XubString aOldText = GetText();
+ Clear();
+
+ ImplDestroyFontList();
+ mpFontList = new ImplFontList;
+
+ // insert fonts
+ sal_uInt16 nFontCount = pList->GetFontNameCount();
+ for ( sal_uInt16 i = 0; i < nFontCount; i++ )
+ {
+ const FontInfo& rFontInfo = pList->GetFontName( i );
+ sal_uLong nIndex = InsertEntry( rFontInfo.GetName() );
+ if ( nIndex != LISTBOX_ERROR )
+ {
+ sal_uInt16 nType = pList->GetFontNameType( i );
+ ImplFontNameListData* pData = new ImplFontNameListData( rFontInfo, nType );
+ mpFontList->Insert( pData, nIndex );
+ }
+ }
+
+ ImplCalcUserItemSize();
+
+ // restore text
+ if ( aOldText.Len() )
+ SetText( aOldText );
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::EnableWYSIWYG( sal_Bool bEnable )
+{
+ if ( bEnable != mbWYSIWYG )
+ {
+ mbWYSIWYG = bEnable;
+ EnableUserDraw( mbWYSIWYG | mbSymbols );
+ ImplCalcUserItemSize();
+ }
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::EnableSymbols( sal_Bool bEnable )
+{
+ if ( bEnable != mbSymbols )
+ {
+ mbSymbols = bEnable;
+ EnableUserDraw( mbWYSIWYG | mbSymbols );
+ ImplCalcUserItemSize();
+ }
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::ImplCalcUserItemSize()
+{
+ Size aUserItemSz;
+ if ( mbWYSIWYG && mpFontList )
+ {
+ sal_uInt16 nMaxLen = 0;
+ sal_Bool bSymbolFont = sal_False;
+ sal_Bool bStarSymbol = sal_False;
+ for ( sal_uInt16 n = GetEntryCount(); n; )
+ {
+ ImplFontNameListData* pData = mpFontList->GetObject( --n );
+ XubString aFontName = pData->maInfo.GetName();
+ if ( aFontName.Len() > nMaxLen )
+ nMaxLen = aFontName.Len();
+ if ( pData->maInfo.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
+ bSymbolFont = sal_True;
+ // starsymbol is a unicode font, but gets WYSIWIG symbols
+ if( aFontName.EqualsIgnoreCaseAscii( "starsymbol" )
+ || aFontName.EqualsIgnoreCaseAscii( "opensymbol" ) )
+ bSymbolFont = bStarSymbol = sal_True;
+ }
+
+ // guess maximimum width
+ Size aOneCharSz( GetTextWidth( String( 'X' ) ), GetTextHeight() );
+ Size aSz( aOneCharSz );
+ aSz.Width() *= nMaxLen;
+ // only XX% of width, because ListBox calculates the normal width...
+ aSz.Width() *= 1;
+ aSz.Width() /= 10;
+ if ( bSymbolFont )
+ {
+ int nLength = sizeof(aImplSymbolFontText)/sizeof(aImplSymbolFontText[0]) - 1;
+ int nLength2 = sizeof(aImplStarSymbolText)/sizeof(aImplStarSymbolText[0]) - 1;
+ if( bStarSymbol && (nLength < nLength2) )
+ nLength = nLength2;
+ aSz.Width() += aOneCharSz.Width() * nLength;
+ }
+ aSz.Height() *= 14;
+ aSz.Height() /= 10;
+ aUserItemSz = aSz;
+ }
+ if ( mbSymbols )
+ {
+ Size aSz = maImageScalableFont.GetSizePixel();
+ aUserItemSz.Width() += aSz.Width() + IMGTEXTSPACE;
+ if ( aSz.Height() > aUserItemSz.Height() )
+ aUserItemSz.Height() = aSz.Height();
+ }
+ SetUserItemSize( aUserItemSz );
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::UserDraw( const UserDrawEvent& rUDEvt )
+{
+ ImplFontNameListData* pData = mpFontList->GetObject( rUDEvt.GetItemId() );
+ const FontInfo& rInfo = pData->maInfo;
+ sal_uInt16 nType = pData->mnType;
+ Point aTopLeft = rUDEvt.GetRect().TopLeft();
+ long nX = aTopLeft.X();
+ long nH = rUDEvt.GetRect().GetHeight();
+
+ if ( mbSymbols )
+ {
+ nX += IMGTEXTSPACE;
+ Image* pImg = NULL;
+ if ( (nType & (FONTLIST_FONTNAMETYPE_PRINTER | FONTLIST_FONTNAMETYPE_SCREEN)) == FONTLIST_FONTNAMETYPE_PRINTER )
+ pImg = &maImagePrinterFont;
+ else if ( nType & FONTLIST_FONTNAMETYPE_SCALABLE )
+ pImg = &maImageScalableFont;
+ else
+ pImg = &maImageBitmapFont;
+
+ if ( pImg )
+ {
+ Point aPos( nX, aTopLeft.Y() + (nH-pImg->GetSizePixel().Height())/2 );
+ rUDEvt.GetDevice()->DrawImage( aPos, *pImg );
+ }
+
+ // X immer um gleiche Breite aendern, auch wenn kein Image ausgegeben.
+ nX += maImagePrinterFont.GetSizePixel().Width();
+ }
+
+ if ( mbWYSIWYG && mpFontList )
+ {
+ nX += IMGTEXTSPACE;
+
+ bool bSymbolFont = (rInfo.GetCharSet() == RTL_TEXTENCODING_SYMBOL);
+ // starsymbol is a unicode font, but cannot display its own name
+ const bool bOpenSymbol = rInfo.GetName().EqualsIgnoreCaseAscii( "starsymbol" )
+ || rInfo.GetName().EqualsIgnoreCaseAscii( "opensymbol" );
+ bSymbolFont |= bOpenSymbol;
+
+ if( bSymbolFont )
+ {
+ String aText( rInfo.GetName() );
+ aText.AppendAscii( " " );
+ Point aPos( nX, aTopLeft.Y() + (nH-rUDEvt.GetDevice()->GetTextHeight())/2 );
+ rUDEvt.GetDevice()->DrawText( aPos, aText );
+ nX += rUDEvt.GetDevice()->GetTextWidth( aText );
+ }
+
+ Color aTextColor = rUDEvt.GetDevice()->GetTextColor();
+ Font aOldFont( rUDEvt.GetDevice()->GetFont() );
+ Size aSize( aOldFont.GetSize() );
+ aSize.Height() += EXTRAFONTSIZE;
+ Font aFont( rInfo );
+ aFont.SetSize( aSize );
+ rUDEvt.GetDevice()->SetFont( aFont );
+ rUDEvt.GetDevice()->SetTextColor( aTextColor );
+
+ FontCharMap aFontCharMap;
+ bool bHasCharMap = rUDEvt.GetDevice()->GetFontCharMap( aFontCharMap );
+
+ String aString;
+ if( !bSymbolFont )
+ {
+ // preview the font name
+ aString = rInfo.GetName();
+
+ // reset font if the name cannot be display in the preview font
+ if( STRING_LEN != rUDEvt.GetDevice()->HasGlyphs( aFont, aString ) )
+ rUDEvt.GetDevice()->SetFont( aOldFont );
+ }
+ else if( bHasCharMap )
+ {
+ // use some sample characters available in the font
+ sal_Unicode aText[8];
+
+ // start just above the PUA used by most symbol fonts
+ sal_uInt32 cNewChar = 0xFF00;
+#ifdef QUARTZ
+ // on MacOSX there are too many non-presentable symbols above the codepoint 0x0192
+ if( !bOpenSymbol )
+ cNewChar = 0x0192;
+#endif
+ const int nMaxCount = sizeof(aText)/sizeof(*aText) - 1;
+ int nSkip = aFontCharMap.GetCharCount() / nMaxCount;
+ if( nSkip > 10 )
+ nSkip = 10;
+ else if( nSkip <= 0 )
+ nSkip = 1;
+ for( int i = 0; i < nMaxCount; ++i )
+ {
+ sal_uInt32 cOldChar = cNewChar;
+ for( int j = nSkip; --j >= 0; )
+ cNewChar = aFontCharMap.GetPrevChar( cNewChar );
+ if( cOldChar == cNewChar )
+ break;
+ aText[ i ] = static_cast<sal_Unicode>(cNewChar); // TODO: support UCS4 samples
+ aText[ i+1 ] = 0;
+ }
+
+ aString = String( aText );
+ }
+ else
+ {
+ const sal_Unicode* pText = aImplSymbolFontText;
+ if( bOpenSymbol )
+ pText = aImplStarSymbolText;
+
+ aString = String( pText );
+ }
+
+ long nTextHeight = rUDEvt.GetDevice()->GetTextHeight();
+ Point aPos( nX, aTopLeft.Y() + (nH-nTextHeight)/2 );
+ rUDEvt.GetDevice()->DrawText( aPos, aString );
+
+ rUDEvt.GetDevice()->SetFont( aOldFont );
+ DrawEntry( rUDEvt, sal_False, sal_False); // draw seperator
+ }
+ else
+ {
+ DrawEntry( rUDEvt, sal_True, sal_True );
+ }
+}
+
+// ===================================================================
+// FontStyleBox
+// ===================================================================
+
+FontStyleBox::FontStyleBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+}
+
+// -------------------------------------------------------------------
+
+FontStyleBox::FontStyleBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( pParent, rResId )
+{
+ aLastStyle = GetText();
+}
+
+// -------------------------------------------------------------------
+
+FontStyleBox::~FontStyleBox()
+{
+}
+
+// -------------------------------------------------------------------
+
+void FontStyleBox::Select()
+{
+ // keep text over fill operation
+ aLastStyle = GetText();
+ ComboBox::Select();
+}
+
+// -------------------------------------------------------------------
+
+void FontStyleBox::LoseFocus()
+{
+ // keep text over fill operation
+ aLastStyle = GetText();
+ ComboBox::LoseFocus();
+}
+
+// -------------------------------------------------------------------
+
+void FontStyleBox::Modify()
+{
+ CharClass aChrCls( ::comphelper::getProcessServiceFactory(),
+ GetSettings().GetLocale() );
+ XubString aStr = GetText();
+ sal_uInt16 nEntryCount = GetEntryCount();
+
+ if ( GetEntryPos( aStr ) == COMBOBOX_ENTRY_NOTFOUND )
+ {
+ aChrCls.toUpper( aStr );
+ for ( sal_uInt16 i = 0; i < nEntryCount; i++ )
+ {
+ XubString aEntryText = GetEntry( i );
+ aChrCls.toUpper( aEntryText );
+
+ if ( aStr == aEntryText )
+ {
+ SetText( GetEntry( i ) );
+ break;
+ }
+ }
+ }
+
+ ComboBox::Modify();
+}
+
+// -------------------------------------------------------------------
+
+void FontStyleBox::Fill( const XubString& rName, const FontList* pList )
+{
+ // note: this method must call ComboBox::SetText(),
+ // else aLastStyle will overwritten
+ // store prior selection position and clear box
+ XubString aOldText = GetText();
+ sal_uInt16 nPos = GetEntryPos( aOldText );
+ Clear();
+
+ // does a font with this name already exist?
+ sal_Handle hFontInfo = pList->GetFirstFontInfo( rName );
+ if ( hFontInfo )
+ {
+ XubString aStyleText;
+ FontWeight eLastWeight = WEIGHT_DONTKNOW;
+ FontItalic eLastItalic = ITALIC_NONE;
+ FontWidth eLastWidth = WIDTH_DONTKNOW;
+ sal_Bool bNormal = sal_False;
+ sal_Bool bItalic = sal_False;
+ sal_Bool bBold = sal_False;
+ sal_Bool bBoldItalic = sal_False;
+ sal_Bool bInsert = sal_False;
+ FontInfo aInfo;
+ while ( hFontInfo )
+ {
+ aInfo = pList->GetFontInfo( hFontInfo );
+
+ FontWeight eWeight = aInfo.GetWeight();
+ FontItalic eItalic = aInfo.GetItalic();
+ FontWidth eWidth = aInfo.GetWidthType();
+ // Only if the attributes are different, we insert the
+ // Font to avoid double Entries in different languages
+ if ( (eWeight != eLastWeight) || (eItalic != eLastItalic) ||
+ (eWidth != eLastWidth) )
+ {
+ if ( bInsert )
+ InsertEntry( aStyleText );
+
+ if ( eWeight <= WEIGHT_NORMAL )
+ {
+ if ( eItalic != ITALIC_NONE )
+ bItalic = sal_True;
+ else
+ bNormal = sal_True;
+ }
+ else
+ {
+ if ( eItalic != ITALIC_NONE )
+ bBoldItalic = sal_True;
+ else
+ bBold = sal_True;
+ }
+
+ // For wrong StyleNames we replace this with the correct once
+ aStyleText = pList->GetStyleName( aInfo );
+ bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
+ if ( !bInsert )
+ {
+ aStyleText = pList->GetStyleName( eWeight, eItalic );
+ bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
+ }
+
+ eLastWeight = eWeight;
+ eLastItalic = eItalic;
+ eLastWidth = eWidth;
+ }
+ else
+ {
+ if ( bInsert )
+ {
+ // If we have two names for the same attributes
+ // we prefer the translated standard names
+ const XubString& rAttrStyleText = pList->GetStyleName( eWeight, eItalic );
+ if ( rAttrStyleText != aStyleText )
+ {
+ XubString aTempStyleText = pList->GetStyleName( aInfo );
+ if ( rAttrStyleText == aTempStyleText )
+ aStyleText = rAttrStyleText;
+ bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
+ }
+ }
+ }
+
+ if ( !bItalic && (aStyleText == pList->GetItalicStr()) )
+ bItalic = sal_True;
+ else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
+ bBold = sal_True;
+ else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
+ bBoldItalic = sal_True;
+
+ hFontInfo = pList->GetNextFontInfo( hFontInfo );
+ }
+
+ if ( bInsert )
+ InsertEntry( aStyleText );
+
+ // Bestimmte Styles als Nachbildung
+ if ( bNormal )
+ {
+ if ( !bItalic )
+ InsertEntry( pList->GetItalicStr() );
+ if ( !bBold )
+ InsertEntry( pList->GetBoldStr() );
+ }
+ if ( !bBoldItalic )
+ {
+ if ( bNormal || bItalic || bBold )
+ InsertEntry( pList->GetBoldItalicStr() );
+ }
+ if ( aOldText.Len() )
+ {
+ if ( GetEntryPos( aLastStyle ) != LISTBOX_ENTRY_NOTFOUND )
+ ComboBox::SetText( aLastStyle );
+ else
+ {
+ if ( nPos >= GetEntryCount() )
+ ComboBox::SetText( GetEntry( 0 ) );
+ else
+ ComboBox::SetText( GetEntry( nPos ) );
+ }
+ }
+ }
+ else
+ {
+ // Wenn Font nicht, dann Standard-Styles einfuegen
+ InsertEntry( pList->GetNormalStr() );
+ InsertEntry( pList->GetItalicStr() );
+ InsertEntry( pList->GetBoldStr() );
+ InsertEntry( pList->GetBoldItalicStr() );
+ if ( aOldText.Len() )
+ {
+ if ( nPos > GetEntryCount() )
+ ComboBox::SetText( GetEntry( 0 ) );
+ else
+ ComboBox::SetText( GetEntry( nPos ) );
+ }
+ }
+}
+
+// ===================================================================
+// FontSizeBox
+// ===================================================================
+
+FontSizeBox::FontSizeBox( Window* pParent, WinBits nWinSize ) :
+ MetricBox( pParent, nWinSize )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+FontSizeBox::FontSizeBox( Window* pParent, const ResId& rResId ) :
+ MetricBox( pParent, rResId )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+FontSizeBox::~FontSizeBox()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::ImplInit()
+{
+ EnableAutocomplete( sal_False );
+
+ bRelativeMode = sal_False;
+ bPtRelative = sal_False;
+ bRelative = sal_False;
+ bStdSize = sal_False;
+ pFontList = NULL;
+
+ SetShowTrailingZeros( sal_False );
+ SetDecimalDigits( 1 );
+ SetMin( 20 );
+ SetMax( 9999 );
+ SetProminentEntryType( PROMINENT_MIDDLE );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::Reformat()
+{
+ FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
+ if ( !bRelativeMode || !aFontSizeNames.IsEmpty() )
+ {
+ long nNewValue = aFontSizeNames.Name2Size( GetText() );
+ if ( nNewValue)
+ {
+ mnLastValue = nNewValue;
+ return;
+ }
+ }
+
+ MetricBox::Reformat();
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::Modify()
+{
+ MetricBox::Modify();
+
+ if ( bRelativeMode )
+ {
+ XubString aStr = GetText();
+ aStr.EraseLeadingChars();
+
+ sal_Bool bNewMode = bRelative;
+ sal_Bool bOldPtRelMode = bPtRelative;
+
+ if ( bRelative )
+ {
+ bPtRelative = sal_False;
+ const xub_Unicode* pStr = aStr.GetBuffer();
+ while ( *pStr )
+ {
+ if ( ((*pStr < '0') || (*pStr > '9')) && (*pStr != '%') )
+ {
+ if ( ('-' == *pStr || '+' == *pStr) && !bPtRelative )
+ bPtRelative = sal_True;
+ else if ( bPtRelative && 'p' == *pStr && 't' == *++pStr )
+ ;
+ else
+ {
+ bNewMode = sal_False;
+ break;
+ }
+ }
+ pStr++;
+ }
+ }
+ else
+ {
+ if ( STRING_NOTFOUND != aStr.Search( '%' ) )
+ {
+ bNewMode = sal_True;
+ bPtRelative = sal_False;
+ }
+
+ if ( '-' == aStr.GetChar( 0 ) || '+' == aStr.GetChar( 0 ) )
+ {
+ bNewMode = sal_True;
+ bPtRelative = sal_True;
+ }
+ }
+
+ if ( bNewMode != bRelative || bPtRelative != bOldPtRelMode )
+ SetRelative( bNewMode );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::Fill( const FontInfo* pInfo, const FontList* pList )
+{
+ // remember for relative mode
+ pFontList = pList;
+
+ // no font sizes need to be set for relative mode
+ if ( bRelative )
+ return;
+
+ // query font sizes
+ const long* pTempAry;
+ const long* pAry = 0;
+
+ if( pInfo )
+ {
+ aFontInfo = *pInfo;
+ pAry = pList->GetSizeAry( *pInfo );
+ }
+ else
+ {
+ pAry = pList->GetStdSizeAry();
+ }
+
+ // first insert font size names (for simplified/traditional chinese)
+ FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
+ if ( pAry == pList->GetStdSizeAry() )
+ {
+ // for standard sizes we don't need to bother
+ if ( bStdSize && GetEntryCount() && aFontSizeNames.IsEmpty() )
+ return;
+ bStdSize = sal_True;
+ }
+ else
+ bStdSize = sal_False;
+
+ Selection aSelection = GetSelection();
+ XubString aStr = GetText();
+
+ Clear();
+ sal_uInt16 nPos = 0;
+
+ if ( !aFontSizeNames.IsEmpty() )
+ {
+ if ( pAry == pList->GetStdSizeAry() )
+ {
+ // for scalable fonts all font size names
+ sal_uLong nCount = aFontSizeNames.Count();
+ for( sal_uLong i = 0; i < nCount; i++ )
+ {
+ String aSizeName = aFontSizeNames.GetIndexName( i );
+ long nSize = aFontSizeNames.GetIndexSize( i );
+ ComboBox::InsertEntry( aSizeName, nPos );
+ ComboBox::SetEntryData( nPos, (void*)(-nSize) ); // mark as special
+ nPos++;
+ }
+ }
+ else
+ {
+ // for fixed size fonts only selectable font size names
+ pTempAry = pAry;
+ while ( *pTempAry )
+ {
+ String aSizeName = aFontSizeNames.Size2Name( *pTempAry );
+ if ( aSizeName.Len() )
+ {
+ ComboBox::InsertEntry( aSizeName, nPos );
+ ComboBox::SetEntryData( nPos, (void*)(-(*pTempAry)) ); // mark as special
+ nPos++;
+ }
+ pTempAry++;
+ }
+ }
+ }
+
+ // then insert numerical font size values
+ pTempAry = pAry;
+ while ( *pTempAry )
+ {
+ InsertValue( *pTempAry, FUNIT_NONE, nPos );
+ ComboBox::SetEntryData( nPos, (void*)(*pTempAry) );
+ nPos++;
+ pTempAry++;
+ }
+
+ SetText( aStr );
+ SetSelection( aSelection );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::EnableRelativeMode( sal_uInt16 nMin, sal_uInt16 nMax, sal_uInt16 nStep )
+{
+ bRelativeMode = sal_True;
+ nRelMin = nMin;
+ nRelMax = nMax;
+ nRelStep = nStep;
+ SetUnit( FUNIT_POINT );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::EnablePtRelativeMode( short nMin, short nMax, short nStep )
+{
+ bRelativeMode = sal_True;
+ nPtRelMin = nMin;
+ nPtRelMax = nMax;
+ nPtRelStep = nStep;
+ SetUnit( FUNIT_POINT );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::SetRelative( sal_Bool bNewRelative )
+{
+ if ( bRelativeMode )
+ {
+ Selection aSelection = GetSelection();
+ XubString aStr = GetText();
+ aStr.EraseLeadingChars();
+
+ if ( bNewRelative )
+ {
+ bRelative = sal_True;
+ bStdSize = sal_False;
+
+ if ( bPtRelative )
+ {
+ SetDecimalDigits( 1 );
+ SetMin( nPtRelMin );
+ SetMax( nPtRelMax );
+ SetUnit( FUNIT_POINT );
+
+ Clear();
+
+ short i = nPtRelMin, n = 0;
+ // JP 30.06.98: more than 100 values are not useful
+ while ( i <= nPtRelMax && n++ < 100 )
+ {
+ InsertValue( i );
+ i = i + nPtRelStep;
+ }
+ }
+ else
+ {
+ SetDecimalDigits( 0 );
+ SetMin( nRelMin );
+ SetMax( nRelMax );
+ SetCustomUnitText( '%' );
+ SetUnit( FUNIT_CUSTOM );
+
+ Clear();
+ sal_uInt16 i = nRelMin;
+ while ( i <= nRelMax )
+ {
+ InsertValue( i );
+ i = i + nRelStep;
+ }
+ }
+ }
+ else
+ {
+ bRelative = bPtRelative = sal_False;
+ SetDecimalDigits( 1 );
+ SetMin( 20 );
+ SetMax( 9999 );
+ SetUnit( FUNIT_POINT );
+ if ( pFontList )
+ Fill( &aFontInfo, pFontList );
+ }
+
+ SetText( aStr );
+ SetSelection( aSelection );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString FontSizeBox::CreateFieldText( sal_Int64 nValue ) const
+{
+ XubString sRet( MetricBox::CreateFieldText( nValue ) );
+ if ( bRelativeMode && bPtRelative && (0 <= nValue) && sRet.Len() )
+ sRet.Insert( '+', 0 );
+ return sRet;
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
+{
+ if ( !bRelative )
+ {
+ sal_Int64 nTempValue = MetricField::ConvertValue( nNewValue, GetBaseValue(), GetDecimalDigits(), eInUnit, GetUnit() );
+ FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
+ // conversion loses precision; however font sizes should
+ // never have a problem with that
+ String aName = aFontSizeNames.Size2Name( static_cast<long>(nTempValue) );
+ if ( aName.Len() && (GetEntryPos( aName ) != LISTBOX_ENTRY_NOTFOUND) )
+ {
+ mnLastValue = nTempValue;
+ SetText( aName );
+ mnFieldValue = mnLastValue;
+ SetEmptyFieldValueData( sal_False );
+ return;
+ }
+ }
+
+ MetricBox::SetValue( nNewValue, eInUnit );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::SetValue( sal_Int64 nNewValue )
+{
+ SetValue( nNewValue, FUNIT_NONE );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int64 FontSizeBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const
+{
+ if ( !bRelative )
+ {
+ sal_Int64 nComboVal = static_cast<sal_Int64>(reinterpret_cast<long>(ComboBox::GetEntryData( nPos )));
+ if ( nComboVal < 0 ) // marked as special?
+ {
+ return MetricField::ConvertValue( -nComboVal, mnBaseValue, GetDecimalDigits(),
+ meUnit, eOutUnit );
+ }
+ }
+
+ // do normal font size processing
+ sal_Int64 nRetValue = MetricBox::GetValue( nPos, eOutUnit );
+ return nRetValue;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int64 FontSizeBox::GetValue( FieldUnit eOutUnit ) const
+{
+ if ( !bRelative )
+ {
+ FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
+ sal_Int64 nValue = aFontSizeNames.Name2Size( GetText() );
+ if ( nValue)
+ return MetricField::ConvertValue( nValue, GetBaseValue(), GetDecimalDigits(), GetUnit(), eOutUnit );
+ }
+
+ return MetricBox::GetValue( eOutUnit );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int64 FontSizeBox::GetValue() const
+{
+ // implementation not inline, because it is a virtual function
+ return GetValue( FUNIT_NONE );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
+{
+ if ( !bRelative )
+ {
+ sal_Int64 nTempValue = MetricField::ConvertValue( nNewValue, GetBaseValue(), GetDecimalDigits(), eInUnit, GetUnit() );
+ FontSizeNames aFontSizeNames( GetSettings().GetUILanguage() );
+ // conversion loses precision
+ // however font sizes should never have a problem with that
+ String aName = aFontSizeNames.Size2Name( static_cast<long>(nTempValue) );
+ if ( aName.Len() && (GetEntryPos( aName ) != LISTBOX_ENTRY_NOTFOUND) )
+ {
+ mnLastValue = nTempValue;
+ SetText( aName );
+ return;
+ }
+ }
+
+ MetricBox::SetUserValue( nNewValue, eInUnit );
+}
+
diff --git a/svtools/source/control/ctrlbox.src b/svtools/source/control/ctrlbox.src
new file mode 100755
index 000000000000..95440c905d89
--- /dev/null
+++ b/svtools/source/control/ctrlbox.src
@@ -0,0 +1,232 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+#include <svtools/svtools.hrc>
+
+#ifndef IMAGE_STDBTN_COLOR
+#define IMAGE_STDBTN_COLOR Color { Red = 0xFFFF; Green = 0x0000; Blue = 0xFFFF; }
+#endif
+
+
+IMAGE RID_IMG_SCALABLEFONT
+{
+ ImageBitmap = Bitmap { File = "scalfont.bmp" ; };
+ MaskColor = IMAGE_STDBTN_COLOR ;
+};
+
+IMAGE RID_IMG_SCALABLEFONT_HC
+{
+ ImageBitmap = Bitmap { File = "scalfont_h.bmp" ; };
+ MaskColor = IMAGE_STDBTN_COLOR ;
+};
+
+IMAGE RID_IMG_PRINTERFONT
+{
+ ImageBitmap = Bitmap { File = "prnfont.bmp" ; };
+ MaskColor = IMAGE_STDBTN_COLOR ;
+};
+
+IMAGE RID_IMG_PRINTERFONT_HC
+{
+ ImageBitmap = Bitmap { File = "prnfont_h.bmp" ; };
+ MaskColor = IMAGE_STDBTN_COLOR ;
+};
+
+IMAGE RID_IMG_BITMAPFONT
+{
+ ImageBitmap = Bitmap { File = "bmpfont.bmp" ; };
+ MaskColor = IMAGE_STDBTN_COLOR ;
+};
+
+IMAGE RID_IMG_BITMAPFONT_HC
+{
+ ImageBitmap = Bitmap { File = "bmpfont_h.bmp" ; };
+ MaskColor = IMAGE_STDBTN_COLOR ;
+};
+
+String STR_SVT_AUTOMATIC_COLOR
+{
+ Text [ en-US ] = "Automatic";
+};
+
+/*
+ * ressources for CollatorRessource / CollatorRessourceData resp.
+ */
+
+String STR_SVT_COLLATE_ALPHANUMERIC
+{
+ /* alphanumeric sorting algorithm */
+ Text [ en-US ] = "Alphanumeric";
+};
+
+String STR_SVT_COLLATE_NORMAL
+{
+ /* default or normal sorting algorithm */
+ Text [ en-US ] = "Normal";
+};
+
+String STR_SVT_COLLATE_CHARSET
+{
+ /* default or normal sorting algorithm */
+ Text [ en-US ] = "Character set";
+};
+
+String STR_SVT_COLLATE_DICTIONARY
+{
+ /* german dictionary word order / sorting */
+ Text [ en-US ] = "Dictionary";
+};
+
+String STR_SVT_COLLATE_PINYIN
+{
+ /* chinese sorting algorithm */
+ Text [ en-US ] = "Pinyin";
+};
+
+String STR_SVT_COLLATE_STROKE
+{
+ /* chinese sorting algorithm */
+ Text [ en-US ] = "Stroke";
+};
+
+String STR_SVT_COLLATE_RADICAL
+{
+ /* chinese sorting algorithm */
+ Text [ en-US ] = "Radical";
+};
+
+String STR_SVT_COLLATE_UNICODE
+{
+ /* sorting according to the unicode code point of the character */
+ Text [ en-US ] = "Unicode";
+};
+
+String STR_SVT_COLLATE_ZHUYIN
+{
+ /* chinese sorting algorithm */
+ Text [ en-US ] = "Zhuyin";
+};
+
+String STR_SVT_COLLATE_PHONEBOOK
+{
+ /* phone book sorting algorithm. e.g. German */
+ Text [ en-US ] = "Phone book";
+};
+
+String STR_SVT_COLLATE_PHONETIC_F
+{
+ Text [ en-US ] = "Phonetic (alphanumeric first)";
+};
+
+String STR_SVT_COLLATE_PHONETIC_L
+{
+ Text [ en-US ] = "Phonetic (alphanumeric last)";
+};
+
+String STR_SVT_INDEXENTRY_ALPHANUMERIC
+{
+ /* alphanumeric indexentry algorithm */
+ Text [ en-US ] = "Alphanumeric";
+};
+
+String STR_SVT_INDEXENTRY_DICTIONARY
+{
+ /* korean dictionary indexentry algorithm */
+ Text [ en-US ] = "Dictionary";
+};
+
+String STR_SVT_INDEXENTRY_PINYIN
+{
+ /* chinese sorting algorithm */
+ Text [ en-US ] = "Pinyin";
+};
+
+String STR_SVT_INDEXENTRY_RADICAL
+{
+ /* chinese indexentry algorithm */
+ Text [ en-US ] = "Radical";
+};
+
+String STR_SVT_INDEXENTRY_STROKE
+{
+ /* chinese indexentry algorithm */
+ Text [ en-US ] = "Stroke";
+};
+
+String STR_SVT_INDEXENTRY_ZHUYIN
+{
+ /* chinese indexentry algorithm */
+ Text [ en-US ] = "Zhuyin";
+};
+
+String STR_SVT_INDEXENTRY_PHONETIC_FS
+{
+ Text [ en-US ] = "Phonetic (alphanumeric first, grouped by syllables)";
+};
+
+String STR_SVT_INDEXENTRY_PHONETIC_FC
+{
+ Text [ en-US ] = "Phonetic (alphanumeric first, grouped by consonants)";
+};
+
+String STR_SVT_INDEXENTRY_PHONETIC_LS
+{
+ Text [ en-US ] = "Phonetic (alphanumeric last, grouped by syllables)";
+};
+
+String STR_SVT_INDEXENTRY_PHONETIC_LC
+{
+ Text [ en-US ] = "Phonetic (alphanumeric last, grouped by consonants)";
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svtools/source/control/ctrltool.cxx b/svtools/source/control/ctrltool.cxx
new file mode 100755
index 000000000000..1314f416eec6
--- /dev/null
+++ b/svtools/source/control/ctrltool.cxx
@@ -0,0 +1,1011 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define CTRLTOOL_CXX
+
+#include <string.h>
+
+#include <tools/debug.hxx>
+#include <i18npool/mslangid.hxx>
+#include <vcl/window.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+#include <svtools/svtools.hrc>
+#include <svtools/svtdata.hxx>
+#include <svtools/ctrltool.hxx>
+
+// =======================================================================
+
+// Standard Fontgroessen fuer scalierbare Fonts
+static long aStdSizeAry[] =
+{
+ 60,
+ 70,
+ 80,
+ 90,
+ 100,
+ 105,
+ 110,
+ 120,
+ 130,
+ 140,
+ 150,
+ 160,
+ 180,
+ 200,
+ 220,
+ 240,
+ 260,
+ 280,
+ 320,
+ 360,
+ 400,
+ 440,
+ 480,
+ 540,
+ 600,
+ 660,
+ 720,
+ 800,
+ 880,
+ 960,
+ 0
+};
+
+// =======================================================================
+
+// -----------------------------
+// - class ImplFontListFonInfo -
+// -----------------------------
+
+class ImplFontListFontInfo : public FontInfo
+{
+ friend class FontList;
+
+private:
+ OutputDevice* mpDevice;
+ ImplFontListFontInfo* mpNext;
+
+public:
+ ImplFontListFontInfo( const FontInfo& rInfo,
+ OutputDevice* pDev ) :
+ FontInfo( rInfo )
+ {
+ mpDevice = pDev;
+ }
+
+ OutputDevice* GetDevice() const { return mpDevice; }
+};
+
+// ------------------------------
+// - class ImplFontListNameInfo -
+// ------------------------------
+
+class ImplFontListNameInfo
+{
+ friend class FontList;
+
+private:
+ XubString maSearchName;
+ ImplFontListFontInfo* mpFirst;
+ sal_uInt16 mnType;
+
+ ImplFontListNameInfo( const XubString& rSearchName ) :
+ maSearchName( rSearchName )
+ {}
+
+ const XubString& GetSearchName() const { return maSearchName; }
+};
+
+// =======================================================================
+
+static StringCompare ImplCompareFontInfo( ImplFontListFontInfo* pInfo1,
+ ImplFontListFontInfo* pInfo2 )
+{
+ if ( pInfo1->GetWeight() < pInfo2->GetWeight() )
+ return COMPARE_LESS;
+ else if ( pInfo1->GetWeight() > pInfo2->GetWeight() )
+ return COMPARE_GREATER;
+
+ if ( pInfo1->GetItalic() < pInfo2->GetItalic() )
+ return COMPARE_LESS;
+ else if ( pInfo1->GetItalic() > pInfo2->GetItalic() )
+ return COMPARE_GREATER;
+
+ return pInfo1->GetStyleName().CompareTo( pInfo2->GetStyleName() );
+}
+
+// =======================================================================
+
+static void ImplMakeSearchString( XubString& rStr )
+{
+ rStr.ToLowerAscii();
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplMakeSearchStringFromName( XubString& rStr )
+{
+ // check for features before alternate font separator
+ if (rStr.Search(':') < rStr.Search(';'))
+ rStr = rStr.GetToken( 0, ':' );
+ else
+ rStr = rStr.GetToken( 0, ';' );
+ ImplMakeSearchString( rStr );
+}
+
+// -----------------------------------------------------------------------
+
+ImplFontListNameInfo* FontList::ImplFind( const XubString& rSearchName, sal_uLong* pIndex ) const
+{
+ // Wenn kein Eintrag in der Liste oder der Eintrag groesser ist als
+ // der Letzte, dann hinten dranhaengen. Wir vergleichen erst mit dem
+ // letzten Eintrag, da die Liste von VCL auch sortiert zurueckkommt
+ // und somit die Wahrscheinlichkeit das hinten angehaengt werden muss
+ // sehr gross ist.
+ StringCompare eComp;
+ sal_uLong nCnt = Count();
+ if ( !nCnt )
+ {
+ if ( pIndex )
+ *pIndex = LIST_APPEND;
+ return NULL;
+ }
+ else
+ {
+ ImplFontListNameInfo* pCmpData = (ImplFontListNameInfo*)List::GetObject( nCnt-1 );
+ eComp = rSearchName.CompareTo( pCmpData->maSearchName );
+ if ( eComp == COMPARE_GREATER )
+ {
+ if ( pIndex )
+ *pIndex = LIST_APPEND;
+ return NULL;
+ }
+ else if ( eComp == COMPARE_EQUAL )
+ return pCmpData;
+ }
+
+ // Fonts in der Liste suchen
+ ImplFontListNameInfo* pCompareData;
+ ImplFontListNameInfo* pFoundData = NULL;
+ sal_uLong nLow = 0;
+ sal_uLong nHigh = nCnt-1;
+ sal_uLong nMid;
+
+ do
+ {
+ nMid = (nLow + nHigh) / 2;
+ pCompareData = (ImplFontListNameInfo*)List::GetObject( nMid );
+ eComp = rSearchName.CompareTo( pCompareData->maSearchName );
+ if ( eComp == COMPARE_LESS )
+ {
+ if ( !nMid )
+ break;
+ nHigh = nMid-1;
+ }
+ else
+ {
+ if ( eComp == COMPARE_GREATER )
+ nLow = nMid + 1;
+ else
+ {
+ pFoundData = pCompareData;
+ break;
+ }
+ }
+ }
+ while ( nLow <= nHigh );
+
+ if ( pIndex )
+ {
+ eComp = rSearchName.CompareTo( pCompareData->maSearchName );
+ if ( eComp == COMPARE_GREATER )
+ *pIndex = (nMid+1);
+ else
+ *pIndex = nMid;
+ }
+
+ return pFoundData;
+}
+
+// -----------------------------------------------------------------------
+
+ImplFontListNameInfo* FontList::ImplFindByName( const XubString& rStr ) const
+{
+ XubString aSearchName = rStr;
+ ImplMakeSearchStringFromName( aSearchName );
+ return ImplFind( aSearchName, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void FontList::ImplInsertFonts( OutputDevice* pDevice, sal_Bool bAll,
+ sal_Bool bInsertData )
+{
+ rtl_TextEncoding eSystemEncoding = gsl_getSystemTextEncoding();
+
+ sal_uInt16 nType;
+ if ( pDevice->GetOutDevType() != OUTDEV_PRINTER )
+ nType = FONTLIST_FONTNAMETYPE_SCREEN;
+ else
+ nType = FONTLIST_FONTNAMETYPE_PRINTER;
+
+ // Alle Fonts vom Device abfragen
+ int n = pDevice->GetDevFontCount();
+ sal_uInt16 i;
+ for( i = 0; i < n; i++ )
+ {
+ FontInfo aFontInfo = pDevice->GetDevFont( i );
+
+ // Wenn keine Raster-Schriften angezeigt werden sollen,
+ // dann diese ignorieren
+ if ( !bAll && (aFontInfo.GetType() == TYPE_RASTER) )
+ continue;
+
+ XubString aSearchName = aFontInfo.GetName();
+ ImplFontListNameInfo* pData;
+ sal_uLong nIndex;
+ ImplMakeSearchString( aSearchName );
+ pData = ImplFind( aSearchName, &nIndex );
+
+ if ( !pData )
+ {
+ if ( bInsertData )
+ {
+ ImplFontListFontInfo* pNewInfo = new ImplFontListFontInfo( aFontInfo, pDevice );
+ pData = new ImplFontListNameInfo( aSearchName );
+ pData->mpFirst = pNewInfo;
+ pNewInfo->mpNext = NULL;
+ pData->mnType = 0;
+ Insert( (void*)pData, nIndex );
+ }
+ }
+ else
+ {
+ if ( bInsertData )
+ {
+ sal_Bool bInsert = sal_True;
+ ImplFontListFontInfo* pPrev = NULL;
+ ImplFontListFontInfo* pTemp = pData->mpFirst;
+ ImplFontListFontInfo* pNewInfo = new ImplFontListFontInfo( aFontInfo, pDevice );
+ while ( pTemp )
+ {
+ StringCompare eComp = ImplCompareFontInfo( pNewInfo, pTemp );
+ if ( (eComp == COMPARE_LESS) || (eComp == COMPARE_EQUAL) )
+ {
+ if ( eComp == COMPARE_EQUAL )
+ {
+ // Overwrite charset, because charset should match
+ // with the system charset
+ if ( (pTemp->GetCharSet() != eSystemEncoding) &&
+ (pNewInfo->GetCharSet() == eSystemEncoding) )
+ {
+ ImplFontListFontInfo* pTemp2 = pTemp->mpNext;
+ *((FontInfo*)pTemp) = *((FontInfo*)pNewInfo);
+ pTemp->mpNext = pTemp2;
+ }
+ delete pNewInfo;
+ bInsert = sal_False;
+ }
+
+ break;
+ }
+
+ pPrev = pTemp;
+ pTemp = pTemp->mpNext;
+ }
+
+ if ( bInsert )
+ {
+ pNewInfo->mpNext = pTemp;
+ if ( pPrev )
+ pPrev->mpNext = pNewInfo;
+ else
+ pData->mpFirst = pNewInfo;
+ }
+ }
+ }
+
+ if ( pData )
+ {
+ pData->mnType |= nType;
+ if ( aFontInfo.GetType() != TYPE_RASTER )
+ pData->mnType |= FONTLIST_FONTNAMETYPE_SCALABLE;
+ }
+ }
+}
+
+// =======================================================================
+
+FontList::FontList( OutputDevice* pDevice, OutputDevice* pDevice2, sal_Bool bAll ) :
+ List( 4096, sal::static_int_cast< sal_uInt16 >(pDevice->GetDevFontCount()), 32 )
+{
+ // Variablen initialisieren
+ mpDev = pDevice;
+ mpDev2 = pDevice2;
+ mpSizeAry = NULL;
+
+ // Stylenamen festlegen
+ maLight = XubString( SvtResId( STR_SVT_STYLE_LIGHT ) );
+ maLightItalic = XubString( SvtResId( STR_SVT_STYLE_LIGHT_ITALIC ) );
+ maNormal = XubString( SvtResId( STR_SVT_STYLE_NORMAL ) );
+ maNormalItalic = XubString( SvtResId( STR_SVT_STYLE_NORMAL_ITALIC ) );
+ maBold = XubString( SvtResId( STR_SVT_STYLE_BOLD ) );
+ maBoldItalic = XubString( SvtResId( STR_SVT_STYLE_BOLD_ITALIC ) );
+ maBlack = XubString( SvtResId( STR_SVT_STYLE_BLACK ) );
+ maBlackItalic = XubString( SvtResId( STR_SVT_STYLE_BLACK_ITALIC ) );
+
+ ImplInsertFonts( pDevice, bAll, sal_True );
+
+ // Gegebenenfalls muessen wir mit den Bildschirmfonts vergleichen,
+ // damit dort die eigentlich doppelten auf Equal mappen koennen
+ sal_Bool bCompareWindow = sal_False;
+ if ( !pDevice2 && (pDevice->GetOutDevType() == OUTDEV_PRINTER) )
+ {
+ bCompareWindow = sal_True;
+ pDevice2 = Application::GetDefaultDevice();
+ }
+
+ if ( pDevice2 &&
+ (pDevice2->GetOutDevType() != pDevice->GetOutDevType()) )
+ ImplInsertFonts( pDevice2, bAll, !bCompareWindow );
+}
+
+// -----------------------------------------------------------------------
+
+FontList::~FontList()
+{
+ // Gegebenenfalls SizeArray loeschen
+ if ( mpSizeAry )
+ delete[] mpSizeAry;
+
+ // FontInfos loeschen
+ ImplFontListNameInfo* pData = (ImplFontListNameInfo*)First();
+ while ( pData )
+ {
+ ImplFontListFontInfo* pTemp;
+ ImplFontListFontInfo* pInfo = pData->mpFirst;
+ while ( pInfo )
+ {
+ pTemp = pInfo->mpNext;
+ delete pInfo;
+ pInfo = pTemp;
+ }
+ ImplFontListNameInfo* pNext = (ImplFontListNameInfo*)Next();
+ delete pData;
+ pData = pNext;
+ }
+}
+// -----------------------------------------------------------------------
+FontList* FontList::Clone() const
+{
+ FontList* pReturn = new FontList(
+ mpDev, mpDev2, GetFontNameCount() == mpDev->GetDevFontCount());
+ return pReturn;
+}
+
+// -----------------------------------------------------------------------
+
+const XubString& FontList::GetStyleName( FontWeight eWeight, FontItalic eItalic ) const
+{
+ if ( eWeight > WEIGHT_BOLD )
+ {
+ if ( eItalic > ITALIC_NONE )
+ return maBlackItalic;
+ else
+ return maBlack;
+ }
+ else if ( eWeight > WEIGHT_MEDIUM )
+ {
+ if ( eItalic > ITALIC_NONE )
+ return maBoldItalic;
+ else
+ return maBold;
+ }
+ else if ( eWeight > WEIGHT_LIGHT )
+ {
+ if ( eItalic > ITALIC_NONE )
+ return maNormalItalic;
+ else
+ return maNormal;
+ }
+ else if ( eWeight != WEIGHT_DONTKNOW )
+ {
+ if ( eItalic > ITALIC_NONE )
+ return maLightItalic;
+ else
+ return maLight;
+ }
+ else
+ {
+ if ( eItalic > ITALIC_NONE )
+ return maNormalItalic;
+ else
+ return maNormal;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString FontList::GetStyleName( const FontInfo& rInfo ) const
+{
+ XubString aStyleName = rInfo.GetStyleName();
+ FontWeight eWeight = rInfo.GetWeight();
+ FontItalic eItalic = rInfo.GetItalic();
+
+ // Nur wenn kein StyleName gesetzt ist, geben wir einen syntetischen
+ // Namen zurueck
+ if ( !aStyleName.Len() )
+ aStyleName = GetStyleName( eWeight, eItalic );
+ else
+ {
+ // Translate StyleName to localized name
+ XubString aCompareStyleName = aStyleName;
+ aCompareStyleName.ToLowerAscii();
+ aCompareStyleName.EraseAllChars( ' ' );
+ if ( aCompareStyleName.EqualsAscii( "bold" ) )
+ aStyleName = maBold;
+ else if ( aCompareStyleName.EqualsAscii( "bolditalic" ) )
+ aStyleName = maBoldItalic;
+ else if ( aCompareStyleName.EqualsAscii( "italic" ) )
+ aStyleName = maNormalItalic;
+ else if ( aCompareStyleName.EqualsAscii( "standard" ) )
+ aStyleName = maNormal;
+ else if ( aCompareStyleName.EqualsAscii( "regular" ) )
+ aStyleName = maNormal;
+ else if ( aCompareStyleName.EqualsAscii( "medium" ) )
+ aStyleName = maNormal;
+ else if ( aCompareStyleName.EqualsAscii( "light" ) )
+ aStyleName = maLight;
+ else if ( aCompareStyleName.EqualsAscii( "lightitalic" ) )
+ aStyleName = maLightItalic;
+ else if ( aCompareStyleName.EqualsAscii( "black" ) )
+ aStyleName = maBlack;
+ else if ( aCompareStyleName.EqualsAscii( "blackitalic" ) )
+ aStyleName = maBlackItalic;
+
+ // fix up StyleName, because the PS Printer driver from
+ // W2000 returns wrong StyleNames (e.g. Bold instead of Bold Italic
+ // for Helvetica)
+ if ( eItalic > ITALIC_NONE )
+ {
+ if ( (aStyleName == maNormal) ||
+ (aStyleName == maBold) ||
+ (aStyleName == maLight) ||
+ (aStyleName == maBlack) )
+ aStyleName = GetStyleName( eWeight, eItalic );
+ }
+ }
+
+ return aStyleName;
+}
+
+// -----------------------------------------------------------------------
+
+XubString FontList::GetFontMapText( const FontInfo& rInfo ) const
+{
+ if ( !rInfo.GetName().Len() )
+ {
+ XubString aEmptryStr;
+ return aEmptryStr;
+ }
+
+ // Search Fontname
+ ImplFontListNameInfo* pData = ImplFindByName( rInfo.GetName() );
+ if ( !pData )
+ {
+ if ( !maMapNotAvailable.Len() )
+ ((FontList*)this)->maMapNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_NOTAVAILABLE ) );
+ return maMapNotAvailable;
+ }
+
+ // search for synthetic style
+ sal_uInt16 nType = pData->mnType;
+ const XubString& rStyleName = rInfo.GetStyleName();
+ if ( rStyleName.Len() )
+ {
+ sal_Bool bNotSynthetic = sal_False;
+ sal_Bool bNoneAvailable = sal_False;
+ FontWeight eWeight = rInfo.GetWeight();
+ FontItalic eItalic = rInfo.GetItalic();
+ ImplFontListFontInfo* pFontInfo = pData->mpFirst;
+ while ( pFontInfo )
+ {
+ if ( (eWeight == pFontInfo->GetWeight()) &&
+ (eItalic == pFontInfo->GetItalic()) )
+ {
+ bNotSynthetic = sal_True;
+ break;
+ }
+
+ pFontInfo = pFontInfo->mpNext;
+ }
+
+ if ( bNoneAvailable )
+ {
+ XubString aEmptryStr;
+ return aEmptryStr;
+ }
+ else if ( !bNotSynthetic )
+ {
+ if ( !maMapStyleNotAvailable.Len() )
+ ((FontList*)this)->maMapStyleNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_STYLENOTAVAILABLE ) );
+ return maMapStyleNotAvailable;
+ }
+ }
+
+ /* Size not available not implemented yet
+ if ( !(nType & FONTLIST_FONTNAMETYPE_SCALABLE) )
+ {
+ ...
+ {
+ if ( !maMapSizeNotAvailable.Len() )
+ ((FontList*)this)->maMapSizeNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_SIZENOTAVAILABLE ) );
+ return maMapSizeNotAvailable;
+ }
+ }
+ */
+
+ // Only Printer-Font?
+ if ( (nType & (FONTLIST_FONTNAMETYPE_PRINTER | FONTLIST_FONTNAMETYPE_SCREEN)) == FONTLIST_FONTNAMETYPE_PRINTER )
+ {
+ if ( !maMapPrinterOnly.Len() )
+ ((FontList*)this)->maMapPrinterOnly = XubString( SvtResId( STR_SVT_FONTMAP_PRINTERONLY ) );
+ return maMapPrinterOnly;
+ }
+ // Only Screen-Font?
+ else if ( (nType & (FONTLIST_FONTNAMETYPE_PRINTER | FONTLIST_FONTNAMETYPE_SCREEN)) == FONTLIST_FONTNAMETYPE_SCREEN
+ && rInfo.GetType() == TYPE_RASTER )
+ {
+ if ( !maMapScreenOnly.Len() )
+ ((FontList*)this)->maMapScreenOnly = XubString( SvtResId( STR_SVT_FONTMAP_SCREENONLY ) );
+ return maMapScreenOnly;
+ }
+ else
+ {
+ if ( !maMapBoth.Len() )
+ ((FontList*)this)->maMapBoth = XubString( SvtResId( STR_SVT_FONTMAP_BOTH ) );
+ return maMapBoth;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 FontList::GetFontNameType( const XubString& rFontName ) const
+{
+ ImplFontListNameInfo* pData = ImplFindByName( rFontName );
+ if ( pData )
+ return pData->mnType;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo FontList::Get( const XubString& rName, const XubString& rStyleName ) const
+{
+ ImplFontListNameInfo* pData = ImplFindByName( rName );
+ ImplFontListFontInfo* pFontInfo = NULL;
+ ImplFontListFontInfo* pFontNameInfo = NULL;
+ if ( pData )
+ {
+ ImplFontListFontInfo* pSearchInfo = pData->mpFirst;
+ pFontNameInfo = pSearchInfo;
+ pSearchInfo = pData->mpFirst;
+ while ( pSearchInfo )
+ {
+ if ( rStyleName.EqualsIgnoreCaseAscii( GetStyleName( *pSearchInfo ) ) )
+ {
+ pFontInfo = pSearchInfo;
+ break;
+ }
+
+ pSearchInfo = pSearchInfo->mpNext;
+ }
+ }
+
+ // Konnten die Daten nicht gefunden werden, dann muessen bestimmte
+ // Attribute nachgebildet werden
+ FontInfo aInfo;
+ if ( !pFontInfo )
+ {
+ if ( pFontNameInfo )
+ aInfo = *pFontNameInfo;
+
+ if ( rStyleName == maNormal )
+ {
+ aInfo.SetItalic( ITALIC_NONE );
+ aInfo.SetWeight( WEIGHT_NORMAL );
+ }
+ else if ( rStyleName == maNormalItalic )
+ {
+ aInfo.SetItalic( ITALIC_NORMAL );
+ aInfo.SetWeight( WEIGHT_NORMAL );
+ }
+ else if ( rStyleName == maBold )
+ {
+ aInfo.SetItalic( ITALIC_NONE );
+ aInfo.SetWeight( WEIGHT_BOLD );
+ }
+ else if ( rStyleName == maBoldItalic )
+ {
+ aInfo.SetItalic( ITALIC_NORMAL );
+ aInfo.SetWeight( WEIGHT_BOLD );
+ }
+ else if ( rStyleName == maLight )
+ {
+ aInfo.SetItalic( ITALIC_NONE );
+ aInfo.SetWeight( WEIGHT_LIGHT );
+ }
+ else if ( rStyleName == maLightItalic )
+ {
+ aInfo.SetItalic( ITALIC_NORMAL );
+ aInfo.SetWeight( WEIGHT_LIGHT );
+ }
+ else if ( rStyleName == maBlack )
+ {
+ aInfo.SetItalic( ITALIC_NONE );
+ aInfo.SetWeight( WEIGHT_BLACK );
+ }
+ else if ( rStyleName == maBlackItalic )
+ {
+ aInfo.SetItalic( ITALIC_NORMAL );
+ aInfo.SetWeight( WEIGHT_BLACK );
+ }
+ else
+ {
+ aInfo.SetItalic( ITALIC_NONE );
+ aInfo.SetWeight( WEIGHT_DONTKNOW );
+ }
+ }
+ else
+ aInfo = *pFontInfo;
+
+ // set Fontname to keep FontAlias
+ aInfo.SetName( rName );
+ aInfo.SetStyleName( rStyleName );
+
+ return aInfo;
+}
+
+// -----------------------------------------------------------------------
+
+FontInfo FontList::Get( const XubString& rName,
+ FontWeight eWeight, FontItalic eItalic ) const
+{
+ ImplFontListNameInfo* pData = ImplFindByName( rName );
+ ImplFontListFontInfo* pFontInfo = NULL;
+ ImplFontListFontInfo* pFontNameInfo = NULL;
+ if ( pData )
+ {
+ ImplFontListFontInfo* pSearchInfo = pData->mpFirst;
+ pFontNameInfo = pSearchInfo;
+ while ( pSearchInfo )
+ {
+ if ( (eWeight == pSearchInfo->GetWeight()) &&
+ (eItalic == pSearchInfo->GetItalic()) )
+ {
+ pFontInfo = pSearchInfo;
+ break;
+ }
+
+ pSearchInfo = pSearchInfo->mpNext;
+ }
+ }
+
+ // Konnten die Daten nicht gefunden werden, dann muessen bestimmte
+ // Attribute nachgebildet werden
+ FontInfo aInfo;
+ if ( !pFontInfo )
+ {
+ // Falls der Fontname stimmt, uebernehmen wir soviel wie moeglich
+ if ( pFontNameInfo )
+ {
+ aInfo = *pFontNameInfo;
+ aInfo.SetStyleName( XubString() );
+ }
+
+ aInfo.SetWeight( eWeight );
+ aInfo.SetItalic( eItalic );
+ }
+ else
+ aInfo = *pFontInfo;
+
+ // set Fontname to keep FontAlias
+ aInfo.SetName( rName );
+
+ return aInfo;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool FontList::IsAvailable( const XubString& rName ) const
+{
+ return (ImplFindByName( rName ) != 0);
+}
+
+// -----------------------------------------------------------------------
+
+const FontInfo& FontList::GetFontName( sal_uInt16 nFont ) const
+{
+ DBG_ASSERT( nFont < GetFontNameCount(), "FontList::GetFontName(): nFont >= Count" );
+
+ ImplFontListNameInfo* pData = (ImplFontListNameInfo*)List::GetObject( nFont );
+ return *(pData->mpFirst);
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 FontList::GetFontNameType( sal_uInt16 nFont ) const
+{
+ DBG_ASSERT( nFont < GetFontNameCount(), "FontList::GetFontNameType(): nFont >= Count" );
+
+ ImplFontListNameInfo* pData = (ImplFontListNameInfo*)List::GetObject( nFont );
+ return pData->mnType;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Handle FontList::GetFirstFontInfo( const XubString& rName ) const
+{
+ ImplFontListNameInfo* pData = ImplFindByName( rName );
+ if ( !pData )
+ return (sal_Handle)NULL;
+ else
+ return (sal_Handle)pData->mpFirst;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Handle FontList::GetNextFontInfo( sal_Handle hFontInfo ) const
+{
+ ImplFontListFontInfo* pInfo = (ImplFontListFontInfo*)(void*)hFontInfo;
+ return (sal_Handle)(pInfo->mpNext);
+}
+
+// -----------------------------------------------------------------------
+
+const FontInfo& FontList::GetFontInfo( sal_Handle hFontInfo ) const
+{
+ ImplFontListFontInfo* pInfo = (ImplFontListFontInfo*)(void*)hFontInfo;
+ return *pInfo;
+}
+
+// -----------------------------------------------------------------------
+
+const long* FontList::GetSizeAry( const FontInfo& rInfo ) const
+{
+ // Size-Array vorher loeschen
+ if ( mpSizeAry )
+ {
+ delete[] ((FontList*)this)->mpSizeAry;
+ ((FontList*)this)->mpSizeAry = NULL;
+ }
+
+ // Falls kein Name, dann Standardgroessen
+ if ( !rInfo.GetName().Len() )
+ return aStdSizeAry;
+
+ // Zuerst nach dem Fontnamen suchen um das Device dann von dem
+ // entsprechenden Font zu nehmen
+ OutputDevice* pDevice = mpDev;
+ ImplFontListNameInfo* pData = ImplFindByName( rInfo.GetName() );
+ if ( pData )
+ pDevice = pData->mpFirst->GetDevice();
+
+ int nDevSizeCount = pDevice->GetDevFontSizeCount( rInfo );
+ if ( !nDevSizeCount ||
+ (pDevice->GetDevFontSize( rInfo, 0 ).Height() == 0) )
+ return aStdSizeAry;
+
+ MapMode aOldMapMode = pDevice->GetMapMode();
+ MapMode aMap( MAP_10TH_INCH, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) );
+ pDevice->SetMapMode( aMap );
+
+ sal_uInt16 i;
+ sal_uInt16 nRealCount = 0;
+ long nOldHeight = 0;
+ ((FontList*)this)->mpSizeAry = new long[nDevSizeCount+1];
+ for ( i = 0; i < nDevSizeCount; i++ )
+ {
+ Size aSize = pDevice->GetDevFontSize( rInfo, i );
+ if ( aSize.Height() != nOldHeight )
+ {
+ nOldHeight = aSize.Height();
+ ((FontList*)this)->mpSizeAry[nRealCount] = nOldHeight;
+ nRealCount++;
+ }
+ }
+ ((FontList*)this)->mpSizeAry[nRealCount] = 0;
+
+ pDevice->SetMapMode( aOldMapMode );
+ return mpSizeAry;
+}
+
+// -----------------------------------------------------------------------
+
+const long* FontList::GetStdSizeAry()
+{
+ return aStdSizeAry;
+}
+
+// =======================================================================
+
+// ---------------------------------
+// - FontSizeNames & FsizeNameItem -
+// ---------------------------------
+
+struct ImplFSNameItem
+{
+ long mnSize;
+ const char* mszUtf8Name;
+};
+
+//------------------------------------------------------------------------
+
+static ImplFSNameItem aImplSimplifiedChinese[] =
+{
+ { 50, "\xe5\x85\xab\xe5\x8f\xb7" },
+ { 55, "\xe4\xb8\x83\xe5\x8f\xb7" },
+ { 65, "\xe5\xb0\x8f\xe5\x85\xad" },
+ { 75, "\xe5\x85\xad\xe5\x8f\xb7" },
+ { 90, "\xe5\xb0\x8f\xe4\xba\x94" },
+ { 105, "\xe4\xba\x94\xe5\x8f\xb7" },
+ { 120, "\xe5\xb0\x8f\xe5\x9b\x9b" },
+ { 140, "\xe5\x9b\x9b\xe5\x8f\xb7" },
+ { 150, "\xe5\xb0\x8f\xe4\xb8\x89" },
+ { 160, "\xe4\xb8\x89\xe5\x8f\xb7" },
+ { 180, "\xe5\xb0\x8f\xe4\xba\x8c" },
+ { 220, "\xe4\xba\x8c\xe5\x8f\xb7" },
+ { 240, "\xe5\xb0\x8f\xe4\xb8\x80" },
+ { 260, "\xe4\xb8\x80\xe5\x8f\xb7" },
+ { 360, "\xe5\xb0\x8f\xe5\x88\x9d" },
+ { 420, "\xe5\x88\x9d\xe5\x8f\xb7" }
+};
+
+// -----------------------------------------------------------------------
+
+#if 0 // #i89077# disabled by popular request
+static ImplFSNameItem aImplTraditionalChinese[] =
+{
+ { 50, "\xe5\x85\xab\xe8\x99\x9f" },
+ { 55, "\xe4\xb8\x83\xe8\x99\x9f" },
+ { 65, "\xe5\xb0\x8f\xe5\x85\xad" },
+ { 75, "\xe5\x85\xad\xe8\x99\x9f" },
+ { 90, "\xe5\xb0\x8f\xe4\xba\x94" },
+ { 105, "\xe4\xba\x94\xe8\x99\x9f" },
+ { 120, "\xe5\xb0\x8f\xe5\x9b\x9b" },
+ { 140, "\xe5\x9b\x9b\xe8\x99\x9f" },
+ { 150, "\xe5\xb0\x8f\xe4\xb8\x89" },
+ { 160, "\xe4\xb8\x89\xe8\x99\x9f" },
+ { 180, "\xe5\xb0\x8f\xe4\xba\x8c" },
+ { 220, "\xe4\xba\x8c\xe8\x99\x9f" },
+ { 240, "\xe5\xb0\x8f\xe4\xb8\x80" },
+ { 260, "\xe4\xb8\x80\xe8\x99\x9f" },
+ { 360, "\xe5\xb0\x8f\xe5\x88\x9d" },
+ { 420, "\xe5\x88\x9d\xe8\x99\x9f" }
+};
+#endif
+
+//------------------------------------------------------------------------
+
+FontSizeNames::FontSizeNames( LanguageType eLanguage )
+{
+ if ( eLanguage == LANGUAGE_DONTKNOW )
+ eLanguage = Application::GetSettings().GetUILanguage();
+ if ( eLanguage == LANGUAGE_SYSTEM )
+ eLanguage = MsLangId::getSystemUILanguage();
+
+ switch( eLanguage )
+ {
+ case LANGUAGE_CHINESE:
+ case LANGUAGE_CHINESE_SIMPLIFIED:
+ mpArray = aImplSimplifiedChinese;
+ mnElem = sizeof(aImplSimplifiedChinese) / sizeof(aImplSimplifiedChinese[0]);
+ break;
+
+#if 0 // #i89077# disabled by popular request
+ case LANGUAGE_CHINESE_HONGKONG:
+ case LANGUAGE_CHINESE_SINGAPORE:
+ case LANGUAGE_CHINESE_MACAU:
+ case LANGUAGE_CHINESE_TRADITIONAL:
+ mpArray = aImplTraditionalChinese;
+ mnElem = sizeof(aImplTraditionalChinese) / sizeof(aImplTraditionalChinese[0]);
+ break;
+#endif
+
+ default:
+ mpArray = NULL;
+ mnElem = 0;
+ break;
+ };
+}
+
+//------------------------------------------------------------------------
+
+long FontSizeNames::Name2Size( const String& rName ) const
+{
+ if ( mnElem )
+ {
+ ByteString aName( rName, RTL_TEXTENCODING_UTF8 );
+
+ // linear search is sufficient for this rare case
+ for( long i = mnElem; --i >= 0; )
+ if ( aName == mpArray[i].mszUtf8Name )
+ return mpArray[i].mnSize;
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+
+String FontSizeNames::Size2Name( long nValue ) const
+{
+ String aStr;
+
+ // binary search
+ for( long lower = 0, upper = mnElem - 1; lower <= upper; )
+ {
+ long mid = (upper + lower) >> 1;
+ if ( nValue == mpArray[mid].mnSize )
+ {
+ aStr = String( mpArray[mid].mszUtf8Name, RTL_TEXTENCODING_UTF8 );
+ break;
+ }
+ else if ( nValue < mpArray[mid].mnSize )
+ upper = mid - 1;
+ else /* ( nValue > mpArray[mid].mnSize ) */
+ lower = mid + 1;
+ }
+
+ return aStr;
+}
+
+//------------------------------------------------------------------------
+
+String FontSizeNames::GetIndexName( sal_uLong nIndex ) const
+{
+ String aStr;
+
+ if ( nIndex < mnElem )
+ aStr = String( mpArray[nIndex].mszUtf8Name, RTL_TEXTENCODING_UTF8 );
+
+ return aStr;
+}
+
+//------------------------------------------------------------------------
+
+long FontSizeNames::GetIndexSize( sal_uLong nIndex ) const
+{
+ if ( nIndex >= mnElem )
+ return 0;
+ return mpArray[nIndex].mnSize;
+}
diff --git a/svtools/source/control/ctrltool.src b/svtools/source/control/ctrltool.src
new file mode 100755
index 000000000000..72420af4908e
--- /dev/null
+++ b/svtools/source/control/ctrltool.src
@@ -0,0 +1,144 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+#include <svtools/svtools.hrc>
+
+String STR_SVT_STYLE_LIGHT
+{
+ Text [ en-US ] = "Light" ;
+};
+
+String STR_SVT_STYLE_LIGHT_ITALIC
+{
+ Text [ en-US ] = "Light Italic" ;
+};
+
+String STR_SVT_STYLE_NORMAL
+{
+ Text [ en-US ] = "Regular" ;
+};
+
+String STR_SVT_STYLE_NORMAL_ITALIC
+{
+ Text [ en-US ] = "Italic" ;
+};
+
+String STR_SVT_STYLE_BOLD
+{
+ Text [ en-US ] = "Bold" ;
+};
+
+String STR_SVT_STYLE_BOLD_ITALIC
+{
+ Text [ en-US ] = "Bold Italic" ;
+};
+
+String STR_SVT_STYLE_BLACK
+{
+ Text [ en-US ] = "Black" ;
+};
+
+String STR_SVT_STYLE_BLACK_ITALIC
+{
+ Text [ en-US ] = "Black Italic" ;
+};
+
+/*
+Finnische Texte:
+ "Light",
+ "Light Kursivoitu",
+ "Normaali",
+ "Kursivoitu",
+ "Lihavoitu",
+ "Lihavoitu Kursivoitu",
+ "Black",
+ "Black Kursivoitu"
+*/
+
+String STR_SVT_FONTMAP_BOTH
+{
+ Text [ en-US ] = "The same font will be used on both your printer and your screen." ;
+};
+
+String STR_SVT_FONTMAP_PRINTERONLY
+{
+ Text [ en-US ] = "This is a printer font. The screen image may differ." ;
+};
+
+String STR_SVT_FONTMAP_SCREENONLY
+{
+ Text [ en-US ] = "This is a screen font. The printer image may differ." ;
+};
+
+String STR_SVT_FONTMAP_SIZENOTAVAILABLE
+{
+ Text [ en-US ] = "This font size has not been installed. The closest available size will be used.";
+};
+
+String STR_SVT_FONTMAP_STYLENOTAVAILABLE
+{
+ Text [ en-US ] = "This font style will be simulated or the closest matching style will be used.";
+};
+
+String STR_SVT_FONTMAP_NOTAVAILABLE
+{
+ Text [ en-US ] = "This font has not been installed. The closest available font will be used.";
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svtools/source/control/filectrl.cxx b/svtools/source/control/filectrl.cxx
new file mode 100755
index 000000000000..eff46b78b2a2
--- /dev/null
+++ b/svtools/source/control/filectrl.cxx
@@ -0,0 +1,231 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _SV_FIELCTRL_CXX
+#include <tools/urlobj.hxx>
+#include <svtools/svtdata.hxx>
+#include <svtools/filectrl.hxx>
+#include <filectrl.hrc>
+
+// =======================================================================
+
+FileControl::FileControl( Window* pParent, WinBits nStyle, FileControlMode nFlags ) :
+ Window( pParent, nStyle|WB_DIALOGCONTROL ),
+ maEdit( this, (nStyle&(~WB_BORDER))|WB_NOTABSTOP ),
+ maButton( this, (nStyle&(~WB_BORDER))|WB_NOLIGHTBORDER|WB_NOPOINTERFOCUS|WB_NOTABSTOP ),
+ maButtonText( SvtResId( STR_FILECTRL_BUTTONTEXT ) ),
+ mnFlags( nFlags ),
+ mnInternalFlags( FILECTRL_ORIGINALBUTTONTEXT )
+{
+ maButton.SetClickHdl( LINK( this, FileControl, ButtonHdl ) );
+ mbOpenDlg = sal_True;
+
+ maButton.Show();
+ maEdit.Show();
+
+ SetCompoundControl( sal_True );
+
+ SetStyle( ImplInitStyle( GetStyle() ) );
+}
+
+// -----------------------------------------------------------------------
+
+WinBits FileControl::ImplInitStyle( WinBits nStyle )
+{
+ if ( !( nStyle & WB_NOTABSTOP ) )
+ {
+ maEdit.SetStyle( (maEdit.GetStyle()|WB_TABSTOP)&(~WB_NOTABSTOP) );
+ maButton.SetStyle( (maButton.GetStyle()|WB_TABSTOP)&(~WB_NOTABSTOP) );
+ }
+ else
+ {
+ maEdit.SetStyle( (maEdit.GetStyle()|WB_NOTABSTOP)&(~WB_TABSTOP) );
+ maButton.SetStyle( (maButton.GetStyle()|WB_NOTABSTOP)&(~WB_TABSTOP) );
+ }
+
+ const WinBits nAlignmentStyle = ( WB_TOP | WB_VCENTER | WB_BOTTOM );
+ maEdit.SetStyle( ( maEdit.GetStyle() & ~nAlignmentStyle ) | ( nStyle & nAlignmentStyle ) );
+
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+
+ if ( !(nStyle & WB_NOBORDER ) )
+ nStyle |= WB_BORDER;
+
+ nStyle &= ~WB_TABSTOP;
+
+ return nStyle;
+}
+
+// -----------------------------------------------------------------------
+
+FileControl::~FileControl()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FileControl::SetText( const XubString& rStr )
+{
+ maEdit.SetText( rStr );
+ if ( mnFlags & FILECTRL_RESIZEBUTTONBYPATHLEN )
+ Resize();
+}
+
+// -----------------------------------------------------------------------
+
+XubString FileControl::GetText() const
+{
+ return maEdit.GetText();
+}
+
+// -----------------------------------------------------------------------
+
+void FileControl::StateChanged( StateChangedType nType )
+{
+ if ( nType == STATE_CHANGE_ENABLE )
+ {
+ maEdit.Enable( IsEnabled() );
+ maButton.Enable( IsEnabled() );
+ }
+ else if ( nType == STATE_CHANGE_ZOOM )
+ {
+ GetEdit().SetZoom( GetZoom() );
+ GetButton().SetZoom( GetZoom() );
+ }
+ else if ( nType == STATE_CHANGE_STYLE )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFONT )
+ {
+ GetEdit().SetControlFont( GetControlFont() );
+ // Fuer den Button nur die Hoehe uebernehmen, weil in
+ // HTML immer Courier eingestellt wird.
+ Font aFont = GetButton().GetControlFont();
+ aFont.SetSize( GetControlFont().GetSize() );
+ GetButton().SetControlFont( aFont );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ GetEdit().SetControlForeground( GetControlForeground() );
+ GetButton().SetControlForeground( GetControlForeground() );
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ GetEdit().SetControlBackground( GetControlBackground() );
+ GetButton().SetControlBackground( GetControlBackground() );
+ }
+ Window::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void FileControl::Resize()
+{
+ static long ButtonBorder = 10;
+
+ if( mnInternalFlags & FILECTRL_INRESIZE )
+ return;
+ mnInternalFlags |= FILECTRL_INRESIZE;//InResize = sal_True
+
+ Size aOutSz = GetOutputSizePixel();
+ long nButtonTextWidth = maButton.GetTextWidth( maButtonText );
+ if ( ((mnInternalFlags & FILECTRL_ORIGINALBUTTONTEXT) == 0) ||
+ ( nButtonTextWidth < aOutSz.Width()/3 &&
+ ( mnFlags & FILECTRL_RESIZEBUTTONBYPATHLEN
+ ? ( maEdit.GetTextWidth( maEdit.GetText() )
+ <= aOutSz.Width() - nButtonTextWidth - ButtonBorder )
+ : sal_True ) )
+ )
+ {
+ maButton.SetText( maButtonText );
+ }
+ else
+ {
+ XubString aSmallText( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
+ maButton.SetText( aSmallText );
+ nButtonTextWidth = maButton.GetTextWidth( aSmallText );
+ }
+
+ long nButtonWidth = nButtonTextWidth+ButtonBorder;
+ maEdit.SetPosSizePixel( 0, 0, aOutSz.Width()-nButtonWidth, aOutSz.Height() );
+ maButton.SetPosSizePixel( aOutSz.Width()-nButtonWidth, 0, nButtonWidth, aOutSz.Height() );
+
+ mnInternalFlags &= ~FILECTRL_INRESIZE; //InResize = sal_False
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( FileControl, ButtonHdl, PushButton*, EMPTYARG )
+{
+ ImplBrowseFile( );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void FileControl::GetFocus()
+{
+ maEdit.GrabFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void FileControl::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
+{
+ WinBits nOldEditStyle = GetEdit().GetStyle();
+ if ( GetStyle() & WB_BORDER )
+ GetEdit().SetStyle( nOldEditStyle|WB_BORDER );
+ GetEdit().Draw( pDev, rPos, rSize, nFlags );
+ if ( GetStyle() & WB_BORDER )
+ GetEdit().SetStyle( nOldEditStyle );
+}
+
+// -----------------------------------------------------------------------
+
+void FileControl::SetButtonText( const XubString& rStr )
+{
+ mnInternalFlags &= ~FILECTRL_ORIGINALBUTTONTEXT;
+ maButtonText = rStr;
+ Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void FileControl::ResetButtonText()
+{
+ mnInternalFlags |= FILECTRL_ORIGINALBUTTONTEXT;
+ maButtonText = XubString( SvtResId( STR_FILECTRL_BUTTONTEXT ) );
+ Resize();
+}
+
+
diff --git a/svtools/source/control/filectrl.src b/svtools/source/control/filectrl.src
new file mode 100755
index 000000000000..f9d63b65b838
--- /dev/null
+++ b/svtools/source/control/filectrl.src
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "filectrl.hrc"
+String STR_FILECTRL_BUTTONTEXT
+{
+ Text [ en-US ] = "Browse..." ;
+};
+
+String STR_TABBAR_PUSHBUTTON_MOVET0HOME
+{
+ Text [ en-US ] = "Move To Home" ;
+};
+String STR_TABBAR_PUSHBUTTON_MOVELEFT
+{
+ Text [ en-US ] = "Move Left" ;
+};
+String STR_TABBAR_PUSHBUTTON_MOVERIGHT
+{
+ Text [ en-US ] = "Move Right" ;
+};
+String STR_TABBAR_PUSHBUTTON_MOVETOEND
+{
+ Text [ en-US ] = "Move To End" ;
+};
+
diff --git a/svtools/source/control/filectrl2.cxx b/svtools/source/control/filectrl2.cxx
new file mode 100755
index 000000000000..904b643d2ae3
--- /dev/null
+++ b/svtools/source/control/filectrl2.cxx
@@ -0,0 +1,94 @@
+/*************************************************************************
+ *
+ * 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"
+
+// this file contains code from filectrl.cxx which needs to be compiled with enabled exception hanling
+#include <svtools/filectrl.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker.hpp>
+#include <vcl/unohelp.hxx>
+#include <tools/urlobj.hxx>
+#include <osl/file.h>
+#include <vcl/stdtext.hxx>
+#include <tools/debug.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ui;
+
+void FileControl::ImplBrowseFile( )
+{
+ try
+ {
+ XubString aNewText;
+
+ const ::rtl::OUString sServiceName = ::rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.FilePicker" );
+
+ Reference< XMultiServiceFactory > xMSF = vcl::unohelper::GetMultiServiceFactory();
+ Reference < dialogs::XFilePicker > xFilePicker( xMSF->createInstance( sServiceName ), UNO_QUERY );
+ if ( xFilePicker.is() )
+ {
+ // transform the system notation text into a file URL
+ ::rtl::OUString sSystemNotation = GetText(), sFileURL;
+ oslFileError nError = osl_getFileURLFromSystemPath( sSystemNotation.pData, &sFileURL.pData );
+ if ( nError == osl_File_E_INVAL )
+ sFileURL = GetText(); // #97709# Maybe URL is already a file URL...
+
+ //#90430# Check if URL is really a file URL
+ ::rtl::OUString aTmp;
+ if ( osl_getSystemPathFromFileURL( sFileURL.pData, &aTmp.pData ) == osl_File_E_None )
+ {
+ // initially set this directory
+ xFilePicker->setDisplayDirectory( sFileURL );
+ }
+
+ if ( xFilePicker.is() && xFilePicker->execute() )
+ {
+ Sequence < rtl::OUString > aPathSeq = xFilePicker->getFiles();
+
+ if ( aPathSeq.getLength() )
+ {
+ aNewText = aPathSeq[0];
+ INetURLObject aObj( aNewText );
+ if ( aObj.GetProtocol() == INET_PROT_FILE )
+ aNewText = aObj.PathToFileName();
+ SetText( aNewText );
+ maEdit.GetModifyHdl().Call( &maEdit );
+ }
+ }
+ }
+ else
+ ShowServiceNotAvailableError( this, sServiceName, sal_True );
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "FileControl::ImplBrowseFile: caught an exception while executing the file picker!" );
+ }
+}
+
diff --git a/svtools/source/control/fileurlbox.cxx b/svtools/source/control/fileurlbox.cxx
new file mode 100644
index 000000000000..476b2864a117
--- /dev/null
+++ b/svtools/source/control/fileurlbox.cxx
@@ -0,0 +1,124 @@
+/*************************************************************************
+ *
+ * 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 <svtools/fileurlbox.hxx>
+#include <osl/file.h>
+#include "svl/filenotation.hxx"
+
+//.........................................................................
+namespace svt
+{
+//.........................................................................
+
+ //=====================================================================
+ //= FileURLBox
+ //=====================================================================
+ //---------------------------------------------------------------------
+ FileURLBox::FileURLBox(Window* _pParent)
+ :SvtURLBox(_pParent, INET_PROT_FILE)
+ {
+ DisableHistory();
+ }
+
+ //---------------------------------------------------------------------
+ FileURLBox::FileURLBox( Window* _pParent, WinBits _nStyle )
+ :SvtURLBox( _pParent, _nStyle, INET_PROT_FILE )
+ {
+ DisableHistory();
+ }
+
+ //---------------------------------------------------------------------
+ FileURLBox::FileURLBox(Window* _pParent, const ResId& _rId)
+ :SvtURLBox(_pParent, _rId, INET_PROT_FILE)
+ {
+ DisableHistory();
+ }
+
+ //---------------------------------------------------------------------
+ void FileURLBox::DisplayURL( const String& _rURL )
+ {
+ String sOldText = GetText();
+
+ OFileNotation aTransformer( _rURL, OFileNotation::N_URL );
+ String sNewText = aTransformer.get( OFileNotation::N_SYSTEM );
+ SetText( sNewText );
+
+ if ( sOldText != sNewText )
+ Modify();
+
+ UpdatePickList();
+ }
+
+ //---------------------------------------------------------------------
+ long FileURLBox::PreNotify( NotifyEvent& _rNEvt )
+ {
+ switch ( _rNEvt.GetType() )
+ {
+ case EVENT_KEYINPUT:
+ if ( ( GetSubEdit() == _rNEvt.GetWindow() )
+ && ( KEY_RETURN == _rNEvt.GetKeyEvent()->GetKeyCode().GetCode() )
+ && ( IsInDropDown() )
+ )
+ m_sPreservedText = GetURL();
+ break;
+
+ case EVENT_LOSEFOCUS:
+ if ( IsWindowOrChild( _rNEvt.GetWindow() ) )
+ DisplayURL( GetText() );
+ break;
+ }
+
+ return SvtURLBox::PreNotify(_rNEvt);
+ }
+
+ //---------------------------------------------------------------------
+ long FileURLBox::Notify( NotifyEvent& _rNEvt )
+ {
+ switch ( _rNEvt.GetType() )
+ {
+ case EVENT_KEYINPUT:
+ if ( ( GetSubEdit() == _rNEvt.GetWindow() )
+ && ( KEY_RETURN == _rNEvt.GetKeyEvent()->GetKeyCode().GetCode() )
+ && ( IsInDropDown() )
+ )
+ {
+ long nReturn = SvtURLBox::Notify(_rNEvt);
+ DisplayURL( m_sPreservedText );
+ return nReturn;
+ }
+ break;
+ }
+
+ return SvtURLBox::Notify(_rNEvt);
+ }
+
+//.........................................................................
+} // namespace svt
+//.........................................................................
+
diff --git a/svtools/source/control/fixedhyper.cxx b/svtools/source/control/fixedhyper.cxx
new file mode 100644
index 000000000000..a8877d240d4e
--- /dev/null
+++ b/svtools/source/control/fixedhyper.cxx
@@ -0,0 +1,233 @@
+/*************************************************************************
+ *
+ * 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 <svtools/fixedhyper.hxx>
+
+//.........................................................................
+namespace svt
+{
+//.........................................................................
+
+// class FixedHyperlink --------------------------------------------------
+
+FixedHyperlink::FixedHyperlink( Window* pParent, const ResId& rResId ) :
+ ::toolkit::FixedHyperlinkBase( pParent, rResId ),
+ m_nTextLen(0)
+{
+ Initialize();
+}
+
+FixedHyperlink::FixedHyperlink( Window* pParent, WinBits nWinStyle ) :
+ ::toolkit::FixedHyperlinkBase( pParent, nWinStyle ),
+ m_nTextLen(0)
+{
+ Initialize();
+}
+
+FixedHyperlink::~FixedHyperlink()
+{
+}
+
+void FixedHyperlink::Initialize()
+{
+ // saves the old pointer
+ m_aOldPointer = GetPointer();
+ // changes the font
+ Font aFont = GetControlFont( );
+ // to underline
+ aFont.SetUnderline( UNDERLINE_SINGLE );
+ SetControlFont( aFont );
+ // changes the color to light blue
+ SetTextColor( Color( COL_LIGHTBLUE ) );
+ // calculates text len
+ m_nTextLen = GetCtrlTextWidth( GetText() );
+}
+
+void FixedHyperlink::MouseMove( const MouseEvent& rMEvt )
+{
+ // changes the pointer if the control is enabled and the mouse is over the text.
+ if ( !rMEvt.IsLeaveWindow() && IsEnabled() && GetPointerPosPixel().X() < m_nTextLen )
+ SetPointer( POINTER_REFHAND );
+ else
+ SetPointer( m_aOldPointer );
+}
+
+void FixedHyperlink::MouseButtonUp( const MouseEvent& )
+{
+ // calls the link if the control is enabled and the mouse is over the text.
+ if ( IsEnabled() && GetPointerPosPixel().X() < m_nTextLen )
+ ImplCallEventListenersAndHandler( VCLEVENT_BUTTON_CLICK, m_aClickHdl, this );
+}
+
+void FixedHyperlink::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( IsEnabled() && GetPointerPosPixel().X() < m_nTextLen )
+ FixedText::RequestHelp( rHEvt );
+}
+
+void FixedHyperlink::GetFocus()
+{
+ SetTextColor( Color( COL_LIGHTRED ) );
+ Paint( Rectangle( Point(), GetSizePixel() ) );
+ ShowFocus( Rectangle( Point( 1, 1 ), Size( m_nTextLen + 4, GetSizePixel().Height() - 2 ) ) );
+}
+
+void FixedHyperlink::LoseFocus()
+{
+ SetTextColor( Color( COL_LIGHTBLUE ) );
+ Paint( Rectangle( Point(), GetSizePixel() ) );
+ HideFocus();
+}
+
+void FixedHyperlink::KeyInput( const KeyEvent& rKEvt )
+{
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_SPACE:
+ case KEY_RETURN:
+ m_aClickHdl.Call( this );
+ break;
+
+ default:
+ FixedText::KeyInput( rKEvt );
+ }
+}
+
+void FixedHyperlink::SetURL( const String& rNewURL )
+{
+ m_sURL = rNewURL;
+ SetQuickHelpText( m_sURL );
+}
+
+String FixedHyperlink::GetURL() const
+{
+ return m_sURL;
+}
+
+void FixedHyperlink::SetDescription( const String& rNewDescription )
+{
+ SetText( rNewDescription );
+ m_nTextLen = GetCtrlTextWidth( GetText() );
+}
+
+// class FixedHyperlinkImage ---------------------------------------------
+
+FixedHyperlinkImage::FixedHyperlinkImage( Window* pParent, const ResId& rResId ) :
+ FixedImage( pParent, rResId )
+{
+ Initialize();
+}
+
+FixedHyperlinkImage::FixedHyperlinkImage( Window* pParent, WinBits nWinStyle ) :
+ FixedImage( pParent, nWinStyle )
+{
+ Initialize();
+}
+
+FixedHyperlinkImage::~FixedHyperlinkImage()
+{
+}
+
+void FixedHyperlinkImage::Initialize()
+{
+ // saves the old pointer
+ m_aOldPointer = GetPointer();
+}
+
+void FixedHyperlinkImage::MouseMove( const MouseEvent& rMEvt )
+{
+ // changes the pointer if the control is enabled and the mouse is over the text.
+ if ( !rMEvt.IsLeaveWindow() && IsEnabled() )
+ SetPointer( POINTER_REFHAND );
+ else
+ SetPointer( m_aOldPointer );
+}
+
+void FixedHyperlinkImage::MouseButtonUp( const MouseEvent& )
+{
+ // calls the link if the control is enabled and the mouse is over the text.
+ if ( IsEnabled() )
+ ImplCallEventListenersAndHandler( VCLEVENT_BUTTON_CLICK, m_aClickHdl, this );
+
+ Size aSize = GetSizePixel();
+ Size aImgSz = GetImage().GetSizePixel();
+ if ( aSize.Width() < aImgSz.Width() )
+ {
+ DBG_ERRORFILE("xxx");
+ }
+}
+
+void FixedHyperlinkImage::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( IsEnabled() )
+ FixedImage::RequestHelp( rHEvt );
+}
+
+void FixedHyperlinkImage::GetFocus()
+{
+ Paint( Rectangle( Point(), GetSizePixel() ) );
+ ShowFocus( Rectangle( Point( 1, 1 ), Size( GetSizePixel().Width() - 2, GetSizePixel().Height() - 2 ) ) );
+}
+
+void FixedHyperlinkImage::LoseFocus()
+{
+ Paint( Rectangle( Point(), GetSizePixel() ) );
+ HideFocus();
+}
+
+void FixedHyperlinkImage::KeyInput( const KeyEvent& rKEvt )
+{
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_SPACE:
+ case KEY_RETURN:
+ m_aClickHdl.Call( this );
+ break;
+
+ default:
+ FixedImage::KeyInput( rKEvt );
+ }
+}
+
+void FixedHyperlinkImage::SetURL( const String& rNewURL )
+{
+ m_sURL = rNewURL;
+ SetQuickHelpText( m_sURL );
+}
+
+String FixedHyperlinkImage::GetURL() const
+{
+ return m_sURL;
+}
+
+//.........................................................................
+} // namespace svt
+//.........................................................................
+
diff --git a/svtools/source/control/fmtfield.cxx b/svtools/source/control/fmtfield.cxx
new file mode 100755
index 000000000000..f123af14d510
--- /dev/null
+++ b/svtools/source/control/fmtfield.cxx
@@ -0,0 +1,1398 @@
+/*************************************************************************
+ *
+ * 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 <stdio.h>
+#include <tools/debug.hxx>
+#include <comphelper/processfactory.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/zformat.hxx>
+#include <svtools/fmtfield.hxx>
+#include <i18npool/mslangid.hxx>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/util/SearchOptions.hpp>
+#include <com/sun/star/util/SearchAlgorithms.hpp>
+#include <com/sun/star/util/SearchResult.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <unotools/syslocale.hxx>
+
+#ifndef REGEXP_SUPPORT
+#include <map>
+#endif
+
+#if !defined INCLUDED_RTL_MATH_HXX
+#include <rtl/math.hxx>
+#endif
+
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+
+#ifdef REGEXP_SUPPORT
+
+//==============================================================================
+// regular expression to validate complete numbers, plus every fragment which can occur during the input
+// of a complete number
+// [+/-][{digit}*.]*{digit}*[,{digit}*][e[+/-]{digit}*]
+const char __FAR_DATA szNumericInput[] = "_[-+]?([0-9]*\\,)*[0-9]*(\\.[0-9]*)?(e[-+]?[0-9]*)?_";
+ // (the two _ are for normalizing it: With this, we can ensure that a to-be-checked text is always
+ // matched as a _whole_)
+#else
+
+// hmm. No support for regular expression. Well, I always (not really :) wanted to write a finite automat
+// so here comes a finite automat ...
+
+namespace validation
+{
+ // the states of our automat.
+ enum State
+ {
+ START, // at the very start of the string
+ NUM_START, // the very start of the number
+
+ DIGIT_PRE_COMMA, // some pre-comma digits are read, perhaps including some thousand separators
+
+ DIGIT_POST_COMMA, // reading digits after the comma
+ EXPONENT_START, // at the very start of the exponent value
+ // (means: not including the "e" which denotes the exponent)
+ EXPONENT_DIGIT, // currently reading the digits of the exponent
+
+ END // reached the end of the string
+ };
+
+ // a row in the transition table (means the set of states to be reached from a given state)
+ typedef ::std::map< sal_Unicode, State > StateTransitions;
+
+ // a single transition
+ typedef StateTransitions::value_type Transition;
+
+ // the complete transition table
+ typedef ::std::map< State, StateTransitions > TransitionTable;
+
+ // the validator class
+ class NumberValidator
+ {
+ private:
+ TransitionTable m_aTransitions;
+ const sal_Unicode m_cThSep;
+ const sal_Unicode m_cDecSep;
+
+ public:
+ NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep );
+
+ sal_Bool isValidNumericFragment( const String& _rText );
+
+ private:
+ sal_Bool implValidateNormalized( const String& _rText );
+ };
+
+ //--------------------------------------------------------------------------
+ //..........................................................................
+ static void lcl_insertStopTransition( StateTransitions& _rRow )
+ {
+ _rRow.insert( Transition( '_', END ) );
+ }
+
+ //..........................................................................
+ static void lcl_insertStartExponentTransition( StateTransitions& _rRow )
+ {
+ _rRow.insert( Transition( 'e', EXPONENT_START ) );
+ }
+
+ //..........................................................................
+ static void lcl_insertSignTransitions( StateTransitions& _rRow, const State eNextState )
+ {
+ _rRow.insert( Transition( '-', eNextState ) );
+ _rRow.insert( Transition( '+', eNextState ) );
+ }
+
+ //..........................................................................
+ static void lcl_insertDigitTransitions( StateTransitions& _rRow, const State eNextState )
+ {
+ for ( sal_Unicode aChar = '0'; aChar <= '9'; ++aChar )
+ _rRow.insert( Transition( aChar, eNextState ) );
+ }
+
+ //..........................................................................
+ static void lcl_insertCommonPreCommaTransitions( StateTransitions& _rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
+ {
+ // digits are allowed
+ lcl_insertDigitTransitions( _rRow, DIGIT_PRE_COMMA );
+
+ // the thousand separator is allowed
+ _rRow.insert( Transition( _cThSep, DIGIT_PRE_COMMA ) );
+
+ // a comma is allowed
+ _rRow.insert( Transition( _cDecSep, DIGIT_POST_COMMA ) );
+ }
+
+ //--------------------------------------------------------------------------
+ NumberValidator::NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
+ :m_cThSep( _cThSep )
+ ,m_cDecSep( _cDecSep )
+ {
+ // build up our transition table
+
+ // how to procede from START
+ {
+ StateTransitions& rRow = m_aTransitions[ START ];
+ rRow.insert( Transition( '_', NUM_START ) );
+ // if we encounter the normalizing character, we want to procede with the number
+ }
+
+ // how to procede from NUM_START
+ {
+ StateTransitions& rRow = m_aTransitions[ NUM_START ];
+
+ // a sign is allowed
+ lcl_insertSignTransitions( rRow, DIGIT_PRE_COMMA );
+
+ // common transitions for the two pre-comma states
+ lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
+
+ // the exponent may start here
+ // (this would mean string like "_+e10_", but this is a valid fragment, though no valid number)
+ lcl_insertStartExponentTransition( rRow );
+ }
+
+ // how to procede from DIGIT_PRE_COMMA
+ {
+ StateTransitions& rRow = m_aTransitions[ DIGIT_PRE_COMMA ];
+
+ // common transitions for the two pre-comma states
+ lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
+
+ // the exponent may start here
+ lcl_insertStartExponentTransition( rRow );
+
+ // the final transition indicating the end of the string
+ // (if there is no comma and no post-comma, then the string may end here)
+ lcl_insertStopTransition( rRow );
+ }
+
+ // how to procede from DIGIT_POST_COMMA
+ {
+ StateTransitions& rRow = m_aTransitions[ DIGIT_POST_COMMA ];
+
+ // there might be digits, which would keep the state at DIGIT_POST_COMMA
+ lcl_insertDigitTransitions( rRow, DIGIT_POST_COMMA );
+
+ // the exponent may start here
+ lcl_insertStartExponentTransition( rRow );
+
+ // the string may end here
+ lcl_insertStopTransition( rRow );
+ }
+
+ // how to procede from EXPONENT_START
+ {
+ StateTransitions& rRow = m_aTransitions[ EXPONENT_START ];
+
+ // there may be a sign
+ lcl_insertSignTransitions( rRow, EXPONENT_DIGIT );
+
+ // there may be digits
+ lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
+
+ // the string may end here
+ lcl_insertStopTransition( rRow );
+ }
+
+ // how to procede from EXPONENT_DIGIT
+ {
+ StateTransitions& rRow = m_aTransitions[ EXPONENT_DIGIT ];
+
+ // there may be digits
+ lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
+
+ // the string may end here
+ lcl_insertStopTransition( rRow );
+ }
+
+ // how to procede from END
+ {
+ /*StateTransitions& rRow =*/ m_aTransitions[ EXPONENT_DIGIT ];
+ // no valid transition to leave this state
+ // (note that we, for consistency, nevertheless want to have a row in the table)
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ sal_Bool NumberValidator::implValidateNormalized( const String& _rText )
+ {
+ const sal_Unicode* pCheckPos = _rText.GetBuffer();
+ State eCurrentState = START;
+
+ while ( END != eCurrentState )
+ {
+ // look up the transition row for the current state
+ TransitionTable::const_iterator aRow = m_aTransitions.find( eCurrentState );
+ DBG_ASSERT( m_aTransitions.end() != aRow,
+ "NumberValidator::implValidateNormalized: invalid transition table (row not found)!" );
+
+ if ( m_aTransitions.end() != aRow )
+ {
+ // look up the current character in this row
+ StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
+ if ( aRow->second.end() != aTransition )
+ {
+ // there is a valid transition for this character
+ eCurrentState = aTransition->second;
+ ++pCheckPos;
+ continue;
+ }
+ }
+
+ // if we're here, there is no valid transition
+ break;
+ }
+
+ DBG_ASSERT( ( END != eCurrentState ) || ( 0 == *pCheckPos ),
+ "NumberValidator::implValidateNormalized: inconsistency!" );
+ // if we're at END, then the string should be done, too - the string should be normalized, means ending
+ // a "_" and not containing any other "_" (except at the start), and "_" is the only possibility
+ // to reach the END state
+
+ // the string is valid if and only if we reached the final state
+ return ( END == eCurrentState );
+ }
+
+ //--------------------------------------------------------------------------
+ sal_Bool NumberValidator::isValidNumericFragment( const String& _rText )
+ {
+ if ( !_rText.Len() )
+ // empty strings are always allowed
+ return sal_True;
+
+ // normalize the string
+ String sNormalized( RTL_CONSTASCII_STRINGPARAM( "_") );
+ sNormalized.Append( _rText );
+ sNormalized.AppendAscii( "_" );
+
+ return implValidateNormalized( sNormalized );
+ }
+}
+
+#endif
+
+//==============================================================================
+SvNumberFormatter* FormattedField::StaticFormatter::s_cFormatter = NULL;
+sal_uLong FormattedField::StaticFormatter::s_nReferences = 0;
+
+//------------------------------------------------------------------------------
+SvNumberFormatter* FormattedField::StaticFormatter::GetFormatter()
+{
+ if (!s_cFormatter)
+ {
+ // get the Office's locale and translate
+ LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage(
+ SvtSysLocale().GetLocaleData().getLocale() );
+ s_cFormatter = new SvNumberFormatter(
+ ::comphelper::getProcessServiceFactory(),
+ eSysLanguage);
+ }
+ return s_cFormatter;
+}
+
+//------------------------------------------------------------------------------
+FormattedField::StaticFormatter::StaticFormatter()
+{
+ ++s_nReferences;
+}
+
+//------------------------------------------------------------------------------
+FormattedField::StaticFormatter::~StaticFormatter()
+{
+ if (--s_nReferences == 0)
+ {
+ delete s_cFormatter;
+ s_cFormatter = NULL;
+ }
+}
+
+//==============================================================================
+DBG_NAME(FormattedField);
+
+#define INIT_MEMBERS() \
+ m_aLastSelection(0,0) \
+ ,m_dMinValue(0) \
+ ,m_dMaxValue(0) \
+ ,m_bHasMin(sal_False) \
+ ,m_bHasMax(sal_False) \
+ ,m_bStrictFormat(sal_True) \
+ ,m_bValueDirty(sal_True) \
+ ,m_bEnableEmptyField(sal_True) \
+ ,m_bAutoColor(sal_False) \
+ ,m_bEnableNaN(sal_False) \
+ ,m_dCurrentValue(0) \
+ ,m_dDefaultValue(0) \
+ ,m_nFormatKey(0) \
+ ,m_pFormatter(NULL) \
+ ,m_dSpinSize(1) \
+ ,m_dSpinFirst(-1000000) \
+ ,m_dSpinLast(1000000) \
+ ,m_bTreatAsNumber(sal_True) \
+ ,m_pLastOutputColor(NULL) \
+ ,m_bUseInputStringForFormatting(false)
+
+//------------------------------------------------------------------------------
+FormattedField::FormattedField(Window* pParent, WinBits nStyle, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
+ :SpinField(pParent, nStyle)
+ ,INIT_MEMBERS()
+{
+ DBG_CTOR(FormattedField, NULL);
+
+ if (pInitialFormatter)
+ {
+ m_pFormatter = pInitialFormatter;
+ m_nFormatKey = nFormatKey;
+ }
+}
+
+//------------------------------------------------------------------------------
+FormattedField::FormattedField(Window* pParent, const ResId& rResId, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
+ :SpinField(pParent, rResId)
+ ,INIT_MEMBERS()
+{
+ DBG_CTOR(FormattedField, NULL);
+
+ if (pInitialFormatter)
+ {
+ m_pFormatter = pInitialFormatter;
+ m_nFormatKey = nFormatKey;
+ }
+}
+
+//------------------------------------------------------------------------------
+FormattedField::~FormattedField()
+{
+ DBG_DTOR(FormattedField, NULL);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetValidateText(const XubString& rText, const String* pErrorText)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if (CheckText(rText))
+ SetText(rText);
+ else
+ if (pErrorText)
+ ImplSetTextImpl(*pErrorText, NULL);
+ else
+ ImplSetValue(m_dDefaultValue, sal_True);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetText(const XubString& rStr)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ SpinField::SetText(rStr);
+ m_bValueDirty = sal_True;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetText( const XubString& rStr, const Selection& rNewSelection )
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ SpinField::SetText( rStr, rNewSelection );
+ m_bValueDirty = sal_True;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetTextFormatted(const XubString& rStr)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+#if defined DBG_UTIL
+ if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
+ DBG_WARNING("FormattedField::SetTextFormatted : valid only with text formats !");
+#endif
+
+ m_sCurrentTextValue = rStr;
+
+ String sFormatted;
+ double dNumber = 0.0;
+ // IsNumberFormat changes the format key parameter
+ sal_uInt32 nTempFormatKey = static_cast< sal_uInt32 >( m_nFormatKey );
+ if( IsUsingInputStringForFormatting() &&
+ ImplGetFormatter()->IsNumberFormat(m_sCurrentTextValue, nTempFormatKey, dNumber) )
+ ImplGetFormatter()->GetInputLineString(dNumber, m_nFormatKey, sFormatted);
+ else
+ ImplGetFormatter()->GetOutputString(m_sCurrentTextValue, m_nFormatKey, sFormatted, &m_pLastOutputColor);
+
+ // calculate the new selection
+ Selection aSel(GetSelection());
+ Selection aNewSel(aSel);
+ aNewSel.Justify();
+ sal_uInt16 nNewLen = sFormatted.Len();
+ sal_uInt16 nCurrentLen = GetText().Len();
+ if ((nNewLen > nCurrentLen) && (aNewSel.Max() == nCurrentLen))
+ { // the new text is longer and the cursor was behind the last char (of the old text)
+ if (aNewSel.Min() == 0)
+ { // the whole text was selected -> select the new text on the whole, too
+ aNewSel.Max() = nNewLen;
+ if (!nCurrentLen)
+ { // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
+ sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
+ if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
+ { // selection should be from right to left -> swap min and max
+ aNewSel.Min() = aNewSel.Max();
+ aNewSel.Max() = 0;
+ }
+ }
+ }
+ else if (aNewSel.Max() == aNewSel.Min())
+ { // there was no selection -> set the cursor behind the new last char
+ aNewSel.Max() = nNewLen;
+ aNewSel.Min() = nNewLen;
+ }
+ }
+ else if (aNewSel.Max() > nNewLen)
+ aNewSel.Max() = nNewLen;
+ else
+ aNewSel = aSel; // don't use the justified version
+ SpinField::SetText(sFormatted, aNewSel);
+ m_bValueDirty = sal_False;
+}
+
+//------------------------------------------------------------------------------
+String FormattedField::GetTextValue() const
+{
+ if (m_bValueDirty)
+ {
+ ((FormattedField*)this)->m_sCurrentTextValue = GetText();
+ ((FormattedField*)this)->m_bValueDirty = sal_False;
+ }
+ return m_sCurrentTextValue;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::EnableNotANumber( sal_Bool _bEnable )
+{
+ if ( m_bEnableNaN == _bEnable )
+ return;
+
+ m_bEnableNaN = _bEnable;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetAutoColor(sal_Bool _bAutomatic)
+{
+ if (_bAutomatic == m_bAutoColor)
+ return;
+
+ m_bAutoColor = _bAutomatic;
+ if (m_bAutoColor)
+ { // if auto color is switched on, adjust the current text color, too
+ if (m_pLastOutputColor)
+ SetControlForeground(*m_pLastOutputColor);
+ else
+ SetControlForeground();
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::Modify()
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if (!IsStrictFormat())
+ {
+ m_bValueDirty = sal_True;
+ SpinField::Modify();
+ return;
+ }
+
+ String sCheck = GetText();
+ if (CheckText(sCheck))
+ {
+ m_sLastValidText = sCheck;
+ m_aLastSelection = GetSelection();
+ m_bValueDirty = sal_True;
+ }
+ else
+ {
+ ImplSetTextImpl(m_sLastValidText, &m_aLastSelection);
+ }
+
+ SpinField::Modify();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::ImplSetTextImpl(const XubString& rNew, Selection* pNewSel)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if (m_bAutoColor)
+ {
+ if (m_pLastOutputColor)
+ SetControlForeground(*m_pLastOutputColor);
+ else
+ SetControlForeground();
+ }
+
+ if (pNewSel)
+ SpinField::SetText(rNew, *pNewSel);
+ else
+ {
+ Selection aSel(GetSelection());
+ aSel.Justify();
+
+ sal_uInt16 nNewLen = rNew.Len();
+ sal_uInt16 nCurrentLen = GetText().Len();
+
+ if ((nNewLen > nCurrentLen) && (aSel.Max() == nCurrentLen))
+ { // new new text is longer and the cursor is behind the last char
+ if (aSel.Min() == 0)
+ { // the whole text was selected -> select the new text on the whole, too
+ aSel.Max() = nNewLen;
+ if (!nCurrentLen)
+ { // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
+ sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
+ if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
+ { // selection should be from right to left -> swap min and max
+ aSel.Min() = aSel.Max();
+ aSel.Max() = 0;
+ }
+ }
+ }
+ else if (aSel.Max() == aSel.Min())
+ { // there was no selection -> set the cursor behind the new last char
+ aSel.Max() = nNewLen;
+ aSel.Min() = nNewLen;
+ }
+ }
+ else if (aSel.Max() > nNewLen)
+ aSel.Max() = nNewLen;
+ SpinField::SetText(rNew, aSel);
+ }
+
+ m_bValueDirty = sal_True;
+ // muss nicht stimmen, aber sicherheitshalber ...
+}
+
+//------------------------------------------------------------------------------
+long FormattedField::PreNotify(NotifyEvent& rNEvt)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ if (rNEvt.GetType() == EVENT_KEYINPUT)
+ m_aLastSelection = GetSelection();
+ return SpinField::PreNotify(rNEvt);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::ImplSetFormatKey(sal_uLong nFormatKey)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ m_nFormatKey = nFormatKey;
+ sal_Bool bNeedFormatter = (m_pFormatter == NULL) && (nFormatKey != 0);
+ if (bNeedFormatter)
+ {
+ ImplGetFormatter(); // damit wird ein Standard-Formatter angelegt
+
+ m_nFormatKey = nFormatKey;
+ // kann sein, dass das in dem Standard-Formatter keinen Sinn macht, aber der nimmt dann ein Default-Format an.
+ // Auf diese Weise kann ich einfach einen der - formatteruebergreifended gleichen - Standard-Keys setzen.
+ DBG_ASSERT(m_pFormatter->GetEntry(nFormatKey) != NULL, "FormattedField::ImplSetFormatKey : invalid format key !");
+ // Wenn SetFormatKey aufgerufen wird, ohne dass ein Formatter existiert, muss der Key einer der Standard-Werte
+ // sein, der in allen Formattern (also auch in meinem neu angelegten) vorhanden ist.
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetFormatKey(sal_uLong nFormatKey)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ sal_Bool bNoFormatter = (m_pFormatter == NULL);
+ ImplSetFormatKey(nFormatKey);
+ FormatChanged((bNoFormatter && (m_pFormatter != NULL)) ? FCT_FORMATTER : FCT_KEYONLY);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, sal_Bool bResetFormat)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if (bResetFormat)
+ {
+ m_pFormatter = pFormatter;
+
+ // calc the default format key from the Office's UI locale
+ if ( m_pFormatter )
+ {
+ // get the Office's locale and translate
+ LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage(
+ SvtSysLocale().GetLocaleData().getLocale() );
+ // get the standard numeric format for this language
+ m_nFormatKey = m_pFormatter->GetStandardFormat( NUMBERFORMAT_NUMBER, eSysLanguage );
+ }
+ else
+ m_nFormatKey = 0;
+ }
+ else
+ {
+ XubString sOldFormat;
+ LanguageType aOldLang;
+ GetFormat(sOldFormat, aOldLang);
+
+ sal_uInt32 nDestKey = pFormatter->TestNewString(sOldFormat);
+ if (nDestKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ // die Sprache des neuen Formatters
+ const SvNumberformat* pDefaultEntry = pFormatter->GetEntry(0);
+ LanguageType aNewLang = pDefaultEntry ? pDefaultEntry->GetLanguage() : LANGUAGE_DONTKNOW;
+
+ // den alten Format-String in die neue Sprache konvertieren
+ sal_uInt16 nCheckPos;
+ short nType;
+ pFormatter->PutandConvertEntry(sOldFormat, nCheckPos, nType, nDestKey, aOldLang, aNewLang);
+ m_nFormatKey = nDestKey;
+ }
+ m_pFormatter = pFormatter;
+ }
+
+ FormatChanged(FCT_FORMATTER);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::GetFormat(XubString& rFormatString, LanguageType& eLang) const
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
+ DBG_ASSERT(pFormatEntry != NULL, "FormattedField::GetFormat: no number format for the given format key.");
+ rFormatString = pFormatEntry ? pFormatEntry->GetFormatstring() : XubString();
+ eLang = pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_DONTKNOW;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FormattedField::SetFormat(const XubString& rFormatString, LanguageType eLang)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ sal_uInt32 nNewKey = ImplGetFormatter()->TestNewString(rFormatString, eLang);
+ if (nNewKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
+ {
+ sal_uInt16 nCheckPos;
+ short nType;
+ XubString rFormat(rFormatString);
+ if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
+ return sal_False;
+ DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
+ }
+
+ if (nNewKey != m_nFormatKey)
+ SetFormatKey(nNewKey);
+ return sal_True;
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FormattedField::GetThousandsSep() const
+{
+ DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
+ "FormattedField::GetThousandsSep : your'e sure what your'e doing when setting the precision of a text format ?");
+
+ sal_Bool bThousand, IsRed;
+ sal_uInt16 nPrecision, nAnzLeading;
+ ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
+
+ return bThousand;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetThousandsSep(sal_Bool _bUseSeparator)
+{
+ DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
+ "FormattedField::SetThousandsSep : your'e sure what your'e doing when setting the precision of a text format ?");
+
+ // get the current settings
+ sal_Bool bThousand, IsRed;
+ sal_uInt16 nPrecision, nAnzLeading;
+ ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
+ if (bThousand == _bUseSeparator)
+ return;
+
+ // we need the language for the following
+ LanguageType eLang;
+ String sFmtDescription;
+ GetFormat(sFmtDescription, eLang);
+
+ // generate a new format ...
+ ImplGetFormatter()->GenerateFormat(sFmtDescription, m_nFormatKey, eLang, _bUseSeparator, IsRed, nPrecision, nAnzLeading);
+ // ... and introduce it to the formatter
+ sal_uInt16 nCheckPos;
+ sal_uInt32 nNewKey;
+ short nType;
+ ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
+
+ // set the new key
+ ImplSetFormatKey(nNewKey);
+ FormatChanged(FCT_THOUSANDSSEP);
+}
+
+//------------------------------------------------------------------------------
+sal_uInt16 FormattedField::GetDecimalDigits() const
+{
+ DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
+ "FormattedField::GetDecimalDigits : your'e sure what your'e doing when setting the precision of a text format ?");
+
+ sal_Bool bThousand, IsRed;
+ sal_uInt16 nPrecision, nAnzLeading;
+ ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
+
+ return nPrecision;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetDecimalDigits(sal_uInt16 _nPrecision)
+{
+ DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
+ "FormattedField::SetDecimalDigits : your'e sure what your'e doing when setting the precision of a text format ?");
+
+ // get the current settings
+ sal_Bool bThousand, IsRed;
+ sal_uInt16 nPrecision, nAnzLeading;
+ ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
+ if (nPrecision == _nPrecision)
+ return;
+
+ // we need the language for the following
+ LanguageType eLang;
+ String sFmtDescription;
+ GetFormat(sFmtDescription, eLang);
+
+ // generate a new format ...
+ ImplGetFormatter()->GenerateFormat(sFmtDescription, m_nFormatKey, eLang, bThousand, IsRed, _nPrecision, nAnzLeading);
+ // ... and introduce it to the formatter
+ sal_uInt16 nCheckPos;
+ sal_uInt32 nNewKey;
+ short nType;
+ ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
+
+ // set the new key
+ ImplSetFormatKey(nNewKey);
+ FormatChanged(FCT_PRECISION);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::FormatChanged( FORMAT_CHANGE_TYPE _nWhat )
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ m_pLastOutputColor = NULL;
+
+ if ( ( 0 != ( _nWhat & FCT_FORMATTER ) ) && m_pFormatter )
+ m_pFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
+ // 95845 - 03.04.2002 - fs@openoffice.org
+
+ ReFormat();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::Commit()
+{
+ // remember the old text
+ String sOld( GetText() );
+
+ // do the reformat
+ ReFormat();
+
+ // did the text change?
+ if ( GetText() != sOld )
+ { // consider the field as modified
+ Modify();
+ // but we have the most recent value now
+ m_bValueDirty = sal_False;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::ReFormat()
+{
+ if (!IsEmptyFieldEnabled() || GetText().Len())
+ {
+ if (TreatingAsNumber())
+ {
+ double dValue = GetValue();
+ if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
+ return;
+ ImplSetValue( dValue, sal_True );
+ }
+ else
+ SetTextFormatted(GetTextValue());
+ }
+}
+
+//------------------------------------------------------------------------------
+long FormattedField::Notify(NotifyEvent& rNEvt)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if ((rNEvt.GetType() == EVENT_KEYINPUT) && !IsReadOnly())
+ {
+ const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
+ sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN:
+ if (!nMod && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
+ {
+ // the base class would translate this into calls to Up/Down/First/Last,
+ // but we don't want this if we are text-formatted
+ return 1;
+ }
+ }
+ }
+
+ if ((rNEvt.GetType() == EVENT_COMMAND) && !IsReadOnly())
+ {
+ const CommandEvent* pCommand = rNEvt.GetCommandEvent();
+ if (pCommand->GetCommand() == COMMAND_WHEEL)
+ {
+ const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
+ if ((pData->GetMode() == COMMAND_WHEEL_SCROLL) && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
+ {
+ // same as above : prevent the base class from doing Up/Down-calls
+ // (normally I should put this test into the Up/Down methods itself, shouldn't I ?)
+ // FS - 71553 - 19.01.00
+ return 1;
+ }
+ }
+ }
+
+ if (rNEvt.GetType() == EVENT_LOSEFOCUS)
+ {
+ // Sonderbehandlung fuer leere Texte
+ if (GetText().Len() == 0)
+ {
+ if (!IsEmptyFieldEnabled())
+ {
+ if (TreatingAsNumber())
+ {
+ ImplSetValue(m_dCurrentValue, sal_True);
+ Modify();
+ }
+ else
+ {
+ String sNew = GetTextValue();
+ if (sNew.Len())
+ SetTextFormatted(sNew);
+ else
+ SetTextFormatted(m_sDefaultText);
+ }
+ m_bValueDirty = sal_False;
+ }
+ }
+ else
+ {
+ Commit();
+ }
+ }
+
+ return SpinField::Notify( rNEvt );
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetMinValue(double dMin)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMinValue : only to be used in numeric mode !");
+
+ m_dMinValue = dMin;
+ m_bHasMin = sal_True;
+ // fuer die Ueberpruefung des aktuellen Wertes an der neuen Grenze -> ImplSetValue
+ ReFormat();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetMaxValue(double dMax)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMaxValue : only to be used in numeric mode !");
+
+ m_dMaxValue = dMax;
+ m_bHasMax = sal_True;
+ // fuer die Ueberpruefung des aktuellen Wertes an der neuen Grenze -> ImplSetValue
+ ReFormat();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetTextValue(const XubString& rText)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ SetText(rText);
+ ReFormat();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::EnableEmptyField(sal_Bool bEnable)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ if (bEnable == m_bEnableEmptyField)
+ return;
+
+ m_bEnableEmptyField = bEnable;
+ if (!m_bEnableEmptyField && GetText().Len()==0)
+ ImplSetValue(m_dCurrentValue, sal_True);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::ImplSetValue(double dVal, sal_Bool bForce)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if (m_bHasMin && (dVal<m_dMinValue))
+ dVal = m_dMinValue;
+ if (m_bHasMax && (dVal>m_dMaxValue))
+ dVal = m_dMaxValue;
+ if (!bForce && (dVal == GetValue()))
+ return;
+
+ DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplSetValue : can't set a value without a formatter !");
+
+ m_bValueDirty = sal_False;
+ m_dCurrentValue = dVal;
+
+ String sNewText;
+ if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
+ {
+ // zuerst die Zahl als String im Standard-Format
+ String sTemp;
+ ImplGetFormatter()->GetOutputString(dVal, 0, sTemp, &m_pLastOutputColor);
+ // dann den String entsprechend dem Text-Format
+ ImplGetFormatter()->GetOutputString(sTemp, m_nFormatKey, sNewText, &m_pLastOutputColor);
+ }
+ else
+ {
+ if( IsUsingInputStringForFormatting())
+ ImplGetFormatter()->GetInputLineString(dVal, m_nFormatKey, sNewText);
+ else
+ ImplGetFormatter()->GetOutputString(dVal, m_nFormatKey, sNewText, &m_pLastOutputColor);
+ }
+
+ ImplSetTextImpl(sNewText, NULL);
+ m_bValueDirty = sal_False;
+ DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FormattedField::ImplGetValue(double& dNewVal)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ dNewVal = m_dCurrentValue;
+ if (!m_bValueDirty)
+ return sal_True;
+
+ dNewVal = m_dDefaultValue;
+ String sText(GetText());
+ if (!sText.Len())
+ return sal_True;
+
+ DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplGetValue : can't give you a current value without a formatter !");
+
+ sal_uInt32 nFormatKey = m_nFormatKey; // IsNumberFormat veraendert den FormatKey ...
+
+ if (ImplGetFormatter()->IsTextFormat(nFormatKey) && m_bTreatAsNumber)
+ // damit wir in einem als Text formatierten Feld trotzdem eine Eingabe wie '1,1' erkennen ...
+ nFormatKey = 0;
+
+ // Sonderbehandlung fuer %-Formatierung
+ if (ImplGetFormatter()->GetType(m_nFormatKey) == NUMBERFORMAT_PERCENT)
+ {
+ // the language of our format
+ LanguageType eLanguage = m_pFormatter->GetEntry(m_nFormatKey)->GetLanguage();
+ // the default number format for this language
+ sal_uLong nStandardNumericFormat = m_pFormatter->GetStandardFormat(NUMBERFORMAT_NUMBER, eLanguage);
+
+ sal_uInt32 nTempFormat = nStandardNumericFormat;
+ double dTemp;
+ if (m_pFormatter->IsNumberFormat(sText, nTempFormat, dTemp) &&
+ NUMBERFORMAT_NUMBER == m_pFormatter->GetType(nTempFormat))
+ // der String entspricht einer Number-Formatierung, hat also nur kein %
+ // -> append it
+ sText += '%';
+ // (with this, a input of '3' becomes '3%', which then by the formatter is translated
+ // into 0.03. Without this, the formatter would give us the double 3 for an input '3',
+ // which equals 300 percent.
+ }
+ if (!ImplGetFormatter()->IsNumberFormat(sText, nFormatKey, dNewVal))
+ return sal_False;
+
+
+ if (m_bHasMin && (dNewVal<m_dMinValue))
+ dNewVal = m_dMinValue;
+ if (m_bHasMax && (dNewVal>m_dMaxValue))
+ dNewVal = m_dMaxValue;
+ return sal_True;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetValue(double dVal)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ ImplSetValue(dVal, m_bValueDirty);
+}
+
+//------------------------------------------------------------------------------
+double FormattedField::GetValue()
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if ( !ImplGetValue( m_dCurrentValue ) )
+ {
+ if ( m_bEnableNaN )
+ ::rtl::math::setNan( &m_dCurrentValue );
+ else
+ m_dCurrentValue = m_dDefaultValue;
+ }
+
+ m_bValueDirty = sal_False;
+ return m_dCurrentValue;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::Up()
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ SetValue(GetValue() + m_dSpinSize);
+ // das setValue handelt Bereichsueberschreitungen (min/max) automatisch
+ SetModifyFlag();
+ Modify();
+
+ SpinField::Up();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::Down()
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ SetValue(GetValue() - m_dSpinSize);
+ SetModifyFlag();
+ Modify();
+
+ SpinField::Down();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::First()
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ if (m_bHasMin)
+ {
+ SetValue(m_dMinValue);
+ SetModifyFlag();
+ Modify();
+ }
+
+ SpinField::First();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::Last()
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ if (m_bHasMax)
+ {
+ SetValue(m_dMaxValue);
+ SetModifyFlag();
+ Modify();
+ }
+
+ SpinField::Last();
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::UseInputStringForFormatting( bool bUseInputStr /* = true */ )
+{
+ m_bUseInputStringForFormatting = bUseInputStr;
+}
+
+//------------------------------------------------------------------------------
+bool FormattedField::IsUsingInputStringForFormatting() const
+{
+ return m_bUseInputStringForFormatting;
+}
+
+
+//==============================================================================
+//------------------------------------------------------------------------------
+DoubleNumericField::~DoubleNumericField()
+{
+#ifdef REGEXP_SUPPORT
+ delete m_pConformanceTester;
+#else
+ delete m_pNumberValidator;
+#endif
+}
+
+//------------------------------------------------------------------------------
+void DoubleNumericField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
+{
+ ResetConformanceTester();
+ FormattedField::FormatChanged(nWhat);
+}
+
+//------------------------------------------------------------------------------
+sal_Bool DoubleNumericField::CheckText(const XubString& sText) const
+{
+ // We'd like to implement this using the NumberFormatter::IsNumberFormat, but unfortunately, this doesn't
+ // recognize fragments of numbers (like, for instance "1e", which happens during entering e.g. "1e10")
+ // Thus, the roundabout way via a regular expression
+
+#ifdef REGEXP_SUPPORT
+ if (!sText.Len())
+ return sal_True;
+
+ String sForceComplete = '_';
+ sForceComplete += sText;
+ sForceComplete += '_';
+
+ sal_uInt16 nStart = 0, nEnd = sForceComplete.Len();
+ sal_Bool bFound = m_pConformanceTester->SearchFrwrd(sForceComplete, &nStart, &nEnd);
+
+ if (bFound && (nStart == 0) && (nEnd == sForceComplete.Len()))
+ return sal_True;
+
+ return sal_False;
+#else
+ return m_pNumberValidator->isValidNumericFragment( sText );
+#endif
+}
+
+//------------------------------------------------------------------------------
+void DoubleNumericField::ResetConformanceTester()
+{
+ // the thousands and the decimal separator are language dependent
+ const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
+
+ sal_Unicode cSeparatorThousand = ',';
+ sal_Unicode cSeparatorDecimal = '.';
+ if (pFormatEntry)
+ {
+ Locale aLocale;
+ MsLangId::convertLanguageToLocale( pFormatEntry->GetLanguage(), aLocale );
+ LocaleDataWrapper aLocaleInfo(::comphelper::getProcessServiceFactory(), aLocale);
+
+ String sSeparator = aLocaleInfo.getNumThousandSep();
+ if (sSeparator.Len())
+ cSeparatorThousand = sSeparator.GetBuffer()[0];
+
+ sSeparator = aLocaleInfo.getNumDecimalSep();
+ if (sSeparator.Len())
+ cSeparatorDecimal = sSeparator.GetBuffer()[0];
+ }
+
+#ifdef REGEXP_SUPPORT
+ String sDescription = String::CreateFromAscii(szNumericInput);
+
+ String sReplaceWith((sal_Unicode)'\\');
+ sReplaceWith += cSeparatorThousand;
+ sDescription.SearchAndReplaceAscii("\\,", sReplaceWith);
+
+ sReplaceWith = (sal_Unicode)'\\';
+ sReplaceWith += cSeparatorDecimal;
+ sDescription.SearchAndReplaceAscii("\\.", sReplaceWith);
+
+ delete m_pConformanceTester;
+
+ SearchOptions aParam;
+ aParam.algorithmType = SearchAlgorithms_REGEXP;
+ aParam.searchFlag = SearchFlags::ALL_IGNORE_CASE;
+ aParam.searchString = sDescription;
+ aParam.transliterateFlags = 0;
+
+ String sLanguage, sCountry;
+ ConvertLanguageToIsoNames( pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_ENGLISH_US, sLanguage, sCountry );
+ aParam.Locale.Language = sLanguage;
+ aParam.Locale.Country = sCountry;
+
+ m_pConformanceTester = new ::utl::TextSearch(aParam);
+#else
+ delete m_pNumberValidator;
+ m_pNumberValidator = new validation::NumberValidator( cSeparatorThousand, cSeparatorDecimal );
+#endif
+}
+
+
+//==============================================================================
+
+//------------------------------------------------------------------------------
+DoubleCurrencyField::DoubleCurrencyField(Window* pParent, WinBits nStyle)
+ :FormattedField(pParent, nStyle)
+ ,m_bChangingFormat(sal_False)
+{
+ m_bPrependCurrSym = sal_False;
+
+ // initialize with a system currency format
+ m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
+ UpdateCurrencyFormat();
+}
+
+//------------------------------------------------------------------------------
+DoubleCurrencyField::DoubleCurrencyField(Window* pParent, const ResId& rResId)
+ :FormattedField(pParent, rResId)
+ ,m_bChangingFormat(sal_False)
+{
+ m_bPrependCurrSym = sal_False;
+
+ // initialize with a system currency format
+ m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
+ UpdateCurrencyFormat();
+}
+
+//------------------------------------------------------------------------------
+void DoubleCurrencyField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
+{
+ if (m_bChangingFormat)
+ {
+ FormattedField::FormatChanged(nWhat);
+ return;
+ }
+
+ switch (nWhat)
+ {
+ case FCT_FORMATTER:
+ case FCT_PRECISION:
+ case FCT_THOUSANDSSEP:
+ // the aspects which changed don't take our currency settings into account (in fact, they most probably
+ // destroyed them)
+ UpdateCurrencyFormat();
+ break;
+ case FCT_KEYONLY:
+ DBG_ERROR("DoubleCurrencyField::FormatChanged : somebody modified my key !");
+ // We always build our own format from the settings we get via special methods (setCurrencySymbol etc.).
+ // Nobody but ourself should modifiy the format key directly !
+ break;
+ }
+
+ FormattedField::FormatChanged(nWhat);
+}
+
+//------------------------------------------------------------------------------
+void DoubleCurrencyField::setCurrencySymbol(const String& _sSymbol)
+{
+ if (m_sCurrencySymbol == _sSymbol)
+ return;
+
+ m_sCurrencySymbol = _sSymbol;
+ UpdateCurrencyFormat();
+ FormatChanged(FCT_CURRENCY_SYMBOL);
+}
+
+//------------------------------------------------------------------------------
+void DoubleCurrencyField::setPrependCurrSym(sal_Bool _bPrepend)
+{
+ if (m_bPrependCurrSym == _bPrepend)
+ return;
+
+ m_bPrependCurrSym = _bPrepend;
+ UpdateCurrencyFormat();
+ FormatChanged(FCT_CURRSYM_POSITION);
+}
+
+//------------------------------------------------------------------------------
+void DoubleCurrencyField::UpdateCurrencyFormat()
+{
+ // the old settings
+ XubString sOldFormat;
+ LanguageType eLanguage;
+ GetFormat(sOldFormat, eLanguage);
+ sal_Bool bThSep = GetThousandsSep();
+ sal_uInt16 nDigits = GetDecimalDigits();
+
+ // build a new format string with the base class' and my own settings
+ Locale aLocale;
+ MsLangId::convertLanguageToLocale( eLanguage, aLocale );
+ LocaleDataWrapper aLocaleInfo(::comphelper::getProcessServiceFactory(), aLocale);
+
+ XubString sNewFormat;
+ if (bThSep)
+ {
+ sNewFormat = '#';
+ sNewFormat += aLocaleInfo.getNumThousandSep();
+ sNewFormat.AppendAscii("##0");
+ }
+ else
+ sNewFormat = '0';
+
+ if (nDigits)
+ {
+ sNewFormat += aLocaleInfo.getNumDecimalSep();
+
+ XubString sTemp;
+ sTemp.Fill(nDigits, '0');
+ sNewFormat += sTemp;
+ }
+
+ if (getPrependCurrSym())
+ {
+ XubString sSymbol = getCurrencySymbol();
+ sSymbol.EraseLeadingChars(' ');
+ sSymbol.EraseTrailingChars(' ');
+
+ XubString sTemp = String::CreateFromAscii("[$");
+ sTemp += sSymbol;
+ sTemp.AppendAscii("] ");
+ sTemp += sNewFormat;
+
+ // for negative values : $ -0.00, not -$ 0.00 ...
+ // (the real solution would be a possibility to choose a "positive currency format" and a "negative currency format" ...
+ // But not now ... (and hey, you could take a formatted field for this ....))
+ // FS - 31.03.00 74642
+ sTemp.AppendAscii(";[$");
+ sTemp += sSymbol;
+ sTemp.AppendAscii("] -");
+ sTemp += sNewFormat;
+
+ sNewFormat = sTemp;
+ }
+ else
+ {
+ XubString sTemp = getCurrencySymbol();
+ sTemp.EraseLeadingChars(' ');
+ sTemp.EraseTrailingChars(' ');
+
+ sNewFormat += String::CreateFromAscii(" [$");
+ sNewFormat += sTemp;
+ sNewFormat += ']';
+ }
+
+ // set this new basic format
+ m_bChangingFormat = sal_True;
+ SetFormat(sNewFormat, eLanguage);
+ m_bChangingFormat = sal_False;
+}
+
diff --git a/svtools/source/control/headbar.cxx b/svtools/source/control/headbar.cxx
new file mode 100755
index 000000000000..06886339fda5
--- /dev/null
+++ b/svtools/source/control/headbar.cxx
@@ -0,0 +1,1651 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _SV_HEADBAR_CXX
+#include <svtools/headbar.hxx>
+#include <tools/debug.hxx>
+#ifndef _TOOLS_LIST_HXX
+#include <tools/list.hxx>
+#endif
+
+#ifndef _VCL_APP_HXX
+#include <vcl/svapp.hxx>
+#endif
+#ifndef _VCL_HELP_HXX
+#include <vcl/help.hxx>
+#endif
+#ifndef _VCL_IMAGE_HXX
+#include <vcl/image.hxx>
+#endif
+#include <com/sun/star/accessibility/XAccessible.hpp>
+
+// =======================================================================
+
+struct ImplHeadItem
+{
+ sal_uInt16 mnId;
+ HeaderBarItemBits mnBits;
+ long mnSize;
+ rtl::OString maHelpId;
+ Image maImage;
+ XubString maOutText;
+ XubString maText;
+ XubString maHelpText;
+ void* mpUserData;
+};
+
+DECLARE_LIST( ImplHeadItemList, ImplHeadItem* )
+
+// =======================================================================
+
+#define HEAD_ARROWSIZE1 4
+#define HEAD_ARROWSIZE2 7
+
+#define HEADERBAR_TEXTOFF 2
+#define HEADERBAR_ARROWOFF 5
+#define HEADERBAR_SPLITOFF 3
+
+#define HEADERBAR_DRAGOFF 4
+#define HEADERBAR_DRAGOUTOFF 15
+
+#define HEAD_HITTEST_ITEM ((sal_uInt16)0x0001)
+#define HEAD_HITTEST_DIVIDER ((sal_uInt16)0x0002)
+
+// =======================================================================
+
+void HeaderBar::ImplInit( WinBits nWinStyle )
+{
+ mpItemList = new ImplHeadItemList;
+ mnBorderOff1 = 0;
+ mnBorderOff2 = 0;
+ mnOffset = 0;
+ mnDX = 0;
+ mnDY = 0;
+ mnDragSize = 0;
+ mnStartPos = 0;
+ mnDragPos = 0;
+ mnMouseOff = 0;
+ mnCurItemId = 0;
+ mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
+ mbDrag = sal_False;
+ mbItemDrag = sal_False;
+ mbOutDrag = sal_False;
+ mbItemMode = sal_False;
+
+ // StyleBits auswerten
+ if ( nWinStyle & WB_DRAG )
+ mbDragable = sal_True;
+ else
+ mbDragable = sal_False;
+ if ( nWinStyle & WB_BUTTONSTYLE )
+ mbButtonStyle = sal_True;
+ else
+ mbButtonStyle = sal_False;
+ if ( nWinStyle & WB_BORDER )
+ {
+ mnBorderOff1 = 1;
+ mnBorderOff2 = 1;
+ }
+ else
+ {
+ if ( nWinStyle & WB_BOTTOMBORDER )
+ mnBorderOff2 = 1;
+ }
+
+ ImplInitSettings( sal_True, sal_True, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+HeaderBar::HeaderBar( Window* pParent, WinBits nWinStyle ) :
+ Window( pParent, nWinStyle & WB_3DLOOK )
+{
+ ImplInit( nWinStyle );
+ SetSizePixel( CalcWindowSizePixel() );
+}
+
+// -----------------------------------------------------------------------
+
+HeaderBar::HeaderBar( Window* pParent, const ResId& rResId ) :
+ Window( pParent, rResId )
+{
+ ImplInit( rResId.GetWinBits() );
+}
+
+// -----------------------------------------------------------------------
+
+HeaderBar::~HeaderBar()
+{
+ // Alle Items loeschen
+ ImplHeadItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ delete mpItemList;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplInitSettings( sal_Bool bFont,
+ sal_Bool bForeground, sal_Bool bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont;
+ aFont = rStyleSettings.GetToolFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetButtonTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else
+ aColor = rStyleSettings.GetFaceColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long HeaderBar::ImplGetItemPos( sal_uInt16 nPos ) const
+{
+ long nX = -mnOffset;
+ for ( sal_uInt16 i = 0; i < nPos; i++ )
+ nX += mpItemList->GetObject( i )->mnSize;
+ return nX;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle HeaderBar::ImplGetItemRect( sal_uInt16 nPos ) const
+{
+ Rectangle aRect( ImplGetItemPos( nPos ), 0, 0, mnDY-1 );
+ aRect.Right() = aRect.Left() + mpItemList->GetObject( nPos )->mnSize - 1;
+ // Gegen Ueberlauf auf einigen Systemen testen
+ if ( aRect.Right() > 16000 )
+ aRect.Right() = 16000;
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 HeaderBar::ImplHitTest( const Point& rPos,
+ long& nMouseOff, sal_uInt16& nPos ) const
+{
+ ImplHeadItem* pItem;
+ sal_uInt16 nCount = (sal_uInt16)mpItemList->Count();
+ sal_Bool bLastFixed = sal_True;
+ long nX = -mnOffset;
+
+ for ( sal_uInt16 i = 0; i < nCount; i++ )
+ {
+ pItem = mpItemList->GetObject( i );
+
+ if ( rPos.X() < (nX+pItem->mnSize) )
+ {
+ sal_uInt16 nMode;
+
+ if ( !bLastFixed && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
+ {
+ nMode = HEAD_HITTEST_DIVIDER;
+ nPos = i-1;
+ nMouseOff = rPos.X()-nX+1;
+ }
+ else
+ {
+ nPos = i;
+
+ if ( !(pItem->mnBits & HIB_FIXED) && (rPos.X() >= (nX+pItem->mnSize-HEADERBAR_SPLITOFF)) )
+ {
+ nMode = HEAD_HITTEST_DIVIDER;
+ nMouseOff = rPos.X()-(nX+pItem->mnSize);
+ }
+ else
+ {
+ nMode = HEAD_HITTEST_ITEM;
+ nMouseOff = rPos.X()-nX;
+ }
+ }
+
+ return nMode;
+ }
+
+ if ( pItem->mnBits & HIB_FIXED )
+ bLastFixed = sal_True;
+ else
+ bLastFixed = sal_False;
+
+ nX += pItem->mnSize;
+ }
+
+ if ( !bLastFixed )
+ {
+ pItem = mpItemList->GetObject( nCount-1 );
+ if ( (pItem->mnSize < 4) && (rPos.X() < (nX+HEADERBAR_SPLITOFF)) )
+ {
+ nPos = nCount-1;
+ nMouseOff = rPos.X()-nX+1;
+ return HEAD_HITTEST_DIVIDER;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplInvertDrag( sal_uInt16 nStartPos, sal_uInt16 nEndPos )
+{
+ Rectangle aRect1 = ImplGetItemRect( nStartPos );
+ Rectangle aRect2 = ImplGetItemRect( nEndPos );
+ Point aStartPos = aRect1.Center();
+ Point aEndPos = aStartPos;
+ Rectangle aStartRect( aStartPos.X()-2, aStartPos.Y()-2,
+ aStartPos.X()+2, aStartPos.Y()+2 );
+
+ if ( nEndPos > nStartPos )
+ {
+ aStartPos.X() += 3;
+ aEndPos.X() = aRect2.Right()-6;
+ }
+ else
+ {
+ aStartPos.X() -= 3;
+ aEndPos.X() = aRect2.Left()+6;
+ }
+
+ SetRasterOp( ROP_INVERT );
+ DrawRect( aStartRect );
+ DrawLine( aStartPos, aEndPos );
+ if ( nEndPos > nStartPos )
+ {
+ DrawLine( Point( aEndPos.X()+1, aEndPos.Y()-3 ),
+ Point( aEndPos.X()+1, aEndPos.Y()+3 ) );
+ DrawLine( Point( aEndPos.X()+2, aEndPos.Y()-2 ),
+ Point( aEndPos.X()+2, aEndPos.Y()+2 ) );
+ DrawLine( Point( aEndPos.X()+3, aEndPos.Y()-1 ),
+ Point( aEndPos.X()+3, aEndPos.Y()+1 ) );
+ DrawPixel( Point( aEndPos.X()+4, aEndPos.Y() ) );
+ }
+ else
+ {
+ DrawLine( Point( aEndPos.X()-1, aEndPos.Y()-3 ),
+ Point( aEndPos.X()-1, aEndPos.Y()+3 ) );
+ DrawLine( Point( aEndPos.X()-2, aEndPos.Y()-2 ),
+ Point( aEndPos.X()-2, aEndPos.Y()+2 ) );
+ DrawLine( Point( aEndPos.X()-3, aEndPos.Y()-1 ),
+ Point( aEndPos.X()-3, aEndPos.Y()+1 ) );
+ DrawPixel( Point( aEndPos.X()-4, aEndPos.Y() ) );
+ }
+ SetRasterOp( ROP_OVERPAINT );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplDrawItem( OutputDevice* pDev,
+ sal_uInt16 nPos, sal_Bool bHigh, sal_Bool bDrag,
+ const Rectangle& rItemRect,
+ const Rectangle* pRect,
+ sal_uLong )
+{
+ Rectangle aRect = rItemRect;
+
+ // Wenn kein Platz, dann brauchen wir auch nichts ausgeben
+ if ( aRect.GetWidth() <= 1 )
+ return;
+
+ // Feststellen, ob Rectangle ueberhaupt sichtbar
+ if ( pRect )
+ {
+ if ( aRect.Right() < pRect->Left() )
+ return;
+ else if ( aRect.Left() > pRect->Right() )
+ return;
+ }
+ else
+ {
+ if ( aRect.Right() < 0 )
+ return;
+ else if ( aRect.Left() > mnDX )
+ return;
+ }
+
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ HeaderBarItemBits nBits = pItem->mnBits;
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ // Border muss nicht gemalt werden
+ aRect.Top() += mnBorderOff1;
+ aRect.Bottom() -= mnBorderOff2;
+
+ // Hintergrund loeschen
+ if ( !pRect || bDrag )
+ {
+ if ( bDrag )
+ {
+ pDev->SetLineColor();
+ pDev->SetFillColor( rStyleSettings.GetCheckedColor() );
+ pDev->DrawRect( aRect );
+ }
+ else
+ pDev->DrawWallpaper( aRect, GetBackground() );
+ }
+
+ // Trennlinie malen
+ pDev->SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ pDev->DrawLine( Point( aRect.Right(), aRect.Top() ),
+ Point( aRect.Right(), aRect.Bottom() ) );
+
+ // ButtonStyle malen
+ // avoid 3D borders
+ Color aSelectionTextColor( COL_TRANSPARENT );
+ if( bHigh )
+ DrawSelectionBackground( aRect, 1, sal_True, sal_False, sal_False, &aSelectionTextColor );
+ else if ( !mbButtonStyle || (nBits & HIB_FLAT) )
+ DrawSelectionBackground( aRect, 0, sal_True, sal_False, sal_False, &aSelectionTextColor );
+
+ // Wenn kein Platz, dann brauchen wir auch nichts ausgeben
+ if ( aRect.GetWidth() < 1 )
+ return;
+
+ // Positionen und Groessen berechnen und Inhalt ausgeben
+ pItem->maOutText = pItem->maText;
+ Size aImageSize = pItem->maImage.GetSizePixel();
+ Size aTxtSize( pDev->GetTextWidth( pItem->maOutText ), 0 );
+ if ( pItem->maOutText.Len() )
+ aTxtSize.Height() = pDev->GetTextHeight();
+ long nArrowWidth = 0;
+ if ( nBits & (HIB_UPARROW | HIB_DOWNARROW) )
+ nArrowWidth = HEAD_ARROWSIZE2+HEADERBAR_ARROWOFF;
+
+ // Wenn kein Platz fuer Image, dann nicht ausgeben
+ long nTestHeight = aImageSize.Height();
+ if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
+ nTestHeight += aTxtSize.Height();
+ if ( (aImageSize.Width() > aRect.GetWidth()) || (nTestHeight > aRect.GetHeight()) )
+ {
+ aImageSize.Width() = 0;
+ aImageSize.Height() = 0;
+ }
+
+ // Text auf entsprechende Laenge kuerzen
+ sal_Bool bLeftText = sal_False;
+ long nMaxTxtWidth = aRect.GetWidth()-(HEADERBAR_TEXTOFF*2)-nArrowWidth;
+ if ( nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE) )
+ nMaxTxtWidth -= aImageSize.Width();
+ long nTxtWidth = aTxtSize.Width();
+ if ( nTxtWidth > nMaxTxtWidth )
+ {
+ bLeftText = sal_True;
+ // 3 == Len of "..."
+ pItem->maOutText.AppendAscii( "..." );
+ do
+ {
+ pItem->maOutText.Erase( pItem->maOutText.Len()-3-1, 1 );
+ nTxtWidth = pDev->GetTextWidth( pItem->maOutText );
+ }
+ while ( (nTxtWidth > nMaxTxtWidth) && (pItem->maOutText.Len() > 3) );
+ if ( pItem->maOutText.Len() == 3 )
+ {
+ nTxtWidth = 0;
+ pItem->maOutText.Erase();
+ }
+ }
+
+ // Text/Imageposition berechnen
+ long nTxtPos;
+ if ( !bLeftText && (nBits & HIB_RIGHT) )
+ {
+ nTxtPos = aRect.Right()-nTxtWidth-HEADERBAR_TEXTOFF;
+ if ( nBits & HIB_RIGHTIMAGE )
+ nTxtPos -= aImageSize.Width();
+ }
+ else if ( !bLeftText && (nBits & HIB_CENTER) )
+ {
+ long nTempWidth = nTxtWidth;
+ if ( nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE) )
+ nTempWidth += aImageSize.Width();
+ nTxtPos = aRect.Left()+(aRect.GetWidth()-nTempWidth)/2;
+ if ( nBits & HIB_LEFTIMAGE )
+ nTxtPos += aImageSize.Width();
+ if ( nArrowWidth )
+ {
+ if ( nTxtPos+nTxtWidth+nArrowWidth >= aRect.Right() )
+ {
+ nTxtPos = aRect.Left()+HEADERBAR_TEXTOFF;
+ if ( nBits & HIB_LEFTIMAGE )
+ nTxtPos += aImageSize.Width();
+ }
+ }
+ }
+ else
+ {
+ nTxtPos = aRect.Left()+HEADERBAR_TEXTOFF;
+ if ( nBits & HIB_LEFTIMAGE )
+ nTxtPos += aImageSize.Width();
+ if ( nBits & HIB_RIGHT )
+ nTxtPos += nArrowWidth;
+ }
+
+ // TextPosition berechnen
+ long nTxtPosY = 0;
+ if ( pItem->maOutText.Len() || (nArrowWidth && aTxtSize.Height()) )
+ {
+ if ( nBits & HIB_TOP )
+ {
+ nTxtPosY = aRect.Top();
+ if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
+ nTxtPosY += aImageSize.Height();
+ }
+ else if ( nBits & HIB_BOTTOM )
+ nTxtPosY = aRect.Bottom()-aTxtSize.Height();
+ else
+ {
+ long nTempHeight = aTxtSize.Height();
+ if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
+ nTempHeight += aImageSize.Height();
+ nTxtPosY = aRect.Top()+((aRect.GetHeight()-nTempHeight)/2);
+ if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
+ nTxtPosY += aImageSize.Height();
+ }
+ }
+
+ // Text ausgebeben
+ if ( pItem->maOutText.Len() )
+ {
+ if( aSelectionTextColor != Color( COL_TRANSPARENT ) )
+ {
+ pDev->Push( PUSH_TEXTCOLOR );
+ pDev->SetTextColor( aSelectionTextColor );
+ }
+ if ( IsEnabled() )
+ pDev->DrawText( Point( nTxtPos, nTxtPosY ), pItem->maOutText );
+ else
+ pDev->DrawCtrlText( Point( nTxtPos, nTxtPosY ), pItem->maOutText, 0, STRING_LEN, TEXT_DRAW_DISABLE );
+ if( aSelectionTextColor != Color( COL_TRANSPARENT ) )
+ pDev->Pop();
+ }
+
+ // Wenn Image vorhanden, Position berechnen und ausgeben
+ long nImagePosY = 0;
+ if ( aImageSize.Width() && aImageSize.Height() )
+ {
+ long nImagePos = nTxtPos;
+ if ( nBits & HIB_LEFTIMAGE )
+ {
+ nImagePos -= aImageSize.Width();
+ if ( nBits & HIB_RIGHT )
+ nImagePos -= nArrowWidth;
+ }
+ else if ( nBits & HIB_RIGHTIMAGE )
+ {
+ nImagePos += nTxtWidth;
+ if ( !(nBits & HIB_RIGHT) )
+ nImagePos += nArrowWidth;
+ }
+ else
+ {
+ if ( nBits & HIB_RIGHT )
+ nImagePos = aRect.Right()-aImageSize.Width();
+ else if ( nBits & HIB_CENTER )
+ nImagePos = aRect.Left()+(aRect.GetWidth()-aImageSize.Width())/2;
+ else
+ nImagePos = aRect.Left()+HEADERBAR_TEXTOFF;
+ }
+
+ if ( nBits & HIB_TOP )
+ nImagePosY = aRect.Top();
+ else if ( nBits & HIB_BOTTOM )
+ {
+ nImagePosY = aRect.Bottom()-aImageSize.Height();
+ if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
+ nImagePosY -= aTxtSize.Height();
+ }
+ else
+ {
+ long nTempHeight = aImageSize.Height();
+ if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) )
+ nTempHeight += aTxtSize.Height();
+ nImagePosY = aRect.Top()+((aRect.GetHeight()-nTempHeight)/2);
+ }
+ if ( nImagePos+aImageSize.Width() <= aRect.Right() )
+ {
+ sal_uInt16 nStyle = 0;
+ if ( !IsEnabled() )
+ nStyle |= IMAGE_DRAW_DISABLE;
+ pDev->DrawImage( Point( nImagePos, nImagePosY ), pItem->maImage, nStyle );
+ }
+ }
+
+ if ( nBits & (HIB_UPARROW | HIB_DOWNARROW) )
+ {
+ long nArrowX = nTxtPos;
+ if ( nBits & HIB_RIGHT )
+ nArrowX -= nArrowWidth;
+ else
+ nArrowX += nTxtWidth+HEADERBAR_ARROWOFF;
+ if ( !(nBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) && !pItem->maText.Len() )
+ {
+ if ( nBits & HIB_RIGHT )
+ nArrowX -= aImageSize.Width();
+ else
+ nArrowX += aImageSize.Width();
+ }
+
+ // Feststellen, ob Platz genug ist, das Item zu malen
+ sal_Bool bDraw = sal_True;
+ if ( nArrowX < aRect.Left()+HEADERBAR_TEXTOFF )
+ bDraw = sal_False;
+ else if ( nArrowX+HEAD_ARROWSIZE2 > aRect.Right() )
+ bDraw = sal_False;
+
+ if ( bDraw )
+ {
+ long nArrowY;
+ if ( aTxtSize.Height() )
+ nArrowY = nTxtPosY+(aTxtSize.Height()/2);
+ else if ( aImageSize.Width() && aImageSize.Height() )
+ nArrowY = nImagePosY+(aImageSize.Height()/2);
+ else
+ {
+ if ( nBits & HIB_TOP )
+ nArrowY = aRect.Top()+1;
+ else if ( nBits & HIB_BOTTOM )
+ nArrowY = aRect.Bottom()-HEAD_ARROWSIZE2-1;
+ else
+ nArrowY = aRect.Top()+((aRect.GetHeight()-HEAD_ARROWSIZE2)/2);;
+ }
+ nArrowY -= HEAD_ARROWSIZE1-1;
+ if ( nBits & HIB_DOWNARROW )
+ {
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( Point( nArrowX, nArrowY ),
+ Point( nArrowX+HEAD_ARROWSIZE2, nArrowY ) );
+ pDev->DrawLine( Point( nArrowX, nArrowY ),
+ Point( nArrowX+HEAD_ARROWSIZE1, nArrowY+HEAD_ARROWSIZE2 ) );
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( nArrowX+HEAD_ARROWSIZE1, nArrowY+HEAD_ARROWSIZE2 ),
+ Point( nArrowX+HEAD_ARROWSIZE2, nArrowY ) );
+ }
+ else
+ {
+ pDev->SetLineColor( rStyleSettings.GetLightColor() );
+ pDev->DrawLine( Point( nArrowX, nArrowY+HEAD_ARROWSIZE2 ),
+ Point( nArrowX+HEAD_ARROWSIZE1, nArrowY ) );
+ pDev->SetLineColor( rStyleSettings.GetShadowColor() );
+ pDev->DrawLine( Point( nArrowX, nArrowY+HEAD_ARROWSIZE2 ),
+ Point( nArrowX+HEAD_ARROWSIZE2, nArrowY+HEAD_ARROWSIZE2 ) );
+ pDev->DrawLine( Point( nArrowX+HEAD_ARROWSIZE2, nArrowY+HEAD_ARROWSIZE2 ),
+ Point( nArrowX+HEAD_ARROWSIZE1, nArrowY ) );
+ }
+ }
+ }
+
+ // Gegebenenfalls auch UserDraw aufrufen
+ if ( nBits & HIB_USERDRAW )
+ {
+ Region aRegion( aRect );
+ if ( pRect )
+ aRegion.Intersect( *pRect );
+ pDev->SetClipRegion( aRegion );
+ UserDrawEvent aODEvt( pDev, aRect, pItem->mnId );
+ UserDraw( aODEvt );
+ pDev->SetClipRegion();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplDrawItem( sal_uInt16 nPos, sal_Bool bHigh, sal_Bool bDrag,
+ const Rectangle* pRect )
+{
+ Rectangle aRect = ImplGetItemRect( nPos );
+ ImplDrawItem( this, nPos, bHigh, bDrag, aRect, pRect, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplUpdate( sal_uInt16 nPos, sal_Bool bEnd, sal_Bool bDirect )
+{
+ if ( IsVisible() && IsUpdateMode() )
+ {
+ if ( !bDirect )
+ {
+ Rectangle aRect;
+ sal_uInt16 nItemCount = (sal_uInt16)(mpItemList->Count());
+ if ( nPos < nItemCount )
+ aRect = ImplGetItemRect( nPos );
+ else
+ {
+ aRect.Bottom() = mnDY-1;
+ if ( nItemCount )
+ aRect.Left() = ImplGetItemRect( nItemCount-1 ).Right();
+ }
+ if ( bEnd )
+ aRect.Right() = mnDX-1;
+ aRect.Top() += mnBorderOff1;
+ aRect.Bottom() -= mnBorderOff2;
+ Invalidate( aRect );
+ }
+ else
+ {
+ for ( sal_uInt16 i = nPos; i < mpItemList->Count(); i++ )
+ ImplDrawItem( i );
+ if ( bEnd )
+ {
+ Rectangle aRect = ImplGetItemRect( (sal_uInt16)mpItemList->Count() );
+ aRect.Left() = aRect.Right();
+ aRect.Right() = mnDX-1;
+ if ( aRect.Left() < aRect.Right() )
+ {
+ aRect.Top() += mnBorderOff1;
+ aRect.Bottom() -= mnBorderOff2;
+ Erase( aRect );
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplStartDrag( const Point& rMousePos, sal_Bool bCommand )
+{
+ sal_uInt16 nPos;
+ sal_uInt16 nHitTest = ImplHitTest( rMousePos, mnMouseOff, nPos );
+ if ( nHitTest )
+ {
+ mbDrag = sal_False;
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( nHitTest & HEAD_HITTEST_DIVIDER )
+ mbDrag = sal_True;
+ else
+ {
+ if ( ((pItem->mnBits & HIB_CLICKABLE) && !(pItem->mnBits & HIB_FLAT)) ||
+ (mbDragable && !(pItem->mnBits & HIB_FIXEDPOS)) )
+ {
+ mbItemMode = sal_True;
+ mbDrag = sal_True;
+ if ( bCommand )
+ {
+ if ( mbDragable )
+ mbItemDrag = sal_True;
+ else
+ {
+ mbItemMode = sal_False;
+ mbDrag = sal_False;
+ }
+ }
+ }
+ else
+ {
+ if ( !bCommand )
+ {
+ mnCurItemId = pItem->mnId;
+ Select();
+ mnCurItemId = 0;
+ }
+ }
+ }
+
+ if ( mbDrag )
+ {
+ mbOutDrag = sal_False;
+ mnCurItemId = pItem->mnId;
+ mnItemDragPos = nPos;
+ StartTracking();
+ mnStartPos = rMousePos.X()-mnMouseOff;
+ mnDragPos = mnStartPos;
+ StartDrag();
+ if ( mbItemMode )
+ ImplDrawItem( nPos, sal_True, mbItemDrag );
+ else
+ {
+ Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
+ ShowTracking( aSizeRect, SHOWTRACK_SPLIT );
+ }
+ }
+ else
+ mnMouseOff = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplDrag( const Point& rMousePos )
+{
+ sal_Bool bNewOutDrag;
+ sal_uInt16 nPos = GetItemPos( mnCurItemId );
+
+ mnDragPos = rMousePos.X()-mnMouseOff;
+ if ( mbItemMode )
+ {
+ Rectangle aItemRect = ImplGetItemRect( nPos );
+ if ( aItemRect.IsInside( rMousePos ) )
+ bNewOutDrag = sal_False;
+ else
+ bNewOutDrag = sal_True;
+
+ // Evt. ItemDrag anschalten
+ if ( bNewOutDrag && mbDragable && !mbItemDrag &&
+ !(mpItemList->GetObject(nPos)->mnBits & HIB_FIXEDPOS) )
+ {
+ if ( (rMousePos.Y() >= aItemRect.Top()) && (rMousePos.Y() <= aItemRect.Bottom()) )
+ {
+ mbItemDrag = sal_True;
+ ImplDrawItem( nPos, sal_True, mbItemDrag );
+ }
+ }
+
+ sal_uInt16 nOldItemDragPos = mnItemDragPos;
+ if ( mbItemDrag )
+ {
+ if ( (rMousePos.Y() < -HEADERBAR_DRAGOUTOFF) || (rMousePos.Y() > mnDY+HEADERBAR_DRAGOUTOFF) )
+ bNewOutDrag = sal_True;
+ else
+ bNewOutDrag = sal_False;
+
+ if ( bNewOutDrag )
+ mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
+ else
+ {
+ sal_uInt16 nTempId = GetItemId( Point( rMousePos.X(), 2 ) );
+ if ( nTempId )
+ mnItemDragPos = GetItemPos( nTempId );
+ else
+ {
+ if ( rMousePos.X() <= 0 )
+ mnItemDragPos = 0;
+ else
+ mnItemDragPos = GetItemCount()-1;
+ }
+
+ // Nicht verschiebbare Items aussparen
+ if ( mnItemDragPos < nPos )
+ {
+ while ( (mpItemList->GetObject(mnItemDragPos)->mnBits & HIB_FIXEDPOS) &&
+ (mnItemDragPos < nPos) )
+ mnItemDragPos++;
+ }
+ else if ( mnItemDragPos > nPos )
+ {
+ while ( (mpItemList->GetObject(mnItemDragPos)->mnBits & HIB_FIXEDPOS) &&
+ (mnItemDragPos > nPos) )
+ mnItemDragPos--;
+ }
+ }
+
+ if ( (mnItemDragPos != nOldItemDragPos) &&
+ (nOldItemDragPos != nPos) &&
+ (nOldItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
+ {
+ ImplInvertDrag( nPos, nOldItemDragPos );
+ ImplDrawItem( nOldItemDragPos );
+ }
+ }
+
+ if ( bNewOutDrag != mbOutDrag )
+ ImplDrawItem( nPos, !bNewOutDrag, mbItemDrag );
+
+ if ( mbItemDrag )
+ {
+ if ( (mnItemDragPos != nOldItemDragPos) &&
+ (mnItemDragPos != nPos) &&
+ (mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
+ {
+ ImplDrawItem( mnItemDragPos, sal_False, sal_True );
+ ImplInvertDrag( nPos, mnItemDragPos );
+ }
+ }
+
+ mbOutDrag = bNewOutDrag;
+ }
+ else
+ {
+ Rectangle aItemRect = ImplGetItemRect( nPos );
+ if ( mnDragPos < aItemRect.Left() )
+ mnDragPos = aItemRect.Left();
+ if ( (mnDragPos < 0) || (mnDragPos > mnDX-1) )
+ HideTracking();
+ else
+ {
+ Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
+ ShowTracking( aSizeRect, SHOWTRACK_SPLIT );
+ }
+ }
+
+ Drag();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplEndDrag( sal_Bool bCancel )
+{
+ HideTracking();
+
+ if ( bCancel || mbOutDrag )
+ {
+ if ( mbItemMode && (!mbOutDrag || mbItemDrag) )
+ {
+ sal_uInt16 nPos = GetItemPos( mnCurItemId );
+ ImplDrawItem( nPos );
+ }
+
+ mnCurItemId = 0;
+ }
+ else
+ {
+ sal_uInt16 nPos = GetItemPos( mnCurItemId );
+ if ( mbItemMode )
+ {
+ if ( mbItemDrag )
+ {
+ Pointer aPointer( POINTER_ARROW );
+ SetPointer( aPointer );
+ if ( (mnItemDragPos != nPos) &&
+ (mnItemDragPos != HEADERBAR_ITEM_NOTFOUND) )
+ {
+ ImplInvertDrag( nPos, mnItemDragPos );
+ MoveItem( mnCurItemId, mnItemDragPos );
+ }
+ else
+ ImplDrawItem( nPos );
+ }
+ else
+ {
+ Select();
+ ImplUpdate( nPos );
+ }
+ }
+ else
+ {
+ long nDelta = mnDragPos - mnStartPos;
+ if ( nDelta )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ pItem->mnSize += nDelta;
+ ImplUpdate( nPos, sal_True );
+ }
+ }
+ }
+
+ mbDrag = sal_False;
+ EndDrag();
+ mnCurItemId = 0;
+ mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
+ mbOutDrag = sal_False;
+ mbItemMode = sal_False;
+ mbItemDrag = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ {
+ if ( rMEvt.GetClicks() == 2 )
+ {
+ long nTemp;
+ sal_uInt16 nPos;
+ sal_uInt16 nHitTest = ImplHitTest( rMEvt.GetPosPixel(), nTemp, nPos );
+ if ( nHitTest )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( nHitTest & HEAD_HITTEST_DIVIDER )
+ mbItemMode = sal_False;
+ else
+ mbItemMode = sal_True;
+ mnCurItemId = pItem->mnId;
+ DoubleClick();
+ mbItemMode = sal_False;
+ mnCurItemId = 0;
+ }
+ }
+ else
+ ImplStartDrag( rMEvt.GetPosPixel(), sal_False );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::MouseMove( const MouseEvent& rMEvt )
+{
+ long nTemp1;
+ sal_uInt16 nTemp2;
+ PointerStyle eStyle = POINTER_ARROW;
+ sal_uInt16 nHitTest = ImplHitTest( rMEvt.GetPosPixel(), nTemp1, nTemp2 );
+
+ if ( nHitTest & HEAD_HITTEST_DIVIDER )
+ eStyle = POINTER_HSIZEBAR;
+ Pointer aPtr( eStyle );
+ SetPointer( aPtr );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Tracking( const TrackingEvent& rTEvt )
+{
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ if ( rTEvt.IsTrackingEnded() )
+ ImplEndDrag( rTEvt.IsTrackingCanceled() );
+ else
+ ImplDrag( aMousePos );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Paint( const Rectangle& rRect )
+{
+ if ( mnBorderOff1 || mnBorderOff2 )
+ {
+ SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
+ if ( mnBorderOff1 )
+ DrawLine( Point( 0, 0 ), Point( mnDX-1, 0 ) );
+ if ( mnBorderOff2 )
+ DrawLine( Point( 0, mnDY-1 ), Point( mnDX-1, mnDY-1 ) );
+ // #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
+ if ( mnBorderOff1 && mnBorderOff2 )
+ {
+ DrawLine( Point( 0, 0 ), Point( 0, mnDY-1 ) );
+ DrawLine( Point( mnDX-1, 0 ), Point( mnDX-1, mnDY-1 ) );
+ }
+ }
+
+ sal_uInt16 nCurItemPos;
+ if ( mbDrag )
+ nCurItemPos = GetItemPos( mnCurItemId );
+ else
+ nCurItemPos = HEADERBAR_ITEM_NOTFOUND;
+ sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
+ for ( sal_uInt16 i = 0; i < nItemCount; i++ )
+ ImplDrawItem( i, (i == nCurItemPos) ? sal_True : sal_False, sal_False, &rRect );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ sal_uLong nFlags )
+{
+ Point aPos = pDev->LogicToPixel( rPos );
+ Size aSize = pDev->LogicToPixel( rSize );
+ Rectangle aRect( aPos, aSize );
+ Font aFont = GetDrawPixelFont( pDev );
+
+ pDev->Push();
+ pDev->SetMapMode();
+ pDev->SetFont( aFont );
+ if ( nFlags & WINDOW_DRAW_MONO )
+ pDev->SetTextColor( Color( COL_BLACK ) );
+ else
+ pDev->SetTextColor( GetTextColor() );
+ pDev->SetTextFillColor();
+
+ if ( !(nFlags & WINDOW_DRAW_NOBACKGROUND) )
+ {
+ pDev->DrawWallpaper( aRect, GetBackground() );
+ if ( mnBorderOff1 || mnBorderOff2 )
+ {
+ pDev->SetLineColor( GetSettings().GetStyleSettings().GetDarkShadowColor() );
+ if ( mnBorderOff1 )
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right(), aRect.Top() ) );
+ if ( mnBorderOff2 )
+ pDev->DrawLine( Point( aRect.Left(), aRect.Bottom() ), Point( aRect.Right(), aRect.Bottom() ) );
+ // #i40393# draw left and right border, if WB_BORDER was set in ImplInit()
+ if ( mnBorderOff1 && mnBorderOff2 )
+ {
+ pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() ) );
+ pDev->DrawLine( Point( aRect.Right(), aRect.Top() ), Point( aRect.Right(), aRect.Bottom() ) );
+ }
+ }
+ }
+
+ Rectangle aItemRect( aRect );
+// aItemRect.Bottom()--;
+ sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
+ for ( sal_uInt16 i = 0; i < nItemCount; i++ )
+ {
+ aItemRect.Left() = aRect.Left()+ImplGetItemPos( i );
+ aItemRect.Right() = aItemRect.Left() + mpItemList->GetObject( i )->mnSize - 1;
+ // Gegen Ueberlauf auf einigen Systemen testen
+ if ( aItemRect.Right() > 16000 )
+ aItemRect.Right() = 16000;
+ Region aRegion( aRect );
+ pDev->SetClipRegion( aRegion );
+ ImplDrawItem( pDev, i, sal_False, sal_False, aItemRect, &aRect, nFlags );
+ pDev->SetClipRegion();
+ }
+
+ pDev->Pop();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Resize()
+{
+ Size aSize = GetOutputSizePixel();
+ if ( IsVisible() && (mnDY != aSize.Height()) )
+ Invalidate();
+ mnDX = aSize.Width();
+ mnDY = aSize.Height();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.IsMouseEvent() && (rCEvt.GetCommand() == COMMAND_STARTDRAG) && !mbDrag )
+ {
+ ImplStartDrag( rCEvt.GetMousePosPixel(), sal_True );
+ return;
+ }
+
+ Window::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+ if ( nItemId )
+ {
+ if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
+ {
+ Rectangle aItemRect = GetItemRect( nItemId );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+
+ XubString aStr = GetHelpText( nItemId );
+ if ( !aStr.Len() || !(rHEvt.GetMode() & HELPMODE_BALLOON) )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( GetItemPos( nItemId ) );
+ // Wir zeigen die Quick-Hilfe nur an, wenn Text nicht
+ // vollstaendig sichtbar, ansonsten zeigen wir den Hilfetext
+ // an, wenn das Item keinen Text besitzt
+ if ( pItem->maOutText != pItem->maText )
+ aStr = pItem->maText;
+ else if ( pItem->maText.Len() )
+ aStr.Erase();
+ }
+
+ if ( aStr.Len() )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ else
+ Help::ShowQuickHelp( this, aItemRect, aStr );
+ return;
+ }
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ rtl::OUString aHelpId( rtl::OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
+ if ( aHelpId.getLength() )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( aHelpId, this );
+ return;
+ }
+ }
+ }
+
+ Window::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_ENABLE )
+ Invalidate();
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( sal_True, sal_False, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( sal_False, sal_True, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( sal_False, sal_False, sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( sal_True, sal_True, sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::StartDrag()
+{
+ maStartDragHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Drag()
+{
+ maDragHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::EndDrag()
+{
+ maEndDragHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::InsertItem( sal_uInt16 nItemId, const Image& rImage,
+ long nSize, HeaderBarItemBits nBits, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
+ "HeaderBar::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ ImplHeadItem* pItem = new ImplHeadItem;
+ pItem->mnId = nItemId;
+ pItem->mnBits = nBits;
+ pItem->mnSize = nSize;
+ pItem->maImage = rImage;
+ pItem->mpUserData = 0;
+ mpItemList->Insert( pItem, nPos );
+
+ // Ausgabe updaten
+ ImplUpdate( nPos, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::InsertItem( sal_uInt16 nItemId, const XubString& rText,
+ long nSize, HeaderBarItemBits nBits, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
+ "HeaderBar::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ ImplHeadItem* pItem = new ImplHeadItem;
+ pItem->mnId = nItemId;
+ pItem->mnBits = nBits;
+ pItem->mnSize = nSize;
+ pItem->maText = rText;
+ pItem->mpUserData = 0;
+ mpItemList->Insert( pItem, nPos );
+
+ // Ausgabe updaten
+ ImplUpdate( nPos, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::InsertItem( sal_uInt16 nItemId,
+ const Image& rImage, const XubString& rText,
+ long nSize, HeaderBarItemBits nBits,
+ sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "HeaderBar::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == HEADERBAR_ITEM_NOTFOUND,
+ "HeaderBar::InsertItem(): ItemId already exists" );
+
+ // Item anlegen und in die Liste einfuegen
+ ImplHeadItem* pItem = new ImplHeadItem;
+ pItem->mnId = nItemId;
+ pItem->mnBits = nBits;
+ pItem->mnSize = nSize;
+ pItem->maImage = rImage;
+ pItem->maText = rText;
+ pItem->mpUserData = 0;
+ mpItemList->Insert( pItem, nPos );
+
+ // Ausgabe updaten
+ ImplUpdate( nPos, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::RemoveItem( sal_uInt16 nItemId )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ ImplHeadItem* pItem = mpItemList->Remove( nPos );
+ delete pItem;
+ ImplUpdate( nPos, sal_True );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::MoveItem( sal_uInt16 nItemId, sal_uInt16 nNewPos )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ if ( nPos != nNewPos )
+ {
+ ImplHeadItem* pItem = mpItemList->Remove( nPos );
+ if ( nNewPos < nPos )
+ nPos = nNewPos;
+ mpItemList->Insert( pItem, nNewPos );
+ ImplUpdate( nPos, sal_True );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Clear()
+{
+ // Alle Items loeschen
+ ImplHeadItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+ mpItemList->Clear();
+
+ ImplUpdate( 0, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetOffset( long nNewOffset )
+{
+ // Hier erstmal neu zeichnen, damit mit alten Offset noch das
+ // richtige gemalt wird
+ //Update();
+
+ // Bereich verschieben
+ Rectangle aRect( 0, mnBorderOff1, mnDX-1, mnDY-mnBorderOff1-mnBorderOff2-1 );
+ long nDelta = mnOffset-nNewOffset;
+ mnOffset = nNewOffset;
+ Scroll( nDelta, 0, aRect );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 HeaderBar::GetItemCount() const
+{
+ return (sal_uInt16)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 HeaderBar::GetItemPos( sal_uInt16 nItemId ) const
+{
+ ImplHeadItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return (sal_uInt16)mpItemList->GetCurPos();
+ pItem = mpItemList->Next();
+ }
+
+ return HEADERBAR_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 HeaderBar::GetItemId( sal_uInt16 nPos ) const
+{
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 HeaderBar::GetItemId( const Point& rPos ) const
+{
+ sal_uInt16 nPos = 0;
+ while ( nPos < mpItemList->Count() )
+ {
+ if ( ImplGetItemRect( nPos ).IsInside( rPos ) )
+ return GetItemId( nPos );
+
+ nPos++;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle HeaderBar::GetItemRect( sal_uInt16 nItemId ) const
+{
+ Rectangle aRect;
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ aRect = ImplGetItemRect( nPos );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemSize( sal_uInt16 nItemId, long nNewSize )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem->mnSize != nNewSize )
+ {
+ pItem->mnSize = nNewSize;
+ ImplUpdate( nPos, sal_True );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long HeaderBar::GetItemSize( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnSize;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemBits( sal_uInt16 nItemId, HeaderBarItemBits nNewBits )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem->mnBits != nNewBits )
+ {
+ pItem->mnBits = nNewBits;
+ ImplUpdate( nPos );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+HeaderBarItemBits HeaderBar::GetItemBits( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemData( sal_uInt16 nItemId, void* pNewData )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ mpItemList->GetObject( nPos )->mpUserData = pNewData;
+ ImplUpdate( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* HeaderBar::GetItemData( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mpUserData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ mpItemList->GetObject( nPos )->maImage = rImage;
+ ImplUpdate( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image HeaderBar::GetItemImage( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemText( sal_uInt16 nItemId, const XubString& rText )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ mpItemList->GetObject( nPos )->maText = rText;
+ ImplUpdate( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString HeaderBar::GetItemText( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maText;
+ else
+ return String();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetHelpText( sal_uInt16 nItemId, const XubString& rText )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+XubString HeaderBar::GetHelpText( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return XubString();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetHelpId( sal_uInt16 nItemId, const rtl::OString& rHelpId )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->maHelpId = rHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+rtl::OString HeaderBar::GetHelpId( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+ rtl::OString aRet;
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ aRet = mpItemList->GetObject( nPos )->maHelpId;
+ return aRet;
+}
+
+// -----------------------------------------------------------------------
+
+Size HeaderBar::CalcWindowSizePixel() const
+{
+ long nMaxImageSize = 0;
+ Size aSize( 0, GetTextHeight() );
+
+ ImplHeadItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Image-Groessen beruecksichtigen
+ long nImageHeight = pItem->maImage.GetSizePixel().Height();
+ if ( !(pItem->mnBits & (HIB_LEFTIMAGE | HIB_RIGHTIMAGE)) && pItem->maText.Len() )
+ nImageHeight += aSize.Height();
+ if ( nImageHeight > nMaxImageSize )
+ nMaxImageSize = nImageHeight;
+
+ // Breite aufaddieren
+ aSize.Width() += pItem->mnSize;
+
+ pItem = mpItemList->Next();
+ }
+
+ if ( nMaxImageSize > aSize.Height() )
+ aSize.Height() = nMaxImageSize;
+
+ // Border aufaddieren
+ if ( mbButtonStyle )
+ aSize.Height() += 4;
+ else
+ aSize.Height() += 2;
+ aSize.Height() += mnBorderOff1+mnBorderOff2;
+
+ return aSize;
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > HeaderBar::CreateAccessible()
+{
+ if ( !mxAccessible.is() )
+ {
+ if ( maCreateAccessibleHdl.IsSet() )
+ maCreateAccessibleHdl.Call( this );
+
+ if ( !mxAccessible.is() )
+ mxAccessible = Window::CreateAccessible();
+ }
+
+ return mxAccessible;
+}
+
+void HeaderBar::SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > _xAccessible )
+{
+ mxAccessible = _xAccessible;
+}
+
diff --git a/svtools/source/control/hyperlabel.cxx b/svtools/source/control/hyperlabel.cxx
new file mode 100644
index 000000000000..10ef8cdcfadf
--- /dev/null
+++ b/svtools/source/control/hyperlabel.cxx
@@ -0,0 +1,270 @@
+/*************************************************************************
+ *
+ * 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"
+#ifndef SVTOOLS_ROADMAP_HXX
+#include <svtools/hyperlabel.hxx>
+#endif
+#include <vcl/bitmap.hxx>
+#include <tools/color.hxx>
+
+#ifndef _VCL_TABPAGE_HXX
+#include <vcl/tabpage.hxx>
+#endif
+
+
+//.........................................................................
+namespace svt
+{
+//.........................................................................
+
+ //=====================================================================
+ //= FontChanger
+ //=====================================================================
+ class FontChanger
+ {
+ protected:
+ OutputDevice* m_pDev;
+
+ public:
+ FontChanger( OutputDevice* _pDev, const Font& _rNewFont )
+ :m_pDev( _pDev )
+ {
+ m_pDev->Push( PUSH_FONT );
+ m_pDev->SetFont( _rNewFont );
+ }
+
+ ~FontChanger()
+ {
+ m_pDev->Pop( );
+ }
+ };
+
+ class HyperLabelImpl
+ {
+ public:
+ sal_Int16 ID;
+ sal_Int32 Index;
+ sal_Bool bInteractive;
+ Size m_aMinSize;
+ sal_Bool m_bHyperMode;
+
+ HyperLabelImpl();
+ };
+
+ //---------------------------------------------------------------------
+ HyperLabelImpl::HyperLabelImpl()
+ {
+ }
+
+ HyperLabel::HyperLabel( Window* _pParent, const ResId& _rId )
+ :FixedText( _pParent, _rId )
+ ,m_pImpl( new HyperLabelImpl )
+ {
+ implInit();
+ }
+
+ HyperLabel::HyperLabel( Window* _pParent, WinBits _nWinStyle )
+ :FixedText( _pParent, _nWinStyle )
+ ,m_pImpl( new HyperLabelImpl )
+ {
+ implInit();
+ }
+
+
+ sal_Int32 HyperLabel::GetLogicWidth()
+ {
+ Size rLogicLocSize = PixelToLogic( m_pImpl->m_aMinSize, MAP_APPFONT );
+ return rLogicLocSize.Width();
+ }
+
+
+ Size HyperLabel::CalcMinimumSize( long nMaxWidth ) const
+ {
+ m_pImpl->m_aMinSize = FixedText::CalcMinimumSize( nMaxWidth );
+ // the MinimumSize is used to size the FocusRectangle
+ // and for the MouseMove method
+ m_pImpl->m_aMinSize.Height() += 2;
+ m_pImpl->m_aMinSize.Width() += 1;
+ return m_pImpl->m_aMinSize;
+ }
+
+ void HyperLabel::implInit()
+ {
+ ToggleBackgroundColor( COL_TRANSPARENT );
+
+ WinBits nWinStyle = GetStyle();
+ nWinStyle |= WB_EXTRAOFFSET;
+ SetStyle( nWinStyle );
+
+ Show();
+ }
+
+ void HyperLabel::ToggleBackgroundColor( const Color& _rGBColor )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetControlBackground( _rGBColor );
+ if (_rGBColor == COL_TRANSPARENT)
+ SetTextColor( rStyleSettings.GetFieldTextColor( ) );
+ else
+ SetTextColor( rStyleSettings.GetHighlightTextColor( ) );
+ }
+
+
+ void HyperLabel::MouseMove( const MouseEvent& rMEvt )
+ {
+ Font aFont = GetControlFont( );
+ const Color aColor = GetTextColor();
+
+ if (rMEvt.IsLeaveWindow())
+ {
+ DeactivateHyperMode(aFont, aColor);
+ }
+ else
+ {
+ Point aPoint = GetPointerPosPixel();
+ if (aPoint.X() < m_pImpl->m_aMinSize.Width())
+ {
+ if ( IsEnabled() && (m_pImpl->bInteractive) )
+ {
+ ActivateHyperMode( aFont, aColor);
+ return;
+ }
+ }
+ DeactivateHyperMode(aFont, aColor);
+ }
+ }
+
+ void HyperLabel::ActivateHyperMode(Font aFont, const Color aColor)
+ {
+ aFont.SetUnderline(UNDERLINE_SINGLE);
+ m_pImpl->m_bHyperMode = sal_True;
+ SetPointer( POINTER_REFHAND );
+ SetControlFont( aFont);
+ SetTextColor( aColor);
+
+ }
+
+ void HyperLabel::DeactivateHyperMode(Font aFont, const Color aColor)
+ {
+ m_pImpl->m_bHyperMode = sal_False;
+ aFont.SetUnderline(UNDERLINE_NONE);
+ SetPointer( POINTER_ARROW );
+ SetControlFont( aFont);
+ SetTextColor( aColor);
+ }
+
+ void HyperLabel::MouseButtonDown( const MouseEvent& )
+ {
+ if ( m_pImpl->m_bHyperMode && m_pImpl->bInteractive )
+ {
+ maClickHdl.Call( this );
+ }
+ }
+
+ void HyperLabel::GetFocus()
+ {
+ if ( IsEnabled() && m_pImpl->bInteractive )
+ {
+ Point aPoint(0,0);
+ Rectangle rRect(aPoint, Size( m_pImpl->m_aMinSize.Width(), GetSizePixel().Height() ) );
+ ShowFocus( rRect );
+ }
+ }
+
+ void HyperLabel::LoseFocus()
+ {
+ HideFocus();
+ }
+
+ HyperLabel::~HyperLabel( )
+ {
+ delete m_pImpl;
+ }
+
+ void HyperLabel::SetInteractive( sal_Bool _bInteractive )
+ {
+ m_pImpl->bInteractive = ( _bInteractive && IsEnabled() );
+ }
+
+ sal_Int16 HyperLabel::GetID() const
+ {
+ return m_pImpl->ID;
+ }
+
+ sal_Int32 HyperLabel::GetIndex() const
+ {
+ return m_pImpl->Index;
+ }
+
+ void HyperLabel::SetID( sal_Int16 _ID )
+ {
+ m_pImpl->ID = _ID;
+ }
+
+ void HyperLabel::SetIndex( sal_Int32 _Index )
+ {
+ m_pImpl->Index = _Index;
+ }
+
+ ::rtl::OUString HyperLabel::GetLabel( )
+ {
+ return GetText();
+ }
+
+ void HyperLabel::SetLabel( const ::rtl::OUString& _rText )
+ {
+ SetText(_rText);
+ }
+
+
+ //------------------------------------------------------------------------------
+ void HyperLabel::DataChanged( const DataChangedEvent& rDCEvt )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ FixedText::DataChanged( rDCEvt );
+ if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS ) ||
+ ( rDCEvt.GetType() == DATACHANGED_DISPLAY )) &&
+ ( rDCEvt.GetFlags() & SETTINGS_STYLE ))
+ {
+ const Color& rGBColor = GetControlBackground();
+ if (rGBColor == COL_TRANSPARENT)
+ SetTextColor( rStyleSettings.GetFieldTextColor( ) );
+ else
+ {
+ SetControlBackground(rStyleSettings.GetHighlightColor());
+ SetTextColor( rStyleSettings.GetHighlightTextColor( ) );
+ }
+ Invalidate();
+ }
+ }
+
+//.........................................................................
+} // namespace svt
+//.........................................................................
+
diff --git a/svtools/source/control/indexentryres.cxx b/svtools/source/control/indexentryres.cxx
new file mode 100755
index 000000000000..23eada244a47
--- /dev/null
+++ b/svtools/source/control/indexentryres.cxx
@@ -0,0 +1,131 @@
+/*************************************************************************
+ *
+ * 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 <svtools/svtdata.hxx>
+#include <svtools/svtools.hrc>
+#include <svtools/indexentryres.hxx>
+
+// -------------------------------------------------------------------------
+//
+// wrapper for locale specific translations data of indexentry algorithm
+//
+// -------------------------------------------------------------------------
+
+class IndexEntryRessourceData
+{
+ friend class IndexEntryRessource;
+ private: /* data */
+ String ma_Name;
+ String ma_Translation;
+ private: /* member functions */
+ IndexEntryRessourceData () {}
+ public:
+ IndexEntryRessourceData ( const String &r_Algorithm, const String &r_Translation)
+ : ma_Name (r_Algorithm), ma_Translation (r_Translation) {}
+
+ const String& GetAlgorithm () const { return ma_Name; }
+
+ const String& GetTranslation () const { return ma_Translation; }
+
+ ~IndexEntryRessourceData () {}
+
+ IndexEntryRessourceData& operator= (const IndexEntryRessourceData& r_From)
+ {
+ ma_Name = r_From.GetAlgorithm();
+ ma_Translation = r_From.GetTranslation();
+ return *this;
+ }
+};
+
+// -------------------------------------------------------------------------
+//
+// implementation of the indexentry-algorithm-name translation
+//
+// -------------------------------------------------------------------------
+
+#define INDEXENTRY_RESSOURCE_COUNT (STR_SVT_INDEXENTRY_END - STR_SVT_INDEXENTRY_START + 1)
+
+IndexEntryRessource::IndexEntryRessource()
+{
+ mp_Data = new IndexEntryRessourceData[INDEXENTRY_RESSOURCE_COUNT];
+
+ #define ASCSTR(str) String(RTL_CONSTASCII_USTRINGPARAM(str))
+ #define RESSTR(rid) String(SvtResId(rid))
+
+ mp_Data[STR_SVT_INDEXENTRY_ALPHANUMERIC - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("alphanumeric"), RESSTR(STR_SVT_INDEXENTRY_ALPHANUMERIC));
+ mp_Data[STR_SVT_INDEXENTRY_DICTIONARY - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("dict"), RESSTR(STR_SVT_INDEXENTRY_DICTIONARY));
+ mp_Data[STR_SVT_INDEXENTRY_PINYIN - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("pinyin"), RESSTR(STR_SVT_INDEXENTRY_PINYIN));
+ mp_Data[STR_SVT_INDEXENTRY_PINYIN - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("radical"), RESSTR(STR_SVT_INDEXENTRY_RADICAL));
+ mp_Data[STR_SVT_INDEXENTRY_STROKE - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("stroke"), RESSTR(STR_SVT_INDEXENTRY_STROKE));
+ mp_Data[STR_SVT_INDEXENTRY_STROKE - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("zhuyin"), RESSTR(STR_SVT_INDEXENTRY_ZHUYIN));
+ mp_Data[STR_SVT_INDEXENTRY_ZHUYIN - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("phonetic (alphanumeric first) (grouped by syllable)"),
+ RESSTR(STR_SVT_INDEXENTRY_PHONETIC_FS));
+ mp_Data[STR_SVT_INDEXENTRY_PHONETIC_FS - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("phonetic (alphanumeric first) (grouped by consonant)"),
+ RESSTR(STR_SVT_INDEXENTRY_PHONETIC_FC));
+ mp_Data[STR_SVT_INDEXENTRY_PHONETIC_FC - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("phonetic (alphanumeric last) (grouped by syllable)"),
+ RESSTR(STR_SVT_INDEXENTRY_PHONETIC_LS));
+ mp_Data[STR_SVT_INDEXENTRY_PHONETIC_LS - STR_SVT_INDEXENTRY_START] =
+ IndexEntryRessourceData (ASCSTR("phonetic (alphanumeric last) (grouped by consonant)"),
+ RESSTR(STR_SVT_INDEXENTRY_PHONETIC_LC));
+}
+
+IndexEntryRessource::~IndexEntryRessource()
+{
+ delete[] mp_Data;
+}
+
+const String&
+IndexEntryRessource::GetTranslation (const String &r_Algorithm)
+{
+ xub_StrLen nIndex = r_Algorithm.Search('.');
+ String aLocaleFreeAlgorithm;
+
+ if (nIndex == STRING_NOTFOUND)
+ aLocaleFreeAlgorithm = r_Algorithm;
+ else {
+ nIndex += 1;
+ aLocaleFreeAlgorithm = String(r_Algorithm, nIndex, r_Algorithm.Len() - nIndex);
+ }
+
+ for (sal_uInt32 i = 0; i < INDEXENTRY_RESSOURCE_COUNT; i++)
+ if (aLocaleFreeAlgorithm == mp_Data[i].GetAlgorithm())
+ return mp_Data[i].GetTranslation();
+ return r_Algorithm;
+}
+
diff --git a/svtools/source/control/inettbc.cxx b/svtools/source/control/inettbc.cxx
new file mode 100755
index 000000000000..94db99a66194
--- /dev/null
+++ b/svtools/source/control/inettbc.cxx
@@ -0,0 +1,1365 @@
+/*************************************************************************
+ *
+ * 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"
+
+#ifdef UNX
+#include <pwd.h>
+#include <sys/types.h>
+#endif
+
+#include <svtools/inettbc.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/ucb/NumberedSortingInfo.hpp>
+#include <com/sun/star/ucb/XAnyCompareFactory.hpp>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <vcl/toolbox.hxx>
+#include <vos/thread.hxx>
+#include <vos/mutex.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/historyoptions.hxx>
+#include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
+#include <svl/itemset.hxx>
+#include "svl/urihelper.hxx"
+#include <unotools/pathoptions.hxx>
+
+#define _SVSTDARR_STRINGSDTOR
+#include <svl/svstdarr.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <ucbhelper/content.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <unotools/ucbhelper.hxx>
+#include "iodlg.hrc"
+#include <svtools/asynclink.hxx>
+#include <svl/urlfilter.hxx>
+
+#include <vector>
+#include <algorithm>
+
+// -----------------------------------------------------------------------
+
+using namespace ::rtl;
+using namespace ::ucbhelper;
+using namespace ::utl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::task;
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::uno;
+
+// -----------------------------------------------------------------------
+class SvtURLBox_Impl
+{
+public:
+ SvStringsDtor* pURLs;
+ SvStringsDtor* pCompletions;
+ const IUrlFilter* pUrlFilter;
+ ::std::vector< WildCard > m_aFilters;
+
+ static sal_Bool TildeParsing( String& aText, String& aBaseUrl );
+
+ inline SvtURLBox_Impl( )
+ :pURLs( NULL )
+ ,pCompletions( NULL )
+ ,pUrlFilter( NULL )
+ {
+ FilterMatch::createWildCardFilterList(String(),m_aFilters);
+ }
+};
+
+// -----------------------------------------------------------------------
+class SvtMatchContext_Impl : public ::vos::OThread
+{
+ static ::vos::OMutex* pDirMutex;
+
+ SvStringsDtor aPickList;
+ SvStringsDtor* pCompletions;
+ SvStringsDtor* pURLs;
+ svtools::AsynchronLink aLink;
+ String aBaseURL;
+ String aText;
+ SvtURLBox* pBox;
+ sal_Bool bStop;
+ sal_Bool bOnlyDirectories;
+ sal_Bool bNoSelection;
+
+ DECL_STATIC_LINK( SvtMatchContext_Impl, Select_Impl, void* );
+
+ virtual void SAL_CALL onTerminated( );
+ virtual void SAL_CALL run();
+ virtual void SAL_CALL Cancel();
+ void Insert( const String& rCompletion, const String& rURL, sal_Bool bForce = sal_False);
+ void ReadFolder( const String& rURL, const String& rMatch, sal_Bool bSmart );
+ void FillPicklist( SvStringsDtor& rPickList );
+
+public:
+ static ::vos::OMutex* GetMutex();
+
+ SvtMatchContext_Impl( SvtURLBox* pBoxP, const String& rText );
+ ~SvtMatchContext_Impl();
+ void Stop();
+};
+
+::vos::OMutex* SvtMatchContext_Impl::pDirMutex = 0;
+
+::vos::OMutex* SvtMatchContext_Impl::GetMutex()
+{
+ ::vos::OGuard aGuard( ::vos::OMutex::getGlobalMutex() );
+ if( !pDirMutex )
+ pDirMutex = new ::vos::OMutex;
+ return pDirMutex;
+}
+
+//-------------------------------------------------------------------------
+SvtMatchContext_Impl::SvtMatchContext_Impl(
+ SvtURLBox* pBoxP, const String& rText )
+ : aLink( STATIC_LINK( this, SvtMatchContext_Impl, Select_Impl ) )
+ , aBaseURL( pBoxP->aBaseURL )
+ , aText( rText )
+ , pBox( pBoxP )
+ , bStop( sal_False )
+ , bOnlyDirectories( pBoxP->bOnlyDirectories )
+ , bNoSelection( pBoxP->bNoSelection )
+{
+ pURLs = new SvStringsDtor;
+ pCompletions = new SvStringsDtor;
+
+ aLink.CreateMutex();
+
+ FillPicklist( aPickList );
+
+ create();
+}
+
+//-------------------------------------------------------------------------
+SvtMatchContext_Impl::~SvtMatchContext_Impl()
+{
+ aLink.ClearPendingCall();
+ delete pURLs;
+ delete pCompletions;
+}
+
+//-------------------------------------------------------------------------
+void SvtMatchContext_Impl::FillPicklist( SvStringsDtor& rPickList )
+{
+ // Einlesung der Historypickliste
+ Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( eHISTORY );
+ sal_uInt32 nCount = seqPicklist.getLength();
+
+ for( sal_uInt32 nItem=0; nItem < nCount; nItem++ )
+ {
+ Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
+
+ OUString sTitle;
+ INetURLObject aURL;
+
+ sal_uInt32 nPropertyCount = seqPropertySet.getLength();
+
+ for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ )
+ {
+ if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_TITLE )
+ {
+ seqPropertySet[nProperty].Value >>= sTitle;
+ aURL.SetURL( sTitle );
+ const StringPtr pStr = new String( aURL.GetMainURL( INetURLObject::DECODE_WITH_CHARSET ) );
+ rPickList.Insert( pStr, (sal_uInt16) nItem );
+ break;
+ }
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+void SAL_CALL SvtMatchContext_Impl::Cancel()
+{
+ // Cancel button pressed
+ terminate();
+}
+
+//-------------------------------------------------------------------------
+void SvtMatchContext_Impl::Stop()
+{
+ bStop = sal_True;
+
+ if( isRunning() )
+ terminate();
+}
+
+//-------------------------------------------------------------------------
+void SvtMatchContext_Impl::onTerminated( )
+{
+ aLink.Call( this );
+}
+
+//-------------------------------------------------------------------------
+// This method is called via AsynchronLink, so it has the SolarMutex and
+// calling solar code ( VCL ... ) is safe. It is called when the thread is
+// terminated ( finished work or stopped ). Cancelling the thread via
+// Cancellable does not not discard the information gained so far, it
+// inserts all collected completions into the listbox.
+
+IMPL_STATIC_LINK( SvtMatchContext_Impl, Select_Impl, void*, )
+{
+ // avoid recursion through cancel button
+ if( pThis->bStop )
+ {
+ // completions was stopped, no display
+ delete pThis;
+ return 0;
+ }
+
+ SvtURLBox* pBox = pThis->pBox;
+ pBox->bAutoCompleteMode = sal_True;
+
+ // did we filter completions which otherwise would have been valid?
+ // (to be filled below)
+ bool bValidCompletionsFiltered = false;
+
+ // insert all completed strings into the listbox
+ pBox->Clear();
+
+ for( sal_uInt16 nPos = 0; nPos<pThis->pCompletions->Count(); nPos++ )
+ {
+ String sCompletion( *(*pThis->pCompletions)[nPos] );
+
+ // convert the file into an URL
+ String sURL( sCompletion );
+ ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sCompletion, sURL );
+ // note: if this doesn't work, we're not interested in: we're checking the
+ // untouched sCompletion then
+
+ if ( pBox->pImp->pUrlFilter )
+ {
+ if ( !pBox->pImp->pUrlFilter->isUrlAllowed( sURL ) )
+ { // this URL is not allowed
+ bValidCompletionsFiltered = true;
+ continue;
+ }
+ }
+ if (( sURL.Len() > 0 ) && ( sURL.GetChar(sURL.Len()-1) != '/' ))
+ {
+ String sUpperURL( sURL );
+ sUpperURL.ToUpperAscii();
+
+ ::std::vector< WildCard >::const_iterator aMatchingFilter =
+ ::std::find_if(
+ pBox->pImp->m_aFilters.begin(),
+ pBox->pImp->m_aFilters.end(),
+ FilterMatch( sUpperURL )
+ );
+ if ( aMatchingFilter == pBox->pImp->m_aFilters.end() )
+
+ { // this URL is not allowed
+ bValidCompletionsFiltered = true;
+ continue;
+ }
+ }
+
+ pBox->InsertEntry( sCompletion );
+ }
+
+ if( !pThis->bNoSelection && pThis->pCompletions->Count() && !bValidCompletionsFiltered )
+ {
+ // select the first one
+ String aTmp( pBox->GetEntry(0) );
+ pBox->SetText( aTmp );
+ pBox->SetSelection( Selection( pThis->aText.Len(), aTmp.Len() ) );
+ }
+
+ // transfer string lists to listbox and forget them
+ delete pBox->pImp->pURLs;
+ delete pBox->pImp->pCompletions;
+ pBox->pImp->pURLs = pThis->pURLs;
+ pBox->pImp->pCompletions = pThis->pCompletions;
+ pThis->pURLs = NULL;
+ pThis->pCompletions = NULL;
+
+ // force listbox to resize ( it may be open )
+ pBox->Resize();
+
+ // the box has this control as a member so we have to set that member
+ // to zero before deleting ourself.
+ pBox->pCtx = NULL;
+ delete pThis;
+
+ return 0;
+}
+
+//-------------------------------------------------------------------------
+void SvtMatchContext_Impl::Insert( const String& rCompletion,
+ const String& rURL,
+ sal_Bool bForce )
+{
+ if( !bForce )
+ {
+ // avoid doubles
+ for( sal_uInt16 nPos = pCompletions->Count(); nPos--; )
+ if( *(*pCompletions)[ nPos ] == rCompletion )
+ return;
+ }
+
+ const StringPtr pCompletion = new String( rCompletion );
+ pCompletions->Insert( pCompletion, pCompletions->Count() );
+ const StringPtr pURL = new String( rURL );
+ pURLs->Insert( pURL, pURLs->Count() );
+}
+
+//-------------------------------------------------------------------------
+void SvtMatchContext_Impl::ReadFolder( const String& rURL,
+ const String& rMatch,
+ sal_Bool bSmart )
+{
+ // check folder to scan
+ if( !UCBContentHelper::IsFolder( rURL ) )
+ return;
+
+ sal_Bool bPureHomePath = sal_False;
+#ifdef UNX
+ bPureHomePath = aText.Search( '~' ) == 0 && aText.Search( '/' ) == STRING_NOTFOUND;
+#endif
+
+ sal_Bool bExectMatch = bPureHomePath
+ || aText.CompareToAscii( "." ) == COMPARE_EQUAL
+ || (aText.Len() > 1 && aText.Copy( aText.Len() - 2, 2 ).CompareToAscii( "/." ) == COMPARE_EQUAL)
+ || (aText.Len() > 2 && aText.Copy( aText.Len() - 3, 3 ).CompareToAscii( "/.." ) == COMPARE_EQUAL);
+
+ // for pure home pathes ( ~username ) the '.' at the end of rMatch
+ // means that it poits to root catalog
+ // this is done only for file contents since home pathes parsing is usefull only for them
+ if ( bPureHomePath && rMatch.Equals( String::CreateFromAscii( "file:///." ) ) )
+ {
+ // a home that refers to /
+
+ String aNewText( aText );
+ aNewText += '/';
+ Insert( aNewText, rURL, sal_True );
+
+ return;
+ }
+
+ // string to match with
+ INetURLObject aMatchObj( rMatch );
+ String aMatchName;
+
+ if ( rURL != String(aMatchObj.GetMainURL( INetURLObject::NO_DECODE ) ))
+ {
+ aMatchName = aMatchObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
+
+ // matching is always done case insensitive, but completion will be case sensitive and case preserving
+ aMatchName.ToLowerAscii();
+
+ // if the matchstring ends with a slash, we must search for this also
+ if ( rMatch.GetChar(rMatch.Len()-1) == '/' )
+ aMatchName += '/';
+ }
+
+ xub_StrLen nMatchLen = aMatchName.Len();
+
+ INetURLObject aFolderObj( rURL );
+ DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
+
+ try
+ {
+ uno::Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
+
+ Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ),
+ new ::ucbhelper::CommandEnvironment( uno::Reference< XInteractionHandler >(),
+ uno::Reference< XProgressHandler >() ) );
+ uno::Reference< XResultSet > xResultSet;
+ Sequence< OUString > aProps(2);
+ OUString* pProps = aProps.getArray();
+ pProps[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
+ pProps[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) );
+
+ try
+ {
+ uno::Reference< XDynamicResultSet > xDynResultSet;
+ ResultSetInclude eInclude = INCLUDE_FOLDERS_AND_DOCUMENTS;
+ if ( bOnlyDirectories )
+ eInclude = INCLUDE_FOLDERS_ONLY;
+
+ xDynResultSet = aCnt.createDynamicCursor( aProps, eInclude );
+
+ uno::Reference < XAnyCompareFactory > xCompare;
+ uno::Reference < XSortedDynamicResultSetFactory > xSRSFac(
+ xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SortedDynamicResultSetFactory") ) ), UNO_QUERY );
+
+ Sequence< NumberedSortingInfo > aSortInfo( 2 );
+ NumberedSortingInfo* pInfo = aSortInfo.getArray();
+ pInfo[ 0 ].ColumnIndex = 2;
+ pInfo[ 0 ].Ascending = sal_False;
+ pInfo[ 1 ].ColumnIndex = 1;
+ pInfo[ 1 ].Ascending = sal_True;
+
+ uno::Reference< XDynamicResultSet > xDynamicResultSet;
+ xDynamicResultSet =
+ xSRSFac->createSortedDynamicResultSet( xDynResultSet, aSortInfo, xCompare );
+
+ if ( xDynamicResultSet.is() )
+ {
+ xResultSet = xDynamicResultSet->getStaticResultSet();
+ }
+ }
+ catch( ::com::sun::star::uno::Exception& ) {}
+
+ if ( xResultSet.is() )
+ {
+ uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
+ uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
+
+ try
+ {
+ while ( schedule() && xResultSet->next() )
+ {
+ String aURL = xContentAccess->queryContentIdentifierString();
+ String aTitle = xRow->getString(1);
+ sal_Bool bIsFolder = xRow->getBoolean(2);
+
+ // matching is always done case insensitive, but completion will be case sensitive and case preserving
+ aTitle.ToLowerAscii();
+
+ if (
+ !nMatchLen ||
+ (bExectMatch && aMatchName.Equals(aTitle)) ||
+ (!bExectMatch && aMatchName.CompareTo(aTitle, nMatchLen) == COMPARE_EQUAL)
+ )
+ {
+ // all names fit if matchstring is empty
+ INetURLObject aObj( aURL );
+ sal_Unicode aDelimiter = '/';
+ if ( bSmart )
+ // when parsing is done "smart", the delimiter must be "guessed"
+ aObj.getFSysPath( (INetURLObject::FSysStyle)(INetURLObject::FSYS_DETECT & ~INetURLObject::FSYS_VOS), &aDelimiter );
+
+ if ( bIsFolder )
+ aObj.setFinalSlash();
+
+ // get the last name of the URL
+ String aMatch = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
+ String aInput( aText );
+ if ( nMatchLen )
+ {
+ if ((aText.Len() && aText.GetChar(aText.Len() - 1) == '.') || bPureHomePath)
+ {
+ // if a "special folder" URL was typed, don't touch the user input
+ aMatch.Erase( 0, nMatchLen );
+ }
+ else
+ {
+ // make the user input case preserving
+ DBG_ASSERT( aInput.Len() >= nMatchLen, "Suspicious Matching!" );
+ aInput.Erase( aInput.Len() - nMatchLen );
+ }
+ }
+
+ aInput += aMatch;
+
+ // folders should get a final slash automatically
+ if ( bIsFolder )
+ aInput += aDelimiter;
+
+ Insert( aInput, aObj.GetMainURL( INetURLObject::NO_DECODE ), sal_True );
+ }
+ }
+ }
+ catch( ::com::sun::star::uno::Exception& )
+ {
+ }
+ }
+ }
+ catch( ::com::sun::star::uno::Exception& )
+ {
+ }
+}
+
+//-------------------------------------------------------------------------
+String SvtURLBox::ParseSmart( String aText, String aBaseURL, String aWorkDir )
+{
+ String aMatch;
+
+ // parse ~ for Unix systems
+ // does nothing for Windows
+ if( !SvtURLBox_Impl::TildeParsing( aText, aBaseURL ) )
+ return String();
+
+ INetURLObject aURLObject;
+ if( aBaseURL.Len() )
+ {
+ INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL );
+
+ // if a base URL is set the string may be parsed relative
+ if( aText.Search( '/' ) == 0 )
+ {
+ // text starting with slashes means absolute file URLs
+ String aTemp = INetURLObject::GetScheme( eBaseProt );
+
+ // file URL must be correctly encoded!
+ String aTextURL = INetURLObject::encode( aText, INetURLObject::PART_FPATH,
+ '%', INetURLObject::ENCODE_ALL );
+ aTemp += aTextURL;
+
+ INetURLObject aTmp( aTemp );
+ if ( !aTmp.HasError() && aTmp.GetProtocol() != INET_PROT_NOT_VALID )
+ aMatch = aTmp.GetMainURL( INetURLObject::NO_DECODE );
+ }
+ else
+ {
+ String aSmart( aText );
+ INetURLObject aObj( aBaseURL );
+
+ // HRO: I suppose this hack should only be done for Windows !!!???
+#ifdef WNT
+ // HRO: INetURLObject::smatRel2Abs does not recognize '\\' as a relative path
+ // but in case of "\\\\" INetURLObject is right - this is an absolute path !
+
+ if( aText.Search( '\\' ) == 0 && (aText.Len() < 2 || aText.GetChar( 1 ) != '\\') )
+ {
+ // cut to first segment
+ String aTmp = INetURLObject::GetScheme( eBaseProt );
+ aTmp += '/';
+ aTmp += String(aObj.getName( 0, true, INetURLObject::DECODE_WITH_CHARSET ));
+ aObj.SetURL( aTmp );
+
+ aSmart.Erase(0,1);
+ }
+#endif
+ // base URL must be a directory !
+ aObj.setFinalSlash();
+
+ // take base URL and append current input
+ bool bWasAbsolute = sal_False;
+#ifdef UNX
+ // don't support FSYS_MAC under Unix, because here ':' is a valid character for a filename
+ INetURLObject::FSysStyle eStyle = static_cast< INetURLObject::FSysStyle >( INetURLObject::FSYS_VOS | INetURLObject::FSYS_UNX | INetURLObject::FSYS_DOS );
+ // encode file URL correctly
+ aSmart = INetURLObject::encode( aSmart, INetURLObject::PART_FPATH, '%', INetURLObject::ENCODE_ALL );
+ INetURLObject aTmp( aObj.smartRel2Abs(
+ aSmart, bWasAbsolute, false, INetURLObject::WAS_ENCODED, RTL_TEXTENCODING_UTF8, false, eStyle ) );
+#else
+ INetURLObject aTmp( aObj.smartRel2Abs( aSmart, bWasAbsolute ) );
+#endif
+
+ if ( aText.GetChar( aText.Len() - 1 ) == '.' )
+ // INetURLObject appends a final slash for the directories "." and "..", this is a bug!
+ // Remove it as a workaround
+ aTmp.removeFinalSlash();
+ if ( !aTmp.HasError() && aTmp.GetProtocol() != INET_PROT_NOT_VALID )
+ aMatch = aTmp.GetMainURL( INetURLObject::NO_DECODE );
+ }
+ }
+ else
+ {
+ ::utl::LocalFileHelper::ConvertSystemPathToURL( aText, aWorkDir, aMatch );
+ }
+
+ return aMatch;
+}
+
+//-------------------------------------------------------------------------
+void SvtMatchContext_Impl::run()
+{
+ ::vos::OGuard aGuard( GetMutex() );
+ if( bStop )
+ // have we been stopped while we were waiting for the mutex?
+ return;
+
+ // Reset match lists
+ pCompletions->Remove( 0, pCompletions->Count() );
+ pURLs->Remove( 0, pURLs->Count() );
+
+ // check for input
+ sal_uInt16 nTextLen = aText.Len();
+ if ( !nTextLen )
+ return;
+
+ if( aText.Search( '*' ) != STRING_NOTFOUND || aText.Search( '?' ) != STRING_NOTFOUND )
+ // no autocompletion for wildcards
+ return;
+
+ String aMatch;
+ String aWorkDir( SvtPathOptions().GetWorkPath() );
+ INetProtocol eProt = INetURLObject::CompareProtocolScheme( aText );
+ INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL );
+ if ( !aBaseURL.Len() )
+ eBaseProt = INetURLObject::CompareProtocolScheme( aWorkDir );
+ INetProtocol eSmartProt = pBox->GetSmartProtocol();
+
+ // if the user input is a valid URL, go on with it
+ // otherwise it could be parsed smart with a predefined smart protocol
+ // ( or if this is not set with the protocol of a predefined base URL )
+ if( eProt == INET_PROT_NOT_VALID || eProt == eSmartProt || (eSmartProt == INET_PROT_NOT_VALID && eProt == eBaseProt) )
+ {
+ // not stopped yet ?
+ if( schedule() )
+ {
+ if ( eProt == INET_PROT_NOT_VALID )
+ aMatch = SvtURLBox::ParseSmart( aText, aBaseURL, aWorkDir );
+ else
+ aMatch = aText;
+ if ( aMatch.Len() )
+ {
+ INetURLObject aURLObject( aMatch );
+ String aMainURL( aURLObject.GetMainURL( INetURLObject::NO_DECODE ) );
+ if ( aMainURL.Len() )
+ {
+ // if text input is a directory, it must be part of the match list! Until then it is scanned
+ if ( UCBContentHelper::IsFolder( aMainURL ) && aURLObject.hasFinalSlash() )
+ Insert( aText, aMatch );
+ else
+ // otherwise the parent folder will be taken
+ aURLObject.removeSegment();
+
+ // scan directory and insert all matches
+ ReadFolder( aURLObject.GetMainURL( INetURLObject::NO_DECODE ), aMatch, eProt == INET_PROT_NOT_VALID );
+ }
+ }
+ }
+ }
+
+ if ( bOnlyDirectories )
+ // don't scan history picklist if only directories are allowed, picklist contains only files
+ return;
+
+ sal_Bool bFull = sal_False;
+ int nCount = aPickList.Count();
+
+ INetURLObject aCurObj;
+ String aEmpty, aCurString, aCurMainURL;
+ INetURLObject aObj;
+ aObj.SetSmartProtocol( eSmartProt == INET_PROT_NOT_VALID ? INET_PROT_HTTP : eSmartProt );
+ for( ;; )
+ {
+ for( sal_uInt16 nPos = 0; schedule() && nPos < nCount; nPos++ )
+ {
+ aCurObj.SetURL( *aPickList.GetObject( nPos ) );
+ aCurObj.SetSmartURL( aCurObj.GetURLNoPass());
+ aCurMainURL = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
+
+ if( eProt != INET_PROT_NOT_VALID && aCurObj.GetProtocol() != eProt )
+ continue;
+
+ if( eSmartProt != INET_PROT_NOT_VALID && aCurObj.GetProtocol() != eSmartProt )
+ continue;
+
+ switch( aCurObj.GetProtocol() )
+ {
+ case INET_PROT_HTTP:
+ case INET_PROT_HTTPS:
+ case INET_PROT_FTP:
+ {
+ if( eProt == INET_PROT_NOT_VALID && !bFull )
+ {
+ aObj.SetSmartURL( aText );
+ if( aObj.GetURLPath().getLength() > 1 )
+ continue;
+ }
+
+ aCurString = aCurMainURL;
+ if( eProt == INET_PROT_NOT_VALID )
+ {
+ // try if text matches the scheme
+ String aScheme( INetURLObject::GetScheme( aCurObj.GetProtocol() ) );
+ if ( aText.CompareIgnoreCaseToAscii( aScheme, aText.Len() ) == COMPARE_EQUAL && aText.Len() < aScheme.Len() )
+ {
+ if( bFull )
+ aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
+ else
+ {
+ aCurObj.SetMark( aEmpty );
+ aCurObj.SetParam( aEmpty );
+ aCurObj.SetURLPath( aEmpty );
+ aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
+ }
+
+ Insert( aMatch, aMatch );
+ }
+
+ // now try smart matching
+ aCurString.Erase( 0, aScheme.Len() );
+ }
+
+ if( aText.CompareIgnoreCaseToAscii( aCurString, aText.Len() )== COMPARE_EQUAL )
+ {
+ if( bFull )
+ aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
+ else
+ {
+ aCurObj.SetMark( aEmpty );
+ aCurObj.SetParam( aEmpty );
+ aCurObj.SetURLPath( aEmpty );
+ aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
+ }
+
+ String aURL( aMatch );
+ if( eProt == INET_PROT_NOT_VALID )
+ aMatch.Erase( 0, sal::static_int_cast< xub_StrLen >(INetURLObject::GetScheme( aCurObj.GetProtocol() ).getLength()) );
+
+ if( aText.Len() < aMatch.Len() )
+ Insert( aMatch, aURL );
+
+ continue;
+ }
+ break;
+ }
+ default:
+ {
+ if( bFull )
+ continue;
+
+ if( aText.CompareTo( aCurMainURL, aText.Len() ) == COMPARE_EQUAL )
+ {
+ if( aText.Len() < aCurMainURL.Len() )
+ Insert( aCurMainURL, aCurMainURL );
+
+ continue;
+ }
+ break;
+ }
+ }
+ }
+
+ if( !bFull )
+ bFull = sal_True;
+ else
+ break;
+ }
+
+ return;
+}
+
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+void SvtURLBox::TryAutoComplete( sal_Bool bForce )
+{
+ if( Application::AnyInput( INPUT_KEYBOARD ) ) return;
+
+ String aMatchString;
+ String aCurText = GetText();
+ Selection aSelection( GetSelection() );
+ if( aSelection.Max() != aCurText.Len() && !bForce )
+ return;
+ sal_uInt16 nLen = (sal_uInt16)aSelection.Min();
+ aCurText.Erase( nLen );
+ if( aCurText.Len() && bIsAutoCompleteEnabled )
+ {
+ if ( pCtx )
+ {
+ pCtx->Stop();
+ pCtx = NULL;
+ }
+ pCtx = new SvtMatchContext_Impl( this, aCurText );
+ }
+}
+
+//-------------------------------------------------------------------------
+SvtURLBox::SvtURLBox( Window* pParent, INetProtocol eSmart )
+ : ComboBox( pParent , WB_DROPDOWN | WB_AUTOSIZE | WB_AUTOHSCROLL ),
+ pCtx( 0 ),
+ eSmartProtocol( eSmart ),
+ bAutoCompleteMode( sal_False ),
+ bOnlyDirectories( sal_False ),
+ bTryAutoComplete( sal_False ),
+ bCtrlClick( sal_False ),
+ bHistoryDisabled( sal_False ),
+ bNoSelection( sal_False ),
+ bIsAutoCompleteEnabled( sal_True )
+{
+ ImplInit();
+
+ if ( GetDesktopRectPixel().GetWidth() > 800 )
+ SetSizePixel( Size( 300, 240 ) );
+ else
+ SetSizePixel( Size( 225, 240 ) );
+}
+
+//-------------------------------------------------------------------------
+SvtURLBox::SvtURLBox( Window* pParent, WinBits _nStyle, INetProtocol eSmart )
+ : ComboBox( pParent, _nStyle ),
+ pCtx( 0 ),
+ eSmartProtocol( eSmart ),
+ bAutoCompleteMode( sal_False ),
+ bOnlyDirectories( sal_False ),
+ bTryAutoComplete( sal_False ),
+ bCtrlClick( sal_False ),
+ bHistoryDisabled( sal_False ),
+ bNoSelection( sal_False ),
+ bIsAutoCompleteEnabled( sal_True )
+{
+ ImplInit();
+}
+
+//-------------------------------------------------------------------------
+SvtURLBox::SvtURLBox( Window* pParent, const ResId& _rResId, INetProtocol eSmart )
+ : ComboBox( pParent , _rResId ),
+ pCtx( 0 ),
+ eSmartProtocol( eSmart ),
+ bAutoCompleteMode( sal_False ),
+ bOnlyDirectories( sal_False ),
+ bTryAutoComplete( sal_False ),
+ bCtrlClick( sal_False ),
+ bHistoryDisabled( sal_False ),
+ bNoSelection( sal_False ),
+ bIsAutoCompleteEnabled( sal_True )
+{
+ ImplInit();
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::ImplInit()
+{
+ pImp = new SvtURLBox_Impl();
+
+ if ( GetHelpId().getLength() == 0 )
+ SetHelpId( ".uno:OpenURL" );
+ EnableAutocomplete( sal_False );
+
+ SetText( String() );
+
+ GetSubEdit()->SetAutocompleteHdl( LINK( this, SvtURLBox, AutoCompleteHdl_Impl ) );
+ UpdatePicklistForSmartProtocol_Impl();
+}
+
+//-------------------------------------------------------------------------
+SvtURLBox::~SvtURLBox()
+{
+ if( pCtx )
+ {
+ pCtx->Stop();
+ pCtx = NULL;
+ }
+
+ delete pImp->pURLs;
+ delete pImp->pCompletions;
+ delete pImp;
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::UpdatePickList( )
+{
+ if( pCtx )
+ {
+ pCtx->Stop();
+ pCtx = NULL;
+ }
+
+ String sText = GetText();
+ if ( sText.Len() && bIsAutoCompleteEnabled )
+ pCtx = new SvtMatchContext_Impl( this, sText );
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::SetSmartProtocol( INetProtocol eProt )
+{
+ if ( eSmartProtocol != eProt )
+ {
+ eSmartProtocol = eProt;
+ UpdatePicklistForSmartProtocol_Impl();
+ }
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::UpdatePicklistForSmartProtocol_Impl()
+{
+ Clear();
+ if ( !bHistoryDisabled )
+ {
+ // read history pick list
+ Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( eHISTORY );
+ sal_uInt32 nCount = seqPicklist.getLength();
+ INetURLObject aCurObj;
+
+ for( sal_uInt32 nItem=0; nItem < nCount; nItem++ )
+ {
+ Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
+
+ OUString sURL;
+
+ sal_uInt32 nPropertyCount = seqPropertySet.getLength();
+
+ for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ )
+ {
+ if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_URL )
+ {
+ seqPropertySet[nProperty].Value >>= sURL;
+ aCurObj.SetURL( sURL );
+
+ if ( sURL.getLength() && ( eSmartProtocol != INET_PROT_NOT_VALID ) )
+ {
+ if( aCurObj.GetProtocol() != eSmartProtocol )
+ break;
+ }
+
+ String aURL( aCurObj.GetMainURL( INetURLObject::DECODE_WITH_CHARSET ) );
+
+ if ( aURL.Len() && ( !pImp->pUrlFilter || pImp->pUrlFilter->isUrlAllowed( aURL ) ) )
+ {
+ sal_Bool bFound = (aURL.GetChar(aURL.Len()-1) == '/' );
+ if ( !bFound )
+ {
+ String aUpperURL( aURL );
+ aUpperURL.ToUpperAscii();
+
+ bFound
+ = (::std::find_if(
+ pImp->m_aFilters.begin(),
+ pImp->m_aFilters.end(),
+ FilterMatch( aUpperURL ) )
+ != pImp->m_aFilters.end());
+ }
+ if ( bFound )
+ {
+ String aFile;
+ if (::utl::LocalFileHelper::ConvertURLToSystemPath(aURL,aFile))
+ InsertEntry(aFile);
+ else
+ InsertEntry(aURL);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+sal_Bool SvtURLBox::ProcessKey( const KeyCode& rKey )
+{
+ // every key input stops the current matching thread
+ if( pCtx )
+ {
+ pCtx->Stop();
+ pCtx = NULL;
+ }
+
+ KeyCode aCode( rKey.GetCode() );
+ if ( aCode == KEY_RETURN && GetText().Len() )
+ {
+ // wait for completion of matching thread
+ ::vos::OGuard aGuard( SvtMatchContext_Impl::GetMutex() );
+
+ if ( bAutoCompleteMode )
+ {
+ // reset picklist
+ bAutoCompleteMode = sal_False;
+ Selection aSelection( GetSelection() );
+ SetSelection( Selection( aSelection.Min(), aSelection.Min() ) );
+ if ( bOnlyDirectories )
+ Clear();
+ else
+ UpdatePicklistForSmartProtocol_Impl();
+ Resize();
+ }
+
+ bCtrlClick = rKey.IsMod1();
+ sal_Bool bHandled = sal_False;
+ if ( GetOpenHdl().IsSet() )
+ {
+ bHandled = sal_True;
+ GetOpenHdl().Call(this);
+ }
+ else if ( GetSelectHdl().IsSet() )
+ {
+ bHandled = sal_True;
+ GetSelectHdl().Call(this);
+ }
+
+ bCtrlClick = sal_False;
+
+ ClearModifyFlag();
+ return bHandled;
+ }
+ else if ( aCode == KEY_RETURN && !GetText().Len() && GetOpenHdl().IsSet() )
+ {
+ // for file dialog
+ bAutoCompleteMode = sal_False;
+ GetOpenHdl().Call(this);
+ return sal_True;
+ }
+ else if( aCode == KEY_ESCAPE )
+ {
+ Selection aSelection( GetSelection() );
+ if ( bAutoCompleteMode || aSelection.Min() != aSelection.Max() )
+ {
+ SetSelection( Selection( aSelection.Min(), aSelection.Min() ) );
+ if ( bOnlyDirectories )
+ Clear();
+ else
+ UpdatePicklistForSmartProtocol_Impl();
+ Resize();
+ }
+ else
+ {
+ return sal_False;
+ }
+
+ bAutoCompleteMode = sal_False;
+ return sal_True;
+ }
+ else
+ {
+ return sal_False;
+ }
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::Modify()
+{
+ ComboBox::Modify();
+}
+
+//-------------------------------------------------------------------------
+long SvtURLBox::PreNotify( NotifyEvent& rNEvt )
+{
+ if( rNEvt.GetWindow() == GetSubEdit() && rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+
+ const KeyEvent& rEvent = *rNEvt.GetKeyEvent();
+ const KeyCode& rKey = rEvent.GetKeyCode();
+ KeyCode aCode( rKey.GetCode() );
+ if( ProcessKey( rKey ) )
+ {
+ return sal_True;
+ }
+ else if( ( aCode == KEY_UP || aCode == KEY_DOWN ) && !rKey.IsMod2() )
+ {
+ Selection aSelection( GetSelection() );
+ sal_uInt16 nLen = (sal_uInt16)aSelection.Min();
+ GetSubEdit()->KeyInput( rEvent );
+ SetSelection( Selection( nLen, GetText().Len() ) );
+ return sal_True;
+ }
+
+ if ( MatchesPlaceHolder( GetText() ) )
+ {
+ // set the selection so a key stroke will overwrite
+ // the placeholder rather than edit it
+ SetSelection( Selection( 0, GetText().Len() ) );
+ }
+ }
+
+ return ComboBox::PreNotify( rNEvt );
+}
+
+//-------------------------------------------------------------------------
+IMPL_LINK( SvtURLBox, AutoCompleteHdl_Impl, void*, EMPTYARG )
+{
+ if ( GetSubEdit()->GetAutocompleteAction() == AUTOCOMPLETE_KEYINPUT )
+ {
+ TryAutoComplete( sal_False );
+ return 1L;
+ }
+
+ return 0L;
+}
+
+//-------------------------------------------------------------------------
+long SvtURLBox::Notify( NotifyEvent &rEvt )
+{
+ if ( EVENT_GETFOCUS == rEvt.GetType() )
+ {
+#ifndef UNX
+ // pb: don't select automatically on unix #93251#
+ SetSelection( Selection( 0, GetText().Len() ) );
+#endif
+ }
+ else if ( EVENT_LOSEFOCUS == rEvt.GetType() )
+ {
+ if( !GetText().Len() )
+ ClearModifyFlag();
+ if ( pCtx )
+ {
+ pCtx->Stop();
+ pCtx = NULL;
+ }
+ }
+
+ return ComboBox::Notify( rEvt );
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::Select()
+{
+ ComboBox::Select();
+ ClearModifyFlag();
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::SetOnlyDirectories( sal_Bool bDir )
+{
+ bOnlyDirectories = bDir;
+ if ( bOnlyDirectories )
+ Clear();
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::SetNoURLSelection( sal_Bool bSet )
+{
+ bNoSelection = bSet;
+}
+
+//-------------------------------------------------------------------------
+String SvtURLBox::GetURL()
+{
+ // wait for end of autocompletion
+ ::vos::OGuard aGuard( SvtMatchContext_Impl::GetMutex() );
+
+ String aText( GetText() );
+ if ( MatchesPlaceHolder( aText ) )
+ return aPlaceHolder;
+ // try to get the right case preserving URL from the list of URLs
+ if ( pImp->pCompletions && pImp->pURLs )
+ {
+ for( sal_uInt16 nPos=0; nPos<pImp->pCompletions->Count(); nPos++ )
+ {
+#ifdef DBG_UTIL
+ String aTmp( *(*pImp->pCompletions)[ nPos ] );
+#endif
+ if( *(*pImp->pCompletions)[ nPos ] == aText )
+ return *(*pImp->pURLs)[nPos];
+ }
+ }
+
+#ifdef WNT
+ // erase trailing spaces on Windows since thay are invalid on this OS and
+ // most of the time they are inserted by accident via copy / paste
+ aText.EraseTrailingChars();
+ if ( !aText.Len() )
+ return aText;
+ // #i9739# - 2002-12-03 - fs@openoffice.org
+#endif
+
+ INetURLObject aObj( aText );
+ if( aText.Search( '*' ) != STRING_NOTFOUND || aText.Search( '?' ) != STRING_NOTFOUND )
+ {
+ // no autocompletion for wildcards
+ INetURLObject aTempObj;
+ if ( eSmartProtocol != INET_PROT_NOT_VALID )
+ aTempObj.SetSmartProtocol( eSmartProtocol );
+ if ( aTempObj.SetSmartURL( aText ) )
+ return aTempObj.GetMainURL( INetURLObject::NO_DECODE );
+ else
+ return aText;
+ }
+
+ if ( aObj.GetProtocol() == INET_PROT_NOT_VALID )
+ {
+ String aName = ParseSmart( aText, aBaseURL, SvtPathOptions().GetWorkPath() );
+ aObj.SetURL( aName );
+ ::rtl::OUString aURL( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
+ if ( !aURL.getLength() )
+ // aText itself is invalid, and even together with aBaseURL, it could not
+ // made valid -> no chance
+ return aText;
+
+ bool bSlash = aObj.hasFinalSlash();
+ {
+ static const rtl::OUString aPropName(
+ rtl::OUString::createFromAscii("CasePreservingURL"));
+
+ rtl::OUString aFileURL;
+
+ Any aAny =
+ UCBContentHelper::GetProperty(aURL,aPropName);
+ sal_Bool success = (aAny >>= aFileURL);
+ String aTitle;
+ if(success)
+ aTitle = String(
+ INetURLObject(aFileURL).getName(
+ INetURLObject::LAST_SEGMENT,
+ true,
+ INetURLObject::DECODE_WITH_CHARSET ));
+ else
+ success =
+ UCBContentHelper::GetTitle(aURL,aTitle);
+
+ if( success &&
+ ( aTitle.Len() > 1 ||
+ (aTitle.CompareToAscii("/") != 0 &&
+ aTitle.CompareToAscii(".") != 0) ) )
+ {
+ aObj.SetName( aTitle );
+ if ( bSlash )
+ aObj.setFinalSlash();
+ }
+ }
+ }
+
+ return aObj.GetMainURL( INetURLObject::NO_DECODE );
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::DisableHistory()
+{
+ bHistoryDisabled = sal_True;
+ UpdatePicklistForSmartProtocol_Impl();
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::SetBaseURL( const String& rURL )
+{
+ ::vos::OGuard aGuard( SvtMatchContext_Impl::GetMutex() );
+
+ // Reset match lists
+ if ( pImp->pCompletions )
+ pImp->pCompletions->Remove( 0, pImp->pCompletions->Count() );
+
+ if ( pImp->pURLs )
+ pImp->pURLs->Remove( 0, pImp->pURLs->Count() );
+
+ aBaseURL = rURL;
+}
+
+//-------------------------------------------------------------------------
+/** Parse leading ~ for Unix systems,
+ does nothing for Windows
+ */
+sal_Bool SvtURLBox_Impl::TildeParsing(
+ String&
+#ifdef UNX
+ aText
+#endif
+ , String&
+#ifdef UNX
+ aBaseURL
+#endif
+)
+{
+#ifdef UNX
+ if( aText.Search( '~' ) == 0 )
+ {
+ String aParseTilde;
+ sal_Bool bTrailingSlash = sal_True; // use trailing slash
+
+ if( aText.Len() == 1 || aText.GetChar( 1 ) == '/' )
+ {
+ // covers "~" or "~/..." cases
+ const char* aHomeLocation = getenv( "HOME" );
+ if( !aHomeLocation )
+ aHomeLocation = "";
+
+ aParseTilde = String::CreateFromAscii( aHomeLocation );
+
+ // in case the whole path is just "~" then there should
+ // be no trailing slash at the end
+ if( aText.Len() == 1 )
+ bTrailingSlash = sal_False;
+ }
+ else
+ {
+ // covers "~username" and "~username/..." cases
+ xub_StrLen nNameEnd = aText.Search( '/' );
+ String aUserName = aText.Copy( 1, ( nNameEnd != STRING_NOTFOUND ) ? nNameEnd : ( aText.Len() - 1 ) );
+
+ struct passwd* pPasswd = NULL;
+#ifdef SOLARIS
+ Sequence< sal_Int8 > sBuf( 1024 );
+ struct passwd aTmp;
+ sal_Int32 nRes = getpwnam_r( OUStringToOString( OUString( aUserName ), RTL_TEXTENCODING_ASCII_US ).getStr(),
+ &aTmp,
+ (char*)sBuf.getArray(),
+ 1024,
+ &pPasswd );
+ if( !nRes && pPasswd )
+ aParseTilde = String::CreateFromAscii( pPasswd->pw_dir );
+ else
+ return sal_False; // no such user
+#else
+ pPasswd = getpwnam( OUStringToOString( OUString( aUserName ), RTL_TEXTENCODING_ASCII_US ).getStr() );
+ if( pPasswd )
+ aParseTilde = String::CreateFromAscii( pPasswd->pw_dir );
+ else
+ return sal_False; // no such user
+#endif
+
+ // in case the path is "~username" then there should
+ // be no trailing slash at the end
+ if( nNameEnd == STRING_NOTFOUND )
+ bTrailingSlash = sal_False;
+ }
+
+ if( !bTrailingSlash )
+ {
+ if( !aParseTilde.Len() || aParseTilde.EqualsAscii( "/" ) )
+ {
+ // "/" path should be converted to "/."
+ aParseTilde = String::CreateFromAscii( "/." );
+ }
+ else
+ {
+ // "blabla/" path should be converted to "blabla"
+ aParseTilde.EraseTrailingChars( '/' );
+ }
+ }
+ else
+ {
+ if( aParseTilde.GetChar( aParseTilde.Len() - 1 ) != '/' )
+ aParseTilde += '/';
+ if( aText.Len() > 2 )
+ aParseTilde += aText.Copy( 2 );
+ }
+
+ aText = aParseTilde;
+ aBaseURL = String(); // tilde provide absolute path
+ }
+#endif
+
+ return sal_True;
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::SetUrlFilter( const IUrlFilter* _pFilter )
+{
+ pImp->pUrlFilter = _pFilter;
+}
+
+//-------------------------------------------------------------------------
+const IUrlFilter* SvtURLBox::GetUrlFilter( ) const
+{
+ return pImp->pUrlFilter;
+}
+// -----------------------------------------------------------------------------
+void SvtURLBox::SetFilter(const String& _sFilter)
+{
+ pImp->m_aFilters.clear();
+ FilterMatch::createWildCardFilterList(_sFilter,pImp->m_aFilters);
+}
+
diff --git a/svtools/source/control/prgsbar.cxx b/svtools/source/control/prgsbar.cxx
new file mode 100755
index 000000000000..86b49c782398
--- /dev/null
+++ b/svtools/source/control/prgsbar.cxx
@@ -0,0 +1,258 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _SV_PRGSBAR_CXX
+
+#include <tools/debug.hxx>
+#include <vcl/status.hxx>
+#include <svtools/prgsbar.hxx>
+
+// =======================================================================
+
+#define PROGRESSBAR_OFFSET 3
+#define PROGRESSBAR_WIN_OFFSET 2
+
+// =======================================================================
+
+void ProgressBar::ImplInit()
+{
+ mnPercent = 0;
+ mbCalcNew = sal_True;
+
+ ImplInitSettings( sal_True, sal_True, sal_True );
+}
+
+static WinBits clearProgressBarBorder( Window* pParent, WinBits nOrgStyle )
+{
+ WinBits nOutStyle = nOrgStyle;
+ if( pParent && (nOrgStyle & WB_BORDER) != 0 )
+ {
+ if( pParent->IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
+ nOutStyle &= WB_BORDER;
+ }
+ return nOutStyle;
+}
+
+// -----------------------------------------------------------------------
+
+ProgressBar::ProgressBar( Window* pParent, WinBits nWinStyle ) :
+ Window( pParent, clearProgressBarBorder( pParent, nWinStyle ) )
+{
+ SetOutputSizePixel( Size( 150, 20 ) );
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+ProgressBar::ProgressBar( Window* pParent, const ResId& rResId ) :
+ Window( pParent, rResId )
+{
+ ImplInit();
+}
+
+// -----------------------------------------------------------------------
+
+ProgressBar::~ProgressBar()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::ImplInitSettings( sal_Bool bFont,
+ sal_Bool bForeground, sal_Bool bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+/* !!! Derzeit unterstuetzen wir keine Textausgaben
+ if ( bFont )
+ {
+ Font aFont;
+ aFont = rStyleSettings.GetAppFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+*/
+
+ if ( bBackground )
+ {
+ if( !IsControlBackground() &&
+ IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) )
+ {
+ if( (GetStyle() & WB_BORDER) )
+ SetBorderStyle( WINDOW_BORDER_REMOVEBORDER );
+ EnableChildTransparentMode( sal_True );
+ SetPaintTransparent( sal_True );
+ SetBackground();
+ SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ }
+ else
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else
+ aColor = rStyleSettings.GetFaceColor();
+ SetBackground( aColor );
+ }
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor = rStyleSettings.GetHighlightColor();
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ if ( aColor.IsRGBEqual( GetBackground().GetColor() ) )
+ {
+ if ( aColor.GetLuminance() > 100 )
+ aColor.DecreaseLuminance( 64 );
+ else
+ aColor.IncreaseLuminance( 64 );
+ }
+ SetLineColor();
+ SetFillColor( aColor );
+/* !!! Derzeit unterstuetzen wir keine Textausgaben
+ SetTextColor( aColor );
+ SetTextFillColor();
+*/
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::ImplDrawProgress( sal_uInt16 nOldPerc, sal_uInt16 nNewPerc )
+{
+ if ( mbCalcNew )
+ {
+ mbCalcNew = sal_False;
+
+ Size aSize = GetOutputSizePixel();
+ mnPrgsHeight = aSize.Height()-(PROGRESSBAR_WIN_OFFSET*2);
+ mnPrgsWidth = (mnPrgsHeight*2)/3;
+ maPos.Y() = PROGRESSBAR_WIN_OFFSET;
+ long nMaxWidth = (aSize.Width()-(PROGRESSBAR_WIN_OFFSET*2)+PROGRESSBAR_OFFSET);
+ sal_uInt16 nMaxCount = (sal_uInt16)(nMaxWidth / (mnPrgsWidth+PROGRESSBAR_OFFSET));
+ if ( nMaxCount <= 1 )
+ nMaxCount = 1;
+ else
+ {
+ while ( ((10000/(10000/nMaxCount))*(mnPrgsWidth+PROGRESSBAR_OFFSET)) > nMaxWidth )
+ nMaxCount--;
+ }
+ mnPercentCount = 10000/nMaxCount;
+ nMaxWidth = ((10000/(10000/nMaxCount))*(mnPrgsWidth+PROGRESSBAR_OFFSET))-PROGRESSBAR_OFFSET;
+ maPos.X() = (aSize.Width()-nMaxWidth)/2;
+ }
+
+ ::DrawProgress( this, maPos, PROGRESSBAR_OFFSET, mnPrgsWidth, mnPrgsHeight,
+ nOldPerc*100, nNewPerc*100, mnPercentCount,
+ Rectangle( Point(), GetSizePixel() ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::Paint( const Rectangle& )
+{
+ ImplDrawProgress( 0, mnPercent );
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::Resize()
+{
+ mbCalcNew = sal_True;
+ if ( IsReallyVisible() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::SetValue( sal_uInt16 nNewPercent )
+{
+ DBG_ASSERTWARNING( nNewPercent <= 100, "StatusBar::SetProgressValue(): nPercent > 100" );
+
+ if ( nNewPercent < mnPercent )
+ {
+ mbCalcNew = sal_True;
+ mnPercent = nNewPercent;
+ if ( IsReallyVisible() )
+ {
+ Invalidate();
+ Update();
+ }
+ }
+ else
+ {
+ ImplDrawProgress( mnPercent, nNewPercent );
+ mnPercent = nNewPercent;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::StateChanged( StateChangedType nType )
+{
+/* !!! Derzeit unterstuetzen wir keine Textausgaben
+ if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( sal_True, sal_False, sal_False );
+ Invalidate();
+ }
+ else
+*/
+ if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( sal_False, sal_True, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( sal_False, sal_False, sal_True );
+ Invalidate();
+ }
+
+ Window::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings( sal_True, sal_True, sal_True );
+ Invalidate();
+ }
+
+ Window::DataChanged( rDCEvt );
+}
+
diff --git a/svtools/source/control/roadmap.cxx b/svtools/source/control/roadmap.cxx
new file mode 100755
index 000000000000..118c16c3a4dc
--- /dev/null
+++ b/svtools/source/control/roadmap.cxx
@@ -0,0 +1,1018 @@
+/*************************************************************************
+ *
+ * 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 <svtools/roadmap.hxx>
+
+#ifndef _STRING_HXX
+#define _STRING_HXX
+#endif
+
+#include <vector>
+#include <algorithm>
+#include <vcl/bitmap.hxx>
+#include <tools/color.hxx>
+#include <memory>
+
+#define ROADMAP_INDENT_X 4
+#define ROADMAP_INDENT_Y 27
+#define ROADMAP_ITEM_DISTANCE_Y 6
+#define RMINCOMPLETE -1
+#define NADDITEM 1
+#define INCOMPLETELABEL ::String::CreateFromAscii("...") // TODO: Cast to String
+
+//.........................................................................
+namespace svt
+{
+//.........................................................................
+
+ typedef std::vector< ::rtl::OUString > S_Vector;
+ typedef std::vector< RoadmapItem* > HL_Vector;
+
+ //=====================================================================
+ //= ColorChanger
+ //=====================================================================
+ class IDLabel : public FixedText
+ {
+ public:
+ IDLabel( Window* _pParent, WinBits _nWinStyle = 0 );
+ ~IDLabel( );
+ virtual void DataChanged( const DataChangedEvent& rDCEvt );
+ };
+
+ //=====================================================================
+ //= ColorChanger
+ //=====================================================================
+ class ColorChanger
+ {
+ protected:
+ OutputDevice* m_pDev;
+
+ public:
+ ColorChanger( OutputDevice* _pDev, const Color& _rNewLineColor, const Color& _rNewFillColor )
+ :m_pDev( _pDev )
+ {
+ m_pDev->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ m_pDev->SetLineColor( _rNewLineColor );
+ m_pDev->SetFillColor( _rNewFillColor );
+ }
+
+ ~ColorChanger()
+ {
+ m_pDev->Pop();
+ }
+ };
+
+ //=====================================================================
+ //= RoadmapItem
+ //=====================================================================
+ class RoadmapItem : public RoadmapTypes
+ {
+ private:
+ IDLabel* mpID;
+ HyperLabel* mpDescription;
+ const Size m_aItemPlayground;
+
+ public:
+ RoadmapItem( ORoadmap& _rParent, const Size& _rItemPlayground );
+ ~RoadmapItem( );
+
+ void SetID( sal_Int16 _ID );
+ sal_Int16 GetID() const;
+
+ void SetIndex( ItemIndex _Index );
+ ItemIndex GetIndex() const;
+
+ void SetLabel( const ::rtl::OUString& _rText );
+ ::rtl::OUString GetLabel( );
+
+ void Update( ItemIndex _RMIndex, const ::rtl::OUString& _rText );
+
+ void SetPosition( RoadmapItem* OldHyperLabel );
+
+ void ToggleBackgroundColor( const Color& _rGBColor );
+ void SetInteractive( sal_Bool _bInteractive );
+
+ void SetClickHdl( const Link& rLink );
+ const Link& GetClickHdl() const;
+ void SetZOrder( RoadmapItem* pRefRoadmapHyperLabel, sal_uInt16 nFlags );
+ void Enable( sal_Bool bEnable = sal_True);
+ sal_Bool IsEnabled() const;
+ void GrabFocus();
+
+ bool Contains( const Window* _pWindow ) const;
+
+ HyperLabel* GetDescriptionHyperLabel() const { return mpDescription; }
+
+ private:
+ void ImplUpdateIndex( const ItemIndex _nIndex );
+ void ImplUpdatePosSize();
+ };
+
+ //=====================================================================
+ //= RoadmapImpl
+ //=====================================================================
+ class RoadmapImpl : public RoadmapTypes
+ {
+ protected:
+ const ORoadmap& m_rAntiImpl;
+ Link m_aSelectHdl;
+ BitmapEx m_aPicture;
+ HL_Vector m_aRoadmapSteps;
+ ItemId m_iCurItemID;
+ sal_Bool m_bInteractive;
+ sal_Bool m_bComplete;
+ Size m_aItemSizePixel;
+
+ public:
+ RoadmapImpl( const ORoadmap& _rAntiImpl )
+ :m_rAntiImpl( _rAntiImpl )
+ ,m_iCurItemID( -1 )
+ ,m_bInteractive( sal_True )
+ ,m_bComplete( sal_True )
+ {
+ }
+
+ RoadmapItem* InCompleteHyperLabel;
+
+ void addHyperLabel( RoadmapItem* _rRoadmapStep ) { m_aRoadmapSteps.push_back(_rRoadmapStep); }
+
+ HL_Vector& getHyperLabels() { return m_aRoadmapSteps; }
+ const HL_Vector& getHyperLabels() const { return m_aRoadmapSteps; }
+
+ void insertHyperLabel( ItemIndex _Index, RoadmapItem* _rRoadmapStep ) { m_aRoadmapSteps.insert( m_aRoadmapSteps.begin() + _Index, _rRoadmapStep ); }
+
+ ItemIndex getItemCount() const { return m_aRoadmapSteps.size();}
+
+ void setCurItemID( ItemId i ) {m_iCurItemID = i; }
+ ItemId getCurItemID() const { return m_iCurItemID; }
+
+ void setInteractive(const sal_Bool _bInteractive) {m_bInteractive = _bInteractive; }
+ sal_Bool isInteractive() const { return m_bInteractive; };
+
+ void setComplete(const sal_Bool _bComplete) {m_bComplete = _bComplete; }
+ sal_Bool isComplete() const { return m_bComplete; };
+
+ void setPicture( const BitmapEx& _rPic ) { m_aPicture = _rPic; }
+ const BitmapEx& getPicture( ) const { return m_aPicture; }
+
+ void setSelectHdl( const Link& _rHdl ) { m_aSelectHdl = _rHdl; }
+ const Link& getSelectHdl( ) const { return m_aSelectHdl; }
+
+ void initItemSize();
+ const Size& getItemSize() const { return m_aItemSizePixel; }
+
+ void removeHyperLabel( ItemIndex _Index )
+ {
+ if ( ( _Index > -1 ) && ( _Index < getItemCount() ) )
+ {
+ delete m_aRoadmapSteps[_Index];
+ m_aRoadmapSteps.erase( m_aRoadmapSteps.begin() + _Index);
+ }
+ }
+ };
+
+
+ //=====================================================================
+ //= Roadmap
+ //=====================================================================
+ //---------------------------------------------------------------------
+ void RoadmapImpl::initItemSize()
+ {
+ Size aLabelSize( m_rAntiImpl.GetOutputSizePixel() );
+ aLabelSize.Height() = m_rAntiImpl.LogicToPixel( Size( 0, LABELBASEMAPHEIGHT ), MAP_APPFONT ).Height();
+ aLabelSize.Width() -= m_rAntiImpl.LogicToPixel( Size( 2 * ROADMAP_INDENT_X, 0 ), MAP_APPFONT ).Width();
+ m_aItemSizePixel = aLabelSize;
+ }
+
+ //=====================================================================
+ //= Roadmap
+ //=====================================================================
+ //---------------------------------------------------------------------
+ ORoadmap::ORoadmap( Window* _pParent, const ResId& _rId )
+ :Control( _pParent, _rId )
+ ,m_pImpl( new RoadmapImpl( *this ) )
+ {
+ implInit();
+ }
+
+ //---------------------------------------------------------------------
+ ORoadmap::ORoadmap( Window* _pParent, WinBits _nWinStyle )
+ :Control( _pParent, _nWinStyle )
+ ,m_pImpl( new RoadmapImpl( *this ) )
+
+ {
+ implInit();
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::implInit()
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Color aTextColor = rStyleSettings.GetFieldTextColor();
+ Font aFont = GetFont( );
+ aFont.SetColor( aTextColor );
+ aFont.SetWeight( WEIGHT_BOLD );
+ aFont.SetUnderline( UNDERLINE_SINGLE );
+ SetFont( aFont );
+ SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
+ m_pImpl->InCompleteHyperLabel = NULL;
+ m_pImpl->setCurItemID(-1 );
+ m_pImpl->setComplete( sal_True );
+
+ // Roadmap control should be reachable as one unit with a Tab key
+ // the next Tab key should spring out of the control.
+ // To reach it the control itself should get focus and set it
+ // on entries. The entries themself should not be reachable with
+ // the Tab key directly. So each entry should have WB_NOTABSTOP.
+ //
+ // In other words the creator should create the control with the following
+ // flags:
+ // SetStyle( ( GetStyle() | WB_TABSTOP ) & ~WB_DIALOGCONTROL );
+
+// TODO: if somebody sets a new font from outside (OutputDevice::SetFont), we would have to react
+// on this with calculating a new bold font.
+// Unfortunately, the OutputDevice does not offer a notify mechanism for a changed font.
+// So settings the font from outside is simply a forbidded scenario at the moment
+ EnableMapMode( sal_False );
+ }
+
+ //---------------------------------------------------------------------
+ ORoadmap::~ORoadmap( )
+ {
+ HL_Vector aItemsCopy = m_pImpl->getHyperLabels();
+ m_pImpl->getHyperLabels().clear();
+ for ( HL_Vector::iterator i = aItemsCopy.begin(); i< aItemsCopy.end(); ++i )
+ {
+ delete *i;
+ }
+ if ( ! m_pImpl->isComplete() )
+ delete m_pImpl->InCompleteHyperLabel;
+ delete m_pImpl;
+ m_pImpl = NULL;
+ }
+
+
+ RoadmapTypes::ItemId ORoadmap::GetCurrentRoadmapItemID() const
+ {
+ return m_pImpl->getCurItemID();
+ }
+
+
+ RoadmapItem* ORoadmap::GetPreviousHyperLabel( ItemIndex _Index)
+ {
+ RoadmapItem* pOldItem = NULL;
+ if ( _Index > 0 )
+ pOldItem = m_pImpl->getHyperLabels().at( _Index - 1 );
+ return pOldItem;
+ }
+
+
+ //---------------------------------------------------------------------
+
+ RoadmapItem* ORoadmap::InsertHyperLabel( ItemIndex _Index, const ::rtl::OUString& _sLabel, ItemId _RMID, sal_Bool _bEnabled)
+ {
+ if ( m_pImpl->getItemCount() == 0 )
+ m_pImpl->initItemSize();
+
+ RoadmapItem* pItem = NULL;
+ RoadmapItem* pOldItem = GetPreviousHyperLabel( _Index );
+
+ pItem = new RoadmapItem( *this, m_pImpl->getItemSize() );
+ if ( _RMID != RMINCOMPLETE )
+ {
+ pItem->SetInteractive( m_pImpl->isInteractive() );
+ m_pImpl->insertHyperLabel( _Index, pItem );
+ }
+ else
+ {
+ pItem->SetInteractive( sal_False );
+ }
+ pItem->SetPosition( pOldItem );
+ pItem->Update( _Index, _sLabel );
+ pItem->SetClickHdl(LINK( this, ORoadmap, ImplClickHdl ) );
+ pItem->SetID( _RMID );
+ pItem->SetIndex( _Index );
+ if (!_bEnabled)
+ pItem->Enable( _bEnabled );
+ return pItem;
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::SetRoadmapBitmap( const BitmapEx& _rBmp, sal_Bool _bInvalidate )
+ {
+ m_pImpl->setPicture( _rBmp );
+ if ( _bInvalidate )
+ Invalidate( );
+ }
+
+ //---------------------------------------------------------------------
+ const BitmapEx& ORoadmap::GetRoadmapBitmap( ) const
+ {
+ return m_pImpl->getPicture( );
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::SetRoadmapInteractive( sal_Bool _bInteractive )
+ {
+ m_pImpl->setInteractive( _bInteractive );
+
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ for ( HL_Vector::const_iterator i = rItems.begin();
+ i < rItems.end();
+ ++i
+ )
+ {
+ (*i)->SetInteractive( _bInteractive );
+ }
+ }
+
+ //---------------------------------------------------------------------
+ sal_Bool ORoadmap::IsRoadmapInteractive()
+ {
+ return m_pImpl->isInteractive();
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::SetRoadmapComplete( sal_Bool _bComplete )
+ {
+ sal_Bool bWasComplete = m_pImpl->isComplete();
+ m_pImpl->setComplete( _bComplete );
+ if ( _bComplete )
+ {
+ if ( m_pImpl->InCompleteHyperLabel != NULL)
+ {
+ delete m_pImpl->InCompleteHyperLabel;
+ m_pImpl->InCompleteHyperLabel = NULL;
+ }
+ }
+ else if ( bWasComplete )
+ m_pImpl->InCompleteHyperLabel = InsertHyperLabel( m_pImpl->getItemCount(), ::String::CreateFromAscii( "..." ), RMINCOMPLETE );
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::UpdatefollowingHyperLabels( ItemIndex _nIndex )
+ {
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ if ( _nIndex < (ItemIndex)rItems.size() )
+ {
+ RoadmapItem* pItem = NULL;
+ for ( HL_Vector::const_iterator i = rItems.begin() + _nIndex;
+ i< rItems.end();
+ ++i, ++_nIndex
+ )
+ {
+ pItem = *i;
+
+ pItem->SetIndex( _nIndex );
+ pItem->SetPosition( GetPreviousHyperLabel( _nIndex ) );
+ }
+ }
+ if ( ! m_pImpl->isComplete() )
+ {
+ RoadmapItem* pOldItem = GetPreviousHyperLabel( m_pImpl->getItemCount() );
+ m_pImpl->InCompleteHyperLabel->SetPosition( pOldItem );
+ m_pImpl->InCompleteHyperLabel->Update( m_pImpl->getItemCount(), ::String::CreateFromAscii("...") );
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::ReplaceRoadmapItem( ItemIndex _Index, const ::rtl::OUString& _RoadmapItem, ItemId _RMID, sal_Bool _bEnabled )
+ {
+ RoadmapItem* pItem = GetByIndex( _Index);
+ if ( pItem != NULL )
+ {
+ pItem->Update( _Index, _RoadmapItem );
+ pItem->SetID( _RMID );
+ pItem->Enable( _bEnabled );
+ }
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapTypes::ItemIndex ORoadmap::GetItemCount() const
+ {
+ return m_pImpl->getItemCount();
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapTypes::ItemId ORoadmap::GetItemID( ItemIndex _nIndex ) const
+ {
+ const RoadmapItem* pHyperLabel = GetByIndex( _nIndex );
+ if ( pHyperLabel )
+ return pHyperLabel->GetID();
+ return -1;
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapTypes::ItemIndex ORoadmap::GetItemIndex( ItemId _nID ) const
+ {
+ ItemId nLocID = 0;
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ for ( HL_Vector::const_iterator i = rItems.begin();
+ i < rItems.end();
+ ++i
+ )
+ {
+ nLocID = (*i)->GetID();
+ if ( nLocID == _nID )
+ return ItemIndex( i - rItems.begin() );
+ }
+ return -1;
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::InsertRoadmapItem( ItemIndex _Index, const ::rtl::OUString& _RoadmapItem, ItemId _nUniqueId, sal_Bool _bEnabled )
+ {
+ InsertHyperLabel( _Index, _RoadmapItem, _nUniqueId, _bEnabled );
+ // Todo: YPos is superfluous, if items are always appended
+ UpdatefollowingHyperLabels( _Index + 1 );
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::DeleteRoadmapItem( ItemIndex _Index )
+ {
+ if ( m_pImpl->getItemCount() > 0 && ( _Index > -1) && ( _Index < m_pImpl->getItemCount() ) )
+ {
+ m_pImpl->removeHyperLabel( _Index );
+ UpdatefollowingHyperLabels( _Index );
+ }
+ }
+
+ //---------------------------------------------------------------------
+ sal_Bool ORoadmap::IsRoadmapComplete( ) const
+ {
+ return m_pImpl->isComplete();
+ }
+
+ //---------------------------------------------------------------------
+ sal_Bool ORoadmap::IsRoadmapItemEnabled( ItemId _nItemId, ItemIndex _nStartIndex ) const
+ {
+ const RoadmapItem* _pLabelItem = GetByID( _nItemId, _nStartIndex );
+ return _pLabelItem ? _pLabelItem->IsEnabled() : sal_False;
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::EnableRoadmapItem( ItemId _nItemId, sal_Bool _bEnable, ItemIndex _nStartIndex )
+ {
+ RoadmapItem* pItem = GetByID( _nItemId, _nStartIndex );
+ if ( pItem != NULL )
+ pItem->Enable( _bEnable );
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::ChangeRoadmapItemLabel( ItemId _nID, const ::rtl::OUString& _sLabel, ItemIndex _nStartIndex )
+ {
+ RoadmapItem* pItem = GetByID( _nID, _nStartIndex );
+ if ( pItem != NULL )
+ {
+ pItem->Update( pItem->GetIndex(), _sLabel );
+
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ for ( HL_Vector::const_iterator i = rItems.begin() + _nStartIndex;
+ i < rItems.end();
+ ++i
+ )
+ {
+ (*i)->SetPosition( GetPreviousHyperLabel( i - rItems.begin() ) );
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------
+
+ ::rtl::OUString ORoadmap::GetRoadmapItemLabel( ItemId _nID, ItemIndex _nStartIndex )
+ {
+ RoadmapItem* pItem = GetByID( _nID, _nStartIndex );
+ if ( pItem != NULL )
+ return pItem->GetLabel();
+ else
+ return ::rtl::OUString();
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::ChangeRoadmapItemID( ItemId _nID, ItemId _NewID, ItemIndex _nStartIndex )
+ {
+ RoadmapItem* pItem = GetByID( _nID, _nStartIndex );
+ if ( pItem != NULL )
+ pItem->SetID( _NewID );
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapItem* ORoadmap::GetByID( ItemId _nID, ItemIndex _nStartIndex)
+ {
+ ItemId nLocID = 0;
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ for ( HL_Vector::const_iterator i = rItems.begin() + _nStartIndex;
+ i < rItems.end();
+ ++i
+ )
+ {
+ nLocID = (*i)->GetID();
+ if ( nLocID == _nID )
+ return *i;
+ }
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------
+ const RoadmapItem* ORoadmap::GetByID( ItemId _nID, ItemIndex _nStartIndex ) const
+ {
+ return const_cast< ORoadmap* >( this )->GetByID( _nID, _nStartIndex );
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapItem* ORoadmap::GetByIndex( ItemIndex _nItemIndex)
+ {
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ if ( ( _nItemIndex > -1 ) && ( _nItemIndex < (ItemIndex)rItems.size() ) )
+ {
+ return rItems.at( _nItemIndex );
+ }
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------
+ const RoadmapItem* ORoadmap::GetByIndex( ItemIndex _nItemIndex ) const
+ {
+ return const_cast< ORoadmap* >( this )->GetByIndex( _nItemIndex );
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapTypes::ItemId ORoadmap::GetNextAvailableItemId( ItemIndex _nNewIndex )
+ {
+ RoadmapItem* pItem = NULL;
+
+ ItemIndex searchIndex = ++_nNewIndex;
+ while ( searchIndex < m_pImpl->getItemCount() )
+ {
+ pItem = GetByIndex( searchIndex );
+ if ( pItem->IsEnabled() )
+ return pItem->GetID( );
+
+ ++searchIndex;
+ }
+ return -1;
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapTypes::ItemId ORoadmap::GetPreviousAvailableItemId( ItemIndex _nNewIndex )
+ {
+ RoadmapItem* pItem = NULL;
+ ItemIndex searchIndex = --_nNewIndex;
+ while ( searchIndex > -1 )
+ {
+ pItem = GetByIndex( searchIndex );
+ if ( pItem->IsEnabled() )
+ return pItem->GetID( );
+
+ searchIndex--;
+ }
+ return -1;
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::DeselectOldRoadmapItems()
+ {
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ for ( HL_Vector::const_iterator i = rItems.begin();
+ i < rItems.end();
+ ++i
+ )
+ {
+ (*i)->ToggleBackgroundColor( COL_TRANSPARENT );
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::SetItemSelectHdl( const Link& _rHdl )
+ {
+ m_pImpl->setSelectHdl( _rHdl );
+ }
+
+ //---------------------------------------------------------------------
+ Link ORoadmap::GetItemSelectHdl( ) const
+ {
+ return m_pImpl->getSelectHdl();
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::Select()
+ {
+ GetItemSelectHdl().Call( this );
+ CallEventListeners( VCLEVENT_ROADMAP_ITEMSELECTED );
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::GetFocus()
+ {
+ RoadmapItem* pCurHyperLabel = GetByID( GetCurrentRoadmapItemID() );
+ if ( pCurHyperLabel != NULL )
+ pCurHyperLabel->GrabFocus();
+ }
+
+ //---------------------------------------------------------------------
+ sal_Bool ORoadmap::SelectRoadmapItemByID( ItemId _nNewID )
+ {
+ DeselectOldRoadmapItems();
+ RoadmapItem* pItem = GetByID( _nNewID );
+ if ( pItem != NULL )
+ {
+ if ( pItem->IsEnabled() )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ pItem->ToggleBackgroundColor( rStyleSettings.GetHighlightColor() ); //HighlightColor
+
+ pItem->GrabFocus();
+ m_pImpl->setCurItemID(_nNewID);
+
+ Select();
+ return sal_True;
+ }
+ }
+ return sal_False;
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::Paint( const Rectangle& _rRect )
+ {
+ Control::Paint( _rRect );
+
+
+ // draw the bitmap
+ if ( !!m_pImpl->getPicture() )
+ {
+ Size aBitmapSize = m_pImpl->getPicture().GetSizePixel();
+ Size aMySize = GetOutputSizePixel();
+
+ Point aBitmapPos( aMySize.Width() - aBitmapSize.Width(), aMySize.Height() - aBitmapSize.Height() );
+
+ // draw it
+ DrawBitmapEx( aBitmapPos, m_pImpl->getPicture() );
+ }
+
+ //.................................................................
+ // draw the headline
+ DrawHeadline();
+ }
+
+ //---------------------------------------------------------------------
+ void ORoadmap::DrawHeadline()
+ {
+ Point aTextPos = LogicToPixel( Point( ROADMAP_INDENT_X, 8 ), MAP_APPFONT );
+
+ Size aOutputSize( GetOutputSizePixel() );
+
+ // draw it
+ DrawText( Rectangle( aTextPos, aOutputSize ), GetText(), TEXT_DRAW_LEFT | TEXT_DRAW_TOP | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
+ DrawTextLine( aTextPos, aOutputSize.Width(), STRIKEOUT_NONE, UNDERLINE_SINGLE, UNDERLINE_NONE, sal_False );
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetLineColor( rStyleSettings.GetFieldTextColor());
+ SetTextColor(rStyleSettings.GetFieldTextColor());
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapItem* ORoadmap::GetByPointer(Window* pWindow)
+ {
+ const HL_Vector& rItems = m_pImpl->getHyperLabels();
+ for ( HL_Vector::const_iterator i = rItems.begin();
+ i < rItems.end();
+ ++i
+ )
+ {
+ if ( (*i)->Contains( pWindow ) )
+ return *i;
+ }
+ return NULL;
+ }
+
+ //---------------------------------------------------------------------
+ long ORoadmap::PreNotify( NotifyEvent& _rNEvt )
+ {
+ // capture KeyEvents for taskpane cycling
+ if ( _rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ Window* pWindow = _rNEvt.GetWindow();
+ RoadmapItem* pItem = GetByPointer( pWindow );
+ if ( pItem != NULL )
+ {
+ sal_Int16 nKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
+ switch( nKeyCode )
+ {
+ case KEY_UP:
+ { // Note: Performancewise this is not optimal, because we search for an ID in the labels
+ // and afterwards we search again for a label with the appropriate ID ->
+ // unnecessarily we search twice!!!
+ ItemId nPrevItemID = GetPreviousAvailableItemId( pItem->GetIndex() );
+ if ( nPrevItemID != -1 )
+ return SelectRoadmapItemByID( nPrevItemID );
+ }
+ break;
+ case KEY_DOWN:
+ {
+ ItemId nNextItemID = GetNextAvailableItemId( pItem->GetIndex() );
+ if ( nNextItemID != -1 )
+ return SelectRoadmapItemByID( nNextItemID );
+ }
+ break;
+ case KEY_SPACE:
+ return SelectRoadmapItemByID( pItem->GetID() );
+ }
+ }
+ }
+ return Window::PreNotify( _rNEvt );
+ }
+
+ //---------------------------------------------------------------------
+ IMPL_LINK(ORoadmap, ImplClickHdl, HyperLabel*, _CurHyperLabel)
+ {
+ return SelectRoadmapItemByID( _CurHyperLabel->GetID() );
+ }
+
+
+
+ //---------------------------------------------------------------------
+ void ORoadmap::DataChanged( const DataChangedEvent& rDCEvt )
+ {
+ if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS ) ||
+ ( rDCEvt.GetType() == DATACHANGED_DISPLAY )) &&
+ ( rDCEvt.GetFlags() & SETTINGS_STYLE ))
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetBackground( Wallpaper( rStyleSettings.GetFieldColor() ) );
+ Color aTextColor = rStyleSettings.GetFieldTextColor();
+ Font aFont = GetFont();
+ aFont.SetColor( aTextColor );
+ SetFont( aFont );
+ RoadmapTypes::ItemId curItemID = GetCurrentRoadmapItemID();
+ RoadmapItem* pLabelItem = GetByID( curItemID );
+ pLabelItem->ToggleBackgroundColor(rStyleSettings.GetHighlightColor());
+ Invalidate();
+ }
+ }
+
+
+ //---------------------------------------------------------------------
+ RoadmapItem::RoadmapItem( ORoadmap& _rParent, const Size& _rItemPlayground )
+ :m_aItemPlayground( _rItemPlayground )
+ {
+ mpID = new IDLabel( &_rParent, WB_WORDBREAK );
+ mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetFieldTextColor( ) );
+ mpID->Show();
+ mpDescription = new HyperLabel( &_rParent, WB_NOTABSTOP | WB_WORDBREAK );
+ mpDescription->Show();
+ }
+
+ //---------------------------------------------------------------------
+ bool RoadmapItem::Contains( const Window* _pWindow ) const
+ {
+ return ( mpID == _pWindow ) || ( mpDescription == _pWindow );
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::GrabFocus()
+ {
+ if ( mpDescription )
+ mpDescription->GrabFocus();
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::SetInteractive( sal_Bool _bInteractive )
+ {
+ if ( mpDescription )
+ mpDescription->SetInteractive(_bInteractive);
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::SetID( sal_Int16 _ID )
+ {
+ if ( mpDescription )
+ mpDescription->SetID(_ID);
+ }
+
+ //---------------------------------------------------------------------
+ sal_Int16 RoadmapItem::GetID() const
+ {
+ return mpDescription ? mpDescription->GetID() : sal_Int16(-1);
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::ImplUpdateIndex( const ItemIndex _nIndex )
+ {
+ if ( mpDescription )
+ mpDescription->SetIndex( _nIndex );
+
+ if ( mpID )
+ {
+ ::rtl::OUString aIDText = ::rtl::OUString::valueOf( (sal_Int32)( _nIndex + 1 ) ) + ::rtl::OUString::createFromAscii( "." );
+ mpID->SetText( aIDText );
+ }
+
+ // update the geometry of both controls
+ ImplUpdatePosSize();
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::SetIndex( ItemIndex _Index )
+ {
+ ImplUpdateIndex( _Index );
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapTypes::ItemIndex RoadmapItem::GetIndex() const
+ {
+ return mpDescription ? mpDescription->GetIndex() : ItemIndex(-1);
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::SetLabel( const ::rtl::OUString& _rText )
+ {
+ if ( mpDescription )
+ mpDescription->SetText(_rText);
+ }
+
+ //---------------------------------------------------------------------
+ ::rtl::OUString RoadmapItem::GetLabel( )
+ {
+ return mpDescription ? mpDescription->GetText() : String();
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::SetPosition( RoadmapItem* _pOldItem )
+ {
+ Point aIDPos;
+ if ( _pOldItem == NULL )
+ {
+ aIDPos = mpID->LogicToPixel( Point( ROADMAP_INDENT_X, ROADMAP_INDENT_Y ), MAP_APPFONT );
+ }
+ else
+ {
+ Size aOldSize = _pOldItem->GetDescriptionHyperLabel()->GetSizePixel();
+
+ aIDPos = _pOldItem->mpID->GetPosPixel();
+ aIDPos.Y() += aOldSize.Height();
+ aIDPos.Y() += mpID->GetParent()->LogicToPixel( Size( 0, ROADMAP_ITEM_DISTANCE_Y ) ).Height();
+ }
+ mpID->SetPosPixel( aIDPos );
+
+ sal_Int32 nDescPos = aIDPos.X() + mpID->GetSizePixel().Width();
+ mpDescription->SetPosPixel( Point( nDescPos, aIDPos.Y() ) );
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::SetZOrder( RoadmapItem* pRefRoadmapHyperLabel, sal_uInt16 nFlags )
+ {
+ if (pRefRoadmapHyperLabel == NULL)
+ mpDescription->SetZOrder( NULL, nFlags); //WINDOW_ZORDER_FIRST );
+ else
+ mpDescription->SetZOrder( pRefRoadmapHyperLabel->mpDescription, nFlags); //, WINDOW_ZORDER_BEHIND );
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::Enable( sal_Bool _bEnable)
+ {
+ mpID->Enable(_bEnable);
+ mpDescription->Enable(_bEnable);
+ }
+
+ //---------------------------------------------------------------------
+ sal_Bool RoadmapItem::IsEnabled() const
+ {
+ return mpID->IsEnabled();
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::ToggleBackgroundColor( const Color& _rGBColor )
+ {
+ if (_rGBColor == COL_TRANSPARENT)
+ {
+ mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetFieldTextColor( ) );
+ mpID->SetControlBackground( COL_TRANSPARENT );
+ }
+ else
+ {
+ mpID->SetControlBackground( mpID->GetSettings().GetStyleSettings().GetHighlightColor() );
+ mpID->SetTextColor( mpID->GetSettings().GetStyleSettings().GetHighlightTextColor( ) );
+ }
+ mpDescription->ToggleBackgroundColor(_rGBColor);
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::ImplUpdatePosSize()
+ {
+ // calculate widths
+ long nIDWidth = mpID->GetTextWidth( mpID->GetText() );
+ long nMaxIDWidth = mpID->GetTextWidth( ::rtl::OUString::createFromAscii( "100." ) );
+ nIDWidth = ::std::min( nIDWidth, nMaxIDWidth );
+
+ // check how many space the description would need
+ Size aDescriptionSize = mpDescription->CalcMinimumSize( m_aItemPlayground.Width() - nIDWidth );
+
+ // position and size both controls
+ Size aIDSize( nIDWidth, aDescriptionSize.Height() );
+ mpID->SetSizePixel( aIDSize );
+
+ Point aIDPos = mpID->GetPosPixel();
+ mpDescription->SetPosPixel( Point( aIDPos.X() + nIDWidth, aIDPos.Y() ) );
+ mpDescription->SetSizePixel( aDescriptionSize );
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::Update( ItemIndex _RMIndex, const ::rtl::OUString& _rText )
+ {
+ // update description label
+ mpDescription->SetLabel( _rText );
+
+ // update the index in both controls, which triggers updating the geometry of both
+ ImplUpdateIndex( _RMIndex );
+ }
+
+ //---------------------------------------------------------------------
+ RoadmapItem::~RoadmapItem( )
+ {
+ {
+ ::std::auto_ptr<Control> aTemp(mpID);
+ mpID = NULL;
+ }
+ {
+ ::std::auto_ptr<Control> aTemp(mpDescription);
+ mpDescription = NULL;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::SetClickHdl( const Link& rLink )
+ {
+ if ( mpDescription )
+ mpDescription->SetClickHdl( rLink);
+ }
+
+ //---------------------------------------------------------------------
+ const Link& RoadmapItem::GetClickHdl( ) const
+ {
+ return mpDescription->GetClickHdl();
+ }
+
+ //---------------------------------------------------------------------
+ IDLabel::IDLabel( Window* _pParent, WinBits _nWinStyle )
+ :FixedText( _pParent, _nWinStyle )
+ {
+
+ }
+
+ //---------------------------------------------------------------------
+ IDLabel::~IDLabel( )
+ {
+ }
+
+ //---------------------------------------------------------------------
+ void IDLabel::DataChanged( const DataChangedEvent& rDCEvt )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ FixedText::DataChanged( rDCEvt );
+ if ((( rDCEvt.GetType() == DATACHANGED_SETTINGS ) ||
+ ( rDCEvt.GetType() == DATACHANGED_DISPLAY )) &&
+ ( rDCEvt.GetFlags() & SETTINGS_STYLE ))
+ {
+ const Color& rGBColor = GetControlBackground();
+ if (rGBColor == COL_TRANSPARENT)
+ SetTextColor( rStyleSettings.GetFieldTextColor( ) );
+ else
+ {
+ SetControlBackground(rStyleSettings.GetHighlightColor());
+ SetTextColor( rStyleSettings.GetHighlightTextColor( ) );
+ }
+ Invalidate();
+ }
+ }
+
+
+
+
+//.........................................................................
+} // namespace svt
+//.........................................................................
diff --git a/svtools/source/control/ruler.cxx b/svtools/source/control/ruler.cxx
new file mode 100755
index 000000000000..1c5b95460232
--- /dev/null
+++ b/svtools/source/control/ruler.cxx
@@ -0,0 +1,3185 @@
+/*************************************************************************
+ *
+ * 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 <string.h>
+#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/poly.hxx>
+#include <vcl/i18nhelp.hxx>
+
+#define _SV_RULER_CXX
+#include <svtools/ruler.hxx>
+
+// =======================================================================
+
+#define RULER_OFF 3
+#define RULER_TEXTOFF 2
+#define RULER_RESIZE_OFF 4
+#define RULER_LINE_WIDTH 7
+#define RULER_MIN_SIZE 3
+
+#define RULER_TICK1_WIDTH 1
+#define RULER_TICK2_WIDTH 3
+#define RULER_TICK3_WIDTH 5
+
+#define RULER_VAR_SIZE 8
+
+#define RULER_TAB_HEIGHT2 2
+#define RULER_TAB_WIDTH2 2
+#define RULER_TAB_CWIDTH 8
+#define RULER_TAB_CWIDTH2 4
+#define RULER_TAB_CWIDTH3 4
+#define RULER_TAB_CWIDTH4 2
+#define RULER_TAB_DHEIGHT 4
+#define RULER_TAB_DHEIGHT2 1
+#define RULER_TAB_DWIDTH 5
+#define RULER_TAB_DWIDTH2 3
+#define RULER_TAB_DWIDTH3 3
+#define RULER_TAB_DWIDTH4 1
+
+#define RULER_UPDATE_LINES 0x01
+#define RULER_UPDATE_DRAW 0x02
+
+#define RULER_CLIP 150
+
+// =======================================================================
+
+#define RULER_UNIT_MM 0
+#define RULER_UNIT_CM 1
+#define RULER_UNIT_M 2
+#define RULER_UNIT_KM 3
+#define RULER_UNIT_INCH 4
+#define RULER_UNIT_FOOT 5
+#define RULER_UNIT_MILE 6
+#define RULER_UNIT_POINT 7
+#define RULER_UNIT_PICA 8
+#define RULER_UNIT_COUNT 9
+
+// -----------------
+// - ImplRulerData -
+// -----------------
+class ImplRulerData
+{
+ friend class Ruler;
+
+private:
+ RulerLine* pLines;
+ RulerArrow* pArrows;
+ RulerBorder* pBorders;
+ RulerIndent* pIndents;
+ RulerTab* pTabs;
+ long nNullVirOff;
+ long nRulVirOff;
+ long nRulWidth;
+ long nPageOff;
+ long nPageWidth;
+ long nNullOff;
+ long nMargin1;
+ long nMargin2;
+ sal_uInt16 nLines;
+ sal_uInt16 nArrows;
+ sal_uInt16 nBorders;
+ sal_uInt16 nIndents;
+ sal_uInt16 nTabs;
+ sal_uInt16 nMargin1Style;
+ sal_uInt16 nMargin2Style;
+ sal_Bool bAutoPageWidth;
+ sal_Bool bTextRTL;
+
+#ifdef _SV_RULER_CXX
+public:
+ ImplRulerData();
+ ~ImplRulerData();
+ ImplRulerData& operator=( const ImplRulerData& rData );
+#endif
+};
+
+
+struct ImplRulerUnitData
+{
+ MapUnit eMapUnit; // MAP_UNIT zum Umrechnen
+ long nTickUnit; // Teiler fuer Einheit
+ long nTick1; // Schrittweite
+ long nTick2; // Tick fuer halbe Werte
+ long nTick3; // Tick fuer Zahlenausgabe
+ long n100THMM; // Teiler fuer Einheit
+ sal_uInt16 nUnitDigits; // Anzahl Nachkommastellen
+ sal_Char aUnitStr[8]; // Einheiten-String
+};
+
+static ImplRulerUnitData aImplRulerUnitTab[RULER_UNIT_COUNT] =
+{
+{ MAP_100TH_MM, 100, 25, 50, 100, 100, 3, " mm" }, // MM
+{ MAP_100TH_MM, 1000, 250, 500, 1000, 1000, 3, " cm" }, // CM
+{ MAP_MM, 1000, 250, 500, 1000, 10000, 4, " m" }, // M
+{ MAP_CM, 100000, 25000, 50000, 100000, 100000, 6, " km" }, // KM
+{ MAP_100TH_INCH, 100, 10, 50, 100, 2540, 3, "\"" }, // INCH
+{ MAP_100TH_INCH, 1200, 120, 600, 1200, 30480, 3, "'" }, // FOOT
+{ MAP_10TH_INCH, 633600, 63360, 316800, 633600, 1609344, 4, " miles" }, // MILE
+{ MAP_POINT, 1, 12, 12, 36, 353, 2, " pt" }, // POINT
+{ MAP_100TH_MM, 423, 423, 423, 846, 423, 3, " pi" } // PICA
+};
+
+// =======================================================================
+
+struct ImplRulerHitTest
+{
+ long nPos;
+ RulerType eType;
+ sal_uInt16 nAryPos;
+ sal_uInt16 mnDragSize;
+ sal_Bool bSize;
+ sal_Bool bSizeBar;
+ sal_Bool bExpandTest;
+ ImplRulerHitTest() :
+ bExpandTest( sal_False ) {}
+};
+
+// =======================================================================
+
+ImplRulerData::ImplRulerData()
+{
+ memset( this, 0, sizeof( ImplRulerData ) );
+
+ // PageBreite == EditWinBreite
+ bAutoPageWidth = sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+ImplRulerData::~ImplRulerData()
+{
+ delete[] pLines;
+ delete[] pArrows;
+ delete[] pBorders;
+ delete[] pIndents;
+ delete[] pTabs;
+}
+
+// -----------------------------------------------------------------------
+
+ImplRulerData& ImplRulerData::operator=( const ImplRulerData& rData )
+{
+ delete[] pLines;
+ delete[] pArrows;
+ delete[] pBorders;
+ delete[] pIndents;
+ delete[] pTabs;
+
+ memcpy( this, &rData, sizeof( ImplRulerData ) );
+
+ if ( rData.pLines )
+ {
+ pLines = new RulerLine[nLines];
+ memcpy( pLines, rData.pLines, nLines*sizeof( RulerLine ) );
+ }
+
+ if ( rData.pArrows )
+ {
+ pArrows = new RulerArrow[nArrows];
+ memcpy( pArrows, rData.pArrows, nArrows*sizeof( RulerArrow ) );
+ }
+
+ if ( rData.pBorders )
+ {
+ pBorders = new RulerBorder[nBorders];
+ memcpy( pBorders, rData.pBorders, nBorders*sizeof( RulerBorder ) );
+ }
+
+ if ( rData.pIndents )
+ {
+ pIndents = new RulerIndent[nIndents];
+ memcpy( pIndents, rData.pIndents, nIndents*sizeof( RulerIndent ) );
+ }
+
+ if ( rData.pTabs )
+ {
+ pTabs = new RulerTab[nTabs];
+ memcpy( pTabs, rData.pTabs, nTabs*sizeof( RulerTab ) );
+ }
+
+ return *this;
+}
+
+// =======================================================================
+
+void Ruler::ImplInit( WinBits nWinBits )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ // Default WinBits setzen
+ if ( !(nWinBits & WB_VERT) )
+ {
+ nWinBits |= WB_HORZ;
+
+ // --- RTL --- no UI mirroring for horizontal rulers, because
+ // the document is also not mirrored
+ EnableRTL( sal_False );
+ }
+
+ // Variablen initialisieren
+ mnWinStyle = nWinBits; // Window-Style
+ mnBorderOff = 0; // Border-Offset
+ mnWinOff = 0; // EditWinOffset
+ mnWinWidth = 0; // EditWinWidth
+ mnWidth = 0; // Fensterbreite
+ mnHeight = 0; // Fensterhoehe
+ mnVirOff = 0; // Offset des VirtualDeice vom linke/oberen Rand
+ mnVirWidth = 0; // Breite bzw. Hoehe vom VirtualDevice
+ mnVirHeight = 0; // Hoehe bzw. Breite vom VirtualDevice
+ mnDragPos = 0; // Drag-Position (NullPunkt)
+ mnUpdateEvtId = 0; // Noch kein Update-Event verschickt
+ mnDragAryPos = 0; // Drag-Array-Index
+ mnDragSize = 0; // Wird beim Draggen die Groesse geaendert
+ mnDragScroll = 0; // Soll beim Draggen gescrollt werden
+ mnDragModifier = 0; // Modifier-Tasten beim Draggen
+ mnExtraStyle = 0; // Style des Extra-Feldes
+ mnExtraClicks = 0; // Click-Anzahl fuer Extra-Feld
+ mnExtraModifier = 0; // Modifier-Tasten beim Click im Extrafeld
+ mbCalc = sal_True; // Muessen Pagebreiten neu berechnet werden
+ mbFormat = sal_True; // Muss neu ausgegeben werden
+ mbDrag = sal_False; // Sind wir im Drag-Modus
+ mbDragDelete = sal_False; // Wird Maus beim Draggen unten rausgezogen
+ mbDragCanceled = sal_False; // Wurde Dragging abgebrochen
+ mbAutoWinWidth = sal_True; // EditWinBreite == RulerBreite
+ mbActive = sal_True; // Ist Lineal aktiv
+ mnUpdateFlags = 0; // Was soll im Update-Handler upgedatet werden
+ mpData = mpSaveData; // Wir zeigen auf die normalen Daten
+ meExtraType = RULER_EXTRA_DONTKNOW; // Was im ExtraFeld dargestellt wird
+ meDragType = RULER_TYPE_DONTKNOW; // Gibt an, was gedragt wird
+
+ // Units initialisieren
+ mnUnitIndex = RULER_UNIT_CM;
+ meUnit = FUNIT_CM;
+ maZoom = Fraction( 1, 1 );
+ meSourceUnit = MAP_100TH_MM;
+
+ // Border-Breiten berechnen
+ if ( nWinBits & WB_BORDER )
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ mnBorderWidth = 2;
+ else
+ mnBorderWidth = 1;
+ }
+ else
+ mnBorderWidth = 0;
+
+ // Einstellungen setzen
+ ImplInitSettings( sal_True, sal_True, sal_True );
+
+ // Default-Groesse setzen
+ long nDefHeight = GetTextHeight() + RULER_OFF*2 + RULER_TEXTOFF*2 + mnBorderWidth;
+ Size aDefSize;
+ if ( nWinBits & WB_HORZ )
+ aDefSize.Height() = nDefHeight;
+ else
+ aDefSize.Width() = nDefHeight;
+ SetOutputSizePixel( aDefSize );
+ SetType(WINDOW_RULER);
+}
+
+// -----------------------------------------------------------------------
+
+Ruler::Ruler( Window* pParent, WinBits nWinStyle ) :
+ Window( pParent, nWinStyle & WB_3DLOOK ),
+ maVirDev( *this ),
+ maMapMode( MAP_100TH_MM ),
+ mpSaveData(new ImplRulerData),
+ mpData(0),
+ mpDragData(new ImplRulerData)
+{
+ ImplInit( nWinStyle );
+}
+
+// -----------------------------------------------------------------------
+
+Ruler::~Ruler()
+{
+ if ( mnUpdateEvtId )
+ Application::RemoveUserEvent( mnUpdateEvtId );
+ delete mpSaveData;
+ delete mpDragData;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplVDrawLine( long nX1, long nY1, long nX2, long nY2 )
+{
+ if ( nX1 < -RULER_CLIP )
+ {
+ nX1 = -RULER_CLIP;
+ if ( nX2 < -RULER_CLIP )
+ return;
+ }
+ long nClip = mnVirWidth+RULER_CLIP;
+ if ( nX2 > nClip )
+ {
+ nX2 = nClip;
+ if ( nX1 > nClip )
+ return;
+ }
+
+ if ( mnWinStyle & WB_HORZ )
+ maVirDev.DrawLine( Point( nX1, nY1 ), Point( nX2, nY2 ) );
+ else
+ maVirDev.DrawLine( Point( nY1, nX1 ), Point( nY2, nX2 ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplVDrawRect( long nX1, long nY1, long nX2, long nY2 )
+{
+ if ( nX1 < -RULER_CLIP )
+ {
+ nX1 = -RULER_CLIP;
+ if ( nX2 < -RULER_CLIP )
+ return;
+ }
+ long nClip = mnVirWidth+RULER_CLIP;
+ if ( nX2 > nClip )
+ {
+ nX2 = nClip;
+ if ( nX1 > nClip )
+ return;
+ }
+
+ if ( mnWinStyle & WB_HORZ )
+ maVirDev.DrawRect( Rectangle( nX1, nY1, nX2, nY2 ) );
+ else
+ maVirDev.DrawRect( Rectangle( nY1, nX1, nY2, nX2 ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplVDrawText( long nX, long nY, const String& rText )
+{
+ if ( (nX > -RULER_CLIP) && (nX < mnVirWidth+RULER_CLIP) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ maVirDev.DrawText( Point( nX, nY ), rText );
+ else
+ maVirDev.DrawText( Point( nY, nX ), rText );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplInvertLines( sal_Bool bErase )
+{
+ // Positionslinien
+ if ( mpData->nLines && mbActive && !mbDrag && !mbFormat &&
+ !(mnUpdateFlags & RULER_UPDATE_LINES) )
+ {
+ long n;
+ long nNullWinOff = mpData->nNullVirOff+mnVirOff;
+ long nRulX1 = mpData->nRulVirOff+mnVirOff;
+ long nRulX2 = nRulX1+mpData->nRulWidth;
+ long nY = (RULER_OFF*2)+mnVirHeight-1;
+
+ // Rectangle berechnen
+ Rectangle aRect;
+ if ( mnWinStyle & WB_HORZ )
+ aRect.Bottom() = nY;
+ else
+ aRect.Right() = nY;
+
+ // Linien ausgeben
+ for ( sal_uInt16 i = 0; i < mpData->nLines; i++ )
+ {
+ n = mpData->pLines[i].nPos+nNullWinOff;
+ if ( (n >= nRulX1) && (n < nRulX2) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ {
+ aRect.Left() = n;
+ aRect.Right() = n;
+ }
+ else
+ {
+ aRect.Top() = n;
+ aRect.Bottom() = n;
+ }
+ if ( bErase )
+ {
+ Rectangle aTempRect = aRect;
+ if ( mnWinStyle & WB_HORZ )
+ aTempRect.Bottom() = RULER_OFF-1;
+ else
+ aTempRect.Right() = RULER_OFF-1;
+ Erase( aTempRect );
+ if ( mnWinStyle & WB_HORZ )
+ {
+ aTempRect.Bottom() = aRect.Bottom();
+ aTempRect.Top() = aTempRect.Bottom()-RULER_OFF+1;
+ }
+ else
+ {
+ aTempRect.Right() = aRect.Right();
+ aTempRect.Left() = aTempRect.Right()-RULER_OFF+1;
+ }
+ Erase( aTempRect );
+ }
+ Invert( aRect );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawTicks( long nMin, long nMax, long nStart, long nCenter )
+{
+ long n = 0;
+ long nTick = 0;
+ long nTick3 = aImplRulerUnitTab[mnUnitIndex].nTick3;
+ long nTickCount = aImplRulerUnitTab[mnUnitIndex].nTick1;
+ Size aPixSize = maVirDev.LogicToPixel( Size( nTick3, nTick3 ), maMapMode );
+ long nTickWidth;
+ long nX;
+ long nY;
+ sal_Bool bNoTicks = sal_False;
+
+ // Groessenvorberechnung
+ // Sizes calculation
+ sal_Bool bVertRight = sal_False;
+ if ( mnWinStyle & WB_HORZ )
+ nTickWidth = aPixSize.Width();
+ else
+ {
+ Font aFont = GetFont();
+ if ( mnWinStyle & WB_RIGHT_ALIGNED )
+ {
+ aFont.SetOrientation( 2700 );
+ bVertRight = sal_True;
+ }
+ else
+ aFont.SetOrientation( 900 );
+ maVirDev.SetFont( aFont );
+ nTickWidth = aPixSize.Height();
+ }
+ long nMaxWidth = maVirDev.PixelToLogic( Size( mpData->nPageWidth, 0 ), maMapMode ).Width();
+ if ( nMaxWidth < 0 )
+ nMaxWidth = -nMaxWidth;
+ nMaxWidth /= aImplRulerUnitTab[mnUnitIndex].nTickUnit;
+ UniString aNumStr( UniString::CreateFromInt32( nMaxWidth ) );
+ long nTxtWidth = GetTextWidth( aNumStr );
+
+ const long nTextOff = 4;
+ if ( nTickWidth < nTxtWidth+nTextOff )
+ {
+ // Calculate the scale of the ruler
+ long nMulti = 1;
+ long nOrgTick3 = nTick3;
+ while ( nTickWidth < nTxtWidth+nTextOff )
+ {
+ long nOldMulti = nMulti;
+ if ( !nTickWidth ) //If nTickWidth equals 0
+ nMulti *= 10;
+ else if ( nMulti < 10 )
+ nMulti++;
+ else if ( nMulti < 100 )
+ nMulti += 10;
+ else if ( nMulti < 1000 )
+ nMulti += 100;
+ else
+ nMulti += 1000;
+ // Ueberlauf, dann geben wir nichts aus, da wir bei so einem
+ // unsinnigen Massstab sowieso nichts vernuenftiges anzeigen
+ // koennen
+ if ( nMulti < nOldMulti )
+ {
+ bNoTicks = sal_True;
+ break;
+ }
+
+ nTick3 = nOrgTick3 * nMulti;
+ aPixSize = maVirDev.LogicToPixel( Size( nTick3, nTick3 ), maMapMode );
+ if ( mnWinStyle & WB_HORZ )
+ nTickWidth = aPixSize.Width();
+ else
+ nTickWidth = aPixSize.Height();
+ }
+ nTickCount = nTick3;
+ }
+ else
+ maVirDev.SetLineColor( GetSettings().GetStyleSettings().GetWindowTextColor() );
+
+ if ( !bNoTicks )
+ {
+ long nTxtWidth2;
+ long nTxtHeight2 = GetTextHeight()/2;
+ while ( ((nStart-n) >= nMin) || ((nStart+n) <= nMax) )
+ {
+ // Null-Punkt
+ if ( !nTick )
+ {
+ if ( nStart > nMin )
+ {
+ // 0 is only painted when Margin1 is not equal to zero
+ if ( (mpData->nMargin1Style & RULER_STYLE_INVISIBLE) || (mpData->nMargin1 != 0) )
+ {
+ aNumStr = (sal_Unicode)'0';
+ nTxtWidth2 = maVirDev.GetTextWidth( aNumStr )/2;
+ if ( (mnWinStyle & WB_HORZ)^mpData->bTextRTL )
+ nX = nStart-nTxtWidth2;
+ else
+ nX = nStart+nTxtWidth2;
+ long n_Y = bVertRight ? nCenter+nTxtHeight2 : nCenter-nTxtHeight2;
+ ImplVDrawText( nX, n_Y, aNumStr );
+ }
+ }
+ }
+ else
+ {
+ aPixSize = maVirDev.LogicToPixel( Size( nTick, nTick ), maMapMode );
+
+ if ( mnWinStyle & WB_HORZ )
+ n = aPixSize.Width();
+ else
+ n = aPixSize.Height();
+
+ // Tick3 - Output (Text)
+ if ( !(nTick % nTick3) )
+ {
+ aNumStr = UniString::CreateFromInt32( nTick / aImplRulerUnitTab[mnUnitIndex].nTickUnit );
+ nTxtWidth2 = GetTextWidth( aNumStr )/2;
+
+ nX = nStart+n;
+ //different orientation needs a different starting position
+ nY = bVertRight ? nCenter+nTxtHeight2 : nCenter-nTxtHeight2;
+
+ // Check if we can display full number
+ if ( nX < (nMax-nTxtWidth2) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ nX -= nTxtWidth2;
+ else
+ nX += nTxtWidth2;
+ ImplVDrawText( nX, nY, aNumStr );
+ }
+ nX = nStart-n;
+ if ( nX > (nMin+nTxtWidth2) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ nX -= nTxtWidth2;
+ else
+ nX += nTxtWidth2;
+ ImplVDrawText( nX, nY, aNumStr );
+ }
+ }
+ // Tick/Tick2 - Output (Strokes)
+ else
+ {
+ if ( !(nTick % aImplRulerUnitTab[mnUnitIndex].nTick2) )
+ nTickWidth = RULER_TICK2_WIDTH;
+ else
+ nTickWidth = RULER_TICK1_WIDTH;
+ long nT1 = nCenter-(nTickWidth/2);
+ long nT2 = nT1+nTickWidth-1;
+ long nT;
+
+ nT = nStart+n;
+ if ( nT < nMax )
+ ImplVDrawLine( nT, nT1, nT, nT2 );
+ nT = nStart-n;
+ if ( nT > nMin )
+ ImplVDrawLine( nT, nT1, nT, nT2 );
+ }
+ }
+ // #i49017# with some zoom factors the value nTick can overflow
+ if( ((sal_uLong)nTick + (sal_uLong)nTickCount) > (sal_uLong)LONG_MAX)
+ break;
+ nTick += nTickCount;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawArrows( long nCenter )
+{
+ sal_uInt16 i;
+ long n1;
+ long n2;
+ long n3;
+ long n4;
+ long nLogWidth;
+ String aStr;
+ String aStr2;
+ sal_Bool bDrawUnit;
+ long nTxtWidth;
+ long nTxtHeight2 = GetTextHeight()/2;
+
+ const vcl::I18nHelper& rI18nHelper = GetSettings().GetLocaleI18nHelper();
+
+ maVirDev.SetLineColor( GetSettings().GetStyleSettings().GetWindowTextColor() );
+ for ( i = 0; i < mpData->nArrows; i++ )
+ {
+ n1 = mpData->pArrows[i].nPos+mpData->nNullVirOff+1;
+ n2 = n1+mpData->pArrows[i].nWidth-2;
+
+ // Einheit umrechnen
+ nLogWidth = mpData->pArrows[i].nLogWidth;
+ if ( meSourceUnit == MAP_TWIP )
+ {
+ if ( nLogWidth >= 100000 )
+ nLogWidth = (nLogWidth*254)/144;
+ else
+ nLogWidth = (nLogWidth*2540)/1440;
+ }
+ if ( nLogWidth >= 1000000 )
+ nLogWidth = (nLogWidth / aImplRulerUnitTab[mnUnitIndex].n100THMM) * 1000;
+ else
+ nLogWidth = (nLogWidth*1000) / aImplRulerUnitTab[mnUnitIndex].n100THMM;
+ aStr = rI18nHelper.GetNum( nLogWidth, aImplRulerUnitTab[mnUnitIndex].nUnitDigits, sal_True, sal_False );
+
+ // Einheit an den String haengen
+ aStr2 = aStr;
+ aStr2.AppendAscii( aImplRulerUnitTab[mnUnitIndex].aUnitStr );
+
+ // Textbreite ermitteln
+ bDrawUnit = sal_True;
+ nTxtWidth = GetTextWidth( aStr2 );
+ if ( nTxtWidth < mpData->pArrows[i].nWidth-10 )
+ aStr = aStr2;
+ else
+ {
+ nTxtWidth = GetTextWidth( aStr );
+ if ( nTxtWidth > mpData->pArrows[i].nWidth-10 )
+ bDrawUnit = sal_False;
+ }
+
+ // Ist genuegen Platz fuer Einheiten-String vorhanden
+ if ( bDrawUnit )
+ {
+ n3 = n1 + ((n2-n1)/2) - 1;
+ if ( mnWinStyle & WB_HORZ )
+ n3 -= nTxtWidth/2;
+ else
+ n3 += nTxtWidth/2;
+ if ( mnWinStyle & WB_HORZ )
+ {
+ n4 = n3 + nTxtWidth + 2;
+ ImplVDrawLine( n1, nCenter, n3, nCenter );
+ ImplVDrawLine( n4, nCenter, n2, nCenter );
+ }
+ else
+ {
+ n4 = n3 - nTxtWidth - 2;
+ ImplVDrawLine( n1, nCenter, n4, nCenter );
+ ImplVDrawLine( n3, nCenter, n2, nCenter );
+ }
+ ImplVDrawText( n3, nCenter-nTxtHeight2, aStr );
+ }
+ else
+ ImplVDrawLine( n1, nCenter, n2, nCenter );
+ ImplVDrawLine( n1+1, nCenter-1, n1+1, nCenter+1 );
+ ImplVDrawLine( n1+2, nCenter-2, n1+2, nCenter+2 );
+ ImplVDrawLine( n2-1, nCenter-1, n2-1, nCenter+1 );
+ ImplVDrawLine( n2-2, nCenter-2, n2-2, nCenter+2 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawBorders( long nMin, long nMax, long nVirTop, long nVirBottom )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ long n;
+ long n1;
+ long n2;
+ long nTemp1;
+ long nTemp2;
+ sal_uInt16 i;
+
+ for ( i = 0; i < mpData->nBorders; i++ )
+ {
+ if ( mpData->pBorders[i].nStyle & RULER_STYLE_INVISIBLE )
+ continue;
+
+ n1 = mpData->pBorders[i].nPos+mpData->nNullVirOff;
+ n2 = n1+mpData->pBorders[i].nWidth;
+
+ if ( ((n1 >= nMin) && (n1 <= nMax)) || ((n2 >= nMin) && (n2 <= nMax)) )
+ {
+ if ( (n2-n1) > 3 )
+ {
+ maVirDev.SetLineColor();
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
+ else
+ maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
+ ImplVDrawRect( n1, nVirTop, n2, nVirBottom );
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
+ ImplVDrawLine( n1+1, nVirTop, n1+1, nVirBottom );
+ ImplVDrawLine( n1, nVirTop, n2, nVirTop );
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ ImplVDrawLine( n1, nVirTop, n1, nVirBottom );
+ ImplVDrawLine( n1, nVirBottom, n2, nVirBottom );
+ ImplVDrawLine( n2-1, nVirTop, n2-1, nVirBottom );
+ maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
+ ImplVDrawLine( n2, nVirTop, n2, nVirBottom );
+ }
+ else
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
+ ImplVDrawLine( n1, nVirTop, n1, nVirBottom );
+ ImplVDrawLine( n2, nVirTop, n2, nVirBottom );
+ }
+
+ if ( mpData->pBorders[i].nStyle & RULER_BORDER_VARIABLE )
+ {
+ if ( n2-n1 > RULER_VAR_SIZE+4 )
+ {
+ nTemp1 = n1 + (((n2-n1+1)-RULER_VAR_SIZE) / 2);
+ nTemp2 = nVirTop + (((nVirBottom-nVirTop+1)-RULER_VAR_SIZE) / 2);
+ long nTemp3 = nTemp1+RULER_VAR_SIZE-1;
+ long nTemp4 = nTemp2+RULER_VAR_SIZE-1;
+ long nTempY = nTemp2;
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
+ else
+ maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
+ while ( nTempY <= nTemp4 )
+ {
+ ImplVDrawLine( nTemp1, nTempY, nTemp3, nTempY );
+ nTempY += 2;
+ }
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ nTempY = nTemp2+1;
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ while ( nTempY <= nTemp4 )
+ {
+ ImplVDrawLine( nTemp1, nTempY, nTemp3, nTempY );
+ nTempY += 2;
+ }
+ }
+ }
+ }
+
+ if ( mpData->pBorders[i].nStyle & RULER_BORDER_SIZEABLE )
+ {
+ if ( n2-n1 > RULER_VAR_SIZE+10 )
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ ImplVDrawLine( n1+4, nVirTop+3, n1+4, nVirBottom-3 );
+ ImplVDrawLine( n2-5, nVirTop+3, n2-5, nVirBottom-3 );
+ maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
+ ImplVDrawLine( n1+5, nVirTop+3, n1+5, nVirBottom-3 );
+ ImplVDrawLine( n2-4, nVirTop+3, n2-4, nVirBottom-3 );
+ }
+ else
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
+ ImplVDrawLine( n1+4, nVirTop+3, n1+4, nVirBottom-3 );
+ ImplVDrawLine( n2-4, nVirTop+3, n2-4, nVirBottom-3 );
+ }
+ }
+ }
+ }
+ else
+ {
+ n = n1+((n2-n1)/2);
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ else
+ maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
+ if ( mpData->pBorders[i].nStyle & RULER_BORDER_SNAP )
+ ImplVDrawLine( n, nVirTop, n, nVirBottom );
+ else if ( mpData->pBorders[i].nStyle & RULER_BORDER_MARGIN )
+ ImplVDrawLine( n, nVirTop, n, nVirBottom );
+ else
+ {
+ ImplVDrawLine( n-1, nVirTop, n-1, nVirBottom );
+ ImplVDrawLine( n+1, nVirTop, n+1, nVirBottom );
+ maVirDev.SetLineColor();
+ maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
+ ImplVDrawRect( n, nVirTop, n, nVirBottom );
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawIndent( const Polygon& rPoly, sal_uInt16 nStyle )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Point aPos1;
+ Point aPos2;
+ sal_uInt16 nIndentStyle = nStyle & RULER_INDENT_STYLE;
+
+ if ( nStyle & RULER_STYLE_INVISIBLE )
+ return;
+
+ if ( nStyle & RULER_STYLE_DONTKNOW )
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
+ }
+ else
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
+ }
+
+ maVirDev.DrawPolygon( rPoly );
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) && !(nStyle & RULER_STYLE_DONTKNOW) )
+ {
+ if ( nIndentStyle == RULER_INDENT_BOTTOM )
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
+ aPos1 = rPoly.GetPoint( 2 );
+ aPos1.X()++;
+ aPos2 = rPoly.GetPoint( 1 );
+ aPos2.X()++;
+ maVirDev.DrawLine( aPos2, aPos1 );
+ aPos2.X()--;
+ aPos2.Y()++;
+ aPos1 = rPoly.GetPoint( 0 );
+ aPos1.Y()++;
+ maVirDev.DrawLine( aPos2, aPos1 );
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ aPos2 = rPoly.GetPoint( 4 );
+ aPos2.Y()++;
+ maVirDev.DrawLine( aPos1, aPos2 );
+ aPos2.X()--;
+ aPos1 = rPoly.GetPoint( 3 );
+ aPos1.X()--;
+ maVirDev.DrawLine( aPos2, aPos1 );
+ aPos1.Y()--;
+ aPos2 = rPoly.GetPoint( 2 );
+ aPos2.X()++;
+ aPos2.Y()--;
+ maVirDev.DrawLine( aPos2, aPos1 );
+ }
+ else
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
+ aPos1 = rPoly.GetPoint( 2 );
+ aPos1.X()++;
+ aPos1.Y()++;
+ aPos2 = rPoly.GetPoint( 3 );
+ aPos2.Y()++;
+ maVirDev.DrawLine( aPos1, aPos2 );
+ aPos2 = rPoly.GetPoint( 1 );
+ aPos2.X()++;
+ maVirDev.DrawLine( aPos1, aPos2 );
+ aPos2.X()--;
+ aPos2.Y()--;
+ aPos1 = rPoly.GetPoint( 0 );
+ aPos1.Y()--;
+ maVirDev.DrawLine( aPos2, aPos1 );
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ aPos2 = rPoly.GetPoint( 4 );
+ aPos2.Y()--;
+ maVirDev.DrawLine( aPos1, aPos2 );
+ aPos2.X()--;
+ aPos1 = rPoly.GetPoint( 3 );
+ aPos1.X()--;
+ maVirDev.DrawLine( aPos2, aPos1 );
+ }
+
+ maVirDev.SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ maVirDev.SetFillColor();
+ maVirDev.DrawPolygon( rPoly );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawIndents( long nMin, long nMax, long nVirTop, long nVirBottom )
+{
+ sal_uInt16 j;
+ long n;
+ long nIndentHeight = (mnVirHeight/2) - 1;
+ long nIndentWidth2 = nIndentHeight-3;
+ Polygon aPoly( 5 );
+
+ for ( j = 0; j < mpData->nIndents; j++ )
+ {
+ if ( mpData->pIndents[j].nStyle & RULER_STYLE_INVISIBLE )
+ continue;
+
+ sal_uInt16 nStyle = mpData->pIndents[j].nStyle;
+ sal_uInt16 nIndentStyle = nStyle & RULER_INDENT_STYLE;
+
+ n = mpData->pIndents[j].nPos+mpData->nNullVirOff;
+
+ if ( (n >= nMin) && (n <= nMax) )
+ {
+ if(nIndentStyle == RULER_INDENT_BORDER)
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ ImplVDrawLine( n, nVirTop, n, nVirBottom );
+ }
+ else if ( nIndentStyle == RULER_INDENT_BOTTOM )
+ {
+ aPoly.SetPoint( Point( n+0, nVirBottom-nIndentHeight ), 0 );
+ aPoly.SetPoint( Point( n-nIndentWidth2, nVirBottom-3 ), 1 );
+ aPoly.SetPoint( Point( n-nIndentWidth2, nVirBottom ), 2 );
+ aPoly.SetPoint( Point( n+nIndentWidth2, nVirBottom ), 3 );
+ aPoly.SetPoint( Point( n+nIndentWidth2, nVirBottom-3 ), 4 );
+ }
+ else
+ {
+ aPoly.SetPoint( Point( n+0, nVirTop+nIndentHeight ), 0 );
+ aPoly.SetPoint( Point( n-nIndentWidth2, nVirTop+3 ), 1 );
+ aPoly.SetPoint( Point( n-nIndentWidth2, nVirTop ), 2 );
+ aPoly.SetPoint( Point( n+nIndentWidth2, nVirTop ), 3 );
+ aPoly.SetPoint( Point( n+nIndentWidth2, nVirTop+3 ), 4 );
+ }
+
+ if(0 == (mnWinStyle & WB_HORZ))
+ {
+ Point aTmp;
+ for(sal_uInt16 i = 0; i < 5; i++)
+ {
+ aTmp = aPoly[i];
+ Point aSet(nVirBottom - aTmp.Y(), aTmp.X());
+ aPoly[i] = aSet;
+ }
+ }
+ if(RULER_INDENT_BORDER != nIndentStyle)
+ ImplDrawIndent( aPoly, nStyle );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplCenterTabPos( Point& rPos, sal_uInt16 nTabStyle )
+{
+ sal_Bool bRTL = 0 != (nTabStyle & RULER_TAB_RTL);
+ nTabStyle &= RULER_TAB_STYLE;
+ rPos.Y() += RULER_TAB_HEIGHT/2;
+ if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||( bRTL && nTabStyle == RULER_TAB_RIGHT))
+ rPos.X() -= RULER_TAB_WIDTH/2;
+ else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||( bRTL && nTabStyle == RULER_TAB_LEFT))
+ rPos.X() += RULER_TAB_WIDTH/2;
+}
+
+// -----------------------------------------------------------------------
+void lcl_RotateRect_Impl(Rectangle& rRect, const long nReference, sal_Bool bRightAligned)
+{
+ if(!rRect.IsEmpty())
+ {
+ Rectangle aTmp(rRect);
+ rRect.Top() = aTmp.Left();
+ rRect.Bottom() = aTmp.Right();
+ rRect.Left() = aTmp.Top();
+ rRect.Right() = aTmp.Bottom();
+ if(bRightAligned)
+ {
+ long nRef = 2 * nReference;
+ rRect.Left() = nRef - rRect.Left();
+ rRect.Right() = nRef - rRect.Right();
+ }
+ }
+}
+// -----------------------------------------------------------------------
+
+static void ImplDrawRulerTab( OutputDevice* pDevice,
+ const Point& rPos, sal_uInt16 nStyle, WinBits nWinBits )
+{
+ if ( nStyle & RULER_STYLE_INVISIBLE )
+ return;
+
+ sal_uInt16 nTabStyle = nStyle & RULER_TAB_STYLE;
+ sal_Bool bRTL = 0 != (nStyle & RULER_TAB_RTL);
+ Rectangle aRect1, aRect2, aRect3;
+ aRect3.SetEmpty();
+ if ( nTabStyle == RULER_TAB_DEFAULT )
+ {
+ aRect1.Left() = rPos.X() - RULER_TAB_DWIDTH2 + 1 ;
+ aRect1.Top() = rPos.Y() - RULER_TAB_DHEIGHT2 + 1 ;
+ aRect1.Right() = rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH ;
+ aRect1.Bottom() = rPos.Y();
+ aRect2.Left() = rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3;
+ aRect2.Top() = rPos.Y() - RULER_TAB_DHEIGHT + 1;
+ aRect2.Right() = rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3 + RULER_TAB_DWIDTH4 - 1;
+ aRect2.Bottom() = rPos.Y();
+
+ }
+ else if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||( bRTL && nTabStyle == RULER_TAB_RIGHT))
+ {
+ aRect1.Left() = rPos.X();
+ aRect1.Top() = rPos.Y() - RULER_TAB_HEIGHT2 + 1;
+ aRect1.Right() = rPos.X() + RULER_TAB_WIDTH - 1;
+ aRect1.Bottom() = rPos.Y();
+ aRect2.Left() = rPos.X();
+ aRect2.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1;
+ aRect2.Right() = rPos.X() + RULER_TAB_WIDTH2 - 1;
+ aRect2.Bottom() = rPos.Y();
+ }
+ else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||( bRTL && nTabStyle == RULER_TAB_LEFT))
+ {
+ aRect1.Left() = rPos.X() - RULER_TAB_WIDTH + 1;
+ aRect1.Top() = rPos.Y() - RULER_TAB_HEIGHT2 + 1;
+ aRect1.Right() = rPos.X();
+ aRect1.Bottom() = rPos.Y();
+ aRect2.Left() = rPos.X() - RULER_TAB_WIDTH2 + 1;
+ aRect2.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1;
+ aRect2.Right() = rPos.X();
+ aRect2.Bottom() = rPos.Y();
+ }
+ else
+ {
+ aRect1.Left() = rPos.X() - RULER_TAB_CWIDTH2 + 1;
+ aRect1.Top() = rPos.Y() - RULER_TAB_HEIGHT2 + 1;
+ aRect1.Right() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH;
+ aRect1.Bottom() = rPos.Y();
+ aRect2.Left() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3;
+ aRect2.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1;
+ aRect2.Right() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3 + RULER_TAB_CWIDTH4 - 1;
+ aRect2.Bottom() = rPos.Y();
+
+ if ( nTabStyle == RULER_TAB_DECIMAL )
+ {
+ aRect3.Left() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH - 1;
+ aRect3.Top() = rPos.Y() - RULER_TAB_HEIGHT + 1 + 1;
+ aRect3.Right() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH;
+ aRect3.Bottom()= rPos.Y() - RULER_TAB_HEIGHT + 1 + 2 ;
+ }
+ }
+ if( 0 == (nWinBits&WB_HORZ) )
+ {
+ sal_Bool bRightAligned = 0 != (nWinBits&WB_RIGHT_ALIGNED);
+ lcl_RotateRect_Impl(aRect1, rPos.Y(), bRightAligned);
+ lcl_RotateRect_Impl(aRect2, rPos.Y(), bRightAligned);
+ lcl_RotateRect_Impl(aRect3, rPos.Y(), bRightAligned);
+ }
+ pDevice->DrawRect( aRect1 );
+ pDevice->DrawRect( aRect2 );
+ if(!aRect2.IsEmpty())
+ pDevice->DrawRect( aRect3 );
+
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawTab( OutputDevice* pDevice, const Point& rPos, sal_uInt16 nStyle )
+{
+ if ( nStyle & RULER_STYLE_INVISIBLE )
+ return;
+
+ pDevice->SetLineColor();
+ if ( nStyle & RULER_STYLE_DONTKNOW )
+ pDevice->SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
+ else
+ pDevice->SetFillColor( GetSettings().GetStyleSettings().GetWindowTextColor() );
+
+ if(mpData->bTextRTL)
+ nStyle |= RULER_TAB_RTL;
+ ImplDrawRulerTab( pDevice, rPos, nStyle, GetStyle());
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawTabs( long nMin, long nMax, long nVirTop, long nVirBottom )
+{
+ for ( sal_uInt16 i = 0; i < mpData->nTabs; i++ )
+ {
+ if ( mpData->pTabs[i].nStyle & RULER_STYLE_INVISIBLE )
+ continue;
+
+ long n;
+ n = mpData->pTabs[i].nPos;
+ n += +mpData->nNullVirOff;
+ long nTopBottom = GetStyle() & WB_RIGHT_ALIGNED ? nVirTop : nVirBottom;
+ if ( (n >= nMin) && (n <= nMax) )
+ ImplDrawTab( &maVirDev, Point( n, nTopBottom ), mpData->pTabs[i].nStyle );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplInitSettings( sal_Bool bFont,
+ sal_Bool bForeground, sal_Bool bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont;
+ aFont = rStyleSettings.GetToolFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetWindowTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else
+ aColor = rStyleSettings.GetFaceColor();
+ SetBackground( aColor );
+ }
+
+ maVirDev.SetSettings( GetSettings() );
+ maVirDev.SetBackground( GetBackground() );
+ Font aFont = GetFont();
+ if ( mnWinStyle & WB_VERT )
+ aFont.SetOrientation( 900 );
+ maVirDev.SetFont( aFont );
+ maVirDev.SetTextColor( GetTextColor() );
+ maVirDev.SetTextFillColor( GetTextFillColor() );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplCalc()
+{
+ // Offset berechnen
+ mpData->nRulVirOff = mnWinOff + mpData->nPageOff;
+ if ( mpData->nRulVirOff > mnVirOff )
+ mpData->nRulVirOff -= mnVirOff;
+ else
+ mpData->nRulVirOff = 0;
+ long nRulWinOff = mpData->nRulVirOff+mnVirOff;
+
+ // Nicht sichtbaren Bereich der Page berechnen
+ long nNotVisPageWidth;
+ if ( mpData->nPageOff < 0 )
+ {
+ nNotVisPageWidth = -(mpData->nPageOff);
+ if ( nRulWinOff < mnWinOff )
+ nNotVisPageWidth -= mnWinOff-nRulWinOff;
+ }
+ else
+ nNotVisPageWidth = 0;
+
+ // Breite berechnen
+ if ( mnWinStyle & WB_HORZ )
+ {
+ if ( mbAutoWinWidth )
+ mnWinWidth = mnWidth - mnVirOff;
+ if ( mpData->bAutoPageWidth )
+ mpData->nPageWidth = mnWinWidth;
+ mpData->nRulWidth = Min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
+ if ( nRulWinOff+mpData->nRulWidth > mnWidth )
+ mpData->nRulWidth = mnWidth-nRulWinOff;
+ }
+ else
+ {
+ if ( mbAutoWinWidth )
+ mnWinWidth = mnHeight - mnVirOff;
+ if ( mpData->bAutoPageWidth )
+ mpData->nPageWidth = mnWinWidth;
+ mpData->nRulWidth = Min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
+ if ( nRulWinOff+mpData->nRulWidth > mnHeight )
+ mpData->nRulWidth = mnHeight-nRulWinOff;
+ }
+
+ mbCalc = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplFormat()
+{
+ // Wenn schon formatiert ist, brauchen wir es nicht nochmal
+ if ( !mbFormat )
+ return;
+
+ // Wenn Fenster noch keine Groesse hat, brauchen wir noch nichts machen
+ if ( !mnVirWidth )
+ return;
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ long nP1; // Pixel-Position von Page1
+ long nP2; // Pixel-Position von Page2
+ long nM1; // Pixel-Position von Margin1
+ long nM2; // Pixel-Position von Margin2
+ long nVirTop; // Obere/Linke-Kante bei Ausgabe
+ long nVirBottom; // Untere/Rechte-Kante bei Ausgabe
+ long nVirLeft; // Linke/Obere-Kante bei Ausgabe
+ long nVirRight; // Rechte/Untere-Kante bei Ausgabe
+ long nNullVirOff; // Fuer schnellere Berechnung
+
+ // Werte berechnen
+ if ( mbCalc )
+ ImplCalc();
+ mpData->nNullVirOff = mnWinOff+mpData->nPageOff+mpData->nNullOff-mnVirOff;
+ nNullVirOff = mpData->nNullVirOff;
+ nVirLeft = mpData->nRulVirOff;
+ nVirRight = nVirLeft+mpData->nRulWidth-1;
+ nVirTop = 0;
+ nVirBottom = mnVirHeight-1;
+
+ if ( !IsReallyVisible() )
+ return;
+
+ Size aVirDevSize;
+ sal_Bool b3DLook = !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO);
+
+ // VirtualDevice initialize
+ if ( mnWinStyle & WB_HORZ )
+ {
+ aVirDevSize.Width() = mnVirWidth;
+ aVirDevSize.Height() = mnVirHeight;
+ }
+ else
+ {
+ aVirDevSize.Height() = mnVirWidth;
+ aVirDevSize.Width() = mnVirHeight;
+ }
+ if ( aVirDevSize != maVirDev.GetOutputSizePixel() )
+ maVirDev.SetOutputSizePixel( aVirDevSize, sal_True );
+ else
+ maVirDev.Erase();
+
+ // Raender berechnen
+ if ( !(mpData->nMargin1Style & RULER_STYLE_INVISIBLE) )
+ {
+ nM1 = mpData->nMargin1+nNullVirOff;
+ if ( mpData->bAutoPageWidth )
+ {
+ nP1 = nVirLeft;
+ if ( nM1 < nVirLeft )
+ nP1--;
+ }
+ else
+ nP1 = nNullVirOff-mpData->nNullOff;
+ }
+ else
+ {
+ nM1 = nVirLeft-1;
+ nP1 = nM1;
+ }
+ if ( !(mpData->nMargin2Style & RULER_STYLE_INVISIBLE) )
+ {
+ nM2 = mpData->nMargin2+nNullVirOff;
+ if ( mpData->bAutoPageWidth )
+ {
+ nP2 = nVirRight;
+ if ( nM2 > nVirRight )
+ nP2++;
+ }
+ else
+ nP2 = nNullVirOff-mpData->nNullOff+mpData->nPageWidth;
+ if ( nM2 > nP2 )
+ nM2 = nP2;
+ }
+ else
+ {
+ nM2 = nVirRight+1;
+ nP2 = nM2;
+ }
+
+ // Obere/untere Kante ausgeben
+ if ( b3DLook )
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ else
+ maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
+ ImplVDrawLine( nVirLeft, nVirTop, nM1 - 1, nVirTop ); //top left line
+ ImplVDrawLine( nM2 +1, nVirTop, nP2 -1, nVirTop ); //top right line
+
+ // Jetzt wird zwischen dem Schatten ausgegeben
+ nVirTop++;
+ nVirBottom--;
+
+ // Margin1, Margin2 und Zwischenraum ausgeben
+ maVirDev.SetLineColor();
+ if ( b3DLook )
+ maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
+ else
+ maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
+ if ( nM1 > nVirLeft )
+ ImplVDrawRect( nP1, nVirTop, nM1-1, nVirBottom ); //left gray rectangle
+ if ( nM2 < nP2 )
+ ImplVDrawRect( nM2+1, nVirTop, nP2, nVirBottom ); //right gray rectangle
+ if ( nM2-nM1 > 0 )
+ {
+ maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
+ ImplVDrawRect( nM1, nVirTop, nM2-1, nVirBottom ); //center rectangle
+ }
+ if ( b3DLook )
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
+ if ( nM1 > nVirLeft )
+ {
+ ImplVDrawLine( nM1-1, nVirTop, nM1-1, nVirBottom );//right line of the left rectangle
+ ImplVDrawLine( nP1, nVirBottom, nM1-1, nVirBottom );//bottom line of the left rectangle
+ if ( nP1 >= nVirLeft )
+ {
+ ImplVDrawLine( nP1, nVirTop, nP1, nVirBottom );//left line of the left rectangle
+ ImplVDrawLine( nP1, nVirBottom, nP1+1, nVirBottom );//?
+ }
+ }
+ if ( nM2 < nP2 )
+ {
+ ImplVDrawLine( nM2+1, nVirBottom, nP2-1, nVirBottom );//bottom line of the right rectangle
+ ImplVDrawLine( nM2+1, nVirTop, nM2+1, nVirBottom );//left line of the right rectangle
+ if ( nP2 <= nVirRight+1 )
+ ImplVDrawLine( nP2-1, nVirTop, nP2-1, nVirBottom );//right line of the right rectangle
+ }
+ }
+ else
+ {
+ maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
+ if ( nP1 >= nVirLeft )
+ ImplVDrawLine( nP1, nVirTop, nP1, nVirBottom+1 );
+ if ( nM1 > nP1 )
+ ImplVDrawLine( nM1, nVirTop, nM1, nVirBottom );
+ if ( nM2 < nP2 )
+ ImplVDrawLine( nM2, nVirTop, nM2, nVirBottom );
+ if ( nP2 <= nVirRight+1 )
+ ImplVDrawLine( nP2, nVirTop, nP2, nVirBottom+1 );
+ }
+
+ // Lineal-Beschriftung (nur wenn keine Bemassungspfeile)
+ if ( !mpData->pArrows )
+ {
+ long nMin = nVirLeft;
+ long nMax = nP2;
+ long nStart = mpData->bTextRTL ? mpData->nMargin2 + nNullVirOff : nNullVirOff;
+ long nCenter = nVirTop+((nVirBottom-nVirTop)/2);
+
+ // Nicht Schatten uebermalen
+ if ( nP1 > nVirLeft )
+ nMin++;
+ if ( nP2 < nVirRight )
+ nMax--;
+
+ // Draw captions
+ ImplDrawTicks( nMin, nMax, nStart, nCenter );
+ }
+
+ // Draw borders
+ if ( mpData->pBorders )
+ ImplDrawBorders( nVirLeft, nP2, nVirTop, nVirBottom );
+
+ // Draw indents
+ if ( mpData->pIndents )
+ ImplDrawIndents( nVirLeft, nP2, nVirTop-1, nVirBottom+1 );
+
+ // Tabs
+ if ( mpData->pTabs )
+ {
+ ImplDrawTabs( nVirLeft, nP2, nVirTop-1, nVirBottom+1 );
+ }
+
+ // Bemassungspfeile
+ if ( mpData->pArrows )
+ ImplDrawArrows( nVirTop+((nVirBottom-nVirTop)/2) );
+
+ // Wir haben formatiert
+ mbFormat = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplInitExtraField( sal_Bool bUpdate )
+{
+ // Extra-Field beruecksichtigen
+ if ( mnWinStyle & WB_EXTRAFIELD )
+ {
+ maExtraRect.Left() = RULER_OFF;
+ maExtraRect.Top() = RULER_OFF;
+ maExtraRect.Right() = RULER_OFF+mnVirHeight-1;
+ maExtraRect.Bottom() = RULER_OFF+mnVirHeight-1;
+ if(mpData->bTextRTL)
+ {
+ Size aWinSize = GetOutputSizePixel();
+ if(mnWinStyle & WB_HORZ)
+ maExtraRect.Move(aWinSize.Width() - maExtraRect.GetWidth() - maExtraRect.Left(), 0);
+ else
+ maExtraRect.Move(0, aWinSize.Height() - maExtraRect.GetHeight() - maExtraRect.Top());
+ mnVirOff = 0;
+ }
+ else
+ mnVirOff = maExtraRect.Right()+1;
+
+ }
+ else
+ {
+ maExtraRect.SetEmpty();
+ mnVirOff = 0;
+ }
+
+ if ( bUpdate )
+ {
+ mbCalc = sal_True;
+ mbFormat = sal_True;
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDraw()
+{
+ if ( mbFormat )
+ ImplFormat();
+
+ if ( IsReallyVisible() )
+ {
+ // Lineal ueber das VirtualDevice ausgeben
+ Point aOffPos;
+ Size aVirDevSize = maVirDev.GetOutputSizePixel();
+// Size aVirDevSize2 = maVirDev.GetOutputSizePixel();
+ if ( mnWinStyle & WB_HORZ )
+ {
+ aOffPos.X() = mnVirOff;
+ if(mpData->bTextRTL)
+ aVirDevSize.Width() -= maExtraRect.GetWidth();
+
+// else
+// aVirDevSize.Width() -= mnVirOff;
+ aOffPos.Y() = RULER_OFF;
+ }
+ else
+ {
+ aOffPos.X() = RULER_OFF;
+ aOffPos.Y() = mnVirOff;
+// else
+// aVirDevSize.Height() -= mnVirOff;
+ }
+ DrawOutDev( aOffPos, aVirDevSize, Point(), aVirDevSize, maVirDev );
+
+ // Positionslinien neu malen
+ ImplInvertLines( sal_True );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawExtra( sal_Bool bPaint )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aRect = maExtraRect;
+ sal_Bool bEraseRect = sal_False;
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ aRect.Left() += 2;
+ aRect.Top() += 2;
+ aRect.Right() -= 2;
+ aRect.Bottom() -= 2;
+ }
+ else
+ {
+ aRect.Left() += 1;
+ aRect.Top() += 1;
+ aRect.Right() -= 1;
+ aRect.Bottom() -= 1;
+ }
+
+ if ( !bPaint && !(mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ SetFillColor( rStyleSettings.GetFaceColor() );
+ else
+ SetFillColor( rStyleSettings.GetWindowColor() );
+ bEraseRect = sal_True;
+ }
+ else
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) && (mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
+ {
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ bEraseRect = sal_True;
+ }
+ }
+
+ if ( bEraseRect )
+ {
+ SetLineColor();
+ DrawRect( aRect );
+ }
+
+ // Inhalt ausgeben
+ if ( meExtraType == RULER_EXTRA_NULLOFFSET )
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ SetLineColor( rStyleSettings.GetButtonTextColor() );
+ else
+ SetLineColor( rStyleSettings.GetWindowTextColor() );
+ DrawLine( Point( aRect.Left()+1, aRect.Top()+4 ),
+ Point( aRect.Right()-1, aRect.Top()+4 ) );
+ DrawLine( Point( aRect.Left()+4, aRect.Top()+1 ),
+ Point( aRect.Left()+4, aRect.Bottom()-1 ) );
+ }
+ else if ( meExtraType == RULER_EXTRA_TAB )
+ {
+ sal_uInt16 nTabStyle = mnExtraStyle & RULER_TAB_STYLE;
+ if(mpData->bTextRTL)
+ nTabStyle |= RULER_TAB_RTL;
+ Point aCenter = aRect.Center();
+ Point aDraw(aCenter);
+ ImplCenterTabPos( aDraw, nTabStyle );
+ WinBits nWinBits = GetStyle();
+ if(0 == (nWinBits&WB_HORZ) )
+ {
+ if(0 != (nWinBits&WB_RIGHT_ALIGNED))
+ aDraw.Y() = 2 * aCenter.Y() - aDraw.Y();
+ if(mpData->bTextRTL)
+ {
+ long nTemp = aDraw.X();
+ aDraw.X() = aDraw.Y();
+ aDraw.Y() = nTemp;
+ }
+ }
+ ImplDrawTab( this, aDraw, nTabStyle );
+ }
+
+ if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) && (mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
+ Invert( aRect );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplUpdate( sal_Bool bMustCalc )
+{
+ // Hier schon Linien loeschen, damit Sie vor dem Neuberechnen schon
+ // geloscht sind, da danach die alten Positionen nicht mehr bestimmt
+ // werden koennen
+ if ( !mbFormat )
+ ImplInvertLines();
+
+ // Flags setzen
+ if ( bMustCalc )
+ mbCalc = sal_True;
+ mbFormat = sal_True;
+
+ // Wenn wir am Draggen sind, wird nach dem Drag-Handler automatisch
+ // das Lineal neu upgedatet
+ if ( mbDrag )
+ return;
+
+ // Gegebenenfalls Update ausloesen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ mnUpdateFlags |= RULER_UPDATE_DRAW;
+ if ( !mnUpdateEvtId )
+ mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Ruler::ImplHitTest( const Point& rPos, ImplRulerHitTest* pHitTest,
+ sal_Bool bRequireStyle, sal_uInt16 nRequiredStyle ) const
+{
+ sal_uInt16 i;
+ sal_uInt16 nStyle;
+ long nHitBottom;
+ long nX;
+ long nY;
+ long n1;
+ long n2;
+
+ if ( !mbActive )
+ return sal_False;
+
+ // Position ermitteln
+ sal_Bool bIsHori = 0 != (mnWinStyle & WB_HORZ);
+ if ( bIsHori )
+ {
+ nX = rPos.X();
+ nY = rPos.Y();
+ }
+ else
+ {
+ nX = rPos.Y();
+ nY = rPos.X();
+ }
+ nHitBottom = mnVirHeight+(RULER_OFF*2);
+
+ // --> FME 2004-08-05 #i32608#
+ pHitTest->nAryPos = 0;
+ pHitTest->mnDragSize = 0;
+ pHitTest->bSize = sal_False;
+ pHitTest->bSizeBar = sal_False;
+ // <--
+
+ // Damit ueberstehende Tabs und Einzuege mit beruecksichtigt werden
+ long nXExtraOff;
+ if ( mpData->pTabs || mpData->pIndents )
+ nXExtraOff = (mnVirHeight/2) - 4;
+ else
+ nXExtraOff = 0;
+
+ // Test auf ausserhalb
+ nX -= mnVirOff;
+ long nXTemp = nX;
+ if ( (nX < mpData->nRulVirOff-nXExtraOff) || (nX > mpData->nRulVirOff+mpData->nRulWidth+nXExtraOff) ||
+ (nY < 0) || (nY > nHitBottom) )
+ {
+ pHitTest->nPos = 0;
+ pHitTest->eType = RULER_TYPE_OUTSIDE;
+ return sal_False;
+ }
+
+ nX -= mpData->nNullVirOff;
+ pHitTest->nPos = nX;
+ pHitTest->eType = RULER_TYPE_DONTKNOW;
+
+ // Zuerst die Tabs testen
+ Rectangle aRect;
+ if ( mpData->pTabs )
+ {
+ aRect.Bottom() = nHitBottom;
+ aRect.Top() = aRect.Bottom()-RULER_TAB_HEIGHT-RULER_OFF;
+
+ for ( i = mpData->nTabs; i; i-- )
+ {
+ nStyle = mpData->pTabs[i-1].nStyle;
+ if ( !(nStyle & RULER_STYLE_INVISIBLE) )
+ {
+ nStyle &= RULER_TAB_STYLE;
+
+ // Default-Tabs werden nur angezeigt
+ if ( nStyle != RULER_TAB_DEFAULT )
+ {
+ n1 = mpData->pTabs[i-1].nPos;
+
+ if ( nStyle == RULER_TAB_LEFT )
+ {
+ aRect.Left() = n1;
+ aRect.Right() = n1+RULER_TAB_WIDTH-1;
+ }
+ else if ( nStyle == RULER_TAB_RIGHT )
+ {
+ aRect.Right() = n1;
+ aRect.Left() = n1-RULER_TAB_WIDTH-1;
+ }
+ else
+ {
+ aRect.Left() = n1-RULER_TAB_CWIDTH2+1;
+ aRect.Right() = n1-RULER_TAB_CWIDTH2+RULER_TAB_CWIDTH;
+ }
+
+ if ( aRect.IsInside( Point( nX, nY ) ) )
+ {
+ pHitTest->eType = RULER_TYPE_TAB;
+ pHitTest->nAryPos = i-1;
+ return sal_True;
+ }
+ }
+ }
+ }
+ }
+
+ // Dann die Einzuege
+ if ( mpData->pIndents )
+ {
+ long nIndentHeight = (mnVirHeight/2) - 1;
+ long nIndentWidth2 = nIndentHeight-3;
+
+ for ( i = mpData->nIndents; i; i-- )
+ {
+ nStyle = mpData->pIndents[i-1].nStyle;
+ if ( (! bRequireStyle || nStyle == nRequiredStyle) &&
+ !(nStyle & RULER_STYLE_INVISIBLE) )
+ {
+ nStyle &= RULER_INDENT_STYLE;
+ n1 = mpData->pIndents[i-1].nPos;
+
+ if ( (nStyle == RULER_INDENT_BOTTOM) ^ (!bIsHori) )
+ {
+ aRect.Left() = n1-nIndentWidth2;
+ aRect.Right() = n1+nIndentWidth2;
+ aRect.Top() = nHitBottom-nIndentHeight-RULER_OFF+1;
+ aRect.Bottom() = nHitBottom;
+ }
+ else
+ {
+ aRect.Left() = n1-nIndentWidth2;
+ aRect.Right() = n1+nIndentWidth2;
+ aRect.Top() = 0;
+ aRect.Bottom() = nIndentHeight+RULER_OFF-1;
+ }
+
+ if ( aRect.IsInside( Point( nX, nY ) ) )
+ {
+ pHitTest->eType = RULER_TYPE_INDENT;
+ pHitTest->nAryPos = i-1;
+ return sal_True;
+ }
+ }
+ }
+ }
+
+ // Jetzt zaehlt nichts mehr, was links oder rechts uebersteht
+ if ( (nXTemp < mpData->nRulVirOff) || (nXTemp > mpData->nRulVirOff+mpData->nRulWidth) )
+ {
+ pHitTest->nPos = 0;
+ pHitTest->eType = RULER_TYPE_OUTSIDE;
+ return sal_False;
+ }
+
+ // Danach die Spalten testen
+ int nBorderTolerance = 1;
+ if(pHitTest->bExpandTest)
+ {
+ nBorderTolerance++;
+ }
+
+ for ( i = mpData->nBorders; i; i-- )
+ {
+ n1 = mpData->pBorders[i-1].nPos;
+ n2 = n1 + mpData->pBorders[i-1].nWidth;
+
+ // Spalten werden mit mindestens 3 Pixel breite gezeichnet
+ if ( !mpData->pBorders[i-1].nWidth )
+ {
+ n1 -= nBorderTolerance;
+ n2 += nBorderTolerance;
+
+ }
+
+ if ( (nX >= n1) && (nX <= n2) )
+ {
+ nStyle = mpData->pBorders[i-1].nStyle;
+ if ( !(nStyle & RULER_STYLE_INVISIBLE) )
+ {
+ pHitTest->eType = RULER_TYPE_BORDER;
+ pHitTest->nAryPos = i-1;
+
+ if ( !(nStyle & RULER_BORDER_SIZEABLE) )
+ {
+ if ( nStyle & RULER_BORDER_MOVEABLE )
+ {
+ pHitTest->bSizeBar = sal_True;
+ pHitTest->mnDragSize = RULER_DRAGSIZE_MOVE;
+ }
+ }
+ else
+ {
+ long nMOff = RULER_MOUSE_BORDERWIDTH;
+ while ( nMOff*2 >= (n2-n1-RULER_MOUSE_BORDERMOVE) )
+ {
+ if ( nMOff < 2 )
+ {
+ nMOff = 0;
+ break;
+ }
+ else
+ nMOff--;
+ }
+
+ if ( nX <= n1+nMOff )
+ {
+ pHitTest->bSize = sal_True;
+ pHitTest->mnDragSize = RULER_DRAGSIZE_1;
+ }
+ else if ( nX >= n2-nMOff )
+ {
+ pHitTest->bSize = sal_True;
+ pHitTest->mnDragSize = RULER_DRAGSIZE_2;
+ }
+ else
+ {
+ if ( nStyle & RULER_BORDER_MOVEABLE )
+ {
+ pHitTest->bSizeBar = sal_True;
+ pHitTest->mnDragSize = RULER_DRAGSIZE_MOVE;
+ }
+ }
+ }
+
+ return sal_True;
+ }
+ }
+ }
+
+ // Und zum Schluss die Raender
+ int nMarginTolerance = pHitTest->bExpandTest ? nBorderTolerance : RULER_MOUSE_MARGINWIDTH;
+
+ if ( (mpData->nMargin1Style & (RULER_MARGIN_SIZEABLE | RULER_STYLE_INVISIBLE)) == RULER_MARGIN_SIZEABLE )
+ {
+ n1 = mpData->nMargin1;
+ if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
+ {
+ pHitTest->eType = RULER_TYPE_MARGIN1;
+ pHitTest->bSize = sal_True;
+ return sal_True;
+ }
+ }
+ if ( (mpData->nMargin2Style & (RULER_MARGIN_SIZEABLE | RULER_STYLE_INVISIBLE)) == RULER_MARGIN_SIZEABLE )
+ {
+ n1 = mpData->nMargin2;
+ if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
+ {
+ pHitTest->eType = RULER_TYPE_MARGIN2;
+ pHitTest->bSize = sal_True;
+ return sal_True;
+ }
+ }
+
+ // Jetzt nocheinmal die Tabs testen, nur mit etwas mehr spielraum
+ if ( mpData->pTabs )
+ {
+ aRect.Top() = RULER_OFF;
+ aRect.Bottom() = nHitBottom;
+
+ for ( i = mpData->nTabs; i; i-- )
+ {
+ nStyle = mpData->pTabs[i-1].nStyle;
+ if ( !(nStyle & RULER_STYLE_INVISIBLE) )
+ {
+ nStyle &= RULER_TAB_STYLE;
+
+ // Default-Tabs werden nur angezeigt
+ if ( nStyle != RULER_TAB_DEFAULT )
+ {
+ n1 = mpData->pTabs[i-1].nPos;
+
+ if ( nStyle == RULER_TAB_LEFT )
+ {
+ aRect.Left() = n1;
+ aRect.Right() = n1+RULER_TAB_WIDTH-1;
+ }
+ else if ( nStyle == RULER_TAB_RIGHT )
+ {
+ aRect.Right() = n1;
+ aRect.Left() = n1-RULER_TAB_WIDTH-1;
+ }
+ else
+ {
+ aRect.Left() = n1-RULER_TAB_CWIDTH2+1;
+ aRect.Right() = n1-RULER_TAB_CWIDTH2+RULER_TAB_CWIDTH;
+ }
+
+ aRect.Left()--;
+ aRect.Right()++;
+
+ if ( aRect.IsInside( Point( nX, nY ) ) )
+ {
+ pHitTest->eType = RULER_TYPE_TAB;
+ pHitTest->nAryPos = i-1;
+ return sal_True;
+ }
+ }
+ }
+ }
+ }
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Ruler::ImplDocHitTest( const Point& rPos, RulerType eDragType,
+ ImplRulerHitTest* pHitTest ) const
+{
+ Point aPos = rPos;
+ sal_Bool bRequiredStyle = sal_False;
+ sal_uInt16 nRequiredStyle = 0;
+
+ if (eDragType == RULER_TYPE_INDENT)
+ {
+ bRequiredStyle = sal_True;
+ nRequiredStyle = RULER_INDENT_BOTTOM;
+ }
+
+ if ( mnWinStyle & WB_HORZ )
+ aPos.X() += mnWinOff;
+ else
+ aPos.Y() += mnWinOff;
+
+ if ( (eDragType == RULER_TYPE_INDENT) || (eDragType == RULER_TYPE_DONTKNOW) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPos.Y() = RULER_OFF+1;
+ else
+ aPos.X() = RULER_OFF+1;
+
+ // HitTest durchfuehren
+ if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
+ {
+ if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
+ return sal_True;
+ }
+ }
+
+ if ( (eDragType == RULER_TYPE_INDENT) || (eDragType == RULER_TYPE_TAB) ||
+ (eDragType == RULER_TYPE_DONTKNOW) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPos.Y() = mnHeight-RULER_OFF-1;
+ else
+ aPos.X() = mnWidth-RULER_OFF-1;
+
+ // HitTest durchfuehren
+ if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
+ {
+ if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
+ return sal_True;
+ }
+ }
+
+ if ( (eDragType == RULER_TYPE_MARGIN1) || (eDragType == RULER_TYPE_MARGIN2) ||
+ (eDragType == RULER_TYPE_BORDER) || (eDragType == RULER_TYPE_DONTKNOW) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPos.Y() = RULER_OFF + (mnVirHeight/2);
+ else
+ aPos.X() = RULER_OFF + (mnVirHeight/2);
+
+ // HitTest durchfuehren
+ if ( ImplHitTest( aPos, pHitTest ) )
+ {
+ if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
+ return sal_True;
+ }
+ }
+
+ // Auf DontKnow setzen
+ pHitTest->eType = RULER_TYPE_DONTKNOW;
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Ruler::ImplStartDrag( ImplRulerHitTest* pHitTest, sal_uInt16 nModifier )
+{
+ // Wenn eine Spalte angeklick wurde, die weder verschiebar noch
+ // in der Groesse aenderbar ist, brauchen wir auch kein Drag ausloesen
+ if ( (pHitTest->eType == RULER_TYPE_BORDER) &&
+ !pHitTest->bSize && !pHitTest->bSizeBar )
+ return sal_False;
+
+ // Dragdaten setzen
+ meDragType = pHitTest->eType;
+ mnDragPos = pHitTest->nPos;
+ mnDragAryPos = pHitTest->nAryPos;
+ mnDragSize = pHitTest->mnDragSize;
+ mnDragModifier = nModifier;
+ *mpDragData = *mpSaveData;
+ mpData = mpDragData;
+
+ // Handler rufen
+ if ( StartDrag() )
+ {
+ // Wenn der Handler das Draggen erlaubt, dann das Draggen
+ // initialisieren
+ ImplInvertLines();
+ mbDrag = sal_True;
+ mnStartDragPos = mnDragPos;
+ StartTracking();
+ return sal_True;
+ }
+ else
+ {
+ // Ansonsten muessen wir die Daten zuruecksetzen
+ meDragType = RULER_TYPE_DONTKNOW;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ mnDragSize = 0;
+ mnDragModifier = 0;
+ mpData = mpSaveData;
+ }
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrag( const Point& rPos )
+{
+ long nX;
+ long nY;
+ long nOutHeight;
+
+ if ( mnWinStyle & WB_HORZ )
+ {
+ nX = rPos.X();
+ nY = rPos.Y();
+ nOutHeight = mnHeight;
+ }
+ else
+ {
+ nX = rPos.Y();
+ nY = rPos.X();
+ nOutHeight = mnWidth;
+ }
+
+ // X berechnen und einpassen
+ nX -= mnVirOff;
+ if ( nX < mpData->nRulVirOff )
+ {
+ nX = mpData->nRulVirOff;
+ mnDragScroll = RULER_SCROLL_1;
+ }
+ else if ( nX > mpData->nRulVirOff+mpData->nRulWidth )
+ {
+ nX = mpData->nRulVirOff+mpData->nRulWidth;
+ mnDragScroll = RULER_SCROLL_2;
+ }
+ nX -= mpData->nNullVirOff;
+
+ // Wenn oberhalb oder links vom Lineal, dann alte Werte
+ mbDragDelete = sal_False;
+ if ( nY < 0 )
+ {
+ if ( !mbDragCanceled )
+ {
+ // Daten wiederherstellen
+ mbDragCanceled = sal_True;
+ ImplRulerData aTempData;
+ aTempData = *mpDragData;
+ *mpDragData = *mpSaveData;
+ mbCalc = sal_True;
+ mbFormat = sal_True;
+
+ // Handler rufen
+ mnDragPos = mnStartDragPos;
+ Drag();
+
+ // Und neu ausgeben (zeitverzoegert)
+/*
+ mnUpdateFlags |= RULER_UPDATE_DRAW;
+ if ( mnUpdateEvtId )
+ Application::RemoveUserEvent( mnUpdateEvtId );
+ mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
+*/
+ ImplDraw();
+
+ // Daten wieder wie vor dem Cancel herstellen
+ *mpDragData = aTempData;
+ }
+ }
+ else
+ {
+ mbDragCanceled = sal_False;
+
+ // +2, damit nicht so schnell die Tabs geloescht werden
+ if ( nY > nOutHeight+2 )
+ mbDragDelete = sal_True;
+
+ mnDragPos = nX;
+
+ // Handler rufen
+ Drag();
+
+ // Und neu ausgeben
+ if ( mbFormat )
+ ImplDraw();
+ }
+
+ mnDragScroll = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplEndDrag()
+{
+ // Werte uebernehmen
+ if ( mbDragCanceled )
+ *mpDragData = *mpSaveData;
+ else
+ *mpSaveData = *mpDragData;
+ mpData = mpSaveData;
+ mbDrag = sal_False;
+
+ // Handler rufen
+ EndDrag();
+
+ // Drag-Werte zuruecksetzen
+ meDragType = RULER_TYPE_DONTKNOW;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ mnDragSize = 0;
+ mbDragCanceled = sal_False;
+ mbDragDelete = sal_False;
+ mnDragModifier = 0;
+ mnDragScroll = 0;
+ mnStartDragPos = 0;
+
+ // Und neu ausgeben
+ ImplDraw();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( Ruler, ImplUpdateHdl, void*, EMPTYARG )
+{
+ mnUpdateEvtId = 0;
+
+ // Feststellen, was upgedatet werden muss
+ if ( mnUpdateFlags & RULER_UPDATE_DRAW )
+ {
+ mnUpdateFlags = 0;
+ ImplDraw();
+ }
+ else if ( mnUpdateFlags & RULER_UPDATE_LINES )
+ {
+ mnUpdateFlags = 0;
+ ImplInvertLines();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && !IsTracking() )
+ {
+ Point aMousePos = rMEvt.GetPosPixel();
+ sal_uInt16 nMouseClicks = rMEvt.GetClicks();
+ sal_uInt16 nMouseModifier = rMEvt.GetModifier();
+
+ // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
+ // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
+ if ( mbFormat )
+ {
+ ImplDraw();
+ mnUpdateFlags &= ~RULER_UPDATE_DRAW;
+ }
+
+ if ( maExtraRect.IsInside( aMousePos ) )
+ {
+ mnExtraClicks = nMouseClicks;
+ mnExtraModifier = nMouseModifier;
+ ExtraDown();
+ mnExtraClicks = 0;
+ mnExtraModifier = 0;
+ }
+ else
+ {
+ ImplRulerHitTest aHitTest;
+
+ if ( nMouseClicks == 1 )
+ {
+ if ( ImplHitTest( aMousePos, &aHitTest ) )
+ ImplStartDrag( &aHitTest, nMouseModifier );
+ else
+ {
+ // Position innerhalb des Lineal-Bereiches
+ if ( aHitTest.eType == RULER_TYPE_DONTKNOW )
+ {
+ mnDragPos = aHitTest.nPos;
+ Click();
+ mnDragPos = 0;
+
+ // Nocheinmal HitTest durchfuehren, da durch den Click
+ // zum Beispiel ein neuer Tab gesetzt werden konnte
+ if ( ImplHitTest( aMousePos, &aHitTest ) )
+ ImplStartDrag( &aHitTest, nMouseModifier );
+ }
+ }
+ }
+ else
+ {
+ if ( ImplHitTest( aMousePos, &aHitTest ) )
+ {
+ mnDragPos = aHitTest.nPos;
+ mnDragAryPos = aHitTest.nAryPos;
+ }
+ meDragType = aHitTest.eType;
+
+ DoubleClick();
+
+ meDragType = RULER_TYPE_DONTKNOW;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::MouseMove( const MouseEvent& rMEvt )
+{
+ PointerStyle ePtrStyle = POINTER_ARROW;
+
+ // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
+ // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
+ if ( mbFormat )
+ {
+ ImplDraw();
+ mnUpdateFlags &= ~RULER_UPDATE_DRAW;
+ }
+
+ ImplRulerHitTest aHitTest;
+ if ( ImplHitTest( rMEvt.GetPosPixel(), &aHitTest ) )
+ {
+ if ( aHitTest.bSize )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ ePtrStyle = POINTER_ESIZE;
+ else
+ ePtrStyle = POINTER_SSIZE;
+ }
+ else if ( aHitTest.bSizeBar )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ ePtrStyle = POINTER_HSIZEBAR;
+ else
+ ePtrStyle = POINTER_VSIZEBAR;
+ }
+ }
+
+ SetPointer( Pointer( ePtrStyle ) );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ // Bei Abbruch, den alten Status wieder herstellen
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ mbDragCanceled = sal_True;
+ mbFormat = sal_True;
+ }
+
+ ImplEndDrag();
+ }
+ else
+ ImplDrag( rTEvt.GetMouseEvent().GetPosPixel() );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::Paint( const Rectangle& )
+{
+ ImplDraw();
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ // Extra-Field beruecksichtigen
+ if ( mnWinStyle & WB_EXTRAFIELD )
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( maExtraRect.Left(), maExtraRect.Top() ),
+ Point( maExtraRect.Right()-1, maExtraRect.Top() ) );
+ DrawLine( Point( maExtraRect.Left(), maExtraRect.Top() ),
+ Point( maExtraRect.Left(), maExtraRect.Bottom()-1 ) );
+ DrawLine( Point( maExtraRect.Left(), maExtraRect.Bottom()-1 ),
+ Point( maExtraRect.Right()-1, maExtraRect.Bottom()-1 ) );
+ DrawLine( Point( maExtraRect.Right()-1, maExtraRect.Top() ),
+ Point( maExtraRect.Right()-1, maExtraRect.Bottom()-1 ) );
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( maExtraRect.Left()+1, maExtraRect.Top()+1 ),
+ Point( maExtraRect.Right()-2, maExtraRect.Top()+1 ) );
+ DrawLine( Point( maExtraRect.Left()+1, maExtraRect.Top()+1 ),
+ Point( maExtraRect.Left()+1, maExtraRect.Bottom()-2 ) );
+ DrawLine( Point( maExtraRect.Left(), maExtraRect.Bottom() ),
+ Point( maExtraRect.Right(), maExtraRect.Bottom() ) );
+ DrawLine( Point( maExtraRect.Right(), maExtraRect.Top() ),
+ Point( maExtraRect.Right(), maExtraRect.Bottom() ) );
+ }
+ else
+ {
+ SetLineColor( rStyleSettings.GetWindowTextColor() );
+ SetFillColor( rStyleSettings.GetWindowColor() );
+ DrawRect( maExtraRect );
+ }
+
+ // Imhalt vom Extrafeld ausgeben
+ ImplDrawExtra( sal_True );
+ }
+
+ if ( mnWinStyle & WB_BORDER )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( mnBorderOff, mnHeight-2 ),
+ Point( mnWidth, mnHeight-2 ) );
+ if ( mnBorderOff )
+ {
+ DrawLine( Point( mnBorderOff-1, mnHeight-2 ),
+ Point( mnBorderOff-1, mnHeight-1 ) );
+ }
+ }
+ SetLineColor( rStyleSettings.GetWindowTextColor() );
+ DrawLine( Point( mnBorderOff, mnHeight-1 ),
+ Point( mnWidth, mnHeight-1 ) );
+ }
+ else
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( mnWidth-2, mnBorderOff ),
+ Point( mnWidth-2, mnHeight ) );
+ if ( mnBorderOff )
+ {
+ DrawLine( Point( mnWidth-2, mnBorderOff-1 ),
+ Point( mnWidth-1, mnBorderOff-1 ) );
+ }
+ }
+ SetLineColor( rStyleSettings.GetWindowTextColor() );
+ DrawLine( Point( mnWidth-1, mnBorderOff ),
+ Point( mnWidth-1, mnHeight ) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::Resize()
+{
+ Size aWinSize = GetOutputSizePixel();
+
+ long nNewHeight;
+ if ( mnWinStyle & WB_HORZ )
+ {
+ if ( aWinSize.Height() != mnHeight )
+ nNewHeight = aWinSize.Height();
+ else
+ nNewHeight = 0;
+ }
+ else
+ {
+ if ( aWinSize.Width() != mnWidth )
+ nNewHeight = aWinSize.Width();
+ else
+ nNewHeight = 0;
+ }
+
+ // Hier schon Linien loeschen
+ sal_Bool bVisible = IsReallyVisible();
+ if ( bVisible && mpData->nLines )
+ {
+ ImplInvertLines();
+ mnUpdateFlags |= RULER_UPDATE_LINES;
+ if ( !mnUpdateEvtId )
+ mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
+ }
+ mbFormat = sal_True;
+
+ // Wenn sich die Hoehe bzw. Breite aendert, dann muessen besimmte Werte
+ // neu berechnet werden
+ //extra field should always be updated
+ ImplInitExtraField( mpData->bTextRTL );
+ if ( nNewHeight )
+ {
+ mbCalc = sal_True;
+ mnVirHeight = nNewHeight - mnBorderWidth - (RULER_OFF*2);
+ }
+ else
+ {
+ if ( mpData->bAutoPageWidth )
+ ImplUpdate( sal_True );
+ else if ( mbAutoWinWidth )
+ mbCalc = sal_True;
+ }
+
+ // Wenn Ruler eine Groesse hat, dann Groesse vom VirtualDevice setzen
+ if ( (mnVirWidth > RULER_MIN_SIZE) ||
+ ((aWinSize.Width() > RULER_MIN_SIZE) && (aWinSize.Height() > RULER_MIN_SIZE)) )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ mnVirWidth = aWinSize.Width()-mnVirOff;
+ else
+ mnVirWidth = aWinSize.Height()-mnVirOff;
+ if ( mnVirWidth < RULER_MIN_SIZE )
+ mnVirWidth = 0;
+ }
+
+ // Gegebenenfalls ein Teil vom Rand loeschen, da 3D-Effekt/Trennlinie am
+ // Fensterrand
+ if ( bVisible )
+ {
+ if ( nNewHeight )
+ Invalidate();
+ else if ( mpData->bAutoPageWidth )
+ {
+ // Nur bei AutoPageWidth haben wir rechts einen 3D-Effekt,
+ // der sich der Fensterbreite anpasst und deshalb neu gezeichnet
+ // werden muss
+ Rectangle aRect;
+
+ if ( mnWinStyle & WB_HORZ )
+ {
+ if ( mnWidth < aWinSize.Width() )
+ aRect.Left() = mnWidth-RULER_RESIZE_OFF;
+ else
+ aRect.Left() = aWinSize.Width()-RULER_RESIZE_OFF;
+ aRect.Right() = aRect.Left()+RULER_RESIZE_OFF;
+ aRect.Top() = RULER_OFF;
+ aRect.Bottom() = RULER_OFF+mnVirHeight;
+ }
+ else
+ {
+ if ( mnHeight < aWinSize.Height() )
+ aRect.Top() = mnHeight-RULER_RESIZE_OFF;
+ else
+ aRect.Top() = aWinSize.Height()-RULER_RESIZE_OFF;
+ aRect.Bottom() = aRect.Top()+RULER_RESIZE_OFF;
+ aRect.Left() = RULER_OFF;
+ aRect.Right() = RULER_OFF+mnVirHeight;
+ }
+
+ Invalidate( aRect );
+ }
+ }
+
+ // Neue Groesse merken
+ mnWidth = aWinSize.Width();
+ mnHeight = aWinSize.Height();
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ ImplFormat();
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplDraw();
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( sal_True, sal_False, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( sal_False, sal_True, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( sal_False, sal_False, sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ mbFormat = sal_True;
+ ImplInitSettings( sal_True, sal_True, sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long Ruler::StartDrag()
+{
+ if ( maStartDragHdl.IsSet() )
+ return maStartDragHdl.Call( this );
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::Drag()
+{
+ maDragHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::EndDrag()
+{
+ maEndDragHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::Click()
+{
+ maClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ExtraDown()
+{
+ maExtraDownHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::Activate()
+{
+ mbActive = sal_True;
+
+ // Positionslinien wieder anzeigen (erst hinter mbActive=sal_True rufen, da
+ // von ImplInvertLines() ausgewertet wird). Das Zeichnen der Linien
+ // wird verzoegert, damit im vermutlich noch nicht gepainteten Zustand
+ // Linien gezeichnet werden.
+ mnUpdateFlags |= RULER_UPDATE_LINES;
+ if ( !mnUpdateEvtId )
+ mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::Deactivate()
+{
+ // Positionslinien loeschen (schon vor mbActive=sal_False rufen, da
+ // von ImplInvertLines() ausgewertet wird)
+ ImplInvertLines();
+
+ mbActive = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool Ruler::StartDocDrag( const MouseEvent& rMEvt, RulerType eDragType )
+{
+ if ( !mbDrag )
+ {
+ Point aMousePos = rMEvt.GetPosPixel();
+ sal_uInt16 nMouseClicks = rMEvt.GetClicks();
+ sal_uInt16 nMouseModifier = rMEvt.GetModifier();
+ ImplRulerHitTest aHitTest;
+ if(eDragType != RULER_TYPE_DONTKNOW)
+ aHitTest.bExpandTest = sal_True;
+
+ // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
+ // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
+ if ( mbFormat )
+ {
+ ImplDraw();
+ mnUpdateFlags &= ~RULER_UPDATE_DRAW;
+ }
+
+ if ( nMouseClicks == 1 )
+ {
+ if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
+ {
+ Pointer aPtr;
+
+ if ( aHitTest.bSize )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPtr = Pointer( POINTER_ESIZE );
+ else
+ aPtr = Pointer( POINTER_SSIZE );
+ }
+ else if ( aHitTest.bSizeBar )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ aPtr = Pointer( POINTER_HSIZEBAR );
+ else
+ aPtr = Pointer( POINTER_VSIZEBAR );
+ }
+ SetPointer( aPtr );
+ return ImplStartDrag( &aHitTest, nMouseModifier );
+ }
+ }
+ else if ( nMouseClicks == 2 )
+ {
+ if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
+ {
+ mnDragPos = aHitTest.nPos;
+ mnDragAryPos = aHitTest.nAryPos;
+ }
+ eDragType = aHitTest.eType;
+
+ DoubleClick();
+
+ eDragType = RULER_TYPE_DONTKNOW;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+RulerType Ruler::GetDocType( const Point& rPos, RulerType eDragType,
+ sal_uInt16* pAryPos ) const
+{
+ ImplRulerHitTest aHitTest;
+
+ // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
+ // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
+ if ( IsReallyVisible() && mbFormat )
+ {
+ ((Ruler*)this)->ImplDraw();
+ ((Ruler*)this)->mnUpdateFlags &= ~RULER_UPDATE_DRAW;
+ }
+
+ // HitTest durchfuehren
+ ImplDocHitTest( rPos, eDragType, &aHitTest );
+
+ // Werte zurueckgeben
+ if ( pAryPos )
+ *pAryPos = aHitTest.nAryPos;
+ return aHitTest.eType;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::CancelDrag()
+{
+ if ( mbDrag )
+ {
+ ImplDrag( Point( -1, -1 ) );
+ ImplEndDrag();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+RulerType Ruler::GetType( const Point& rPos, sal_uInt16* pAryPos ) const
+{
+ ImplRulerHitTest aHitTest;
+
+ // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
+ // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
+ if ( IsReallyVisible() && mbFormat )
+ {
+ ((Ruler*)this)->ImplDraw();
+ ((Ruler*)this)->mnUpdateFlags &= ~RULER_UPDATE_DRAW;
+ }
+
+ // HitTest durchfuehren
+ ImplHitTest( rPos, &aHitTest );
+
+ // Werte zurueckgeben
+ if ( pAryPos )
+ *pAryPos = aHitTest.nAryPos;
+ return aHitTest.eType;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetWinPos( long nNewOff, long nNewWidth )
+{
+ // Gegebenenfalls werden die Breiten automatisch berechnet
+ if ( !nNewWidth )
+ mbAutoWinWidth = sal_True;
+ else
+ mbAutoWinWidth = sal_False;
+
+ // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
+ mnWinOff = nNewOff;
+ mnWinWidth = nNewWidth;
+ ImplUpdate( sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetPagePos( long nNewOff, long nNewWidth )
+{
+ // Muessen wir ueberhaupt was machen
+ if ( (mpData->nPageOff == nNewOff) && (mpData->nPageWidth == nNewWidth) )
+ return;
+
+ // Gegebenenfalls werden die Breiten automatisch berechnet
+ if ( !nNewWidth )
+ mpData->bAutoPageWidth = sal_True;
+ else
+ mpData->bAutoPageWidth = sal_False;
+
+ // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
+ mpData->nPageOff = nNewOff;
+ mpData->nPageWidth = nNewWidth;
+ ImplUpdate( sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetBorderPos( long nOff )
+{
+ if ( mnWinStyle & WB_BORDER )
+ {
+ if ( mnBorderOff != nOff )
+ {
+ mnBorderOff = nOff;
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetUnit( FieldUnit eNewUnit )
+{
+ if ( meUnit != eNewUnit )
+ {
+ meUnit = eNewUnit;
+ switch ( meUnit )
+ {
+ case FUNIT_MM:
+ mnUnitIndex = RULER_UNIT_MM;
+ break;
+ case FUNIT_CM:
+ mnUnitIndex = RULER_UNIT_CM;
+ break;
+ case FUNIT_M:
+ mnUnitIndex = RULER_UNIT_M;
+ break;
+ case FUNIT_KM:
+ mnUnitIndex = RULER_UNIT_KM;
+ break;
+ case FUNIT_INCH:
+ mnUnitIndex = RULER_UNIT_INCH;
+ break;
+ case FUNIT_FOOT:
+ mnUnitIndex = RULER_UNIT_FOOT;
+ break;
+ case FUNIT_MILE:
+ mnUnitIndex = RULER_UNIT_MILE;
+ break;
+ case FUNIT_POINT:
+ mnUnitIndex = RULER_UNIT_POINT;
+ break;
+ case FUNIT_PICA:
+ mnUnitIndex = RULER_UNIT_PICA;
+ break;
+ default:
+#ifdef DBG_UTIL
+ DBG_ERRORFILE( "Ruler::SetUnit() - Wrong Unit" );
+#endif
+ break;
+ }
+
+ maMapMode.SetMapUnit( aImplRulerUnitTab[mnUnitIndex].eMapUnit );
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetZoom( const Fraction& rNewZoom )
+{
+ DBG_ASSERT( rNewZoom.GetNumerator(), "Ruler::SetZoom() with scale 0 is not allowed" );
+
+ if ( maZoom != rNewZoom )
+ {
+ maZoom = rNewZoom;
+ maMapMode.SetScaleX( maZoom );
+ maMapMode.SetScaleY( maZoom );
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetExtraType( RulerExtra eNewExtraType, sal_uInt16 nStyle )
+{
+ if ( mnWinStyle & WB_EXTRAFIELD )
+ {
+ meExtraType = eNewExtraType;
+ mnExtraStyle = nStyle;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplDrawExtra( sal_False );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetNullOffset( long nPos )
+{
+ if ( mpData->nNullOff != nPos )
+ {
+ mpData->nNullOff = nPos;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetMargin1( long nPos, sal_uInt16 nMarginStyle )
+{
+ if ( (mpData->nMargin1 != nPos) || (mpData->nMargin1Style != nMarginStyle) )
+ {
+ mpData->nMargin1 = nPos;
+ mpData->nMargin1Style = nMarginStyle;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetMargin2( long nPos, sal_uInt16 nMarginStyle )
+{
+ DBG_ASSERT( (nPos >= mpData->nMargin1) ||
+ (mpData->nMargin1Style & RULER_STYLE_INVISIBLE) ||
+ (mpData->nMargin2Style & RULER_STYLE_INVISIBLE),
+ "Ruler::SetMargin2() - Margin2 < Margin1" );
+
+ if ( (mpData->nMargin2 != nPos) || (mpData->nMargin2Style != nMarginStyle) )
+ {
+ mpData->nMargin2 = nPos;
+ mpData->nMargin2Style = nMarginStyle;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetLines( sal_uInt16 n, const RulerLine* pLineAry )
+{
+ // To determine if what has changed
+ if ( mpData->nLines == n )
+ {
+ sal_uInt16 i = n;
+ const RulerLine* pAry1 = mpData->pLines;
+ const RulerLine* pAry2 = pLineAry;
+ while ( i )
+ {
+ if ( (pAry1->nPos != pAry2->nPos) ||
+ (pAry1->nStyle != pAry2->nStyle) )
+ break;
+ pAry1++;
+ pAry2++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+
+ // New values and new share issue
+ sal_Bool bMustUpdate;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ bMustUpdate = sal_True;
+ else
+ bMustUpdate = sal_False;
+
+ // Delete old lines
+ if ( bMustUpdate )
+ ImplInvertLines();
+
+ // New data set
+ if ( !n || !pLineAry )
+ {
+ if ( !mpData->pLines )
+ return;
+ delete[] mpData->pLines;
+ mpData->nLines = 0;
+ mpData->pLines = NULL;
+ }
+ else
+ {
+ if ( mpData->nLines != n )
+ {
+ delete[] mpData->pLines;
+ mpData->nLines = n;
+ mpData->pLines = new RulerLine[n];
+ }
+
+ memcpy( mpData->pLines, pLineAry, n*sizeof( RulerLine ) );
+
+ // Linien neu ausgeben
+ if ( bMustUpdate )
+ ImplInvertLines();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetArrows( sal_uInt16 n, const RulerArrow* pArrowAry )
+{
+ if ( !n || !pArrowAry )
+ {
+ if ( !mpData->pArrows )
+ return;
+ delete[] mpData->pArrows;
+ mpData->nArrows = 0;
+ mpData->pArrows = NULL;
+ }
+ else
+ {
+ if ( mpData->nArrows != n )
+ {
+ delete[] mpData->pArrows;
+ mpData->nArrows = n;
+ mpData->pArrows = new RulerArrow[n];
+ }
+ else
+ {
+ sal_uInt16 i = n;
+ const RulerArrow* pAry1 = mpData->pArrows;
+ const RulerArrow* pAry2 = pArrowAry;
+ while ( i )
+ {
+ if ( (pAry1->nPos != pAry2->nPos) ||
+ (pAry1->nWidth != pAry2->nWidth) ||
+ (pAry1->nLogWidth != pAry2->nLogWidth) ||
+ (pAry1->nStyle != pAry2->nStyle) )
+ break;
+ pAry1++;
+ pAry2++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+
+ memcpy( mpData->pArrows, pArrowAry, n*sizeof( RulerArrow ) );
+ }
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetBorders( sal_uInt16 n, const RulerBorder* pBrdAry )
+{
+ if ( !n || !pBrdAry )
+ {
+ if ( !mpData->pBorders )
+ return;
+ delete[] mpData->pBorders;
+ mpData->nBorders = 0;
+ mpData->pBorders = NULL;
+ }
+ else
+ {
+ if ( mpData->nBorders != n )
+ {
+ delete[] mpData->pBorders;
+ mpData->nBorders = n;
+ mpData->pBorders = new RulerBorder[n];
+ }
+ else
+ {
+ sal_uInt16 i = n;
+ const RulerBorder* pAry1 = mpData->pBorders;
+ const RulerBorder* pAry2 = pBrdAry;
+ while ( i )
+ {
+ if ( (pAry1->nPos != pAry2->nPos) ||
+ (pAry1->nWidth != pAry2->nWidth) ||
+ (pAry1->nStyle != pAry2->nStyle) )
+ break;
+ pAry1++;
+ pAry2++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+
+ memcpy( mpData->pBorders, pBrdAry, n*sizeof( RulerBorder ) );
+ }
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetIndents( sal_uInt16 n, const RulerIndent* pIndentAry )
+{
+
+ if ( !n || !pIndentAry )
+ {
+ if ( !mpData->pIndents )
+ return;
+ delete[] mpData->pIndents;
+ mpData->nIndents = 0;
+ mpData->pIndents = NULL;
+ }
+ else
+ {
+ if ( mpData->nIndents != n )
+ {
+ delete[] mpData->pIndents;
+ mpData->nIndents = n;
+ mpData->pIndents = new RulerIndent[n];
+ }
+ else
+ {
+ sal_uInt16 i = n;
+ const RulerIndent* pAry1 = mpData->pIndents;
+ const RulerIndent* pAry2 = pIndentAry;
+ while ( i )
+ {
+ if ( (pAry1->nPos != pAry2->nPos) ||
+ (pAry1->nStyle != pAry2->nStyle) )
+ break;
+ pAry1++;
+ pAry2++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+
+ memcpy( mpData->pIndents, pIndentAry, n*sizeof( RulerIndent ) );
+ }
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetTabs( sal_uInt16 n, const RulerTab* pTabAry )
+{
+ if ( !n || !pTabAry )
+ {
+ if ( !mpData->pTabs )
+ return;
+ delete[] mpData->pTabs;
+ mpData->nTabs = 0;
+ mpData->pTabs = NULL;
+ }
+ else
+ {
+ if ( mpData->nTabs != n )
+ {
+ delete[] mpData->pTabs;
+ mpData->nTabs = n;
+ mpData->pTabs = new RulerTab[n];
+ }
+ else
+ {
+ sal_uInt16 i = n;
+ const RulerTab* pAry1 = mpData->pTabs;
+ const RulerTab* pAry2 = pTabAry;
+ while ( i )
+ {
+ if ( (pAry1->nPos != pAry2->nPos) ||
+ (pAry1->nStyle != pAry2->nStyle) )
+ break;
+ pAry1++;
+ pAry2++;
+ i--;
+ }
+ if ( !i )
+ return;
+ }
+
+ memcpy( mpData->pTabs, pTabAry, n*sizeof( RulerTab ) );
+ }
+
+ ImplUpdate();
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetStyle( WinBits nStyle )
+{
+ if ( mnWinStyle != nStyle )
+ {
+ mnWinStyle = nStyle;
+ ImplInitExtraField( sal_True );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::DrawTab( OutputDevice* pDevice, const Point& rPos, sal_uInt16 nStyle )
+{
+ /*const StyleSettings& rStyleSettings =*/ pDevice->GetSettings().GetStyleSettings();
+ Point aPos( rPos );
+ sal_uInt16 nTabStyle = nStyle & (RULER_TAB_STYLE | RULER_TAB_RTL);
+
+ pDevice->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
+ pDevice->SetLineColor();
+ pDevice->SetFillColor( pDevice->GetSettings().GetStyleSettings().GetWindowTextColor() );
+ ImplCenterTabPos( aPos, nTabStyle );
+ ImplDrawRulerTab( pDevice, aPos, nTabStyle, nStyle );
+ pDevice->Pop();
+}
+/* -----------------16.10.2002 15:17-----------------
+ *
+ * --------------------------------------------------*/
+void Ruler::SetTextRTL(sal_Bool bRTL)
+{
+ if(mpData->bTextRTL != bRTL)
+ {
+ mpData->bTextRTL = bRTL;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplInitExtraField( sal_True );
+ }
+
+}
+long Ruler::GetPageOffset() const { return mpData->nPageOff; }
+long Ruler::GetPageWidth() const { return mpData->nPageWidth; }
+long Ruler::GetNullOffset() const { return mpData->nNullOff; }
+long Ruler::GetMargin1() const { return mpData->nMargin1; }
+sal_uInt16 Ruler::GetMargin1Style() const { return mpData->nMargin1Style; }
+long Ruler::GetMargin2() const { return mpData->nMargin2; }
+sal_uInt16 Ruler::GetMargin2Style() const { return mpData->nMargin2Style; }
+sal_uInt16 Ruler::GetLineCount() const { return mpData->nLines; }
+const RulerLine* Ruler::GetLines() const { return mpData->pLines; }
+sal_uInt16 Ruler::GetArrowCount() const { return mpData->nArrows; }
+const RulerArrow* Ruler::GetArrows() const { return mpData->pArrows; }
+sal_uInt16 Ruler::GetBorderCount() const { return mpData->nBorders; }
+const RulerBorder* Ruler::GetBorders() const { return mpData->pBorders; }
+sal_uInt16 Ruler::GetIndentCount() const { return mpData->nIndents; }
+const RulerIndent* Ruler::GetIndents() const { return mpData->pIndents; }
+
diff --git a/svtools/source/control/scriptedtext.cxx b/svtools/source/control/scriptedtext.cxx
new file mode 100755
index 000000000000..7e657ba56ce8
--- /dev/null
+++ b/svtools/source/control/scriptedtext.cxx
@@ -0,0 +1,392 @@
+/*************************************************************************
+ *
+ * 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 <svtools/scriptedtext.hxx>
+#include <vector>
+#include <rtl/ustring.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/font.hxx>
+#include <tools/debug.hxx>
+#include <com/sun/star/i18n/ScriptType.hpp>
+
+
+using namespace ::std;
+using namespace ::rtl;
+using namespace ::com::sun::star;
+
+
+//_____________________________________________________________________________
+
+class SvtScriptedTextHelper_Impl
+{
+private:
+ OutputDevice& mrOutDevice; /// The output device for drawing the text.
+ Font maLatinFont; /// The font for latin text portions.
+ Font maAsianFont; /// The font for asian text portions.
+ Font maCmplxFont; /// The font for complex text portions.
+ Font maDefltFont; /// The default font of the output device.
+ OUString maText; /// The text.
+
+ vector< sal_Int32 > maPosVec; /// The start position of each text portion.
+ vector< sal_Int16 > maScriptVec; /// The script type of each text portion.
+ vector< sal_Int32 > maWidthVec; /// The output width of each text portion.
+ Size maTextSize; /// The size the text will take in the current output device.
+
+ /** Assignment operator not implemented to prevent usage. */
+ SvtScriptedTextHelper_Impl& operator=( const SvtScriptedTextHelper_Impl& );
+
+ /** Gets the font of the given script type. */
+ const Font& GetFont( sal_uInt16 _nScript ) const;
+ /** Sets a font on the output device depending on the script type. */
+ inline void SetOutDevFont( sal_uInt16 _nScript )
+ { mrOutDevice.SetFont( GetFont( _nScript ) ); }
+ /** Fills maPosVec with positions of all changes of script type.
+ This method expects correctly initialized maPosVec and maScriptVec. */
+ void CalculateSizes();
+ /** Fills maPosVec with positions of all changes of script type and
+ maScriptVec with the script type of each portion. */
+ void CalculateBreaks(
+ const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
+
+public:
+ /** This constructor sets an output device and fonts for all script types. */
+ SvtScriptedTextHelper_Impl(
+ OutputDevice& _rOutDevice,
+ Font* _pLatinFont,
+ Font* _pAsianFont,
+ Font* _pCmplxFont );
+ /** Copy constructor. */
+ SvtScriptedTextHelper_Impl(
+ const SvtScriptedTextHelper_Impl& _rCopy );
+ /** Destructor. */
+ ~SvtScriptedTextHelper_Impl();
+
+ /** Sets new fonts and recalculates the text width. */
+ void SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont );
+ /** Sets a new text and calculates all script breaks and the text width. */
+ void SetText(
+ const OUString& _rText,
+ const uno::Reference< i18n::XBreakIterator >& _xBreakIter );
+
+ /** Returns the previously set text. */
+ const OUString& GetText() const;
+ /** Returns a size struct containing the width and height of the text in the current output device. */
+ const Size& GetTextSize() const;
+
+ /** Draws the text in the current output device. */
+ void DrawText( const Point& _rPos );
+};
+
+
+SvtScriptedTextHelper_Impl::SvtScriptedTextHelper_Impl(
+ OutputDevice& _rOutDevice,
+ Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont ) :
+ mrOutDevice( _rOutDevice ),
+ maLatinFont( _pLatinFont ? *_pLatinFont : _rOutDevice.GetFont() ),
+ maAsianFont( _pAsianFont ? *_pAsianFont : _rOutDevice.GetFont() ),
+ maCmplxFont( _pCmplxFont ? *_pCmplxFont : _rOutDevice.GetFont() ),
+ maDefltFont( _rOutDevice.GetFont() )
+{
+}
+
+SvtScriptedTextHelper_Impl::SvtScriptedTextHelper_Impl( const SvtScriptedTextHelper_Impl& _rCopy ) :
+ mrOutDevice( _rCopy.mrOutDevice ),
+ maLatinFont( _rCopy.maLatinFont ),
+ maAsianFont( _rCopy.maAsianFont ),
+ maCmplxFont( _rCopy.maCmplxFont ),
+ maDefltFont( _rCopy.maDefltFont ),
+ maText( _rCopy.maText ),
+ maPosVec( _rCopy.maPosVec ),
+ maScriptVec( _rCopy.maScriptVec ),
+ maWidthVec( _rCopy.maWidthVec ),
+ maTextSize( _rCopy.maTextSize )
+{
+}
+
+SvtScriptedTextHelper_Impl::~SvtScriptedTextHelper_Impl()
+{
+}
+
+const Font& SvtScriptedTextHelper_Impl::GetFont( sal_uInt16 _nScript ) const
+{
+ switch( _nScript )
+ {
+ case i18n::ScriptType::LATIN: return maLatinFont;
+ case i18n::ScriptType::ASIAN: return maAsianFont;
+ case i18n::ScriptType::COMPLEX: return maCmplxFont;
+ }
+ return maDefltFont;
+}
+
+void SvtScriptedTextHelper_Impl::CalculateSizes()
+{
+ maTextSize.Width() = maTextSize.Height() = 0;
+ maDefltFont = mrOutDevice.GetFont();
+
+ // calculate text portion widths and total width
+ maWidthVec.clear();
+ if( !maPosVec.empty() )
+ {
+ DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(),
+ "SvtScriptedTextHelper_Impl::CalculateWidth - invalid vectors" );
+
+ xub_StrLen nThisPos = static_cast< xub_StrLen >( maPosVec[ 0 ] );
+ xub_StrLen nNextPos;
+ sal_Int32 nPosVecSize = maPosVec.size();
+ sal_Int32 nPosVecIndex = 1;
+
+ sal_Int16 nScript;
+ sal_Int32 nScriptVecIndex = 0;
+
+ sal_Int32 nCurrWidth;
+
+ while( nPosVecIndex < nPosVecSize )
+ {
+ nNextPos = static_cast< xub_StrLen >( maPosVec[ nPosVecIndex++ ] );
+ nScript = maScriptVec[ nScriptVecIndex++ ];
+
+ SetOutDevFont( nScript );
+ nCurrWidth = mrOutDevice.GetTextWidth( maText, nThisPos, nNextPos - nThisPos );
+ maWidthVec.push_back( nCurrWidth );
+ maTextSize.Width() += nCurrWidth;
+ nThisPos = nNextPos;
+ }
+ }
+
+ // calculate maximum font height
+ SetOutDevFont( i18n::ScriptType::LATIN );
+ maTextSize.Height() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
+ SetOutDevFont( i18n::ScriptType::ASIAN );
+ maTextSize.Height() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
+ SetOutDevFont( i18n::ScriptType::COMPLEX );
+ maTextSize.Height() = Max( maTextSize.Height(), mrOutDevice.GetTextHeight() );
+
+ mrOutDevice.SetFont( maDefltFont );
+}
+
+void SvtScriptedTextHelper_Impl::CalculateBreaks( const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
+{
+ maPosVec.clear();
+ maScriptVec.clear();
+
+ DBG_ASSERT( _xBreakIter.is(), "SvtScriptedTextHelper_Impl::CalculateBreaks - no break iterator" );
+
+ sal_Int32 nLen = maText.getLength();
+ if( nLen )
+ {
+ if( _xBreakIter.is() )
+ {
+ sal_Int32 nThisPos = 0; // first position of this portion
+ sal_Int32 nNextPos = 0; // first position of next portion
+ sal_Int16 nPortScript; // script type of this portion
+ do
+ {
+ nPortScript = _xBreakIter->getScriptType( maText, nThisPos );
+ nNextPos = _xBreakIter->endOfScript( maText, nThisPos, nPortScript );
+
+ switch( nPortScript )
+ {
+ case i18n::ScriptType::LATIN:
+ case i18n::ScriptType::ASIAN:
+ case i18n::ScriptType::COMPLEX:
+ maPosVec.push_back( nThisPos );
+ maScriptVec.push_back( nPortScript );
+ break;
+ default:
+ {
+/* *** handling of weak characters ***
+- first portion is weak: Use OutputDevice::HasGlyphs() to find the correct font
+- weak portion follows another portion: Script type of preceding portion is used */
+ if( maPosVec.empty() )
+ {
+ sal_Int32 nCharIx = 0;
+ sal_Int32 nNextCharIx = 0;
+ sal_Int16 nScript;
+ do
+ {
+ nScript = i18n::ScriptType::LATIN;
+ while( (nScript != i18n::ScriptType::WEAK) && (nCharIx == nNextCharIx) )
+ {
+ nNextCharIx = mrOutDevice.HasGlyphs( GetFont( nScript ), maText, sal::static_int_cast< sal_uInt16 >(nCharIx), sal::static_int_cast< sal_uInt16 >(nNextPos - nCharIx) );
+ if( nCharIx == nNextCharIx )
+ ++nScript;
+ }
+ if( nNextCharIx == nCharIx )
+ ++nNextCharIx;
+
+ maPosVec.push_back( nCharIx );
+ maScriptVec.push_back( nScript );
+ nCharIx = nNextCharIx;
+ }
+ while( nCharIx < nNextPos );
+ }
+ // nothing to do for following portions
+ }
+ }
+ nThisPos = nNextPos;
+ }
+ while( (0 <= nThisPos) && (nThisPos < nLen) );
+ }
+ else // no break iterator: whole text LATIN
+ {
+ maPosVec.push_back( 0 );
+ maScriptVec.push_back( i18n::ScriptType::LATIN );
+ }
+
+ // push end position of last portion
+ if( !maPosVec.empty() )
+ maPosVec.push_back( nLen );
+ }
+ CalculateSizes();
+}
+
+void SvtScriptedTextHelper_Impl::SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont )
+{
+ maLatinFont = _pLatinFont ? *_pLatinFont : maDefltFont;
+ maAsianFont = _pAsianFont ? *_pAsianFont : maDefltFont;
+ maCmplxFont = _pCmplxFont ? *_pCmplxFont : maDefltFont;
+ CalculateSizes();
+}
+
+void SvtScriptedTextHelper_Impl::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
+{
+ maText = _rText;
+ CalculateBreaks( _xBreakIter );
+}
+
+const OUString& SvtScriptedTextHelper_Impl::GetText() const
+{
+ return maText;
+}
+
+const Size& SvtScriptedTextHelper_Impl::GetTextSize() const
+{
+ return maTextSize;
+}
+
+void SvtScriptedTextHelper_Impl::DrawText( const Point& _rPos )
+{
+ if( !maText.getLength() || maPosVec.empty() )
+ return;
+
+ DBG_ASSERT( maPosVec.size() - 1 == maScriptVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
+ DBG_ASSERT( maScriptVec.size() == maWidthVec.size(), "SvtScriptedTextHelper_Impl::DrawText - invalid vectors" );
+
+ maDefltFont = mrOutDevice.GetFont();
+ Point aCurrPos( _rPos );
+ xub_StrLen nThisPos = static_cast< xub_StrLen >( maPosVec[ 0 ] );
+ xub_StrLen nNextPos;
+ sal_Int32 nPosVecSize = maPosVec.size();
+ sal_Int32 nPosVecIndex = 1;
+
+ sal_Int16 nScript;
+ sal_Int32 nVecIndex = 0;
+
+ while( nPosVecIndex < nPosVecSize )
+ {
+ nNextPos = static_cast< xub_StrLen >( maPosVec[ nPosVecIndex++ ] );
+ nScript = maScriptVec[ nVecIndex ];
+
+ SetOutDevFont( nScript );
+ mrOutDevice.DrawText( aCurrPos, maText, nThisPos, nNextPos - nThisPos );
+ aCurrPos.X() += maWidthVec[ nVecIndex++ ];
+ aCurrPos.X() += mrOutDevice.GetTextHeight() / 5; // add 20% of font height as portion spacing
+ nThisPos = nNextPos;
+ }
+ mrOutDevice.SetFont( maDefltFont );
+}
+
+
+//_____________________________________________________________________________
+
+SvtScriptedTextHelper::SvtScriptedTextHelper( OutputDevice& _rOutDevice ) :
+ mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice, NULL, NULL, NULL ) )
+{
+}
+
+SvtScriptedTextHelper::SvtScriptedTextHelper(
+ OutputDevice& _rOutDevice,
+ Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont ) :
+ mpImpl( new SvtScriptedTextHelper_Impl( _rOutDevice, _pLatinFont, _pAsianFont, _pCmplxFont ) )
+{
+}
+
+SvtScriptedTextHelper::SvtScriptedTextHelper( const SvtScriptedTextHelper& _rCopy ) :
+ mpImpl( new SvtScriptedTextHelper_Impl( *_rCopy.mpImpl ) )
+{
+}
+
+SvtScriptedTextHelper::~SvtScriptedTextHelper()
+{
+ delete mpImpl;
+}
+
+void SvtScriptedTextHelper::SetFonts( Font* _pLatinFont, Font* _pAsianFont, Font* _pCmplxFont )
+{
+ mpImpl->SetFonts( _pLatinFont, _pAsianFont, _pCmplxFont );
+}
+
+void SvtScriptedTextHelper::SetDefaultFont()
+{
+ mpImpl->SetFonts( NULL, NULL, NULL );
+}
+
+void SvtScriptedTextHelper::SetText( const OUString& _rText, const uno::Reference< i18n::XBreakIterator >& _xBreakIter )
+{
+ mpImpl->SetText( _rText, _xBreakIter );
+}
+
+const OUString& SvtScriptedTextHelper::GetText() const
+{
+ return mpImpl->GetText();
+}
+
+sal_Int32 SvtScriptedTextHelper::GetTextWidth() const
+{
+ return mpImpl->GetTextSize().Width();
+}
+
+sal_Int32 SvtScriptedTextHelper::GetTextHeight() const
+{
+ return mpImpl->GetTextSize().Height();
+}
+
+const Size& SvtScriptedTextHelper::GetTextSize() const
+{
+ return mpImpl->GetTextSize();
+}
+
+void SvtScriptedTextHelper::DrawText( const Point& _rPos )
+{
+ mpImpl->DrawText( _rPos );
+}
+
+
+//_____________________________________________________________________________
+
diff --git a/svtools/source/control/scrwin.cxx b/svtools/source/control/scrwin.cxx
new file mode 100755
index 000000000000..ab4946a8400b
--- /dev/null
+++ b/svtools/source/control/scrwin.cxx
@@ -0,0 +1,572 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _SVT_SCRWIN_CXX
+#include <svtools/scrwin.hxx>
+
+//===================================================================
+
+void ScrollableWindow::ImpInitialize( ScrollableWindowFlags nFlags )
+{
+ bHandleDragging = (sal_Bool) ( nFlags & SCRWIN_THUMBDRAGGING );
+ bVCenter = (nFlags & SCRWIN_VCENTER) == SCRWIN_VCENTER;
+ bHCenter = (nFlags & SCRWIN_HCENTER) == SCRWIN_HCENTER;
+ bScrolling = sal_False;
+
+ // set the handlers for the scrollbars
+ aVScroll.SetScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
+ aHScroll.SetScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
+ aVScroll.SetEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
+ aHScroll.SetEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
+
+ nColumnPixW = nLinePixH = GetSettings().GetStyleSettings().GetScrollBarSize();
+}
+
+//-------------------------------------------------------------------
+
+ScrollableWindow::ScrollableWindow( Window* pParent, WinBits nBits,
+ ScrollableWindowFlags nFlags ) :
+ Window( pParent, WinBits(nBits|WB_CLIPCHILDREN) ),
+ aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
+ aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
+ aCornerWin( this )
+{
+ ImpInitialize( nFlags );
+}
+
+//-------------------------------------------------------------------
+
+ScrollableWindow::ScrollableWindow( Window* pParent, const ResId& rId,
+ ScrollableWindowFlags nFlags ) :
+ Window( pParent, rId ),
+ aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
+ aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
+ aCornerWin( this )
+{
+ ImpInitialize( nFlags );
+}
+
+// -----------------------------------------------------------------------
+
+void ScrollableWindow::Command( const CommandEvent& rCEvt )
+{
+ if ( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
+ (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
+ (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
+ {
+ ScrollBar* pHScrBar;
+ ScrollBar* pVScrBar;
+ if ( aHScroll.IsVisible() )
+ pHScrBar = &aHScroll;
+ else
+ pHScrBar = NULL;
+ if ( aVScroll.IsVisible() )
+ pVScrBar = &aVScroll;
+ else
+ pVScrBar = NULL;
+ if ( HandleScrollCommand( rCEvt, pHScrBar, pVScrBar ) )
+ return;
+ }
+
+ Window::Command( rCEvt );
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ Resize();
+ Invalidate();
+ }
+
+ Window::DataChanged( rDCEvt );
+}
+
+//-------------------------------------------------------------------
+
+Size __EXPORT ScrollableWindow::GetOutputSizePixel() const
+{
+ Size aSz( Window::GetOutputSizePixel() );
+
+ long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( aHScroll.IsVisible() )
+ aSz.Height() -= nTmp;
+ if ( aVScroll.IsVisible() )
+ aSz.Width() -= nTmp;
+ return aSz;
+}
+
+//-------------------------------------------------------------------
+
+Size ScrollableWindow::GetOutputSize() const
+{
+ return PixelToLogic( GetOutputSizePixel() );
+}
+
+//-------------------------------------------------------------------
+
+IMPL_LINK( ScrollableWindow, EndScrollHdl, ScrollBar *, pScroll )
+{
+ // notify the start of scrolling, if not already scrolling
+ if ( !bScrolling )
+ StartScroll(), bScrolling = sal_True;
+
+ // get the delta in logic coordinates
+ Size aDelta( PixelToLogic( Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
+
+ // scroll the window, if this is not already done
+ if ( !bHandleDragging )
+ {
+ if ( pScroll == &aHScroll )
+ Scroll( aDelta.Width(), 0 );
+ else
+ Scroll( 0, aDelta.Height() );
+ }
+
+ // notify the end of scrolling
+ bScrolling = sal_False;
+ EndScroll( aDelta.Width(), aDelta.Height() );
+ return 0;
+}
+
+//-------------------------------------------------------------------
+
+IMPL_LINK( ScrollableWindow, ScrollHdl, ScrollBar *, pScroll )
+{
+ // notify the start of scrolling, if not already scrolling
+ if ( !bScrolling )
+ StartScroll(), bScrolling = sal_True;
+
+ if ( bHandleDragging )
+ {
+ // get the delta in logic coordinates
+ Size aDelta( PixelToLogic(
+ Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
+ if ( pScroll == &aHScroll )
+ Scroll( aDelta.Width(), 0 );
+ else
+ Scroll( 0, aDelta.Height() );
+ }
+ return 0;
+}
+
+//-------------------------------------------------------------------
+
+void __EXPORT ScrollableWindow::Resize()
+{
+ // get the new output-size in pixel
+ Size aOutPixSz = Window::GetOutputSizePixel();
+
+ // determine the size of the output-area and if we need scrollbars
+ const long nScrSize = GetSettings().GetStyleSettings().GetScrollBarSize();
+ sal_Bool bVVisible = sal_False; // by default no vertical-ScrollBar
+ sal_Bool bHVisible = sal_False; // by default no horizontal-ScrollBar
+ sal_Bool bChanged; // determines if a visiblility was changed
+ do
+ {
+ bChanged = sal_False;
+
+ // does we need a vertical ScrollBar
+ if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
+ { bHVisible = sal_True;
+ aOutPixSz.Height() -= nScrSize;
+ bChanged = sal_True;
+ }
+
+ // does we need a horizontal ScrollBar
+ if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
+ { bVVisible = sal_True;
+ aOutPixSz.Width() -= nScrSize;
+ bChanged = sal_True;
+ }
+
+ }
+ while ( bChanged ); // until no visibility has changed
+
+ // store the old offset and map-mode
+ MapMode aMap( GetMapMode() );
+ Point aOldPixOffset( aPixOffset );
+
+ // justify (right/bottom borders should never exceed the virtual window)
+ Size aPixDelta;
+ if ( aPixOffset.X() < 0 &&
+ aPixOffset.X() + aTotPixSz.Width() < aOutPixSz.Width() )
+ aPixDelta.Width() =
+ aOutPixSz.Width() - ( aPixOffset.X() + aTotPixSz.Width() );
+ if ( aPixOffset.Y() < 0 &&
+ aPixOffset.Y() + aTotPixSz.Height() < aOutPixSz.Height() )
+ aPixDelta.Height() =
+ aOutPixSz.Height() - ( aPixOffset.Y() + aTotPixSz.Height() );
+ if ( aPixDelta.Width() || aPixDelta.Height() )
+ {
+ aPixOffset.X() += aPixDelta.Width();
+ aPixOffset.Y() += aPixDelta.Height();
+ }
+
+ // for axis without scrollbar restore the origin
+ if ( !bVVisible || !bHVisible )
+ {
+ aPixOffset = Point(
+ bHVisible
+ ? aPixOffset.X()
+ : ( bHCenter
+ ? (aOutPixSz.Width()-aTotPixSz.Width()) / 2
+ : 0 ),
+ bVVisible
+ ? aPixOffset.Y()
+ : ( bVCenter
+ ? (aOutPixSz.Height()-aTotPixSz.Height()) / 2
+ : 0 ) );
+ }
+ if ( bHVisible && !aHScroll.IsVisible() )
+ aPixOffset.X() = 0;
+ if ( bVVisible && !aVScroll.IsVisible() )
+ aPixOffset.Y() = 0;
+
+ // select the shifted map-mode
+ if ( aPixOffset != aOldPixOffset )
+ {
+ Window::SetMapMode( MapMode( MAP_PIXEL ) );
+ Window::Scroll(
+ aPixOffset.X() - aOldPixOffset.X(),
+ aPixOffset.Y() - aOldPixOffset.Y() );
+ SetMapMode( aMap );
+ }
+
+ // show or hide scrollbars
+ aVScroll.Show( bVVisible );
+ aHScroll.Show( bHVisible );
+
+ // disable painting in the corner between the scrollbars
+ if ( bVVisible && bHVisible )
+ {
+ aCornerWin.SetPosSizePixel(Point(aOutPixSz.Width(), aOutPixSz.Height()),
+ Size(nScrSize, nScrSize) );
+ aCornerWin.Show();
+ }
+ else
+ aCornerWin.Hide();
+
+ // resize scrollbars and set their ranges
+ if ( bHVisible )
+ {
+ aHScroll.SetPosSizePixel(
+ Point( 0, aOutPixSz.Height() ),
+ Size( aOutPixSz.Width(), nScrSize ) );
+ aHScroll.SetRange( Range( 0, aTotPixSz.Width() ) );
+ aHScroll.SetPageSize( aOutPixSz.Width() );
+ aHScroll.SetVisibleSize( aOutPixSz.Width() );
+ aHScroll.SetLineSize( nColumnPixW );
+ aHScroll.SetThumbPos( -aPixOffset.X() );
+ }
+ if ( bVVisible )
+ {
+ aVScroll.SetPosSizePixel(
+ Point( aOutPixSz.Width(), 0 ),
+ Size( nScrSize,aOutPixSz.Height() ) );
+ aVScroll.SetRange( Range( 0, aTotPixSz.Height() ) );
+ aVScroll.SetPageSize( aOutPixSz.Height() );
+ aVScroll.SetVisibleSize( aOutPixSz.Height() );
+ aVScroll.SetLineSize( nLinePixH );
+ aVScroll.SetThumbPos( -aPixOffset.Y() );
+ }
+}
+
+//-------------------------------------------------------------------
+
+void __EXPORT ScrollableWindow::StartScroll()
+{
+}
+
+//-------------------------------------------------------------------
+
+void __EXPORT ScrollableWindow::EndScroll( long, long )
+{
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::SetMapMode( const MapMode& rNewMapMode )
+{
+ MapMode aMap( rNewMapMode );
+ aMap.SetOrigin( aMap.GetOrigin() + PixelToLogic( aPixOffset, aMap ) );
+ Window::SetMapMode( aMap );
+}
+
+//-------------------------------------------------------------------
+
+MapMode ScrollableWindow::GetMapMode() const
+{
+ MapMode aMap( Window::GetMapMode() );
+ aMap.SetOrigin( aMap.GetOrigin() - PixelToLogic( aPixOffset ) );
+ return aMap;
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::SetTotalSize( const Size& rNewSize )
+{
+ aTotPixSz = LogicToPixel( rNewSize );
+ ScrollableWindow::Resize();
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::SetVisibleSize( const Size& rNewSize )
+{
+ // get the rectangle, we wish to view
+ Rectangle aWish( Point(0, 0), LogicToPixel(rNewSize) );
+
+ // get maximum rectangle for us from our parent-window (subst our border!)
+ Rectangle aMax( Point(0, 0), GetParent()->GetOutputSizePixel() );
+ aMax.Left() -= ( Window::GetSizePixel().Width() -
+ Window::GetOutputSizePixel().Width() );
+ aMax.Bottom() -= (Window::GetSizePixel().Height() -
+ Window::GetOutputSizePixel().Height());
+
+ Size aWill( aWish.GetIntersection(aMax).GetSize() );
+ sal_Bool bHScroll = sal_False;
+ const long nScrSize = GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( aWill.Width() < aWish.GetSize().Width() )
+ { bHScroll = sal_True;
+ aWill.Height() =
+ Min( aWill.Height()+nScrSize, aMax.GetSize().Height() );
+ }
+ if ( aWill.Height() < aWish.GetSize().Height() )
+ aWill.Width() =
+ Min( aWill.Width()+nScrSize, aMax.GetSize().Width() );
+ if ( !bHScroll && (aWill.Width() < aWish.GetSize().Width()) )
+ aWill.Height() =
+ Min( aWill.Height()+nScrSize, aMax.GetSize().Height() );
+ Window::SetOutputSizePixel( aWill );
+}
+
+//-------------------------------------------------------------------
+
+sal_Bool ScrollableWindow::MakeVisible( const Rectangle& rTarget, sal_Bool bSloppy )
+{
+ Rectangle aTarget;
+ Rectangle aTotRect( Point(0, 0), PixelToLogic( aTotPixSz ) );
+
+ if ( bSloppy )
+ {
+ aTarget = rTarget;
+
+ // at maximum to right border
+ if ( aTarget.Right() > aTotRect.Right() )
+ {
+ long nDelta = aTarget.Right() - aTotRect.Right();
+ aTarget.Left() -= nDelta;
+ aTarget.Right() -= nDelta;
+
+ // too wide?
+ if ( aTarget.Left() < aTotRect.Left() )
+ aTarget.Left() = aTotRect.Left();
+ }
+
+ // at maximum to bottom border
+ if ( aTarget.Bottom() > aTotRect.Bottom() )
+ {
+ long nDelta = aTarget.Bottom() - aTotRect.Bottom();
+ aTarget.Top() -= nDelta;
+ aTarget.Bottom() -= nDelta;
+
+ // too high?
+ if ( aTarget.Top() < aTotRect.Top() )
+ aTarget.Top() = aTotRect.Top();
+ }
+
+ // at maximum to left border
+ if ( aTarget.Left() < aTotRect.Left() )
+ {
+ long nDelta = aTarget.Left() - aTotRect.Left();
+ aTarget.Right() -= nDelta;
+ aTarget.Left() -= nDelta;
+
+ // too wide?
+ if ( aTarget.Right() > aTotRect.Right() )
+ aTarget.Right() = aTotRect.Right();
+ }
+
+ // at maximum to top border
+ if ( aTarget.Top() < aTotRect.Top() )
+ {
+ long nDelta = aTarget.Top() - aTotRect.Top();
+ aTarget.Bottom() -= nDelta;
+ aTarget.Top() -= nDelta;
+
+ // too high?
+ if ( aTarget.Bottom() > aTotRect.Bottom() )
+ aTarget.Bottom() = aTotRect.Bottom();
+ }
+ }
+ else
+ aTarget = rTarget.GetIntersection( aTotRect );
+
+ // is the area already visible?
+ Rectangle aVisArea( GetVisibleArea() );
+ if ( aVisArea.IsInside(rTarget) )
+ return sal_True;
+
+ // is there somewhat to scroll?
+ if ( aVisArea.TopLeft() != aTarget.TopLeft() )
+ {
+ Rectangle aBox( aTarget.GetUnion(aVisArea) );
+ long nDeltaX = ( aBox.Right() - aVisArea.Right() ) +
+ ( aBox.Left() - aVisArea.Left() );
+ long nDeltaY = ( aBox.Top() - aVisArea.Top() ) +
+ ( aBox.Bottom() - aVisArea.Bottom() );
+ Scroll( nDeltaX, nDeltaY );
+ }
+
+ // determine if the target is completely visible
+ return aVisArea.GetWidth() >= aTarget.GetWidth() &&
+ aVisArea.GetHeight() >= aTarget.GetHeight();
+}
+
+//-------------------------------------------------------------------
+
+Rectangle ScrollableWindow::GetVisibleArea() const
+{
+ Point aTopLeft( PixelToLogic( Point() ) );
+ Size aSz( GetOutputSize() );
+ return Rectangle( aTopLeft, aSz );
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::SetLineSize( sal_uLong nHorz, sal_uLong nVert )
+{
+ Size aPixSz( LogicToPixel( Size(nHorz, nVert) ) );
+ nColumnPixW = aPixSz.Width();
+ nLinePixH = aPixSz.Height();
+ aVScroll.SetLineSize( nLinePixH );
+ aHScroll.SetLineSize( nColumnPixW );
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::Scroll( long nDeltaX, long nDeltaY, sal_uInt16 )
+{
+ if ( !bScrolling )
+ StartScroll();
+
+ // get the delta in pixel
+ Size aDeltaPix( LogicToPixel( Size(nDeltaX, nDeltaY) ) );
+ Size aOutPixSz( GetOutputSizePixel() );
+ MapMode aMap( GetMapMode() );
+ Point aNewPixOffset( aPixOffset );
+
+ // scrolling horizontally?
+ if ( nDeltaX != 0 )
+ {
+ aNewPixOffset.X() -= aDeltaPix.Width();
+ if ( ( aOutPixSz.Width() - aNewPixOffset.X() ) > aTotPixSz.Width() )
+ aNewPixOffset.X() = - ( aTotPixSz.Width() - aOutPixSz.Width() );
+ else if ( aNewPixOffset.X() > 0 )
+ aNewPixOffset.X() = 0;
+ }
+
+ // scrolling vertically?
+ if ( nDeltaY != 0 )
+ {
+ aNewPixOffset.Y() -= aDeltaPix.Height();
+ if ( ( aOutPixSz.Height() - aNewPixOffset.Y() ) > aTotPixSz.Height() )
+ aNewPixOffset.Y() = - ( aTotPixSz.Height() - aOutPixSz.Height() );
+ else if ( aNewPixOffset.Y() > 0 )
+ aNewPixOffset.Y() = 0;
+ }
+
+ // recompute the logical scroll units
+ aDeltaPix.Width() = aPixOffset.X() - aNewPixOffset.X();
+ aDeltaPix.Height() = aPixOffset.Y() - aNewPixOffset.Y();
+ Size aDelta( PixelToLogic(aDeltaPix) );
+ nDeltaX = aDelta.Width();
+ nDeltaY = aDelta.Height();
+ aPixOffset = aNewPixOffset;
+
+ // scrolling?
+ if ( nDeltaX != 0 || nDeltaY != 0 )
+ {
+ Update();
+
+ // does the new area overlap the old one?
+ if ( Abs( (int)aDeltaPix.Height() ) < aOutPixSz.Height() ||
+ Abs( (int)aDeltaPix.Width() ) < aOutPixSz.Width() )
+ {
+ // scroll the overlapping area
+ SetMapMode( aMap );
+
+ // never scroll the scrollbars itself!
+ Window::Scroll(-nDeltaX, -nDeltaY,
+ PixelToLogic( Rectangle( Point(0, 0), aOutPixSz ) ) );
+ }
+ else
+ {
+ // repaint all
+ SetMapMode( aMap );
+ Invalidate();
+ }
+
+ Update();
+ }
+
+ if ( !bScrolling )
+ {
+ EndScroll( nDeltaX, nDeltaY );
+ if ( nDeltaX )
+ aHScroll.SetThumbPos( -aPixOffset.X() );
+ if ( nDeltaY )
+ aVScroll.SetThumbPos( -aPixOffset.Y() );
+ }
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::ScrollLines( long nLinesX, long nLinesY )
+{
+ Size aDelta( PixelToLogic( Size( nColumnPixW, nLinePixH ) ) );
+ Scroll( aDelta.Width()*nLinesX, aDelta.Height()*nLinesY );
+}
+
+//-------------------------------------------------------------------
+
+void ScrollableWindow::ScrollPages( long nPagesX, sal_uLong nOverlapX,
+ long nPagesY, sal_uLong nOverlapY )
+{
+ Size aOutSz( GetVisibleArea().GetSize() );
+ Scroll( nPagesX * aOutSz.Width() + (nPagesX>0 ? 1 : -1) * nOverlapX,
+ nPagesY * aOutSz.Height() + (nPagesY>0 ? 1 : -1) * nOverlapY );
+}
+
+
diff --git a/svtools/source/control/stdctrl.cxx b/svtools/source/control/stdctrl.cxx
new file mode 100755
index 000000000000..fb42b42dc7f3
--- /dev/null
+++ b/svtools/source/control/stdctrl.cxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * 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 <svtools/stdctrl.hxx>
+
+// =======================================================================
+
+FixedInfo::FixedInfo( Window* pParent, WinBits nWinStyle ) :
+ FixedText( pParent, nWinStyle | WB_INFO )
+{
+}
+
+// -----------------------------------------------------------------------
+
+FixedInfo::FixedInfo( Window* pParent, const ResId& rResId ) :
+ FixedText( pParent, rResId )
+{
+ SetStyle( GetStyle() | WB_INFO );
+}
+
+namespace svt
+{
+ // class svt::SelectableFixedText ----------------------------------------
+
+ SelectableFixedText::SelectableFixedText( Window* pParent, WinBits nWinStyle ) :
+ Edit( pParent, nWinStyle )
+ {
+ Init();
+ }
+
+ // -----------------------------------------------------------------------
+
+ SelectableFixedText::SelectableFixedText( Window* pParent, const ResId& rResId ) :
+ Edit( pParent, rResId )
+ {
+ Init();
+ }
+
+ // -----------------------------------------------------------------------
+
+ SelectableFixedText::~SelectableFixedText()
+ {
+ }
+
+ // -----------------------------------------------------------------------
+
+ void SelectableFixedText::Init()
+ {
+ // no border
+ SetBorderStyle( WINDOW_BORDER_NOBORDER );
+ // read-only
+ SetReadOnly();
+ // make it transparent
+ SetControlBackground();
+ SetBackground();
+ SetPaintTransparent( sal_True );
+ }
+
+ // -----------------------------------------------------------------------
+
+ void SelectableFixedText::LoseFocus()
+ {
+ Edit::LoseFocus();
+ // clear cursor
+ Invalidate();
+ }
+
+} // namespace svt
+
diff --git a/svtools/source/control/stdmenu.cxx b/svtools/source/control/stdmenu.cxx
new file mode 100755
index 000000000000..94c15a8604d2
--- /dev/null
+++ b/svtools/source/control/stdmenu.cxx
@@ -0,0 +1,510 @@
+/*************************************************************************
+ *
+ * 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 <string.h>
+#include <vcl/svapp.hxx>
+#include <vcl/i18nhelp.hxx>
+#include <svtools/ctrltool.hxx>
+#include <svtools/stdmenu.hxx>
+
+// ========================================================================
+
+FontNameMenu::FontNameMenu()
+{
+ SetMenuFlags( GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
+}
+
+// -----------------------------------------------------------------------
+
+FontNameMenu::~FontNameMenu()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FontNameMenu::Select()
+{
+ maCurName = GetItemText( GetCurItemId() );
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void FontNameMenu::Highlight()
+{
+ XubString aTempName = maCurName;
+ maCurName = GetItemText( GetCurItemId() );
+ maHighlightHdl.Call( this );
+ maCurName = aTempName;
+}
+
+// -----------------------------------------------------------------------
+
+void FontNameMenu::Fill( const FontList* pList )
+{
+ // clear menu
+ Clear();
+
+ // add fonts
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+ // more than 100 fonts reduces the speed of opening the menu.
+ // So only the first 100 fonts will be displayed.
+ sal_uInt16 nFontCount = ::std::min( pList->GetFontNameCount(), static_cast< sal_uInt16 >(100) );
+ for ( sal_uInt16 i = 0; i < nFontCount; i++ )
+ {
+ const XubString& rName = pList->GetFontName( i ).GetName();
+
+ // sort with the I18nHelper
+ sal_uInt16 j = GetItemCount();
+ while ( j )
+ {
+ XubString aText = GetItemText( GetItemId( j-1 ) );
+ if ( rI18nHelper.CompareString( rName, aText ) > 0 )
+ break;
+ j--;
+ }
+ InsertItem( i+1, rName, MIB_RADIOCHECK | MIB_AUTOCHECK, j );
+ }
+
+ SetCurName( maCurName );
+}
+
+// -----------------------------------------------------------------------
+
+void FontNameMenu::SetCurName( const XubString& rName )
+{
+ maCurName = rName;
+
+ // Menueintrag checken
+ sal_uInt16 nChecked = 0;
+ sal_uInt16 nItemCount = GetItemCount();
+ for( sal_uInt16 i = 0; i < nItemCount; i++ )
+ {
+ sal_uInt16 nItemId = GetItemId( i );
+
+ if ( IsItemChecked( nItemId ) )
+ nChecked = nItemId;
+
+ XubString aText = GetItemText( nItemId );
+ if ( aText == maCurName )
+ {
+ CheckItem( nItemId, sal_True );
+ return;
+ }
+ }
+
+ if ( nChecked )
+ CheckItem( nChecked, sal_False );
+}
+
+// ========================================================================
+
+FontStyleMenu::FontStyleMenu()
+{
+ SetMenuFlags( GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
+}
+
+// -----------------------------------------------------------------------
+
+FontStyleMenu::~FontStyleMenu()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FontStyleMenu::Select()
+{
+ sal_uInt16 nCurId = GetCurItemId();
+
+ if ( (nCurId >= FONTSTYLEMENU_FIRSTID) && (nCurId <= FONTSTYLEMENU_LASTID) )
+ {
+ maCurStyle = GetItemText( nCurId );
+ maSelectHdl.Call( this );
+ }
+ else
+ PopupMenu::Select();
+}
+
+// -----------------------------------------------------------------------
+
+void FontStyleMenu::Highlight()
+{
+ sal_uInt16 nCurId = GetCurItemId();
+
+ if ( (nCurId >= FONTSTYLEMENU_FIRSTID) && (nCurId <= FONTSTYLEMENU_LASTID) )
+ {
+ XubString aTempName = maCurStyle;
+ maCurStyle = GetItemText( nCurId );
+ maHighlightHdl.Call( this );
+ maCurStyle = aTempName;
+ }
+ else
+ PopupMenu::Highlight();
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool FontStyleMenu::ImplIsAlreadyInserted( const XubString& rStyleName, sal_uInt16 nCount )
+{
+ for ( sal_uInt16 i = 0; i < nCount; i++ )
+ {
+ if ( GetItemText( i+FONTSTYLEMENU_FIRSTID ) == rStyleName )
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void FontStyleMenu::Fill( const XubString& rName, const FontList* pList )
+{
+ sal_uInt16 nItemId = GetItemId( 0 );
+ while ( (nItemId >= FONTSTYLEMENU_FIRSTID) &&
+ (nItemId <= FONTSTYLEMENU_LASTID) )
+ {
+ RemoveItem( 0 );
+ nItemId = GetItemId( 0 );
+ }
+
+ // Existiert ein Font mit diesem Namen
+ sal_Handle hFontInfo = pList->GetFirstFontInfo( rName );
+ if ( hFontInfo )
+ {
+ XubString aStyleText;
+ sal_uInt16 nPos = 0;
+ sal_uInt16 nId = FONTSTYLEMENU_FIRSTID;
+ FontWeight eLastWeight = WEIGHT_DONTKNOW;
+ FontItalic eLastItalic = ITALIC_NONE;
+ FontWidth eLastWidth = WIDTH_DONTKNOW;
+ sal_Bool bNormal = sal_False;
+ sal_Bool bItalic = sal_False;
+ sal_Bool bBold = sal_False;
+ sal_Bool bBoldItalic = sal_False;
+ sal_Bool bInsert = sal_False;
+ FontInfo aInfo;
+ while ( hFontInfo )
+ {
+ aInfo = pList->GetFontInfo( hFontInfo );
+
+ FontWeight eWeight = aInfo.GetWeight();
+ FontItalic eItalic = aInfo.GetItalic();
+ FontWidth eWidth = aInfo.GetWidthType();
+ // Only if the attributes are different, we insert the
+ // Font to avoid double Entries in different languages
+ if ( (eWeight != eLastWeight) || (eItalic != eLastItalic) ||
+ (eWidth != eLastWidth) )
+ {
+ if ( bInsert )
+ {
+ InsertItem( nId, aStyleText,
+ MIB_RADIOCHECK | MIB_AUTOCHECK, nPos );
+ nPos++;
+ nId++;
+ }
+
+ if ( eWeight <= WEIGHT_NORMAL )
+ {
+ if ( eItalic != ITALIC_NONE )
+ bItalic = sal_True;
+ else
+ bNormal = sal_True;
+ }
+ else
+ {
+ if ( eItalic != ITALIC_NONE )
+ bBoldItalic = sal_True;
+ else
+ bBold = sal_True;
+ }
+
+ // For wrong StyleNames we replace this with the correct once
+ aStyleText = pList->GetStyleName( aInfo );
+ bInsert = !ImplIsAlreadyInserted( aStyleText, nPos );
+ if ( !bInsert )
+ {
+ aStyleText = pList->GetStyleName( eWeight, eItalic );
+ bInsert = !ImplIsAlreadyInserted( aStyleText, nPos );
+ }
+
+ eLastWeight = eWeight;
+ eLastItalic = eItalic;
+ eLastWidth = eWidth;
+ }
+ else
+ {
+ if ( bInsert )
+ {
+ // If we have two names for the same attributes
+ // we prefer the translated standard names
+ const XubString& rAttrStyleText = pList->GetStyleName( eWeight, eItalic );
+ if ( rAttrStyleText != aStyleText )
+ {
+ XubString aTempStyleText = pList->GetStyleName( aInfo );
+ if ( rAttrStyleText == aTempStyleText )
+ aStyleText = rAttrStyleText;
+ bInsert = !ImplIsAlreadyInserted( aStyleText, nPos );
+ }
+ }
+ }
+
+ if ( !bItalic && (aStyleText == pList->GetItalicStr()) )
+ bItalic = sal_True;
+ else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
+ bBold = sal_True;
+ else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
+ bBoldItalic = sal_True;
+
+ hFontInfo = pList->GetNextFontInfo( hFontInfo );
+ }
+
+ if ( bInsert )
+ {
+ InsertItem( nId, aStyleText,
+ MIB_RADIOCHECK | MIB_AUTOCHECK, nPos );
+ nPos++;
+ nId++;
+ }
+
+ // Bestimmte Styles als Nachbildung
+ if ( bNormal )
+ {
+ if ( !bItalic )
+ {
+ InsertItem( nId, pList->GetItalicStr(),
+ MIB_RADIOCHECK | MIB_AUTOCHECK, nPos );
+ nPos++;
+ nId++;
+ }
+ if ( !bBold )
+ {
+ InsertItem( nId, pList->GetBoldStr(),
+ MIB_RADIOCHECK | MIB_AUTOCHECK, nPos );
+ nPos++;
+ nId++;
+ }
+ }
+ if ( !bBoldItalic )
+ {
+ if ( bNormal || bItalic || bBold )
+ {
+ InsertItem( nId, pList->GetBoldItalicStr(),
+ MIB_RADIOCHECK | MIB_AUTOCHECK, nPos );
+ nPos++;
+ nId++;
+ }
+ }
+ }
+ else
+ {
+ // Wenn Font nicht, dann Standard-Styles einfuegen
+ InsertItem( FONTSTYLEMENU_FIRSTID, pList->GetNormalStr(),
+ MIB_RADIOCHECK | MIB_AUTOCHECK, 0 );
+ InsertItem( FONTSTYLEMENU_FIRSTID+1, pList->GetItalicStr(),
+ MIB_RADIOCHECK | MIB_AUTOCHECK, 0 );
+ InsertItem( FONTSTYLEMENU_FIRSTID+2, pList->GetBoldStr(),
+ MIB_RADIOCHECK | MIB_AUTOCHECK, 0 );
+ InsertItem( FONTSTYLEMENU_FIRSTID+3, pList->GetBoldItalicStr(),
+ MIB_RADIOCHECK | MIB_AUTOCHECK, 0 );
+ }
+
+ SetCurStyle( maCurStyle );
+}
+
+// -----------------------------------------------------------------------
+
+void FontStyleMenu::SetCurStyle( const XubString& rStyle )
+{
+ maCurStyle = rStyle;
+
+ // Menueintrag checken
+ sal_uInt16 nChecked = 0;
+ sal_uInt16 nItemCount = GetItemCount();
+ for( sal_uInt16 i = 0; i < nItemCount; i++ )
+ {
+ sal_uInt16 nItemId = GetItemId( i );
+
+ if ( (nItemId < FONTSTYLEMENU_FIRSTID) ||
+ (nItemId > FONTSTYLEMENU_LASTID) )
+ break;
+
+ if ( IsItemChecked( nItemId ) )
+ nChecked = nItemId;
+
+ XubString aText = GetItemText( nItemId );
+ if ( aText == maCurStyle )
+ {
+ CheckItem( nItemId, sal_True );
+ return;
+ }
+ }
+
+ if ( nChecked )
+ CheckItem( nChecked, sal_False );
+}
+
+// ========================================================================
+
+FontSizeMenu::FontSizeMenu()
+: mpHeightAry( NULL )
+, mnCurHeight( 100 )
+{
+ SetMenuFlags( GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
+}
+
+// -----------------------------------------------------------------------
+
+FontSizeMenu::~FontSizeMenu()
+{
+ if ( mpHeightAry )
+ delete[] mpHeightAry;
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeMenu::Select()
+{
+ const sal_uInt16 nCurItemId = GetCurItemId();
+ mnCurHeight = mpHeightAry[ nCurItemId - 1 ];
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeMenu::Highlight()
+{
+ const long nTempHeight = mnCurHeight;
+ const sal_uInt16 nCurItemId = GetCurItemId();
+ if ( !nCurItemId )
+ mnCurHeight = 0;
+ else
+ {
+ //sal_Int32 nValue = GetItemText( nCurItemId ).ToInt32();
+ mnCurHeight = mpHeightAry[ nCurItemId - 1 ];
+ }
+ maHighlightHdl.Call( this );
+ mnCurHeight = nTempHeight;
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeMenu::Fill( const FontInfo& rInfo, const FontList* pList )
+{
+ Clear();
+
+ // setup font size array
+ if ( mpHeightAry )
+ delete[] mpHeightAry;
+
+ const long* pTempAry;
+ const long* pAry = pList->GetSizeAry( rInfo );
+ sal_uInt16 nSizeCount = 0;
+ while ( pAry[nSizeCount] )
+ nSizeCount++;
+
+ sal_uInt16 nPos = 0;
+
+ // first insert font size names (for simplified/traditional chinese)
+ FontSizeNames aFontSizeNames( Application::GetSettings().GetUILanguage() );
+ mpHeightAry = new long[nSizeCount+aFontSizeNames.Count()];
+ if ( !aFontSizeNames.IsEmpty() )
+ {
+ if ( pAry == pList->GetStdSizeAry() )
+ {
+ // for scalable fonts all font size names
+ sal_uLong nCount = aFontSizeNames.Count();
+ for( sal_uLong i = 0; i < nCount; i++ )
+ {
+ String aSizeName = aFontSizeNames.GetIndexName( i );
+ long nSize = aFontSizeNames.GetIndexSize( i );
+ mpHeightAry[nPos] = nSize;
+ nPos++; // Id is nPos+1
+ InsertItem( nPos, aSizeName, MIB_RADIOCHECK | MIB_AUTOCHECK );
+ }
+ }
+ else
+ {
+ // for fixed size fonts only selectable font size names
+ pTempAry = pAry;
+ while ( *pTempAry )
+ {
+ String aSizeName = aFontSizeNames.Size2Name( *pTempAry );
+ if ( aSizeName.Len() )
+ {
+ mpHeightAry[nPos] = *pTempAry;
+ nPos++; // Id is nPos+1
+ InsertItem( nPos, aSizeName, MIB_RADIOCHECK | MIB_AUTOCHECK );
+ }
+ pTempAry++;
+ }
+ }
+ }
+
+ // then insert numerical font size values
+ const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
+ pTempAry = pAry;
+ while ( *pTempAry )
+ {
+ mpHeightAry[nPos] = *pTempAry;
+ nPos++; // Id is nPos+1
+ InsertItem( nPos, rI18nHelper.GetNum( *pTempAry, 1, sal_True, sal_False ), MIB_RADIOCHECK | MIB_AUTOCHECK );
+ pTempAry++;
+ }
+
+ SetCurHeight( mnCurHeight );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeMenu::SetCurHeight( long nHeight )
+{
+ mnCurHeight = nHeight;
+
+ // check menue item
+ XubString aHeight = Application::GetSettings().GetUILocaleI18nHelper().GetNum( nHeight, 1, sal_True, sal_False );
+ sal_uInt16 nChecked = 0;
+ sal_uInt16 nItemCount = GetItemCount();
+ for( sal_uInt16 i = 0; i < nItemCount; i++ )
+ {
+ sal_uInt16 nItemId = GetItemId( i );
+
+ if ( mpHeightAry[i] == nHeight )
+ {
+ CheckItem( nItemId, sal_True );
+ return;
+ }
+
+ if ( IsItemChecked( nItemId ) )
+ nChecked = nItemId;
+ }
+
+ if ( nChecked )
+ CheckItem( nChecked, sal_False );
+}
diff --git a/svtools/source/control/svxbox.cxx b/svtools/source/control/svxbox.cxx
new file mode 100755
index 000000000000..451837026dbe
--- /dev/null
+++ b/svtools/source/control/svxbox.cxx
@@ -0,0 +1,617 @@
+/*************************************************************************
+ *
+ * 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 <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <svtools/svxbox.hxx>
+#include <unotools/charclass.hxx>
+
+// -----------------------------------------------------------------------
+
+SV_IMPL_PTRARR(SvxEntryLst, SvxBoxEntry*)
+
+/*--------------------------------------------------------------------
+ Beschreibung: Ein ListboxElement
+ --------------------------------------------------------------------*/
+
+SvxBoxEntry::SvxBoxEntry() :
+ nId(LISTBOX_ENTRY_NOTFOUND),
+ bModified(sal_False),
+ bNew(sal_False)
+{
+}
+
+
+SvxBoxEntry::SvxBoxEntry(const String& aNam, sal_uInt16 nIdx) :
+ aName(aNam),
+ nId(nIdx),
+ bModified(sal_False),
+ bNew(sal_False)
+{
+}
+
+
+SvxBoxEntry::SvxBoxEntry(const SvxBoxEntry& rOld) :
+ aName(rOld.aName),
+ nId(rOld.nId),
+ bModified(rOld.bModified),
+ bNew(rOld.bNew)
+{
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung:
+ --------------------------------------------------------------------*/
+
+SvxListBox::SvxListBox(Window* pParent, WinBits nBits) :
+ ListBox(pParent, nBits)
+{
+ InitListBox();
+}
+
+
+SvxListBox::SvxListBox(Window* pParent, const ResId& rId):
+ ListBox(pParent, rId)
+{
+ InitListBox();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Basisklasse Dtor
+ --------------------------------------------------------------------*/
+
+__EXPORT SvxListBox::~SvxListBox()
+{
+ aEntryLst.DeleteAndDestroy(0, aEntryLst.Count());
+ aDelEntryLst.DeleteAndDestroy(0, aDelEntryLst.Count());
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Evtl. Liste aus der Ressource beachten
+ --------------------------------------------------------------------*/
+
+void SvxListBox::InitListBox()
+{
+ // Verwaltung fuer die Stringlist aus der Resource aufbauen
+ sal_uInt16 nSize = GetEntryCount();
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { const SvxBoxEntry* pTmp = new SvxBoxEntry(ListBox::GetEntry(i), i);
+ const SvxBoxEntry* &rpTmp = pTmp;
+ aEntryLst.Insert(rpTmp, aEntryLst.Count());
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: neue Eintraege verwalten
+ --------------------------------------------------------------------*/
+
+void SvxListBox::InsertNewEntry(const SvxBoxEntry& rEntry)
+{
+ SvxBoxEntry* pNew = new SvxBoxEntry(rEntry);
+ pNew->bNew = sal_True;
+ InsertSorted(pNew);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eintrag in die ListBox aufnehmen
+ --------------------------------------------------------------------*/
+
+void SvxListBox::InsertEntry(const SvxBoxEntry& rEntry, sal_uInt16 nPos)
+{
+ if(nPos != LISTBOX_ENTRY_NOTFOUND)
+ {
+ SvxBoxEntry* pEntry = new SvxBoxEntry(rEntry);
+ ListBox::InsertEntry(pEntry->aName, nPos);
+ //const SvxBoxEntry* &rpEntry = pEntry;
+ aEntryLst.C40_INSERT(SvxBoxEntry, pEntry, nPos);
+ }
+ else
+ InsertSorted(new SvxBoxEntry(rEntry));
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eintrag aus der Liste loeschen
+ --------------------------------------------------------------------*/
+
+void SvxListBox::RemoveEntry(sal_uInt16 nPos)
+{
+ if(nPos >= aEntryLst.Count())
+ return;
+
+ // Altes Element austragen
+ SvxBoxEntry* pEntry = aEntryLst[nPos];
+ aEntryLst.Remove(nPos, 1);
+ ListBox::RemoveEntry(nPos);
+
+ // keine neuen Eintraege in die Liste mit aufnehmen
+ if(pEntry->bNew)
+ return;
+
+ // in DeleteListe eintragen
+ aDelEntryLst.C40_INSERT(SvxBoxEntry, pEntry, aDelEntryLst.Count());
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eintrag ueber konkretes Obkjekt loeschen
+ --------------------------------------------------------------------*/
+
+void SvxListBox::RemoveEntry(const SvxBoxEntry& rEntry)
+{
+ sal_uInt16 nPos = ListBox::GetEntryPos(rEntry.aName);
+ RemoveEntry(nPos);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Listen loeschen und Anzeige loeschen
+ --------------------------------------------------------------------*/
+
+void SvxListBox::Clear()
+{
+ ListBox::Clear();
+ aEntryLst.DeleteAndDestroy(0, aEntryLst.Count());
+ aDelEntryLst.DeleteAndDestroy(0, aDelEntryLst.Count());
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Position by Name
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxListBox::GetEntryPos(const SvxBoxEntry& rEntry) const
+{
+ return ListBox::GetEntryPos(rEntry.aName);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Rund um die Entries
+ --------------------------------------------------------------------*/
+
+const SvxBoxEntry& SvxListBox::GetSvxBoxEntry(sal_uInt16 nPos) const
+{
+ if(nPos < aEntryLst.Count())
+ return *aEntryLst[nPos];
+ else
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: aktullen Eintrag zurueckgeben
+ --------------------------------------------------------------------*/
+
+const SvxBoxEntry& SvxListBox::GetSelectSvxBoxEntry(sal_uInt16 nSelId) const
+{
+ String aName(ListBox::GetSelectEntry(nSelId));
+
+ if(aName.Len() > 0)
+ {
+ for (sal_uInt16 i=0; i < aEntryLst.Count(); i++)
+ {
+ if(aEntryLst[i]->aName == aName )
+ return *aEntryLst[i];
+ }
+ }
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: modifizierte Eintraege
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxListBox::GetModifiedCount() const
+{
+ sal_uInt16 nMod = 0;
+ sal_uInt16 nSize = aEntryLst.Count();
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bModified)
+ nMod++;
+ }
+ return nMod;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Modifizierte Eintraege behandeln
+ --------------------------------------------------------------------*/
+
+void SvxListBox::ModifyEntry(sal_uInt16 nPos, const String& rName)
+{
+ if(nPos >= aEntryLst.Count())
+ return;
+
+ SvxBoxEntry* pEntry = aEntryLst[nPos];
+ aEntryLst.Remove(nPos, 1);
+ aEntryLst[nPos]->aName = rName;
+ aEntryLst[nPos]->bModified = sal_True;
+ ListBox::RemoveEntry(nPos);
+
+ InsertSorted(pEntry);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: alle modifizierten Eintraege bahandeln
+ --------------------------------------------------------------------*/
+
+const SvxBoxEntry& SvxListBox::GetModifiedEntry(sal_uInt16 nPos) const
+{
+ sal_uInt16 nSize = aEntryLst.Count();
+ sal_uInt16 nMod = 0;
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bModified)
+ { if(nMod == nPos)
+ return *aEntryLst[i];
+ nMod++;
+ }
+ }
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: geloeschte Eintraege
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxListBox::GetRemovedCount() const
+{
+ return aDelEntryLst.Count();
+}
+
+
+const SvxBoxEntry& SvxListBox::GetRemovedEntry(sal_uInt16 nPos) const
+{
+ if(nPos < aDelEntryLst.Count())
+ return *aDelEntryLst[nPos];
+
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Neue Entries begutachten
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxListBox::GetNewCount() const
+{
+ sal_uInt16 nNew = 0;
+ sal_uInt16 nSize = aEntryLst.Count();
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bNew)
+ nNew++;
+ }
+ return nNew;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle neuen Eintraege ueberpruefen
+ --------------------------------------------------------------------*/
+
+const SvxBoxEntry& SvxListBox::GetNewEntry(sal_uInt16 nPos) const
+{
+ sal_uInt16 nSize = aEntryLst.Count();
+ sal_uInt16 nNew = 0;
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bNew)
+ { if(nNew == nPos)
+ return *aEntryLst[i];
+ nNew++;
+ }
+ }
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortiert einfuegen
+ --------------------------------------------------------------------*/
+
+void SvxListBox::InsertSorted(SvxBoxEntry* pEntry)
+{
+ ListBox::InsertEntry(pEntry->aName);
+ sal_uInt16 nPos = ListBox::GetEntryPos(pEntry->aName);
+ aEntryLst.C40_INSERT(SvxBoxEntry, pEntry, nPos);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: ComboBoxen mit Verwaltungseinheit
+ --------------------------------------------------------------------*/
+
+SvxComboBox::SvxComboBox(Window* pParent, WinBits nBits, sal_uInt16 nStyleBits) :
+ ComboBox(pParent, nBits),
+ nStyle(nStyleBits)
+{
+ InitComboBox();
+}
+
+
+SvxComboBox::SvxComboBox(Window* pParent, const ResId& rId, sal_uInt16 nStyleBits ):
+ ComboBox(pParent, rId),
+ nStyle(nStyleBits)
+{
+ InitComboBox();
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Basisklasse Dtor
+ --------------------------------------------------------------------*/
+
+__EXPORT SvxComboBox::~SvxComboBox()
+{
+ aEntryLst.DeleteAndDestroy(0, aEntryLst.Count());
+ aDelEntryLst.DeleteAndDestroy(0, aDelEntryLst.Count());
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Evtl. Liste aus der Ressource beachten
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::InitComboBox()
+{
+ // Verwaltung fuer die Stringlist aus der Resource aufbauen
+ sal_uInt16 nSize = GetEntryCount();
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { const SvxBoxEntry* pTmp = new SvxBoxEntry(ComboBox::GetEntry(i), i);
+ const SvxBoxEntry* &rpTmp = pTmp;
+ aEntryLst.Insert(rpTmp, aEntryLst.Count());
+ }
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: neue Eintraege verwalten
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::InsertNewEntry(const SvxBoxEntry& rEntry)
+{
+ SvxBoxEntry* pNew = new SvxBoxEntry(rEntry);
+ pNew->bNew = sal_True;
+ InsertSorted(pNew);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eintrag in die ComboBox aufnehmen
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::InsertEntry(const SvxBoxEntry& rEntry)
+{
+ InsertSorted(new SvxBoxEntry(rEntry));
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eintrag aus der Liste loeschen
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::RemoveEntry(sal_uInt16 nPos)
+{
+ if(nPos >= aEntryLst.Count())
+ return;
+
+ // Altes Element austragen
+ SvxBoxEntry* pEntry = aEntryLst[nPos];
+ aEntryLst.Remove(nPos, 1);
+ ComboBox::RemoveEntry(nPos);
+
+ // keine neuen Eintraege in die Liste mit aufnehmen
+ if(pEntry->bNew)
+ return;
+
+ // in DeleteListe eintragen
+ aDelEntryLst.C40_INSERT(SvxBoxEntry, pEntry, aDelEntryLst.Count());
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Eintrag ueber konkretes Obkjekt loeschen
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::RemoveEntry(const SvxBoxEntry& rEntry)
+{
+ sal_uInt16 nPos = ComboBox::GetEntryPos(rEntry.aName);
+ RemoveEntry(nPos);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Listen loeschen und Anzeige loeschen
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::Clear()
+{
+ ComboBox::Clear();
+ aEntryLst.DeleteAndDestroy(0, aEntryLst.Count());
+ aDelEntryLst.DeleteAndDestroy(0, aDelEntryLst.Count());
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Position by Name
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxComboBox::GetEntryPos(const SvxBoxEntry& rEntry) const
+{
+ return ComboBox::GetEntryPos(rEntry.aName);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Rund um die Entries
+ --------------------------------------------------------------------*/
+
+const SvxBoxEntry& SvxComboBox::GetEntry(sal_uInt16 nPos) const
+{
+ if(nPos < aEntryLst.Count())
+ return *aEntryLst[nPos];
+ else
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: modifizierte Eintraege
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxComboBox::GetModifiedCount() const
+{
+ sal_uInt16 nMod = 0;
+ sal_uInt16 nSize = aEntryLst.Count();
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bModified)
+ nMod++;
+ }
+ return nMod;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Modifizierte Eintraege behandeln
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::ModifyEntry(sal_uInt16 nPos, const String& rName)
+{
+ if(nPos >= aEntryLst.Count())
+ return;
+
+ SvxBoxEntry* pEntry = aEntryLst[nPos];
+ aEntryLst.Remove(nPos, 1);
+ aEntryLst[nPos]->aName = rName;
+ aEntryLst[nPos]->bModified = sal_True;
+ ComboBox::RemoveEntry(nPos);
+
+ InsertSorted(pEntry);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: alle modifizierten Eintraege bahandeln
+ --------------------------------------------------------------------*/
+
+const SvxBoxEntry& SvxComboBox::GetModifiedEntry(sal_uInt16 nPos) const
+{
+ sal_uInt16 nSize = aEntryLst.Count();
+ sal_uInt16 nMod = 0;
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bModified)
+ { if(nMod == nPos)
+ return *aEntryLst[i];
+ nMod++;
+ }
+ }
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: geloeschte Eintraege
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxComboBox::GetRemovedCount() const
+{
+ return aDelEntryLst.Count();
+}
+
+
+const SvxBoxEntry& SvxComboBox::GetRemovedEntry(sal_uInt16 nPos) const
+{
+ if(nPos < aDelEntryLst.Count())
+ return *aDelEntryLst[nPos];
+
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Neue Entries begutachten
+ --------------------------------------------------------------------*/
+
+sal_uInt16 SvxComboBox::GetNewCount() const
+{
+ sal_uInt16 nNew = 0;
+ sal_uInt16 nSize = aEntryLst.Count();
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bNew)
+ nNew++;
+ }
+ return nNew;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Alle neuen Eintraege ueberpruefen
+ --------------------------------------------------------------------*/
+
+const SvxBoxEntry& SvxComboBox::GetNewEntry(sal_uInt16 nPos) const
+{
+ sal_uInt16 nSize = aEntryLst.Count();
+ sal_uInt16 nNew = 0;
+ for(sal_uInt16 i=0; i < nSize; ++i)
+ { if(aEntryLst[i]->bNew)
+ { if(nNew == nPos)
+ return *aEntryLst[i];
+ nNew++;
+ }
+ }
+ return aDefault;
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Sortiert einfuegen
+ --------------------------------------------------------------------*/
+
+void SvxComboBox::InsertSorted(SvxBoxEntry* pEntry)
+{
+ ComboBox::InsertEntry(pEntry->aName);
+ sal_uInt16 nPos = ComboBox::GetEntryPos(pEntry->aName);
+ aEntryLst.C40_INSERT(SvxBoxEntry, pEntry, nPos);
+}
+
+
+/*--------------------------------------------------------------------
+ Beschreibung: Je nach Option bestimmte Zeichen ausblenden
+ --------------------------------------------------------------------*/
+
+void __EXPORT SvxComboBox::KeyInput( const KeyEvent& rKEvt )
+{
+ sal_Unicode cChar = rKEvt.GetCharCode();
+
+ if(nStyle & SVX_CBS_FILENAME)
+ {
+#if defined UNX
+ if( cChar == sal_Unicode( '/' ) || cChar == sal_Unicode( ' ' ) )
+ return;
+#else
+ if( cChar == sal_Unicode( ':' ) || cChar == sal_Unicode( '\\' ) ||
+ cChar == sal_Unicode( '.' ) || cChar == sal_Unicode( ' ' ) )
+ return;
+#endif
+ }
+ ComboBox::KeyInput(rKEvt);
+}
+
+/*--------------------------------------------------------------------
+ Beschreibung: Text nach Option konvertieren
+ --------------------------------------------------------------------*/
+
+String SvxComboBox::GetText() const
+{
+ String aTxt(ComboBox::GetText());
+ CharClass aCharClass( Application::GetSettings().GetLocale() );
+
+ if(nStyle & SVX_CBS_LOWER)
+ return aCharClass.lower(aTxt);
+
+ if(nStyle & SVX_CBS_UPPER)
+ return aCharClass.upper(aTxt);
+
+ return aTxt;
+}
+
+
diff --git a/svtools/source/control/tabbar.cxx b/svtools/source/control/tabbar.cxx
new file mode 100755
index 000000000000..b7511d24b5c8
--- /dev/null
+++ b/svtools/source/control/tabbar.cxx
@@ -0,0 +1,2745 @@
+/*************************************************************************
+ *
+ * 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 <svtools/tabbar.hxx>
+#include <tools/time.hxx>
+#include <tools/debug.hxx>
+#include <tools/poly.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/help.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/button.hxx>
+#include <vcl/edit.hxx>
+#include "svtaccessiblefactory.hxx"
+#include <filectrl.hrc>
+#include <svtools/svtdata.hxx>
+#include <limits>
+
+// =======================================================================
+
+#define TABBAR_OFFSET_X 7
+#define TABBAR_OFFSET_X2 2
+#define TABBAR_DRAG_SCROLLOFF 5
+#define TABBAR_MINSIZE 5
+
+const sal_uInt16 ADDNEWPAGE_AREAWIDTH = 10;
+
+// =======================================================================
+
+struct ImplTabBarItem
+{
+ sal_uInt16 mnId;
+ TabBarPageBits mnBits;
+ XubString maText;
+ XubString maHelpText;
+ Rectangle maRect;
+ long mnWidth;
+ rtl::OString maHelpId;
+ sal_Bool mbShort;
+ sal_Bool mbSelect;
+ sal_Bool mbEnable;
+ Color maTabBgColor;
+ bool IsDefaultTabBgColor() const { return maTabBgColor == Color(COL_AUTO) ? sal_True : sal_False; };
+ Color maTabTextColor;
+ bool IsDefaultTabTextColor() const { return maTabTextColor == Color(COL_AUTO) ? sal_True : sal_False; };
+
+ ImplTabBarItem( sal_uInt16 nItemId, const XubString& rText,
+ TabBarPageBits nPageBits ) :
+ maText( rText )
+ {
+ mnId = nItemId;
+ mnBits = nPageBits;
+ mnWidth = 0;
+ mbShort = sal_False;
+ mbSelect = sal_False;
+ mbEnable = sal_True;
+ maTabBgColor = Color( COL_AUTO );
+ maTabTextColor = Color( COL_AUTO );
+ }
+};
+
+DECLARE_LIST( ImplTabBarList, ImplTabBarItem* )
+
+// =======================================================================
+
+// -----------------
+// - ImplTabButton -
+// -----------------
+
+class ImplTabButton : public PushButton
+{
+public:
+ ImplTabButton( TabBar* pParent, WinBits nWinStyle = 0 ) :
+ PushButton( pParent, nWinStyle | WB_RECTSTYLE | WB_SMALLSTYLE | WB_NOLIGHTBORDER | WB_NOPOINTERFOCUS ) {}
+
+ TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
+
+ virtual long PreNotify( NotifyEvent& rNEvt );
+};
+
+// =======================================================================
+
+long ImplTabButton::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
+ {
+ if ( GetParent()->IsInEditMode() )
+ {
+ GetParent()->EndEditMode();
+ return sal_True;
+ }
+ }
+
+ return PushButton::PreNotify( rNEvt );
+}
+
+// =======================================================================
+
+// ----------------
+// - ImplTabSizer -
+// ----------------
+
+class ImplTabSizer : public Window
+{
+public:
+ ImplTabSizer( TabBar* pParent, WinBits nWinStyle = 0 );
+
+ TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
+
+private:
+ void ImplTrack( const Point& rScreenPos );
+
+ virtual void MouseButtonDown( const MouseEvent& rMEvt );
+ virtual void Tracking( const TrackingEvent& rTEvt );
+ virtual void Paint( const Rectangle& rRect );
+
+ Point maStartPos;
+ long mnStartWidth;
+};
+
+// -----------------------------------------------------------------------
+
+ImplTabSizer::ImplTabSizer( TabBar* pParent, WinBits nWinStyle ) :
+ Window( pParent, nWinStyle & WB_3DLOOK )
+{
+ SetPointer( Pointer( POINTER_HSIZEBAR ) );
+ SetSizePixel( Size( 7, 0 ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTabSizer::ImplTrack( const Point& rScreenPos )
+{
+ TabBar* pParent = GetParent();
+ long nDiff = rScreenPos.X() - maStartPos.X();
+ pParent->mnSplitSize = mnStartWidth + (pParent->IsMirrored() ? -nDiff : nDiff);
+ if ( pParent->mnSplitSize < TABBAR_MINSIZE )
+ pParent->mnSplitSize = TABBAR_MINSIZE;
+ pParent->Split();
+ pParent->Update();
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTabSizer::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( GetParent()->IsInEditMode() )
+ {
+ GetParent()->EndEditMode();
+ return;
+ }
+
+ if ( rMEvt.IsLeft() )
+ {
+ maStartPos = OutputToScreenPixel( rMEvt.GetPosPixel() );
+ mnStartWidth = GetParent()->GetSizePixel().Width();
+ StartTracking();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTabSizer::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( rTEvt.IsTrackingCanceled() )
+ ImplTrack( maStartPos );
+ GetParent()->mnSplitSize = 0;
+ }
+ else
+ ImplTrack( OutputToScreenPixel( rTEvt.GetMouseEvent().GetPosPixel() ) );
+}
+
+// -----------------------------------------------------------------------
+
+void ImplTabSizer::Paint( const Rectangle& )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ DecorationView aDecoView( this );
+ long nOffX = 0;
+ Size aOutputSize = GetOutputSizePixel();
+
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ DrawLine( Point( 0, 0 ), Point( 0, aOutputSize.Height()-1 ) );
+ nOffX++;
+ aOutputSize.Width()--;
+ }
+ aDecoView.DrawButton( Rectangle( Point( nOffX, 0 ), aOutputSize ), BUTTON_DRAW_NOLIGHTBORDER );
+}
+
+// =======================================================================
+
+// Heisst nicht Impl, da evtl. mal von aussen benutz- und ueberladbar
+
+// --------------
+// - TabBarEdit -
+// --------------
+
+class TabBarEdit : public Edit
+{
+private:
+ Timer maLoseFocusTimer;
+ sal_Bool mbPostEvt;
+
+ DECL_LINK( ImplEndEditHdl, void* );
+ DECL_LINK( ImplEndTimerHdl, void* );
+
+public:
+ TabBarEdit( TabBar* pParent, WinBits nWinStyle = 0 );
+
+ TabBar* GetParent() const { return (TabBar*)Window::GetParent(); }
+
+ void SetPostEvent() { mbPostEvt = sal_True; }
+ void ResetPostEvent() { mbPostEvt = sal_False; }
+
+ virtual long PreNotify( NotifyEvent& rNEvt );
+ virtual void LoseFocus();
+};
+
+// -----------------------------------------------------------------------
+
+TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) :
+ Edit( pParent, nWinStyle )
+{
+ mbPostEvt = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+long TabBarEdit::PreNotify( NotifyEvent& rNEvt )
+{
+ if ( rNEvt.GetType() == EVENT_KEYINPUT )
+ {
+ const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
+ if ( !pKEvt->GetKeyCode().GetModifier() )
+ {
+ if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN )
+ {
+ if ( !mbPostEvt )
+ {
+ if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
+ mbPostEvt = sal_True;
+ }
+ return sal_True;
+ }
+ else if ( pKEvt->GetKeyCode().GetCode() == KEY_ESCAPE )
+ {
+ if ( !mbPostEvt )
+ {
+ if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_True ) )
+ mbPostEvt = sal_True;
+ }
+ return sal_True;
+ }
+ }
+ }
+
+ return Edit::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBarEdit::LoseFocus()
+{
+ if ( !mbPostEvt )
+ {
+ if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)sal_False ) )
+ mbPostEvt = sal_True;
+ }
+
+ Edit::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( TabBarEdit, ImplEndEditHdl, void*, pCancel )
+{
+ ResetPostEvent();
+ maLoseFocusTimer.Stop();
+
+ // We need this query, because the edit get a losefous event,
+ // when it shows the context menu or the insert symbol dialog
+ if ( !HasFocus() && HasChildPathFocus( sal_True ) )
+ {
+ maLoseFocusTimer.SetTimeout( 30 );
+ maLoseFocusTimer.SetTimeoutHdl( LINK( this, TabBarEdit, ImplEndTimerHdl ) );
+ maLoseFocusTimer.Start();
+ }
+ else
+ GetParent()->EndEditMode( pCancel != 0 );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( TabBarEdit, ImplEndTimerHdl, void*, EMPTYARG )
+{
+ if ( HasFocus() )
+ return 0;
+
+ // We need this query, because the edit get a losefous event,
+ // when it shows the context menu or the insert symbol dialog
+ if ( HasChildPathFocus( sal_True ) )
+ maLoseFocusTimer.Start();
+ else
+ GetParent()->EndEditMode( sal_True );
+
+ return 0;
+}
+
+// =======================================================================
+struct TabBar_Impl
+{
+ ImplTabSizer* mpSizer;
+ ::svt::AccessibleFactoryAccess maAccessibleFactory;
+
+ TabBar_Impl()
+ :mpSizer( NULL )
+ {
+ }
+ ~TabBar_Impl()
+ {
+ delete mpSizer;
+ }
+};
+
+// =======================================================================
+
+const sal_uInt16 TabBar::APPEND = ::std::numeric_limits<sal_uInt16>::max();
+const sal_uInt16 TabBar::PAGE_NOT_FOUND = ::std::numeric_limits<sal_uInt16>::max();
+
+void TabBar::ImplInit( WinBits nWinStyle )
+{
+ mpItemList = new ImplTabBarList;
+ mpFirstBtn = NULL;
+ mpPrevBtn = NULL;
+ mpNextBtn = NULL;
+ mpLastBtn = NULL;
+ mpImpl = new TabBar_Impl;
+ mpEdit = NULL;
+ mnMaxPageWidth = 0;
+ mnCurMaxWidth = 0;
+ mnOffX = 0;
+ mnOffY = 0;
+ mnLastOffX = 0;
+ mnSplitSize = 0;
+ mnSwitchTime = 0;
+ mnWinStyle = nWinStyle;
+ mnCurPageId = 0;
+ mnFirstPos = 0;
+ mnDropPos = 0;
+ mnSwitchId = 0;
+ mnEditId = 0;
+ mbFormat = sal_True;
+ mbFirstFormat = sal_True;
+ mbSizeFormat = sal_True;
+ mbAutoMaxWidth = sal_True;
+ mbInSwitching = sal_False;
+ mbAutoEditMode = sal_False;
+ mbEditCanceled = sal_False;
+ mbDropPos = sal_False;
+ mbInSelect = sal_False;
+ mbSelColor = sal_False;
+ mbSelTextColor = sal_False;
+ mbMirrored = sal_False;
+
+ if ( nWinStyle & WB_3DTAB )
+ mnOffY++;
+
+ ImplInitControls();
+
+ if(mpFirstBtn)
+ mpFirstBtn->SetAccessibleName(String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVET0HOME)));
+ if(mpPrevBtn)
+ mpPrevBtn->SetAccessibleName( String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVELEFT)));
+ if(mpNextBtn)
+ mpNextBtn->SetAccessibleName(String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVERIGHT)));
+ if(mpLastBtn)
+ mpLastBtn->SetAccessibleName( String(SvtResId(STR_TABBAR_PUSHBUTTON_MOVETOEND)));
+
+ SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
+ ImplInitSettings( sal_True, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+TabBar::TabBar( Window* pParent, WinBits nWinStyle ) :
+ Window( pParent, (nWinStyle & WB_3DLOOK) | WB_CLIPCHILDREN )
+{
+ ImplInit( nWinStyle );
+}
+
+// -----------------------------------------------------------------------
+
+TabBar::~TabBar()
+{
+ EndEditMode( sal_True );
+
+ // Controls loeschen
+ if ( mpPrevBtn )
+ delete mpPrevBtn;
+ if ( mpNextBtn )
+ delete mpNextBtn;
+ if ( mpFirstBtn )
+ delete mpFirstBtn;
+ if ( mpLastBtn )
+ delete mpLastBtn;
+ delete mpImpl;
+
+ // Alle Items loeschen
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Itemlist loeschen
+ delete mpItemList;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplInitSettings( sal_Bool bFont, sal_Bool bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aToolFont;
+ aToolFont = rStyleSettings.GetToolFont();
+ if ( IsControlFont() )
+ aToolFont.Merge( GetControlFont() );
+ aToolFont.SetWeight( WEIGHT_BOLD );
+ SetZoomedPointFont( aToolFont );
+
+ // Font in der groesse Anpassen, wenn Fenster zu klein?
+ while ( GetTextHeight() > (GetOutputSizePixel().Height()-1) )
+ {
+ Font aFont = GetFont();
+ if ( aFont.GetHeight() <= 6 )
+ break;
+ aFont.SetHeight( aFont.GetHeight()-1 );
+ SetFont( aFont );
+ }
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else
+ aColor = rStyleSettings.GetFaceColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplGetColors( Color& rFaceColor, Color& rFaceTextColor,
+ Color& rSelectColor, Color& rSelectTextColor )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( IsControlBackground() )
+ rFaceColor = GetControlBackground();
+ else
+ rFaceColor = rStyleSettings.GetInactiveTabColor();
+ if ( IsControlForeground() )
+ rFaceTextColor = GetControlForeground();
+ else
+ rFaceTextColor = rStyleSettings.GetButtonTextColor();
+ if ( mbSelColor )
+ rSelectColor = maSelColor;
+ else
+ rSelectColor = rStyleSettings.GetActiveTabColor();
+ if ( mbSelTextColor )
+ rSelectTextColor = maSelTextColor;
+ else
+ rSelectTextColor = rStyleSettings.GetWindowTextColor();
+
+ // Bei 3D-Tabs wird Selektions- und Face-Farbe umgedreht, da die
+ // selektierten Tabs in 3D erscheinen sollen
+ if ( mnWinStyle & WB_3DTAB )
+ {
+ Color aTempColor = rFaceColor;
+ rFaceColor = rSelectColor;
+ rSelectColor = aTempColor;
+ aTempColor = rFaceTextColor;
+ rFaceTextColor = rSelectTextColor;
+ rSelectTextColor = rFaceTextColor;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TabBar::ImplCalcWidth()
+{
+ // Groessen muessen nur ermittelt werden, wenn sich Text aendert oder
+ // wenn der Font geaendert wurde
+ if ( !mbSizeFormat )
+ return sal_False;
+
+ // Breiten der Tabs mit dem fetten Font ermitteln
+ Font aFont = GetFont();
+ if ( aFont.GetWeight() != WEIGHT_BOLD )
+ {
+ aFont.SetWeight( WEIGHT_BOLD );
+ SetFont( aFont );
+ }
+
+ if ( mnMaxPageWidth )
+ mnCurMaxWidth = mnMaxPageWidth;
+ else if ( mbAutoMaxWidth )
+ {
+ mnCurMaxWidth = mnLastOffX-mnOffX-
+ TABBAR_OFFSET_X-TABBAR_OFFSET_X-
+ TABBAR_OFFSET_X2-TABBAR_OFFSET_X2-TABBAR_OFFSET_X2;
+ if ( mnCurMaxWidth < 1 )
+ mnCurMaxWidth = 1;
+ }
+ else
+ mnCurMaxWidth = 0;
+
+ sal_Bool bChanged = sal_False;
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ long nNewWidth = GetTextWidth( pItem->maText );
+ if ( mnCurMaxWidth && (nNewWidth > mnCurMaxWidth) )
+ {
+ pItem->mbShort = sal_True;
+ nNewWidth = mnCurMaxWidth;
+ }
+ else
+ pItem->mbShort = sal_False;
+ nNewWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
+ if ( pItem->mnWidth != nNewWidth )
+ {
+ pItem->mnWidth = nNewWidth;
+ if ( !pItem->maRect.IsEmpty() )
+ bChanged = sal_True;
+ }
+ pItem = mpItemList->Next();
+ }
+ mbSizeFormat = sal_False;
+ mbFormat = sal_True;
+ return bChanged;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplFormat()
+{
+ ImplCalcWidth();
+
+ if ( !mbFormat )
+ return;
+
+ sal_uInt16 n = 0;
+ long x = mnOffX;
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Bei allen nicht sichtbaren Tabs, wird ein leeres Rechteck
+ // gesetzt
+ if ( (n+1 < mnFirstPos) || (x > mnLastOffX) )
+ pItem->maRect.SetEmpty();
+ else
+ {
+ // Etwas von der Tab vor der ersten sichtbaren Page
+ // muss auch zu sehen sein
+ if ( n+1 == mnFirstPos )
+ pItem->maRect.Left() = x-pItem->mnWidth;
+ else
+ {
+ pItem->maRect.Left() = x;
+ x += pItem->mnWidth;
+ }
+ pItem->maRect.Right() = x+TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
+ pItem->maRect.Bottom() = maWinSize.Height()-1;
+
+ if( mbMirrored )
+ {
+ long nTmp = mnOffX + mnLastOffX - pItem->maRect.Right();
+ pItem->maRect.Right() = mnOffX + mnLastOffX - pItem->maRect.Left();
+ pItem->maRect.Left() = nTmp;
+ }
+ }
+
+ n++;
+ pItem = mpItemList->Next();
+ }
+
+ mbFormat = sal_False;
+
+ // Button enablen/disablen
+ ImplEnableControls();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::ImplGetLastFirstPos()
+{
+ sal_uInt16 nCount = (sal_uInt16)(mpItemList->Count());
+ if ( !nCount || mbSizeFormat || mbFormat )
+ return 0;
+
+ sal_uInt16 nLastFirstPos = nCount-1;
+ long nWinWidth = mnLastOffX-mnOffX-TABBAR_OFFSET_X-ADDNEWPAGE_AREAWIDTH;
+ long nWidth = mpItemList->GetObject( nLastFirstPos )->mnWidth;
+ while ( nLastFirstPos && (nWidth < nWinWidth) )
+ {
+ nLastFirstPos--;
+ nWidth += mpItemList->GetObject( nLastFirstPos )->mnWidth;
+ }
+ if ( (nLastFirstPos != (sal_uInt16)(mpItemList->Count()-1)) &&
+ (nWidth > nWinWidth) )
+ nLastFirstPos++;
+ return nLastFirstPos;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplInitControls()
+{
+ if ( mnWinStyle & WB_SIZEABLE )
+ {
+ if ( !mpImpl->mpSizer )
+ mpImpl->mpSizer = new ImplTabSizer( this, mnWinStyle & (WB_DRAG | WB_3DLOOK) );
+ mpImpl->mpSizer->Show();
+ }
+ else
+ {
+ DELETEZ( mpImpl->mpSizer );
+ }
+
+ Link aLink = LINK( this, TabBar, ImplClickHdl );
+
+ if ( mnWinStyle & (WB_MINSCROLL | WB_SCROLL) )
+ {
+ if ( !mpPrevBtn )
+ {
+ mpPrevBtn = new ImplTabButton( this, WB_REPEAT );
+ mpPrevBtn->SetClickHdl( aLink );
+ }
+ mpPrevBtn->SetSymbol( mbMirrored ? SYMBOL_NEXT : SYMBOL_PREV );
+ mpPrevBtn->Show();
+
+ if ( !mpNextBtn )
+ {
+ mpNextBtn = new ImplTabButton( this, WB_REPEAT );
+ mpNextBtn->SetClickHdl( aLink );
+ }
+ mpNextBtn->SetSymbol( mbMirrored ? SYMBOL_PREV : SYMBOL_NEXT );
+ mpNextBtn->Show();
+ }
+ else
+ {
+ DELETEZ( mpPrevBtn );
+ DELETEZ( mpNextBtn );
+ }
+
+ if ( mnWinStyle & WB_SCROLL )
+ {
+ if ( !mpFirstBtn )
+ {
+ mpFirstBtn = new ImplTabButton( this );
+ mpFirstBtn->SetClickHdl( aLink );
+ }
+ mpFirstBtn->SetSymbol( mbMirrored ? SYMBOL_LAST : SYMBOL_FIRST );
+ mpFirstBtn->Show();
+
+ if ( !mpLastBtn )
+ {
+ mpLastBtn = new ImplTabButton( this );
+ mpLastBtn->SetClickHdl( aLink );
+ }
+ mpLastBtn->SetSymbol( mbMirrored ? SYMBOL_FIRST : SYMBOL_LAST );
+ mpLastBtn->Show();
+ }
+ else
+ {
+ DELETEZ( mpFirstBtn );
+ DELETEZ( mpLastBtn );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplEnableControls()
+{
+ if ( mbSizeFormat || mbFormat )
+ return;
+
+ // Buttons enablen/disblen
+ sal_Bool bEnableBtn = mnFirstPos > 0;
+ if ( mpFirstBtn )
+ mpFirstBtn->Enable( bEnableBtn );
+ if ( mpPrevBtn )
+ mpPrevBtn->Enable( bEnableBtn );
+
+ bEnableBtn = mnFirstPos < ImplGetLastFirstPos();
+ if ( mpNextBtn )
+ mpNextBtn->Enable( bEnableBtn );
+ if ( mpLastBtn )
+ mpLastBtn->Enable( bEnableBtn );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplShowPage( sal_uInt16 nPos )
+{
+ // Breite berechnen
+ long nWidth = GetOutputSizePixel().Width();
+ if ( nWidth >= TABBAR_OFFSET_X )
+ nWidth -= TABBAR_OFFSET_X;
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+ if ( nPos < mnFirstPos )
+ SetFirstPageId( pItem->mnId );
+ else if ( pItem->maRect.Right() > nWidth )
+ {
+ while ( pItem->maRect.Right() > nWidth )
+ {
+ sal_uInt16 nNewPos = mnFirstPos+1;
+ SetFirstPageId( GetPageId( nNewPos ) );
+ ImplFormat();
+ if ( nNewPos != mnFirstPos )
+ break;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( TabBar, ImplClickHdl, ImplTabButton*, pBtn )
+{
+ EndEditMode();
+
+ sal_uInt16 nNewPos = mnFirstPos;
+
+ if ( pBtn == mpFirstBtn )
+ nNewPos = 0;
+ else if ( pBtn == mpPrevBtn )
+ {
+ if ( mnFirstPos )
+ nNewPos = mnFirstPos-1;
+ }
+ else if ( pBtn == mpNextBtn )
+ {
+ sal_uInt16 nCount = GetPageCount();
+ if ( mnFirstPos < nCount )
+ nNewPos = mnFirstPos+1;
+ }
+ else
+ {
+ sal_uInt16 nCount = GetPageCount();
+ if ( nCount )
+ nNewPos = nCount-1;
+ }
+
+ if ( nNewPos != mnFirstPos )
+ SetFirstPageId( GetPageId( nNewPos ) );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeaveWindow() )
+ mbInSelect = sal_False;
+
+ Window::MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ // Bei Klick in unser Fenster EditModus nur beenden und Klick nicht
+ // ausfuehren
+ if ( IsInEditMode() )
+ {
+ EndEditMode();
+ return;
+ }
+
+ ImplTabBarItem* pItem;
+ sal_uInt16 nSelId = GetPageId( rMEvt.GetPosPixel() );
+
+ if ( !rMEvt.IsLeft() )
+ {
+ Window::MouseButtonDown( rMEvt );
+ if ( (nSelId > 0) && (nSelId != mnCurPageId) )
+ {
+ sal_uInt16 nPos = GetPagePos( nSelId );
+ pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbEnable )
+ {
+ if ( ImplDeactivatePage() )
+ {
+ SetCurPageId( nSelId );
+ Update();
+ ImplActivatePage();
+ ImplSelect();
+ }
+ mbInSelect = sal_True;
+ }
+ }
+ return;
+ }
+
+ if ( rMEvt.IsMod2() && mbAutoEditMode && nSelId )
+ {
+ if ( StartEditMode( nSelId ) )
+ return;
+ }
+
+ if ( (rMEvt.GetMode() & (MOUSE_MULTISELECT | MOUSE_RANGESELECT)) && (rMEvt.GetClicks() == 1) )
+ {
+ if ( nSelId )
+ {
+ sal_uInt16 nPos = GetPagePos( nSelId );
+ sal_Bool bSelectTab = sal_False;
+ pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbEnable )
+ {
+ if ( (rMEvt.GetMode() & MOUSE_MULTISELECT) && (mnWinStyle & WB_MULTISELECT) )
+ {
+ if ( nSelId != mnCurPageId )
+ {
+ SelectPage( nSelId, !IsPageSelected( nSelId ) );
+ bSelectTab = sal_True;
+ }
+ }
+ else if ( mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT) )
+ {
+ bSelectTab = sal_True;
+ sal_uInt16 n;
+ sal_Bool bSelect;
+ sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
+ if ( nPos <= nCurPos )
+ {
+ // Alle Tabs bis zur angeklickten Tab deselektieren
+ // und alle Tabs von der angeklickten Tab bis
+ // zur aktuellen Position selektieren
+ n = 0;
+ while ( n < nCurPos )
+ {
+ pItem = mpItemList->GetObject( n );
+ if ( n < nPos )
+ bSelect = sal_False;
+ else
+ bSelect = sal_True;
+
+ if ( pItem->mbSelect != bSelect )
+ {
+ pItem->mbSelect = bSelect;
+ if ( !pItem->maRect.IsEmpty() )
+ Invalidate( pItem->maRect );
+ }
+
+ n++;
+ }
+ }
+
+ if ( nPos >= nCurPos )
+ {
+ // Alle Tabs von der aktuellen bis zur angeklickten
+ // Tab selektieren und alle Tabs von der angeklickten
+ // Tab bis zur letzten Tab deselektieren
+ sal_uInt16 nCount = (sal_uInt16)mpItemList->Count();
+ n = nCurPos;
+ while ( n < nCount )
+ {
+ pItem = mpItemList->GetObject( n );
+
+ if ( n <= nPos )
+ bSelect = sal_True;
+ else
+ bSelect = sal_False;
+
+ if ( pItem->mbSelect != bSelect )
+ {
+ pItem->mbSelect = bSelect;
+ if ( !pItem->maRect.IsEmpty() )
+ Invalidate( pItem->maRect );
+ }
+
+ n++;
+ }
+ }
+ }
+
+ // Gegebenenfalls muss die selektierte Tab gescrollt werden
+ if ( bSelectTab )
+ {
+ ImplShowPage( nPos );
+ Update();
+ ImplSelect();
+ }
+ }
+ else
+ ImplShowPage( nPos );
+ mbInSelect = sal_True;
+
+ return;
+ }
+ }
+ else if ( rMEvt.GetClicks() == 2 )
+ {
+ // Gegebenenfalls den Double-Click-Handler rufen
+ if ( !rMEvt.GetModifier() && (!nSelId || (nSelId == mnCurPageId)) )
+ {
+ sal_uInt16 nOldCurId = mnCurPageId;
+ mnCurPageId = nSelId;
+ DoubleClick();
+ // Abfrage, da im DoubleClick-Handler die aktuelle Seite
+ // umgeschaltet werden konnte
+ if ( mnCurPageId == nSelId )
+ mnCurPageId = nOldCurId;
+ }
+
+ return;
+ }
+ else
+ {
+ if ( nSelId )
+ {
+ // Nur Select ausfuehren, wenn noch nicht aktuelle Page
+ if ( nSelId != mnCurPageId )
+ {
+ sal_uInt16 nPos = GetPagePos( nSelId );
+ pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbEnable )
+ {
+ if ( !pItem->mbSelect )
+ {
+ // Muss invalidiert werden
+ sal_Bool bUpdate = sal_False;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ bUpdate = sal_True;
+
+ // Alle selektierten Items deselektieren
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) )
+ {
+ pItem->mbSelect = sal_False;
+ if ( bUpdate )
+ Invalidate( pItem->maRect );
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+
+ if ( ImplDeactivatePage() )
+ {
+ SetCurPageId( nSelId );
+ Update();
+ ImplActivatePage();
+ ImplSelect();
+ }
+ }
+ else
+ ImplShowPage( nPos );
+ mbInSelect = sal_True;
+ }
+
+ return;
+ }
+ }
+
+ Window::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ mbInSelect = sal_False;
+ Window::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Paint( const Rectangle& )
+{
+ // Items berechnen und ausgeben
+ sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
+ ImplTabBarItem* pItem;
+
+ // kein Item, dann auch nichts zu tun
+ if ( nItemCount )
+ {
+ // TabBar muss formatiert sein
+ ImplFormat();
+
+ // Beim ersten Format auch dafuer sorgen, das aktuelle TabPage
+ // sichtbar wird
+ if ( mbFirstFormat )
+ {
+ mbFirstFormat = sal_False;
+
+ if ( mnCurPageId && (mnFirstPos == 0) && !mbDropPos )
+ {
+ pItem = mpItemList->GetObject( GetPagePos( mnCurPageId ) );
+ if ( pItem->maRect.IsEmpty() )
+ {
+ // mbDropPos setzen (bzw. misbrauchen) um Invalidate()
+ // zu unterbinden
+ mbDropPos = sal_True;
+ SetFirstPageId( mnCurPageId );
+ mbDropPos = sal_False;
+ if ( mnFirstPos != 0 )
+ ImplFormat();
+ }
+ }
+ }
+ }
+
+ // Farben ermitteln
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Color aFaceColor;
+ Color aSelectColor;
+ Color aFaceTextColor;
+ Color aSelectTextColor;
+ ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
+
+ // Font selektieren
+ Font aFont = GetFont();
+ Font aLightFont = aFont;
+ //aLightFont.SetWeight( WEIGHT_LIGHT ); //TODO Make font weight light on custom color only?
+ aLightFont.SetWeight( WEIGHT_NORMAL );
+
+ // #i36013# exclude push buttons from painting area
+ Rectangle aClipRect( Point( mnOffX, 0 ), Point( mnLastOffX, GetOutputHeightPixel() - 1 ) );
+ SetClipRegion( Region( aClipRect ) );
+
+ // Bei Border oben und unten einen Strich extra malen
+ if ( (mnWinStyle & WB_BORDER) || (mnWinStyle & WB_TOPBORDER) )
+ {
+ Size aOutputSize = GetOutputSizePixel();
+
+ // Bei 3D-Tabs wird auch der Border in 3D gemalt
+ if ( mnWinStyle & WB_3DTAB )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( mnOffX, 0 ), Point( aOutputSize.Width(), 0 ) );
+ }
+
+ // Border malen (Strich oben und Strich unten)
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ DrawLine( Point( mnOffX, mnOffY ), Point( aOutputSize.Width()-1, mnOffY ) );
+ }
+ else
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+
+ // Items ausgeben
+ if ( nItemCount )
+ {
+ // letzten sichtbaren Eintrag suchen
+ sal_uInt16 n = mnFirstPos+1;
+ if ( n >= nItemCount )
+ n = nItemCount-1;
+ pItem = mpItemList->Seek( n );
+ while ( pItem )
+ {
+ if ( !pItem->maRect.IsEmpty() )
+ {
+ n++;
+ pItem = mpItemList->Next();
+ }
+ else
+ break;
+ }
+
+ // Alle Tabs ausgeben (von hinten nach vorn und aktuellen zuletzt)
+ if ( pItem )
+ n--;
+ else if ( n >= nItemCount )
+ n = nItemCount-1;
+ pItem = mpItemList->Seek( n );
+ ImplTabBarItem* pCurItem = NULL;
+ while ( pItem )
+ {
+ // CurrentItem als letztes ausgeben, da es alle anderen ueberdeckt
+ if ( !pCurItem && (pItem->mnId == mnCurPageId) )
+ {
+ pCurItem = pItem;
+ pItem = mpItemList->Prev();
+ if ( !pItem )
+ pItem = pCurItem;
+ continue;
+ }
+
+ if ( !pItem->maRect.IsEmpty() )
+ {
+ Rectangle aRect = pItem->maRect;
+
+ // Aktuelle Page wird mit einem fetten Font ausgegeben
+ if ( pItem->mnId == mnCurPageId )
+ SetFont( aFont );
+ else
+ SetFont( aLightFont );
+
+ // Je nach Status die richtige FillInBrush setzen
+ // Set the correct FillInBrush depending upon status
+ if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) )
+ {
+ // Currently selected Tab
+ SetFillColor( aSelectColor );
+ SetTextColor( aSelectTextColor );
+ }
+ else
+ {
+ if ( !pItem->IsDefaultTabBgColor() && !rStyleSettings.GetHighContrastMode() )
+ {
+ SetFillColor( pItem->maTabBgColor );
+ SetTextColor( pItem->maTabTextColor );
+ } else {
+ SetFillColor( aFaceColor );
+ SetTextColor( aFaceTextColor );
+ }
+ }
+
+ // Muss Font Kursiv geschaltet werden
+ if ( pItem->mnBits & TPB_SPECIAL )
+ {
+ SetTextColor( Color( COL_LIGHTBLUE ) );
+ }
+
+ // Position der Page berechnen
+ Point aPos0 = Point( aRect.Left(), mnOffY );
+ Point aPos1 = Point( aRect.Left()+TABBAR_OFFSET_X, aRect.Bottom() );
+ Point aPos2 = Point( aRect.Right()-TABBAR_OFFSET_X, aRect.Bottom() );
+ Point aPos3 = Point( aRect.Right(), mnOffY );
+
+ // Zuerst geben wir das Polygon gefuellt aus
+ Polygon aPoly( 4 );
+ aPoly[0] = aPos0;
+ aPoly[1] = aPos1;
+ aPoly[2] = aPos2;
+ aPoly[3] = aPos3;
+ DrawPolygon( aPoly );
+
+ // Danach den Text zentiert ausgeben
+ XubString aText = pItem->maText;
+ if ( pItem->mbShort )
+ aText = GetEllipsisString( aText, mnCurMaxWidth, TEXT_DRAW_ENDELLIPSIS );
+ Size aRectSize = aRect.GetSize();
+ long nTextWidth = GetTextWidth( aText );
+ long nTextHeight = GetTextHeight();
+ Point aTxtPos( aRect.Left()+(aRectSize.Width()-nTextWidth)/2,
+ (aRectSize.Height()-nTextHeight)/2 );
+ if ( pItem->IsDefaultTabBgColor() || (!pItem->mbSelect) )
+ {
+ if ( !pItem->mbEnable )
+ DrawCtrlText( aTxtPos, aText, 0, STRING_LEN, (TEXT_DRAW_DISABLE | TEXT_DRAW_MNEMONIC) );
+ else
+ DrawText( aTxtPos, aText );
+ }
+ // Jetzt im Inhalt den 3D-Effekt ausgeben
+ aPos0.X()++;
+ aPos1.X()++;
+ aPos2.X()--;
+ aPos3.X()--;
+
+ // If this is the current tab, draw the left inner shadow the default color,
+ // otherwise make it the same as the custom background color
+ if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) ) {
+ SetLineColor( rStyleSettings.GetLightColor() );
+ } else {
+ if ( !pItem->IsDefaultTabBgColor() && ! rStyleSettings.GetHighContrastMode() )
+ {
+ SetLineColor( pItem->maTabBgColor );
+ } else {
+ SetLineColor( rStyleSettings.GetLightColor() );
+ }
+ }
+ // Draw the left side of the tab
+ DrawLine( aPos0, aPos1 );
+
+ if ( !pItem->mbSelect && (pItem->mnId != mnCurPageId) )
+ {
+ // Draw the top inner shadow
+ // ToDo: Change from this static color to tab custom bg color
+ DrawLine( Point( aPos0.X(), aPos0.Y()+1 ),
+ Point( aPos3.X(), aPos3.Y()+1 ) );
+ }
+
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( aPos2, aPos3 );
+ aPos1.X()--;
+ aPos1.Y()--;
+ aPos2.Y()--;
+ if ( !pItem->IsDefaultTabBgColor() && ( pItem->mbSelect || (pItem->mnId == mnCurPageId) ) )
+ {
+ SetLineColor( pItem->maTabBgColor );
+ DrawLine( Point(aPos1.X()-1, aPos1.Y()-1), Point(aPos2.X(), aPos2.Y()-1) );
+ }
+ DrawLine( aPos1, aPos2 );
+
+ // draw a small 2px sliver of the original background color at the bottom of the selected tab
+
+ if ( !pItem->IsDefaultTabBgColor() )
+ {
+ if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) || rStyleSettings.GetHighContrastMode() ) {
+ SetLineColor( pItem->maTabBgColor );
+ DrawLine( Point(aPos1.X()-1, aPos1.Y()-1), Point(aPos2.X(), aPos2.Y()-1) );
+ if ( !pItem->mbEnable )
+ DrawCtrlText( aTxtPos, aText, 0, STRING_LEN, (TEXT_DRAW_DISABLE | TEXT_DRAW_MNEMONIC) );
+ else
+ DrawText( aTxtPos, aText );
+ }
+ }
+
+ // Da etwas uebermalt werden konnte, muessen wir die Polygon-
+ // umrandung nocheinmal ausgeben
+ SetLineColor( rStyleSettings.GetDarkShadowColor() );
+ SetFillColor();
+ DrawPolygon( aPoly );
+
+ // Beim dem aktuellen Tab die restlichten Ausgaben vornehmen und
+ // die Schleife abbrechen, da die aktuelle Tab als letztes
+ // ausgegeben wird
+ if ( pItem == pCurItem )
+ {
+ // Beim aktuellen Item muss der oberstes Strich geloescht
+ // werden
+ SetLineColor();
+ SetFillColor( aSelectColor );
+ Rectangle aDelRect( aPos0, aPos3 );
+ DrawRect( aDelRect );
+ if ( mnWinStyle & WB_3DTAB )
+ {
+ aDelRect.Top()--;
+ DrawRect( aDelRect );
+ }
+
+ break;
+ }
+
+ pItem = mpItemList->Prev();
+ }
+ else
+ {
+ if ( pItem == pCurItem )
+ break;
+
+ pItem = NULL;
+ }
+
+ if ( !pItem )
+ pItem = pCurItem;
+ }
+ }
+
+ // Font wieder herstellen
+ SetFont( aFont );
+ // remove clip region
+ SetClipRegion();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Resize()
+{
+ Size aNewSize = GetOutputSizePixel();
+
+ long nSizerWidth = 0;
+ long nButtonWidth = 0;
+
+ // Sizer anordnen
+ if ( mpImpl->mpSizer )
+ {
+ Size aSizerSize = mpImpl->mpSizer->GetSizePixel();
+ Point aNewSizerPos( mbMirrored ? 0 : (aNewSize.Width()-aSizerSize.Width()), 0 );
+ Size aNewSizerSize( aSizerSize.Width(), aNewSize.Height() );
+ mpImpl->mpSizer->SetPosSizePixel( aNewSizerPos, aNewSizerSize );
+ nSizerWidth = aSizerSize.Width();
+ }
+
+ // Scroll-Buttons anordnen
+ long nHeight = aNewSize.Height();
+ // Font in der groesse Anpassen?
+ ImplInitSettings( sal_True, sal_False );
+
+ long nX = mbMirrored ? (aNewSize.Width()-nHeight) : 0;
+ long nXDiff = mbMirrored ? -nHeight : nHeight;
+
+ Size aBtnSize( nHeight, nHeight );
+ if ( mpFirstBtn )
+ {
+ mpFirstBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
+ nX += nXDiff;
+ nButtonWidth += nHeight;
+ }
+ if ( mpPrevBtn )
+ {
+ mpPrevBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
+ nX += nXDiff;
+ nButtonWidth += nHeight;
+ }
+ if ( mpNextBtn )
+ {
+ mpNextBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
+ nX += nXDiff;
+ nButtonWidth += nHeight;
+ }
+ if ( mpLastBtn )
+ {
+ mpLastBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize );
+ nX += nXDiff;
+ nButtonWidth += nHeight;
+ }
+
+ // Groesse merken
+ maWinSize = aNewSize;
+
+ if( mbMirrored )
+ {
+ mnOffX = nSizerWidth;
+ mnLastOffX = maWinSize.Width() - nButtonWidth - 1;
+ }
+ else
+ {
+ mnOffX = nButtonWidth;
+ mnLastOffX = maWinSize.Width() - nSizerWidth - 1;
+ }
+
+ // Neu formatieren
+ mbSizeFormat = sal_True;
+ if ( IsReallyVisible() )
+ {
+ if ( ImplCalcWidth() )
+ Invalidate();
+ ImplFormat();
+ }
+
+ // Button enablen/disablen
+ ImplEnableControls();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ sal_uInt16 nItemId = GetPageId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+ if ( nItemId )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ XubString aStr = GetHelpText( nItemId );
+ if ( aStr.Len() )
+ {
+ Rectangle aItemRect = GetPageRect( nItemId );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ return;
+ }
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ rtl::OUString aHelpId( rtl::OStringToOUString( GetHelpId( nItemId ), RTL_TEXTENCODING_UTF8 ) );
+ if ( aHelpId.getLength() )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( aHelpId, this );
+ return;
+ }
+ }
+
+ // Bei Quick- oder Ballloon-Help zeigen wir den Text an,
+ // wenn dieser abgeschnitten oder nicht voll sichtbar ist
+ if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
+ {
+ sal_uInt16 nPos = GetPagePos( nItemId );
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem->mbShort ||
+ (pItem->maRect.Right()-TABBAR_OFFSET_X-5 > mnLastOffX) )
+ {
+ Rectangle aItemRect = GetPageRect( nItemId );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ XubString aStr = mpItemList->GetObject( nPos )->maText;
+ if ( aStr.Len() )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ else
+ Help::ShowQuickHelp( this, aItemRect, aStr );
+ return;
+ }
+ }
+ }
+ }
+
+ Window::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( (mbSizeFormat || mbFormat) && mpItemList->Count() )
+ ImplFormat();
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( sal_True, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ Invalidate();
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( sal_False, sal_True );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_MIRRORING )
+ {
+ // reacts on calls of EnableRTL, have to mirror all child controls
+ if( mpFirstBtn ) mpFirstBtn->EnableRTL( IsRTLEnabled() );
+ if( mpPrevBtn ) mpPrevBtn->EnableRTL( IsRTLEnabled() );
+ if( mpNextBtn ) mpNextBtn->EnableRTL( IsRTLEnabled() );
+ if( mpLastBtn ) mpLastBtn->EnableRTL( IsRTLEnabled() );
+ if( mpImpl->mpSizer ) mpImpl->mpSizer->EnableRTL( IsRTLEnabled() );
+ if( mpEdit ) mpEdit->EnableRTL( IsRTLEnabled() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ ImplInitSettings( sal_True, sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplSelect()
+{
+ Select();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGESELECTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Split()
+{
+ maSplitHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplActivatePage()
+{
+ ActivatePage();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ActivatePage()
+{
+ maActivatePageHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+long TabBar::ImplDeactivatePage()
+{
+ long nRet = DeactivatePage();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGEDEACTIVATED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(mnCurPageId)) );
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+long TabBar::DeactivatePage()
+{
+ if ( maDeactivatePageHdl.IsSet() )
+ return maDeactivatePageHdl.Call( this );
+ else
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+long TabBar::StartRenaming()
+{
+ if ( maStartRenamingHdl.IsSet() )
+ return maStartRenamingHdl.Call( this );
+ else
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+long TabBar::AllowRenaming()
+{
+ if ( maAllowRenamingHdl.IsSet() )
+ return maAllowRenamingHdl.Call( this );
+ else
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::EndRenaming()
+{
+ maEndRenamingHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Mirror()
+{
+
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::InsertPage( sal_uInt16 nPageId, const XubString& rText,
+ TabBarPageBits nBits, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" );
+ DBG_ASSERT( GetPagePos( nPageId ) == PAGE_NOT_FOUND,
+ "TabBar::InsertPage(): PageId already exists" );
+ DBG_ASSERT( nBits <= TPB_SPECIAL, "TabBar::InsertPage(): nBits is wrong" );
+
+ // PageItem anlegen und in die Item-Liste eintragen
+ ImplTabBarItem* pItem = new ImplTabBarItem( nPageId, rText, nBits );
+ mpItemList->Insert( pItem, nPos );
+ mbSizeFormat = sal_True;
+
+ // CurPageId gegebenenfalls setzen
+ if ( !mnCurPageId )
+ mnCurPageId = nPageId;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGEINSERTED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
+}
+
+// -----------------------------------------------------------------------
+
+Color TabBar::GetTabBgColor( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ if ( nPos != PAGE_NOT_FOUND )
+ return mpItemList->GetObject( nPos )->maTabBgColor;
+ else
+ return Color( COL_AUTO );
+}
+
+void TabBar::SetTabBgColor( sal_uInt16 nPageId, const Color& aTabBgColor )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ ImplTabBarItem* pItem;
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ pItem = mpItemList->GetObject( nPos );
+ if ( aTabBgColor != Color( COL_AUTO ) )
+ {
+ pItem->maTabBgColor = aTabBgColor;
+ if ( aTabBgColor.GetLuminance() <= 128 ) //Do not use aTabBgColor.IsDark(), because that threshold is way too low...
+ pItem->maTabTextColor = Color( COL_WHITE );
+ else
+ pItem->maTabTextColor = Color( COL_BLACK );
+ }
+ else
+ {
+ pItem->maTabBgColor = Color( COL_AUTO );
+ pItem->maTabTextColor = Color( COL_AUTO );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::RemovePage( sal_uInt16 nPageId )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ // Existiert Item
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ if ( mnCurPageId == nPageId )
+ mnCurPageId = 0;
+
+ // Testen, ob erste sichtbare Seite verschoben werden muss
+ if ( mnFirstPos > nPos )
+ mnFirstPos--;
+
+ // Item-Daten loeschen
+ delete mpItemList->Remove( nPos );
+ mbFormat = sal_True;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::MovePage( sal_uInt16 nPageId, sal_uInt16 nNewPos )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ Pair aPair( nPos, nNewPos );
+
+ if ( nPos < nNewPos )
+ nNewPos--;
+
+ if ( nPos == nNewPos )
+ return;
+
+ // Existiert Item
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ // TabBar-Item in der Liste verschieben
+ ImplTabBarItem* pItem = mpItemList->Remove( nPos );
+ mpItemList->Insert( pItem, nNewPos );
+ mbFormat = sal_True;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGEMOVED, (void*) &aPair );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Clear()
+{
+ // Alle Items loeschen
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ // Item-Daten loeschen
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ // Items aus der Liste loeschen
+ mpItemList->Clear();
+ mbSizeFormat = sal_True;
+ mnCurPageId = 0;
+ mnFirstPos = 0;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, (void*) PAGE_NOT_FOUND );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::EnablePage( sal_uInt16 nPageId, sal_Bool bEnable )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbEnable != bEnable )
+ {
+ pItem->mbEnable = bEnable;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate( pItem->maRect );
+
+ CallEventListeners( bEnable ? VCLEVENT_TABBAR_PAGEENABLED : VCLEVENT_TABBAR_PAGEDISABLED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TabBar::IsPageEnabled( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ if ( nPos != PAGE_NOT_FOUND )
+ return mpItemList->GetObject( nPos )->mbEnable;
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetPageBits( sal_uInt16 nPageId, TabBarPageBits nBits )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mnBits != nBits )
+ {
+ pItem->mnBits = nBits;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate( pItem->maRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TabBarPageBits TabBar::GetPageBits( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ if ( nPos != PAGE_NOT_FOUND )
+ return mpItemList->GetObject( nPos )->mnBits;
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::GetPageCount() const
+{
+ return (sal_uInt16)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::GetPageId( sal_uInt16 nPos ) const
+{
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::GetPagePos( sal_uInt16 nPageId ) const
+{
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nPageId )
+ return (sal_uInt16)mpItemList->GetCurPos();
+
+ pItem = mpItemList->Next();
+ }
+
+ return PAGE_NOT_FOUND;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::GetPageId( const Point& rPos ) const
+{
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->maRect.IsInside( rPos ) )
+ return pItem->mnId;
+
+ pItem = mpItemList->Next();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle TabBar::GetPageRect( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ if ( nPos != PAGE_NOT_FOUND )
+ return mpItemList->GetObject( nPos )->maRect;
+ else
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetCurPageId( sal_uInt16 nPageId )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ // Wenn Item nicht existiert, dann nichts machen
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ // Wenn sich aktuelle Page nicht geaendert hat, dann muessen wir
+ // jetzt nichts mehr machen
+ if ( nPageId == mnCurPageId )
+ return;
+
+ // Muss invalidiert werden
+ sal_Bool bUpdate = sal_False;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ bUpdate = sal_True;
+
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+ ImplTabBarItem* pOldItem;
+
+ if ( mnCurPageId )
+ pOldItem = mpItemList->GetObject( GetPagePos( mnCurPageId ) );
+ else
+ pOldItem = NULL;
+
+ // Wenn Page nicht selektiert, dann vorher selektierte Seite
+ // deselktieren, wenn dies die einzige selektierte Seite ist
+ if ( !pItem->mbSelect && pOldItem )
+ {
+ sal_uInt16 nSelPageCount = GetSelectPageCount();
+ if ( nSelPageCount == 1 )
+ pOldItem->mbSelect = sal_False;
+ pItem->mbSelect = sal_True;
+ }
+
+ mnCurPageId = nPageId;
+ mbFormat = sal_True;
+
+ // Dafuer sorgen, das aktuelle Page sichtbar wird
+ if ( IsReallyVisible() )
+ {
+ if ( nPos < mnFirstPos )
+ SetFirstPageId( nPageId );
+ else
+ {
+ // sichtbare Breite berechnen
+ long nWidth = mnLastOffX;
+ if ( nWidth > TABBAR_OFFSET_X )
+ nWidth -= TABBAR_OFFSET_X;
+ if ( nWidth > ADDNEWPAGE_AREAWIDTH )
+ nWidth -= ADDNEWPAGE_AREAWIDTH;
+
+ if ( pItem->maRect.IsEmpty() )
+ ImplFormat();
+
+ while ( (mbMirrored ? (pItem->maRect.Left() < mnOffX) : (pItem->maRect.Right() > nWidth)) ||
+ pItem->maRect.IsEmpty() )
+ {
+ sal_uInt16 nNewPos = mnFirstPos+1;
+ // Dafuer sorgen, das min. die aktuelle TabPages als
+ // erste TabPage sichtbar ist
+ if ( nNewPos >= nPos )
+ {
+ SetFirstPageId( nPageId );
+ break;
+ }
+ else
+ SetFirstPageId( GetPageId( nNewPos ) );
+ ImplFormat();
+ // Falls erste Seite nicht weitergeschaltet wird, dann
+ // koennen wir abbrechen
+ if ( nNewPos != mnFirstPos )
+ break;
+ }
+ }
+ }
+
+ // Leiste neu ausgeben
+ if ( bUpdate )
+ {
+ Invalidate( pItem->maRect );
+ if ( pOldItem )
+ Invalidate( pOldItem->maRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::MakeVisible( sal_uInt16 nPageId )
+{
+ if ( !IsReallyVisible() )
+ return;
+
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ // Wenn Item nicht existiert, dann nichts machen
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ if ( nPos < mnFirstPos )
+ SetFirstPageId( nPageId );
+ else
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+
+ // sichtbare Breite berechnen
+ long nWidth = mnLastOffX;
+ if ( nWidth > TABBAR_OFFSET_X )
+ nWidth -= TABBAR_OFFSET_X;
+
+ if ( mbFormat || pItem->maRect.IsEmpty() )
+ {
+ mbFormat = sal_True;
+ ImplFormat();
+ }
+
+ while ( (pItem->maRect.Right() > nWidth) ||
+ pItem->maRect.IsEmpty() )
+ {
+ sal_uInt16 nNewPos = mnFirstPos+1;
+ // Dafuer sorgen, das min. die aktuelle TabPages als
+ // erste TabPage sichtbar ist
+ if ( nNewPos >= nPos )
+ {
+ SetFirstPageId( nPageId );
+ break;
+ }
+ else
+ SetFirstPageId( GetPageId( nNewPos ) );
+ ImplFormat();
+ // Falls erste Seite nicht weitergeschaltet wird, dann
+ // koennen wir abbrechen
+ if ( nNewPos != mnFirstPos )
+ break;
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetFirstPageId( sal_uInt16 nPageId )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ // Wenn Item nicht existiert, dann sal_False zurueckgeben
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ if ( nPos != mnFirstPos )
+ {
+ // Dafuer sorgen, das nach Moeglichkteit soviele Pages wie
+ // moeglich sichtbar sind
+ ImplFormat();
+ sal_uInt16 nLastFirstPos = ImplGetLastFirstPos();
+ sal_uInt16 nNewPos;
+ if ( nPos > nLastFirstPos )
+ nNewPos = nLastFirstPos;
+ else
+ nNewPos = nPos;
+
+ if ( nNewPos != mnFirstPos )
+ {
+ mnFirstPos = nNewPos;
+ mbFormat = sal_True;
+
+ // Leiste neu ausgeben (Achtung: mbDropPos beachten, da wenn
+ // dieses Flag gesetzt ist, wird direkt gepaintet)
+ if ( IsReallyVisible() && IsUpdateMode() && !mbDropPos )
+ Invalidate();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SelectPage( sal_uInt16 nPageId, sal_Bool bSelect )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbSelect != bSelect )
+ {
+ pItem->mbSelect = bSelect;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate( pItem->maRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SelectPageRange( sal_Bool bSelect, sal_uInt16 nStartPos, sal_uInt16 nEndPos )
+{
+ Rectangle aPaintRect;
+ sal_uInt16 nPos = nStartPos;
+ ImplTabBarItem* pItem = mpItemList->Seek( nPos );
+ while ( pItem && (nPos <= nEndPos) )
+ {
+ if ( (pItem->mbSelect != bSelect) && (pItem->mnId != mnCurPageId) )
+ {
+ pItem->mbSelect = bSelect;
+ aPaintRect.Union( pItem->maRect );
+ }
+
+ nPos++;
+ pItem = mpItemList->Next();
+ }
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() && !aPaintRect.IsEmpty() )
+ Invalidate( aPaintRect );
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::GetSelectPage( sal_uInt16 nSelIndex ) const
+{
+ sal_uInt16 nSelected = 0;
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbSelect )
+ nSelected++;
+
+ if ( nSelected == nSelIndex )
+ return pItem->mnId;
+
+ pItem = mpItemList->Next();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::GetSelectPageCount() const
+{
+ sal_uInt16 nSelected = 0;
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbSelect )
+ nSelected++;
+
+ pItem = mpItemList->Next();
+ }
+
+ return nSelected;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TabBar::IsPageSelected( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ if ( nPos != PAGE_NOT_FOUND )
+ return mpItemList->GetObject( nPos )->mbSelect;
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TabBar::StartEditMode( sal_uInt16 nPageId )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ if ( mpEdit || (nPos == PAGE_NOT_FOUND) || (mnLastOffX < 8) )
+ return sal_False;
+
+ mnEditId = nPageId;
+ if ( StartRenaming() )
+ {
+ ImplShowPage( nPos );
+ ImplFormat();
+ Update();
+
+ mpEdit = new TabBarEdit( this, WB_CENTER );
+ Rectangle aRect = GetPageRect( mnEditId );
+ long nX = aRect.Left()+TABBAR_OFFSET_X+(TABBAR_OFFSET_X2/2);
+ long nWidth = aRect.GetWidth()-(TABBAR_OFFSET_X*2)-TABBAR_OFFSET_X2;
+ if ( mnEditId != GetCurPageId() )
+ nX += 1;
+ if ( nX+nWidth > mnLastOffX )
+ nWidth = mnLastOffX-nX;
+ if ( nWidth < 3 )
+ {
+ nX = aRect.Left();
+ nWidth = aRect.GetWidth();
+ }
+ mpEdit->SetText( GetPageText( mnEditId ) );
+ mpEdit->SetPosSizePixel( nX, aRect.Top()+mnOffY+1, nWidth, aRect.GetHeight()-3 );
+ Font aFont = GetPointFont();
+ Color aForegroundColor;
+ Color aBackgroundColor;
+ Color aFaceColor;
+ Color aSelectColor;
+ Color aFaceTextColor;
+ Color aSelectTextColor;
+ ImplGetColors( aFaceColor, aFaceTextColor, aSelectColor, aSelectTextColor );
+ if ( mnEditId != GetCurPageId() )
+ aFont.SetWeight( WEIGHT_LIGHT );
+ if ( IsPageSelected( mnEditId ) || (mnEditId == GetCurPageId()) )
+ {
+ aForegroundColor = aSelectTextColor;
+ aBackgroundColor = aSelectColor;
+ }
+ else
+ {
+ aForegroundColor = aFaceTextColor;
+ aBackgroundColor = aFaceColor;
+ }
+ if ( GetPageBits( mnEditId ) & TPB_SPECIAL )
+ aForegroundColor = Color( COL_LIGHTBLUE );
+ mpEdit->SetControlFont( aFont );
+ mpEdit->SetControlForeground( aForegroundColor );
+ mpEdit->SetControlBackground( aBackgroundColor );
+ mpEdit->GrabFocus();
+ mpEdit->SetSelection( Selection( 0, mpEdit->GetText().Len() ) );
+ mpEdit->Show();
+ return sal_True;
+ }
+ else
+ {
+ mnEditId = 0;
+ return sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::EndEditMode( sal_Bool bCancel )
+{
+ if ( mpEdit )
+ {
+ // call hdl
+ sal_Bool bEnd = sal_True;
+ mbEditCanceled = bCancel;
+ maEditText = mpEdit->GetText();
+ mpEdit->SetPostEvent();
+ if ( !bCancel )
+ {
+ long nAllowRenaming = AllowRenaming();
+ if ( nAllowRenaming == TABBAR_RENAMING_YES )
+ SetPageText( mnEditId, maEditText );
+ else if ( nAllowRenaming == TABBAR_RENAMING_NO )
+ bEnd = sal_False;
+ else // nAllowRenaming == TABBAR_RENAMING_CANCEL
+ mbEditCanceled = sal_True;
+ }
+
+ // renaming not allowed, than reset edit data
+ if ( !bEnd )
+ {
+ mpEdit->ResetPostEvent();
+ mpEdit->GrabFocus();
+ }
+ else
+ {
+ // close edit and call end hdl
+ delete mpEdit;
+ mpEdit = NULL;
+ EndRenaming();
+ mnEditId = 0;
+ }
+
+ // reset
+ maEditText.Erase();
+ mbEditCanceled = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetMirrored( sal_Bool bMirrored )
+{
+ if( mbMirrored != bMirrored )
+ {
+ mbMirrored = bMirrored;
+ mbSizeFormat = sal_True;
+ ImplInitControls(); // for button images
+ Resize(); // recalculates control positions
+ Mirror();
+ }
+}
+
+void TabBar::SetEffectiveRTL( sal_Bool bRTL )
+{
+ SetMirrored( bRTL != Application::GetSettings().GetLayoutRTL() );
+}
+
+sal_Bool TabBar::IsEffectiveRTL() const
+{
+ return IsMirrored() != Application::GetSettings().GetLayoutRTL();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetMaxPageWidth( long nMaxWidth )
+{
+ if ( mnMaxPageWidth != nMaxWidth )
+ {
+ mnMaxPageWidth = nMaxWidth;
+ mbSizeFormat = sal_True;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectColor()
+{
+ if ( mbSelColor )
+ {
+ maSelColor = Color( COL_TRANSPARENT );
+ mbSelColor = sal_False;
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectColor( const Color& rColor )
+{
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbSelColor )
+ {
+ maSelColor = Color( COL_TRANSPARENT );
+ mbSelColor = sal_False;
+ Invalidate();
+ }
+ }
+ else
+ {
+ if ( maSelColor != rColor )
+ {
+ maSelColor = rColor;
+ mbSelColor = sal_True;
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectTextColor()
+{
+ if ( mbSelTextColor )
+ {
+ maSelTextColor = Color( COL_TRANSPARENT );
+ mbSelTextColor = sal_False;
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectTextColor( const Color& rColor )
+{
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbSelTextColor )
+ {
+ maSelTextColor = Color( COL_TRANSPARENT );
+ mbSelTextColor = sal_False;
+ Invalidate();
+ }
+ }
+ else
+ {
+ if ( maSelTextColor != rColor )
+ {
+ maSelTextColor = rColor;
+ mbSelTextColor = sal_True;
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetPageText( sal_uInt16 nPageId, const XubString& rText )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ mpItemList->GetObject( nPos )->maText = rText;
+ mbSizeFormat = sal_True;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGETEXTCHANGED, reinterpret_cast<void*>(sal::static_int_cast<sal_IntPtr>(nPageId)) );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString TabBar::GetPageText( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ if ( nPos != PAGE_NOT_FOUND )
+ return mpItemList->GetObject( nPos )->maText;
+ else
+ return XubString();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetHelpText( sal_uInt16 nPageId, const XubString& rText )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ if ( nPos != PAGE_NOT_FOUND )
+ mpItemList->GetObject( nPos )->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+XubString TabBar::GetHelpText( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ if ( nPos != PAGE_NOT_FOUND )
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->maHelpText.Len() && pItem->maHelpId.getLength() )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pItem->maHelpText = pHelp->GetHelpText( rtl::OStringToOUString( pItem->maHelpId, RTL_TEXTENCODING_UTF8 ), this );
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return XubString();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetHelpId( sal_uInt16 nPageId, const rtl::OString& rHelpId )
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ if ( nPos != PAGE_NOT_FOUND )
+ mpItemList->GetObject( nPos )->maHelpId = rHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+rtl::OString TabBar::GetHelpId( sal_uInt16 nPageId ) const
+{
+ sal_uInt16 nPos = GetPagePos( nPageId );
+ rtl::OString aRet;
+ if ( nPos != PAGE_NOT_FOUND )
+ aRet = mpItemList->GetObject( nPos )->maHelpId;
+ return aRet;
+}
+
+// -----------------------------------------------------------------------
+
+long TabBar::GetMinSize() const
+{
+ long nMinSize = TABBAR_MINSIZE + TABBAR_OFFSET_X;
+ if ( mnWinStyle & WB_MINSCROLL )
+ nMinSize += mpPrevBtn->GetSizePixel().Width()*2;
+ else if ( mnWinStyle & WB_SCROLL )
+ nMinSize += mpFirstBtn->GetSizePixel().Width()*4;
+ return nMinSize;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TabBar::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
+{
+ if ( !(mnWinStyle & WB_DRAG) || (rCEvt.GetCommand() != COMMAND_STARTDRAG) )
+ return sal_False;
+
+ // Testen, ob angeklickte Seite selektiert ist. Falls dies nicht
+ // der Fall ist, setzen wir ihn als aktuellen Eintrag. Falls Drag and
+ // Drop auch mal ueber Tastatur ausgeloest werden kann, testen wir
+ // dies nur bei einer Mausaktion.
+ // Ausserdem machen wir das nur, wenn kein Select() ausgeloest wurde,
+ // da der Select schon den Bereich gescrollt haben kann
+ if ( rCEvt.IsMouseEvent() && !mbInSelect )
+ {
+ sal_uInt16 nSelId = GetPageId( rCEvt.GetMousePosPixel() );
+
+ // Falls kein Eintrag angeklickt wurde, starten wir kein Dragging
+ if ( !nSelId )
+ return sal_False;
+
+ // Testen, ob Seite selektiertiert ist. Falls nicht, als aktuelle
+ // Seite setzen und Select rufen.
+ if ( !IsPageSelected( nSelId ) )
+ {
+ if ( ImplDeactivatePage() )
+ {
+ SetCurPageId( nSelId );
+ Update();
+ ImplActivatePage();
+ ImplSelect();
+ }
+ else
+ return sal_False;
+ }
+ }
+ mbInSelect = sal_False;
+
+ Region aRegion;
+
+ // Region zuweisen
+ rRegion = aRegion;
+
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 TabBar::ShowDropPos( const Point& rPos )
+{
+ ImplTabBarItem* pItem;
+ sal_uInt16 nDropId;
+ sal_uInt16 nNewDropPos;
+ sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
+ short nScroll = 0;
+
+ if ( rPos.X() > mnLastOffX-TABBAR_DRAG_SCROLLOFF )
+ {
+ pItem = mpItemList->GetObject( mpItemList->Count()-1 );
+ if ( !pItem->maRect.IsEmpty() && (rPos.X() > pItem->maRect.Right()) )
+ nNewDropPos = (sal_uInt16)mpItemList->Count();
+ else
+ {
+ nNewDropPos = mnFirstPos+1;
+ nScroll = 1;
+ }
+ }
+ else if ( (rPos.X() <= mnOffX) ||
+ (!mnOffX && (rPos.X() <= TABBAR_DRAG_SCROLLOFF)) )
+ {
+ if ( mnFirstPos )
+ {
+ nNewDropPos = mnFirstPos;
+ nScroll = -1;
+ }
+ else
+ nNewDropPos = 0;
+ }
+ else
+ {
+ nDropId = GetPageId( rPos );
+ if ( nDropId )
+ {
+ nNewDropPos = GetPagePos( nDropId );
+ if ( mnFirstPos && (nNewDropPos == mnFirstPos-1) )
+ nScroll = -1;
+ }
+ else
+ nNewDropPos = nItemCount;
+ }
+
+ if ( mbDropPos && (nNewDropPos == mnDropPos) && !nScroll )
+ return mnDropPos;
+
+ if ( mbDropPos )
+ HideDropPos();
+ mbDropPos = sal_True;
+ mnDropPos = nNewDropPos;
+
+ if ( nScroll )
+ {
+ sal_uInt16 nOldFirstPos = mnFirstPos;
+ SetFirstPageId( GetPageId( mnFirstPos+nScroll ) );
+
+ // Direkt ausgeben, da kein Paint bei Drag and Drop moeglich
+ if ( nOldFirstPos != mnFirstPos )
+ {
+ Rectangle aRect( mnOffX, 0, mnLastOffX, maWinSize.Height() );
+ SetFillColor( GetBackground().GetColor() );
+ DrawRect( aRect );
+ Paint( aRect );
+ }
+ }
+
+ // Drop-Position-Pfeile ausgeben
+ Color aBlackColor( COL_BLACK );
+ long nX;
+ long nY = (maWinSize.Height()/2)-1;
+ sal_uInt16 nCurPos = GetPagePos( mnCurPageId );
+
+ SetLineColor( aBlackColor );
+ if ( mnDropPos < nItemCount )
+ {
+ pItem = mpItemList->GetObject( mnDropPos );
+ nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
+ if ( mnDropPos == nCurPos )
+ nX--;
+ else
+ nX++;
+ if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
+ SetLineColor( pItem->maTabTextColor );
+ DrawLine( Point( nX, nY ), Point( nX, nY ) );
+ DrawLine( Point( nX+1, nY-1 ), Point( nX+1, nY+1 ) );
+ DrawLine( Point( nX+2, nY-2 ), Point( nX+2, nY+2 ) );
+ SetLineColor( aBlackColor );
+ }
+ if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
+ {
+ pItem = mpItemList->GetObject( mnDropPos-1 );
+ nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
+ if ( mnDropPos == nCurPos )
+ nX++;
+ if ( !pItem->IsDefaultTabBgColor() && !pItem->mbSelect)
+ SetLineColor( pItem->maTabTextColor );
+ DrawLine( Point( nX, nY ), Point( nX, nY ) );
+ DrawLine( Point( nX-1, nY-1 ), Point( nX-1, nY+1 ) );
+ DrawLine( Point( nX-2, nY-2 ), Point( nX-2, nY+2 ) );
+ }
+
+ return mnDropPos;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::HideDropPos()
+{
+ if ( mbDropPos )
+ {
+ ImplTabBarItem* pItem;
+ long nX;
+ long nY1 = (maWinSize.Height()/2)-3;
+ long nY2 = nY1 + 5;
+ sal_uInt16 nItemCount = (sal_uInt16)mpItemList->Count();
+
+ if ( mnDropPos < nItemCount )
+ {
+ pItem = mpItemList->GetObject( mnDropPos );
+ nX = pItem->maRect.Left()+TABBAR_OFFSET_X;
+ // Paint direkt aufrufen, da bei Drag and Drop kein Paint
+ // moeglich
+ Rectangle aRect( nX-1, nY1, nX+3, nY2 );
+ Region aRegion( aRect );
+ SetClipRegion( aRegion );
+ Paint( aRect );
+ SetClipRegion();
+ }
+ if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
+ {
+ pItem = mpItemList->GetObject( mnDropPos-1 );
+ nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
+ // Paint direkt aufrufen, da bei Drag and Drop kein Paint
+ // moeglich
+ Rectangle aRect( nX-2, nY1, nX+1, nY2 );
+ Region aRegion( aRect );
+ SetClipRegion( aRegion );
+ Paint( aRect );
+ SetClipRegion();
+ }
+
+ mbDropPos = sal_False;
+ mnDropPos = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TabBar::SwitchPage( const Point& rPos )
+{
+ sal_Bool bSwitch = sal_False;
+ sal_uInt16 nSwitchId = GetPageId( rPos );
+ if ( !nSwitchId )
+ EndSwitchPage();
+ else
+ {
+ if ( nSwitchId != mnSwitchId )
+ {
+ mnSwitchId = nSwitchId;
+ mnSwitchTime = Time::GetSystemTicks();
+ }
+ else
+ {
+ // Erst nach 500 ms umschalten
+ if ( mnSwitchId != GetCurPageId() )
+ {
+ if ( Time::GetSystemTicks() > mnSwitchTime+500 )
+ {
+ mbInSwitching = sal_True;
+ if ( ImplDeactivatePage() )
+ {
+ SetCurPageId( mnSwitchId );
+ Update();
+ ImplActivatePage();
+ ImplSelect();
+ bSwitch = sal_True;
+ }
+ mbInSwitching = sal_False;
+ }
+ }
+ }
+ }
+
+ return bSwitch;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::EndSwitchPage()
+{
+ mnSwitchTime = 0;
+ mnSwitchId = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetStyle( WinBits nStyle )
+{
+ mnWinStyle = nStyle;
+ ImplInitControls();
+ // Evt. Controls neu anordnen
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Resize();
+}
+
+// -----------------------------------------------------------------------
+
+Size TabBar::CalcWindowSizePixel() const
+{
+ long nWidth = 0;
+
+ if ( mpItemList->Count() )
+ {
+ ((TabBar*)this)->ImplCalcWidth();
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ nWidth += pItem->mnWidth;
+ pItem = mpItemList->Next();
+ }
+ nWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
+ }
+
+ return Size( nWidth, GetSettings().GetStyleSettings().GetScrollBarSize() );
+}
+// -----------------------------------------------------------------------
+
+Rectangle TabBar::GetPageArea() const
+{
+ return Rectangle( Point( mnOffX, mnOffY ), Size( mnLastOffX-mnOffX+1, GetSizePixel().Height()-mnOffY ) );
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > TabBar::CreateAccessible()
+{
+ return mpImpl->maAccessibleFactory.getFactory().createAccessibleTabBar( *this );
+}
+
+// -----------------------------------------------------------------------
diff --git a/svtools/source/control/taskbar.cxx b/svtools/source/control/taskbar.cxx
new file mode 100755
index 000000000000..06c90818b13e
--- /dev/null
+++ b/svtools/source/control/taskbar.cxx
@@ -0,0 +1,589 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _TASKBAR_CXX
+
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+#include <vcl/floatwin.hxx>
+
+#include <svtools/taskbar.hxx>
+
+// =======================================================================
+
+class ImplTaskBarFloat : public FloatingWindow
+{
+public:
+ TaskBar* mpTaskBar;
+
+public:
+ ImplTaskBarFloat( TaskBar* pTaskBar );
+};
+
+// -----------------------------------------------------------------------
+
+ImplTaskBarFloat::ImplTaskBarFloat( TaskBar* pTaskBar ) :
+ FloatingWindow( pTaskBar, 0 )
+{
+ mpTaskBar = pTaskBar;
+}
+
+// =======================================================================
+
+#define TASKBAR_BORDER 2
+#define TASKBAR_OFFSIZE 3
+#define TASKBAR_OFFX 2
+#define TASKBAR_OFFY 1
+#define TASKBAR_BUTTONOFF 5
+#define TASKBAR_AUTOHIDE_HEIGHT 2
+
+// =======================================================================
+
+TaskBar::TaskBar( Window* pParent, WinBits nWinStyle ) :
+ Window( pParent, WB_3DLOOK )
+{
+ mpButtonBar = NULL;
+ mpTaskToolBox = NULL;
+ mpStatusBar = NULL;
+ mnStatusWidth = 0;
+ mnOldStatusWidth = 0;
+ mnLines = 1;
+ mnWinBits = nWinStyle;
+ mbStatusText = sal_False;
+ mbShowItems = sal_False;
+ mbAutoHide = sal_False;
+
+ ImplInitSettings();
+}
+
+// -----------------------------------------------------------------------
+
+TaskBar::~TaskBar()
+{
+ if ( mpButtonBar )
+ delete mpButtonBar;
+ if ( mpTaskToolBox )
+ delete mpTaskToolBox;
+ if ( mpStatusBar )
+ delete mpStatusBar;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::ImplInitSettings()
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( Window::GetStyle() & WB_3DLOOK )
+ aColor = rStyleSettings.GetFaceColor();
+ else
+ aColor = rStyleSettings.GetWindowColor();
+ SetBackground( aColor );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::ImplNewHeight( long nNewHeight )
+{
+ long nOldHeight = GetSizePixel().Height();
+ if ( nNewHeight != nOldHeight )
+ {
+ long nY = GetPosPixel().Y()-(nNewHeight-nOldHeight);
+ SetPosSizePixel( 0, nY, 0, nNewHeight,
+ WINDOW_POSSIZE_Y | WINDOW_POSSIZE_HEIGHT );
+ TaskResize();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::TaskResize()
+{
+ maTaskResizeHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+TaskButtonBar* TaskBar::CreateButtonBar()
+{
+ return new TaskButtonBar( this );
+}
+
+// -----------------------------------------------------------------------
+
+TaskToolBox* TaskBar::CreateTaskToolBox()
+{
+ return new TaskToolBox( this );
+}
+
+// -----------------------------------------------------------------------
+
+TaskStatusBar* TaskBar::CreateTaskStatusBar()
+{
+ return new TaskStatusBar( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( mnWinBits & WB_SIZEABLE )
+ {
+ TaskToolBox* pTempTaskToolBox = GetTaskToolBox();
+ TaskStatusBar* pTempStatusBar = GetStatusBar();
+
+ if ( pTempTaskToolBox && pTempStatusBar )
+ {
+ long nStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
+ long nMouseX = rMEvt.GetPosPixel().X();
+ PointerStyle ePtrStyle;
+ if ( (nMouseX >= nStatusX-1) && (nMouseX <= nStatusX+3) )
+ ePtrStyle = POINTER_HSIZEBAR;
+ else
+ ePtrStyle = POINTER_ARROW;
+ Pointer aPtr( ePtrStyle );
+ SetPointer( aPtr );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && (mnWinBits & WB_SIZEABLE) )
+ {
+ TaskToolBox* pTempTaskToolBox = GetTaskToolBox();
+ TaskStatusBar* pTempStatusBar = GetStatusBar();
+
+ if ( pTempTaskToolBox && pTempStatusBar )
+ {
+ long nStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
+ long nMouseX = rMEvt.GetPosPixel().X();
+ if ( (nMouseX >= nStatusX-1) && (nMouseX <= nStatusX+3) )
+ {
+ if ( rMEvt.GetClicks() == 2 )
+ {
+ if ( mnStatusWidth )
+ {
+ mnStatusWidth = 0;
+ Resize();
+ }
+ }
+ else
+ {
+ StartTracking();
+ mnOldStatusWidth = mnStatusWidth;
+ mnMouseOff = nMouseX-nStatusX;
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::Tracking( const TrackingEvent& rTEvt )
+{
+ if ( rTEvt.IsTrackingEnded() )
+ {
+ if ( rTEvt.IsTrackingCanceled() )
+ {
+ mnStatusWidth = mnOldStatusWidth;
+ Resize();
+ Update();
+ }
+ }
+ else
+ {
+ Size aSize = GetOutputSizePixel();
+
+ long nMouseX = rTEvt.GetMouseEvent().GetPosPixel().X()-mnMouseOff;
+ if ( nMouseX < 0 )
+ nMouseX = 0;
+ long nMaxX = aSize.Width()-TASKBAR_OFFX-TASKBAR_OFFSIZE-1;
+ if ( nMouseX > nMaxX )
+ nMouseX = nMaxX;
+ mnStatusWidth = aSize.Width()-nMouseX-TASKBAR_OFFX-TASKBAR_OFFSIZE;
+ Resize();
+ Update();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::Paint( const Rectangle& rRect )
+{
+ if ( mnWinBits & (WB_BORDER | WB_SIZEABLE) )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Size aSize = GetOutputSizePixel();
+ long nY = 0;
+
+ if ( mnWinBits & WB_BORDER )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( 0, 0 ), Point( aSize.Width()-1, 0 ) );
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( 0, 1 ), Point( aSize.Width()-1, 1 ) );
+ nY += 2;
+ }
+
+ if ( (mnWinBits & WB_SIZEABLE) )
+ {
+ //TaskButtonBar* pTempButtonBar = GetButtonBar();
+ TaskToolBox* pTempTaskToolBox = GetTaskToolBox();
+ TaskStatusBar* pTempStatusBar = GetStatusBar();
+
+ if ( pTempTaskToolBox && pTempStatusBar )
+ {
+ long nStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
+ if ( nStatusX > 0 )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( Point( nStatusX, nY ), Point( nStatusX, aSize.Height()-1 ) );
+ nStatusX++;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( Point( nStatusX, nY ), Point( nStatusX, aSize.Height()-1 ) );
+ }
+ }
+ }
+ }
+
+ Window::Paint( rRect );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::Resize()
+{
+ if ( !IsReallyShown() )
+ return;
+
+ TaskButtonBar* pTempButtonBar = GetButtonBar();
+ TaskToolBox* pTempTaskToolBox = GetTaskToolBox();
+ TaskStatusBar* pTempStatusBar = GetStatusBar();
+ Point aToolPos( TASKBAR_OFFX, 0 );
+ Size aSize = GetOutputSizePixel();
+ Size aStatusSize;
+ Size aToolSize( aSize.Width()-(TASKBAR_OFFX*2), 0 );
+ long nOldStatusX = -1;
+ long nNewStatusX = -1;
+ long nTaskHeight = aSize.Height() - (TASKBAR_OFFY*2);
+
+ if ( mnWinBits & WB_BORDER )
+ {
+ nTaskHeight -= TASKBAR_BORDER;
+ aToolPos.Y() += TASKBAR_BORDER;
+ }
+
+ if ( pTempButtonBar )
+ {
+ sal_uInt16 i = 0;
+ sal_Bool bVisibleItems = sal_False;
+ while ( i < pTempButtonBar->GetItemCount() )
+ {
+ if ( pTempButtonBar->IsItemVisible( pTempButtonBar->GetItemId( i ) ) )
+ {
+ bVisibleItems = sal_True;
+ break;
+ }
+ i++;
+ }
+ if ( mbStatusText || !bVisibleItems )
+ pTempButtonBar->Hide();
+ else
+ {
+ Size aButtonBarSize = pTempButtonBar->CalcWindowSizePixel();
+ if ( pTempButtonBar->GetItemCount() )
+ nTaskHeight = aButtonBarSize.Height();
+ else
+ aButtonBarSize.Height() = nTaskHeight;
+ Point aTempPos = aToolPos;
+ aTempPos.Y() += (aSize.Height()-aButtonBarSize.Height()-aTempPos.Y())/2;
+ pTempButtonBar->SetPosSizePixel( aTempPos, aButtonBarSize );
+ pTempButtonBar->Show();
+ aToolPos.X() += aButtonBarSize.Width()+TASKBAR_BUTTONOFF;
+ }
+ }
+
+ if ( pTempStatusBar )
+ {
+ aStatusSize = pTempStatusBar->CalcWindowSizePixel();
+ if ( mnStatusWidth )
+ aStatusSize.Width() = mnStatusWidth;
+ if ( !pTempTaskToolBox || mbStatusText )
+ aStatusSize.Width() = aSize.Width();
+ long nMaxHeight = aSize.Height()-(TASKBAR_OFFY*2);
+ if ( mnWinBits & WB_BORDER )
+ nMaxHeight -= TASKBAR_BORDER;
+ if ( nMaxHeight+2 > aStatusSize.Height() )
+ aStatusSize.Height() = nMaxHeight;
+ Point aPos( aSize.Width()-aStatusSize.Width(), 0 );
+ if ( pTempTaskToolBox && (mnWinBits & WB_SIZEABLE) && !mbStatusText )
+ {
+ long nMinToolWidth = aToolPos.X()+50;
+ if ( aPos.X() < nMinToolWidth )
+ {
+ aStatusSize.Width() -= nMinToolWidth-aPos.X();
+ aPos.X() = nMinToolWidth;
+ }
+ }
+ if ( aPos.X() < 0 )
+ {
+ aStatusSize.Width() = aSize.Width();
+ aPos.X() = 0;
+ }
+ if ( mnWinBits & WB_BORDER )
+ aPos.Y() += TASKBAR_BORDER;
+ aPos.Y() += (aSize.Height()-aStatusSize.Height()-aPos.Y())/2;
+ if ( mnWinBits & WB_SIZEABLE )
+ {
+ if ( pTempTaskToolBox )
+ {
+ nOldStatusX = pTempStatusBar->GetPosPixel().X()-TASKBAR_OFFSIZE-2;
+ nNewStatusX = aPos.X()-TASKBAR_OFFSIZE-2;
+ }
+ }
+ pTempStatusBar->SetPosSizePixel( aPos, aStatusSize );
+ pTempStatusBar->Show();
+ aToolSize.Width() = aPos.X()-aToolPos.X()-TASKBAR_OFFX;
+ if ( mnWinBits & WB_SIZEABLE )
+ aToolSize.Width() -= (TASKBAR_OFFSIZE*2)-2;
+ }
+
+ if ( pTempTaskToolBox )
+ {
+ if ( aToolSize.Width() <= 24 )
+ pTempTaskToolBox->Hide();
+ else
+ {
+ aToolSize.Height() = pTempTaskToolBox->CalcWindowSizePixel().Height();
+ if ( pTempTaskToolBox->GetItemCount() )
+ nTaskHeight = aToolSize.Height();
+ else
+ aToolSize.Height() = nTaskHeight;
+ aToolPos.Y() += (aSize.Height()-aToolSize.Height()-aToolPos.Y())/2;
+ pTempTaskToolBox->SetPosSizePixel( aToolPos, aToolSize );
+ pTempTaskToolBox->Show();
+ }
+ }
+
+ if ( nOldStatusX != nNewStatusX )
+ {
+ if ( nOldStatusX > 0 )
+ {
+ Rectangle aRect( nOldStatusX, 0, nOldStatusX+2, aSize.Height()-1 );
+ Invalidate( aRect );
+ }
+ if ( nNewStatusX > 0 )
+ {
+ Rectangle aRect( nNewStatusX, 0, nNewStatusX+2, aSize.Height()-1 );
+ Invalidate( aRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::StateChanged( StateChangedType nType )
+{
+ Window::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ Format();
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings();
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_FORMAT )
+ {
+ ImplInitSettings();
+ ImplNewHeight( CalcWindowSizePixel().Height() );
+ Format();
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Window::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ // Asyncronen StateChanged ausloesen, damit sich die
+ // TaskBar an die neuen Groessen der Child-Fenster
+ // orientieren kann
+ PostStateChanged( STATE_CHANGE_FORMAT );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::Format()
+{
+ ImplNewHeight( CalcWindowSizePixel().Height() );
+ Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::SetLines( sal_uInt16 nLines )
+{
+ mnLines = nLines;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::EnableAutoHide( sal_Bool bAutoHide )
+{
+ mbAutoHide = bAutoHide;
+
+ if ( mbAutoHide )
+ {
+ ImplNewHeight( TASKBAR_AUTOHIDE_HEIGHT );
+ }
+ else
+ {
+ ImplNewHeight( CalcWindowSizePixel().Height() );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::ShowStatusText( const String& rText )
+{
+ if ( mpStatusBar )
+ {
+ if ( !mbStatusText )
+ {
+ mbStatusText = sal_True;
+ if ( mpStatusBar->AreItemsVisible() )
+ {
+ mbShowItems = sal_True;
+ mpStatusBar->HideItems();
+ }
+ else
+ mbShowItems = sal_True;
+ maOldText = mpStatusBar->GetText();
+ Resize();
+ mpStatusBar->SetText( rText );
+ Update();
+ mpStatusBar->Update();
+ }
+ else
+ mpStatusBar->SetText( rText );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::HideStatusText()
+{
+ if ( mbStatusText && mpStatusBar )
+ {
+ mbStatusText = sal_False;
+ mpStatusBar->SetText( maOldText );
+ Resize();
+ if ( mbShowItems )
+ mpStatusBar->ShowItems();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Size TaskBar::CalcWindowSizePixel() const
+{
+ TaskButtonBar* pTempButtonBar = GetButtonBar();
+ TaskToolBox* pTempTaskToolBox = GetTaskToolBox();
+ TaskStatusBar* pTempStatusBar = GetStatusBar();
+ Size aSize;
+ long nTempHeight;
+
+ if ( pTempButtonBar && pTempButtonBar->GetItemCount() )
+ aSize.Height() = pTempButtonBar->CalcWindowSizePixel().Height()+(TASKBAR_OFFY*2);
+ if ( pTempTaskToolBox && pTempTaskToolBox->GetItemCount() )
+ {
+ nTempHeight = pTempTaskToolBox->CalcWindowSizePixel().Height()+(TASKBAR_OFFY*2);
+ if ( nTempHeight > aSize.Height() )
+ aSize.Height() = nTempHeight;
+ }
+ if ( pTempStatusBar )
+ {
+ nTempHeight = pTempStatusBar->GetSizePixel().Height();
+ if ( nTempHeight > aSize.Height() )
+ aSize.Height() = nTempHeight;
+ }
+
+ if ( mnWinBits & WB_BORDER )
+ aSize.Height() += TASKBAR_BORDER;
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+TaskButtonBar* TaskBar::GetButtonBar() const
+{
+ if ( !mpButtonBar )
+ ((TaskBar*)this)->mpButtonBar = ((TaskBar*)this)->CreateButtonBar();
+ return mpButtonBar;
+}
+
+// -----------------------------------------------------------------------
+
+TaskToolBox* TaskBar::GetTaskToolBox() const
+{
+ if ( !mpTaskToolBox )
+ ((TaskBar*)this)->mpTaskToolBox = ((TaskBar*)this)->CreateTaskToolBox();
+ return mpTaskToolBox;
+}
+
+// -----------------------------------------------------------------------
+
+TaskStatusBar* TaskBar::GetStatusBar() const
+{
+ if ( !mpStatusBar )
+ {
+ ((TaskBar*)this)->mpStatusBar = ((TaskBar*)this)->CreateTaskStatusBar();
+ if ( mpStatusBar )
+ mpStatusBar->mpNotifyTaskBar = (TaskBar*)this;
+ }
+ return mpStatusBar;
+}
diff --git a/svtools/source/control/taskbox.cxx b/svtools/source/control/taskbox.cxx
new file mode 100755
index 000000000000..798126ae37af
--- /dev/null
+++ b/svtools/source/control/taskbox.cxx
@@ -0,0 +1,349 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _TASKBAR_CXX
+
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+#include <vcl/image.hxx>
+#include <vcl/help.hxx>
+#include <svtools/taskbar.hxx>
+
+// =======================================================================
+
+#define TASKBOX_TASKOFF 3
+
+// =======================================================================
+
+struct ImplTaskItem
+{
+ Image maImage;
+ XubString maText;
+};
+
+DECLARE_LIST( ImplTaskItemList, ImplTaskItem* )
+
+// =======================================================================
+
+TaskToolBox::TaskToolBox( Window* pParent, WinBits nWinStyle ) :
+ ToolBox( pParent, nWinStyle | WB_SCROLL | WB_3DLOOK )
+{
+ mpItemList = new ImplTaskItemList;
+ mnMaxTextWidth = 0;
+ mnActiveItemId = 0;
+ mnTaskItem = 0;
+ mnSmallItem = TOOLBOX_ITEM_NOTFOUND;
+ mbMinActivate = sal_False;
+
+ SetAlign( WINDOWALIGN_BOTTOM );
+ SetButtonType( BUTTON_SYMBOLTEXT );
+}
+
+// -----------------------------------------------------------------------
+
+TaskToolBox::~TaskToolBox()
+{
+ ImplTaskItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+
+ delete mpItemList;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::ActivateTaskItem( sal_uInt16 nItemId, sal_Bool bMinActivate )
+{
+ if ( nItemId )
+ {
+ if ( nItemId != mnActiveItemId )
+ {
+ if ( mnActiveItemId )
+ CheckItem( mnActiveItemId, sal_False );
+ CheckItem( nItemId );
+ mnActiveItemId = nItemId;
+ }
+ else
+ {
+ if ( !bMinActivate )
+ return;
+
+ mbMinActivate = sal_True;
+ }
+
+ mnTaskItem = nItemId-1;
+ ActivateTask();
+ mnTaskItem = 0;
+ mbMinActivate = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::ActivateTask()
+{
+ maActivateTaskHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::ContextMenu()
+{
+ maContextMenuHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( !rMEvt.IsRight() )
+ ToolBox::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::Resize()
+{
+ mnOldItemCount = mpItemList->Count();
+ mnUpdatePos = (sal_uInt16)mnOldItemCount;
+ mnUpdateNewPos = TOOLBOX_ITEM_NOTFOUND;
+ ImplFormatTaskToolBox();
+ ToolBox::Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
+ {
+ sal_uInt16 nItemId = GetItemId( rCEvt.GetMousePosPixel() );
+// Dies machen wir nicht mehr, da es von zu vielen als stoerend empfunden wurde
+// ActivateTaskItem( nItemId );
+ mnTaskItem = nItemId-1;
+
+ maContextMenuPos = rCEvt.GetMousePosPixel();
+ ContextMenu();
+ maContextMenuPos = Point();
+ mnTaskItem = 0;
+ }
+ else
+ ToolBox::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+
+ if ( nItemId )
+ {
+ ImplTaskItem* pItem = mpItemList->GetObject( nItemId-1 );
+ if ( pItem )
+ {
+ if ( pItem->maText != GetItemText( nItemId ) )
+ {
+ Rectangle aItemRect = GetItemRect( nItemId );
+ if ( rHEvt.GetMode() & HELPMODE_QUICK )
+ Help::ShowQuickHelp( this, aItemRect, pItem->maText );
+ else
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, pItem->maText );
+ }
+ else
+ Help::ShowQuickHelp( this, Rectangle(), String() );
+ return;
+ }
+ }
+ }
+
+ ToolBox::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::Select()
+{
+ sal_uInt16 nItemId = GetCurItemId();
+ ActivateTaskItem( nItemId, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::ImplFormatTaskToolBox()
+{
+ if ( mnUpdateNewPos == TOOLBOX_ITEM_NOTFOUND )
+ {
+ // Eintraege aus der Liste entfernen
+ while ( mpItemList->Count() > mnUpdatePos )
+ delete mpItemList->Remove( (sal_uLong)mnUpdatePos );
+ mnUpdateNewPos = mnUpdatePos;
+ }
+
+ // Maximale Itemgroesse berechnen
+ long nOldMaxTextWidth = mnMaxTextWidth;
+ mnMaxTextWidth = 70;
+ if ( mpItemList->Count() )
+ {
+ long nWinSize = GetOutputSizePixel().Width()-8;
+ long nItemSize = mpItemList->GetObject(0)->maImage.GetSizePixel().Width()+7+TASKBOX_TASKOFF+2;
+ nWinSize -= mpItemList->Count()*nItemSize;
+ if ( nWinSize > 0 )
+ nWinSize /= mpItemList->Count();
+ else
+ nWinSize = 0;
+ if ( nWinSize < mnMaxTextWidth )
+ mnMaxTextWidth = nWinSize;
+ if ( (mnMaxTextWidth < nOldMaxTextWidth) ||
+ ((mnMaxTextWidth-nOldMaxTextWidth > 3) &&
+ (mnSmallItem != TOOLBOX_ITEM_NOTFOUND)) )
+ {
+ mnSmallItem = TOOLBOX_ITEM_NOTFOUND;
+ mnUpdateNewPos = 0;
+ }
+ }
+
+ // Eintraege aus der ToolBox entfernen, die ersetzt werden
+ sal_uInt16 nBtnPos = (mnUpdateNewPos*2);
+ while ( nBtnPos < GetItemCount() )
+ RemoveItem( nBtnPos );
+ if ( mnUpdateNewPos <= (mnActiveItemId-1) )
+ mnActiveItemId = 0;
+
+ // Neue Eintrage einfuegen
+ sal_uInt16 i = mnUpdateNewPos;
+ while ( i < mpItemList->Count() )
+ {
+ ImplTaskItem* pItem = mpItemList->GetObject( i );
+
+ // Textlaenge berechnen
+ XubString aText = pItem->maText;
+ if ( !aText.Len() )
+ aText = ' ';
+ long nTxtWidth = GetTextWidth( aText );
+ if ( nTxtWidth > mnMaxTextWidth )
+ {
+ if ( mnSmallItem == TOOLBOX_ITEM_NOTFOUND )
+ mnSmallItem = i;
+ // 3 == Len of "..."
+ aText.AppendAscii( "..." );
+ do
+ {
+ aText.Erase( aText.Len()-3-1, 1 );
+ nTxtWidth = GetTextWidth( aText );
+ }
+ while ( (nTxtWidth > mnMaxTextWidth) && (aText.Len() > 3) );
+ }
+
+ sal_uInt16 nItemId = i+1;
+ if ( aText.EqualsAscii( "..." ) )
+ InsertItem( nItemId, pItem->maImage, TIB_LEFT );
+ else
+ InsertItem( nItemId, pItem->maImage, aText, TIB_LEFT );
+ InsertSeparator( TOOLBOX_APPEND, TASKBOX_TASKOFF );
+ i++;
+ }
+
+ if ( mnUpdateNewPos != 0 )
+ mnMaxTextWidth = nOldMaxTextWidth;
+
+ if ( mnNewActivePos+1 != mnActiveItemId )
+ {
+ if ( mnActiveItemId )
+ CheckItem( mnActiveItemId, sal_False );
+ mnActiveItemId = mnNewActivePos+1;
+ CheckItem( mnActiveItemId );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::StartUpdateTask()
+{
+ mnOldItemCount = mpItemList->Count();
+ mnUpdatePos = 0;
+ mnUpdateNewPos = TOOLBOX_ITEM_NOTFOUND;
+ mnNewActivePos = 0xFFFE;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::UpdateTask( const Image& rImage, const String& rText,
+ sal_Bool bActive )
+{
+ ImplTaskItem* pItem = mpItemList->GetObject( mnUpdatePos );
+ if ( pItem )
+ {
+ if ( (pItem->maText != rText) || (pItem->maImage != rImage) )
+ {
+ // Eintraege aus der Liste entfernen
+ while ( mpItemList->Count() > mnUpdatePos )
+ delete mpItemList->Remove( (sal_uLong)mnUpdatePos );
+ pItem = NULL;
+ }
+ }
+
+ if ( !pItem )
+ {
+ if ( mnUpdatePos < mnUpdateNewPos )
+ mnUpdateNewPos = mnUpdatePos;
+
+ pItem = new ImplTaskItem;
+ pItem->maImage = rImage;
+ pItem->maText = rText;
+ mpItemList->Insert( pItem, LIST_APPEND );
+ }
+
+ if ( bActive )
+ mnNewActivePos = mnUpdatePos;
+
+ mnUpdatePos++;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::EndUpdateTask()
+{
+ if ( mnUpdateNewPos == TOOLBOX_ITEM_NOTFOUND )
+ {
+ // Eintraege aus der Liste entfernen
+ while ( mpItemList->Count() > mnUpdatePos )
+ delete mpItemList->Remove( (sal_uLong)mnUpdatePos );
+ mnUpdateNewPos = mnUpdatePos;
+ }
+
+ ImplFormatTaskToolBox();
+}
+
diff --git a/svtools/source/control/taskmisc.cxx b/svtools/source/control/taskmisc.cxx
new file mode 100755
index 000000000000..35d5d8997624
--- /dev/null
+++ b/svtools/source/control/taskmisc.cxx
@@ -0,0 +1,377 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _TASKBAR_CXX
+
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+#include <vcl/help.hxx>
+#include <svtools/taskbar.hxx>
+
+// =======================================================================
+
+TaskButtonBar::TaskButtonBar( Window* pParent, WinBits nWinStyle ) :
+ ToolBox( pParent, nWinStyle | WB_3DLOOK )
+{
+ SetAlign( WINDOWALIGN_BOTTOM );
+ SetButtonType( BUTTON_SYMBOLTEXT );
+}
+
+// -----------------------------------------------------------------------
+
+TaskButtonBar::~TaskButtonBar()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void TaskButtonBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ ToolBox::RequestHelp( rHEvt );
+}
+
+// =======================================================================
+
+WindowArrange::WindowArrange()
+{
+ mpWinList = new List;
+}
+
+// -----------------------------------------------------------------------
+
+WindowArrange::~WindowArrange()
+{
+ delete mpWinList;
+}
+
+// -----------------------------------------------------------------------
+
+static sal_uInt16 ImplCeilSqareRoot( sal_uInt16 nVal )
+{
+ sal_uInt16 i;
+
+ // Ueberlauf verhindern
+ if ( nVal > 0xFE * 0xFE )
+ return 0xFE;
+
+ for ( i=0; i*i < nVal; i++ )
+ {}
+
+ return i;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplPosSizeWindow( Window* pWindow,
+ long nX, long nY, long nWidth, long nHeight )
+{
+ if ( nWidth < 32 )
+ nWidth = 32;
+ if ( nHeight < 24 )
+ nHeight = 24;
+ pWindow->SetPosSizePixel( nX, nY, nWidth, nHeight );
+}
+
+// -----------------------------------------------------------------------
+
+void WindowArrange::ImplTile( const Rectangle& rRect )
+{
+ sal_uInt16 nCount = (sal_uInt16)mpWinList->Count();
+ if ( nCount < 3 )
+ {
+ ImplVert( rRect );
+ return;
+ }
+
+ sal_uInt16 i;
+ sal_uInt16 j;
+ sal_uInt16 nCols;
+ sal_uInt16 nRows;
+ sal_uInt16 nActRows;
+ sal_uInt16 nOffset;
+ long nOverWidth;
+ long nOverHeight;
+ Window* pWindow;
+ long nX = rRect.Left();
+ long nY = rRect.Top();
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+ long nRectY = nY;
+ long nRectWidth = nWidth;
+ long nRectHeight = nHeight;
+ long nTempWidth;
+ long nTempHeight;
+
+ nCols = ImplCeilSqareRoot( nCount );
+ nOffset = (nCols*nCols) - nCount;
+ if ( nOffset >= nCols )
+ {
+ nRows = nCols -1;
+ nOffset = nOffset - nCols;
+ }
+ else
+ nRows = nCols;
+
+ nWidth /= nCols;
+ if ( nWidth < 1 )
+ nWidth = 1;
+ nOverWidth = nRectWidth-(nWidth*nCols);
+
+ pWindow = (Window*)mpWinList->First();
+ for ( i = 0; i < nCols; i++ )
+ {
+ if ( i < nOffset )
+ nActRows = nRows - 1;
+ else
+ nActRows = nRows;
+
+ nTempWidth = nWidth;
+ if ( nOverWidth > 0 )
+ {
+ nTempWidth++;
+ nOverWidth--;
+ }
+
+ nHeight = nRectHeight / nActRows;
+ if ( nHeight < 1 )
+ nHeight = 1;
+ nOverHeight = nRectHeight-(nHeight*nActRows);
+ for ( j = 0; j < nActRows; j++ )
+ {
+ // Ueberhang verteilen
+ nTempHeight = nHeight;
+ if ( nOverHeight > 0 )
+ {
+ nTempHeight++;
+ nOverHeight--;
+ }
+ ImplPosSizeWindow( pWindow, nX, nY, nTempWidth, nTempHeight );
+ nY += nTempHeight;
+
+ pWindow = (Window*)mpWinList->Next();
+ if ( !pWindow )
+ break;
+ }
+
+ nX += nWidth;
+ nY = nRectY;
+
+ if ( !pWindow )
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WindowArrange::ImplHorz( const Rectangle& rRect )
+{
+ long nCount = (long)mpWinList->Count();
+ long nX = rRect.Left();
+ long nY = rRect.Top();
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+ long nRectHeight = nHeight;
+ long nOver;
+ long nTempHeight;
+ Window* pWindow;
+
+ nHeight /= nCount;
+ if ( nHeight < 1 )
+ nHeight = 1;
+ nOver = nRectHeight - (nCount*nHeight);
+ pWindow = (Window*)mpWinList->First();
+ while ( pWindow )
+ {
+ nTempHeight = nHeight;
+ if ( nOver > 0 )
+ {
+ nTempHeight++;
+ nOver--;
+ }
+ ImplPosSizeWindow( pWindow, nX, nY, nWidth, nTempHeight );
+ nY += nTempHeight;
+
+ pWindow = (Window*)mpWinList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WindowArrange::ImplVert( const Rectangle& rRect )
+{
+ long nCount = (long)mpWinList->Count();
+ long nX = rRect.Left();
+ long nY = rRect.Top();
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+ long nRectWidth = nWidth;
+ long nOver;
+ long nTempWidth;
+ Window* pWindow;
+
+ nWidth /= nCount;
+ if ( nWidth < 1 )
+ nWidth = 1;
+ nOver = nRectWidth - (nCount*nWidth);
+ pWindow = (Window*)mpWinList->First();
+ while ( pWindow )
+ {
+ nTempWidth = nWidth;
+ if ( nOver > 0 )
+ {
+ nTempWidth++;
+ nOver--;
+ }
+ ImplPosSizeWindow( pWindow, nX, nY, nTempWidth, nHeight );
+ nX += nTempWidth;
+
+ pWindow = (Window*)mpWinList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WindowArrange::ImplCascade( const Rectangle& rRect )
+{
+ long nX = rRect.Left();
+ long nY = rRect.Top();
+ long nWidth = rRect.GetWidth();
+ long nHeight = rRect.GetHeight();
+ long nRectWidth = nWidth;
+ long nRectHeight = nHeight;
+ long nOff;
+ long nCascadeWins;
+ sal_Int32 nLeftBorder;
+ sal_Int32 nTopBorder;
+ sal_Int32 nRightBorder;
+ sal_Int32 nBottomBorder;
+ long nStartOverWidth;
+ long nStartOverHeight;
+ long nOverWidth = 0;
+ long nOverHeight = 0;
+ long nTempX;
+ long nTempY;
+ long nTempWidth;
+ long nTempHeight;
+ long i;
+ Window* pWindow;
+ Window* pTempWindow;
+
+ // Border-Fenster suchen um den Versatz zu ermitteln
+ pTempWindow = (Window*)mpWinList->First();
+ pTempWindow->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ while ( !nTopBorder )
+ {
+ Window* pBrdWin = pTempWindow->GetWindow( WINDOW_REALPARENT );
+ if ( !pBrdWin || (pBrdWin->GetWindow( WINDOW_CLIENT ) != pTempWindow) )
+ break;
+ pTempWindow = pBrdWin;
+ pTempWindow->GetBorder( nLeftBorder, nTopBorder, nRightBorder, nBottomBorder );
+ }
+ if ( !nTopBorder )
+ nTopBorder = 22;
+ nOff = nTopBorder;
+
+ nCascadeWins = nRectHeight / 3 / nOff;
+ if ( !nCascadeWins )
+ nCascadeWins = 1;
+ nWidth -= nCascadeWins*nOff;
+ nHeight -= nCascadeWins*nOff;
+ if ( nWidth < 1 )
+ nWidth = 1;
+ if ( nHeight < 1 )
+ nHeight = 1;
+
+ nStartOverWidth = nRectWidth-(nWidth+(nCascadeWins*nOff));
+ nStartOverHeight = nRectHeight-(nHeight+(nCascadeWins*nOff));
+
+ i = 0;
+ pWindow = (Window*)mpWinList->First();
+ while ( pWindow )
+ {
+ if ( !i )
+ {
+ nOverWidth = nStartOverWidth;
+ nOverHeight = nStartOverHeight;
+ }
+
+ // Position
+ nTempX = nX + (i*nOff);
+ nTempY = nY + (i*nOff);
+
+ // Ueberhang verteilen
+ nTempWidth = nWidth;
+ if ( nOverWidth > 0 )
+ {
+ nTempWidth++;
+ nOverWidth--;
+ }
+ nTempHeight = nHeight;
+ if ( nOverHeight > 0 )
+ {
+ nTempHeight++;
+ nOverHeight--;
+ }
+
+ ImplPosSizeWindow( pWindow, nTempX, nTempY, nTempWidth, nTempHeight );
+
+ if ( i < nCascadeWins )
+ i++;
+ else
+ i = 0;
+
+ pWindow = (Window*)mpWinList->Next();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void WindowArrange::Arrange( sal_uInt16 nType, const Rectangle& rRect )
+{
+ if ( !mpWinList->Count() )
+ return;
+
+ switch ( nType )
+ {
+ case WINDOWARRANGE_TILE:
+ ImplTile( rRect );
+ break;
+ case WINDOWARRANGE_HORZ:
+ ImplHorz( rRect );
+ break;
+ case WINDOWARRANGE_VERT:
+ ImplVert( rRect );
+ break;
+ case WINDOWARRANGE_CASCADE:
+ ImplCascade( rRect );
+ break;
+ }
+}
+
diff --git a/svtools/source/control/taskstat.cxx b/svtools/source/control/taskstat.cxx
new file mode 100755
index 000000000000..7792fe32bff8
--- /dev/null
+++ b/svtools/source/control/taskstat.cxx
@@ -0,0 +1,653 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _TASKBAR_CXX
+
+#include <tools/list.hxx>
+#include <tools/debug.hxx>
+#include <tools/date.hxx>
+#include <vcl/image.hxx>
+#include <vcl/help.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/calendarwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <svtools/taskbar.hxx>
+
+// =======================================================================
+
+#define TASKSTATUSBAR_CLOCXOFFX 3
+#define TASKSTATUSBAR_IMAGEOFFX 1
+
+// =======================================================================
+
+struct ImplTaskSBFldItem
+{
+ TaskStatusFieldItem maItem;
+ sal_uInt16 mnId;
+ long mnOffX;
+};
+
+DECLARE_LIST( ImplTaskSBItemList, ImplTaskSBFldItem* )
+
+// =======================================================================
+
+sal_Bool ITaskStatusNotify::MouseButtonDown( sal_uInt16, const MouseEvent& )
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ITaskStatusNotify::MouseButtonUp( sal_uInt16, const MouseEvent& )
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ITaskStatusNotify::MouseMove( sal_uInt16, const MouseEvent& )
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ITaskStatusNotify::Command( sal_uInt16, const CommandEvent& )
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ITaskStatusNotify::UpdateHelp( sal_uInt16 )
+{
+ return sal_False;
+}
+
+// =======================================================================
+
+TaskStatusFieldItem::TaskStatusFieldItem()
+{
+ mpNotify = NULL;
+ mnFlags = 0;
+}
+
+// -----------------------------------------------------------------------
+
+TaskStatusFieldItem::TaskStatusFieldItem( const TaskStatusFieldItem& rItem ) :
+ mpNotify( rItem.mpNotify ),
+ maImage( rItem.maImage ),
+ maQuickHelpText( rItem.maQuickHelpText ),
+ maHelpText( rItem.maHelpText ),
+ mnFlags( rItem.mnFlags )
+{
+}
+
+// -----------------------------------------------------------------------
+
+TaskStatusFieldItem::TaskStatusFieldItem( ITaskStatusNotify* pNotify,
+ const Image& rImage,
+ const XubString& rQuickHelpText,
+ const XubString& rHelpText,
+ sal_uInt16 nFlags ) :
+ mpNotify( pNotify ),
+ maImage( rImage ),
+ maQuickHelpText( rQuickHelpText ),
+ maHelpText( rHelpText ),
+ mnFlags( nFlags )
+{
+}
+
+// -----------------------------------------------------------------------
+
+TaskStatusFieldItem::~TaskStatusFieldItem()
+{
+}
+
+// -----------------------------------------------------------------------
+
+const TaskStatusFieldItem& TaskStatusFieldItem::operator=( const TaskStatusFieldItem& rItem )
+{
+ mpNotify = rItem.mpNotify;
+ maImage = rItem.maImage;
+ maQuickHelpText = rItem.maQuickHelpText;
+ maHelpText = rItem.maHelpText;
+ mnFlags = rItem.mnFlags;
+ return *this;
+}
+
+// =======================================================================
+
+TaskStatusBar::TaskStatusBar( Window* pParent, WinBits nWinStyle ) :
+ StatusBar( pParent, nWinStyle | WB_3DLOOK ),
+ maTime( 0, 0, 0 )
+{
+ mpFieldItemList = NULL;
+ mpNotifyTaskBar = NULL;
+ mpNotify = NULL;
+ mnClockWidth = 0;
+ mnItemWidth = 0;
+ mnFieldWidth = 0;
+ mnFieldFlags = 0;
+ mbFlashItems = sal_False;
+ mbOutInterval = sal_False;
+
+ maTimer.SetTimeoutHdl( LINK( this, TaskStatusBar, ImplTimerHdl ) );
+}
+
+// -----------------------------------------------------------------------
+
+TaskStatusBar::~TaskStatusBar()
+{
+ if ( mpFieldItemList )
+ {
+ ImplTaskSBFldItem* pItem = mpFieldItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpFieldItemList->Next();
+ }
+
+ delete mpFieldItemList;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( TaskStatusBar, ImplTimerHdl, Timer*, EMPTYARG )
+{
+ sal_Bool bUpdate = ImplUpdateClock();
+ if ( ImplUpdateFlashItems() )
+ bUpdate = sal_True;
+ if ( bUpdate )
+ SetItemData( TASKSTATUSBAR_STATUSFIELDID, NULL );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplTaskSBFldItem* TaskStatusBar::ImplGetFieldItem( sal_uInt16 nItemId ) const
+{
+ if ( !mpFieldItemList )
+ return NULL;
+
+ ImplTaskSBFldItem* pItem = mpFieldItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return pItem;
+
+ pItem = mpFieldItemList->Next();
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+ImplTaskSBFldItem* TaskStatusBar::ImplGetFieldItem( const Point& rPos, sal_Bool& rFieldRect ) const
+{
+ if ( GetItemId( rPos ) == TASKSTATUSBAR_STATUSFIELDID )
+ {
+ rFieldRect = sal_True;
+
+ if ( mpFieldItemList )
+ {
+ long nX = rPos.X()-GetItemRect( TASKSTATUSBAR_STATUSFIELDID ).Left();
+ ImplTaskSBFldItem* pItem = mpFieldItemList->First();
+ while ( pItem )
+ {
+ if ( nX < pItem->mnOffX+pItem->maItem.GetImage().GetSizePixel().Width() )
+ return pItem;
+
+ pItem = mpFieldItemList->Next();
+ }
+ }
+ }
+ else
+ rFieldRect = sal_False;
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TaskStatusBar::ImplUpdateClock()
+{
+ if ( mnFieldFlags & TASKSTATUSFIELD_CLOCK )
+ {
+ Time aTime;
+ maTimer.SetTimeout( ((long)60000)-((aTime.GetSec()*1000)+(aTime.Get100Sec()*10)) );
+ if ( (aTime.GetMin() != maTime.GetMin()) ||
+ (aTime.GetHour() != maTime.GetHour()) )
+ {
+ maTime = aTime;
+ maTimeText = SvtSysLocale().GetLocaleData().getTime( aTime, sal_False, sal_False );
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TaskStatusBar::ImplUpdateFlashItems()
+{
+ if ( mbFlashItems )
+ {
+ if ( mbOutInterval )
+ {
+ maTimer.SetTimeout( 900 );
+ mbOutInterval = sal_False;
+ }
+ else
+ {
+ maTimer.SetTimeout( 700 );
+ mbOutInterval = sal_True;
+ }
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::ImplUpdateField( sal_Bool bItems )
+{
+ maTimer.Stop();
+
+ if ( bItems )
+ {
+ ImplTaskSBFldItem* pItem = mpFieldItemList->First();
+ mnItemWidth = 0;
+ mbFlashItems = sal_False;
+ mbOutInterval = sal_False;
+ while ( pItem )
+ {
+ mnItemWidth += TASKSTATUSBAR_IMAGEOFFX;
+ pItem->mnOffX = mnItemWidth;
+ mnItemWidth += pItem->maItem.GetImage().GetSizePixel().Width();
+ if ( pItem->maItem.GetFlags() & TASKSTATUSFIELDITEM_FLASH )
+ mbFlashItems = sal_True;
+
+ pItem = mpFieldItemList->Next();
+ }
+ }
+ else
+ {
+ if ( mnFieldFlags & TASKSTATUSFIELD_CLOCK )
+ {
+ XubString aStr = SvtSysLocale().GetLocaleData().getTime( Time( 23, 59, 59 ), sal_False, sal_False );
+ mnClockWidth = GetTextWidth( aStr )+(TASKSTATUSBAR_CLOCXOFFX*2);
+ }
+ else
+ mnClockWidth = 0;
+ }
+
+ long nNewWidth = mnItemWidth+mnClockWidth;
+ if ( mnItemWidth && !mnClockWidth )
+ nNewWidth += TASKSTATUSBAR_IMAGEOFFX;
+ if ( nNewWidth != mnFieldWidth )
+ {
+ RemoveItem( TASKSTATUSBAR_STATUSFIELDID );
+
+ if ( mnItemWidth || mnClockWidth )
+ {
+ mnFieldWidth = nNewWidth;
+ long nOffset = GetItemOffset( TASKSTATUSBAR_STATUSFIELDID );
+ sal_uInt16 nItemPos = GetItemPos( TASKSTATUSBAR_STATUSFIELDID );
+ InsertItem( TASKSTATUSBAR_STATUSFIELDID, nNewWidth, SIB_RIGHT | SIB_IN | SIB_USERDRAW, nOffset, nItemPos );
+ }
+ else
+ mnFieldWidth = 0;
+
+ if ( mpNotifyTaskBar )
+ mpNotifyTaskBar->Resize();
+ }
+ else
+ SetItemData( TASKSTATUSBAR_STATUSFIELDID, NULL );
+
+ if ( mbFlashItems || (mnFieldFlags & TASKSTATUSFIELD_CLOCK) )
+ {
+ ImplUpdateClock();
+ mbOutInterval = sal_True;
+ ImplUpdateFlashItems();
+ maTimer.Start();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ sal_Bool bFieldRect;
+ sal_Bool bBaseClass = sal_False;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ sal_uInt16 nItemId = 0;
+
+ if ( bFieldRect )
+ nItemId = TASKSTATUSBAR_CLOCKID;
+
+ if ( pItem )
+ {
+ pNotify = pItem->maItem.GetNotifyObject();
+ nItemId = pItem->mnId;
+ }
+
+ if ( pNotify )
+ bBaseClass = pNotify->MouseButtonDown( nItemId, rMEvt );
+
+ if ( bBaseClass )
+ StatusBar::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ sal_Bool bFieldRect;
+ sal_Bool bBaseClass = sal_False;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ sal_uInt16 nItemId = 0;
+
+ if ( bFieldRect )
+ nItemId = TASKSTATUSBAR_CLOCKID;
+
+ if ( pItem )
+ {
+ pNotify = pItem->maItem.GetNotifyObject();
+ nItemId = pItem->mnId;
+ }
+
+ if ( pNotify )
+ bBaseClass = pNotify->MouseButtonUp( nItemId, rMEvt );
+
+ if ( bBaseClass )
+ StatusBar::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::MouseMove( const MouseEvent& rMEvt )
+{
+ sal_Bool bFieldRect;
+ sal_Bool bBaseClass = sal_False;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ sal_uInt16 nItemId = 0;
+
+ if ( bFieldRect )
+ nItemId = TASKSTATUSBAR_CLOCKID;
+
+ if ( pItem )
+ {
+ pNotify = pItem->maItem.GetNotifyObject();
+ nItemId = pItem->mnId;
+ }
+
+ if ( pNotify )
+ bBaseClass = pNotify->MouseMove( nItemId, rMEvt );
+
+ if ( bBaseClass )
+ StatusBar::MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::Command( const CommandEvent& rCEvt )
+{
+ sal_Bool bFieldRect;
+ sal_Bool bBaseClass = sal_False;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rCEvt.GetMousePosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ sal_uInt16 nItemId = 0;
+
+ if ( bFieldRect )
+ nItemId = TASKSTATUSBAR_CLOCKID;
+
+ if ( pItem )
+ {
+ pNotify = pItem->maItem.GetNotifyObject();
+ nItemId = pItem->mnId;
+ }
+
+ if ( pNotify )
+ bBaseClass = pNotify->Command( nItemId, rCEvt );
+
+ if ( bBaseClass )
+ StatusBar::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ sal_Bool bFieldRect;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ), bFieldRect );
+ if ( bFieldRect )
+ {
+ ITaskStatusNotify* pNotify = mpNotify;
+ sal_uInt16 nItemId = 0;
+
+ if ( pItem )
+ {
+ pNotify = pItem->maItem.GetNotifyObject();
+ nItemId = pItem->mnId;
+ }
+
+ if ( pNotify )
+ pNotify->UpdateHelp( nItemId );
+
+ if ( rHEvt.GetMode() & (HELPMODE_BALLOON | HELPMODE_QUICK) )
+ {
+ Rectangle aItemRect = GetItemRect( TASKSTATUSBAR_STATUSFIELDID );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ if ( pItem )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ {
+ XubString aStr = pItem->maItem.GetHelpText();
+ if ( !aStr.Len() )
+ aStr = pItem->maItem.GetQuickHelpText();
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ }
+ else
+ Help::ShowQuickHelp( this, aItemRect, pItem->maItem.GetQuickHelpText() );
+ }
+ else
+ {
+ SvtSysLocale aSL;
+ const LocaleDataWrapper& rLDW = aSL.GetLocaleData();
+ CalendarWrapper aCal( rLDW.getServiceFactory());
+ aCal.loadDefaultCalendar( rLDW.getLoadedLocale());
+ XubString aStr = rLDW.getLongDate( Date(), aCal );
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aStr );
+ else
+ Help::ShowQuickHelp( this, aItemRect, aStr );
+ }
+ return;
+ }
+ else if ( rHEvt.GetMode() & HELPMODE_EXTENDED )
+ {
+ if ( pItem )
+ {
+ rtl::OUString aHelpId( rtl::OStringToOUString( pItem->maItem.GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
+ if ( aHelpId.getLength() )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( aHelpId, this );
+ return;
+ }
+ }
+ }
+ }
+
+ StatusBar::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::UserDraw( const UserDrawEvent& rUDEvt )
+{
+ if ( rUDEvt.GetItemId() == TASKSTATUSBAR_STATUSFIELDID )
+ {
+ OutputDevice* pDev = rUDEvt.GetDevice();
+ Rectangle aRect = rUDEvt.GetRect();
+
+ if ( mpFieldItemList )
+ {
+ ImplTaskSBFldItem* pItem = mpFieldItemList->First();
+ while ( pItem )
+ {
+ if ( !mbOutInterval || !(pItem->maItem.GetFlags() & TASKSTATUSFIELDITEM_FLASH) )
+ {
+ const Image& rImage = pItem->maItem.GetImage();
+ Size aImgSize = rImage.GetSizePixel();
+ pDev->DrawImage( Point( aRect.Left()+pItem->mnOffX,
+ aRect.Top()+((aRect.GetHeight()-aImgSize.Width())/2) ),
+ rImage );
+ }
+
+ pItem = mpFieldItemList->Next();
+ }
+ }
+
+ if ( mnFieldFlags & TASKSTATUSFIELD_CLOCK )
+ {
+ long nX = mnItemWidth+TASKSTATUSBAR_CLOCXOFFX;
+ Point aPos = GetItemTextPos( TASKSTATUSBAR_STATUSFIELDID );
+ aPos.X() = aRect.Left()+nX;
+ pDev->DrawText( aPos, maTimeText );
+ }
+ }
+ else
+ StatusBar::UserDraw( rUDEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::InsertStatusField( long, sal_uInt16,
+ sal_uInt16 nFlags )
+{
+ mnFieldFlags = nFlags;
+ ImplUpdateField( sal_False );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::SetFieldFlags( sal_uInt16 nFlags )
+{
+ if ( mnFieldFlags != nFlags )
+ {
+ mnFieldFlags = nFlags;
+ ImplUpdateField( sal_False );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::AddStatusFieldItem( sal_uInt16 nItemId, const TaskStatusFieldItem& rItem,
+ sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "TaskStatusBar::AddStatusFieldItem() - Item is 0" );
+ DBG_ASSERT( !ImplGetFieldItem( nItemId ), "TaskStatusBar::AddStatusFieldItem() - Item-Id already exist" );
+
+ if ( !mpFieldItemList )
+ mpFieldItemList = new ImplTaskSBItemList;
+
+ ImplTaskSBFldItem* pItem = new ImplTaskSBFldItem;
+ pItem->maItem = rItem;
+ pItem->mnId = nItemId;
+ pItem->mnOffX = 0;
+ mpFieldItemList->Insert( pItem, (sal_uLong)nPos );
+
+ ImplUpdateField( sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::ModifyStatusFieldItem( sal_uInt16 nItemId, const TaskStatusFieldItem& rItem )
+{
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId );
+ if ( pItem )
+ {
+ sal_Bool bUpdate = (pItem->maItem.GetImage() != rItem.GetImage()) ||
+ (pItem->maItem.GetFlags() != rItem.GetFlags());
+ pItem->maItem = rItem;
+ if ( bUpdate )
+ ImplUpdateField( sal_True );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::RemoveStatusFieldItem( sal_uInt16 nItemId )
+{
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId );
+ if ( pItem )
+ {
+ mpFieldItemList->Remove( pItem );
+ delete pItem;
+ ImplUpdateField( sal_True );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool TaskStatusBar::GetStatusFieldItem( sal_uInt16 nItemId, TaskStatusFieldItem& rItem ) const
+{
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId );
+ if ( pItem )
+ {
+ rItem = pItem->maItem;
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx
new file mode 100644
index 000000000000..c84eb17afecc
--- /dev/null
+++ b/svtools/source/control/toolbarmenu.cxx
@@ -0,0 +1,1805 @@
+/*************************************************************************
+ *
+ * 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 <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include <vcl/dockwin.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/image.hxx>
+#include <vcl/taskpanelist.hxx>
+#include <vcl/toolbox.hxx>
+
+#include "svtools/valueset.hxx"
+#include "svtools/toolbarmenu.hxx"
+#include "toolbarmenuimp.hxx"
+
+using ::rtl::OUString;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::accessibility;
+
+namespace svtools {
+
+// --------------------------------------------------------------------
+
+static Window* GetTopMostParentSystemWindow( Window* pWindow )
+{
+ OSL_ASSERT( pWindow );
+ if ( pWindow )
+ {
+ // ->manually search topmost system window
+ // required because their might be another system window between this and the top window
+ pWindow = pWindow->GetParent();
+ SystemWindow* pTopMostSysWin = NULL;
+ while ( pWindow )
+ {
+ if ( pWindow->IsSystemWindow() )
+ pTopMostSysWin = (SystemWindow*)pWindow;
+ pWindow = pWindow->GetParent();
+ }
+ pWindow = pTopMostSysWin;
+ OSL_ASSERT( pWindow );
+ return pWindow;
+ }
+
+ return NULL;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenuEntry::init( int nEntryId, MenuItemBits nBits )
+{
+ mnEntryId = nEntryId;
+ mnBits = nBits;
+
+ mbHasText = false;
+ mbHasImage = false;
+ mbChecked = false;
+ mbEnabled = true;
+
+ mpControl = NULL;
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits )
+: mrMenu( rMenu )
+{
+ init( nEntryId, nBits );
+
+ maText = rText;
+ mbHasText = true;
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits )
+: mrMenu( rMenu )
+{
+ init( nEntryId, nBits );
+
+ maImage = rImage;
+ mbHasImage = true;
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits )
+: mrMenu( rMenu )
+{
+ init( nEntryId, nBits );
+
+ maText = rText;
+ mbHasText = true;
+
+ maImage = rImage;
+ mbHasImage = true;
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits )
+: mrMenu( rMenu )
+{
+ init( nEntryId, nBits );
+
+ if( pControl )
+ {
+ mpControl = pControl;
+ mpControl->Show();
+ }
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry::~ToolbarMenuEntry()
+{
+ if( mxAccContext.is() )
+ {
+ Reference< XComponent > xComponent( mxAccContext, UNO_QUERY );
+ if( xComponent.is() )
+ xComponent->dispose();
+ mxAccContext.clear();
+ }
+ delete mpControl;
+}
+
+// --------------------------------------------------------------------
+
+const Reference< XAccessibleContext >& ToolbarMenuEntry::GetAccessible( bool bCreate /* = false */ )
+{
+ if( !mxAccContext.is() && bCreate )
+ {
+ if( mpControl )
+ {
+ mxAccContext = Reference< XAccessibleContext >( mpControl->GetAccessible( sal_True ), UNO_QUERY );
+ }
+ else
+ {
+ mxAccContext = Reference< XAccessibleContext >( new ToolbarMenuEntryAcc( this ) );
+ }
+ }
+
+ return mxAccContext;
+}
+
+// --------------------------------------------------------------------
+
+sal_Int32 ToolbarMenuEntry::getAccessibleChildCount() throw (RuntimeException)
+{
+ if( mpControl )
+ {
+ const Reference< XAccessibleContext >& xContext = GetAccessible( true );
+ if( xContext.is() )
+ {
+ return xContext->getAccessibleChildCount();
+ }
+ }
+ return 1;
+}
+
+// --------------------------------------------------------------------
+
+Reference< XAccessible > ToolbarMenuEntry::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const Reference< XAccessibleContext >& xContext = GetAccessible( true );
+ if( mpControl )
+ {
+ if( xContext.is() )
+ {
+ return xContext->getAccessibleChild(index);
+ }
+ }
+ else if( index == 0 )
+ {
+ Reference< XAccessible > xRet( xContext, UNO_QUERY );
+ if( xRet.is() )
+ return xRet;
+ }
+
+ throw IndexOutOfBoundsException();
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenu_Impl::ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame )
+: mrMenu( rMenu )
+, mxFrame( xFrame )
+, mxServiceManager( ::comphelper::getProcessServiceFactory() )
+, mnCheckPos(0)
+, mnImagePos(0)
+, mnTextPos(0)
+, mnHighlightedEntry(-1)
+, mnSelectedEntry(-1)
+, mnLastColumn(0)
+{
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenu_Impl::~ToolbarMenu_Impl()
+{
+ setAccessible( 0 );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu_Impl::setAccessible( ToolbarMenuAcc* pAccessible )
+{
+ if( mxAccessible.get() != pAccessible )
+ {
+ if( mxAccessible.is() )
+ mxAccessible->dispose();
+
+ mxAccessible.set( pAccessible );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolbarMenu_Impl::fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue )
+{
+ if( mxAccessible.is() )
+ mxAccessible->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
+}
+
+// -----------------------------------------------------------------------
+
+bool ToolbarMenu_Impl::hasAccessibleListeners()
+{
+ return( mxAccessible.is() && mxAccessible->HasAccessibleListeners() );
+}
+
+// --------------------------------------------------------------------
+
+sal_Int32 ToolbarMenu_Impl::getAccessibleChildCount() throw (RuntimeException)
+{
+ sal_Int32 nCount = 0;
+ const int nEntryCount = maEntryVector.size();
+ for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
+ if( pEntry )
+ {
+ if( pEntry->mpControl )
+ {
+ nCount += pEntry->getAccessibleChildCount();
+ }
+ else
+ {
+ nCount += 1;
+ }
+ }
+ }
+
+ return nCount;
+}
+
+// --------------------------------------------------------------------
+
+Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const int nEntryCount = maEntryVector.size();
+ for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
+ if( pEntry )
+ {
+ const sal_Int32 nCount = pEntry->getAccessibleChildCount();
+ if( index < nCount )
+ {
+ return pEntry->getAccessibleChild( index );
+ }
+ index -= nCount;
+ }
+ }
+
+ throw IndexOutOfBoundsException();
+}
+
+// --------------------------------------------------------------------
+
+Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const int nEntryCount = maEntryVector.size();
+ for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
+ if( pEntry && (pEntry->mpControl == pControl) )
+ {
+ return pEntry->getAccessibleChild( childIndex );
+ }
+ }
+
+ throw IndexOutOfBoundsException();
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu_Impl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const int nEntryCount = maEntryVector.size();
+ for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
+ if( pEntry )
+ {
+ const sal_Int32 nCount = pEntry->getAccessibleChildCount();
+ if( nChildIndex < nCount )
+ {
+ if( pEntry->mpControl )
+ {
+ Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW );
+ xSel->selectAccessibleChild(nChildIndex);
+ }
+ else if( pEntry->mnEntryId != TITLE_ID )
+ {
+ mrMenu.implSelectEntry( nEntry );
+ }
+ return;
+ }
+ nChildIndex -= nCount;
+ }
+ }
+
+ throw IndexOutOfBoundsException();
+}
+
+// --------------------------------------------------------------------
+
+sal_Bool ToolbarMenu_Impl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const int nEntryCount = maEntryVector.size();
+ for( int nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = maEntryVector[nEntry];
+ if( pEntry )
+ {
+ const sal_Int32 nCount = pEntry->getAccessibleChildCount();
+ if( nChildIndex < nCount )
+ {
+ if( mnHighlightedEntry == nEntry )
+ {
+ if( pEntry->mpControl )
+ {
+ Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW );
+ xSel->isAccessibleChildSelected(nChildIndex);
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ nChildIndex -= nCount;
+ }
+ }
+
+ throw IndexOutOfBoundsException();
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu_Impl::clearAccessibleSelection()
+{
+ if( mnHighlightedEntry != -1 )
+ {
+ mrMenu.implHighlightEntry( mnHighlightedEntry, false );
+ mnHighlightedEntry = -1;
+ }
+}
+
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu_Impl::notifyHighlightedEntry()
+{
+ if( hasAccessibleListeners() )
+ {
+ ToolbarMenuEntry* pEntry = implGetEntry( mnHighlightedEntry );
+ if( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) )
+ {
+ Any aNew;
+ Any aOld( mxOldSelection );
+ if( pEntry->mpControl )
+ {
+ sal_Int32 nChildIndex = 0;
+ // todo: if other controls than ValueSet are allowed, addapt this code
+ ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl );
+ if( pValueSet )
+ nChildIndex = static_cast< sal_Int32 >( pValueSet->GetItemPos( pValueSet->GetSelectItemId() ) );
+
+ if( nChildIndex >= pEntry->getAccessibleChildCount() )
+ return;
+
+ aNew <<= getAccessibleChild( pEntry->mpControl, nChildIndex );
+ }
+ else
+ {
+ aNew <<= pEntry->GetAccessible(true);
+ }
+
+ fireAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOld, aNew );
+ fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOld, aNew );
+ fireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) );
+ aNew >>= mxOldSelection;
+ }
+ }
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry* ToolbarMenu_Impl::implGetEntry( int nEntry ) const
+{
+ if( (nEntry < 0) || (nEntry >= (int)maEntryVector.size() ) )
+ return NULL;
+
+ return maEntryVector[nEntry];
+}
+
+
+// --------------------------------------------------------------------
+
+IMPL_LINK( ToolbarMenu, HighlightHdl, Control *, pControl )
+{
+ (void)pControl;
+ mpImpl->notifyHighlightedEntry();
+ return 0;
+}
+
+// ====================================================================
+
+ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, WinBits nBits )
+: DockingWindow(pParentWindow, nBits)
+{
+ implInit(rFrame);
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, const ResId& rResId )
+: DockingWindow(pParentWindow, rResId)
+{
+ implInit(rFrame);
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::implInit(const Reference< XFrame >& rFrame)
+{
+ mpImpl = new ToolbarMenu_Impl( *this, rFrame );
+
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetControlBackground( rStyleSettings.GetMenuColor() );
+
+ initWindow();
+
+ Window* pWindow = GetTopMostParentSystemWindow( this );
+ if ( pWindow )
+ ((SystemWindow *)pWindow)->GetTaskPaneList()->AddWindow( this );
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenu::~ToolbarMenu()
+{
+ Window* pWindow = GetTopMostParentSystemWindow( this );
+ if ( pWindow )
+ ((SystemWindow *)pWindow)->GetTaskPaneList()->RemoveWindow( this );
+
+ if ( mpImpl->mxStatusListener.is() )
+ {
+ mpImpl->mxStatusListener->dispose();
+ mpImpl->mxStatusListener.clear();
+ }
+
+ // delete all menu entries
+ const int nEntryCount = mpImpl->maEntryVector.size();
+ int nEntry;
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ delete mpImpl->maEntryVector[nEntry];
+ }
+
+ delete mpImpl;
+}
+
+// --------------------------------------------------------------------
+
+int ToolbarMenu::getSelectedEntryId() const
+{
+ ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnSelectedEntry );
+ return pEntry ? pEntry->mnEntryId : -1;
+}
+
+// --------------------------------------------------------------------
+
+int ToolbarMenu::getHighlightedEntryId() const
+{
+ ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry );
+ return pEntry ? pEntry->mnEntryId : -1;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::checkEntry( int nEntryId, bool bChecked )
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ if( pEntry && pEntry->mbChecked != bChecked )
+ {
+ pEntry->mbChecked = bChecked;
+ Invalidate();
+ }
+}
+
+// --------------------------------------------------------------------
+
+bool ToolbarMenu::isEntryChecked( int nEntryId ) const
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ return pEntry && pEntry->mbChecked;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::enableEntry( int nEntryId, bool bEnable )
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ if( pEntry && pEntry->mbEnabled != bEnable )
+ {
+ pEntry->mbEnabled = bEnable;
+ if( pEntry->mpControl )
+ {
+ pEntry->mpControl->Enable( bEnable );
+
+ // hack for the valueset to make it paint itself anew
+ pEntry->mpControl->Resize();
+ }
+ Invalidate();
+ }
+}
+
+// --------------------------------------------------------------------
+
+bool ToolbarMenu::isEntryEnabled( int nEntryId ) const
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ return pEntry && pEntry->mbEnabled;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::setEntryText( int nEntryId, const String& rStr )
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ if( pEntry && pEntry->maText != rStr )
+ {
+ pEntry->maText = rStr;
+ mpImpl->maSize = implCalcSize();
+ if( IsVisible() )
+ Invalidate();
+ }
+}
+
+// --------------------------------------------------------------------
+
+const String& ToolbarMenu::getEntryText( int nEntryId ) const
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ if( pEntry )
+ return pEntry->maText;
+ else
+ {
+ static String aEmptyStr;
+ return aEmptyStr;
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::setEntryImage( int nEntryId, const Image& rImage )
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ if( pEntry && pEntry->maImage != rImage )
+ {
+ pEntry->maImage = rImage;
+ mpImpl->maSize = implCalcSize();
+ if( IsVisible() )
+ Invalidate();
+ }
+}
+
+// --------------------------------------------------------------------
+
+const Image& ToolbarMenu::getEntryImage( int nEntryId ) const
+{
+ ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId );
+ if( pEntry )
+ return pEntry->maImage;
+ else
+ {
+ static Image aEmptyImage;
+ return aEmptyImage;
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::initWindow()
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ SetPointFont( rStyleSettings.GetMenuFont() );
+ SetBackground( Wallpaper( GetControlBackground() ) );
+ SetTextColor( rStyleSettings.GetMenuTextColor() );
+ SetTextFillColor();
+ SetLineColor();
+
+ mpImpl->maSize = implCalcSize();
+}
+
+// --------------------------------------------------------------------
+
+Size ToolbarMenu::implCalcSize()
+{
+ const long nFontHeight = GetTextHeight();
+ long nExtra = nFontHeight/4;
+
+ Size aSz;
+ Size aMaxImgSz;
+ long nMaxTextWidth = 0;
+ long nMinMenuItemHeight = nFontHeight+2;
+ sal_Bool bCheckable = sal_False;
+
+ const int nEntryCount = mpImpl->maEntryVector.size();
+ int nEntry;
+
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+ const bool bUseImages = rSettings.GetUseImagesInMenus();
+
+ // get maximum image size
+ if( bUseImages )
+ {
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
+ if( pEntry && pEntry->mbHasImage )
+ {
+ Size aImgSz( pEntry->maImage.GetSizePixel() );
+ nMinMenuItemHeight = std::max( nMinMenuItemHeight, aImgSz.Height() + 6 );
+ aMaxImgSz.Width() = std::max( aMaxImgSz.Width(), aImgSz.Width() );
+ }
+ }
+ }
+
+ mpImpl->mnCheckPos = nExtra;
+ mpImpl->mnImagePos = nExtra;
+ mpImpl->mnTextPos = mpImpl->mnImagePos + aMaxImgSz.Width();
+
+ if ( aMaxImgSz.Width() )
+ mpImpl->mnTextPos += std::max( nExtra, 7L );
+ if ( bCheckable )
+ mpImpl->mnTextPos += 16;
+
+ // set heights, calc maximum width
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
+
+ if( pEntry )
+ {
+ if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) )
+ bCheckable = sal_True;
+
+ // Text:
+ if( pEntry->mbHasText || pEntry->mbHasImage )
+ {
+ pEntry->maSize.Height() = nMinMenuItemHeight;
+
+ if( pEntry->mbHasText )
+ {
+ long nTextWidth = GetCtrlTextWidth( pEntry->maText ) + mpImpl->mnTextPos + nExtra;
+ nMaxTextWidth = std::max( nTextWidth, nMaxTextWidth );
+ }
+ }
+ // Control:
+ else if( pEntry->mpControl )
+ {
+ Size aControlSize( pEntry->mpControl->GetOutputSizePixel() );
+
+ nMaxTextWidth = std::max( aControlSize.Width(), nMaxTextWidth );
+ pEntry->maSize.Height() = aControlSize.Height() + 1;
+ }
+
+ }
+ }
+
+ aSz.Width() = nMaxTextWidth + (BORDER_X<<1);
+
+ // positionate controls
+ int nY = BORDER_Y;
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
+
+ if( pEntry )
+ {
+ pEntry->maSize.Width() = nMaxTextWidth;
+
+ if( pEntry->mpControl )
+ {
+ Size aControlSize( pEntry->mpControl->GetOutputSizePixel() );
+ Point aControlPos( (aSz.Width() - aControlSize.Width())>>1, nY);
+
+ pEntry->mpControl->SetPosPixel( aControlPos );
+
+ pEntry->maRect = Rectangle( aControlPos, aControlSize );
+ }
+ else
+ {
+ pEntry->maRect = Rectangle( Point( 0, nY ), pEntry->maSize );
+ }
+
+ nY += pEntry->maSize.Height();
+ }
+ else
+ {
+ nY += SEPARATOR_HEIGHT;
+ }
+ }
+
+ aSz.Height() += nY + BORDER_Y;
+
+ return aSz;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::highlightFirstEntry()
+{
+ implChangeHighlightEntry( 0 );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::GetFocus()
+{
+ if( mpImpl->mnHighlightedEntry == -1 )
+ implChangeHighlightEntry( 0 );
+
+ DockingWindow::GetFocus();
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::LoseFocus()
+{
+ if( mpImpl->mnHighlightedEntry != -1 )
+ implChangeHighlightEntry( -1 );
+
+ DockingWindow::LoseFocus();
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, MenuItemBits nItemBits )
+{
+ appendEntry( new ToolbarMenuEntry( *this, nEntryId, rStr, nItemBits ) );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::appendEntry( int nEntryId, const Image& rImage, MenuItemBits nItemBits )
+{
+ appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, nItemBits ) );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, const Image& rImage, MenuItemBits nItemBits )
+{
+ appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, rStr, nItemBits ) );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::appendEntry( int nEntryId, Control* pControl, MenuItemBits nItemBits )
+{
+ appendEntry( new ToolbarMenuEntry( *this, nEntryId, pControl, nItemBits ) );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::appendEntry( ToolbarMenuEntry* pEntry )
+{
+ mpImpl->maEntryVector.push_back( pEntry );
+ mpImpl->maSize = implCalcSize();
+ if( IsVisible() )
+ Invalidate();
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::appendSeparator()
+{
+ appendEntry( 0 );
+}
+
+// --------------------------------------------------------------------
+
+/** creates an empty ValueSet that is initialized and can be inserted with appendEntry. */
+ValueSet* ToolbarMenu::createEmptyValueSetControl()
+{
+ ValueSet* pSet = new ValueSet( this, WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT );
+ pSet->EnableFullItemMode( sal_False );
+ pSet->SetColor( GetControlBackground() );
+ pSet->SetHighlightHdl( LINK( this, ToolbarMenu, HighlightHdl ) );
+ return pSet;
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry* ToolbarMenu::implGetEntry( int nEntry ) const
+{
+ return mpImpl->implGetEntry( nEntry );
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry* ToolbarMenu::implSearchEntry( int nEntryId ) const
+{
+ const int nEntryCount = mpImpl->maEntryVector.size();
+ int nEntry;
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* p = mpImpl->maEntryVector[nEntry];
+ if( p && p->mnEntryId == nEntryId )
+ {
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight )
+{
+ Size aSz( GetOutputSizePixel() );
+ long nX = 0, nY = 0;
+
+ const int nEntryCount = mpImpl->maEntryVector.size();
+ int nEntry;
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
+ if( pEntry && (nEntry == nHighlightEntry) )
+ {
+ // no highlights for controls only items
+ if( pEntry->mpControl )
+ {
+ if( !bHighlight )
+ {
+ ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl );
+ if( pValueSet )
+ {
+ pValueSet->SetNoSelection();
+ }
+ }
+ break;
+ }
+
+ bool bRestoreLineColor = false;
+ Color oldLineColor;
+ bool bDrawItemRect = true;
+
+ Rectangle aItemRect( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) );
+ if ( pEntry->mnBits & MIB_POPUPSELECT )
+ {
+ long nFontHeight = GetTextHeight();
+ aItemRect.Right() -= nFontHeight + nFontHeight/4;
+ }
+
+ if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) )
+ {
+ Size aPxSize( GetOutputSizePixel() );
+ Push( PUSH_CLIPREGION );
+ IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ) );
+ Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) );
+ DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL,
+ aCtrlRect,
+ CTRL_STATE_ENABLED,
+ ImplControlValue(),
+ OUString() );
+ if( bHighlight && IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) )
+ {
+ bDrawItemRect = false;
+ if( sal_False == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM,
+ aItemRect,
+ CTRL_STATE_SELECTED | ( pEntry->mbEnabled? CTRL_STATE_ENABLED: 0 ),
+ ImplControlValue(),
+ OUString() ) )
+ {
+ bDrawItemRect = bHighlight;
+ }
+ }
+ else
+ bDrawItemRect = bHighlight;
+ Pop();
+ }
+ if( bDrawItemRect )
+ {
+ if ( bHighlight )
+ {
+ if( pEntry->mbEnabled )
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
+ else
+ {
+ SetFillColor();
+ oldLineColor = GetLineColor();
+ SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() );
+ bRestoreLineColor = true;
+ }
+ }
+ else
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
+
+ DrawRect( aItemRect );
+ }
+ implPaint( pEntry, bHighlight );
+ if( bRestoreLineColor )
+ SetLineColor( oldLineColor );
+ break;
+ }
+
+ nY += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT;
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::implSelectEntry( int nSelectedEntry )
+{
+ mpImpl->mnSelectedEntry = nSelectedEntry;
+
+ ToolbarMenuEntry* pEntry = NULL;
+ if( nSelectedEntry != -1 )
+ pEntry = mpImpl->maEntryVector[ nSelectedEntry ];
+
+ if( pEntry )
+ mpImpl->maSelectHdl.Call( this );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ implHighlightEntry( rMEvt, true );
+
+ implSelectEntry( mpImpl->mnHighlightedEntry );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::MouseButtonUp( const MouseEvent& )
+{
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( !IsVisible() )
+ return;
+
+ implHighlightEntry( rMEvt, false );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::implHighlightEntry( const MouseEvent& rMEvt, bool bMBDown )
+{
+ long nY = 0;
+ long nMouseY = rMEvt.GetPosPixel().Y();
+ Size aOutSz = GetOutputSizePixel();
+ if ( ( nMouseY >= 0 ) && ( nMouseY < aOutSz.Height() ) )
+ {
+ bool bHighlighted = sal_False;
+
+ const int nEntryCount = mpImpl->maEntryVector.size();
+ int nEntry;
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
+ if( pEntry )
+ {
+ long nOldY = nY;
+ nY += pEntry->maSize.Height();
+
+ if( pEntry->mnEntryId != TITLE_ID )
+ {
+ if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) )
+ {
+ if( bMBDown )
+ {
+ if( nEntry != mpImpl->mnHighlightedEntry )
+ {
+ implChangeHighlightEntry( nEntry );
+ }
+ }
+ else
+ {
+ if ( nEntry != mpImpl->mnHighlightedEntry )
+ {
+ implChangeHighlightEntry( nEntry );
+ }
+ }
+ bHighlighted = true;
+ }
+ }
+ }
+ else
+ {
+ nY += SEPARATOR_HEIGHT;
+ }
+ }
+ if ( !bHighlighted )
+ implChangeHighlightEntry( -1 );
+ }
+ else
+ {
+ implChangeHighlightEntry( -1 );
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::implChangeHighlightEntry( int nEntry )
+{
+ if( mpImpl->mnHighlightedEntry != -1 )
+ {
+ implHighlightEntry( mpImpl->mnHighlightedEntry, false );
+ }
+
+ mpImpl->mnHighlightedEntry = nEntry;
+ Invalidate();
+
+ if( mpImpl->mnHighlightedEntry != -1 )
+ {
+ implHighlightEntry( mpImpl->mnHighlightedEntry, true );
+ }
+
+ mpImpl->notifyHighlightedEntry();
+}
+
+// --------------------------------------------------------------------
+
+static bool implCheckSubControlCursorMove( Control* pControl, bool bUp, int& nLastColumn )
+{
+ ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl );
+ if( pValueSet )
+ {
+ sal_uInt16 nItemPos = pValueSet->GetItemPos( pValueSet->GetSelectItemId() );
+ if( nItemPos != VALUESET_ITEM_NOTFOUND )
+ {
+ const sal_uInt16 nColCount = pValueSet->GetColCount();
+ const sal_uInt16 nLine = nItemPos / nColCount;
+
+ nLastColumn = nItemPos - (nLine * nColCount);
+
+ if( bUp )
+ {
+ return nLine > 0;
+ }
+ else
+ {
+ const sal_uInt16 nLineCount = (pValueSet->GetItemCount() + nColCount - 1) / nColCount;
+ return (nLine+1) < nLineCount;
+ }
+ }
+ }
+
+ return false;
+}
+
+// --------------------------------------------------------------------
+
+ToolbarMenuEntry* ToolbarMenu::implCursorUpDown( bool bUp, bool bHomeEnd )
+{
+ int n = 0, nLoop = 0;
+ if( !bHomeEnd )
+ {
+ n = mpImpl->mnHighlightedEntry;
+ if( n == -1 )
+ {
+ if( bUp )
+ n = 0;
+ else
+ n = mpImpl->maEntryVector.size()-1;
+ }
+ else
+ {
+ // if we have a currently selected entry and
+ // cursor keys are used than check if this entry
+ // has a control that can use those cursor keys
+ ToolbarMenuEntry* pData = mpImpl->maEntryVector[n];
+ if( pData && pData->mpControl && !pData->mbHasText )
+ {
+ if( implCheckSubControlCursorMove( pData->mpControl, bUp, mpImpl->mnLastColumn ) )
+ return pData;
+ }
+ }
+ nLoop = n;
+ }
+ else
+ {
+ // absolute positioning
+ if( bUp )
+ {
+ n = mpImpl->maEntryVector.size();
+ nLoop = n-1;
+ }
+ else
+ {
+ n = -1;
+ nLoop = mpImpl->maEntryVector.size()-1;
+ }
+ }
+
+ do
+ {
+ if( bUp )
+ {
+ if ( n )
+ n--;
+ else
+ if( mpImpl->mnHighlightedEntry == -1 )
+ n = mpImpl->maEntryVector.size()-1;
+ else
+ break;
+ }
+ else
+ {
+ if( n < ((int)mpImpl->maEntryVector.size()-1) )
+ n++;
+ else
+ if( mpImpl->mnHighlightedEntry == -1 )
+ n = 0;
+ else
+ break;
+ }
+
+ ToolbarMenuEntry* pData = mpImpl->maEntryVector[n];
+ if( pData && (pData->mnEntryId != TITLE_ID) )
+ {
+ implChangeHighlightEntry( n );
+ return pData;
+ }
+ } while ( n != nLoop );
+
+ return 0;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu_Impl::implHighlightControl( sal_uInt16 nCode, Control* pControl )
+{
+ ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl );
+ if( pValueSet )
+ {
+ const sal_uInt16 nItemCount = pValueSet->GetItemCount();
+ sal_uInt16 nItemPos = VALUESET_ITEM_NOTFOUND;
+ switch( nCode )
+ {
+ case KEY_UP:
+ {
+ const sal_uInt16 nColCount = pValueSet->GetColCount();
+ const sal_uInt16 nLastLine = nItemCount / nColCount;
+ nItemPos = std::min( ((nLastLine-1) * nColCount) + mnLastColumn, nItemCount-1 );
+ break;
+ }
+ case KEY_DOWN:
+ nItemPos = std::min( mnLastColumn, nItemCount-1 );
+ break;
+ case KEY_END:
+ nItemPos = nItemCount -1;
+ break;
+ case KEY_HOME:
+ nItemPos = 0;
+ break;
+ }
+ pValueSet->SelectItem( pValueSet->GetItemId( nItemPos ) );
+ notifyHighlightedEntry();
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::KeyInput( const KeyEvent& rKEvent )
+{
+ Control* pForwardControl = 0;
+ sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
+ switch ( nCode )
+ {
+ case KEY_UP:
+ case KEY_DOWN:
+ {
+ int nOldEntry = mpImpl->mnHighlightedEntry;
+ ToolbarMenuEntry*p = implCursorUpDown( nCode == KEY_UP, false );
+ if( p && p->mpControl )
+ {
+ if( nOldEntry != mpImpl->mnHighlightedEntry )
+ {
+ mpImpl->implHighlightControl( nCode, p->mpControl );
+ }
+ else
+ {
+ // in case we are in a system floating window, GrabFocus does not work :-/
+ pForwardControl = p->mpControl;
+ }
+ }
+ }
+ break;
+ case KEY_END:
+ case KEY_HOME:
+ {
+ ToolbarMenuEntry* p = implCursorUpDown( nCode == KEY_END, true );
+ if( p && p->mpControl )
+ {
+ mpImpl->implHighlightControl( nCode, p->mpControl );
+ }
+ }
+ break;
+ case KEY_F6:
+ case KEY_ESCAPE:
+ {
+ // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document
+ if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() )
+ break;
+
+ implSelectEntry( -1 );
+ }
+ break;
+
+ case KEY_RETURN:
+ {
+ ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry );
+ if ( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) )
+ {
+ if( pEntry->mpControl )
+ {
+ pForwardControl = pEntry->mpControl;
+ }
+ else
+ {
+ implSelectEntry( mpImpl->mnHighlightedEntry );
+ }
+ }
+ }
+ break;
+ default:
+ {
+ ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry );
+ if ( pEntry && pEntry->mbEnabled && pEntry->mpControl && !pEntry->mbHasText )
+ {
+ pForwardControl = pEntry->mpControl;
+ }
+ }
+
+ }
+ if( pForwardControl )
+ pForwardControl->KeyInput( rKEvent );
+
+}
+
+// --------------------------------------------------------------------
+static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight )
+{
+ sal_Bool bNativeOk = sal_False;
+ if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) )
+ {
+ ImplControlValue aControlValue;
+ ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED;
+
+ aControlValue.setTristateVal( BUTTONVALUE_ON );
+
+ bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON,
+ i_rRect, nState, aControlValue,
+ rtl::OUString() );
+ }
+
+ if( ! bNativeOk )
+ {
+ const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings();
+ Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() );
+ i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, sal_True, sal_False, 2, NULL, &aColor );
+ }
+}
+
+static long ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth )
+{
+ rMaxWidth = rCheckHeight = rRadioHeight = 0;
+
+ ImplControlValue aVal;
+ Rectangle aNativeBounds;
+ Rectangle aNativeContent;
+ Point tmp( 0, 0 );
+ Rectangle aCtrlRegion( tmp, Size( 100, 15 ) );
+ if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) )
+ {
+ if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
+ ControlPart(PART_MENU_ITEM_CHECK_MARK),
+ aCtrlRegion,
+ ControlState(CTRL_STATE_ENABLED),
+ aVal,
+ OUString(),
+ aNativeBounds,
+ aNativeContent )
+ )
+ {
+ rCheckHeight = aNativeBounds.GetHeight();
+ rMaxWidth = aNativeContent.GetWidth();
+ }
+ }
+ if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) )
+ {
+ if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP),
+ ControlPart(PART_MENU_ITEM_RADIO_MARK),
+ aCtrlRegion,
+ ControlState(CTRL_STATE_ENABLED),
+ aVal,
+ OUString(),
+ aNativeBounds,
+ aNativeContent )
+ )
+ {
+ rRadioHeight = aNativeBounds.GetHeight();
+ rMaxWidth = Max (rMaxWidth, aNativeContent.GetWidth());
+ }
+ }
+ return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight;
+}
+
+void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted )
+{
+ sal_uInt16 nBorder = 0; long nStartY = 0; // from Menu implementations, needed when we support native menu background & scrollable menu
+
+ long nFontHeight = GetTextHeight();
+// long nExtra = nFontHeight/4;
+
+ long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0;
+ ImplGetNativeCheckAndRadioSize( this, nCheckHeight, nRadioHeight, nMaxCheckWidth );
+
+ DecorationView aDecoView( this );
+ const StyleSettings& rSettings = GetSettings().GetStyleSettings();
+ const bool bUseImages = rSettings.GetUseImagesInMenus();
+
+ int nOuterSpace = 0; // ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder;
+ Point aTopLeft( nOuterSpace, nOuterSpace ), aTmpPos;
+
+ Size aOutSz( GetOutputSizePixel() );
+ const int nEntryCount = mpImpl->maEntryVector.size();
+ int nEntry;
+ for( nEntry = 0; nEntry < nEntryCount; nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry];
+
+ Point aPos( aTopLeft );
+ aPos.Y() += nBorder;
+ aPos.Y() += nStartY;
+
+
+ if( (pEntry == 0) && !pThisOnly )
+ {
+ // Separator
+ aTmpPos.Y() = aPos.Y() + ((SEPARATOR_HEIGHT-2)/2);
+ aTmpPos.X() = aPos.X() + 2 + nOuterSpace;
+ SetLineColor( rSettings.GetShadowColor() );
+ DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
+ aTmpPos.Y()++;
+ SetLineColor( rSettings.GetLightColor() );
+ DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) );
+ SetLineColor();
+ }
+ else if( !pThisOnly || ( pEntry == pThisOnly ) )
+ {
+ const bool bTitle = pEntry->mnEntryId == TITLE_ID;
+
+ if ( pThisOnly && bHighlighted )
+ SetTextColor( rSettings.GetMenuHighlightTextColor() );
+
+ if( aPos.Y() >= 0 )
+ {
+ long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2);
+
+ sal_uInt16 nTextStyle = 0;
+ sal_uInt16 nSymbolStyle = 0;
+ sal_uInt16 nImageStyle = 0;
+
+ if( !pEntry->mbEnabled )
+ {
+ nTextStyle |= TEXT_DRAW_DISABLE;
+ nSymbolStyle |= SYMBOL_DRAW_DISABLE;
+ nImageStyle |= IMAGE_DRAW_DISABLE;
+ }
+
+ Rectangle aOuterCheckRect( Point( aPos.X()+mpImpl->mnCheckPos, aPos.Y() ), Size( pEntry->maSize.Height(), pEntry->maSize.Height() ) );
+ aOuterCheckRect.Left() += 1;
+ aOuterCheckRect.Right() -= 1;
+ aOuterCheckRect.Top() += 1;
+ aOuterCheckRect.Bottom() -= 1;
+
+ if( bTitle )
+ {
+ // fill the background
+ Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) );
+ SetFillColor(rSettings.GetDialogColor());
+ SetLineColor();
+ DrawRect(aRect);
+ SetLineColor( rSettings.GetLightColor() );
+ DrawLine( aRect.TopLeft(), aRect.TopRight() );
+ SetLineColor( rSettings.GetShadowColor() );
+ DrawLine( aRect.BottomLeft(), aRect.BottomRight() );
+ }
+
+ // CheckMark
+ if ( pEntry->HasCheck() )
+ {
+ // draw selection transparent marker if checked
+ // onto that either a checkmark or the item image
+ // will be painted
+ // however do not do this if native checks will be painted since
+ // the selection color too often does not fit the theme's check and/or radio
+
+ if( !pEntry->mbHasImage )
+ {
+ if( this->IsNativeControlSupported( CTRL_MENU_POPUP,
+ (pEntry->mnBits & MIB_RADIOCHECK)
+ ? PART_MENU_ITEM_CHECK_MARK
+ : PART_MENU_ITEM_RADIO_MARK ) )
+ {
+ ControlPart nPart = ((pEntry->mnBits & MIB_RADIOCHECK)
+ ? PART_MENU_ITEM_RADIO_MARK
+ : PART_MENU_ITEM_CHECK_MARK);
+
+ ControlState nState = 0;
+
+ if ( pEntry->mbChecked )
+ nState |= CTRL_STATE_PRESSED;
+
+ if ( pEntry->mbEnabled )
+ nState |= CTRL_STATE_ENABLED;
+
+ if ( bHighlighted )
+ nState |= CTRL_STATE_SELECTED;
+
+ long nCtrlHeight = (pEntry->mnBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight;
+ aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2;
+ aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2;
+
+ Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) );
+ DrawNativeControl( CTRL_MENU_POPUP, nPart, aCheckRect, nState, ImplControlValue(), OUString() );
+ }
+ else if ( pEntry->mbChecked ) // by default do nothing for unchecked items
+ {
+ ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted );
+
+ SymbolType eSymbol;
+ Size aSymbolSize;
+ if ( pEntry->mnBits & MIB_RADIOCHECK )
+ {
+ eSymbol = SYMBOL_RADIOCHECKMARK;
+ aSymbolSize = Size( nFontHeight/2, nFontHeight/2 );
+ }
+ else
+ {
+ eSymbol = SYMBOL_CHECKMARK;
+ aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 );
+ }
+ aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2;
+ aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2;
+ Rectangle aRect( aTmpPos, aSymbolSize );
+ aDecoView.DrawSymbol( aRect, eSymbol, GetTextColor(), nSymbolStyle );
+ }
+ }
+ }
+
+ // Image:
+ if( pEntry->mbHasImage && bUseImages )
+ {
+ // Don't render an image for a check thing
+ /* if((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pEntry->HasCheck() )*/
+ {
+ if( pEntry->mbChecked )
+ ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted );
+ aTmpPos = aOuterCheckRect.TopLeft();
+ aTmpPos.X() += (aOuterCheckRect.GetWidth()-pEntry->maImage.GetSizePixel().Width())/2;
+ aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pEntry->maImage.GetSizePixel().Height())/2;
+ DrawImage( aTmpPos, pEntry->maImage, nImageStyle );
+ }
+ }
+
+ // Text:
+ if( pEntry->mbHasText )
+ {
+ aTmpPos.X() = aPos.X() + (bTitle ? 4 : mpImpl->mnTextPos);
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nTextOffsetY;
+ sal_uInt16 nStyle = nTextStyle|TEXT_DRAW_MNEMONIC;
+
+ DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle, NULL, NULL ); // pVector, pDisplayText );
+ }
+
+/*
+ // Accel
+ if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() )
+ {
+ XubString aAccText = pData->aAccelKey.GetName();
+ aTmpPos.X() = aOutSz.Width() - this->GetTextWidth( aAccText );
+ aTmpPos.X() -= 4*nExtra;
+
+ aTmpPos.X() -= nOuterSpace;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nTextOffsetY;
+ this->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle );
+ }
+*/
+
+/*
+ // SubMenu?
+ if ( !bLayout && !bIsMenuBar && pData->pSubMenu )
+ {
+ aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace;
+ aTmpPos.Y() = aPos.Y();
+ aTmpPos.Y() += nExtra/2;
+ aTmpPos.Y() += ( pEntry->maSize.Height() / 2 ) - ( nFontHeight/4 );
+ if ( pEntry->mnBits & MIB_POPUPSELECT )
+ {
+ this->SetTextColor( rSettings.GetMenuTextColor() );
+ Point aTmpPos2( aPos );
+ aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4;
+ aDecoView.DrawFrame(
+ Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pEntry->maSize.Height() ) ), FRAME_DRAW_GROUP );
+ }
+ aDecoView.DrawSymbol(
+ Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ),
+ SYMBOL_SPIN_RIGHT, this->GetTextColor(), nSymbolStyle );
+// if ( pEntry->mnBits & MIB_POPUPSELECT )
+// {
+// aTmpPos.Y() += nFontHeight/2 ;
+// this->SetLineColor( rSettings.GetShadowColor() );
+// this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
+// this->SetLineColor( rSettings.GetLightColor() );
+// aTmpPos.Y()++;
+// this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) );
+// this->SetLineColor();
+// }
+ }
+*/
+
+ if ( pThisOnly && bHighlighted )
+ {
+ // This restores the normal menu or menu bar text
+ // color for when it is no longer highlighted.
+ SetTextColor( rSettings.GetMenuTextColor() );
+ }
+ }
+ }
+
+ aTopLeft.Y() += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT;
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::Paint( const Rectangle& )
+{
+ SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() );
+
+ implPaint();
+
+ if( mpImpl->mnHighlightedEntry != -1 )
+ implHighlightEntry( mpImpl->mnHighlightedEntry, true );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::RequestHelp( const HelpEvent& rHEvt )
+{
+ DockingWindow::RequestHelp( rHEvt );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::StateChanged( StateChangedType nType )
+{
+ DockingWindow::StateChanged( nType );
+
+ if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) )
+ {
+ initWindow();
+ Invalidate();
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ DockingWindow::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ initWindow();
+ Invalidate();
+ }
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() == COMMAND_WHEEL )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) )
+ {
+ implCursorUpDown( pData->GetDelta() > 0L, false );
+ }
+ }
+}
+
+// --------------------------------------------------------------------
+
+Reference< ::com::sun::star::accessibility::XAccessible > ToolbarMenu::CreateAccessible()
+{
+ mpImpl->setAccessible( new ToolbarMenuAcc( *mpImpl ) );
+ return Reference< XAccessible >( mpImpl->mxAccessible.get() );
+}
+
+// --------------------------------------------------------------------
+
+// todo: move to new base class that will replace SfxPopupWindo
+void ToolbarMenu::AddStatusListener( const rtl::OUString& rCommandURL )
+{
+ initStatusListener();
+ mpImpl->mxStatusListener->addStatusListener( rCommandURL );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::RemoveStatusListener( const rtl::OUString& rCommandURL )
+{
+ mpImpl->mxStatusListener->removeStatusListener( rCommandURL );
+}
+// --------------------------------------------------------------------
+
+
+void ToolbarMenu::UpdateStatus( const rtl::OUString& rCommandURL )
+{
+ mpImpl->mxStatusListener->updateStatus( rCommandURL );
+}
+
+// --------------------------------------------------------------------
+
+// XStatusListener (subclasses must override this one to get the status updates
+void SAL_CALL ToolbarMenu::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& /*Event*/ ) throw ( ::com::sun::star::uno::RuntimeException )
+{
+}
+
+// --------------------------------------------------------------------
+
+class ToolbarMenuStatusListener : public svt::FrameStatusListener
+{
+public:
+ ToolbarMenuStatusListener( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame,
+ ToolbarMenu& rToolbarMenu );
+
+ virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException );
+
+ ToolbarMenu* mpMenu;
+};
+
+// --------------------------------------------------------------------
+
+ToolbarMenuStatusListener::ToolbarMenuStatusListener(
+ const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame,
+ ToolbarMenu& rToolbarMenu )
+: svt::FrameStatusListener( xServiceManager, xFrame )
+, mpMenu( &rToolbarMenu )
+{
+}
+
+// --------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuStatusListener::dispose() throw (::com::sun::star::uno::RuntimeException)
+{
+ mpMenu = 0;
+ svt::FrameStatusListener::dispose();
+}
+
+// --------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuStatusListener::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ if( mpMenu )
+ mpMenu->statusChanged( Event );
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::initStatusListener()
+{
+ if( !mpImpl->mxStatusListener.is() )
+ mpImpl->mxStatusListener.set( new ToolbarMenuStatusListener( mpImpl->mxServiceManager, mpImpl->mxFrame, *this ) );
+}
+
+// --------------------------------------------------------------------
+
+bool ToolbarMenu::IsInPopupMode()
+{
+ return GetDockingManager()->IsInPopupMode(this);
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::EndPopupMode()
+{
+ GetDockingManager()->EndPopupMode(this);
+}
+
+// --------------------------------------------------------------------
+
+const Size& ToolbarMenu::getMenuSize() const
+{
+ return mpImpl->maSize;
+}
+
+// --------------------------------------------------------------------
+
+void ToolbarMenu::SetSelectHdl( const Link& rLink )
+{
+ mpImpl->maSelectHdl = rLink;
+}
+
+// --------------------------------------------------------------------
+
+const Link& ToolbarMenu::GetSelectHdl() const
+{
+ return mpImpl->maSelectHdl;
+}
+
+// --------------------------------------------------------------------
+
+Reference< XFrame > ToolbarMenu::GetFrame() const
+{
+ return mpImpl->mxFrame;
+}
+
+// --------------------------------------------------------------------
+
+
+// --------------------------------------------------------------------
+
+}
+
+
diff --git a/svtools/source/control/toolbarmenuacc.cxx b/svtools/source/control/toolbarmenuacc.cxx
new file mode 100644
index 000000000000..620002017e6c
--- /dev/null
+++ b/svtools/source/control/toolbarmenuacc.cxx
@@ -0,0 +1,1003 @@
+/*************************************************************************
+ *
+ * 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 <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+
+#include <unotools/accessiblestatesethelper.hxx>
+
+#include <vcl/svapp.hxx>
+
+#include "svtools/toolbarmenu.hxx"
+
+#include "toolbarmenuimp.hxx"
+
+using ::rtl::OUString;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::accessibility;
+
+namespace svtools {
+
+// ------------------
+// - ToolbarMenuAcc -
+// ------------------
+
+ToolbarMenuAcc::ToolbarMenuAcc( ToolbarMenu_Impl& rParent )
+: ToolbarMenuAccComponentBase(m_aMutex)
+, mpParent( &rParent )
+, mbIsFocused(false)
+{
+ mpParent->mrMenu.AddEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) );
+}
+
+// -----------------------------------------------------------------------------
+
+ToolbarMenuAcc::~ToolbarMenuAcc()
+{
+ if( mpParent )
+ mpParent->mrMenu.RemoveEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ToolbarMenuAcc, WindowEventListener, VclSimpleEvent*, pEvent )
+{
+ DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
+
+ /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper
+ * might have been destroyed by the previous VCLEventListener (if no AT tool
+ * is running), e.g. sub-toolbars in impress.
+ */
+ if ( mpParent && pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) )
+ {
+ DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
+ if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) )
+ {
+ ProcessWindowEvent( *(VclWindowEvent*)pEvent );
+ }
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ToolbarMenuAcc::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ Any aOldValue, aNewValue;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VCLEVENT_OBJECT_DYING:
+ {
+ mpParent->mrMenu.RemoveEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) );
+ mpParent = 0;
+ }
+ break;
+
+ case VCLEVENT_WINDOW_GETFOCUS:
+ {
+ if( !mbIsFocused )
+ {
+ mpParent->notifyHighlightedEntry();
+ mbIsFocused = true;
+ }
+ }
+ break;
+ case VCLEVENT_WINDOW_LOSEFOCUS:
+ {
+ if( mbIsFocused )
+ {
+ mbIsFocused = false;
+ }
+ }
+ break;
+ default:
+ {
+ }
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ToolbarMenuAcc::FireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue )
+{
+ if( nEventId )
+ {
+ EventListenerVector aTmpListeners( mxEventListeners );
+ EventListenerVector::const_iterator aIter( aTmpListeners.begin() );
+ AccessibleEventObject aEvtObject;
+
+ aEvtObject.EventId = nEventId;
+ aEvtObject.Source = static_cast<XWeak*>(this);
+ aEvtObject.NewValue = rNewValue;
+ aEvtObject.OldValue = rOldValue;
+
+ while( aIter != aTmpListeners.end() )
+ {
+ try
+ {
+ (*aIter)->notifyEvent( aEvtObject );
+ }
+ catch( Exception& )
+ {
+ }
+
+ aIter++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessibleContext > SAL_CALL ToolbarMenuAcc::getAccessibleContext() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ return this;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuAcc::getAccessibleChildCount() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+
+ return mpParent->getAccessibleChildCount();
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+
+ return mpParent->getAccessibleChild(i);
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleParent() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+
+ Reference< XAccessible > xRet;
+
+ Window* pParent = mpParent->mrMenu.GetParent();
+ if( pParent )
+ xRet = pParent->GetAccessible();
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuAcc::getAccessibleIndexInParent() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+
+ Window* pParent = mpParent->mrMenu.GetParent();
+ if( pParent )
+ {
+ for( sal_uInt16 i = 0, nCount = pParent->GetChildCount(); i < nCount ; i++ )
+ {
+ if( pParent->GetChild( i ) == &mpParent->mrMenu )
+ return i;
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int16 SAL_CALL ToolbarMenuAcc::getAccessibleRole() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ return AccessibleRole::LIST;
+}
+
+// -----------------------------------------------------------------------------
+
+OUString SAL_CALL ToolbarMenuAcc::getAccessibleDescription() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ return OUString( RTL_CONSTASCII_USTRINGPARAM( "ToolbarMenu" ) );
+}
+
+// -----------------------------------------------------------------------------
+
+OUString SAL_CALL ToolbarMenuAcc::getAccessibleName() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ OUString aRet;
+
+ if( mpParent )
+ aRet = mpParent->mrMenu.GetAccessibleName();
+
+ if( !aRet.getLength() )
+ {
+ Window* pLabel = mpParent->mrMenu.GetAccessibleRelationLabeledBy();
+ if( pLabel && pLabel != &mpParent->mrMenu )
+ aRet = OutputDevice::GetNonMnemonicString( pLabel->GetText() );
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessibleRelationSet > SAL_CALL ToolbarMenuAcc::getAccessibleRelationSet() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ return Reference< XAccessibleRelationSet >();
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessibleStateSet > SAL_CALL ToolbarMenuAcc::getAccessibleStateSet() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
+
+ // Set some states.
+ pStateSet->AddState (AccessibleStateType::ENABLED);
+ pStateSet->AddState (AccessibleStateType::SENSITIVE);
+ pStateSet->AddState (AccessibleStateType::SHOWING);
+ pStateSet->AddState (AccessibleStateType::VISIBLE);
+ pStateSet->AddState (AccessibleStateType::MANAGES_DESCENDANTS);
+ pStateSet->AddState (AccessibleStateType::FOCUSABLE);
+ if (mbIsFocused)
+ pStateSet->AddState (AccessibleStateType::FOCUSED);
+
+ return pStateSet;
+}
+
+// -----------------------------------------------------------------------------
+
+Locale SAL_CALL ToolbarMenuAcc::getLocale() throw (IllegalAccessibleComponentStateException, RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const ::rtl::OUString aEmptyStr;
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr );
+
+ if( xParent.is() )
+ {
+ Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+
+ if( xParentContext.is() )
+ aRet = xParentContext->getLocale ();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::addEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ if( rxListener.is() )
+ {
+ EventListenerVector::const_iterator aIter = mxEventListeners.begin();
+ bool bFound = false;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ bFound = true;
+ else
+ aIter++;
+ }
+
+ if (!bFound)
+ mxEventListeners.push_back( rxListener );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::removeEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard(m_aMutex);
+
+ if( rxListener.is() )
+ {
+ EventListenerVector::iterator aIter = mxEventListeners.begin();
+ bool bFound = false;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ {
+ mxEventListeners.erase( aIter );
+ bFound = true;
+ }
+ else
+ aIter++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL ToolbarMenuAcc::containsPoint( const awt::Point& aPoint ) throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aRect( getBounds() );
+ const Point aSize( aRect.Width, aRect.Height );
+ const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
+
+ return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleAtPoint( const awt::Point& aPoint ) throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+
+ Reference< XAccessible > xRet;
+
+ const Point aVclPoint( aPoint.X, aPoint.Y );
+
+ const int nEntryCount = mpParent->maEntryVector.size();
+ for( int nEntry = 0; (nEntry < nEntryCount) && !xRet.is(); nEntry++ )
+ {
+ ToolbarMenuEntry* pEntry = mpParent->maEntryVector[nEntry];
+ if( pEntry && pEntry->maRect.IsInside( aVclPoint ) )
+ {
+ if( pEntry->mpControl )
+ {
+ awt::Point aChildPoint( aPoint.X - pEntry->maRect.Left(), aPoint.Y - pEntry->maRect.Top() );
+ Reference< XAccessibleComponent > xComp( pEntry->GetAccessible(true), UNO_QUERY_THROW );
+ xRet = xComp->getAccessibleAtPoint(aChildPoint);
+ }
+ else
+ {
+ xRet = Reference< XAccessible >( pEntry->GetAccessible(true), UNO_QUERY );
+ }
+ }
+ }
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Rectangle SAL_CALL ToolbarMenuAcc::getBounds() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const Point aOutPos( mpParent->mrMenu.GetPosPixel() );
+ const Size aOutSize( mpParent->mrMenu.GetOutputSizePixel() );
+ awt::Rectangle aRet;
+
+ aRet.X = aOutPos.X();
+ aRet.Y = aOutPos.Y();
+ aRet.Width = aOutSize.Width();
+ aRet.Height = aOutSize.Height();
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ToolbarMenuAcc::getLocation() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const Point aOutPos( mpParent->mrMenu.GetPosPixel() );
+ return awt::Point( aOutPos.X(), aOutPos.Y() );
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ToolbarMenuAcc::getLocationOnScreen() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const Point aScreenPos( mpParent->mrMenu.OutputToAbsoluteScreenPixel( Point() ) );
+ return awt::Point( aScreenPos.X(), aScreenPos.Y() );
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Size SAL_CALL ToolbarMenuAcc::getSize() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const Size aOutSize( mpParent->mrMenu.GetOutputSizePixel() );
+ return awt::Size( aOutSize.Width(), aOutSize.Height() );
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::grabFocus() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ mpParent->mrMenu.GrabFocus();
+}
+
+// -----------------------------------------------------------------------------
+
+Any SAL_CALL ToolbarMenuAcc::getAccessibleKeyBinding() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ return Any();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuAcc::getForeground() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetMenuTextColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuAcc::getBackground() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetMenuColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+
+ mpParent->selectAccessibleChild( nChildIndex );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL ToolbarMenuAcc::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+ return mpParent->isAccessibleChildSelected( nChildIndex );
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::clearAccessibleSelection() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+ mpParent->clearAccessibleSelection();
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::selectAllAccessibleChildren() throw (RuntimeException)
+{
+ ThrowIfDisposed();
+ // unsupported due to single selection only
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuAcc::getSelectedAccessibleChildCount() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+
+ return mpParent->mnHighlightedEntry != -1 ? 1 : 0;
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+
+ if( (mpParent->mnHighlightedEntry != -1) && (nSelectedChildIndex == 0) )
+ {
+ ToolbarMenuEntry* pEntry = mpParent->maEntryVector[ mpParent->mnHighlightedEntry ];
+ if( pEntry )
+ {
+ if( pEntry->mpControl )
+ {
+ Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW );
+ return xSel->getSelectedAccessibleChild(0);
+ }
+ else
+ return Reference< XAccessible >( pEntry->GetAccessible(true), UNO_QUERY );
+ }
+ }
+
+ throw IndexOutOfBoundsException();
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ // Because of the single selection we can reset the whole selection when
+ // the specified child is currently selected.
+ if (isAccessibleChildSelected(nChildIndex))
+ mpParent->clearAccessibleSelection();
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuAcc::disposing (void)
+{
+ EventListenerVector aListenerListCopy;
+
+ {
+ // Make a copy of the list and clear the original.
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ::osl::MutexGuard aGuard (m_aMutex);
+ aListenerListCopy = mxEventListeners;
+ mxEventListeners.clear();
+
+ // Reset the pointer to the parent. It has to be the one who has
+ // disposed us because he is dying.
+ mpParent = NULL;
+ }
+
+ // Inform all listeners that this objects is disposing.
+ EventListenerVector::const_iterator aListenerIterator (aListenerListCopy.begin());
+ EventObject aEvent (static_cast<XAccessible*>(this));
+ while(aListenerIterator != aListenerListCopy.end())
+ {
+ try
+ {
+ (*aListenerIterator)->disposing (aEvent);
+ }
+ catch( Exception& )
+ {
+ // Ignore exceptions.
+ }
+
+ ++aListenerIterator;
+ }
+}
+
+void ToolbarMenuAcc::ThrowIfDisposed (void) throw (DisposedException)
+{
+ if(rBHelper.bDisposed || rBHelper.bInDispose || !mpParent)
+ {
+ throw DisposedException ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), static_cast<XWeak*>(this));
+ }
+}
+
+// -----------------------
+// - ToolbarMenuEntryAcc -
+// -----------------------
+
+ToolbarMenuEntryAcc::ToolbarMenuEntryAcc( ToolbarMenuEntry* pParent )
+: ToolbarMenuEntryAccBase( m_aMutex )
+, mpParent( pParent )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ToolbarMenuEntryAcc::~ToolbarMenuEntryAcc()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ToolbarMenuEntryAcc::FireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue )
+{
+ if( nEventId )
+ {
+ EventListenerVector aTmpListeners( mxEventListeners );
+ ::std::vector< Reference< XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() );
+ AccessibleEventObject aEvtObject;
+
+ aEvtObject.EventId = nEventId;
+ aEvtObject.Source = static_cast<XWeak*>(this);
+ aEvtObject.NewValue = rNewValue;
+ aEvtObject.OldValue = rOldValue;
+
+ while( aIter != aTmpListeners.end() )
+ {
+ (*aIter)->notifyEvent( aEvtObject );
+ aIter++;
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuEntryAcc::disposing (void)
+{
+ EventListenerVector aListenerListCopy;
+
+ {
+ // Make a copy of the list and clear the original.
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ::osl::MutexGuard aGuard (m_aMutex);
+ aListenerListCopy = mxEventListeners;
+ mxEventListeners.clear();
+
+ // Reset the pointer to the parent. It has to be the one who has
+ // disposed us because he is dying.
+ mpParent = NULL;
+ }
+
+ // Inform all listeners that this objects is disposing.
+ EventListenerVector::const_iterator aListenerIterator (aListenerListCopy.begin());
+ EventObject aEvent (static_cast<XAccessible*>(this));
+ while(aListenerIterator != aListenerListCopy.end())
+ {
+ try
+ {
+ (*aListenerIterator)->disposing (aEvent);
+ }
+ catch( Exception& )
+ {
+ // Ignore exceptions.
+ }
+
+ ++aListenerIterator;
+ }
+}
+// -----------------------------------------------------------------------------
+
+Reference< XAccessibleContext > SAL_CALL ToolbarMenuEntryAcc::getAccessibleContext() throw (RuntimeException)
+{
+ return this;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getAccessibleChildCount() throw (RuntimeException)
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleChild( sal_Int32 ) throw (IndexOutOfBoundsException, RuntimeException)
+{
+ throw IndexOutOfBoundsException();
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleParent() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ Reference< XAccessible > xRet;
+
+ if( mpParent )
+ xRet = mpParent->mrMenu.GetAccessible();
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getAccessibleIndexInParent() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ // The index defaults to -1 to indicate the child does not belong to its
+ // parent.
+ sal_Int32 nIndexInParent = -1;
+
+ if( mpParent )
+ {
+ Reference< XAccessibleContext > xParent( mpParent->mrMenu.GetAccessible(), UNO_QUERY );
+
+ if( xParent.is() )
+ {
+ Reference< XAccessible > xThis( this );
+
+ const sal_Int32 nCount = xParent->getAccessibleChildCount();
+ for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ if( xParent->getAccessibleChild(nIndex) == xThis )
+ {
+ nIndexInParent = nIndex;
+ break;
+ }
+ }
+ }
+ }
+
+ return nIndexInParent;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int16 SAL_CALL ToolbarMenuEntryAcc::getAccessibleRole() throw (RuntimeException)
+{
+ return AccessibleRole::LIST_ITEM;
+}
+
+// -----------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL ToolbarMenuEntryAcc::getAccessibleDescription() throw (RuntimeException)
+{
+ return ::rtl::OUString();
+}
+
+// -----------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL ToolbarMenuEntryAcc::getAccessibleName() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ String aRet;
+
+ if( mpParent )
+ {
+ aRet = mpParent->maText;
+
+ if( !aRet.Len() )
+ {
+ aRet = String( RTL_CONSTASCII_USTRINGPARAM( "Item " ) );
+ aRet += String::CreateFromInt32( mpParent->mnEntryId );
+ }
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessibleRelationSet > SAL_CALL ToolbarMenuEntryAcc::getAccessibleRelationSet() throw (RuntimeException)
+{
+ return Reference< XAccessibleRelationSet >();
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessibleStateSet > SAL_CALL ToolbarMenuEntryAcc::getAccessibleStateSet() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper;
+
+ if( mpParent )
+ {
+ pStateSet->AddState (AccessibleStateType::ENABLED);
+ pStateSet->AddState (AccessibleStateType::SENSITIVE);
+ pStateSet->AddState (AccessibleStateType::SHOWING);
+ pStateSet->AddState (AccessibleStateType::VISIBLE);
+ pStateSet->AddState (AccessibleStateType::TRANSIENT);
+ if( mpParent->mnEntryId != TITLE_ID )
+ {
+ pStateSet->AddState( AccessibleStateType::SELECTABLE );
+
+ // SELECTED
+ if( mpParent->mrMenu.getHighlightedEntryId() == mpParent->mnEntryId )
+ pStateSet->AddState( AccessibleStateType::SELECTED );
+ }
+ }
+
+ return pStateSet;
+}
+
+// -----------------------------------------------------------------------------
+
+Locale SAL_CALL ToolbarMenuEntryAcc::getLocale() throw (IllegalAccessibleComponentStateException, RuntimeException)
+{
+ const ::rtl::OUString aEmptyStr;
+ Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr );
+
+ Reference< XAccessible > xParent( getAccessibleParent() );
+ if( xParent.is() )
+ {
+ Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+
+ if( xParentContext.is() )
+ aRet = xParentContext->getLocale();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuEntryAcc::addEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException)
+{
+ const ::vos::OGuard aGuard( maMutex );
+
+ if( rxListener.is() )
+ {
+ EventListenerVector::const_iterator aIter( mxEventListeners.begin() );
+ bool bFound = false;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ bFound = true;
+ else
+ aIter++;
+ }
+
+ if (!bFound)
+ mxEventListeners.push_back( rxListener );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuEntryAcc::removeEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException)
+{
+ const ::vos::OGuard aGuard( maMutex );
+
+ if( rxListener.is() )
+ {
+ EventListenerVector::iterator aIter = mxEventListeners.begin();
+ bool bFound = false;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ {
+ mxEventListeners.erase( aIter );
+ bFound = true;
+ }
+ else
+ aIter++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL ToolbarMenuEntryAcc::containsPoint( const awt::Point& aPoint ) throw (RuntimeException)
+{
+ const awt::Rectangle aRect( getBounds() );
+ const Point aSize( aRect.Width, aRect.Height );
+ const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
+
+ return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
+}
+
+// -----------------------------------------------------------------------------
+
+Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleAtPoint( const awt::Point& ) throw (RuntimeException)
+{
+ Reference< XAccessible > xRet;
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Rectangle SAL_CALL ToolbarMenuEntryAcc::getBounds() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ awt::Rectangle aRet;
+
+ if( mpParent )
+ {
+ Rectangle aRect( mpParent->maRect );
+ Point aOrigin;
+ Rectangle aParentRect( aOrigin, mpParent->mrMenu.GetOutputSizePixel() );
+
+ aRect.Intersection( aParentRect );
+
+ aRet.X = aRect.Left();
+ aRet.Y = aRect.Top();
+ aRet.Width = aRect.GetWidth();
+ aRet.Height = aRect.GetHeight();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ToolbarMenuEntryAcc::getLocation() throw (RuntimeException)
+{
+ const awt::Rectangle aRect( getBounds() );
+ return awt::Point( aRect.X, aRect.Y );
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ToolbarMenuEntryAcc::getLocationOnScreen() throw (RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ awt::Point aRet;
+
+ if( mpParent )
+ {
+ const Point aScreenPos( mpParent->mrMenu.OutputToAbsoluteScreenPixel( mpParent->maRect.TopLeft() ) );
+
+ aRet.X = aScreenPos.X();
+ aRet.Y = aScreenPos.Y();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Size SAL_CALL ToolbarMenuEntryAcc::getSize() throw (RuntimeException)
+{
+ const awt::Rectangle aRect( getBounds() );
+ awt::Size aRet;
+
+ aRet.Width = aRect.Width;
+ aRet.Height = aRect.Height;
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ToolbarMenuEntryAcc::grabFocus() throw (RuntimeException)
+{
+ // nothing to do
+}
+
+// -----------------------------------------------------------------------------
+
+Any SAL_CALL ToolbarMenuEntryAcc::getAccessibleKeyBinding() throw (RuntimeException)
+{
+ return Any();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getForeground( ) throw (RuntimeException)
+{
+ return static_cast<sal_Int32>(Application::GetSettings().GetStyleSettings().GetMenuTextColor().GetColor());
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getBackground( ) throw (RuntimeException)
+{
+ return static_cast<sal_Int32>(Application::GetSettings().GetStyleSettings().GetMenuColor().GetColor());
+}
+
+}
diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx
new file mode 100644
index 000000000000..a190fd9f205d
--- /dev/null
+++ b/svtools/source/control/toolbarmenuimp.hxx
@@ -0,0 +1,314 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include <vos/mutex.hxx>
+#include <vcl/image.hxx>
+#include <vcl/menu.hxx>
+
+#include <cppuhelper/compbase4.hxx>
+#include <cppuhelper/compbase5.hxx>
+#include <comphelper/broadcasthelper.hxx>
+
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+#include "framestatuslistener.hxx"
+
+#include "svtools/valueset.hxx"
+
+namespace svtools {
+
+struct ToolbarMenu_Impl;
+class ToolbarMenu;
+class ToolbarMenuEntry;
+
+typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener > > EventListenerVector;
+typedef std::vector< ToolbarMenuEntry * > ToolbarMenuEntryVector;
+
+const int EXTRAITEMHEIGHT = 0; // 4;
+const int SEPARATOR_HEIGHT = 4;
+const int TITLE_ID = -1;
+const int BORDER_X = 0;
+const int BORDER_Y = 0;
+
+// --------------------
+// - ToolbarMenuEntry -
+// --------------------
+
+class ToolbarMenuEntry
+{
+public:
+ ToolbarMenu& mrMenu;
+
+ int mnEntryId;
+ MenuItemBits mnBits;
+ Size maSize;
+
+ bool mbHasText;
+ bool mbHasImage;
+ bool mbChecked;
+ bool mbEnabled;
+
+ String maText;
+ Image maImage;
+ Control* mpControl;
+ Rectangle maRect;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > mxAccContext;
+
+public:
+ ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits );
+ ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits );
+ ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits );
+ ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits );
+ ~ToolbarMenuEntry();
+
+ void init( int nEntryId, MenuItemBits nBits );
+
+ const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& GetAccessible( bool bCreate = false );
+
+ sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException);
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+
+ bool HasCheck() const
+ {
+ return mbChecked || ( mnBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) );
+ }
+};
+
+// ---------------
+// - ToolbarMenuAcc -
+// ---------------
+
+typedef ::cppu::WeakComponentImplHelper5<
+ ::com::sun::star::accessibility::XAccessible,
+ ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
+ ::com::sun::star::accessibility::XAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleComponent,
+ ::com::sun::star::accessibility::XAccessibleSelection >
+ ToolbarMenuAccComponentBase;
+
+class ToolbarMenuAcc :
+ public ::comphelper::OBaseMutex,
+ public ToolbarMenuAccComponentBase
+{
+public:
+
+ ToolbarMenuAcc( ToolbarMenu_Impl& rParent );
+ ~ToolbarMenuAcc();
+
+ void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
+ bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); }
+
+public:
+ // XAccessible
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleEventBroadcaster
+ using cppu::WeakComponentImplHelper5<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection>::addEventListener;
+ virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+ using cppu::WeakComponentImplHelper5<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection>::removeEventListener;
+ virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleComponent
+ virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleSelection
+ virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL clearAccessibleSelection( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL selectAllAccessibleChildren( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+
+ DECL_LINK( WindowEventListener, VclSimpleEvent* );
+
+private:
+ EventListenerVector mxEventListeners;
+ ToolbarMenu_Impl* mpParent;
+ /// The current FOCUSED state.
+ bool mbIsFocused;
+
+ void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent );
+
+ /** Tell all listeners that the object is dying. This callback is
+ usually called from the WeakComponentImplHelper class.
+ */
+ virtual void SAL_CALL disposing (void);
+
+ /** Check whether or not the object has been disposed (or is in the
+ state of beeing disposed). If that is the case then
+ DisposedException is thrown to inform the (indirect) caller of the
+ foul deed.
+ */
+ void ThrowIfDisposed (void) throw (::com::sun::star::lang::DisposedException);
+};
+
+// -----------------------
+// - ToolbarMenuEntryAcc -
+// -----------------------
+
+typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::accessibility::XAccessible,
+ ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
+ ::com::sun::star::accessibility::XAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleComponent > ToolbarMenuEntryAccBase;
+
+class ToolbarMenuEntryAcc : public ::comphelper::OBaseMutex,
+ public ToolbarMenuEntryAccBase
+{
+public:
+ ToolbarMenuEntryAcc( ToolbarMenuEntry* pParent );
+ ~ToolbarMenuEntryAcc();
+
+ void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
+ bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); }
+
+ // XAccessible
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleEventBroadcaster
+ using ToolbarMenuEntryAccBase::addEventListener;
+ virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+ using ToolbarMenuEntryAccBase::removeEventListener;
+ virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleComponent
+ virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException);
+
+private:
+ EventListenerVector mxEventListeners;
+ ::vos::OMutex maMutex;
+ ToolbarMenuEntry* mpParent;
+
+ /** Tell all listeners that the object is dying. This callback is
+ usually called from the WeakComponentImplHelper class.
+ */
+ virtual void SAL_CALL disposing (void);
+};
+
+// -----------------------------------------------------------------------------
+
+struct ToolbarMenu_Impl
+{
+ ToolbarMenu& mrMenu;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame;
+ rtl::Reference< svt::FrameStatusListener > mxStatusListener;
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceManager;
+ rtl::Reference< ToolbarMenuAcc > mxAccessible;
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxOldSelection;
+
+ ToolbarMenuEntryVector maEntryVector;
+
+ int mnCheckPos;
+ int mnImagePos;
+ int mnTextPos;
+
+ int mnHighlightedEntry;
+ int mnSelectedEntry;
+ int mnLastColumn;
+
+ Size maSize;
+
+ Link maSelectHdl;
+
+ ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame );
+ ~ToolbarMenu_Impl();
+
+ void setAccessible( ToolbarMenuAcc* pAccessible );
+
+ void fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
+ bool hasAccessibleListeners();
+
+ sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException);
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+
+ void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ sal_Bool isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ void clearAccessibleSelection();
+
+ ToolbarMenuEntry* implGetEntry( int nEntry ) const;
+ void notifyHighlightedEntry();
+
+ void implHighlightControl( sal_uInt16 nCode, Control* pControl );
+};
+
+}
diff --git a/svtools/source/control/urlcontrol.cxx b/svtools/source/control/urlcontrol.cxx
new file mode 100644
index 000000000000..788948355965
--- /dev/null
+++ b/svtools/source/control/urlcontrol.cxx
@@ -0,0 +1,95 @@
+/*************************************************************************
+ *
+ * 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 <svtools/urlcontrol.hxx>
+#include "svl/filenotation.hxx"
+
+//.........................................................................
+namespace svt
+{
+//.........................................................................
+
+ //=====================================================================
+ //= OFileURLControl
+ //=====================================================================
+ //---------------------------------------------------------------------
+ OFileURLControl::OFileURLControl(Window* _pParent)
+ :SvtURLBox(_pParent, INET_PROT_FILE)
+ {
+ DisableHistory();
+ }
+
+ //---------------------------------------------------------------------
+ OFileURLControl::OFileURLControl(Window* _pParent, const ResId& _rId)
+ :SvtURLBox(_pParent, _rId, INET_PROT_FILE)
+ {
+ DisableHistory();
+ }
+
+ //---------------------------------------------------------------------
+ long OFileURLControl::PreNotify( NotifyEvent& _rNEvt )
+ {
+ if (GetSubEdit() == _rNEvt.GetWindow())
+ if (EVENT_KEYINPUT == _rNEvt.GetType())
+ if (KEY_RETURN == _rNEvt.GetKeyEvent()->GetKeyCode().GetCode())
+ if (IsInDropDown())
+ m_sPreservedText = GetURL();
+
+ return SvtURLBox::PreNotify(_rNEvt);
+ }
+
+ //---------------------------------------------------------------------
+ long OFileURLControl::Notify( NotifyEvent& _rNEvt )
+ {
+ if (GetSubEdit() == _rNEvt.GetWindow())
+ if (EVENT_KEYINPUT == _rNEvt.GetType())
+ if (KEY_RETURN == _rNEvt.GetKeyEvent()->GetKeyCode().GetCode())
+ if (IsInDropDown())
+ {
+ long nReturn = SvtURLBox::Notify(_rNEvt);
+
+ // build a system dependent (thus more user readable) file name
+ OFileNotation aTransformer(m_sPreservedText, OFileNotation::N_URL);
+ SetText(aTransformer.get(OFileNotation::N_SYSTEM));
+ Modify();
+
+ // Update the pick list
+ UpdatePickList();
+
+ return nReturn;
+ }
+
+ return SvtURLBox::Notify(_rNEvt);
+ }
+
+//.........................................................................
+} // namespace svt
+//.........................................................................
+
diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx
new file mode 100644
index 000000000000..1b98e3197bd3
--- /dev/null
+++ b/svtools/source/control/valueacc.cxx
@@ -0,0 +1,1258 @@
+/*************************************************************************
+ *
+ * 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"
+
+#define _SV_VALUESET_CXX
+
+#include <unotools/accessiblestatesethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <svtools/valueset.hxx>
+#include "valueimp.hxx"
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+
+using namespace ::com::sun::star;
+
+// ----------------
+// - ValueSetItem -
+// ----------------
+
+ValueSetItem::ValueSetItem( ValueSet& rParent ) :
+ mrParent( rParent ),
+ mnId( 0 ),
+ mnBits( 0 ),
+ mpData( NULL ),
+ mpxAcc( NULL )
+{
+}
+
+// -----------------------------------------------------------------------
+
+ValueSetItem::~ValueSetItem()
+{
+ if( mpxAcc )
+ {
+ static_cast< ValueItemAcc* >( mpxAcc->get() )->ParentDestroyed();
+ delete mpxAcc;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > ValueSetItem::GetAccessible( bool bIsTransientChildrenDisabled )
+{
+ if( !mpxAcc )
+ mpxAcc = new uno::Reference< accessibility::XAccessible >( new ValueItemAcc( this, bIsTransientChildrenDisabled ) );
+
+ return *mpxAcc;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSetItem::ClearAccessible()
+{
+ if( mpxAcc )
+ delete mpxAcc, mpxAcc = NULL;
+}
+
+
+// ---------------
+// - ValueSetAcc -
+// ---------------
+
+ValueSetAcc::ValueSetAcc( ValueSet* pParent, bool bIsTransientChildrenDisabled ) :
+ ValueSetAccComponentBase (m_aMutex),
+ mpParent( pParent ),
+ mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled ),
+ mbIsFocused(false)
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ValueSetAcc::~ValueSetAcc()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSetAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
+{
+ if( nEventId )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners );
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() );
+ accessibility::AccessibleEventObject aEvtObject;
+
+ aEvtObject.EventId = nEventId;
+ aEvtObject.Source = static_cast<uno::XWeak*>(this);
+ aEvtObject.NewValue = rNewValue;
+ aEvtObject.OldValue = rOldValue;
+
+ while( aIter != aTmpListeners.end() )
+ {
+ try
+ {
+ (*aIter)->notifyEvent( aEvtObject );
+ }
+ catch( uno::Exception& )
+ {
+ }
+
+ aIter++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+const uno::Sequence< sal_Int8 >& ValueSetAcc::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq;
+
+ if( !aSeq.getLength() )
+ {
+ static osl::Mutex aCreateMutex;
+ osl::Guard< osl::Mutex > aGuard( aCreateMutex );
+
+ aSeq.realloc( 16 );
+ rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
+ }
+
+ return aSeq;
+}
+
+// -----------------------------------------------------------------------------
+
+ValueSetAcc* ValueSetAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
+ throw()
+{
+ try
+ {
+ uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
+ return( xUnoTunnel.is() ? reinterpret_cast<ValueSetAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ValueSetAcc::getUnoTunnelId() ))) : NULL );
+ }
+ catch( const ::com::sun::star::uno::Exception& )
+ {
+ return NULL;
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+
+void ValueSetAcc::GetFocus (void)
+{
+ mbIsFocused = true;
+
+ // Boradcast the state change.
+ ::com::sun::star::uno::Any aOldState, aNewState;
+ aNewState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
+ FireAccessibleEvent(
+ ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED,
+ aOldState, aNewState);
+}
+
+// -----------------------------------------------------------------------------
+
+void ValueSetAcc::LoseFocus (void)
+{
+ mbIsFocused = false;
+
+ // Boradcast the state change.
+ ::com::sun::star::uno::Any aOldState, aNewState;
+ aOldState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
+ FireAccessibleEvent(
+ ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED,
+ aOldState, aNewState);
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessibleContext > SAL_CALL ValueSetAcc::getAccessibleContext()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ return this;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueSetAcc::getAccessibleChildCount()
+ throw (uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ThrowIfDisposed();
+
+ sal_Int32 nCount = mpParent->ImplGetVisibleItemCount();
+ if (HasNoneField())
+ nCount += 1;
+ return nCount;
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleChild( sal_Int32 i )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ uno::Reference< accessibility::XAccessible > xRet;
+ ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(i));
+
+ if( pItem )
+ xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
+ else
+ throw lang::IndexOutOfBoundsException();
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleParent()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ Window* pParent = mpParent->GetParent();
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ if( pParent )
+ xRet = pParent->GetAccessible();
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueSetAcc::getAccessibleIndexInParent()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ Window* pParent = mpParent->GetParent();
+ sal_Int32 nRet = 0;
+
+ if( pParent )
+ {
+ sal_Bool bFound = sal_False;
+
+ for( sal_uInt16 i = 0, nCount = pParent->GetChildCount(); ( i < nCount ) && !bFound; i++ )
+ {
+ if( pParent->GetChild( i ) == mpParent )
+ {
+ nRet = i;
+ bFound = sal_True;
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int16 SAL_CALL ValueSetAcc::getAccessibleRole()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ // #i73746# As the Java Access Bridge (v 2.0.1) uses "managesDescendants"
+ // always if the role is LIST, we need a different role in this case
+ return (mbIsTransientChildrenDisabled
+ ? accessibility::AccessibleRole::PANEL
+ : accessibility::AccessibleRole::LIST );
+}
+
+// -----------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL ValueSetAcc::getAccessibleDescription()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ String aRet( RTL_CONSTASCII_USTRINGPARAM( "ValueSet" ) );
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL ValueSetAcc::getAccessibleName()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ String aRet;
+
+ if ( mpParent )
+ aRet = mpParent->GetAccessibleName();
+
+ if ( !aRet.Len() )
+ {
+ Window* pLabel = mpParent->GetAccessibleRelationLabeledBy();
+ if ( pLabel && pLabel != mpParent )
+ aRet = OutputDevice::GetNonMnemonicString( pLabel->GetText() );
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ValueSetAcc::getAccessibleRelationSet()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ return uno::Reference< accessibility::XAccessibleRelationSet >();
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ValueSetAcc::getAccessibleStateSet()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
+
+ // Set some states.
+ pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
+ pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
+ pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
+ pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
+ if ( !mbIsTransientChildrenDisabled )
+ pStateSet->AddState (accessibility::AccessibleStateType::MANAGES_DESCENDANTS);
+ pStateSet->AddState (accessibility::AccessibleStateType::FOCUSABLE);
+ if (mbIsFocused)
+ pStateSet->AddState (accessibility::AccessibleStateType::FOCUSED);
+
+ return pStateSet;
+}
+
+// -----------------------------------------------------------------------------
+
+lang::Locale SAL_CALL ValueSetAcc::getLocale()
+ throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const ::rtl::OUString aEmptyStr;
+ uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() );
+ lang::Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr );
+
+ if( xParent.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+
+ if( xParentContext.is() )
+ aRet = xParentContext->getLocale ();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueSetAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (m_aMutex);
+
+ if( rxListener.is() )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin();
+ sal_Bool bFound = sal_False;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ bFound = sal_True;
+ else
+ aIter++;
+ }
+
+ if (!bFound)
+ mxEventListeners.push_back( rxListener );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueSetAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ ::osl::MutexGuard aGuard (m_aMutex);
+
+ if( rxListener.is() )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin();
+ sal_Bool bFound = sal_False;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ {
+ mxEventListeners.erase( aIter );
+ bFound = sal_True;
+ }
+ else
+ aIter++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL ValueSetAcc::containsPoint( const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aRect( getBounds() );
+ const Point aSize( aRect.Width, aRect.Height );
+ const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
+
+ return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleAtPoint( const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const sal_uInt16 nItemId = mpParent->GetItemId( Point( aPoint.X, aPoint.Y ) );
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ if( VALUESET_ITEM_NOTFOUND != nItemId )
+ {
+ const sal_uInt16 nItemPos = mpParent->GetItemPos( nItemId );
+
+ if( VALUESET_ITEM_NONEITEM != nItemPos )
+ {
+ ValueSetItem* pItem = mpParent->mpImpl->mpItemList->GetObject( nItemPos );
+
+ if( ( pItem->meType != VALUESETITEM_SPACE ) && !pItem->maRect.IsEmpty() )
+ xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
+ }
+ }
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Rectangle SAL_CALL ValueSetAcc::getBounds()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const Point aOutPos( mpParent->GetPosPixel() );
+ const Size aOutSize( mpParent->GetOutputSizePixel() );
+ awt::Rectangle aRet;
+
+ aRet.X = aOutPos.X();
+ aRet.Y = aOutPos.Y();
+ aRet.Width = aOutSize.Width();
+ aRet.Height = aOutSize.Height();
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ValueSetAcc::getLocation()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aRect( getBounds() );
+ awt::Point aRet;
+
+ aRet.X = aRect.X;
+ aRet.Y = aRect.Y;
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ValueSetAcc::getLocationOnScreen()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const Point aScreenPos( mpParent->OutputToAbsoluteScreenPixel( Point() ) );
+ awt::Point aRet;
+
+ aRet.X = aScreenPos.X();
+ aRet.Y = aScreenPos.Y();
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Size SAL_CALL ValueSetAcc::getSize()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const awt::Rectangle aRect( getBounds() );
+ awt::Size aRet;
+
+ aRet.Width = aRect.Width;
+ aRet.Height = aRect.Height;
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueSetAcc::grabFocus()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ mpParent->GrabFocus();
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Any SAL_CALL ValueSetAcc::getAccessibleKeyBinding()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ return uno::Any();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueSetAcc::getForeground( )
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueSetAcc::getBackground( )
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueSetAcc::selectAccessibleChild( sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
+
+ if(pItem != NULL)
+ {
+ mpParent->SelectItem( pItem->mnId );
+ mpParent->Select ();
+ }
+ else
+ throw lang::IndexOutOfBoundsException();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL ValueSetAcc::isAccessibleChildSelected( sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
+ sal_Bool bRet = sal_False;
+
+ if (pItem != NULL)
+ bRet = mpParent->IsItemSelected( pItem->mnId );
+ else
+ throw lang::IndexOutOfBoundsException();
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueSetAcc::clearAccessibleSelection()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ mpParent->SetNoSelection();
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueSetAcc::selectAllAccessibleChildren()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ // unsupported due to single selection only
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueSetAcc::getSelectedAccessibleChildCount()
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ sal_Int32 nRet = 0;
+
+ for( sal_uInt16 i = 0, nCount = getItemCount(); i < nCount; i++ )
+ {
+ ValueSetItem* pItem = getItem (i);
+
+ if( pItem && mpParent->IsItemSelected( pItem->mnId ) )
+ ++nRet;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ for( sal_uInt16 i = 0, nCount = getItemCount(), nSel = 0; ( i < nCount ) && !xRet.is(); i++ )
+ {
+ ValueSetItem* pItem = getItem(i);
+
+ if( pItem && mpParent->IsItemSelected( pItem->mnId ) && ( nSelectedChildIndex == static_cast< sal_Int32 >( nSel++ ) ) )
+ xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
+ }
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueSetAcc::deselectAccessibleChild( sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ // Because of the single selection we can reset the whole selection when
+ // the specified child is currently selected.
+ if (isAccessibleChildSelected(nChildIndex))
+ mpParent->SetNoSelection();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int64 SAL_CALL ValueSetAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException )
+{
+ sal_Int64 nRet;
+
+ if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ValueSetAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
+ nRet = reinterpret_cast< sal_Int64 >( this );
+ else
+ nRet = 0;
+
+ return nRet;
+}
+
+
+
+
+void SAL_CALL ValueSetAcc::disposing (void)
+{
+ ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> > aListenerListCopy;
+
+ {
+ // Make a copy of the list and clear the original.
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ::osl::MutexGuard aGuard (m_aMutex);
+ aListenerListCopy = mxEventListeners;
+ mxEventListeners.clear();
+
+ // Reset the pointer to the parent. It has to be the one who has
+ // disposed us because he is dying.
+ mpParent = NULL;
+ }
+
+ // Inform all listeners that this objects is disposing.
+ ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> >::const_iterator
+ aListenerIterator (aListenerListCopy.begin());
+ lang::EventObject aEvent (static_cast<accessibility::XAccessible*>(this));
+ while (aListenerIterator != aListenerListCopy.end())
+ {
+ try
+ {
+ (*aListenerIterator)->disposing (aEvent);
+ }
+ catch( uno::Exception& )
+ {
+ // Ignore exceptions.
+ }
+
+ ++aListenerIterator;
+ }
+}
+
+
+sal_uInt16 ValueSetAcc::getItemCount (void) const
+{
+ sal_uInt16 nCount = mpParent->ImplGetVisibleItemCount();
+ // When the None-Item is visible then increase the number of items by
+ // one.
+ if (HasNoneField())
+ nCount += 1;
+ return nCount;
+}
+
+
+ValueSetItem* ValueSetAcc::getItem (sal_uInt16 nIndex) const
+{
+ ValueSetItem* pItem = NULL;
+
+ if (HasNoneField())
+ {
+ if (nIndex == 0)
+ // When present the first item is the then allways visible none field.
+ pItem = mpParent->ImplGetItem (VALUESET_ITEM_NONEITEM);
+ else
+ // Shift down the index to compensate for the none field.
+ nIndex -= 1;
+ }
+ if (pItem == NULL)
+ pItem = mpParent->ImplGetVisibleItem (static_cast<sal_uInt16>(nIndex));
+
+ return pItem;
+}
+
+
+
+
+void ValueSetAcc::ThrowIfDisposed (void)
+ throw (::com::sun::star::lang::DisposedException)
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ OSL_TRACE ("Calling disposed object. Throwing exception:");
+ throw lang::DisposedException (
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
+ static_cast<uno::XWeak*>(this));
+ }
+ else
+ {
+ DBG_ASSERT (mpParent!=NULL, "ValueSetAcc not disposed but mpParent == NULL");
+ }
+}
+
+
+
+sal_Bool ValueSetAcc::IsDisposed (void)
+{
+ return (rBHelper.bDisposed || rBHelper.bInDispose);
+}
+
+
+
+
+bool ValueSetAcc::HasNoneField (void) const
+{
+ DBG_ASSERT (mpParent!=NULL, "ValueSetAcc::HasNoneField called with mpParent==NULL");
+ return ((mpParent->GetStyle() & WB_NONEFIELD) != 0);
+}
+
+
+
+
+// ----------------
+// - ValueItemAcc -
+// ----------------
+
+ValueItemAcc::ValueItemAcc( ValueSetItem* pParent, bool bIsTransientChildrenDisabled ) :
+ mpParent( pParent ),
+ mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+ValueItemAcc::~ValueItemAcc()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ValueItemAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
+{
+ if( nEventId )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners );
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() );
+ accessibility::AccessibleEventObject aEvtObject;
+
+ aEvtObject.EventId = nEventId;
+ aEvtObject.Source = static_cast<uno::XWeak*>(this);
+ aEvtObject.NewValue = rNewValue;
+ aEvtObject.OldValue = rOldValue;
+
+ while( aIter != aTmpListeners.end() )
+ {
+ (*aIter)->notifyEvent( aEvtObject );
+ aIter++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void ValueItemAcc::ParentDestroyed()
+{
+ const ::vos::OGuard aGuard( maMutex );
+ mpParent = NULL;
+}
+
+// -----------------------------------------------------------------------------
+
+const uno::Sequence< sal_Int8 >& ValueItemAcc::getUnoTunnelId()
+{
+ static uno::Sequence< sal_Int8 > aSeq;
+
+ if( !aSeq.getLength() )
+ {
+ static osl::Mutex aCreateMutex;
+ osl::Guard< osl::Mutex > aGuard( aCreateMutex );
+
+ aSeq.realloc( 16 );
+ rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
+ }
+
+ return aSeq;
+}
+
+// -----------------------------------------------------------------------------
+
+ValueItemAcc* ValueItemAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
+ throw()
+{
+ try
+ {
+ uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
+ return( xUnoTunnel.is() ? reinterpret_cast<ValueItemAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ValueItemAcc::getUnoTunnelId() ))) : NULL );
+ }
+ catch( const ::com::sun::star::uno::Exception& )
+ {
+ return NULL;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessibleContext > SAL_CALL ValueItemAcc::getAccessibleContext()
+ throw (uno::RuntimeException)
+{
+ return this;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueItemAcc::getAccessibleChildCount()
+ throw (uno::RuntimeException)
+{
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleChild( sal_Int32 )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ throw lang::IndexOutOfBoundsException();
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleParent()
+ throw (uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ if( mpParent )
+ xRet = mpParent->mrParent.GetAccessible();
+
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueItemAcc::getAccessibleIndexInParent()
+ throw (uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ // The index defaults to -1 to indicate the child does not belong to its
+ // parent.
+ sal_Int32 nIndexInParent = -1;
+
+ if( mpParent )
+ {
+ bool bDone = false;
+
+ sal_uInt16 nCount = mpParent->mrParent.ImplGetVisibleItemCount();
+ ValueSetItem* pItem;
+ for (sal_uInt16 i=0; i<nCount && !bDone; i++)
+ {
+ // Guard the retrieval of the i-th child with a try/catch block
+ // just in case the number of children changes in the mean time.
+ try
+ {
+ pItem = mpParent->mrParent.ImplGetVisibleItem (i);
+ }
+ catch (lang::IndexOutOfBoundsException aException)
+ {
+ pItem = NULL;
+ }
+
+ // Do not create an accessible object for the test.
+ if (pItem != NULL && pItem->mpxAcc != NULL)
+ if (pItem->GetAccessible( mbIsTransientChildrenDisabled ).get() == this )
+ {
+ nIndexInParent = i;
+ bDone = true;
+ }
+ }
+ }
+
+ return nIndexInParent;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int16 SAL_CALL ValueItemAcc::getAccessibleRole()
+ throw (uno::RuntimeException)
+{
+ return accessibility::AccessibleRole::LIST_ITEM;
+}
+
+// -----------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleDescription()
+ throw (uno::RuntimeException)
+{
+ return ::rtl::OUString();
+}
+
+// -----------------------------------------------------------------------------
+
+::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleName()
+ throw (uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ String aRet;
+
+ if( mpParent )
+ {
+ aRet = mpParent->maText;
+
+ if( !aRet.Len() )
+ {
+ aRet = String( RTL_CONSTASCII_USTRINGPARAM( "Item " ) );
+ aRet += String::CreateFromInt32( mpParent->mnId );
+ }
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ValueItemAcc::getAccessibleRelationSet()
+ throw (uno::RuntimeException)
+{
+ return uno::Reference< accessibility::XAccessibleRelationSet >();
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ValueItemAcc::getAccessibleStateSet()
+ throw (uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper;
+
+ if( mpParent )
+ {
+ pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
+ pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
+ pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
+ pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
+ if ( !mbIsTransientChildrenDisabled )
+ pStateSet->AddState (accessibility::AccessibleStateType::TRANSIENT);
+
+ // SELECTABLE
+ pStateSet->AddState( accessibility::AccessibleStateType::SELECTABLE );
+ // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSABLE );
+
+ // SELECTED
+ if( mpParent->mrParent.GetSelectItemId() == mpParent->mnId )
+ {
+ pStateSet->AddState( accessibility::AccessibleStateType::SELECTED );
+ // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSED );
+ }
+ }
+
+ return pStateSet;
+}
+
+// -----------------------------------------------------------------------------
+
+lang::Locale SAL_CALL ValueItemAcc::getLocale()
+ throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ const ::rtl::OUString aEmptyStr;
+ uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() );
+ lang::Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr );
+
+ if( xParent.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
+
+ if( xParentContext.is() )
+ aRet = xParentContext->getLocale();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueItemAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ const ::vos::OGuard aGuard( maMutex );
+
+ if( rxListener.is() )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin();
+ sal_Bool bFound = sal_False;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ bFound = sal_True;
+ else
+ aIter++;
+ }
+
+ if (!bFound)
+ mxEventListeners.push_back( rxListener );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueItemAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
+ throw (uno::RuntimeException)
+{
+ const ::vos::OGuard aGuard( maMutex );
+
+ if( rxListener.is() )
+ {
+ ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin();
+ sal_Bool bFound = sal_False;
+
+ while( !bFound && ( aIter != mxEventListeners.end() ) )
+ {
+ if( *aIter == rxListener )
+ {
+ mxEventListeners.erase( aIter );
+ bFound = sal_True;
+ }
+ else
+ aIter++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL ValueItemAcc::containsPoint( const awt::Point& aPoint )
+ throw (uno::RuntimeException)
+{
+ const awt::Rectangle aRect( getBounds() );
+ const Point aSize( aRect.Width, aRect.Height );
+ const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
+
+ return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleAtPoint( const awt::Point& )
+ throw (uno::RuntimeException)
+{
+ uno::Reference< accessibility::XAccessible > xRet;
+ return xRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Rectangle SAL_CALL ValueItemAcc::getBounds()
+ throw (uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ awt::Rectangle aRet;
+
+ if( mpParent )
+ {
+ Rectangle aRect( mpParent->maRect );
+ Point aOrigin;
+ Rectangle aParentRect( aOrigin, mpParent->mrParent.GetOutputSizePixel() );
+
+ aRect.Intersection( aParentRect );
+
+ aRet.X = aRect.Left();
+ aRet.Y = aRect.Top();
+ aRet.Width = aRect.GetWidth();
+ aRet.Height = aRect.GetHeight();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ValueItemAcc::getLocation()
+ throw (uno::RuntimeException)
+{
+ const awt::Rectangle aRect( getBounds() );
+ awt::Point aRet;
+
+ aRet.X = aRect.X;
+ aRet.Y = aRect.Y;
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Point SAL_CALL ValueItemAcc::getLocationOnScreen()
+ throw (uno::RuntimeException)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ awt::Point aRet;
+
+ if( mpParent )
+ {
+ const Point aScreenPos( mpParent->mrParent.OutputToAbsoluteScreenPixel( mpParent->maRect.TopLeft() ) );
+
+ aRet.X = aScreenPos.X();
+ aRet.Y = aScreenPos.Y();
+ }
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+awt::Size SAL_CALL ValueItemAcc::getSize()
+ throw (uno::RuntimeException)
+{
+ const awt::Rectangle aRect( getBounds() );
+ awt::Size aRet;
+
+ aRet.Width = aRect.Width;
+ aRet.Height = aRect.Height;
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL ValueItemAcc::grabFocus()
+ throw (uno::RuntimeException)
+{
+ // nothing to do
+}
+
+// -----------------------------------------------------------------------------
+
+uno::Any SAL_CALL ValueItemAcc::getAccessibleKeyBinding()
+ throw (uno::RuntimeException)
+{
+ return uno::Any();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueItemAcc::getForeground( )
+ throw (uno::RuntimeException)
+{
+ sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueItemAcc::getBackground( )
+ throw (uno::RuntimeException)
+{
+ sal_uInt32 nColor;
+ if (mpParent && mpParent->meType == VALUESETITEM_COLOR)
+ nColor = mpParent->maColor.GetColor();
+ else
+ nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int64 SAL_CALL ValueItemAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException )
+{
+ sal_Int64 nRet;
+
+ if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ValueItemAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
+ nRet = reinterpret_cast< sal_Int64 >( this );
+ else
+ nRet = 0;
+
+ return nRet;
+}
diff --git a/svtools/source/control/valueimp.hxx b/svtools/source/control/valueimp.hxx
new file mode 100755
index 000000000000..bc5252372be9
--- /dev/null
+++ b/svtools/source/control/valueimp.hxx
@@ -0,0 +1,330 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include <vos/mutex.hxx>
+#include <tools/list.hxx>
+#include <tools/color.hxx>
+#include <tools/string.hxx>
+#ifndef _IMAGE_HXX
+#include <vcl/image.hxx>
+#endif
+#include <rtl/uuid.h>
+#include <cppuhelper/implbase5.hxx>
+#include <cppuhelper/compbase6.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+
+#include <memory>
+#include <vector>
+
+// -----------
+// - Defines -
+// -----------
+
+#define ITEM_OFFSET 4
+#define ITEM_OFFSET_DOUBLE 6
+#define NAME_LINE_OFF_X 2
+#define NAME_LINE_OFF_Y 2
+#define NAME_LINE_HEIGHT 2
+#define NAME_OFFSET 2
+#define SCRBAR_OFFSET 1
+#define VALUESET_ITEM_NONEITEM 0xFFFE
+#define VALUESET_SCROLL_OFFSET 4
+
+// --------------------
+// - ValueSetItemType -
+// --------------------
+
+enum ValueSetItemType
+{
+ VALUESETITEM_NONE,
+ VALUESETITEM_IMAGE,
+ VALUESETITEM_COLOR,
+ VALUESETITEM_USERDRAW,
+ VALUESETITEM_SPACE
+};
+
+// ----------------
+// - ValueSetItem -
+// ----------------
+
+class ValueSet;
+
+struct ValueSetItem
+{
+ ValueSet& mrParent;
+ sal_uInt16 mnId;
+ sal_uInt16 mnBits;
+ ValueSetItemType meType;
+ Image maImage;
+ Color maColor;
+ XubString maText;
+ void* mpData;
+ Rectangle maRect;
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >* mpxAcc;
+
+ ValueSetItem( ValueSet& rParent );
+ ~ValueSetItem();
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
+ GetAccessible( bool bIsTransientChildrenDisabled );
+ void ClearAccessible();
+};
+
+// -----------------------------------------------------------------------------
+
+DECLARE_LIST( ValueItemList, ValueSetItem* )
+
+// -----------------------------------------------------------------------------
+
+struct ValueSet_Impl
+{
+ ::std::auto_ptr< ValueItemList > mpItemList;
+ bool mbIsTransientChildrenDisabled;
+ Link maHighlightHdl;
+
+ ValueSet_Impl() : mpItemList( ::std::auto_ptr< ValueItemList >( new ValueItemList() ) ),
+ mbIsTransientChildrenDisabled( false )
+ {
+ }
+};
+
+// ---------------
+// - ValueSetAcc -
+// ---------------
+
+typedef ::cppu::WeakComponentImplHelper6<
+ ::com::sun::star::accessibility::XAccessible,
+ ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
+ ::com::sun::star::accessibility::XAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleComponent,
+ ::com::sun::star::accessibility::XAccessibleSelection,
+ ::com::sun::star::lang::XUnoTunnel >
+ ValueSetAccComponentBase;
+
+class ValueSetAcc :
+ public ::comphelper::OBaseMutex,
+ public ValueSetAccComponentBase
+{
+public:
+
+ ValueSetAcc( ValueSet* pParent, bool bIsTransientChildrenDisabled );
+ ~ValueSetAcc();
+
+ void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
+ sal_Bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); }
+
+ static ValueSetAcc* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxData ) throw();
+
+public:
+
+ /** Called by the corresponding ValueSet when it gets the focus.
+ Stores the new focus state and broadcasts a state change event.
+ */
+ void GetFocus (void);
+
+ /** Called by the corresponding ValueSet when it loses the focus.
+ Stores the new focus state and broadcasts a state change event.
+ */
+ void LoseFocus (void);
+
+
+ // XAccessible
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleEventBroadcaster
+ using cppu::WeakComponentImplHelper6<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection, com::sun::star::lang::XUnoTunnel>::addEventListener;
+ virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+ using cppu::WeakComponentImplHelper6<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection, com::sun::star::lang::XUnoTunnel>::removeEventListener;
+ virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleComponent
+ virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleSelection
+ virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL clearAccessibleSelection( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL selectAllAccessibleChildren( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( ::com::sun::star::uno::RuntimeException );
+
+private:
+ // ::vos::OMutex maMutex;
+ ::std::vector< ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener > > mxEventListeners;
+ ValueSet* mpParent;
+ bool mbIsTransientChildrenDisabled;
+ /// The current FOCUSED state.
+ bool mbIsFocused;
+
+ static const ::com::sun::star::uno::Sequence< sal_Int8 >& getUnoTunnelId();
+
+ /** Tell all listeners that the object is dying. This callback is
+ usually called from the WeakComponentImplHelper class.
+ */
+ virtual void SAL_CALL disposing (void);
+
+ /** Return the number of items. This takes the None-Item into account.
+ */
+ sal_uInt16 getItemCount (void) const;
+
+ /** Return the item associated with the given index. The None-Item is
+ taken into account which, when present, is taken to be the first
+ (with index 0) item.
+ @param nIndex
+ Index of the item to return. The index 0 denotes the None-Item
+ when present.
+ @return
+ Returns NULL when the given index is out of range.
+ */
+ ValueSetItem* getItem (sal_uInt16 nIndex) const;
+
+ /** Check whether or not the object has been disposed (or is in the
+ state of beeing disposed). If that is the case then
+ DisposedException is thrown to inform the (indirect) caller of the
+ foul deed.
+ */
+ void ThrowIfDisposed (void)
+ throw (::com::sun::star::lang::DisposedException);
+
+ /** Check whether or not the object has been disposed (or is in the
+ state of beeing disposed).
+
+ @return sal_True, if the object is disposed or in the course
+ of being disposed. Otherwise, sal_False is returned.
+ */
+ sal_Bool IsDisposed (void);
+
+ /** Check whether the value set has a 'none' field, i.e. a field (button)
+ that deselects any items (selects none of them).
+ @return
+ Returns <true/> if there is a 'none' field and <false/> it it is
+ missing.
+ */
+ bool HasNoneField (void) const;
+};
+
+// ----------------
+// - ValueItemAcc -
+// ----------------
+
+class ValueItemAcc : public ::cppu::WeakImplHelper5< ::com::sun::star::accessibility::XAccessible,
+ ::com::sun::star::accessibility::XAccessibleEventBroadcaster,
+ ::com::sun::star::accessibility::XAccessibleContext,
+ ::com::sun::star::accessibility::XAccessibleComponent,
+ ::com::sun::star::lang::XUnoTunnel >
+{
+private:
+
+ ::std::vector< ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessibleEventListener > > mxEventListeners;
+ ::vos::OMutex maMutex;
+ ValueSetItem* mpParent;
+ bool mbIsTransientChildrenDisabled;
+
+ static const ::com::sun::star::uno::Sequence< sal_Int8 >& getUnoTunnelId();
+
+public:
+
+ ValueItemAcc( ValueSetItem* pParent, bool bIsTransientChildrenDisabled );
+ ~ValueItemAcc();
+
+ void ParentDestroyed();
+
+ void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue );
+ sal_Bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); }
+
+ static ValueItemAcc* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxData ) throw();
+
+public:
+
+ // XAccessible
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleEventBroadcaster
+ virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleContext
+ virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException);
+
+ // XAccessibleComponent
+ virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( ::com::sun::star::uno::RuntimeException );
+};
diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx
new file mode 100644
index 000000000000..8875ce66354c
--- /dev/null
+++ b/svtools/source/control/valueset.cxx
@@ -0,0 +1,2758 @@
+/*************************************************************************
+ *
+ * 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 <tools/list.hxx>
+#include <tools/debug.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/svapp.hxx>
+#ifndef _SCRBAR_HXX
+#include <vcl/scrbar.hxx>
+#endif
+#ifndef _HELP_HXX
+#include <vcl/help.hxx>
+#endif
+#include <com/sun/star/accessibility/AccessibleEventObject.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <rtl/ustring.hxx>
+
+#include "valueimp.hxx"
+
+#define _SV_VALUESET_CXX
+#include <svtools/valueset.hxx>
+
+// ------------
+// - ValueSet -
+// ------------
+
+void ValueSet::ImplInit()
+{
+ // Size aWinSize = GetSizePixel();
+ mpImpl = new ValueSet_Impl;
+ mpNoneItem = NULL;
+ mpScrBar = NULL;
+ mnTextOffset = 0;
+ mnVisLines = 0;
+ mnLines = 0;
+ mnUserItemWidth = 0;
+ mnUserItemHeight = 0;
+ mnFirstLine = 0;
+ mnOldItemId = 0;
+ mnSelItemId = 0;
+ mnHighItemId = 0;
+ mnDropPos = VALUESET_ITEM_NOTFOUND;
+ mnCols = 0;
+ mnCurCol = 0;
+ mnUserCols = 0;
+ mnUserVisLines = 0;
+ mnSpacing = 0;
+ mnFrameStyle = 0;
+ mbFormat = sal_True;
+ mbHighlight = sal_False ;
+ mbSelection = sal_False;
+ mbNoSelection = sal_True;
+ mbDrawSelection = sal_True;
+ mbBlackSel = sal_False;
+ mbDoubleSel = sal_False;
+ mbScroll = sal_False;
+ mbDropPos = sal_False;
+ mbFullMode = sal_True;
+
+ // #106446#, #106601# force mirroring of virtual device
+ maVirDev.EnableRTL( GetParent()->IsRTLEnabled() );
+
+ ImplInitSettings( sal_True, sal_True, sal_True );
+}
+
+// -----------------------------------------------------------------------
+
+ValueSet::ValueSet( Window* pParent, WinBits nWinStyle, bool bDisableTransientChildren ) :
+ Control( pParent, nWinStyle ),
+ maVirDev( *this ),
+ maColor( COL_TRANSPARENT )
+{
+ ImplInit();
+ if( mpImpl )
+ mpImpl->mbIsTransientChildrenDisabled = bDisableTransientChildren;
+}
+
+// -----------------------------------------------------------------------
+
+ValueSet::ValueSet( Window* pParent, const ResId& rResId, bool bDisableTransientChildren ) :
+ Control( pParent, rResId ),
+ maVirDev( *this ),
+ maColor( COL_TRANSPARENT )
+{
+ ImplInit();
+ if( mpImpl )
+ mpImpl->mbIsTransientChildrenDisabled = bDisableTransientChildren;
+}
+
+// -----------------------------------------------------------------------
+
+ValueSet::~ValueSet()
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent>
+ xComponent (GetAccessible(sal_False), ::com::sun::star::uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose ();
+
+ if ( mpScrBar )
+ delete mpScrBar;
+
+ if ( mpNoneItem )
+ delete mpNoneItem;
+
+ ImplDeleteItems();
+ delete mpImpl;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplDeleteItems()
+{
+ for( ValueSetItem* pItem = mpImpl->mpItemList->First(); pItem; pItem = mpImpl->mpItemList->Next() )
+ {
+ if( !pItem->maRect.IsEmpty() && ImplHasAccessibleListeners() )
+ {
+ ::com::sun::star::uno::Any aOldAny, aNewAny;
+
+ aOldAny <<= pItem->GetAccessible( mpImpl->mbIsTransientChildrenDisabled );
+ ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
+ }
+
+ delete pItem;
+ }
+
+ mpImpl->mpItemList->Clear();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplInitSettings( sal_Bool bFont,
+ sal_Bool bForeground, sal_Bool bBackground )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+
+ if ( bFont )
+ {
+ Font aFont;
+ aFont = rStyleSettings.GetAppFont();
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ SetZoomedPointFont( aFont );
+ }
+
+ if ( bForeground || bFont )
+ {
+ Color aColor;
+ if ( IsControlForeground() )
+ aColor = GetControlForeground();
+ else
+ aColor = rStyleSettings.GetButtonTextColor();
+ SetTextColor( aColor );
+ SetTextFillColor();
+ }
+
+ if ( bBackground )
+ {
+ Color aColor;
+ if ( IsControlBackground() )
+ aColor = GetControlBackground();
+ else if ( GetStyle() & WB_MENUSTYLEVALUESET )
+ aColor = rStyleSettings.GetMenuColor();
+ else if ( IsEnabled() && (GetStyle() & WB_FLATVALUESET) )
+ aColor = rStyleSettings.GetWindowColor();
+ else
+ aColor = rStyleSettings.GetFaceColor();
+ SetBackground( aColor );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplInitScrollBar()
+{
+ if ( GetStyle() & WB_VSCROLL )
+ {
+ if ( !mpScrBar )
+ {
+ mpScrBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG );
+ mpScrBar->SetScrollHdl( LINK( this, ValueSet, ImplScrollHdl ) );
+ }
+ else
+ {
+ // Wegen Einstellungsaenderungen passen wir hier die Breite an
+ long nScrBarWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
+ mpScrBar->SetPosSizePixel( 0, 0, nScrBarWidth, 0, WINDOW_POSSIZE_WIDTH );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplFormatItem( ValueSetItem* pItem )
+{
+ if ( pItem->meType == VALUESETITEM_SPACE )
+ return;
+
+ Rectangle aRect = pItem->maRect;
+ WinBits nStyle = GetStyle();
+ if ( nStyle & WB_ITEMBORDER )
+ {
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ if ( nStyle & WB_FLATVALUESET )
+ {
+ if ( nStyle & WB_DOUBLEBORDER )
+ {
+ aRect.Left() += 2;
+ aRect.Top() += 2;
+ aRect.Right() -= 2;
+ aRect.Bottom() -= 2;
+ }
+ else
+ {
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ }
+ }
+ else
+ {
+ DecorationView aView( &maVirDev );
+ aRect = aView.DrawFrame( aRect, mnFrameStyle );
+ }
+ }
+
+ if ( pItem == mpNoneItem )
+ pItem->maText = GetText();
+
+ if ( (aRect.GetHeight() > 0) && (aRect.GetWidth() > 0) )
+ {
+ if ( pItem == mpNoneItem )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ maVirDev.SetFont( GetFont() );
+ maVirDev.SetTextColor( ( nStyle & WB_MENUSTYLEVALUESET ) ? rStyleSettings.GetMenuTextColor() : rStyleSettings.GetWindowTextColor() );
+ maVirDev.SetTextFillColor();
+ maVirDev.SetFillColor( ( nStyle & WB_MENUSTYLEVALUESET ) ? rStyleSettings.GetMenuColor() : rStyleSettings.GetWindowColor() );
+ maVirDev.DrawRect( aRect );
+ Point aTxtPos( aRect.Left()+2, aRect.Top() );
+ long nTxtWidth = GetTextWidth( pItem->maText );
+ if ( nStyle & WB_RADIOSEL )
+ {
+ aTxtPos.X() += 4;
+ aTxtPos.Y() += 4;
+ }
+ if ( (aTxtPos.X()+nTxtWidth) > aRect.Right() )
+ {
+ maVirDev.SetClipRegion( Region( aRect ) );
+ maVirDev.DrawText( aTxtPos, pItem->maText );
+ maVirDev.SetClipRegion();
+ }
+ else
+ maVirDev.DrawText( aTxtPos, pItem->maText );
+ }
+ else if ( pItem->meType == VALUESETITEM_COLOR )
+ {
+ maVirDev.SetFillColor( pItem->maColor );
+ maVirDev.DrawRect( aRect );
+ }
+ else
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ if ( IsColor() )
+ maVirDev.SetFillColor( maColor );
+ else if ( nStyle & WB_MENUSTYLEVALUESET )
+ maVirDev.SetFillColor( rStyleSettings.GetMenuColor() );
+ else if ( IsEnabled() )
+ maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
+ else
+ maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
+ maVirDev.DrawRect( aRect );
+
+ if ( pItem->meType == VALUESETITEM_USERDRAW )
+ {
+ UserDrawEvent aUDEvt( &maVirDev, aRect, pItem->mnId );
+ UserDraw( aUDEvt );
+ }
+ else
+ {
+ Size aImageSize = pItem->maImage.GetSizePixel();
+ Size aRectSize = aRect.GetSize();
+ Point aPos( aRect.Left(), aRect.Top() );
+ aPos.X() += (aRectSize.Width()-aImageSize.Width())/2;
+ aPos.Y() += (aRectSize.Height()-aImageSize.Height())/2;
+
+ sal_uInt16 nImageStyle = 0;
+ if( !IsEnabled() )
+ nImageStyle |= IMAGE_DRAW_DISABLE;
+
+ if ( (aImageSize.Width() > aRectSize.Width()) ||
+ (aImageSize.Height() > aRectSize.Height()) )
+ {
+ maVirDev.SetClipRegion( Region( aRect ) );
+ maVirDev.DrawImage( aPos, pItem->maImage, nImageStyle);
+ maVirDev.SetClipRegion();
+ }
+ else
+ maVirDev.DrawImage( aPos, pItem->maImage, nImageStyle );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ValueSet::CreateAccessible()
+{
+ return new ValueSetAcc( this, mpImpl->mbIsTransientChildrenDisabled );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Format()
+{
+ Size aWinSize = GetOutputSizePixel();
+ sal_uLong nItemCount = mpImpl->mpItemList->Count();
+ WinBits nStyle = GetStyle();
+ long nTxtHeight = GetTextHeight();
+ long nOff;
+ long nSpace;
+ long nNoneHeight;
+ long nNoneSpace;
+ ScrollBar* pDelScrBar = NULL;
+
+ // Scrolling beruecksichtigen
+ if ( nStyle & WB_VSCROLL )
+ ImplInitScrollBar();
+ else
+ {
+ if ( mpScrBar )
+ {
+ // ScrollBar erst spaeter zerstoeren, damit keine rekursiven
+ // Aufrufe entstehen koennen
+ pDelScrBar = mpScrBar;
+ mpScrBar = NULL;
+ }
+ }
+
+ // Item-Offset berechnen
+ if ( nStyle & WB_ITEMBORDER )
+ {
+ if ( nStyle & WB_DOUBLEBORDER )
+ nOff = ITEM_OFFSET_DOUBLE;
+ else
+ nOff = ITEM_OFFSET;
+ }
+ else
+ nOff = 0;
+ nSpace = mnSpacing;
+
+ // Groesse beruecksichtigen, wenn NameField vorhanden
+ if ( nStyle & WB_NAMEFIELD )
+ {
+ mnTextOffset = aWinSize.Height()-nTxtHeight-NAME_OFFSET;
+ aWinSize.Height() -= nTxtHeight+NAME_OFFSET;
+
+ if ( !(nStyle & WB_FLATVALUESET) )
+ {
+ mnTextOffset -= NAME_LINE_HEIGHT+NAME_LINE_OFF_Y;
+ aWinSize.Height() -= NAME_LINE_HEIGHT+NAME_LINE_OFF_Y;
+ }
+ }
+ else
+ mnTextOffset = 0;
+
+ // Offset und Groesse beruecksichtigen, wenn NoneField vorhanden
+ if ( nStyle & WB_NONEFIELD )
+ {
+ nNoneHeight = nTxtHeight+nOff;
+ nNoneSpace = nSpace;
+ if ( nStyle & WB_RADIOSEL )
+ nNoneHeight += 8;
+ }
+ else
+ {
+ nNoneHeight = 0;
+ nNoneSpace = 0;
+
+ if ( mpNoneItem )
+ {
+ delete mpNoneItem;
+ mpNoneItem = NULL;
+ }
+ }
+
+ // Breite vom ScrollBar berechnen
+ long nScrBarWidth = 0;
+ if ( mpScrBar )
+ nScrBarWidth = mpScrBar->GetSizePixel().Width()+SCRBAR_OFFSET;
+
+ // Spaltenanzahl berechnen
+ if ( !mnUserCols )
+ {
+ if ( mnUserItemWidth )
+ {
+ mnCols = (sal_uInt16)((aWinSize.Width()-nScrBarWidth+nSpace) / (mnUserItemWidth+nSpace));
+ if ( !mnCols )
+ mnCols = 1;
+ }
+ else
+ mnCols = 1;
+ }
+ else
+ mnCols = mnUserCols;
+
+ // Zeilenanzahl berechnen
+ mbScroll = sal_False;
+ mnLines = (long)mpImpl->mpItemList->Count() / mnCols;
+ if ( mpImpl->mpItemList->Count() % mnCols )
+ mnLines++;
+ else if ( !mnLines )
+ mnLines = 1;
+
+ long nCalcHeight = aWinSize.Height()-nNoneHeight;
+ if ( mnUserVisLines )
+ mnVisLines = mnUserVisLines;
+ else if ( mnUserItemHeight )
+ {
+ mnVisLines = (nCalcHeight-nNoneSpace+nSpace) / (mnUserItemHeight+nSpace);
+ if ( !mnVisLines )
+ mnVisLines = 1;
+ }
+ else
+ mnVisLines = mnLines;
+ if ( mnLines > mnVisLines )
+ mbScroll = sal_True;
+ if ( mnLines <= mnVisLines )
+ mnFirstLine = 0;
+ else
+ {
+ if ( mnFirstLine > (sal_uInt16)(mnLines-mnVisLines) )
+ mnFirstLine = (sal_uInt16)(mnLines-mnVisLines);
+ }
+
+ // Itemgroessen berechnen
+ long nColSpace = (mnCols-1)*nSpace;
+ long nLineSpace = ((mnVisLines-1)*nSpace)+nNoneSpace;
+ long nItemWidth;
+ long nItemHeight;
+ if ( mnUserItemWidth && !mnUserCols )
+ {
+ nItemWidth = mnUserItemWidth;
+ if ( nItemWidth > aWinSize.Width()-nScrBarWidth-nColSpace )
+ nItemWidth = aWinSize.Width()-nScrBarWidth-nColSpace;
+ }
+ else
+ nItemWidth = (aWinSize.Width()-nScrBarWidth-nColSpace) / mnCols;
+ if ( mnUserItemHeight && !mnUserVisLines )
+ {
+ nItemHeight = mnUserItemHeight;
+ if ( nItemHeight > nCalcHeight-nNoneSpace )
+ nItemHeight = nCalcHeight-nNoneSpace;
+ }
+ else
+ {
+ nCalcHeight -= nLineSpace;
+ nItemHeight = nCalcHeight / mnVisLines;
+ }
+
+ // Init VirDev
+ maVirDev.SetSettings( GetSettings() );
+ maVirDev.SetBackground( GetBackground() );
+ maVirDev.SetOutputSizePixel( aWinSize, sal_True );
+
+ // Bei zu kleinen Items machen wir nichts
+ long nMinHeight = 2;
+ if ( nStyle & WB_ITEMBORDER )
+ nMinHeight = 4;
+ if ( (nItemWidth <= 0) || (nItemHeight <= nMinHeight) || !nItemCount )
+ {
+ if ( nStyle & WB_NONEFIELD )
+ {
+ if ( mpNoneItem )
+ {
+ mpNoneItem->maRect.SetEmpty();
+ mpNoneItem->maText = GetText();
+ }
+ }
+
+ for ( sal_uLong i = 0; i < nItemCount; i++ )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( i );
+ pItem->maRect.SetEmpty();
+ }
+
+ if ( mpScrBar )
+ mpScrBar->Hide();
+ }
+ else
+ {
+ // Frame-Style ermitteln
+ if ( nStyle & WB_DOUBLEBORDER )
+ mnFrameStyle = FRAME_DRAW_DOUBLEIN;
+ else
+ mnFrameStyle = FRAME_DRAW_IN;
+
+ // Selektionsfarben und -breiten ermitteln
+ // Gegebenenfalls die Farben anpassen, damit man die Selektion besser
+ // erkennen kann
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Color aHighColor( rStyleSettings.GetHighlightColor() );
+ if ( ((aHighColor.GetRed() > 0x80) || (aHighColor.GetGreen() > 0x80) ||
+ (aHighColor.GetBlue() > 0x80)) ||
+ ((aHighColor.GetRed() == 0x80) && (aHighColor.GetGreen() == 0x80) &&
+ (aHighColor.GetBlue() == 0x80)) )
+ mbBlackSel = sal_True;
+ else
+ mbBlackSel = sal_False;
+
+ // Wenn die Items groesser sind, dann die Selektion doppelt so breit
+ // zeichnen
+ if ( (nStyle & WB_DOUBLEBORDER) &&
+ ((nItemWidth >= 25) && (nItemHeight >= 20)) )
+ mbDoubleSel = sal_True;
+ else
+ mbDoubleSel = sal_False;
+
+ // Calculate offsets
+ long nStartX;
+ long nStartY;
+ if ( mbFullMode )
+ {
+ long nAllItemWidth = (nItemWidth*mnCols)+nColSpace;
+ long nAllItemHeight = (nItemHeight*mnVisLines)+nNoneHeight+nLineSpace;
+ nStartX = (aWinSize.Width()-nScrBarWidth-nAllItemWidth)/2;
+ nStartY = (aWinSize.Height()-nAllItemHeight)/2;
+ }
+ else
+ {
+ nStartX = 0;
+ nStartY = 0;
+ }
+
+ // Items berechnen und zeichnen
+ maVirDev.SetLineColor();
+ long x = nStartX;
+ long y = nStartY;
+
+ // NoSelection-Field erzeugen und anzeigen
+ if ( nStyle & WB_NONEFIELD )
+ {
+ if ( !mpNoneItem )
+ mpNoneItem = new ValueSetItem( *this );
+
+ mpNoneItem->mnId = 0;
+ mpNoneItem->meType = VALUESETITEM_NONE;
+ mpNoneItem->maRect.Left() = x;
+ mpNoneItem->maRect.Top() = y;
+ mpNoneItem->maRect.Right() = mpNoneItem->maRect.Left()+aWinSize.Width()-x-1;
+ mpNoneItem->maRect.Bottom() = y+nNoneHeight-1;
+
+ ImplFormatItem( mpNoneItem );
+
+ y += nNoneHeight+nNoneSpace;
+ }
+
+ // draw items
+ sal_uLong nFirstItem = mnFirstLine * mnCols;
+ sal_uLong nLastItem = nFirstItem + (mnVisLines * mnCols);
+
+ if ( !mbFullMode )
+ {
+ // If want also draw parts of items in the last line,
+ // then we add one more line if parts of these line are
+ // visible
+ if ( y+(mnVisLines*(nItemHeight+nSpace)) < aWinSize.Height() )
+ nLastItem += mnCols;
+ }
+ for ( sal_uLong i = 0; i < nItemCount; i++ )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( i );
+
+ if ( (i >= nFirstItem) && (i < nLastItem) )
+ {
+ const sal_Bool bWasEmpty = pItem->maRect.IsEmpty();
+
+ pItem->maRect.Left() = x;
+ pItem->maRect.Top() = y;
+ pItem->maRect.Right() = pItem->maRect.Left()+nItemWidth-1;
+ pItem->maRect.Bottom() = pItem->maRect.Top()+nItemHeight-1;
+
+ if( bWasEmpty && ImplHasAccessibleListeners() )
+ {
+ ::com::sun::star::uno::Any aOldAny, aNewAny;
+
+ aNewAny <<= pItem->GetAccessible( mpImpl->mbIsTransientChildrenDisabled );
+ ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
+ }
+
+ ImplFormatItem( pItem );
+
+ if ( !((i+1) % mnCols) )
+ {
+ x = nStartX;
+ y += nItemHeight+nSpace;
+ }
+ else
+ x += nItemWidth+nSpace;
+ }
+ else
+ {
+ if( !pItem->maRect.IsEmpty() && ImplHasAccessibleListeners() )
+ {
+ ::com::sun::star::uno::Any aOldAny, aNewAny;
+
+ aOldAny <<= pItem->GetAccessible( mpImpl->mbIsTransientChildrenDisabled );
+ ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny );
+ }
+
+ pItem->maRect.SetEmpty();
+ }
+ }
+
+ // ScrollBar anordnen, Werte setzen und anzeigen
+ if ( mpScrBar )
+ {
+ Point aPos( aWinSize.Width()-nScrBarWidth+SCRBAR_OFFSET, 0 );
+ Size aSize( nScrBarWidth-SCRBAR_OFFSET, aWinSize.Height() );
+ // If a none field is visible, then we center the scrollbar
+ if ( nStyle & WB_NONEFIELD )
+ {
+ aPos.Y() = nStartY+nNoneHeight+1;
+ aSize.Height() = ((nItemHeight+nSpace)*mnVisLines)-2-nSpace;
+ }
+ mpScrBar->SetPosSizePixel( aPos, aSize );
+ mpScrBar->SetRangeMax( mnLines );
+ mpScrBar->SetVisibleSize( mnVisLines );
+ mpScrBar->SetThumbPos( (long)mnFirstLine );
+ long nPageSize = mnVisLines;
+ if ( nPageSize < 1 )
+ nPageSize = 1;
+ mpScrBar->SetPageSize( nPageSize );
+ mpScrBar->Show();
+ }
+ }
+
+ // Jetzt haben wir formatiert und warten auf das naechste
+ mbFormat = sal_False;
+
+ // ScrollBar loeschen
+ if ( pDelScrBar )
+ delete pDelScrBar;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplDrawItemText( const XubString& rText )
+{
+ if ( !(GetStyle() & WB_NAMEFIELD) )
+ return;
+
+ Size aWinSize = GetOutputSizePixel();
+ long nTxtWidth = GetTextWidth( rText );
+ long nTxtOffset = mnTextOffset;
+
+ // Rechteck loeschen und Text ausgeben
+ if ( GetStyle() & WB_FLATVALUESET )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetLineColor();
+ SetFillColor( rStyleSettings.GetFaceColor() );
+ DrawRect( Rectangle( Point( 0, nTxtOffset ), Point( aWinSize.Width(), aWinSize.Height() ) ) );
+ SetTextColor( rStyleSettings.GetButtonTextColor() );
+ }
+ else
+ {
+ nTxtOffset += NAME_LINE_HEIGHT+NAME_LINE_OFF_Y;
+ Erase( Rectangle( Point( 0, nTxtOffset ), Point( aWinSize.Width(), aWinSize.Height() ) ) );
+ }
+ DrawText( Point( (aWinSize.Width()-nTxtWidth) / 2, nTxtOffset+(NAME_OFFSET/2) ), rText );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplDrawSelect()
+{
+ if ( !IsReallyVisible() )
+ return;
+
+ sal_Bool bFocus = HasFocus();
+ sal_Bool bDrawSel;
+
+ if ( (mbNoSelection && !mbHighlight) || (!mbDrawSelection && mbHighlight) )
+ bDrawSel = sal_False;
+ else
+ bDrawSel = sal_True;
+
+ if ( !bFocus &&
+ ((mbNoSelection && !mbHighlight) || (!mbDrawSelection && mbHighlight)) )
+ {
+ XubString aEmptyStr;
+ ImplDrawItemText( aEmptyStr );
+ return;
+ }
+
+ sal_uInt16 nItemId = mnSelItemId;
+
+ for( int stage = 0; stage < 2; stage++ )
+ {
+ if( stage == 1 )
+ {
+ if ( mbHighlight )
+ nItemId = mnHighItemId;
+ else
+ break;
+ }
+
+ ValueSetItem* pItem;
+ if ( nItemId )
+ pItem = mpImpl->mpItemList->GetObject( GetItemPos( nItemId ) );
+ else
+ {
+ if ( mpNoneItem )
+ pItem = mpNoneItem;
+ else
+ {
+ pItem = ImplGetFirstItem();
+ if ( !bFocus || !pItem )
+ continue;
+ }
+ }
+
+ if ( pItem->maRect.IsEmpty() )
+ continue;
+
+ // Selection malen
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aRect = pItem->maRect;
+ Control::SetFillColor();
+
+ Color aDoubleColor( rStyleSettings.GetHighlightColor() );
+ Color aSingleColor( rStyleSettings.GetHighlightTextColor() );
+ if( ! mbDoubleSel )
+ {
+ /*
+ * #99777# contrast enhancement for thin mode
+ */
+ const Wallpaper& rWall = GetDisplayBackground();
+ if( ! rWall.IsBitmap() && ! rWall.IsGradient() )
+ {
+ const Color& rBack = rWall.GetColor();
+ if( rBack.IsDark() && ! aDoubleColor.IsBright() )
+ {
+ aDoubleColor = Color( COL_WHITE );
+ aSingleColor = Color( COL_BLACK );
+ }
+ else if( rBack.IsBright() && ! aDoubleColor.IsDark() )
+ {
+ aDoubleColor = Color( COL_BLACK );
+ aSingleColor = Color( COL_WHITE );
+ }
+ }
+ }
+
+ // Selectionsausgabe festlegen
+ WinBits nStyle = GetStyle();
+ if ( nStyle & WB_MENUSTYLEVALUESET )
+ {
+ if ( bFocus )
+ ShowFocus( aRect );
+
+ if ( bDrawSel )
+ {
+ if ( mbBlackSel )
+ SetLineColor( Color( COL_BLACK ) );
+ else
+ SetLineColor( aDoubleColor );
+ DrawRect( aRect );
+ }
+ }
+ else if ( nStyle & WB_RADIOSEL )
+ {
+ aRect.Left() += 3;
+ aRect.Top() += 3;
+ aRect.Right() -= 3;
+ aRect.Bottom() -= 3;
+ if ( nStyle & WB_DOUBLEBORDER )
+ {
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ }
+
+ if ( bFocus )
+ ShowFocus( aRect );
+
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+
+ if ( bDrawSel )
+ {
+ SetLineColor( aDoubleColor );
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ DrawRect( aRect );
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ DrawRect( aRect );
+ }
+ }
+ else
+ {
+ if ( bDrawSel )
+ {
+ if ( mbBlackSel )
+ SetLineColor( Color( COL_BLACK ) );
+ else
+ SetLineColor( aDoubleColor );
+ DrawRect( aRect );
+ }
+ if ( mbDoubleSel )
+ {
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ if ( bDrawSel )
+ DrawRect( aRect );
+ }
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ Rectangle aRect2 = aRect;
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ if ( bDrawSel )
+ DrawRect( aRect );
+ if ( mbDoubleSel )
+ {
+ aRect.Left()++;
+ aRect.Top()++;
+ aRect.Right()--;
+ aRect.Bottom()--;
+ if ( bDrawSel )
+ DrawRect( aRect );
+ }
+
+ if ( bDrawSel )
+ {
+ if ( mbBlackSel )
+ SetLineColor( Color( COL_WHITE ) );
+ else
+ SetLineColor( aSingleColor );
+ }
+ else
+ SetLineColor( Color( COL_LIGHTGRAY ) );
+ DrawRect( aRect2 );
+
+ if ( bFocus )
+ ShowFocus( aRect2 );
+ }
+
+ ImplDrawItemText( pItem->maText );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplHideSelect( sal_uInt16 nItemId )
+{
+ Rectangle aRect;
+
+ sal_uInt16 nItemPos = GetItemPos( nItemId );
+ if ( nItemPos != sal::static_int_cast<sal_uInt16>(LIST_ENTRY_NOTFOUND) )
+ aRect = mpImpl->mpItemList->GetObject( nItemPos )->maRect;
+ else
+ {
+ if ( mpNoneItem )
+ aRect = mpNoneItem->maRect;
+ }
+
+ if ( !aRect.IsEmpty() )
+ {
+ HideFocus();
+ Point aPos = aRect.TopLeft();
+ Size aSize = aRect.GetSize();
+ DrawOutDev( aPos, aSize, aPos, aSize, maVirDev );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplHighlightItem( sal_uInt16 nItemId, sal_Bool bIsSelection )
+{
+ if ( mnHighItemId != nItemId )
+ {
+ // Alten merken, um vorherige Selektion zu entfernen
+ sal_uInt16 nOldItem = mnHighItemId;
+ mnHighItemId = nItemId;
+
+ // Wenn keiner selektiert ist, dann Selektion nicht malen
+ if ( !bIsSelection && mbNoSelection )
+ mbDrawSelection = sal_False;
+
+ // Neu ausgeben und alte Selection wegnehmen
+ ImplHideSelect( nOldItem );
+ ImplDrawSelect();
+ mbDrawSelection = sal_True;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplDrawDropPos( sal_Bool bShow )
+{
+ if ( (mnDropPos != VALUESET_ITEM_NOTFOUND) && mpImpl->mpItemList->Count() )
+ {
+ sal_uInt16 nItemPos = mnDropPos;
+ sal_uInt16 nItemId1;
+ sal_uInt16 nItemId2 = 0;
+ sal_Bool bRight;
+ if ( nItemPos >= mpImpl->mpItemList->Count() )
+ {
+ nItemPos = (sal_uInt16)(mpImpl->mpItemList->Count()-1);
+ bRight = sal_True;
+ }
+ else
+ bRight = sal_False;
+
+ nItemId1 = GetItemId( nItemPos );
+ if ( (nItemId1 != mnSelItemId) && (nItemId1 != mnHighItemId) )
+ nItemId1 = 0;
+ Rectangle aRect2 = mpImpl->mpItemList->GetObject( nItemPos )->maRect;
+ Rectangle aRect1;
+ if ( bRight )
+ {
+ aRect1 = aRect2;
+ aRect2.SetEmpty();
+ }
+ else if ( nItemPos > 0 )
+ {
+ aRect1 = mpImpl->mpItemList->GetObject( nItemPos-1 )->maRect;
+ nItemId2 = GetItemId( nItemPos-1 );
+ if ( (nItemId2 != mnSelItemId) && (nItemId2 != mnHighItemId) )
+ nItemId2 = 0;
+ }
+
+ // Items ueberhaupt sichtbar (nur Erstes/Letztes)
+ if ( !aRect1.IsEmpty() || !aRect2.IsEmpty() )
+ {
+ if ( nItemId1 )
+ ImplHideSelect( nItemId1 );
+ if ( nItemId2 )
+ ImplHideSelect( nItemId2 );
+
+ if ( bShow )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ long nX;
+ long nY;
+ SetLineColor( rStyleSettings.GetButtonTextColor() );
+ if ( !aRect1.IsEmpty() )
+ {
+ Point aPos = aRect1.RightCenter();
+ nX = aPos.X()-2;
+ nY = aPos.Y();
+ for ( sal_uInt16 i = 0; i < 4; i++ )
+ DrawLine( Point( nX-i, nY-i ), Point( nX-i, nY+i ) );
+ }
+ if ( !aRect2.IsEmpty() )
+ {
+ Point aPos = aRect2.LeftCenter();
+ nX = aPos.X()+2;
+ nY = aPos.Y();
+ for ( sal_uInt16 i = 0; i < 4; i++ )
+ DrawLine( Point( nX+i, nY-i ), Point( nX+i, nY+i ) );
+ }
+ }
+ else
+ {
+ if ( !aRect1.IsEmpty() )
+ {
+ Point aPos = aRect1.TopLeft();
+ Size aSize = aRect1.GetSize();
+ DrawOutDev( aPos, aSize, aPos, aSize, maVirDev );
+ }
+ if ( !aRect2.IsEmpty() )
+ {
+ Point aPos = aRect2.TopLeft();
+ Size aSize = aRect2.GetSize();
+ DrawOutDev( aPos, aSize, aPos, aSize, maVirDev );
+ }
+ }
+
+ if ( nItemId1 || nItemId2 )
+ ImplDrawSelect();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplDraw()
+{
+ if ( mbFormat )
+ Format();
+
+ HideFocus();
+
+ Point aDefPos;
+ Size aSize = maVirDev.GetOutputSizePixel();
+
+ if ( mpScrBar && mpScrBar->IsVisible() )
+ {
+ Point aScrPos = mpScrBar->GetPosPixel();
+ Size aScrSize = mpScrBar->GetSizePixel();
+ Point aTempPos( 0, aScrPos.Y() );
+ Size aTempSize( aSize.Width(), aScrPos.Y() );
+
+ DrawOutDev( aDefPos, aTempSize, aDefPos, aTempSize, maVirDev );
+ aTempSize.Width() = aScrPos.X()-1;
+ aTempSize.Height() = aScrSize.Height();
+ DrawOutDev( aTempPos, aTempSize, aTempPos, aTempSize, maVirDev );
+ aTempPos.Y() = aScrPos.Y()+aScrSize.Height();
+ aTempSize.Width() = aSize.Width();
+ aTempSize.Height() = aSize.Height()-aTempPos.Y();
+ DrawOutDev( aTempPos, aTempSize, aTempPos, aTempSize, maVirDev );
+ }
+ else
+ DrawOutDev( aDefPos, aSize, aDefPos, aSize, maVirDev );
+
+ // Trennlinie zum Namefield zeichnen
+ if ( GetStyle() & WB_NAMEFIELD )
+ {
+ if ( !(GetStyle() & WB_FLATVALUESET) )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Size aWinSize = GetOutputSizePixel();
+ Point aPos1( NAME_LINE_OFF_X, mnTextOffset+NAME_LINE_OFF_Y );
+ Point aPos2( aWinSize.Width()-(NAME_LINE_OFF_X*2), mnTextOffset+NAME_LINE_OFF_Y );
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
+ {
+ SetLineColor( rStyleSettings.GetShadowColor() );
+ DrawLine( aPos1, aPos2 );
+ aPos1.Y()++;
+ aPos2.Y()++;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ }
+ else
+ SetLineColor( rStyleSettings.GetWindowTextColor() );
+ DrawLine( aPos1, aPos2 );
+ }
+ }
+
+ ImplDrawSelect();
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ValueSet::ImplScroll( const Point& rPos )
+{
+ Size aOutSize = GetOutputSizePixel();
+ long nScrBarWidth;
+
+ if ( mpScrBar )
+ nScrBarWidth = mpScrBar->GetSizePixel().Width();
+ else
+ nScrBarWidth = 0;
+
+ if ( !mbScroll || (rPos.X() < 0) || (rPos.X() > aOutSize.Width()-nScrBarWidth) )
+ return sal_False;
+
+ long nScrollOffset;
+ sal_uInt16 nOldLine = mnFirstLine;
+ const Rectangle& rTopRect = mpImpl->mpItemList->GetObject( mnFirstLine*mnCols )->maRect;
+ if ( rTopRect.GetHeight() <= 16 )
+ nScrollOffset = VALUESET_SCROLL_OFFSET/2;
+ else
+ nScrollOffset = VALUESET_SCROLL_OFFSET;
+ if ( (mnFirstLine > 0) && (rPos.Y() >= 0) )
+ {
+ long nTopPos = rTopRect.Top();
+ if ( (rPos.Y() >= nTopPos) && (rPos.Y() <= nTopPos+nScrollOffset) )
+ mnFirstLine--;
+ }
+ if ( (mnFirstLine == nOldLine) &&
+ (mnFirstLine < (sal_uInt16)(mnLines-mnVisLines)) && (rPos.Y() < aOutSize.Height()) )
+ {
+ long nBottomPos = mpImpl->mpItemList->GetObject( (mnFirstLine+mnVisLines-1)*mnCols )->maRect.Bottom();
+ if ( (rPos.Y() >= nBottomPos-nScrollOffset) && (rPos.Y() <= nBottomPos) )
+ mnFirstLine++;
+ }
+
+ if ( mnFirstLine != nOldLine )
+ {
+ mbFormat = sal_True;
+ ImplDraw();
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::ImplGetItem( const Point& rPos, sal_Bool bMove ) const
+{
+ if ( mpNoneItem )
+ {
+ if ( mpNoneItem->maRect.IsInside( rPos ) )
+ return VALUESET_ITEM_NONEITEM;
+ }
+
+ Point aDefPos;
+ Rectangle aWinRect( aDefPos, maVirDev.GetOutputSizePixel() );
+
+ sal_uLong nItemCount = mpImpl->mpItemList->Count();
+ for ( sal_uLong i = 0; i < nItemCount; i++ )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( i );
+ if ( pItem->maRect.IsInside( rPos ) )
+ {
+ if ( aWinRect.IsInside( rPos ) )
+ return (sal_uInt16)i;
+ else
+ return VALUESET_ITEM_NOTFOUND;
+ }
+ }
+
+ // Wenn Spacing gesetzt ist, wird der vorher selektierte
+ // Eintrag zurueckgegeben, wenn die Maus noch nicht das Fenster
+ // verlassen hat
+ if ( bMove && mnSpacing && mnHighItemId )
+ {
+ if ( aWinRect.IsInside( rPos ) )
+ return GetItemPos( mnHighItemId );
+ }
+
+ return VALUESET_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+ValueSetItem* ValueSet::ImplGetItem( sal_uInt16 nPos )
+{
+ if ( nPos == VALUESET_ITEM_NONEITEM )
+ return mpNoneItem;
+ else
+ return mpImpl->mpItemList->GetObject( nPos );
+}
+
+// -----------------------------------------------------------------------
+
+ValueSetItem* ValueSet::ImplGetFirstItem()
+{
+ sal_uInt16 nItemCount = (sal_uInt16)mpImpl->mpItemList->Count();
+ sal_uInt16 i = 0;
+
+ while ( i < nItemCount )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( i );
+ if ( pItem->meType != VALUESETITEM_SPACE )
+ return pItem;
+ i++;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::ImplGetVisibleItemCount() const
+{
+ sal_uInt16 nRet = 0;
+
+ for( sal_Int32 n = 0, nItemCount = mpImpl->mpItemList->Count(); n < nItemCount; n++ )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( n );
+
+ if( pItem->meType != VALUESETITEM_SPACE && !pItem->maRect.IsEmpty() )
+ nRet++;
+ }
+
+ return nRet;
+}
+
+// -----------------------------------------------------------------------
+
+ValueSetItem* ValueSet::ImplGetVisibleItem( sal_uInt16 nVisiblePos )
+{
+ ValueSetItem* pRet = NULL;
+ sal_uInt16 nFoundPos = 0;
+
+ for( sal_Int32 n = 0, nItemCount = mpImpl->mpItemList->Count(); ( n < nItemCount ) && !pRet; n++ )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( n );
+
+ if( ( pItem->meType != VALUESETITEM_SPACE ) && !pItem->maRect.IsEmpty() && ( nVisiblePos == nFoundPos++ ) )
+ pRet = pItem;
+ }
+
+ return pRet;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplFireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue )
+{
+ ValueSetAcc* pAcc = ValueSetAcc::getImplementation( GetAccessible( sal_False ) );
+
+ if( pAcc )
+ pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ValueSet::ImplHasAccessibleListeners()
+{
+ ValueSetAcc* pAcc = ValueSetAcc::getImplementation( GetAccessible( sal_False ) );
+ return( pAcc && pAcc->HasAccessibleListeners() );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ValueSet,ImplScrollHdl, ScrollBar*, pScrollBar )
+{
+ sal_uInt16 nNewFirstLine = (sal_uInt16)pScrollBar->GetThumbPos();
+ if ( nNewFirstLine != mnFirstLine )
+ {
+ mnFirstLine = nNewFirstLine;
+ mbFormat = sal_True;
+ ImplDraw();
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ValueSet,ImplTimerHdl, Timer*, EMPTYARG )
+{
+ ImplTracking( GetPointerPosPixel(), sal_True );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplTracking( const Point& rPos, sal_Bool bRepeat )
+{
+ if ( bRepeat || mbSelection )
+ {
+ if ( ImplScroll( rPos ) )
+ {
+ if ( mbSelection )
+ {
+ maTimer.SetTimeoutHdl( LINK( this, ValueSet, ImplTimerHdl ) );
+ maTimer.SetTimeout( GetSettings().GetMouseSettings().GetScrollRepeat() );
+ maTimer.Start();
+ }
+ }
+ }
+
+ ValueSetItem* pItem = ImplGetItem( ImplGetItem( rPos ) );
+ if ( pItem && (pItem->meType != VALUESETITEM_SPACE) )
+ {
+ if( GetStyle() & WB_MENUSTYLEVALUESET )
+ mbHighlight = sal_True;
+
+ ImplHighlightItem( pItem->mnId );
+ }
+ else
+ {
+ if( GetStyle() & WB_MENUSTYLEVALUESET )
+ mbHighlight = sal_True;
+
+ ImplHighlightItem( mnSelItemId, sal_False );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplEndTracking( const Point& rPos, sal_Bool bCancel )
+{
+ ValueSetItem* pItem;
+
+ // Bei Abbruch, den alten Status wieder herstellen
+ if ( bCancel )
+ pItem = NULL;
+ else
+ pItem = ImplGetItem( ImplGetItem( rPos ) );
+
+ if ( pItem && (pItem->meType != VALUESETITEM_SPACE) )
+ {
+ SelectItem( pItem->mnId );
+ if ( !mbSelection && !(GetStyle() & WB_NOPOINTERFOCUS) )
+ GrabFocus();
+ mbHighlight = sal_False;
+ mbSelection = sal_False;
+ Select();
+ }
+ else
+ {
+ ImplHighlightItem( mnSelItemId, sal_False );
+ mbHighlight = sal_False;
+ mbSelection = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ {
+ ValueSetItem* pItem = ImplGetItem( ImplGetItem( rMEvt.GetPosPixel() ) );
+ if ( mbSelection )
+ {
+ mbHighlight = sal_True;
+ if ( pItem && (pItem->meType != VALUESETITEM_SPACE) )
+ {
+ mnOldItemId = mnSelItemId;
+ mnHighItemId = mnSelItemId;
+ ImplHighlightItem( pItem->mnId );
+ }
+
+ return;
+ }
+ else
+ {
+ if ( pItem && (pItem->meType != VALUESETITEM_SPACE) && !rMEvt.IsMod2() )
+ {
+ if ( (pItem->mnBits & VIB_NODOUBLECLICK) || (rMEvt.GetClicks() == 1) )
+ {
+ mnOldItemId = mnSelItemId;
+ mbHighlight = sal_True;
+ mnHighItemId = mnSelItemId;
+ ImplHighlightItem( pItem->mnId );
+ StartTracking( STARTTRACK_SCROLLREPEAT );
+ }
+ else if ( rMEvt.GetClicks() == 2 )
+ DoubleClick();
+
+ return;
+ }
+ }
+ }
+
+ Control::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ // Wegen SelectionMode
+ if ( rMEvt.IsLeft() && mbSelection )
+ ImplEndTracking( rMEvt.GetPosPixel(), sal_False );
+ else
+ Control::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::MouseMove( const MouseEvent& rMEvt )
+{
+ // Wegen SelectionMode
+ if ( mbSelection || (GetStyle() & WB_MENUSTYLEVALUESET) )
+ ImplTracking( rMEvt.GetPosPixel(), sal_False );
+ Control::MouseMove( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Tracking( const TrackingEvent& rTEvt )
+{
+ Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel();
+
+ if ( rTEvt.IsTrackingEnded() )
+ ImplEndTracking( aMousePos, rTEvt.IsTrackingCanceled() );
+ else
+ ImplTracking( aMousePos, rTEvt.IsTrackingRepeat() );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::KeyInput( const KeyEvent& rKEvt )
+{
+ sal_uInt16 nLastItem = (sal_uInt16)mpImpl->mpItemList->Count();
+ sal_uInt16 nItemPos = VALUESET_ITEM_NOTFOUND;
+ sal_uInt16 nCurPos = VALUESET_ITEM_NONEITEM;
+ sal_uInt16 nCalcPos;
+
+ if ( !nLastItem || !ImplGetFirstItem() )
+ {
+ Control::KeyInput( rKEvt );
+ return;
+ }
+ else
+ nLastItem--;
+
+ if ( mnSelItemId )
+ nCurPos = GetItemPos( mnSelItemId );
+ nCalcPos = nCurPos;
+
+ //switch off selection mode if key travelling is used
+ sal_Bool bDefault = sal_False;
+ switch ( rKEvt.GetKeyCode().GetCode() )
+ {
+ case KEY_HOME:
+ if ( mpNoneItem )
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ else
+ {
+ nItemPos = 0;
+ while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE )
+ nItemPos++;
+ }
+ break;
+
+ case KEY_END:
+ nItemPos = nLastItem;
+ while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE )
+ {
+ if ( nItemPos == 0 )
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ else
+ nItemPos--;
+ }
+ break;
+
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ if ( rKEvt.GetKeyCode().GetCode()==KEY_LEFT )
+ {
+ do
+ {
+ if ( nCalcPos == VALUESET_ITEM_NONEITEM )
+ nItemPos = nLastItem;
+ else if ( !nCalcPos )
+ {
+ if ( mpNoneItem )
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ else
+ nItemPos = nLastItem;
+ }
+ else
+ nItemPos = nCalcPos-1;
+ nCalcPos = nItemPos;
+ }
+ while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE );
+ }
+ else
+ {
+ do
+ {
+ if ( nCalcPos == VALUESET_ITEM_NONEITEM )
+ nItemPos = 0;
+ else if ( nCalcPos == nLastItem )
+ {
+ if ( mpNoneItem )
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ else
+ nItemPos = 0;
+ }
+ else
+ nItemPos = nCalcPos+1;
+ nCalcPos = nItemPos;
+ }
+ while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE );
+ }
+ break;
+
+ case KEY_UP:
+ case KEY_PAGEUP:
+ {
+ if( rKEvt.GetKeyCode().GetCode() != KEY_PAGEUP ||
+ ( !rKEvt.GetKeyCode().IsShift() && !rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() ) )
+ {
+ const long nLineCount = ( ( KEY_UP == rKEvt.GetKeyCode().GetCode() ) ? 1 : mnVisLines );
+ do
+ {
+ if ( nCalcPos == VALUESET_ITEM_NONEITEM )
+ {
+ if ( nLastItem+1 <= mnCols )
+ nItemPos = mnCurCol;
+ else
+ {
+ nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+(mnCurCol%mnCols);
+ if ( nItemPos+mnCols <= nLastItem )
+ nItemPos = nItemPos + mnCols;
+ }
+ }
+ else if ( nCalcPos >= ( nLineCount * mnCols ) )
+ nItemPos = sal::static_int_cast< sal_uInt16 >(
+ nCalcPos - ( nLineCount * mnCols ));
+ else
+ {
+ if ( mpNoneItem )
+ {
+ mnCurCol = nCalcPos%mnCols;
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ }
+ else
+ {
+ if ( nLastItem+1 <= mnCols )
+ nItemPos = nCalcPos;
+ else
+ {
+ nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+(nCalcPos%mnCols);
+ if ( nItemPos+mnCols <= nLastItem )
+ nItemPos = nItemPos + mnCols;
+ }
+ }
+ }
+ nCalcPos = nItemPos;
+ }
+ while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE );
+ }
+ else
+ Control::KeyInput( rKEvt );
+ }
+ break;
+
+ case KEY_DOWN:
+ case KEY_PAGEDOWN:
+ {
+ if( rKEvt.GetKeyCode().GetCode() != KEY_PAGEDOWN ||
+ ( !rKEvt.GetKeyCode().IsShift() && !rKEvt.GetKeyCode().IsMod1() && !rKEvt.GetKeyCode().IsMod2() ) )
+ {
+ const long nLineCount = ( ( KEY_DOWN == rKEvt.GetKeyCode().GetCode() ) ? 1 : mnVisLines );
+ do
+ {
+ if ( nCalcPos == VALUESET_ITEM_NONEITEM )
+ nItemPos = mnCurCol;
+ else if ( nCalcPos + ( nLineCount * mnCols ) <= nLastItem )
+ nItemPos = sal::static_int_cast< sal_uInt16 >(
+ nCalcPos + ( nLineCount * mnCols ));
+ else
+ {
+#if 0
+ if( (KEY_DOWN == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) )
+ {
+ Window* pParent = GetParent();
+ pParent->GrabFocus();
+ pParent->KeyInput( rKEvt );
+ break;
+ }
+ else
+#endif
+ {
+ if ( mpNoneItem )
+ {
+ mnCurCol = nCalcPos%mnCols;
+ nItemPos = VALUESET_ITEM_NONEITEM;
+ }
+ else
+ nItemPos = nCalcPos%mnCols;
+ }
+ }
+ nCalcPos = nItemPos;
+ }
+ while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE );
+ }
+ else
+ Control::KeyInput( rKEvt );
+
+ }
+ break;
+ case KEY_RETURN:
+ //enable default handling of KEY_RETURN in dialogs
+ if(0 != (GetStyle()&WB_NO_DIRECTSELECT))
+ {
+ Select();
+ break;
+ }
+ //no break;
+ default:
+ Control::KeyInput( rKEvt );
+ bDefault = sal_True;
+ break;
+ }
+ if(!bDefault)
+ EndSelection();
+ if ( nItemPos != VALUESET_ITEM_NOTFOUND )
+ {
+ sal_uInt16 nItemId;
+ if ( nItemPos != VALUESET_ITEM_NONEITEM )
+ nItemId = GetItemId( nItemPos );
+ else
+ nItemId = 0;
+
+ if ( nItemId != mnSelItemId )
+ {
+ SelectItem( nItemId );
+ //select only if WB_NO_DIRECTSELECT is not set
+ if(0 == (GetStyle()&WB_NO_DIRECTSELECT))
+ Select();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Command( const CommandEvent& rCEvt )
+{
+ if ( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
+ (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
+ (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
+ {
+ if ( HandleScrollCommand( rCEvt, NULL, mpScrBar ) )
+ return;
+ }
+
+ Control::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Paint( const Rectangle& )
+{
+ if ( GetStyle() & WB_FLATVALUESET )
+ {
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ SetLineColor();
+ SetFillColor( rStyleSettings.GetFaceColor() );
+ long nOffY = maVirDev.GetOutputSizePixel().Height();
+ Size aWinSize = GetOutputSizePixel();
+ DrawRect( Rectangle( Point( 0, nOffY ), Point( aWinSize.Width(), aWinSize.Height() ) ) );
+ }
+
+ ImplDraw();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::GetFocus()
+{
+ OSL_TRACE ("value set getting focus");
+ ImplDrawSelect();
+ Control::GetFocus();
+
+ // Tell the accessible object that we got the focus.
+ ValueSetAcc* pAcc = ValueSetAcc::getImplementation( GetAccessible( sal_False ) );
+ if( pAcc )
+ pAcc->GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::LoseFocus()
+{
+ OSL_TRACE ("value set losing focus");
+ if ( mbNoSelection && mnSelItemId )
+ ImplHideSelect( mnSelItemId );
+ else
+ HideFocus();
+ Control::LoseFocus();
+
+ // Tell the accessible object that we lost the focus.
+ ValueSetAcc* pAcc = ValueSetAcc::getImplementation( GetAccessible( sal_False ) );
+ if( pAcc )
+ pAcc->LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Resize()
+{
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ Control::Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::RequestHelp( const HelpEvent& rHEvt )
+{
+ if ( (rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON)) == HELPMODE_QUICK )
+ {
+ Point aPos = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
+ sal_uInt16 nItemPos = ImplGetItem( aPos );
+ if ( nItemPos != VALUESET_ITEM_NOTFOUND )
+ {
+ ValueSetItem* pItem = ImplGetItem( nItemPos );
+ Rectangle aItemRect = pItem->maRect;
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+ Help::ShowQuickHelp( this, aItemRect, GetItemText( pItem->mnId ) );
+ return;
+ }
+ }
+
+ Control::RequestHelp( rHEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::StateChanged( StateChangedType nType )
+{
+ Control::StateChanged( nType );
+
+ if ( nType == STATE_CHANGE_INITSHOW )
+ {
+ if ( mbFormat )
+ Format();
+ }
+ else if ( nType == STATE_CHANGE_UPDATEMODE )
+ {
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_TEXT )
+ {
+ if ( mpNoneItem && !mbFormat && IsReallyVisible() && IsUpdateMode() )
+ {
+ ImplFormatItem( mpNoneItem );
+ Invalidate( mpNoneItem->maRect );
+ }
+ }
+ else if ( (nType == STATE_CHANGE_ZOOM) ||
+ (nType == STATE_CHANGE_CONTROLFONT) )
+ {
+ ImplInitSettings( sal_True, sal_False, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( sal_False, sal_True, sal_False );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( sal_False, sal_False, sal_True );
+ Invalidate();
+ }
+ else if ( (nType == STATE_CHANGE_STYLE) || (nType == STATE_CHANGE_ENABLE) )
+ {
+ mbFormat = sal_True;
+ ImplInitSettings( sal_False, sal_False, sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ Control::DataChanged( rDCEvt );
+
+ if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
+ (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
+ (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
+ ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
+ {
+ mbFormat = sal_True;
+ ImplInitSettings( sal_True, sal_True, sal_True );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( sal_uInt16 nItemId, const Image& rImage, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "ValueSet::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == VALUESET_ITEM_NOTFOUND,
+ "ValueSet::InsertItem(): ItemId already exists" );
+
+ ValueSetItem* pItem = new ValueSetItem( *this );
+ pItem->mnId = nItemId;
+ pItem->meType = VALUESETITEM_IMAGE;
+ pItem->maImage = rImage;
+ mpImpl->mpItemList->Insert( pItem, (sal_uLong)nPos );
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( sal_uInt16 nItemId, const Color& rColor, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "ValueSet::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == VALUESET_ITEM_NOTFOUND,
+ "ValueSet::InsertItem(): ItemId already exists" );
+
+ ValueSetItem* pItem = new ValueSetItem( *this );
+ pItem->mnId = nItemId;
+ pItem->meType = VALUESETITEM_COLOR;
+ pItem->maColor = rColor;
+ mpImpl->mpItemList->Insert( pItem, (sal_uLong)nPos );
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( sal_uInt16 nItemId, const Image& rImage,
+ const XubString& rText, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "ValueSet::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == VALUESET_ITEM_NOTFOUND,
+ "ValueSet::InsertItem(): ItemId already exists" );
+
+ ValueSetItem* pItem = new ValueSetItem( *this );
+ pItem->mnId = nItemId;
+ pItem->meType = VALUESETITEM_IMAGE;
+ pItem->maImage = rImage;
+ pItem->maText = rText;
+ mpImpl->mpItemList->Insert( pItem, (sal_uLong)nPos );
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( sal_uInt16 nItemId, const Color& rColor,
+ const XubString& rText, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "ValueSet::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == VALUESET_ITEM_NOTFOUND,
+ "ValueSet::InsertItem(): ItemId already exists" );
+
+ ValueSetItem* pItem = new ValueSetItem( *this );
+ pItem->mnId = nItemId;
+ pItem->meType = VALUESETITEM_COLOR;
+ pItem->maColor = rColor;
+ pItem->maText = rText;
+ mpImpl->mpItemList->Insert( pItem, (sal_uLong)nPos );
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( sal_uInt16 nItemId, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "ValueSet::InsertItem(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == VALUESET_ITEM_NOTFOUND,
+ "ValueSet::InsertItem(): ItemId already exists" );
+
+ ValueSetItem* pItem = new ValueSetItem( *this );
+ pItem->mnId = nItemId;
+ pItem->meType = VALUESETITEM_USERDRAW;
+ mpImpl->mpItemList->Insert( pItem, (sal_uLong)nPos );
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertSpace( sal_uInt16 nItemId, sal_uInt16 nPos )
+{
+ DBG_ASSERT( nItemId, "ValueSet::InsertSpace(): ItemId == 0" );
+ DBG_ASSERT( GetItemPos( nItemId ) == VALUESET_ITEM_NOTFOUND,
+ "ValueSet::InsertSpace(): ItemId already exists" );
+
+ ValueSetItem* pItem = new ValueSetItem( *this );
+ pItem->mnId = nItemId;
+ pItem->meType = VALUESETITEM_SPACE;
+ mpImpl->mpItemList->Insert( pItem, (sal_uLong)nPos );
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::RemoveItem( sal_uInt16 nItemId )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos == VALUESET_ITEM_NOTFOUND )
+ return;
+
+ delete mpImpl->mpItemList->Remove( nPos );
+
+ // Variablen zuruecksetzen
+ if ( (mnHighItemId == nItemId) || (mnSelItemId == nItemId) )
+ {
+ mnCurCol = 0;
+ mnOldItemId = 0;
+ mnHighItemId = 0;
+ mnSelItemId = 0;
+ mbNoSelection = sal_True;
+ }
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::CopyItems( const ValueSet& rValueSet )
+{
+ ImplDeleteItems();
+
+ ValueSetItem* pItem = rValueSet.mpImpl->mpItemList->First();
+ while ( pItem )
+ {
+ ValueSetItem* pNewItem = new ValueSetItem( *this );
+
+ pNewItem->mnId = pItem->mnId;
+ pNewItem->mnBits = pItem->mnBits;
+ pNewItem->meType = pItem->meType;
+ pNewItem->maImage = pItem->maImage;
+ pNewItem->maColor = pItem->maColor;
+ pNewItem->maText = pItem->maText;
+ pNewItem->mpData = pItem->mpData;
+ pNewItem->maRect = pItem->maRect;
+ pNewItem->mpxAcc = NULL;
+
+ mpImpl->mpItemList->Insert( pNewItem );
+ pItem = rValueSet.mpImpl->mpItemList->Next();
+ }
+
+ // Variablen zuruecksetzen
+ mnFirstLine = 0;
+ mnCurCol = 0;
+ mnOldItemId = 0;
+ mnHighItemId = 0;
+ mnSelItemId = 0;
+ mbNoSelection = sal_True;
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Clear()
+{
+ ImplDeleteItems();
+
+ // Variablen zuruecksetzen
+ mnFirstLine = 0;
+ mnCurCol = 0;
+ mnOldItemId = 0;
+ mnHighItemId = 0;
+ mnSelItemId = 0;
+ mbNoSelection = sal_True;
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::GetItemCount() const
+{
+ return (sal_uInt16)mpImpl->mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::GetItemPos( sal_uInt16 nItemId ) const
+{
+ ValueSetItem* pItem = mpImpl->mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return (sal_uInt16)mpImpl->mpItemList->GetCurPos();
+ pItem = mpImpl->mpItemList->Next();
+ }
+
+ return VALUESET_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::GetItemId( sal_uInt16 nPos ) const
+{
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( nPos );
+
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::GetItemId( const Point& rPos ) const
+{
+ sal_uInt16 nItemPos = ImplGetItem( rPos );
+ if ( nItemPos != VALUESET_ITEM_NOTFOUND )
+ return GetItemId( nItemPos );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ValueSet::GetItemRect( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->maRect;
+ else
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::EnableFullItemMode( sal_Bool bFullMode )
+{
+ mbFullMode = bFullMode;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetColCount( sal_uInt16 nNewCols )
+{
+ if ( mnUserCols != nNewCols )
+ {
+ mnUserCols = nNewCols;
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetLineCount( sal_uInt16 nNewLines )
+{
+ if ( mnUserVisLines != nNewLines )
+ {
+ mnUserVisLines = nNewLines;
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemWidth( long nNewItemWidth )
+{
+ if ( mnUserItemWidth != nNewItemWidth )
+ {
+ mnUserItemWidth = nNewItemWidth;
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemHeight( long nNewItemHeight )
+{
+ if ( mnUserItemHeight != nNewItemHeight )
+ {
+ mnUserItemHeight = nNewItemHeight;
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetFirstLine( sal_uInt16 nNewLine )
+{
+ if ( mnFirstLine != nNewLine )
+ {
+ mnFirstLine = nNewLine;
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SelectItem( sal_uInt16 nItemId )
+{
+ sal_uInt16 nItemPos = 0;
+
+ if ( nItemId )
+ {
+ nItemPos = GetItemPos( nItemId );
+ if ( nItemPos == VALUESET_ITEM_NOTFOUND )
+ return;
+ if ( mpImpl->mpItemList->GetObject( nItemPos )->meType == VALUESETITEM_SPACE )
+ return;
+ }
+
+ if ( (mnSelItemId != nItemId) || mbNoSelection )
+ {
+ sal_uInt16 nOldItem = mnSelItemId ? mnSelItemId : 1;
+ mnSelItemId = nItemId;
+ mbNoSelection = sal_False;
+
+ sal_Bool bNewOut;
+ sal_Bool bNewLine;
+ if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
+ bNewOut = sal_True;
+ else
+ bNewOut = sal_False;
+ bNewLine = sal_False;
+
+ // Gegebenenfalls in den sichtbaren Bereich scrollen
+ if ( mbScroll && nItemId )
+ {
+ sal_uInt16 nNewLine = (sal_uInt16)(nItemPos / mnCols);
+ if ( nNewLine < mnFirstLine )
+ {
+ mnFirstLine = nNewLine;
+ bNewLine = sal_True;
+ }
+ else if ( nNewLine > (sal_uInt16)(mnFirstLine+mnVisLines-1) )
+ {
+ mnFirstLine = (sal_uInt16)(nNewLine-mnVisLines+1);
+ bNewLine = sal_True;
+ }
+ }
+
+ if ( bNewOut )
+ {
+ if ( bNewLine )
+ {
+ // Falls sich der sichtbare Bereich geaendert hat,
+ // alles neu ausgeben
+ mbFormat = sal_True;
+ ImplDraw();
+ }
+ else
+ {
+ // alte Selection wegnehmen und neue ausgeben
+ ImplHideSelect( nOldItem );
+ ImplDrawSelect();
+ }
+ }
+
+ if( ImplHasAccessibleListeners() )
+ {
+ // focus event (deselect)
+ if( nOldItem )
+ {
+ const sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if( nPos != VALUESET_ITEM_NOTFOUND )
+ {
+ ValueItemAcc* pItemAcc = ValueItemAcc::getImplementation(
+ mpImpl->mpItemList->GetObject( nPos )->GetAccessible( mpImpl->mbIsTransientChildrenDisabled ) );
+
+ if( pItemAcc )
+ {
+ ::com::sun::star::uno::Any aOldAny, aNewAny;
+ if( !mpImpl->mbIsTransientChildrenDisabled)
+ {
+ aOldAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >(
+ static_cast< ::cppu::OWeakObject* >( pItemAcc ));
+ ImplFireAccessibleEvent (::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny );
+ }
+ else
+ {
+ aOldAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
+ pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
+ }
+ }
+ }
+ }
+
+ // focus event (select)
+ const sal_uInt16 nPos = GetItemPos( mnSelItemId );
+
+ ValueSetItem* pItem;
+ if( nPos != VALUESET_ITEM_NOTFOUND )
+ pItem = mpImpl->mpItemList->GetObject(nPos);
+ else
+ pItem = mpNoneItem;
+
+ ValueItemAcc* pItemAcc = NULL;
+ if (pItem != NULL)
+ pItemAcc = ValueItemAcc::getImplementation(pItem->GetAccessible( mpImpl->mbIsTransientChildrenDisabled ) );
+
+ if( pItemAcc )
+ {
+ ::com::sun::star::uno::Any aOldAny, aNewAny;
+ if( !mpImpl->mbIsTransientChildrenDisabled)
+ {
+ aNewAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >(
+ static_cast< ::cppu::OWeakObject* >( pItemAcc ));
+ ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny );
+ }
+ else
+ {
+ aNewAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
+ pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny );
+ }
+ }
+
+ // selection event
+ ::com::sun::star::uno::Any aOldAny, aNewAny;
+ ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny );
+ }
+ mpImpl->maHighlightHdl.Call(this);
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetNoSelection()
+{
+ mbNoSelection = sal_True;
+ mbHighlight = sal_False;
+ mbSelection = sal_False;
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplDraw();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemBits( sal_uInt16 nItemId, sal_uInt16 nItemBits )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ mpImpl->mpItemList->GetObject( nPos )->mnBits = nItemBits;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::GetItemBits( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemImage( sal_uInt16 nItemId, const Image& rImage )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos == VALUESET_ITEM_NOTFOUND )
+ return;
+
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( nPos );
+ pItem->meType = VALUESETITEM_IMAGE;
+ pItem->maImage = rImage;
+
+ if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
+ {
+ ImplFormatItem( pItem );
+ Invalidate( pItem->maRect );
+ }
+ else
+ mbFormat = sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+Image ValueSet::GetItemImage( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->maImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemColor( sal_uInt16 nItemId, const Color& rColor )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos == VALUESET_ITEM_NOTFOUND )
+ return;
+
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( nPos );
+ pItem->meType = VALUESETITEM_COLOR;
+ pItem->maColor = rColor;
+
+ if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
+ {
+ ImplFormatItem( pItem );
+ Invalidate( pItem->maRect );
+ }
+ else
+ mbFormat = sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+Color ValueSet::GetItemColor( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->maColor;
+ else
+ return Color();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemData( sal_uInt16 nItemId, void* pData )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos == VALUESET_ITEM_NOTFOUND )
+ return;
+
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( nPos );
+ pItem->mpData = pData;
+
+ if ( pItem->meType == VALUESETITEM_USERDRAW )
+ {
+ if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
+ {
+ ImplFormatItem( pItem );
+ Invalidate( pItem->maRect );
+ }
+ else
+ mbFormat = sal_True;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* ValueSet::GetItemData( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->mpData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemText( sal_uInt16 nItemId, const XubString& rText )
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos == VALUESET_ITEM_NOTFOUND )
+ return;
+
+
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( nPos );
+
+ // Remember old and new name for accessibility event.
+ ::com::sun::star::uno::Any aOldName, aNewName;
+ ::rtl::OUString sString (pItem->maText);
+ aOldName <<= sString;
+ sString = rText;
+ aNewName <<= sString;
+
+ pItem->maText = rText;
+
+ if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
+ {
+ sal_uInt16 nTempId = mnSelItemId;
+
+ if ( mbHighlight )
+ nTempId = mnHighItemId;
+
+ if ( nTempId == nItemId )
+ ImplDrawItemText( pItem->maText );
+ }
+
+ if (ImplHasAccessibleListeners())
+ {
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::accessibility::XAccessible> xAccessible (
+ pItem->GetAccessible( mpImpl->mbIsTransientChildrenDisabled ) );
+ static_cast<ValueItemAcc*>(xAccessible.get())->FireAccessibleEvent (
+ ::com::sun::star::accessibility::AccessibleEventId::NAME_CHANGED,
+ aOldName, aNewName);
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString ValueSet::GetItemText( sal_uInt16 nItemId ) const
+{
+ sal_uInt16 nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->maText;
+ else
+ return XubString();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetColor( const Color& rColor )
+{
+ maColor = rColor;
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplDraw();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetExtraSpacing( sal_uInt16 nNewSpacing )
+{
+ if ( GetStyle() & WB_ITEMBORDER )
+ {
+ mnSpacing = nNewSpacing;
+
+ mbFormat = sal_True;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::StartSelection()
+{
+ mnOldItemId = mnSelItemId;
+ mbHighlight = sal_True;
+ mbSelection = sal_True;
+ mnHighItemId = mnSelItemId;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::EndSelection()
+{
+ if ( mbHighlight )
+ {
+ if ( IsTracking() )
+ EndTracking( ENDTRACK_CANCEL );
+
+ ImplHighlightItem( mnSelItemId );
+ mbHighlight = sal_False;
+ }
+ mbSelection = sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool ValueSet::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
+{
+ if ( rCEvt.GetCommand() != COMMAND_STARTDRAG )
+ return sal_False;
+
+ // Gegebenenfalls eine vorhandene Aktion abbrechen
+ EndSelection();
+
+ // Testen, ob angeklickte Seite selektiert ist. Falls dies nicht
+ // der Fall ist, setzen wir ihn als aktuellen Eintrag. Falls Drag and
+ // Drop auch mal ueber Tastatur ausgeloest werden kann, testen wir
+ // dies nur bei einer Mausaktion.
+ sal_uInt16 nSelId;
+ if ( rCEvt.IsMouseEvent() )
+ nSelId = GetItemId( rCEvt.GetMousePosPixel() );
+ else
+ nSelId = mnSelItemId;
+
+ // Falls kein Eintrag angeklickt wurde, starten wir kein Dragging
+ if ( !nSelId )
+ return sal_False;
+
+ // Testen, ob Seite selektiertiert ist. Falls nicht, als aktuelle
+ // Seite setzen und Select rufen.
+ if ( nSelId != mnSelItemId )
+ {
+ SelectItem( nSelId );
+ Update();
+ Select();
+ }
+
+ Region aRegion;
+
+ // Region zuweisen
+ rRegion = aRegion;
+
+ return sal_True;
+}
+
+// -----------------------------------------------------------------------
+
+Size ValueSet::CalcWindowSizePixel( const Size& rItemSize, sal_uInt16 nDesireCols,
+ sal_uInt16 nDesireLines )
+{
+ long nCalcCols = (long)nDesireCols;
+ long nCalcLines = (long)nDesireLines;
+
+ if ( !nCalcCols )
+ {
+ if ( mnUserCols )
+ nCalcCols = (long)mnUserCols;
+ else
+ nCalcCols = 1;
+ }
+
+ if ( !nCalcLines )
+ {
+ nCalcLines = mnVisLines;
+
+ if ( mbFormat )
+ {
+ if ( mnUserVisLines )
+ nCalcLines = mnUserVisLines;
+ else
+ {
+ nCalcLines = (long)mpImpl->mpItemList->Count() / nCalcCols;
+ if ( mpImpl->mpItemList->Count() % nCalcCols )
+ nCalcLines++;
+ else if ( !nCalcLines )
+ nCalcLines = 1;
+ }
+ }
+ }
+
+ Size aSize( rItemSize.Width()*nCalcCols, rItemSize.Height()*nCalcLines );
+ WinBits nStyle = GetStyle();
+ long nTxtHeight = GetTextHeight();
+ long nSpace;
+ long n;
+
+ if ( nStyle & WB_ITEMBORDER )
+ {
+ if ( nStyle & WB_DOUBLEBORDER )
+ n = ITEM_OFFSET_DOUBLE;
+ else
+ n = ITEM_OFFSET;
+
+ aSize.Width() += n*nCalcCols;
+ aSize.Height() += n*nCalcLines;
+ }
+ else
+ n = 0;
+
+ if ( mnSpacing )
+ {
+ nSpace = mnSpacing;
+ aSize.Width() += mnSpacing*(nCalcCols-1);
+ aSize.Height() += mnSpacing*(nCalcLines-1);
+ }
+ else
+ nSpace = 0;
+
+ if ( nStyle & WB_NAMEFIELD )
+ {
+ aSize.Height() += nTxtHeight + NAME_OFFSET;
+ if ( !(nStyle & WB_FLATVALUESET) )
+ aSize.Height() += NAME_LINE_HEIGHT+NAME_LINE_OFF_Y;
+ }
+
+ if ( nStyle & WB_NONEFIELD )
+ {
+ aSize.Height() += nTxtHeight + n + nSpace;
+ if ( nStyle & WB_RADIOSEL )
+ aSize.Height() += 8;
+ }
+
+ // Evt. ScrollBar-Breite aufaddieren
+ aSize.Width() += GetScrollWidth();
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+Size ValueSet::CalcItemSizePixel( const Size& rItemSize, sal_Bool bOut ) const
+{
+ Size aSize = rItemSize;
+
+ WinBits nStyle = GetStyle();
+ if ( nStyle & WB_ITEMBORDER )
+ {
+ long n;
+
+ if ( nStyle & WB_DOUBLEBORDER )
+ n = ITEM_OFFSET_DOUBLE;
+ else
+ n = ITEM_OFFSET;
+
+ if ( bOut )
+ {
+ aSize.Width() += n;
+ aSize.Height() += n;
+ }
+ else
+ {
+ aSize.Width() -= n;
+ aSize.Height() -= n;
+ }
+ }
+
+ return aSize;
+}
+
+// -----------------------------------------------------------------------
+
+long ValueSet::GetScrollWidth() const
+{
+ if ( GetStyle() & WB_VSCROLL )
+ {
+ ((ValueSet*)this)->ImplInitScrollBar();
+ return mpScrBar->GetSizePixel().Width()+SCRBAR_OFFSET;
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uInt16 ValueSet::ShowDropPos( const Point& rPos )
+{
+ mbDropPos = sal_True;
+
+ // Gegebenenfalls scrollen
+ ImplScroll( rPos );
+
+ // DropPosition ermitteln
+ sal_uInt16 nPos = ImplGetItem( rPos, sal_True );
+ if ( nPos == VALUESET_ITEM_NONEITEM )
+ nPos = 0;
+ else if ( nPos == VALUESET_ITEM_NOTFOUND )
+ {
+ Size aOutSize = GetOutputSizePixel();
+ if ( GetStyle() & WB_NAMEFIELD )
+ aOutSize.Height() = mnTextOffset;
+ if ( (rPos.X() >= 0) && (rPos.X() < aOutSize.Width()) &&
+ (rPos.Y() >= 0) && (rPos.Y() < aOutSize.Height()) )
+ nPos = (sal_uInt16)mpImpl->mpItemList->Count();
+ }
+ else
+ {
+ // Im letzten viertel, dann wird ein Item spaeter eingefuegt
+ Rectangle aRect = mpImpl->mpItemList->GetObject( nPos )->maRect;
+ if ( rPos.X() > aRect.Left()+aRect.GetWidth()-(aRect.GetWidth()/4) )
+ nPos++;
+ }
+
+ if ( nPos != mnDropPos )
+ {
+ ImplDrawDropPos( sal_False );
+ mnDropPos = nPos;
+ ImplDrawDropPos( sal_True );
+ }
+
+ return mnDropPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::HideDropPos()
+{
+ if ( mbDropPos )
+ {
+ ImplDrawDropPos( sal_False );
+ mbDropPos = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool ValueSet::IsRTLActive (void)
+{
+ return Application::GetSettings().GetLayoutRTL() && IsRTLEnabled();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetHighlightHdl( const Link& rLink )
+{
+ mpImpl->maHighlightHdl = rLink;
+}
+
+// -----------------------------------------------------------------------
+
+const Link& ValueSet::GetHighlightHdl() const
+{
+ return mpImpl->maHighlightHdl;
+}
+
+// -----------------------------------------------------------------------
+