summaryrefslogtreecommitdiff
path: root/svtools/source/control
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/control')
-rw-r--r--svtools/source/control/asynclink.cxx142
-rw-r--r--svtools/source/control/calendar.cxx3054
-rw-r--r--svtools/source/control/calendar.src77
-rw-r--r--svtools/source/control/collatorres.cxx131
-rw-r--r--svtools/source/control/ctrlbox.cxx1511
-rw-r--r--svtools/source/control/ctrlbox.src235
-rw-r--r--svtools/source/control/ctrldll.cxx81
-rw-r--r--svtools/source/control/ctrltool.cxx1019
-rw-r--r--svtools/source/control/ctrltool.src147
-rw-r--r--svtools/source/control/filectrl.cxx236
-rw-r--r--svtools/source/control/filectrl.src61
-rw-r--r--svtools/source/control/filectrl2.cxx97
-rw-r--r--svtools/source/control/fileurlbox.cxx127
-rw-r--r--svtools/source/control/fixedhyper.cxx236
-rw-r--r--svtools/source/control/fmtfield.cxx1401
-rw-r--r--svtools/source/control/headbar.cxx1656
-rw-r--r--svtools/source/control/hyperlabel.cxx273
-rw-r--r--svtools/source/control/indexentryres.cxx136
-rw-r--r--svtools/source/control/inettbc.cxx1379
-rw-r--r--svtools/source/control/makefile.mk89
-rw-r--r--svtools/source/control/prgsbar.cxx265
-rw-r--r--svtools/source/control/reginfo.cxx375
-rw-r--r--svtools/source/control/roadmap.cxx1028
-rw-r--r--svtools/source/control/ruler.cxx3184
-rw-r--r--svtools/source/control/scriptedtext.cxx398
-rw-r--r--svtools/source/control/scrwin.cxx575
-rw-r--r--svtools/source/control/stdctrl.cxx99
-rw-r--r--svtools/source/control/stdmenu.cxx518
-rw-r--r--svtools/source/control/tabbar.cxx2642
-rw-r--r--svtools/source/control/taskbar.cxx597
-rw-r--r--svtools/source/control/taskbox.cxx355
-rw-r--r--svtools/source/control/taskmisc.cxx383
-rw-r--r--svtools/source/control/taskstat.cxx659
-rw-r--r--svtools/source/control/urlcontrol.cxx102
-rw-r--r--svtools/source/control/valueacc.cxx1264
-rw-r--r--svtools/source/control/valueimp.hxx332
-rw-r--r--svtools/source/control/valueset.cxx2754
37 files changed, 27618 insertions, 0 deletions
diff --git a/svtools/source/control/asynclink.cxx b/svtools/source/control/asynclink.cxx
new file mode 100644
index 000000000000..1e47c71de5d4
--- /dev/null
+++ b/svtools/source/control/asynclink.cxx
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: asynclink.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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 <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, BOOL
+#ifdef DBG_UTIL
+bAllowDoubles
+#endif
+, 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 = 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 = TRUE;
+ BOOL bDeleted = FALSE;
+ _pDeleted = &bDeleted;
+ _aLink.Call( pArg );
+ if( !bDeleted )
+ {
+ _bInCall = FALSE;
+ _pDeleted = 0;
+ }
+}
+
+}
diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx
new file mode 100644
index 000000000000..8ff008eaf7e4
--- /dev/null
+++ b/svtools/source/control/calendar.cxx
@@ -0,0 +1,3054 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: calendar.cxx,v $
+ * $Revision: 1.14 $
+ *
+ * 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 _APP_HXX
+#include <vcl/svapp.hxx>
+#endif
+#ifndef _TABLE_HXX
+#include <tools/table.hxx>
+#endif
+#ifndef _HELP_HXX
+#include <vcl/help.hxx>
+#endif
+#ifndef _MENU_HXX
+#include <vcl/menu.hxx>
+#endif
+#ifndef _DECOVIEW_HXX
+#include <vcl/decoview.hxx>
+#endif
+#ifndef _FLOATWIN_HXX
+#include <vcl/floatwin.hxx>
+#endif
+#ifndef _BUTTON_HXX
+#include <vcl/button.hxx>
+#endif
+#ifndef _FIXED_HXX
+#include <vcl/fixed.hxx>
+#endif
+#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 <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 ((USHORT)0x0001)
+#define CALENDAR_HITTEST_WEEK ((USHORT)0x0002)
+#define CALENDAR_HITTEST_MONTHTITLE ((USHORT)0x0004)
+#define CALENDAR_HITTEST_PREV ((USHORT)0x0008)
+#define CALENDAR_HITTEST_NEXT ((USHORT)0x0010)
+#define CALENDAR_HITTEST_OUTSIDE ((USHORT)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;
+ USHORT 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, 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,
+ 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 = TRUE;
+ mbFormat = TRUE;
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ mbMultiSelection = FALSE;
+ mbWeekSel = FALSE;
+ mbUnSel = FALSE;
+ mbMenuDown = FALSE;
+ mbSpinDown = FALSE;
+ mbPrevIn = FALSE;
+ mbNextIn = FALSE;
+ mbDirect = FALSE;
+ mbInSelChange = FALSE;
+ mbTravelSelect = FALSE;
+ mbScrollDateRange = FALSE;
+ mbSelLeft = FALSE;
+ mbAllSel = FALSE;
+ mbDropPos = 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, TRUE );
+
+ // Sonstige Strings erzeugen
+ maDayText = XubString( SvtResId( STR_SVT_CALENDAR_DAY ) );
+ maWeekText = XubString( SvtResId( STR_SVT_CALENDAR_WEEK ) );
+
+ // Tagestexte anlegen
+ for ( USHORT 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 ( USHORT i = 0; i < 31; i++ )
+ delete mpDayText[i];
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetMinimumNumberOfDaysInWeek( sal_Int16 nDays )
+{
+ ImplUpdate( TRUE );
+ maCalendarWrapper.setMinimumNumberOfDaysForFirstWeek( nDays);
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::SetWeekStart( sal_Int16 nDay )
+{
+ ImplUpdate( 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 = FALSE;
+ }
+
+ // Anzahl Tage berechnen
+
+ DayOfWeek eStartDay = ImplGetWeekStart();
+
+ USHORT nWeekDay;
+ Date aTempDate = GetFirstMonth();
+ maFirstDate = aTempDate;
+ nWeekDay = (USHORT)aTempDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(USHORT)eStartDay)) % 7;
+ maFirstDate -= (ULONG)nWeekDay;
+ mnDayCount = nWeekDay;
+ USHORT nDaysInMonth;
+ USHORT nMonthCount = (USHORT)(mnMonthPerLine*mnLines);
+ for ( USHORT i = 0; i < nMonthCount; i++ )
+ {
+ nDaysInMonth = aTempDate.GetDaysInMonth();
+ mnDayCount += nDaysInMonth;
+ aTempDate += nDaysInMonth;
+ }
+ Date aTempDate2 = aTempDate;
+ aTempDate2--;
+ nDaysInMonth = aTempDate2.GetDaysInMonth();
+ aTempDate2 -= nDaysInMonth-1;
+ nWeekDay = (USHORT)aTempDate2.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(USHORT)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
+ USHORT nNewFirstYear = maFirstDate.GetYear();
+ USHORT 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 = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT 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;
+ USHORT 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;
+
+ USHORT 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;
+ USHORT nDayIndex = (USHORT)rDate.GetDayOfWeek();
+ nDayIndex = (nDayIndex+(7-(USHORT)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) )
+ {
+ USHORT nWeekDay = (USHORT)rDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(USHORT)eStartDay)) % 7;
+ USHORT 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,
+ 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( BOOL bDrawPrev, 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, TRUE );
+ }
+ if ( bDrawNext )
+ {
+ Rectangle aOutRect = maNextRect;
+ aOutRect.Left() += 3;
+ aOutRect.Top() += 3;
+ aOutRect.Right() -= 3;
+ aOutRect.Bottom() -= 3;
+ ImplDrawSpinArrow( this, aOutRect, FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplDrawDate( long nX, long nY,
+ USHORT nDay, USHORT nMonth, USHORT nYear,
+ DayOfWeek eDayOfWeek,
+ BOOL bBack, BOOL bOther, ULONG nToday )
+{
+ ImplDateInfo* pDateInfo;
+ Color* pTextColor = NULL;
+ const String& rDay = *(mpDayText[nDay-1]);
+ Rectangle aDateRect( nX, nY, nX+mnDayWidth-1, nY+mnDayHeight-1 );
+
+ BOOL bSel = FALSE;
+ BOOL bFocus = FALSE;
+ // Aktueller Tag
+ if ( (nDay == maCurDate.GetDay()) &&
+ (nMonth == maCurDate.GetMonth()) &&
+ (nYear == maCurDate.GetYear()) )
+ bFocus = TRUE;
+ if ( mpSelectTable )
+ {
+ if ( mpSelectTable->IsKeyValid( Date( nDay, nMonth, nYear ).GetDate() ) )
+ bSel = 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();
+ BOOL bBoldFont = FALSE;
+ if ( (mnWinStyle & WB_BOLDTEXT) &&
+ pDateInfo && (pDateInfo->mnFlags & DIB_BOLD) )
+ {
+ bBoldFont = 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( 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;
+ ULONG nToday = Date().GetDate();
+ USHORT nDay;
+ USHORT nMonth;
+ USHORT 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 ( USHORT 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
+ USHORT 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 );
+ }
+ USHORT nDayIndex = (USHORT)aDate.GetDayOfWeek();
+ nDayIndex = (nDayIndex+(7-(USHORT)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+(USHORT)eStartDay)%7), FALSE, TRUE, nToday );
+ }
+ }
+ for ( nDay = 1; nDay <= nDaysInMonth; nDay++ )
+ {
+ nDeltaX = nDayX + (nDayIndex*mnDayWidth);
+ ImplDrawDate( nDeltaX, nDayY, nDay, nMonth, nYear,
+ (DayOfWeek)((nDayIndex+(USHORT)eStartDay)%7),
+ FALSE, FALSE, nToday );
+ if ( nDayIndex == 6 )
+ {
+ nDayIndex = 0;
+ nDayY += mnDayHeight;
+ }
+ else
+ nDayIndex++;
+ }
+ if ( (i == mnLines-1) && (j == mnMonthPerLine-1) )
+ {
+ USHORT nWeekDay = (USHORT)aDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(USHORT)eStartDay)) % 7;
+ USHORT 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+(USHORT)eStartDay)%7),
+ FALSE, 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() )
+ {
+ BOOL bOther = (rDate < GetFirstMonth()) || (rDate > GetLastMonth());
+ ImplDrawDate( aDateRect.Left(), aDateRect.Top(),
+ rDate.GetDay(), rDate.GetMonth(), rDate.GetYear(),
+ rDate.GetDayOfWeek(), TRUE, bOther );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplUpdateSelection( Table* pOld )
+{
+ Table* pNew = mpSelectTable;
+ void* p;
+ 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, USHORT nHitTest,
+ BOOL bMove, BOOL bExpand, 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, FALSE );
+ ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), FALSE );
+ }
+ else
+ {
+ ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, FALSE );
+ ImplCalendarSelectDateRange( mpSelectTable, aTempDate, Date( 31, 12, 9999 ), FALSE );
+ }
+ }
+ ImplCalendarSelectDateRange( mpSelectTable, aTempDate, maAnchorDate, TRUE );
+ }
+ else if ( bExtended && !(mnWinStyle & WB_RANGESELECT) )
+ {
+ maAnchorDate = aTempDate;
+ if ( IsDateSelected( aTempDate ) )
+ {
+ mbUnSel = TRUE;
+ ImplCalendarSelectDate( mpSelectTable, aTempDate, FALSE );
+ }
+ else
+ {
+ ImplCalendarSelectDate( mpSelectTable, aTempDate, TRUE );
+ }
+ }
+ else
+ {
+ maAnchorDate = aTempDate;
+ ImplCalendarClearSelectDate( mpSelectTable );
+ ImplCalendarSelectDate( mpSelectTable, aTempDate, TRUE );
+ }
+
+ mpRestoreSelectTable = new Table( *mpSelectTable );
+ }
+ }
+ else
+ {
+ if ( aTempDate < maCurDate )
+ mbSelLeft = TRUE;
+ else
+ mbSelLeft = FALSE;
+ if ( !(nHitTest & CALENDAR_HITTEST_DAY) )
+ aTempDate = maOldCurDate;
+ if ( !bMove )
+ maAnchorDate = aTempDate;
+ if ( aTempDate != maCurDate )
+ {
+ maCurDate = aTempDate;
+ ImplCalendarSelectDate( mpSelectTable, aOldDate, FALSE );
+ ImplCalendarSelectDate( mpSelectTable, maCurDate, TRUE );
+ }
+ }
+
+ BOOL bNewSel = *pOldSel != *mpSelectTable;
+ if ( (maCurDate != aOldDate) || bNewSel )
+ {
+ if ( bNewSel )
+ {
+ mbInSelChange = TRUE;
+ SelectionChanging();
+ mbInSelChange = 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( BOOL bCalcNew )
+{
+ if ( IsReallyVisible() && IsUpdateMode() )
+ {
+ if ( bCalcNew && !mbCalc )
+ Invalidate();
+ else if ( !mbFormat && !mbCalc )
+ {
+ if ( mbDirect )
+ {
+ mbFormat = TRUE;
+ ImplDraw( FALSE );
+ return;
+ }
+ else
+ Invalidate();
+ }
+ }
+
+ if ( bCalcNew )
+ mbCalc = TRUE;
+ mbFormat = 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( BOOL bPrev )
+{
+ Date aNewFirstMonth = GetFirstMonth();
+ if ( bPrev )
+ {
+ aNewFirstMonth--;
+ aNewFirstMonth -= aNewFirstMonth.GetDaysInMonth()-1;
+ }
+ else
+ aNewFirstMonth += aNewFirstMonth.GetDaysInMonth();
+ mbDirect = TRUE;
+ SetFirstDate( aNewFirstMonth );
+ mbDirect = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplShowMenu( const Point& rPos, const Date& rDate )
+{
+ EndSelection();
+
+ Date aOldFirstDate = GetFirstMonth();
+ PopupMenu aPopupMenu;
+ PopupMenu* pYearPopupMenus[MENU_YEAR_COUNT];
+ USHORT nMonthOff;
+ USHORT nCurItemId;
+ USHORT nYear = rDate.GetYear()-1;
+ USHORT i;
+ USHORT j;
+ USHORT 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 = TRUE;
+ nCurItemId = aPopupMenu.Execute( this, rPos );
+ mbMenuDown = 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 )
+ {
+ USHORT nTempMonthOff = nMonthOff % 12;
+ USHORT nTempYearOff = nMonthOff / 12;
+ USHORT nNewMonth = nCurItemId % 1000;
+ USHORT 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, BOOL bRepeat )
+{
+ Date aTempDate = maCurDate;
+ USHORT nHitTest = ImplHitTest( rPos, aTempDate );
+
+ if ( mbSpinDown )
+ {
+ mbPrevIn = (nHitTest & CALENDAR_HITTEST_PREV) != 0;
+ mbNextIn = (nHitTest & CALENDAR_HITTEST_NEXT) != 0;
+
+ if ( bRepeat && (mbPrevIn || mbNextIn) )
+ {
+ mbScrollDateRange = TRUE;
+ ImplScroll( mbPrevIn );
+ mbScrollDateRange = FALSE;
+ }
+ }
+ else
+ ImplMouseSelect( aTempDate, nHitTest, TRUE, FALSE, FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::ImplEndTracking( BOOL bCancel )
+{
+ BOOL bSelection = mbSelection;
+ BOOL bSpinDown = mbSpinDown;
+
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ mbMultiSelection = FALSE;
+ mbUnSel = FALSE;
+ mbSpinDown = FALSE;
+ mbPrevIn = FALSE;
+ mbNextIn = 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
+ ULONG nSelCount = mpSelectTable->Count();
+ if ( nSelCount )
+ {
+ Date aFirstSelDate( mpSelectTable->GetObjectKey( 0 ) );
+ Date aLastSelDate( mpSelectTable->GetObjectKey( nSelCount-1 ) );
+ if ( aLastSelDate < GetFirstMonth() )
+ ImplScroll( TRUE );
+ else if ( GetLastMonth() < aFirstSelDate )
+ ImplScroll( 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 )
+{
+ BOOL bPrevIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_PREV) != 0;
+ BOOL bNextIn = (pThis->mnDragScrollHitTest & CALENDAR_HITTEST_NEXT) != 0;
+ if( bNextIn || bPrevIn )
+ {
+ pThis->mbScrollDateRange = TRUE;
+ pThis->ImplScroll( bPrevIn );
+ pThis->mbScrollDateRange = FALSE;
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && !mbMenuDown )
+ {
+ Date aTempDate = maCurDate;
+ USHORT 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 = TRUE;
+ mbScrollDateRange = TRUE;
+ ImplScroll( mbPrevIn );
+ mbScrollDateRange = 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 = TRUE;
+ StartTracking();
+ }
+
+ mbMultiSelection = (mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT)) != 0;
+ if ( (nHitTest & CALENDAR_HITTEST_DAY) && mbMultiSelection )
+ mbWeekSel = TRUE;
+ else
+ mbWeekSel = FALSE;
+ ImplMouseSelect( aTempDate, nHitTest, FALSE, rMEvt.IsShift(), rMEvt.IsMod1() );
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
+ Control::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() && mbSelection )
+ ImplEndTracking( FALSE );
+ else
+ Control::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::MouseMove( const MouseEvent& rMEvt )
+{
+ if ( mbSelection && rMEvt.GetButtons() )
+ ImplTracking( rMEvt.GetPosPixel(), 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;
+ BOOL bMultiSel = (mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) != 0;
+ BOOL bExpand = rKEvt.GetKeyCode().IsShift();
+ 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 )
+ {
+ BOOL bDateSel = IsDateSelected( maCurDate );
+ SelectDate( maCurDate, !bDateSel );
+ mbSelLeft = FALSE;
+ SelectionChanging();
+ mbTravelSelect = TRUE;
+ Select();
+ mbTravelSelect = 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, FALSE );
+ ImplCalendarSelectDateRange( mpSelectTable, maAnchorDate, Date( 31, 12, 9999 ), FALSE );
+ }
+ else
+ {
+ ImplCalendarSelectDateRange( mpSelectTable, Date( 1, 1, 0 ), maAnchorDate, FALSE );
+ ImplCalendarSelectDateRange( mpSelectTable, aNewDate, Date( 31, 12, 9999 ), FALSE );
+ }
+ }
+ ImplCalendarSelectDateRange( mpSelectTable, aNewDate, maAnchorDate, TRUE );
+ mbDirect = TRUE;
+ SetCurDate( aNewDate );
+ mbDirect = FALSE;
+ maAnchorDate = aOldAnchorDate;
+ mbInSelChange = TRUE;
+ SelectionChanging();
+ mbInSelChange = FALSE;
+ ImplUpdateSelection( pOldSel );
+ delete pOldSel;
+ }
+ else
+ {
+ if ( mnWinStyle & WB_RANGESELECT )
+ {
+ SetNoSelection();
+ SelectDate( aNewDate, TRUE );
+ }
+ mbDirect = TRUE;
+ SetCurDate( aNewDate );
+ mbDirect = FALSE;
+ }
+ mbTravelSelect = TRUE;
+ Select();
+ mbTravelSelect = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::Paint( const Rectangle& )
+{
+ ImplDraw( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::GetFocus()
+{
+ ImplUpdateDate( maCurDate );
+ Control::GetFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::LoseFocus()
+{
+ HideFocus();
+ Control::LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::Resize()
+{
+ ImplUpdate( 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);
+ USHORT nWeek = (USHORT) maCalendarWrapper.getValue( i18n::CalendarFieldIndex::WEEK_OF_YEAR);
+ USHORT 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;
+ USHORT 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( TRUE );
+ nNotchDelta++;
+ }
+ }
+ else
+ {
+ while ( nNotchDelta > 0 )
+ {
+ ImplScroll( 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, 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,
+ 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;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Calendar::IsDateSelected( const Date& rDate ) const
+{
+ return mpSelectTable->IsKeyValid( rDate.GetDate() );
+}
+
+// -----------------------------------------------------------------------
+
+ULONG Calendar::GetSelectDateCount() const
+{
+ return mpSelectTable->Count();
+}
+
+// -----------------------------------------------------------------------
+
+Date Calendar::GetSelectDate( 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 )
+ {
+ BOOL bUpdate = IsVisible() && IsUpdateMode();
+ Date aOldDate = maCurDate;
+ maCurDate = rNewDate;
+ maAnchorDate = maCurDate;
+
+ if ( !(mnWinStyle & (WB_RANGESELECT | WB_MULTISELECT)) )
+ {
+ ImplCalendarSelectDate( mpSelectTable, aOldDate, FALSE );
+ ImplCalendarSelectDate( mpSelectTable, maCurDate, TRUE );
+ }
+ else if ( !HasFocus() )
+ bUpdate = 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 = 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();
+ USHORT nMonthCount = GetMonthCount();
+ for ( USHORT i = 0; i < nMonthCount; i++ )
+ aDate += aDate.GetDaysInMonth();
+ aDate--;
+ return aDate;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT Calendar::GetMonthCount() const
+{
+ if ( mbFormat )
+ return 1;
+ else
+ return (USHORT)(mnMonthPerLine*mnLines);
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Calendar::GetDropDate( Date& rDate ) const
+{
+ if( mbDropPos )
+ {
+ rDate = maDropDate;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Calendar::GetDate( const Point& rPos, Date& rDate ) const
+{
+ Date aDate = maCurDate;
+ USHORT nHitTest = ImplHitTest( rPos, aDate );
+ if ( nHitTest & CALENDAR_HITTEST_DAY )
+ {
+ rDate = aDate;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle Calendar::GetDateRect( const Date& rDate ) const
+{
+ Rectangle aRect;
+
+ if ( mbFormat || (rDate < maFirstDate) || (rDate > (maFirstDate+mnDayCount)) )
+ return aRect;
+
+ long nX;
+ long nY;
+ ULONG nDaysOff;
+ USHORT 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 )
+ {
+ USHORT nWeekDay = (USHORT)aLastDate.GetDayOfWeek();
+ nWeekDay = (nWeekDay+(7-(USHORT)ImplGetWeekStart())) % 7;
+ aLastDate -= nWeekDay;
+ aRect = GetDateRect( aLastDate );
+ nDaysOff = rDate-aLastDate;
+ nDayIndex = 0;
+ for ( USHORT 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++ )
+ {
+ USHORT nDaysInMonth = aDate.GetDaysInMonth();
+
+ // Monat gerufen
+ if ( (aDate.GetMonth() == rDate.GetMonth()) &&
+ (aDate.GetYear() == rDate.GetYear()) )
+ {
+ long nDayX = nX+mnDaysOffX;
+ long nDayY = nY+mnDaysOffY;
+ nDayIndex = (USHORT)aDate.GetDayOfWeek();
+ nDayIndex = (nDayIndex+(7-(USHORT)ImplGetWeekStart())) % 7;
+ for ( USHORT 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,
+ USHORT nFlags )
+{
+ if ( !mpDateTable )
+ mpDateTable = new ImplDateTable( 256, 256 );
+
+ BOOL bChanged = FALSE;
+ 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 = TRUE;
+ }
+ }
+ else
+ {
+ pDateInfo->mpTextColor = new Color( *pTextColor );
+ bChanged = TRUE;
+ }
+ }
+ else
+ {
+ if ( pDateInfo->mpTextColor )
+ {
+ delete pDateInfo->mpTextColor;
+ pDateInfo->mpTextColor = NULL;
+ bChanged = TRUE;
+ }
+ }
+ if ( pFrameColor )
+ {
+ if ( pDateInfo->mpFrameColor )
+ {
+ if ( *(pDateInfo->mpFrameColor) != *pFrameColor )
+ {
+ *(pDateInfo->mpFrameColor) = *pFrameColor;
+ bChanged = TRUE;
+ }
+ }
+ else
+ {
+ pDateInfo->mpFrameColor = new Color( *pFrameColor );
+ bChanged = TRUE;
+ }
+ }
+ else
+ {
+ if ( pDateInfo->mpFrameColor )
+ {
+ delete pDateInfo->mpFrameColor;
+ pDateInfo->mpFrameColor = NULL;
+ bChanged = TRUE;
+ }
+ }
+ if ( pDateInfo->mnFlags != nFlags )
+ {
+ pDateInfo->mnFlags = nFlags;
+ bChanged = 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 )
+ {
+ 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 )
+ {
+ ULONG nKey = rDate.GetDate();
+ ImplDateInfo* pDateInfo = mpDateTable->Get( nKey );
+ if ( pDateInfo )
+ aRet = pDateInfo->maText;
+ }
+ return aRet;
+}
+
+// -----------------------------------------------------------------------
+
+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 = TRUE;
+ ImplInvertDropPos();
+ }
+
+ rDate = maDropDate;
+ return TRUE;
+ }
+ }
+ }
+ else
+ maDragScrollTimer.Stop();
+
+ HideDropPos();
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::HideDropPos()
+{
+ if ( mbDropPos )
+ {
+ ImplInvertDropPos();
+ mbDropPos = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::StartSelection()
+{
+ if ( mpOldSelectTable )
+ delete mpOldSelectTable;
+ maOldCurDate = maCurDate;
+ mpOldSelectTable = new Table( *mpSelectTable );
+
+ mbSelection = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void Calendar::EndSelection()
+{
+ if ( mbDrag || mbSpinDown || mbSelection )
+ {
+ if ( !mbSelection )
+ ReleaseMouse();
+
+ mbDrag = FALSE;
+ mbSelection = FALSE;
+ mbMultiSelection = FALSE;
+ mbSpinDown = FALSE;
+ mbPrevIn = FALSE;
+ mbNextIn = 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( BOOL bEnable );
+ PushButton* EnableNoneBtn( 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( 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( 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 = FALSE;
+ mbNone = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+CalendarField::CalendarField( Window* pParent, const ResId& rResId ) :
+ DateField( pParent, rResId ),
+ maDefaultDate( 0, 0, 0 )
+{
+ mpFloatWin = NULL;
+ mpCalendar = NULL;
+ mnCalendarStyle = 0;
+ mbToday = FALSE;
+ mbNone = 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 );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL CalendarField::ShowDropDown( 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 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 100644
index 000000000000..44bffd361847
--- /dev/null
+++ b/svtools/source/control/calendar.src
@@ -0,0 +1,77 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: calendar.src,v $
+ * $Revision: 1.12 $
+ *
+ * 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 100644
index 000000000000..692d470b8f5b
--- /dev/null
+++ b/svtools/source/control/collatorres.cxx
@@ -0,0 +1,131 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: collatorres.cxx,v $
+ * $Revision: 1.10 $
+ *
+ * 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 <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 100644
index 000000000000..097bba0e39f9
--- /dev/null
+++ b/svtools/source/control/ctrlbox.cxx
@@ -0,0 +1,1511 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ctrlbox.cxx,v $
+ * $Revision: 1.27 $
+ *
+ * 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>
+#ifndef _APP_HXX
+#include <vcl/svapp.hxx>
+#endif
+#ifndef _FIELD_HXX
+#include <vcl/field.hxx>
+#endif
+#include <comphelper/processfactory.hxx>
+#include <unotools/charclass.hxx>
+
+#include <svtools/svtdata.hxx>
+#include <svtools/svtools.hrc>
+#include <ctrlbox.hxx>
+#include <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;
+ BOOL bColor;
+
+ ImplColorListData() : aColor( COL_BLACK ) { bColor = FALSE; }
+ ImplColorListData( const Color& rColor ) : aColor( rColor ) { bColor = 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( TRUE );
+ SetUserItemSize( aImageSize );
+}
+
+// -----------------------------------------------------------------------
+
+void ColorListBox::ImplDestroyColorEntries()
+{
+ for ( USHORT n = (USHORT) 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;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ColorListBox::InsertEntry( const XubString& rStr, USHORT nPos )
+{
+ nPos = ListBox::InsertEntry( rStr, nPos );
+ if ( nPos != LISTBOX_ERROR )
+ {
+ ImplColorListData* pData = new ImplColorListData;
+ pColorList->Insert( pData, nPos );
+ }
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ColorListBox::InsertEntry( const Color& rColor, const XubString& rStr,
+ USHORT 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( USHORT 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
+ USHORT nCount = (USHORT) rBox.pColorList->Count();
+ for ( USHORT n = 0; n < nCount; n++ )
+ {
+ ImplColorListData* pData = rBox.pColorList->GetObject( n );
+ USHORT nPos = InsertEntry( rBox.GetEntry( n ), LISTBOX_APPEND );
+ if ( nPos != LISTBOX_ERROR )
+ pColorList->Insert( new ImplColorListData( *pData ), nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ColorListBox::GetEntryPos( const Color& rColor ) const
+{
+ for( USHORT n = (USHORT) pColorList->Count(); n; )
+ {
+ ImplColorListData* pData = pColorList->GetObject( --n );
+ if ( pData->bColor && ( pData->aColor == rColor ) )
+ return n;
+ }
+ return LISTBOX_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+Color ColorListBox::GetEntryColor( USHORT 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, FALSE, TRUE, FALSE );
+ }
+ else
+ ListBox::DrawEntry( rUDEvt, FALSE, TRUE, TRUE );
+ }
+ else
+ ListBox::DrawEntry( rUDEvt, TRUE, TRUE, 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()
+{
+ ULONG n = 0;
+ ULONG nCount = pLineList->Count();
+ while ( n < nCount )
+ {
+ ImpLineListData* pData = pLineList->GetObject( n );
+ if ( pData )
+ delete pData;
+ n++;
+ }
+ delete pLineList;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT LineListBox::InsertEntry( const XubString& rStr, USHORT nPos )
+{
+ nPos = ListBox::InsertEntry( rStr, nPos );
+ if ( nPos != LISTBOX_ERROR )
+ pLineList->Insert( NULL, nPos );
+ return nPos;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT LineListBox::InsertEntry( long nLine1, long nLine2, long nDistance,
+ USHORT 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( USHORT nPos )
+{
+ ListBox::RemoveEntry( nPos );
+ ImpLineListData* pData = pLineList->Remove( nPos );
+ if ( pData )
+ delete pData;
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::Clear()
+{
+ ULONG n = 0;
+ ULONG nCount = pLineList->Count();
+ while ( n < nCount )
+ {
+ ImpLineListData* pData = pLineList->GetObject( n );
+ if ( pData )
+ delete pData;
+ n++;
+ }
+
+ pLineList->Clear();
+ ListBox::Clear();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT LineListBox::GetEntryPos( long nLine1, long nLine2,
+ long nDistance ) const
+{
+ ULONG n = 0;
+ 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 (USHORT)n;
+ }
+
+ n++;
+ }
+
+ return LISTBOX_ENTRY_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+long LineListBox::GetEntryLine1( USHORT nPos ) const
+{
+ ImpLineListData* pData = pLineList->GetObject( nPos );
+ if ( pData )
+ return pData->nLine1;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long LineListBox::GetEntryLine2( USHORT nPos ) const
+{
+ ImpLineListData* pData = pLineList->GetObject( nPos );
+ if ( pData )
+ return pData->nLine2;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long LineListBox::GetEntryDistance( USHORT nPos ) const
+{
+ ImpLineListData* pData = pLineList->GetObject( nPos );
+ if ( pData )
+ return pData->nDistance;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void LineListBox::UpdateLineColors( void )
+{
+ if( UpdatePaintLineColor() )
+ {
+ ULONG nCount = pLineList->Count();
+ if( !nCount )
+ return;
+
+ XubString aStr;
+ Bitmap aBmp;
+
+ // exchange entries which containing lines
+ SetUpdateMode( FALSE );
+
+ USHORT nSelEntry = GetSelectEntryPos();
+ for( ULONG n = 0 ; n < nCount ; ++n )
+ {
+ ImpLineListData* pData = pLineList->GetObject( n );
+ if( pData )
+ {
+ // exchange listbox data
+ ListBox::RemoveEntry( USHORT( n ) );
+ ImpGetLine( pData->nLine1, pData->nLine2, pData->nDistance, aBmp, aStr );
+ ListBox::InsertEntry( aStr, aBmp, USHORT( n ) );
+ }
+ }
+
+ if( nSelEntry != LISTBOX_ENTRY_NOTFOUND )
+ SelectEntryPos( nSelEntry );
+
+ SetUpdateMode( TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL LineListBox::UpdatePaintLineColor( void )
+{
+ BOOL bRet = 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;
+ USHORT mnType;
+
+ ImplFontNameListData( const FontInfo& rInfo,
+ USHORT nType ) :
+ maInfo( rInfo ),
+ mnType( nType )
+ {}
+};
+
+DECLARE_LIST( ImplFontList, ImplFontNameListData* )
+
+// -------------------------------------------------------------------
+
+FontNameBox::FontNameBox( Window* pParent, WinBits nWinStyle ) :
+ ComboBox( pParent, nWinStyle )
+{
+ InitBitmaps();
+ mpFontList = NULL;
+ mbWYSIWYG = FALSE;
+ mbSymbols = FALSE;
+}
+
+// -------------------------------------------------------------------
+
+FontNameBox::FontNameBox( Window* pParent, const ResId& rResId ) :
+ ComboBox( pParent, rResId )
+{
+ InitBitmaps();
+ mpFontList = NULL;
+ mbWYSIWYG = FALSE;
+ mbSymbols = 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 )
+{
+ 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
+ USHORT nFontCount = pList->GetFontNameCount();
+ for ( USHORT i = 0; i < nFontCount; i++ )
+ {
+ const FontInfo& rFontInfo = pList->GetFontName( i );
+ ULONG nIndex = InsertEntry( rFontInfo.GetName() );
+ if ( nIndex != LISTBOX_ERROR )
+ {
+ USHORT 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( BOOL bEnable )
+{
+ if ( bEnable != mbWYSIWYG )
+ {
+ mbWYSIWYG = bEnable;
+ EnableUserDraw( mbWYSIWYG | mbSymbols );
+ ImplCalcUserItemSize();
+ }
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::EnableSymbols( BOOL bEnable )
+{
+ if ( bEnable != mbSymbols )
+ {
+ mbSymbols = bEnable;
+ EnableUserDraw( mbWYSIWYG | mbSymbols );
+ ImplCalcUserItemSize();
+ }
+}
+
+// -------------------------------------------------------------------
+
+void FontNameBox::ImplCalcUserItemSize()
+{
+ Size aUserItemSz;
+ if ( mbWYSIWYG && mpFontList )
+ {
+ USHORT nMaxLen = 0;
+ BOOL bSymbolFont = FALSE;
+ BOOL bStarSymbol = FALSE;
+ for ( USHORT 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 = TRUE;
+ // starsymbol is a unicode font, but gets WYSIWIG symbols
+ if( aFontName.EqualsIgnoreCaseAscii( "starsymbol" )
+ || aFontName.EqualsIgnoreCaseAscii( "opensymbol" ) )
+ bSymbolFont = bStarSymbol = 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;
+ USHORT 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, FALSE, FALSE); // draw seperator
+ }
+ else
+ {
+ DrawEntry( rUDEvt, TRUE, 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();
+ USHORT nEntryCount = GetEntryCount();
+
+ if ( GetEntryPos( aStr ) == COMBOBOX_ENTRY_NOTFOUND )
+ {
+ aChrCls.toUpper( aStr );
+ for ( USHORT 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();
+ USHORT 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;
+ BOOL bNormal = FALSE;
+ BOOL bItalic = FALSE;
+ BOOL bBold = FALSE;
+ BOOL bBoldItalic = FALSE;
+ BOOL bInsert = 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 = TRUE;
+ else
+ bNormal = TRUE;
+ }
+ else
+ {
+ if ( eItalic != ITALIC_NONE )
+ bBoldItalic = TRUE;
+ else
+ bBold = 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 = TRUE;
+ else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
+ bBold = TRUE;
+ else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
+ bBoldItalic = 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( FALSE );
+
+ bRelativeMode = FALSE;
+ bPtRelative = FALSE;
+ bRelative = FALSE;
+ bStdSize = FALSE;
+ pFontList = NULL;
+
+ SetShowTrailingZeros( FALSE );
+ SetDecimalDigits( 1 );
+ SetMin( 20 );
+ SetMax( 9999 );
+}
+
+// -----------------------------------------------------------------------
+
+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();
+
+ BOOL bNewMode = bRelative;
+ BOOL bOldPtRelMode = bPtRelative;
+
+ if ( bRelative )
+ {
+ bPtRelative = FALSE;
+ const xub_Unicode* pStr = aStr.GetBuffer();
+ while ( *pStr )
+ {
+ if ( ((*pStr < '0') || (*pStr > '9')) && (*pStr != '%') )
+ {
+ if ( ('-' == *pStr || '+' == *pStr) && !bPtRelative )
+ bPtRelative = TRUE;
+ else if ( bPtRelative && 'p' == *pStr && 't' == *++pStr )
+ ;
+ else
+ {
+ bNewMode = FALSE;
+ break;
+ }
+ }
+ pStr++;
+ }
+ }
+ else
+ {
+ if ( STRING_NOTFOUND != aStr.Search( '%' ) )
+ {
+ bNewMode = TRUE;
+ bPtRelative = FALSE;
+ }
+
+ if ( '-' == aStr.GetChar( 0 ) || '+' == aStr.GetChar( 0 ) )
+ {
+ bNewMode = TRUE;
+ bPtRelative = 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 = TRUE;
+ }
+ else
+ bStdSize = FALSE;
+
+ Selection aSelection = GetSelection();
+ XubString aStr = GetText();
+
+ Clear();
+ USHORT nPos = 0;
+
+ if ( !aFontSizeNames.IsEmpty() )
+ {
+ if ( pAry == pList->GetStdSizeAry() )
+ {
+ // for scalable fonts all font size names
+ ULONG nCount = aFontSizeNames.Count();
+ for( 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( USHORT nMin, USHORT nMax, USHORT nStep )
+{
+ bRelativeMode = TRUE;
+ nRelMin = nMin;
+ nRelMax = nMax;
+ nRelStep = nStep;
+ SetUnit( FUNIT_POINT );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::EnablePtRelativeMode( short nMin, short nMax, short nStep )
+{
+ bRelativeMode = TRUE;
+ nPtRelMin = nMin;
+ nPtRelMax = nMax;
+ nPtRelStep = nStep;
+ SetUnit( FUNIT_POINT );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::SetRelative( BOOL bNewRelative )
+{
+ if ( bRelativeMode )
+ {
+ Selection aSelection = GetSelection();
+ XubString aStr = GetText();
+ aStr.EraseLeadingChars();
+
+ if ( bNewRelative )
+ {
+ bRelative = TRUE;
+ bStdSize = 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();
+ USHORT i = nRelMin;
+ while ( i <= nRelMax )
+ {
+ InsertValue( i );
+ i = i + nRelStep;
+ }
+ }
+ }
+ else
+ {
+ bRelative = bPtRelative = 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( FALSE );
+ return;
+ }
+ }
+
+ MetricBox::SetValue( nNewValue, eInUnit );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeBox::SetValue( sal_Int64 nNewValue )
+{
+ SetValue( nNewValue, FUNIT_NONE );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int64 FontSizeBox::GetValue( USHORT 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 100644
index 000000000000..5cfee79e5f11
--- /dev/null
+++ b/svtools/source/control/ctrlbox.src
@@ -0,0 +1,235 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ctrlbox.src,v $
+ * $Revision: 1.59 $
+ *
+ * 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/ctrldll.cxx b/svtools/source/control/ctrldll.cxx
new file mode 100644
index 000000000000..084d76125088
--- /dev/null
+++ b/svtools/source/control/ctrldll.cxx
@@ -0,0 +1,81 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ctrldll.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * 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 WIN
+#include <svwin.h>
+
+#ifndef _SYSDEP_HXX
+#include <sysdep.hxx>
+#endif
+
+// Statische DLL-Verwaltungs-Variablen
+static HINSTANCE hDLLInst = 0; // HANDLE der DLL
+
+/***************************************************************************
+|*
+|* LibMain()
+|*
+|* Beschreibung Initialisierungsfunktion der DLL
+|* Ersterstellung TH 05.05.93
+|* Letzte Aenderung TH 05.05.93
+|*
+***************************************************************************/
+
+extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
+{
+#ifndef WNT
+ if ( nHeap )
+ UnlockData( 0 );
+#endif
+
+ hDLLInst = hDLL;
+
+ return TRUE;
+}
+
+/***************************************************************************
+|*
+|* WEP()
+|*
+|* Beschreibung DLL-Deinitialisierung
+|* Ersterstellung TH 05.05.93
+|* Letzte Aenderung TH 05.05.93
+|*
+***************************************************************************/
+
+extern "C" int CALLBACK WEP( int )
+{
+ return 1;
+}
+
+#endif
diff --git a/svtools/source/control/ctrltool.cxx b/svtools/source/control/ctrltool.cxx
new file mode 100644
index 000000000000..77bb996584bd
--- /dev/null
+++ b/svtools/source/control/ctrltool.cxx
@@ -0,0 +1,1019 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ctrltool.cxx,v $
+ * $Revision: 1.19 $
+ *
+ * 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>
+
+#ifndef TOOLS_DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#include <i18npool/mslangid.hxx>
+#ifndef _VCL_WINDOW_HXX
+#include <vcl/window.hxx>
+#endif
+#include <vcl/svapp.hxx>
+#include <vcl/wrkwin.hxx>
+
+#include <svtools/svtools.hrc>
+#include <svtools/svtdata.hxx>
+#include <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;
+ USHORT 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, 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;
+ 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;
+ ULONG nLow = 0;
+ ULONG nHigh = nCnt-1;
+ 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, BOOL bAll,
+ BOOL bInsertData )
+{
+ rtl_TextEncoding eSystemEncoding = gsl_getSystemTextEncoding();
+
+ USHORT nType;
+ if ( pDevice->GetOutDevType() != OUTDEV_PRINTER )
+ nType = FONTLIST_FONTNAMETYPE_SCREEN;
+ else
+ nType = FONTLIST_FONTNAMETYPE_PRINTER;
+
+ // Alle Fonts vom Device abfragen
+ int n = pDevice->GetDevFontCount();
+ USHORT 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;
+ 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 )
+ {
+ BOOL bInsert = 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 = 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, BOOL bAll ) :
+ List( 4096, sal::static_int_cast< USHORT >(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, TRUE );
+
+ // Gegebenenfalls muessen wir mit den Bildschirmfonts vergleichen,
+ // damit dort die eigentlich doppelten auf Equal mappen koennen
+ BOOL bCompareWindow = FALSE;
+ if ( !pDevice2 && (pDevice->GetOutDevType() == OUTDEV_PRINTER) )
+ {
+ bCompareWindow = 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
+ USHORT nType = pData->mnType;
+ const XubString& rStyleName = rInfo.GetStyleName();
+ if ( rStyleName.Len() )
+ {
+ BOOL bNotSynthetic = FALSE;
+ BOOL bNoneAvailable = FALSE;
+ FontWeight eWeight = rInfo.GetWeight();
+ FontItalic eItalic = rInfo.GetItalic();
+ ImplFontListFontInfo* pFontInfo = pData->mpFirst;
+ while ( pFontInfo )
+ {
+ if ( (eWeight == pFontInfo->GetWeight()) &&
+ (eItalic == pFontInfo->GetItalic()) )
+ {
+ bNotSynthetic = 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;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+USHORT 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;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL FontList::IsAvailable( const XubString& rName ) const
+{
+ return (ImplFindByName( rName ) != 0);
+}
+
+// -----------------------------------------------------------------------
+
+const FontInfo& FontList::GetFontName( USHORT nFont ) const
+{
+ DBG_ASSERT( nFont < GetFontNameCount(), "FontList::GetFontName(): nFont >= Count" );
+
+ ImplFontListNameInfo* pData = (ImplFontListNameInfo*)List::GetObject( nFont );
+ return *(pData->mpFirst);
+}
+
+// -----------------------------------------------------------------------
+
+USHORT FontList::GetFontNameType( USHORT 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 );
+
+ USHORT i;
+ USHORT 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( ULONG nIndex ) const
+{
+ String aStr;
+
+ if ( nIndex < mnElem )
+ aStr = String( mpArray[nIndex].mszUtf8Name, RTL_TEXTENCODING_UTF8 );
+
+ return aStr;
+}
+
+//------------------------------------------------------------------------
+
+long FontSizeNames::GetIndexSize( 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 100644
index 000000000000..267a65e98517
--- /dev/null
+++ b/svtools/source/control/ctrltool.src
@@ -0,0 +1,147 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ctrltool.src,v $
+ * $Revision: 1.36 $
+ *
+ * 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 100644
index 000000000000..d820dce097ed
--- /dev/null
+++ b/svtools/source/control/filectrl.cxx
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: filectrl.cxx,v $
+ * $Revision: 1.10 $
+ *
+ * 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 <filectrl.hxx>
+#ifndef _SV_FILECTRL_HRC
+#include <filectrl.hrc>
+#endif
+
+#ifndef GCC
+#endif
+
+// =======================================================================
+
+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 = TRUE;
+
+ maButton.Show();
+ maEdit.Show();
+
+ SetCompoundControl( 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) );
+ }
+
+ 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 = 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 )
+ : 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 = 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, 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 100644
index 000000000000..3a051e8196e1
--- /dev/null
+++ b/svtools/source/control/filectrl.src
@@ -0,0 +1,61 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: filectrl.src,v $
+ * $Revision: 1.11 $
+ *
+ * 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..." ;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/svtools/source/control/filectrl2.cxx b/svtools/source/control/filectrl2.cxx
new file mode 100644
index 000000000000..0ea28fbf96bd
--- /dev/null
+++ b/svtools/source/control/filectrl2.cxx
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: filectrl2.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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 <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..936f8b3e25c5
--- /dev/null
+++ b/svtools/source/control/fileurlbox.cxx
@@ -0,0 +1,127 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: fileurlbox.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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 "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..5525333e083c
--- /dev/null
+++ b/svtools/source/control/fixedhyper.cxx
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: fixedhyper.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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 100644
index 000000000000..387c1db34fc1
--- /dev/null
+++ b/svtools/source/control/fmtfield.cxx
@@ -0,0 +1,1401 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: fmtfield.cxx,v $
+ * $Revision: 1.40 $
+ *
+ * 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 <svtools/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 <svtools/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;
+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(FALSE) \
+ ,m_bHasMax(FALSE) \
+ ,m_bStrictFormat(TRUE) \
+ ,m_bValueDirty(TRUE) \
+ ,m_bEnableEmptyField(TRUE) \
+ ,m_bAutoColor(FALSE) \
+ ,m_bEnableNaN(FALSE) \
+ ,m_dCurrentValue(0) \
+ ,m_dDefaultValue(0) \
+ ,m_nFormatKey(0) \
+ ,m_pFormatter(NULL) \
+ ,m_dSpinSize(1) \
+ ,m_dSpinFirst(-1000000) \
+ ,m_dSpinLast(1000000) \
+ ,m_bTreatAsNumber(TRUE) \
+ ,m_pLastOutputColor(NULL) \
+ ,m_bUseInputStringForFormatting(false)
+
+//------------------------------------------------------------------------------
+FormattedField::FormattedField(Window* pParent, WinBits nStyle, SvNumberFormatter* pInitialFormatter, 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, 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, TRUE);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetText(const XubString& rStr)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ SpinField::SetText(rStr);
+ m_bValueDirty = TRUE;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetText( const XubString& rStr, const Selection& rNewSelection )
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ SpinField::SetText( rStr, rNewSelection );
+ m_bValueDirty = 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();
+ USHORT nNewLen = sFormatted.Len();
+ USHORT 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
+ 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 = FALSE;
+}
+
+//------------------------------------------------------------------------------
+String FormattedField::GetTextValue() const
+{
+ if (m_bValueDirty)
+ {
+ ((FormattedField*)this)->m_sCurrentTextValue = GetText();
+ ((FormattedField*)this)->m_bValueDirty = FALSE;
+ }
+ return m_sCurrentTextValue;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::EnableNotANumber( BOOL _bEnable )
+{
+ if ( m_bEnableNaN == _bEnable )
+ return;
+
+ m_bEnableNaN = _bEnable;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetAutoColor(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 = TRUE;
+ SpinField::Modify();
+ return;
+ }
+
+ String sCheck = GetText();
+ if (CheckText(sCheck))
+ {
+ m_sLastValidText = sCheck;
+ m_aLastSelection = GetSelection();
+ m_bValueDirty = 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();
+
+ USHORT nNewLen = rNew.Len();
+ USHORT 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
+ 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 = 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(ULONG nFormatKey)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ m_nFormatKey = nFormatKey;
+ 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(ULONG nFormatKey)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ BOOL bNoFormatter = (m_pFormatter == NULL);
+ ImplSetFormatKey(nFormatKey);
+ FormatChanged((bNoFormatter && (m_pFormatter != NULL)) ? FCT_FORMATTER : FCT_KEYONLY);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, 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
+ USHORT 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;
+}
+
+//------------------------------------------------------------------------------
+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)
+ {
+ USHORT nCheckPos;
+ short nType;
+ XubString rFormat(rFormatString);
+ if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
+ return FALSE;
+ DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
+ }
+
+ if (nNewKey != m_nFormatKey)
+ SetFormatKey(nNewKey);
+ return TRUE;
+}
+
+//------------------------------------------------------------------------------
+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 ?");
+
+ BOOL bThousand, IsRed;
+ USHORT nPrecision, nAnzLeading;
+ ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
+
+ return bThousand;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetThousandsSep(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
+ BOOL bThousand, IsRed;
+ USHORT 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
+ USHORT nCheckPos;
+ sal_uInt32 nNewKey;
+ short nType;
+ ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
+
+ // set the new key
+ ImplSetFormatKey(nNewKey);
+ FormatChanged(FCT_THOUSANDSSEP);
+}
+
+//------------------------------------------------------------------------------
+USHORT 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 ?");
+
+ BOOL bThousand, IsRed;
+ USHORT nPrecision, nAnzLeading;
+ ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
+
+ return nPrecision;
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::SetDecimalDigits(USHORT _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
+ BOOL bThousand, IsRed;
+ USHORT 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
+ USHORT 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 = FALSE;
+ }
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::ReFormat()
+{
+ if (!IsEmptyFieldEnabled() || GetText().Len())
+ {
+ if (TreatingAsNumber())
+ {
+ double dValue = GetValue();
+ if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
+ return;
+ ImplSetValue( dValue, TRUE );
+ }
+ else
+ SetTextFormatted(GetTextValue());
+ }
+}
+
+//------------------------------------------------------------------------------
+long FormattedField::Notify(NotifyEvent& rNEvt)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ if ((rNEvt.GetType() == EVENT_KEYINPUT) && !IsReadOnly())
+ {
+ const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
+ USHORT 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, TRUE);
+ Modify();
+ }
+ else
+ {
+ String sNew = GetTextValue();
+ if (sNew.Len())
+ SetTextFormatted(sNew);
+ else
+ SetTextFormatted(m_sDefaultText);
+ }
+ m_bValueDirty = 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 = 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 = 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(BOOL bEnable)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+ if (bEnable == m_bEnableEmptyField)
+ return;
+
+ m_bEnableEmptyField = bEnable;
+ if (!m_bEnableEmptyField && GetText().Len()==0)
+ ImplSetValue(m_dCurrentValue, TRUE);
+}
+
+//------------------------------------------------------------------------------
+void FormattedField::ImplSetValue(double dVal, 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 = 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 = FALSE;
+ DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
+}
+
+//------------------------------------------------------------------------------
+BOOL FormattedField::ImplGetValue(double& dNewVal)
+{
+ DBG_CHKTHIS(FormattedField, NULL);
+
+ dNewVal = m_dCurrentValue;
+ if (!m_bValueDirty)
+ return TRUE;
+
+ dNewVal = m_dDefaultValue;
+ String sText(GetText());
+ if (!sText.Len())
+ return 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
+ 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 FALSE;
+
+
+ if (m_bHasMin && (dNewVal<m_dMinValue))
+ dNewVal = m_dMinValue;
+ if (m_bHasMax && (dNewVal>m_dMaxValue))
+ dNewVal = m_dMaxValue;
+ return 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 = 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);
+}
+
+//------------------------------------------------------------------------------
+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 TRUE;
+
+ String sForceComplete = '_';
+ sForceComplete += sText;
+ sForceComplete += '_';
+
+ USHORT nStart = 0, nEnd = sForceComplete.Len();
+ BOOL bFound = m_pConformanceTester->SearchFrwrd(sForceComplete, &nStart, &nEnd);
+
+ if (bFound && (nStart == 0) && (nEnd == sForceComplete.Len()))
+ return TRUE;
+
+ return 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(FALSE)
+{
+ m_bPrependCurrSym = 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(FALSE)
+{
+ m_bPrependCurrSym = 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(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);
+ BOOL bThSep = GetThousandsSep();
+ USHORT 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 = TRUE;
+ SetFormat(sNewFormat, eLanguage);
+ m_bChangingFormat = FALSE;
+}
+
diff --git a/svtools/source/control/headbar.cxx b/svtools/source/control/headbar.cxx
new file mode 100644
index 000000000000..ffef998d7aad
--- /dev/null
+++ b/svtools/source/control/headbar.cxx
@@ -0,0 +1,1656 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: headbar.cxx,v $
+ * $Revision: 1.15 $
+ *
+ * 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
+{
+ USHORT mnId;
+ HeaderBarItemBits mnBits;
+ long mnSize;
+ ULONG mnHelpId;
+ 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 ((USHORT)0x0001)
+#define HEAD_HITTEST_DIVIDER ((USHORT)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 = FALSE;
+ mbItemDrag = FALSE;
+ mbOutDrag = FALSE;
+ mbItemMode = FALSE;
+
+ // StyleBits auswerten
+ if ( nWinStyle & WB_DRAG )
+ mbDragable = TRUE;
+ else
+ mbDragable = FALSE;
+ if ( nWinStyle & WB_BUTTONSTYLE )
+ mbButtonStyle = TRUE;
+ else
+ mbButtonStyle = FALSE;
+ if ( nWinStyle & WB_BORDER )
+ {
+ mnBorderOff1 = 1;
+ mnBorderOff2 = 1;
+ }
+ else
+ {
+ if ( nWinStyle & WB_BOTTOMBORDER )
+ mnBorderOff2 = 1;
+ }
+
+ ImplInitSettings( TRUE, TRUE, 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( BOOL bFont,
+ BOOL bForeground, 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( USHORT nPos ) const
+{
+ long nX = -mnOffset;
+ for ( USHORT i = 0; i < nPos; i++ )
+ nX += mpItemList->GetObject( i )->mnSize;
+ return nX;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle HeaderBar::ImplGetItemRect( USHORT 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;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT HeaderBar::ImplHitTest( const Point& rPos,
+ long& nMouseOff, USHORT& nPos ) const
+{
+ ImplHeadItem* pItem;
+ USHORT nCount = (USHORT)mpItemList->Count();
+ BOOL bLastFixed = TRUE;
+ long nX = -mnOffset;
+
+ for ( USHORT i = 0; i < nCount; i++ )
+ {
+ pItem = mpItemList->GetObject( i );
+
+ if ( rPos.X() < (nX+pItem->mnSize) )
+ {
+ USHORT 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 = TRUE;
+ else
+ bLastFixed = 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( USHORT nStartPos, USHORT 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,
+ USHORT nPos, BOOL bHigh, BOOL bDrag,
+ const Rectangle& rItemRect,
+ const Rectangle* pRect,
+ 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, TRUE, FALSE, FALSE, &aSelectionTextColor );
+ else if ( !mbButtonStyle || (nBits & HIB_FLAT) )
+ DrawSelectionBackground( aRect, 0, TRUE, FALSE, 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
+ BOOL bLeftText = 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 = 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() )
+ {
+ USHORT 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
+ BOOL bDraw = TRUE;
+ if ( nArrowX < aRect.Left()+HEADERBAR_TEXTOFF )
+ bDraw = FALSE;
+ else if ( nArrowX+HEAD_ARROWSIZE2 > aRect.Right() )
+ bDraw = 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( USHORT nPos, BOOL bHigh, BOOL bDrag,
+ const Rectangle* pRect )
+{
+ Rectangle aRect = ImplGetItemRect( nPos );
+ ImplDrawItem( this, nPos, bHigh, bDrag, aRect, pRect, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplUpdate( USHORT nPos, BOOL bEnd, BOOL bDirect )
+{
+ if ( IsVisible() && IsUpdateMode() )
+ {
+ if ( !bDirect )
+ {
+ Rectangle aRect;
+ USHORT nItemCount = (USHORT)(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 ( USHORT i = nPos; i < mpItemList->Count(); i++ )
+ ImplDrawItem( i );
+ if ( bEnd )
+ {
+ Rectangle aRect = ImplGetItemRect( (USHORT)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, BOOL bCommand )
+{
+ USHORT nPos;
+ USHORT nHitTest = ImplHitTest( rMousePos, mnMouseOff, nPos );
+ if ( nHitTest )
+ {
+ mbDrag = FALSE;
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( nHitTest & HEAD_HITTEST_DIVIDER )
+ mbDrag = TRUE;
+ else
+ {
+ if ( ((pItem->mnBits & HIB_CLICKABLE) && !(pItem->mnBits & HIB_FLAT)) ||
+ (mbDragable && !(pItem->mnBits & HIB_FIXEDPOS)) )
+ {
+ mbItemMode = TRUE;
+ mbDrag = TRUE;
+ if ( bCommand )
+ {
+ if ( mbDragable )
+ mbItemDrag = TRUE;
+ else
+ {
+ mbItemMode = FALSE;
+ mbDrag = FALSE;
+ }
+ }
+ }
+ else
+ {
+ if ( !bCommand )
+ {
+ mnCurItemId = pItem->mnId;
+ Select();
+ mnCurItemId = 0;
+ }
+ }
+ }
+
+ if ( mbDrag )
+ {
+ mbOutDrag = FALSE;
+ mnCurItemId = pItem->mnId;
+ mnItemDragPos = nPos;
+ StartTracking();
+ mnStartPos = rMousePos.X()-mnMouseOff;
+ mnDragPos = mnStartPos;
+ StartDrag();
+ if ( mbItemMode )
+ ImplDrawItem( nPos, TRUE, mbItemDrag );
+ else
+ {
+ Rectangle aSizeRect( mnDragPos, 0, mnDragPos, mnDragSize+mnDY );
+ ShowTracking( aSizeRect, SHOWTRACK_SPLIT );
+ }
+ }
+ else
+ mnMouseOff = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::ImplDrag( const Point& rMousePos )
+{
+ BOOL bNewOutDrag;
+ USHORT nPos = GetItemPos( mnCurItemId );
+
+ mnDragPos = rMousePos.X()-mnMouseOff;
+ if ( mbItemMode )
+ {
+ Rectangle aItemRect = ImplGetItemRect( nPos );
+ if ( aItemRect.IsInside( rMousePos ) )
+ bNewOutDrag = FALSE;
+ else
+ bNewOutDrag = TRUE;
+
+ // Evt. ItemDrag anschalten
+ if ( bNewOutDrag && mbDragable && !mbItemDrag &&
+ !(mpItemList->GetObject(nPos)->mnBits & HIB_FIXEDPOS) )
+ {
+ if ( (rMousePos.Y() >= aItemRect.Top()) && (rMousePos.Y() <= aItemRect.Bottom()) )
+ {
+ mbItemDrag = TRUE;
+ ImplDrawItem( nPos, TRUE, mbItemDrag );
+ }
+ }
+
+ USHORT nOldItemDragPos = mnItemDragPos;
+ if ( mbItemDrag )
+ {
+ if ( (rMousePos.Y() < -HEADERBAR_DRAGOUTOFF) || (rMousePos.Y() > mnDY+HEADERBAR_DRAGOUTOFF) )
+ bNewOutDrag = TRUE;
+ else
+ bNewOutDrag = FALSE;
+
+ if ( bNewOutDrag )
+ mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
+ else
+ {
+ USHORT 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, FALSE, 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( BOOL bCancel )
+{
+ HideTracking();
+
+ if ( bCancel || mbOutDrag )
+ {
+ if ( mbItemMode && (!mbOutDrag || mbItemDrag) )
+ {
+ USHORT nPos = GetItemPos( mnCurItemId );
+ ImplDrawItem( nPos );
+ }
+
+ mnCurItemId = 0;
+ }
+ else
+ {
+ USHORT 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, TRUE );
+ }
+ }
+ }
+
+ mbDrag = FALSE;
+ EndDrag();
+ mnCurItemId = 0;
+ mnItemDragPos = HEADERBAR_ITEM_NOTFOUND;
+ mbOutDrag = FALSE;
+ mbItemMode = FALSE;
+ mbItemDrag = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ {
+ if ( rMEvt.GetClicks() == 2 )
+ {
+ long nTemp;
+ USHORT nPos;
+ USHORT nHitTest = ImplHitTest( rMEvt.GetPosPixel(), nTemp, nPos );
+ if ( nHitTest )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( nHitTest & HEAD_HITTEST_DIVIDER )
+ mbItemMode = FALSE;
+ else
+ mbItemMode = TRUE;
+ mnCurItemId = pItem->mnId;
+ DoubleClick();
+ mbItemMode = FALSE;
+ mnCurItemId = 0;
+ }
+ }
+ else
+ ImplStartDrag( rMEvt.GetPosPixel(), FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::MouseMove( const MouseEvent& rMEvt )
+{
+ long nTemp1;
+ USHORT nTemp2;
+ PointerStyle eStyle = POINTER_ARROW;
+ USHORT 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 ) );
+ }
+ }
+
+ USHORT nCurItemPos;
+ if ( mbDrag )
+ nCurItemPos = GetItemPos( mnCurItemId );
+ else
+ nCurItemPos = HEADERBAR_ITEM_NOTFOUND;
+ USHORT nItemCount = (USHORT)mpItemList->Count();
+ for ( USHORT i = 0; i < nItemCount; i++ )
+ ImplDrawItem( i, (i == nCurItemPos) ? TRUE : FALSE, FALSE, &rRect );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize,
+ 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()--;
+ USHORT nItemCount = (USHORT)mpItemList->Count();
+ for ( USHORT 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, FALSE, 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(), TRUE );
+ return;
+ }
+
+ Window::Command( rCEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT 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 )
+ {
+ ULONG nHelpId = GetHelpId( nItemId );
+ if ( nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( nHelpId, 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( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, 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( TRUE, TRUE, 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( USHORT nItemId, const Image& rImage,
+ long nSize, HeaderBarItemBits nBits, USHORT 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, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::InsertItem( USHORT nItemId, const XubString& rText,
+ long nSize, HeaderBarItemBits nBits, USHORT 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->mnHelpId = 0;
+ pItem->maText = rText;
+ pItem->mpUserData = 0;
+ mpItemList->Insert( pItem, nPos );
+
+ // Ausgabe updaten
+ ImplUpdate( nPos, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::InsertItem( USHORT nItemId,
+ const Image& rImage, const XubString& rText,
+ long nSize, HeaderBarItemBits nBits,
+ USHORT 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->mnHelpId = 0;
+ pItem->maImage = rImage;
+ pItem->maText = rText;
+ pItem->mpUserData = 0;
+ mpItemList->Insert( pItem, nPos );
+
+ // Ausgabe updaten
+ ImplUpdate( nPos, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::RemoveItem( USHORT nItemId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ ImplHeadItem* pItem = mpItemList->Remove( nPos );
+ delete pItem;
+ ImplUpdate( nPos, TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::MoveItem( USHORT nItemId, USHORT nNewPos )
+{
+ USHORT 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, TRUE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::Clear()
+{
+ // Alle Items loeschen
+ ImplHeadItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ delete pItem;
+ pItem = mpItemList->Next();
+ }
+ mpItemList->Clear();
+
+ ImplUpdate( 0, 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 );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT HeaderBar::GetItemCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT HeaderBar::GetItemPos( USHORT nItemId ) const
+{
+ ImplHeadItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return (USHORT)mpItemList->GetCurPos();
+ pItem = mpItemList->Next();
+ }
+
+ return HEADERBAR_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT HeaderBar::GetItemId( USHORT nPos ) const
+{
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT HeaderBar::GetItemId( const Point& rPos ) const
+{
+ USHORT nPos = 0;
+ while ( nPos < mpItemList->Count() )
+ {
+ if ( ImplGetItemRect( nPos ).IsInside( rPos ) )
+ return GetItemId( nPos );
+
+ nPos++;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle HeaderBar::GetItemRect( USHORT nItemId ) const
+{
+ Rectangle aRect;
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ aRect = ImplGetItemRect( nPos );
+ return aRect;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemSize( USHORT nItemId, long nNewSize )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem->mnSize != nNewSize )
+ {
+ pItem->mnSize = nNewSize;
+ ImplUpdate( nPos, TRUE );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long HeaderBar::GetItemSize( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnSize;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemBits( USHORT nItemId, HeaderBarItemBits nNewBits )
+{
+ USHORT 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( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemData( USHORT nItemId, void* pNewData )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ mpItemList->GetObject( nPos )->mpUserData = pNewData;
+ ImplUpdate( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* HeaderBar::GetItemData( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mpUserData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemImage( USHORT nItemId, const Image& rImage )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ mpItemList->GetObject( nPos )->maImage = rImage;
+ ImplUpdate( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+Image HeaderBar::GetItemImage( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetItemText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ mpItemList->GetObject( nPos )->maText = rText;
+ ImplUpdate( nPos );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+XubString HeaderBar::GetItemText( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maText;
+ else
+ return String();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetHelpText( USHORT nItemId, const XubString& rText )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+XubString HeaderBar::GetHelpText( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ {
+ ImplHeadItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId, this );
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return XubString();
+}
+
+// -----------------------------------------------------------------------
+
+void HeaderBar::SetHelpId( USHORT nItemId, ULONG nHelpId )
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ mpItemList->GetObject( nPos )->mnHelpId = nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG HeaderBar::GetHelpId( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+ if ( nPos != HEADERBAR_ITEM_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnHelpId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+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..7d7477130e0d
--- /dev/null
+++ b/svtools/source/control/hyperlabel.cxx
@@ -0,0 +1,273 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: hyperlabel.cxx,v $
+ * $Revision: 1.11 $
+ *
+ * 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 100644
index 000000000000..49096144b215
--- /dev/null
+++ b/svtools/source/control/indexentryres.cxx
@@ -0,0 +1,136 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: indexentryres.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * 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 <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 100644
index 000000000000..4a01a03ad759
--- /dev/null
+++ b/svtools/source/control/inettbc.cxx
@@ -0,0 +1,1379 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: inettbc.cxx,v $
+ * $Revision: 1.12 $
+ *
+ * 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>
+
+#ifndef _COM_SUN_STAR_TASK_XINTERACTIONHANDLER_HDL_
+#include <com/sun/star/task/XInteractionHandler.hdl>
+#endif
+#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>
+
+#ifndef _UNOTOOLS_PROCESSFACTORY_HXX
+#include <comphelper/processfactory.hxx>
+#endif
+
+#include <vcl/toolbox.hxx>
+#ifndef _VOS_THREAD_HXX //autogen
+#include <vos/thread.hxx>
+#endif
+#ifndef _VOS_MUTEX_HXX //autogen
+#include <vos/mutex.hxx>
+#endif
+#include <vcl/svapp.hxx>
+#include <svtools/historyoptions.hxx>
+#include <svtools/eitem.hxx>
+#include <svtools/stritem.hxx>
+#include <svtools/cancel.hxx>
+#include <svtools/itemset.hxx>
+#include "urihelper.hxx"
+#include <svtools/pathoptions.hxx>
+
+#define _SVSTDARR_STRINGSDTOR
+#include <svtools/svstdarr.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <ucbhelper/content.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <unotools/ucbhelper.hxx>
+
+#include "iodlg.hrc"
+#include <asynclink.hxx>
+#include <svtools/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;
+ BOOL bStop;
+ BOOL bOnlyDirectories;
+ 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, BOOL bForce = FALSE);
+ void ReadFolder( const String& rURL, const String& rMatch, 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( 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, (USHORT) nItem );
+ break;
+ }
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+void SAL_CALL SvtMatchContext_Impl::Cancel()
+{
+ // Cancel button pressed
+ terminate();
+}
+
+//-------------------------------------------------------------------------
+void SvtMatchContext_Impl::Stop()
+{
+ bStop = 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 = 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( USHORT 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,
+ BOOL bForce )
+{
+ if( !bForce )
+ {
+ // avoid doubles
+ for( USHORT 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,
+ 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, 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 ), 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 = 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
+ USHORT 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;
+
+ BOOL bFull = 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( USHORT 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.CompareTo( 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.CompareTo( 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 = TRUE;
+ else
+ break;
+ }
+
+ return;
+}
+
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+void SvtURLBox::TryAutoComplete( BOOL bForce )
+{
+ if( Application::AnyInput( INPUT_KEYBOARD ) ) return;
+
+ String aMatchString;
+ String aCurText = GetText();
+ Selection aSelection( GetSelection() );
+ if( aSelection.Max() != aCurText.Len() && !bForce )
+ return;
+ USHORT nLen = (USHORT)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( FALSE ),
+ bOnlyDirectories( FALSE ),
+ bTryAutoComplete( FALSE ),
+ bCtrlClick( FALSE ),
+ bHistoryDisabled( FALSE ),
+ bNoSelection( FALSE ),
+ bIsAutoCompleteEnabled( 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( FALSE ),
+ bOnlyDirectories( FALSE ),
+ bTryAutoComplete( FALSE ),
+ bCtrlClick( FALSE ),
+ bHistoryDisabled( FALSE ),
+ bNoSelection( FALSE ),
+ bIsAutoCompleteEnabled( TRUE )
+{
+ ImplInit();
+}
+
+//-------------------------------------------------------------------------
+SvtURLBox::SvtURLBox( Window* pParent, const ResId& _rResId, INetProtocol eSmart )
+ : ComboBox( pParent , _rResId ),
+ pCtx( 0 ),
+ eSmartProtocol( eSmart ),
+ bAutoCompleteMode( FALSE ),
+ bOnlyDirectories( FALSE ),
+ bTryAutoComplete( FALSE ),
+ bCtrlClick( FALSE ),
+ bHistoryDisabled( FALSE ),
+ bNoSelection( FALSE ),
+ bIsAutoCompleteEnabled( TRUE )
+{
+ ImplInit();
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::ImplInit()
+{
+ pImp = new SvtURLBox_Impl();
+ SetHelpId( SID_OPENURL );
+ EnableAutocomplete( 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 ) ) )
+ {
+ 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;
+ }
+ }
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+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 = FALSE;
+ Selection aSelection( GetSelection() );
+ SetSelection( Selection( aSelection.Min(), aSelection.Min() ) );
+ if ( bOnlyDirectories )
+ Clear();
+ else
+ UpdatePicklistForSmartProtocol_Impl();
+ Resize();
+ }
+
+ bCtrlClick = rKey.IsMod1();
+ BOOL bHandled = FALSE;
+ if ( GetOpenHdl().IsSet() )
+ {
+ bHandled = TRUE;
+ GetOpenHdl().Call(this);
+ }
+ else if ( GetSelectHdl().IsSet() )
+ {
+ bHandled = TRUE;
+ GetSelectHdl().Call(this);
+ }
+
+ bCtrlClick = FALSE;
+
+ ClearModifyFlag();
+ return bHandled;
+ }
+ else if ( aCode == KEY_RETURN && !GetText().Len() && GetOpenHdl().IsSet() )
+ {
+ // for file dialog
+ bAutoCompleteMode = FALSE;
+ GetOpenHdl().Call(this);
+ return 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 FALSE;
+ }
+
+ bAutoCompleteMode = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ return 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 TRUE;
+ }
+ else if( ( aCode == KEY_UP || aCode == KEY_DOWN ) && !rKey.IsMod2() )
+ {
+ Selection aSelection( GetSelection() );
+ USHORT nLen = (USHORT)aSelection.Min();
+ GetSubEdit()->KeyInput( rEvent );
+ SetSelection( Selection( nLen, GetText().Len() ) );
+ return 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( 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( BOOL bDir )
+{
+ bOnlyDirectories = bDir;
+ if ( bOnlyDirectories )
+ Clear();
+}
+
+//-------------------------------------------------------------------------
+void SvtURLBox::SetNoURLSelection( 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( USHORT 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 = 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/makefile.mk b/svtools/source/control/makefile.mk
new file mode 100644
index 000000000000..10bb6beb50e4
--- /dev/null
+++ b/svtools/source/control/makefile.mk
@@ -0,0 +1,89 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.19 $
+#
+# 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.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=svtools
+TARGET=ctrl
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/svt.pmk
+
+# --- Files --------------------------------------------------------
+
+SRS1NAME=$(TARGET)
+SRC1FILES=\
+ ctrltool.src \
+ ctrlbox.src \
+ calendar.src \
+ filectrl.src
+
+EXCEPTIONSFILES=\
+ $(SLO)$/filectrl2.obj \
+ $(SLO)$/roadmap.obj \
+ $(SLO)$/scriptedtext.obj\
+ $(SLO)$/fmtfield.obj \
+ $(SLO)$/inettbc.obj \
+ $(SLO)$/valueacc.obj
+
+SLOFILES=\
+ $(EXCEPTIONSFILES) \
+ $(SLO)$/asynclink.obj \
+ $(SLO)$/urlcontrol.obj \
+ $(SLO)$/fileurlbox.obj \
+ $(SLO)$/ctrltool.obj \
+ $(SLO)$/ctrlbox.obj \
+ $(SLO)$/stdctrl.obj \
+ $(SLO)$/stdmenu.obj \
+ $(SLO)$/valueset.obj \
+ $(SLO)$/tabbar.obj \
+ $(SLO)$/headbar.obj \
+ $(SLO)$/prgsbar.obj \
+ $(SLO)$/ruler.obj \
+ $(SLO)$/taskbar.obj \
+ $(SLO)$/taskbox.obj \
+ $(SLO)$/taskstat.obj \
+ $(SLO)$/taskmisc.obj \
+ $(SLO)$/calendar.obj \
+ $(SLO)$/filectrl.obj \
+ $(SLO)$/scrwin.obj \
+ $(SLO)$/reginfo.obj \
+ $(SLO)$/collatorres.obj \
+ $(SLO)$/indexentryres.obj \
+ $(SLO)$/hyperlabel.obj \
+ $(SLO)$/fixedhyper.obj
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/svtools/source/control/prgsbar.cxx b/svtools/source/control/prgsbar.cxx
new file mode 100644
index 000000000000..b6702e93af4d
--- /dev/null
+++ b/svtools/source/control/prgsbar.cxx
@@ -0,0 +1,265 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: prgsbar.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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
+
+#ifndef _TOOLS_DEBUGS_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _VCL_STATUS_HXX
+#include <vcl/status.hxx>
+#endif
+#include <prgsbar.hxx>
+
+// =======================================================================
+
+#define PROGRESSBAR_OFFSET 3
+#define PROGRESSBAR_WIN_OFFSET 2
+
+// =======================================================================
+
+void ProgressBar::ImplInit()
+{
+ mnPercent = 0;
+ mbCalcNew = TRUE;
+
+ ImplInitSettings( TRUE, TRUE, 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( BOOL bFont,
+ BOOL bForeground, 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( TRUE );
+ SetPaintTransparent( 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( USHORT nOldPerc, USHORT nNewPerc )
+{
+ if ( mbCalcNew )
+ {
+ mbCalcNew = 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);
+ USHORT nMaxCount = (USHORT)(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 = TRUE;
+ if ( IsReallyVisible() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::SetValue( USHORT nNewPercent )
+{
+ DBG_ASSERTWARNING( nNewPercent <= 100, "StatusBar::SetProgressValue(): nPercent > 100" );
+
+ if ( nNewPercent < mnPercent )
+ {
+ mbCalcNew = 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( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else
+*/
+ if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+
+ Window::StateChanged( nType );
+}
+
+// -----------------------------------------------------------------------
+
+void ProgressBar::DataChanged( const DataChangedEvent& rDCEvt )
+{
+ if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
+ (rDCEvt.GetFlags() & SETTINGS_STYLE) )
+ {
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+
+ Window::DataChanged( rDCEvt );
+}
+
diff --git a/svtools/source/control/reginfo.cxx b/svtools/source/control/reginfo.cxx
new file mode 100644
index 000000000000..24daba5e6123
--- /dev/null
+++ b/svtools/source/control/reginfo.cxx
@@ -0,0 +1,375 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: reginfo.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * 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 "reginfo.hxx"
+#include <tools/debug.hxx>
+#include <osl/thread.h>
+
+#define MAXREGVALUE 200
+
+// *****************************************************************************
+#if defined(WIN) || defined(WNT)
+
+#include <tools/svwin.h>
+
+#define DBG_HDL DBG_ASSERT(pImp->bValidGroup, "Keine Gruppe gesetzt"); \
+ if( !pImp->bValidGroup ) return
+
+struct RegInfo_Impl
+{
+ HKEY aGroupHdl;
+ BOOL bValidGroup;
+};
+
+RegInfo::RegInfo()
+{
+ pImp=new RegInfo_Impl;
+ pImp->bValidGroup = FALSE;
+}
+
+RegInfo::~RegInfo()
+{
+ if(pImp->bValidGroup)
+ RegCloseKey( pImp->aGroupHdl );
+ delete pImp;
+}
+
+String RegInfo::GetKeyName( USHORT nKey ) const
+{
+ DBG_HDL String::EmptyString();
+ char aBuffer[MAXREGVALUE];
+ RegEnumKey( pImp->aGroupHdl, nKey, aBuffer, MAXREGVALUE );
+ return String( UniString::CreateFromAscii(aBuffer) );
+}
+
+USHORT RegInfo::GetKeyCount() const
+{
+ DBG_HDL 0;
+#ifdef WNT
+ DWORD nKeys;
+ DWORD Dum1=10, Dum2, Dum3, Dum4, Dum5, Dum6, Dum7;
+ char s[10];
+ FILETIME aDumFileTime;
+ RegQueryInfoKey( pImp->aGroupHdl, s, &Dum1, 0, &nKeys, &Dum2, &Dum3,
+ &Dum4, &Dum5, &Dum6, &Dum7, &aDumFileTime );
+ return (USHORT) nKeys;
+#else
+ char aBuffer[MAXREGVALUE];
+ USHORT n=0;
+ while(RegEnumKey(
+ pImp->aGroupHdl, n, aBuffer, MAXREGVALUE) == ERROR_SUCCESS)
+ n++;
+ return n;
+#endif
+}
+
+inline String MakeAppGroupString_Impl( const String &rGroup )
+{
+ String aGroup( UniString::CreateFromAscii("SvAppGroups\\") );
+ aGroup+=rGroup;
+ return aGroup;
+}
+
+void RegInfo::SetAppGroup( const String& rGroup )
+{
+ aCurrentGroup = MakeAppGroupString_Impl(rGroup);
+ if( pImp->bValidGroup )
+ {
+ RegCloseKey( pImp->aGroupHdl );
+ pImp->bValidGroup = FALSE;
+ }
+ ByteString aBStr( aCurrentGroup, osl_getThreadTextEncoding() );
+ RegCreateKey( HKEY_CLASSES_ROOT, aBStr.GetBuffer(), &pImp->aGroupHdl );
+ pImp->bValidGroup = TRUE;
+}
+
+void RegInfo::DeleteAppGroup( const String &rGroup )
+{
+ String aOldGroup = aCurrentGroup;
+ SetAppGroup( rGroup );
+ DBG_HDL;
+ USHORT nMax = GetKeyCount();
+ for( USHORT n = nMax; n--; )
+ {
+ String aKey( GetKeyName( n ));
+ DeleteKey( aKey );
+ }
+ RegCloseKey( pImp->aGroupHdl );
+
+ ByteString aBStr( rGroup, osl_getThreadTextEncoding() );
+ RegDeleteKey( HKEY_CLASSES_ROOT, aBStr.GetBuffer() );
+ pImp->bValidGroup = FALSE;
+ if( rGroup != aOldGroup )
+ SetAppGroup( aOldGroup );
+}
+
+BOOL ReadKey_Impl( const String& rKey,
+ HKEY aHdl, String& rResult )
+{
+ char s[MAXREGVALUE];
+ LONG aLen=MAXREGVALUE;
+
+ ByteString aBStr( rKey, osl_getThreadTextEncoding() );
+ LONG nRes = RegQueryValue( aHdl, aBStr.GetBuffer(), s, &aLen);
+ if(nRes == ERROR_SUCCESS)
+ {
+ rResult = UniString::CreateFromAscii(s);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+String RegInfo::ReadKey( const String& rKey ) const
+{
+ DBG_HDL String::EmptyString();
+ String aRes;
+ if(ReadKey_Impl( rKey, pImp->aGroupHdl, aRes))
+ return aRes;
+ else
+ return String::EmptyString();
+}
+
+String RegInfo::ReadKey( const String& rKey, const String &rDefault ) const
+{
+ DBG_HDL String::EmptyString();
+ String aRes;
+ if(ReadKey_Impl( rKey, pImp->aGroupHdl, aRes))
+ return aRes;
+ else
+ return rDefault;
+}
+
+void RegInfo::WriteKey( const String& rKey, const String& rValue )
+{
+ DBG_HDL;
+ ByteString aBStr( rKey, osl_getThreadTextEncoding() );
+ ByteString aBStr1( rValue, osl_getThreadTextEncoding() );
+ RegSetValue( pImp->aGroupHdl, aBStr.GetBuffer(), REG_SZ, aBStr1.GetBuffer(), 0);
+}
+
+
+void RegInfo::DeleteKey( const String& rKey )
+{
+ DBG_HDL;
+ ByteString aBStr( rKey, osl_getThreadTextEncoding() );
+ RegDeleteKey( pImp->aGroupHdl, aBStr.GetBuffer() );
+}
+
+// *****************************************************************************
+#elif defined(OS2)
+
+#define INCL_WINSHELLDATA
+#include <svpm.h>
+
+struct RegInfo_Impl
+{
+ char *pKeyList;
+ String aCurrentApp;
+ void BuildKeyList( const String &rGroup );
+};
+
+void RegInfo_Impl::BuildKeyList( const String &rGroup )
+{
+ ByteString aBStr( rGroup, osl_getThreadTextEncoding() );
+ USHORT nLen = 0;
+ do
+ {
+ nLen+=1000;
+ delete[] pKeyList;
+ pKeyList = new char[nLen];
+ *(int *)pKeyList = 0;
+ }
+ while( PrfQueryProfileString(
+ HINI_USERPROFILE, (PCSZ)aBStr.GetBuffer(),
+ 0, 0, pKeyList, nLen) == nLen);
+}
+
+
+RegInfo::RegInfo()
+{
+ pImp=new RegInfo_Impl;
+ pImp->pKeyList = 0;
+}
+
+RegInfo::~RegInfo()
+{
+ delete[] pImp->pKeyList;
+ delete pImp;
+}
+
+inline String MakeAppGroupString_Impl( const String &rGroup )
+{
+ String aGroup(UniString::CreateFromAscii("SvAppGroups:"));
+ aGroup+=rGroup;
+ return aGroup;
+}
+
+String RegInfo::GetKeyName( USHORT nKey ) const
+{
+ if( !pImp->pKeyList )
+ pImp->BuildKeyList(pImp->aCurrentApp);
+
+ const char *pc=pImp->pKeyList;
+ for( USHORT n=0; n<nKey; n++ )
+ while(*pc++);
+
+ return String(UniString::CreateFromAscii(pc));
+}
+
+USHORT RegInfo::GetKeyCount() const
+{
+ if( !pImp->pKeyList )
+ pImp->BuildKeyList( pImp->aCurrentApp);
+
+ const char *pc=pImp->pKeyList;
+ USHORT nRet=0;
+ while(*pc)
+ {
+ while(*pc++);
+ nRet++;
+ }
+ return nRet;
+}
+
+void RegInfo::SetAppGroup( const String& rGroup )
+{
+ delete[] pImp->pKeyList;
+ pImp->pKeyList = 0;
+ aCurrentGroup = rGroup;
+ pImp->aCurrentApp = MakeAppGroupString_Impl( rGroup );
+}
+
+void RegInfo::DeleteAppGroup( const String &rGroup )
+{
+ ByteString aBStr( MakeAppGroupString_Impl( rGroup ), osl_getThreadTextEncoding() );
+ PrfWriteProfileString(
+ HINI_USERPROFILE, (PCSZ)aBStr.GetBuffer(), 0, 0);
+}
+
+
+String RegInfo::ReadKey( const String& rKey ) const
+{
+ ULONG ulBufferMax = MAXREGVALUE;
+ char *pBuffer= new char[MAXREGVALUE];
+ ByteString aBStr( pImp->aCurrentApp, osl_getThreadTextEncoding() );
+ ByteString aBStr1( rKey, osl_getThreadTextEncoding() );
+ *pBuffer=0;
+ PrfQueryProfileData(
+ HINI_USERPROFILE, (PCSZ)aBStr.GetBuffer(), (PCSZ)aBStr1.GetBuffer(), pBuffer, &ulBufferMax);
+ String aRet(UniString::CreateFromAscii(pBuffer));
+ delete[] pBuffer;
+ return aRet;
+}
+
+
+String RegInfo::ReadKey( const String& rKey, const String &rDefault ) const
+{
+ String aResult = ReadKey(rKey);
+ if (!aResult.Len())
+ return rDefault;
+ else
+ return aResult;
+}
+
+
+void RegInfo::WriteKey( const String& rKey, const String& rValue )
+{
+ ByteString aBStr( pImp->aCurrentApp, osl_getThreadTextEncoding() );
+ ByteString aBStr1( rKey, osl_getThreadTextEncoding() );
+ PrfWriteProfileData(
+ HINI_USERPROFILE, (PCSZ)aBStr.GetBuffer(), (PCSZ)aBStr1.GetBuffer(), (PVOID)rValue.GetBuffer(), rValue.Len()*2);
+}
+
+void RegInfo::DeleteKey( const String& rKey )
+{
+ ByteString aBStr( pImp->aCurrentApp, osl_getThreadTextEncoding() );
+ ByteString aBStr1( rKey, osl_getThreadTextEncoding() );
+ PrfWriteProfileString(
+ HINI_USERPROFILE, (PCSZ)aBStr.GetBuffer(), (PCSZ)rKey.GetBuffer(), 0);
+}
+
+// *****************************************************************************
+
+#else
+
+RegInfo::RegInfo()
+{
+}
+
+
+RegInfo::~RegInfo()
+{
+}
+
+String RegInfo::GetKeyName( USHORT ) const
+{
+ return String::EmptyString();
+}
+
+USHORT RegInfo::GetKeyCount() const
+{
+ return 0;
+}
+
+void RegInfo::SetAppGroup( const String& )
+{
+ return ;
+}
+
+void RegInfo::DeleteAppGroup( const String& )
+{
+ return;
+}
+
+String RegInfo::ReadKey( const String& ) const
+{
+ return String::EmptyString();
+}
+
+String RegInfo::ReadKey( const String&, const String& ) const
+{
+ return String::EmptyString();
+}
+
+void RegInfo::WriteKey( const String&, const String& )
+{
+ return;
+}
+
+void RegInfo::DeleteKey( const String& )
+{
+ return;
+}
+
+#endif
diff --git a/svtools/source/control/roadmap.cxx b/svtools/source/control/roadmap.cxx
new file mode 100644
index 000000000000..693bca733813
--- /dev/null
+++ b/svtools/source/control/roadmap.cxx
@@ -0,0 +1,1028 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: roadmap.cxx,v $
+ * $Revision: 1.16.56.1 $
+ *
+ * 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 <roadmap.hxx>
+
+#ifndef _STRING_HXX
+#define _STRING_HXX
+#endif
+
+#ifndef __SGI_STL_VECTOR
+#include <vector>
+#endif
+
+#include <algorithm>
+#include <vcl/bitmap.hxx>
+#include <tools/color.hxx>
+
+#ifndef _RTL_USTRING_HXX_
+#include <rtl/OUString.hxx>
+#endif
+#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, USHORT nFlags );
+ void Enable( BOOL bEnable = TRUE);
+ 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, USHORT nFlags )
+ {
+ if (pRefRoadmapHyperLabel == NULL)
+ mpDescription->SetZOrder( NULL, nFlags); //WINDOW_ZORDER_FIRST );
+ else
+ mpDescription->SetZOrder( pRefRoadmapHyperLabel->mpDescription, nFlags); //, WINDOW_ZORDER_BEHIND );
+ }
+
+ //---------------------------------------------------------------------
+ void RoadmapItem::Enable( BOOL _bEnable)
+ {
+ mpID->Enable(_bEnable);
+ mpDescription->Enable(_bEnable);
+ }
+
+ //---------------------------------------------------------------------
+ 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 100644
index 000000000000..c3f10f1866aa
--- /dev/null
+++ b/svtools/source/control/ruler.cxx
@@ -0,0 +1,3184 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ruler.cxx,v $
+ * $Revision: 1.27 $
+ *
+ * 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 <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;
+ USHORT nLines;
+ USHORT nArrows;
+ USHORT nBorders;
+ USHORT nIndents;
+ USHORT nTabs;
+ USHORT nMargin1Style;
+ USHORT nMargin2Style;
+ BOOL bAutoPageWidth;
+ 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
+ USHORT 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;
+ USHORT nAryPos;
+ USHORT mnDragSize;
+ BOOL bSize;
+ BOOL bSizeBar;
+ BOOL bExpandTest;
+ ImplRulerHitTest() :
+ bExpandTest( FALSE ) {}
+};
+
+// =======================================================================
+
+ImplRulerData::ImplRulerData()
+{
+ memset( this, 0, sizeof( ImplRulerData ) );
+
+ // PageBreite == EditWinBreite
+ bAutoPageWidth = 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( 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 = TRUE; // Muessen Pagebreiten neu berechnet werden
+ mbFormat = TRUE; // Muss neu ausgegeben werden
+ mbDrag = FALSE; // Sind wir im Drag-Modus
+ mbDragDelete = FALSE; // Wird Maus beim Draggen unten rausgezogen
+ mbDragCanceled = FALSE; // Wurde Dragging abgebrochen
+ mbAutoWinWidth = TRUE; // EditWinBreite == RulerBreite
+ mbActive = 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( TRUE, TRUE, 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 );
+}
+
+// -----------------------------------------------------------------------
+
+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( 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 ( USHORT 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;
+ BOOL bNoTicks = FALSE;
+
+ // Groessenvorberechnung
+ BOOL bVertRight = FALSE;
+ if ( mnWinStyle & WB_HORZ )
+ nTickWidth = aPixSize.Width();
+ else
+ {
+ Font aFont = GetFont();
+ if ( mnWinStyle & WB_RIGHT_ALIGNED )
+ {
+ aFont.SetOrientation( 2700 );
+ bVertRight = 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 *= -1;
+ nMaxWidth /= aImplRulerUnitTab[mnUnitIndex].nTickUnit;
+ UniString aNumStr( UniString::CreateFromInt32( nMaxWidth ) );
+ long nTxtWidth = GetTextWidth( aNumStr );
+ if ( (nTxtWidth*2) > nTickWidth )
+ {
+ long nMulti = 1;
+ long nOrgTick3 = nTick3;
+ long nTextOff = 2;
+ while ( nTickWidth < nTxtWidth+nTextOff )
+ {
+ long nOldMulti = nMulti;
+ if ( !nTickWidth )
+ 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 = TRUE;
+ break;
+ }
+ if ( nMulti >= 100 )
+ nTextOff = 4;
+ 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 )
+ {
+ // Nur 0 malen, wenn Margin1 nicht gleich dem NullPunkt ist
+ 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 - Ausgabe (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;
+ if ( nX < nMax )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ nX -= nTxtWidth2;
+ else
+ nX += nTxtWidth2;
+ ImplVDrawText( nX, nY, aNumStr );
+ }
+ nX = nStart-n;
+ if ( nX > nMin )
+ {
+ if ( mnWinStyle & WB_HORZ )
+ nX -= nTxtWidth2;
+ else
+ nX += nTxtWidth2;
+ ImplVDrawText( nX, nY, aNumStr );
+ }
+ }
+ // Tick/Tick2 - Ausgabe (Striche)
+ 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( ((ULONG)nTick + (ULONG)nTickCount) > (ULONG)LONG_MAX)
+ break;
+ nTick += nTickCount;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawArrows( long nCenter )
+{
+ USHORT i;
+ long n1;
+ long n2;
+ long n3;
+ long n4;
+ long nLogWidth;
+ String aStr;
+ String aStr2;
+ 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, TRUE, FALSE );
+
+ // Einheit an den String haengen
+ aStr2 = aStr;
+ aStr2.AppendAscii( aImplRulerUnitTab[mnUnitIndex].aUnitStr );
+
+ // Textbreite ermitteln
+ bDrawUnit = 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 = 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;
+ USHORT 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, USHORT nStyle )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Point aPos1;
+ Point aPos2;
+ USHORT 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 )
+{
+ USHORT 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;
+
+ USHORT nStyle = mpData->pIndents[j].nStyle;
+ USHORT 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(USHORT 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, USHORT nTabStyle )
+{
+ 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, 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, USHORT nStyle, WinBits nWinBits )
+{
+ if ( nStyle & RULER_STYLE_INVISIBLE )
+ return;
+
+ USHORT nTabStyle = nStyle & RULER_TAB_STYLE;
+ 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) )
+ {
+ 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, USHORT 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 ( USHORT 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( BOOL bFont,
+ BOOL bForeground, 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 = 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;
+ BOOL b3DLook = !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO);
+
+ // VirtualDevice initialisieren
+ if ( mnWinStyle & WB_HORZ )
+ {
+ aVirDevSize.Width() = mnVirWidth;
+ aVirDevSize.Height() = mnVirHeight;
+ }
+ else
+ {
+ aVirDevSize.Height() = mnVirWidth;
+ aVirDevSize.Width() = mnVirHeight;
+ }
+ if ( aVirDevSize != maVirDev.GetOutputSizePixel() )
+ maVirDev.SetOutputSizePixel( aVirDevSize, 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--;
+
+ // Beschriftung ausgeben
+ ImplDrawTicks( nMin, nMax, nStart, nCenter );
+ }
+
+ // Spalten ausgeben
+ if ( mpData->pBorders )
+ ImplDrawBorders( nVirLeft, nP2, nVirTop, nVirBottom );
+
+ // Einzuege ausgeben
+ 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 = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplInitExtraField( 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 = TRUE;
+ mbFormat = 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( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::ImplDrawExtra( BOOL bPaint )
+{
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ Rectangle aRect = maExtraRect;
+ BOOL bEraseRect = 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 = TRUE;
+ }
+ else
+ {
+ if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) && (mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
+ {
+ SetFillColor( rStyleSettings.GetCheckedColor() );
+ bEraseRect = 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 )
+ {
+ USHORT 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( 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 = TRUE;
+ mbFormat = 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 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Ruler::ImplHitTest( const Point& rPos, ImplRulerHitTest* pHitTest,
+ BOOL bRequireStyle, USHORT nRequiredStyle ) const
+{
+ USHORT i;
+ USHORT nStyle;
+ long nHitBottom;
+ long nX;
+ long nY;
+ long n1;
+ long n2;
+
+ if ( !mbActive )
+ return FALSE;
+
+ // Position ermitteln
+ 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 = FALSE;
+ pHitTest->bSizeBar = 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 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 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 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 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 = 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 = TRUE;
+ pHitTest->mnDragSize = RULER_DRAGSIZE_1;
+ }
+ else if ( nX >= n2-nMOff )
+ {
+ pHitTest->bSize = TRUE;
+ pHitTest->mnDragSize = RULER_DRAGSIZE_2;
+ }
+ else
+ {
+ if ( nStyle & RULER_BORDER_MOVEABLE )
+ {
+ pHitTest->bSizeBar = TRUE;
+ pHitTest->mnDragSize = RULER_DRAGSIZE_MOVE;
+ }
+ }
+ }
+
+ return 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 = TRUE;
+ return 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 = TRUE;
+ return 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 TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Ruler::ImplDocHitTest( const Point& rPos, RulerType eDragType,
+ ImplRulerHitTest* pHitTest ) const
+{
+ Point aPos = rPos;
+ BOOL bRequiredStyle = FALSE;
+ USHORT nRequiredStyle = 0;
+
+ if (eDragType == RULER_TYPE_INDENT)
+ {
+ bRequiredStyle = 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 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 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 TRUE;
+ }
+ }
+
+ // Auf DontKnow setzen
+ pHitTest->eType = RULER_TYPE_DONTKNOW;
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Ruler::ImplStartDrag( ImplRulerHitTest* pHitTest, USHORT 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 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 = TRUE;
+ mnStartDragPos = mnDragPos;
+ StartTracking();
+ return TRUE;
+ }
+ else
+ {
+ // Ansonsten muessen wir die Daten zuruecksetzen
+ meDragType = RULER_TYPE_DONTKNOW;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ mnDragSize = 0;
+ mnDragModifier = 0;
+ mpData = mpSaveData;
+ }
+
+ return 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 = FALSE;
+ if ( nY < 0 )
+ {
+ if ( !mbDragCanceled )
+ {
+ // Daten wiederherstellen
+ mbDragCanceled = TRUE;
+ ImplRulerData aTempData;
+ aTempData = *mpDragData;
+ *mpDragData = *mpSaveData;
+ mbCalc = TRUE;
+ mbFormat = 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 = FALSE;
+
+ // +2, damit nicht so schnell die Tabs geloescht werden
+ if ( nY > nOutHeight+2 )
+ mbDragDelete = 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 = FALSE;
+
+ // Handler rufen
+ EndDrag();
+
+ // Drag-Werte zuruecksetzen
+ meDragType = RULER_TYPE_DONTKNOW;
+ mnDragPos = 0;
+ mnDragAryPos = 0;
+ mnDragSize = 0;
+ mbDragCanceled = FALSE;
+ mbDragDelete = 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();
+ USHORT nMouseClicks = rMEvt.GetClicks();
+ USHORT 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 = TRUE;
+ mbFormat = 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( 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
+ BOOL bVisible = IsReallyVisible();
+ if ( bVisible && mpData->nLines )
+ {
+ ImplInvertLines();
+ mnUpdateFlags |= RULER_UPDATE_LINES;
+ if ( !mnUpdateEvtId )
+ mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
+ }
+ mbFormat = 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 = TRUE;
+ mnVirHeight = nNewHeight - mnBorderWidth - (RULER_OFF*2);
+ }
+ else
+ {
+ if ( mpData->bAutoPageWidth )
+ ImplUpdate( TRUE );
+ else if ( mbAutoWinWidth )
+ mbCalc = 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( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, 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 = TRUE;
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+long Ruler::StartDrag()
+{
+ if ( maStartDragHdl.IsSet() )
+ return maStartDragHdl.Call( this );
+ else
+ return 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 = TRUE;
+
+ // Positionslinien wieder anzeigen (erst hinter mbActive=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=FALSE rufen, da
+ // von ImplInvertLines() ausgewertet wird)
+ ImplInvertLines();
+
+ mbActive = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL Ruler::StartDocDrag( const MouseEvent& rMEvt, RulerType eDragType )
+{
+ if ( !mbDrag )
+ {
+ Point aMousePos = rMEvt.GetPosPixel();
+ USHORT nMouseClicks = rMEvt.GetClicks();
+ USHORT nMouseModifier = rMEvt.GetModifier();
+ ImplRulerHitTest aHitTest;
+ if(eDragType != RULER_TYPE_DONTKNOW)
+ aHitTest.bExpandTest = 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 TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+RulerType Ruler::GetDocType( const Point& rPos, RulerType eDragType,
+ USHORT* 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, USHORT* 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 = TRUE;
+ else
+ mbAutoWinWidth = FALSE;
+
+ // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
+ mnWinOff = nNewOff;
+ mnWinWidth = nNewWidth;
+ ImplUpdate( 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 = TRUE;
+ else
+ mpData->bAutoPageWidth = FALSE;
+
+ // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
+ mpData->nPageOff = nNewOff;
+ mpData->nPageWidth = nNewWidth;
+ ImplUpdate( 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, USHORT nStyle )
+{
+ if ( mnWinStyle & WB_EXTRAFIELD )
+ {
+ meExtraType = eNewExtraType;
+ mnExtraStyle = nStyle;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplDrawExtra( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetNullOffset( long nPos )
+{
+ if ( mpData->nNullOff != nPos )
+ {
+ mpData->nNullOff = nPos;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetMargin1( long nPos, USHORT nMarginStyle )
+{
+ if ( (mpData->nMargin1 != nPos) || (mpData->nMargin1Style != nMarginStyle) )
+ {
+ mpData->nMargin1 = nPos;
+ mpData->nMargin1Style = nMarginStyle;
+ ImplUpdate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::SetMargin2( long nPos, USHORT 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( USHORT n, const RulerLine* pLineAry )
+{
+ // Testen, ob sich was geaendert hat
+ if ( mpData->nLines == n )
+ {
+ USHORT 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;
+ }
+
+ // Neue Werte setzen und neu ausgeben
+ BOOL bMustUpdate;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ bMustUpdate = TRUE;
+ else
+ bMustUpdate = FALSE;
+
+ // Alte Linien loeschen
+ if ( bMustUpdate )
+ ImplInvertLines();
+
+ // Neue Daten setzen
+ 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( USHORT 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
+ {
+ USHORT 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( USHORT 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
+ {
+ USHORT 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( USHORT 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
+ {
+ USHORT 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( USHORT 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
+ {
+ USHORT 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( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void Ruler::DrawTab( OutputDevice* pDevice, const Point& rPos, USHORT nStyle )
+{
+ /*const StyleSettings& rStyleSettings =*/ pDevice->GetSettings().GetStyleSettings();
+ Point aPos( rPos );
+ USHORT 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(BOOL bRTL)
+{
+ if(mpData->bTextRTL != bRTL)
+ {
+ mpData->bTextRTL = bRTL;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplInitExtraField( 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; }
+USHORT Ruler::GetMargin1Style() const { return mpData->nMargin1Style; }
+long Ruler::GetMargin2() const { return mpData->nMargin2; }
+USHORT Ruler::GetMargin2Style() const { return mpData->nMargin2Style; }
+USHORT Ruler::GetLineCount() const { return mpData->nLines; }
+const RulerLine* Ruler::GetLines() const { return mpData->pLines; }
+USHORT Ruler::GetArrowCount() const { return mpData->nArrows; }
+const RulerArrow* Ruler::GetArrows() const { return mpData->pArrows; }
+USHORT Ruler::GetBorderCount() const { return mpData->nBorders; }
+const RulerBorder* Ruler::GetBorders() const { return mpData->pBorders; }
+USHORT 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 100644
index 000000000000..04f3d55c35b0
--- /dev/null
+++ b/svtools/source/control/scriptedtext.cxx
@@ -0,0 +1,398 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: scriptedtext.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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 "scriptedtext.hxx"
+
+#ifndef __SGI_STL_VECTOR
+#include <vector>
+#endif
+#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< USHORT >(nCharIx), sal::static_int_cast< USHORT >(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 100644
index 000000000000..162f23948385
--- /dev/null
+++ b/svtools/source/control/scrwin.cxx
@@ -0,0 +1,575 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: scrwin.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * 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 <scrwin.hxx>
+
+//===================================================================
+
+void ScrollableWindow::ImpInitialize( ScrollableWindowFlags nFlags )
+{
+ bHandleDragging = (BOOL) ( nFlags & SCRWIN_THUMBDRAGGING );
+ bVCenter = (nFlags & SCRWIN_VCENTER) == SCRWIN_VCENTER;
+ bHCenter = (nFlags & SCRWIN_HCENTER) == SCRWIN_HCENTER;
+ bScrolling = 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 = 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 = 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 = 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();
+ BOOL bVVisible = FALSE; // by default no vertical-ScrollBar
+ BOOL bHVisible = FALSE; // by default no horizontal-ScrollBar
+ BOOL bChanged; // determines if a visiblility was changed
+ do
+ {
+ bChanged = FALSE;
+
+ // does we need a vertical ScrollBar
+ if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
+ { bHVisible = TRUE;
+ aOutPixSz.Height() -= nScrSize;
+ bChanged = TRUE;
+ }
+
+ // does we need a horizontal ScrollBar
+ if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
+ { bVVisible = TRUE;
+ aOutPixSz.Width() -= nScrSize;
+ bChanged = 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() );
+ BOOL bHScroll = FALSE;
+ const long nScrSize = GetSettings().GetStyleSettings().GetScrollBarSize();
+ if ( aWill.Width() < aWish.GetSize().Width() )
+ { bHScroll = 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 );
+}
+
+//-------------------------------------------------------------------
+
+BOOL ScrollableWindow::MakeVisible( const Rectangle& rTarget, 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 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( ULONG nHorz, 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, USHORT )
+{
+ 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, ULONG nOverlapX,
+ long nPagesY, 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 100644
index 000000000000..ddfb607d8064
--- /dev/null
+++ b/svtools/source/control/stdctrl.cxx
@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stdctrl.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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( 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 100644
index 000000000000..35250753de1e
--- /dev/null
+++ b/svtools/source/control/stdmenu.cxx
@@ -0,0 +1,518 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stdmenu.cxx,v $
+ * $Revision: 1.11 $
+ *
+ * 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>
+
+#ifndef _APP_HXX
+#include <vcl/svapp.hxx>
+#endif
+
+#include <vcl/i18nhelp.hxx>
+
+#include <ctrltool.hxx>
+#include <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.
+ USHORT nFontCount = ::std::min( pList->GetFontNameCount(), static_cast< USHORT >(100) );
+ for ( USHORT i = 0; i < nFontCount; i++ )
+ {
+ const XubString& rName = pList->GetFontName( i ).GetName();
+
+ // sort with the I18nHelper
+ USHORT 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
+ USHORT nChecked = 0;
+ USHORT nItemCount = GetItemCount();
+ for( USHORT i = 0; i < nItemCount; i++ )
+ {
+ USHORT nItemId = GetItemId( i );
+
+ if ( IsItemChecked( nItemId ) )
+ nChecked = nItemId;
+
+ XubString aText = GetItemText( nItemId );
+ if ( aText == maCurName )
+ {
+ CheckItem( nItemId, TRUE );
+ return;
+ }
+ }
+
+ if ( nChecked )
+ CheckItem( nChecked, FALSE );
+}
+
+// ========================================================================
+
+FontStyleMenu::FontStyleMenu()
+{
+ SetMenuFlags( GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
+}
+
+// -----------------------------------------------------------------------
+
+FontStyleMenu::~FontStyleMenu()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void FontStyleMenu::Select()
+{
+ USHORT nCurId = GetCurItemId();
+
+ if ( (nCurId >= FONTSTYLEMENU_FIRSTID) && (nCurId <= FONTSTYLEMENU_LASTID) )
+ {
+ maCurStyle = GetItemText( nCurId );
+ maSelectHdl.Call( this );
+ }
+ else
+ PopupMenu::Select();
+}
+
+// -----------------------------------------------------------------------
+
+void FontStyleMenu::Highlight()
+{
+ USHORT nCurId = GetCurItemId();
+
+ if ( (nCurId >= FONTSTYLEMENU_FIRSTID) && (nCurId <= FONTSTYLEMENU_LASTID) )
+ {
+ XubString aTempName = maCurStyle;
+ maCurStyle = GetItemText( nCurId );
+ maHighlightHdl.Call( this );
+ maCurStyle = aTempName;
+ }
+ else
+ PopupMenu::Highlight();
+}
+
+// -----------------------------------------------------------------------
+
+BOOL FontStyleMenu::ImplIsAlreadyInserted( const XubString& rStyleName, USHORT nCount )
+{
+ for ( USHORT i = 0; i < nCount; i++ )
+ {
+ if ( GetItemText( i+FONTSTYLEMENU_FIRSTID ) == rStyleName )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void FontStyleMenu::Fill( const XubString& rName, const FontList* pList )
+{
+ USHORT 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;
+ USHORT nPos = 0;
+ USHORT nId = FONTSTYLEMENU_FIRSTID;
+ FontWeight eLastWeight = WEIGHT_DONTKNOW;
+ FontItalic eLastItalic = ITALIC_NONE;
+ FontWidth eLastWidth = WIDTH_DONTKNOW;
+ BOOL bNormal = FALSE;
+ BOOL bItalic = FALSE;
+ BOOL bBold = FALSE;
+ BOOL bBoldItalic = FALSE;
+ BOOL bInsert = 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 = TRUE;
+ else
+ bNormal = TRUE;
+ }
+ else
+ {
+ if ( eItalic != ITALIC_NONE )
+ bBoldItalic = TRUE;
+ else
+ bBold = 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 = TRUE;
+ else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
+ bBold = TRUE;
+ else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
+ bBoldItalic = 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
+ USHORT nChecked = 0;
+ USHORT nItemCount = GetItemCount();
+ for( USHORT i = 0; i < nItemCount; i++ )
+ {
+ USHORT 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, TRUE );
+ return;
+ }
+ }
+
+ if ( nChecked )
+ CheckItem( nChecked, FALSE );
+}
+
+// ========================================================================
+
+FontSizeMenu::FontSizeMenu()
+: mpHeightAry( NULL )
+, mnCurHeight( 100 )
+{
+ SetMenuFlags( GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
+}
+
+// -----------------------------------------------------------------------
+
+FontSizeMenu::~FontSizeMenu()
+{
+ if ( mpHeightAry )
+ delete[] mpHeightAry;
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeMenu::Select()
+{
+ const USHORT nCurItemId = GetCurItemId();
+ mnCurHeight = mpHeightAry[ nCurItemId - 1 ];
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void FontSizeMenu::Highlight()
+{
+ const long nTempHeight = mnCurHeight;
+ const USHORT 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 );
+ USHORT nSizeCount = 0;
+ while ( pAry[nSizeCount] )
+ nSizeCount++;
+
+ USHORT 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
+ ULONG nCount = aFontSizeNames.Count();
+ for( 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, TRUE, 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, TRUE, FALSE );
+ USHORT nChecked = 0;
+ USHORT nItemCount = GetItemCount();
+ for( USHORT i = 0; i < nItemCount; i++ )
+ {
+ USHORT nItemId = GetItemId( i );
+
+ if ( mpHeightAry[i] == nHeight )
+ {
+ CheckItem( nItemId, TRUE );
+ return;
+ }
+
+ if ( IsItemChecked( nItemId ) )
+ nChecked = nItemId;
+ }
+
+ if ( nChecked )
+ CheckItem( nChecked, FALSE );
+}
diff --git a/svtools/source/control/tabbar.cxx b/svtools/source/control/tabbar.cxx
new file mode 100644
index 000000000000..ed1abbe53a2a
--- /dev/null
+++ b/svtools/source/control/tabbar.cxx
@@ -0,0 +1,2642 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: tabbar.cxx,v $
+ * $Revision: 1.21.100.1 $
+ *
+ * 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 "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"
+
+// =======================================================================
+
+#define TABBAR_OFFSET_X 7
+#define TABBAR_OFFSET_X2 2
+#define TABBAR_DRAG_SCROLLOFF 5
+#define TABBAR_MINSIZE 5
+
+const USHORT ADDNEWPAGE_AREAWIDTH = 10;
+
+// =======================================================================
+
+struct ImplTabBarItem
+{
+ USHORT mnId;
+ TabBarPageBits mnBits;
+ XubString maText;
+ XubString maHelpText;
+ Rectangle maRect;
+ long mnWidth;
+ ULONG mnHelpId;
+ BOOL mbShort;
+ BOOL mbSelect;
+ BOOL mbEnable;
+
+ ImplTabBarItem( USHORT nItemId, const XubString& rText,
+ TabBarPageBits nPageBits ) :
+ maText( rText )
+ {
+ mnId = nItemId;
+ mnBits = nPageBits;
+ mnWidth = 0;
+ mnHelpId = 0;
+ mbShort = FALSE;
+ mbSelect = FALSE;
+ mbEnable = TRUE;
+ }
+};
+
+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 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;
+ 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 = TRUE; }
+ void ResetPostEvent() { mbPostEvt = FALSE; }
+
+ virtual long PreNotify( NotifyEvent& rNEvt );
+ virtual void LoseFocus();
+};
+
+// -----------------------------------------------------------------------
+
+TabBarEdit::TabBarEdit( TabBar* pParent, WinBits nWinStyle ) :
+ Edit( pParent, nWinStyle )
+{
+ mbPostEvt = 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*)FALSE ) )
+ mbPostEvt = TRUE;
+ }
+ return TRUE;
+ }
+ else if ( pKEvt->GetKeyCode().GetCode() == KEY_ESCAPE )
+ {
+ if ( !mbPostEvt )
+ {
+ if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)TRUE ) )
+ mbPostEvt = TRUE;
+ }
+ return TRUE;
+ }
+ }
+ }
+
+ return Edit::PreNotify( rNEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBarEdit::LoseFocus()
+{
+ if ( !mbPostEvt )
+ {
+ if ( PostUserEvent( LINK( this, TabBarEdit, ImplEndEditHdl ), (void*)FALSE ) )
+ mbPostEvt = 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( 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( TRUE ) )
+ maLoseFocusTimer.Start();
+ else
+ GetParent()->EndEditMode( TRUE );
+
+ return 0;
+}
+
+// =======================================================================
+struct TabBar_Impl
+{
+ ImplTabSizer* mpSizer;
+ ::svt::AccessibleFactoryAccess maAccessibleFactory;
+
+ TabBar_Impl()
+ :mpSizer( NULL )
+ {
+ }
+ ~TabBar_Impl()
+ {
+ delete mpSizer;
+ }
+};
+
+// =======================================================================
+
+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 = TRUE;
+ mbFirstFormat = TRUE;
+ mbSizeFormat = TRUE;
+ mbAutoMaxWidth = TRUE;
+ mbInSwitching = FALSE;
+ mbAutoEditMode = FALSE;
+ mbEditCanceled = FALSE;
+ mbDropPos = FALSE;
+ mbInSelect = FALSE;
+ mbSelColor = FALSE;
+ mbSelTextColor = FALSE;
+ mbMirrored = FALSE;
+
+ if ( nWinStyle & WB_3DTAB )
+ mnOffY++;
+
+ ImplInitControls();
+ SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) );
+ ImplInitSettings( TRUE, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+TabBar::TabBar( Window* pParent, WinBits nWinStyle ) :
+ Window( pParent, (nWinStyle & WB_3DLOOK) | WB_CLIPCHILDREN )
+{
+ ImplInit( nWinStyle );
+}
+
+// -----------------------------------------------------------------------
+
+TabBar::~TabBar()
+{
+ EndEditMode( 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( BOOL bFont, 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;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TabBar::ImplCalcWidth()
+{
+ // Groessen muessen nur ermittelt werden, wenn sich Text aendert oder
+ // wenn der Font geaendert wurde
+ if ( !mbSizeFormat )
+ return 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;
+
+ BOOL bChanged = FALSE;
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ long nNewWidth = GetTextWidth( pItem->maText );
+ if ( mnCurMaxWidth && (nNewWidth > mnCurMaxWidth) )
+ {
+ pItem->mbShort = TRUE;
+ nNewWidth = mnCurMaxWidth;
+ }
+ else
+ pItem->mbShort = FALSE;
+ nNewWidth += TABBAR_OFFSET_X+TABBAR_OFFSET_X2;
+ if ( pItem->mnWidth != nNewWidth )
+ {
+ pItem->mnWidth = nNewWidth;
+ if ( !pItem->maRect.IsEmpty() )
+ bChanged = TRUE;
+ }
+ pItem = mpItemList->Next();
+ }
+ mbSizeFormat = FALSE;
+ mbFormat = TRUE;
+ return bChanged;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::ImplFormat()
+{
+ ImplCalcWidth();
+
+ if ( !mbFormat )
+ return;
+
+ USHORT 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 = FALSE;
+
+ // Button enablen/disablen
+ ImplEnableControls();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabBar::ImplGetLastFirstPos()
+{
+ USHORT nCount = (USHORT)(mpItemList->Count());
+ if ( !nCount || mbSizeFormat || mbFormat )
+ return 0;
+
+ USHORT 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 != (USHORT)(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
+ 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( USHORT 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 )
+ {
+ USHORT nNewPos = mnFirstPos+1;
+ SetFirstPageId( GetPageId( nNewPos ) );
+ ImplFormat();
+ if ( nNewPos != mnFirstPos )
+ break;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( TabBar, ImplClickHdl, ImplTabButton*, pBtn )
+{
+ EndEditMode();
+
+ USHORT nNewPos = mnFirstPos;
+
+ if ( pBtn == mpFirstBtn )
+ nNewPos = 0;
+ else if ( pBtn == mpPrevBtn )
+ {
+ if ( mnFirstPos )
+ nNewPos = mnFirstPos-1;
+ }
+ else if ( pBtn == mpNextBtn )
+ {
+ USHORT nCount = GetPageCount();
+ if ( mnFirstPos < nCount )
+ nNewPos = mnFirstPos+1;
+ }
+ else
+ {
+ USHORT 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 = 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;
+ USHORT nSelId = GetPageId( rMEvt.GetPosPixel() );
+
+ if ( !rMEvt.IsLeft() )
+ {
+ Window::MouseButtonDown( rMEvt );
+ if ( (nSelId > 0) && (nSelId != mnCurPageId) )
+ {
+ USHORT nPos = GetPagePos( nSelId );
+ pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbEnable )
+ {
+ if ( ImplDeactivatePage() )
+ {
+ SetCurPageId( nSelId );
+ Update();
+ ImplActivatePage();
+ ImplSelect();
+ }
+ mbInSelect = TRUE;
+ }
+ }
+ return;
+ }
+
+ if ( rMEvt.IsMod2() && mbAutoEditMode && nSelId )
+ {
+ if ( StartEditMode( nSelId ) )
+ return;
+ }
+
+ if ( (rMEvt.GetMode() & (MOUSE_MULTISELECT | MOUSE_RANGESELECT)) && (rMEvt.GetClicks() == 1) )
+ {
+ if ( nSelId )
+ {
+ USHORT nPos = GetPagePos( nSelId );
+ BOOL bSelectTab = FALSE;
+ pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbEnable )
+ {
+ if ( (rMEvt.GetMode() & MOUSE_MULTISELECT) && (mnWinStyle & WB_MULTISELECT) )
+ {
+ if ( nSelId != mnCurPageId )
+ {
+ SelectPage( nSelId, !IsPageSelected( nSelId ) );
+ bSelectTab = TRUE;
+ }
+ }
+ else if ( mnWinStyle & (WB_MULTISELECT | WB_RANGESELECT) )
+ {
+ bSelectTab = TRUE;
+ USHORT n;
+ BOOL bSelect;
+ USHORT 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 = FALSE;
+ else
+ bSelect = 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
+ USHORT nCount = (USHORT)mpItemList->Count();
+ n = nCurPos;
+ while ( n < nCount )
+ {
+ pItem = mpItemList->GetObject( n );
+
+ if ( n <= nPos )
+ bSelect = TRUE;
+ else
+ bSelect = 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 = TRUE;
+
+ return;
+ }
+ }
+ else if ( rMEvt.GetClicks() == 2 )
+ {
+ // Gegebenenfalls den Double-Click-Handler rufen
+ if ( !rMEvt.GetModifier() && (!nSelId || (nSelId == mnCurPageId)) )
+ {
+ USHORT 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 )
+ {
+ USHORT nPos = GetPagePos( nSelId );
+ pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbEnable )
+ {
+ if ( !pItem->mbSelect )
+ {
+ // Muss invalidiert werden
+ BOOL bUpdate = FALSE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ bUpdate = TRUE;
+
+ // Alle selektierten Items deselektieren
+ pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) )
+ {
+ pItem->mbSelect = FALSE;
+ if ( bUpdate )
+ Invalidate( pItem->maRect );
+ }
+
+ pItem = mpItemList->Next();
+ }
+ }
+
+ if ( ImplDeactivatePage() )
+ {
+ SetCurPageId( nSelId );
+ Update();
+ ImplActivatePage();
+ ImplSelect();
+ }
+ }
+ else
+ ImplShowPage( nPos );
+ mbInSelect = TRUE;
+ }
+
+ return;
+ }
+ }
+
+ Window::MouseButtonDown( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ mbInSelect = FALSE;
+ Window::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Paint( const Rectangle& )
+{
+ // Items berechnen und ausgeben
+ USHORT nItemCount = (USHORT)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 = FALSE;
+
+ if ( mnCurPageId && (mnFirstPos == 0) && !mbDropPos )
+ {
+ pItem = mpItemList->GetObject( GetPagePos( mnCurPageId ) );
+ if ( pItem->maRect.IsEmpty() )
+ {
+ // mbDropPos setzen (bzw. misbrauchen) um Invalidate()
+ // zu unterbinden
+ mbDropPos = TRUE;
+ SetFirstPageId( mnCurPageId );
+ mbDropPos = 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 );
+
+ // #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
+ USHORT 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
+ if ( pItem->mbSelect || (pItem->mnId == mnCurPageId) )
+ {
+ SetFillColor( aSelectColor );
+ SetTextColor( aSelectTextColor );
+ }
+ 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->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()--;
+ SetLineColor( rStyleSettings.GetLightColor() );
+ DrawLine( aPos0, aPos1 );
+
+ if ( !pItem->mbSelect && (pItem->mnId != mnCurPageId) )
+ {
+ 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()--;
+ DrawLine( aPos1, aPos2 );
+
+ // 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( TRUE, 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 = TRUE;
+ if ( IsReallyVisible() )
+ {
+ if ( ImplCalcWidth() )
+ Invalidate();
+ ImplFormat();
+ }
+
+ // Button enablen/disablen
+ ImplEnableControls();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::RequestHelp( const HelpEvent& rHEvt )
+{
+ USHORT 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 )
+ {
+ ULONG nHelpId = GetHelpId( nItemId );
+ if ( nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( nHelpId, 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) )
+ {
+ USHORT 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( TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ Invalidate();
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, 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( TRUE, 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 TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+long TabBar::StartRenaming()
+{
+ if ( maStartRenamingHdl.IsSet() )
+ return maStartRenamingHdl.Call( this );
+ else
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+long TabBar::AllowRenaming()
+{
+ if ( maAllowRenamingHdl.IsSet() )
+ return maAllowRenamingHdl.Call( this );
+ else
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::EndRenaming()
+{
+ maEndRenamingHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::Mirror()
+{
+
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::InsertPage( USHORT nPageId, const XubString& rText,
+ TabBarPageBits nBits, USHORT nPos )
+{
+ DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" );
+ DBG_ASSERT( GetPagePos( nPageId ) == TABBAR_PAGE_NOTFOUND,
+ "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 = 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)) );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::RemovePage( USHORT nPageId )
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ // Existiert Item
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ 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 = 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( USHORT nPageId, USHORT nNewPos )
+{
+ USHORT nPos = GetPagePos( nPageId );
+ Pair aPair( nPos, nNewPos );
+
+ if ( nPos < nNewPos )
+ nNewPos--;
+
+ if ( nPos == nNewPos )
+ return;
+
+ // Existiert Item
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ // TabBar-Item in der Liste verschieben
+ ImplTabBarItem* pItem = mpItemList->Remove( nPos );
+ mpItemList->Insert( pItem, nNewPos );
+ mbFormat = 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 = TRUE;
+ mnCurPageId = 0;
+ mnFirstPos = 0;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+
+ CallEventListeners( VCLEVENT_TABBAR_PAGEREMOVED, (void*) TABBAR_PAGE_NOTFOUND );
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::EnablePage( USHORT nPageId, BOOL bEnable )
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ 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)) );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TabBar::IsPageEnabled( USHORT nPageId ) const
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mbEnable;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetPageBits( USHORT nPageId, TabBarPageBits nBits )
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mnBits != nBits )
+ {
+ pItem->mnBits = nBits;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate( pItem->maRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+TabBarPageBits TabBar::GetPageBits( USHORT nPageId ) const
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnBits;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabBar::GetPageCount() const
+{
+ return (USHORT)mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabBar::GetPageId( USHORT nPos ) const
+{
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabBar::GetPagePos( USHORT nPageId ) const
+{
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nPageId )
+ return (USHORT)mpItemList->GetCurPos();
+
+ pItem = mpItemList->Next();
+ }
+
+ return TABBAR_PAGE_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT 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( USHORT nPageId ) const
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maRect;
+ else
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetCurPageId( USHORT nPageId )
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ // Wenn Item nicht existiert, dann nichts machen
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ // Wenn sich aktuelle Page nicht geaendert hat, dann muessen wir
+ // jetzt nichts mehr machen
+ if ( nPageId == mnCurPageId )
+ return;
+
+ // Muss invalidiert werden
+ BOOL bUpdate = FALSE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ bUpdate = 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 )
+ {
+ USHORT nSelPageCount = GetSelectPageCount();
+ if ( nSelPageCount == 1 )
+ pOldItem->mbSelect = FALSE;
+ pItem->mbSelect = TRUE;
+ }
+
+ mnCurPageId = nPageId;
+ mbFormat = 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() )
+ {
+ USHORT 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( USHORT nPageId )
+{
+ if ( !IsReallyVisible() )
+ return;
+
+ USHORT nPos = GetPagePos( nPageId );
+
+ // Wenn Item nicht existiert, dann nichts machen
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ 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 = TRUE;
+ ImplFormat();
+ }
+
+ while ( (pItem->maRect.Right() > nWidth) ||
+ pItem->maRect.IsEmpty() )
+ {
+ USHORT 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( USHORT nPageId )
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ // Wenn Item nicht existiert, dann FALSE zurueckgeben
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ if ( nPos != mnFirstPos )
+ {
+ // Dafuer sorgen, das nach Moeglichkteit soviele Pages wie
+ // moeglich sichtbar sind
+ ImplFormat();
+ USHORT nLastFirstPos = ImplGetLastFirstPos();
+ USHORT nNewPos;
+ if ( nPos > nLastFirstPos )
+ nNewPos = nLastFirstPos;
+ else
+ nNewPos = nPos;
+
+ if ( nNewPos != mnFirstPos )
+ {
+ mnFirstPos = nNewPos;
+ mbFormat = TRUE;
+
+ // Leiste neu ausgeben (Achtung: mbDropPos beachten, da wenn
+ // dieses Flag gesetzt ist, wird direkt gepaintet)
+ if ( IsReallyVisible() && IsUpdateMode() && !mbDropPos )
+ Invalidate();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SelectPage( USHORT nPageId, BOOL bSelect )
+{
+ USHORT nPos = GetPagePos( nPageId );
+
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+
+ if ( pItem->mbSelect != bSelect )
+ {
+ pItem->mbSelect = bSelect;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate( pItem->maRect );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SelectPageRange( BOOL bSelect, USHORT nStartPos, USHORT nEndPos )
+{
+ Rectangle aPaintRect;
+ USHORT 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 );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabBar::GetSelectPage( USHORT nSelIndex ) const
+{
+ USHORT nSelected = 0;
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbSelect )
+ nSelected++;
+
+ if ( nSelected == nSelIndex )
+ return pItem->mnId;
+
+ pItem = mpItemList->Next();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabBar::GetSelectPageCount() const
+{
+ USHORT nSelected = 0;
+ ImplTabBarItem* pItem = mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mbSelect )
+ nSelected++;
+
+ pItem = mpItemList->Next();
+ }
+
+ return nSelected;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TabBar::IsPageSelected( USHORT nPageId ) const
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mbSelect;
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TabBar::StartEditMode( USHORT nPageId )
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( mpEdit || (nPos == TABBAR_PAGE_NOTFOUND) || (mnLastOffX < 8) )
+ return 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 TRUE;
+ }
+ else
+ {
+ mnEditId = 0;
+ return FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::EndEditMode( BOOL bCancel )
+{
+ if ( mpEdit )
+ {
+ // call hdl
+ BOOL bEnd = 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 = FALSE;
+ else // nAllowRenaming == TABBAR_RENAMING_CANCEL
+ mbEditCanceled = 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 = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetMirrored( BOOL bMirrored )
+{
+ if( mbMirrored != bMirrored )
+ {
+ mbMirrored = bMirrored;
+ mbSizeFormat = TRUE;
+ ImplInitControls(); // for button images
+ Resize(); // recalculates control positions
+ Mirror();
+ }
+}
+
+void TabBar::SetEffectiveRTL( BOOL bRTL )
+{
+ SetMirrored( bRTL != Application::GetSettings().GetLayoutRTL() );
+}
+
+BOOL TabBar::IsEffectiveRTL() const
+{
+ return IsMirrored() != Application::GetSettings().GetLayoutRTL();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetMaxPageWidth( long nMaxWidth )
+{
+ if ( mnMaxPageWidth != nMaxWidth )
+ {
+ mnMaxPageWidth = nMaxWidth;
+ mbSizeFormat = TRUE;
+
+ // Leiste neu ausgeben
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectColor()
+{
+ if ( mbSelColor )
+ {
+ maSelColor = Color( COL_TRANSPARENT );
+ mbSelColor = FALSE;
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectColor( const Color& rColor )
+{
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbSelColor )
+ {
+ maSelColor = Color( COL_TRANSPARENT );
+ mbSelColor = FALSE;
+ Invalidate();
+ }
+ }
+ else
+ {
+ if ( maSelColor != rColor )
+ {
+ maSelColor = rColor;
+ mbSelColor = TRUE;
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectTextColor()
+{
+ if ( mbSelTextColor )
+ {
+ maSelTextColor = Color( COL_TRANSPARENT );
+ mbSelTextColor = FALSE;
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetSelectTextColor( const Color& rColor )
+{
+ if ( rColor.GetTransparency() )
+ {
+ if ( mbSelTextColor )
+ {
+ maSelTextColor = Color( COL_TRANSPARENT );
+ mbSelTextColor = FALSE;
+ Invalidate();
+ }
+ }
+ else
+ {
+ if ( maSelTextColor != rColor )
+ {
+ maSelTextColor = rColor;
+ mbSelTextColor = TRUE;
+ Invalidate();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetPageText( USHORT nPageId, const XubString& rText )
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ mpItemList->GetObject( nPos )->maText = rText;
+ mbSizeFormat = 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( USHORT nPageId ) const
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ return mpItemList->GetObject( nPos )->maText;
+ else
+ return XubString();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetHelpText( USHORT nPageId, const XubString& rText )
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ mpItemList->GetObject( nPos )->maHelpText = rText;
+}
+
+// -----------------------------------------------------------------------
+
+XubString TabBar::GetHelpText( USHORT nPageId ) const
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ {
+ ImplTabBarItem* pItem = mpItemList->GetObject( nPos );
+ if ( !pItem->maHelpText.Len() && pItem->mnHelpId )
+ {
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pItem->maHelpText = pHelp->GetHelpText( pItem->mnHelpId, this );
+ }
+
+ return pItem->maHelpText;
+ }
+ else
+ return XubString();
+}
+
+// -----------------------------------------------------------------------
+
+void TabBar::SetHelpId( USHORT nPageId, ULONG nHelpId )
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ mpItemList->GetObject( nPos )->mnHelpId = nHelpId;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG TabBar::GetHelpId( USHORT nPageId ) const
+{
+ USHORT nPos = GetPagePos( nPageId );
+ if ( nPos != TABBAR_PAGE_NOTFOUND )
+ return mpItemList->GetObject( nPos )->mnHelpId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+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;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TabBar::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
+{
+ if ( !(mnWinStyle & WB_DRAG) || (rCEvt.GetCommand() != COMMAND_STARTDRAG) )
+ return 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 )
+ {
+ USHORT nSelId = GetPageId( rCEvt.GetMousePosPixel() );
+
+ // Falls kein Eintrag angeklickt wurde, starten wir kein Dragging
+ if ( !nSelId )
+ return 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 FALSE;
+ }
+ }
+ mbInSelect = FALSE;
+
+ Region aRegion;
+
+ // Region zuweisen
+ rRegion = aRegion;
+
+ return TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT TabBar::ShowDropPos( const Point& rPos )
+{
+ ImplTabBarItem* pItem;
+ USHORT nDropId;
+ USHORT nNewDropPos;
+ USHORT nItemCount = (USHORT)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 = (USHORT)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 = TRUE;
+ mnDropPos = nNewDropPos;
+
+ if ( nScroll )
+ {
+ USHORT 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;
+ USHORT 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++;
+ 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 ) );
+ }
+ if ( (mnDropPos > 0) && (mnDropPos < nItemCount+1) )
+ {
+ pItem = mpItemList->GetObject( mnDropPos-1 );
+ nX = pItem->maRect.Right()-TABBAR_OFFSET_X;
+ if ( mnDropPos == nCurPos )
+ nX++;
+ 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;
+ USHORT nItemCount = (USHORT)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 = FALSE;
+ mnDropPos = 0;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TabBar::SwitchPage( const Point& rPos )
+{
+ BOOL bSwitch = FALSE;
+ USHORT 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 = TRUE;
+ if ( ImplDeactivatePage() )
+ {
+ SetCurPageId( mnSwitchId );
+ Update();
+ ImplActivatePage();
+ ImplSelect();
+ bSwitch = TRUE;
+ }
+ mbInSwitching = 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 100644
index 000000000000..146fa4933af3
--- /dev/null
+++ b/svtools/source/control/taskbar.cxx
@@ -0,0 +1,597 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: taskbar.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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
+
+#ifndef _TOOLS_LIST_HXX
+#include <tools/list.hxx>
+#endif
+#include <tools/debug.hxx>
+
+#ifndef _VCL_FLOATWIN_HXX
+#include <vcl/floatwin.hxx>
+#endif
+
+#include <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 = FALSE;
+ mbShowItems = FALSE;
+ mbAutoHide = 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 )
+ {
+ USHORT i = 0;
+ BOOL bVisibleItems = FALSE;
+ while ( i < pTempButtonBar->GetItemCount() )
+ {
+ if ( pTempButtonBar->IsItemVisible( pTempButtonBar->GetItemId( i ) ) )
+ {
+ bVisibleItems = 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( USHORT nLines )
+{
+ mnLines = nLines;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::EnableAutoHide( 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 = TRUE;
+ if ( mpStatusBar->AreItemsVisible() )
+ {
+ mbShowItems = TRUE;
+ mpStatusBar->HideItems();
+ }
+ else
+ mbShowItems = TRUE;
+ maOldText = mpStatusBar->GetText();
+ Resize();
+ mpStatusBar->SetText( rText );
+ Update();
+ mpStatusBar->Update();
+ }
+ else
+ mpStatusBar->SetText( rText );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskBar::HideStatusText()
+{
+ if ( mbStatusText && mpStatusBar )
+ {
+ mbStatusText = 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 100644
index 000000000000..72a7345f1660
--- /dev/null
+++ b/svtools/source/control/taskbox.cxx
@@ -0,0 +1,355 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: taskbox.cxx,v $
+ * $Revision: 1.8 $
+ *
+ * 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
+
+#ifndef _TOOLS_LIST_HXX
+#include <tools/list.hxx>
+#endif
+#include <tools/debug.hxx>
+#include <vcl/image.hxx>
+#include <vcl/help.hxx>
+
+#include <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 = 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( USHORT nItemId, BOOL bMinActivate )
+{
+ if ( nItemId )
+ {
+ if ( nItemId != mnActiveItemId )
+ {
+ if ( mnActiveItemId )
+ CheckItem( mnActiveItemId, FALSE );
+ CheckItem( nItemId );
+ mnActiveItemId = nItemId;
+ }
+ else
+ {
+ if ( !bMinActivate )
+ return;
+
+ mbMinActivate = TRUE;
+ }
+
+ mnTaskItem = nItemId-1;
+ ActivateTask();
+ mnTaskItem = 0;
+ mbMinActivate = 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 = (USHORT)mnOldItemCount;
+ mnUpdateNewPos = TOOLBOX_ITEM_NOTFOUND;
+ ImplFormatTaskToolBox();
+ ToolBox::Resize();
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::Command( const CommandEvent& rCEvt )
+{
+ if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
+ {
+ USHORT 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) )
+ {
+ USHORT 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()
+{
+ USHORT nItemId = GetCurItemId();
+ ActivateTaskItem( nItemId, TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskToolBox::ImplFormatTaskToolBox()
+{
+ if ( mnUpdateNewPos == TOOLBOX_ITEM_NOTFOUND )
+ {
+ // Eintraege aus der Liste entfernen
+ while ( mpItemList->Count() > mnUpdatePos )
+ delete mpItemList->Remove( (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
+ USHORT nBtnPos = (mnUpdateNewPos*2);
+ while ( nBtnPos < GetItemCount() )
+ RemoveItem( nBtnPos );
+ if ( mnUpdateNewPos <= (mnActiveItemId-1) )
+ mnActiveItemId = 0;
+
+ // Neue Eintrage einfuegen
+ USHORT 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) );
+ }
+
+ USHORT 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, 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,
+ 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( (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( (ULONG)mnUpdatePos );
+ mnUpdateNewPos = mnUpdatePos;
+ }
+
+ ImplFormatTaskToolBox();
+}
+
diff --git a/svtools/source/control/taskmisc.cxx b/svtools/source/control/taskmisc.cxx
new file mode 100644
index 000000000000..bada5926d639
--- /dev/null
+++ b/svtools/source/control/taskmisc.cxx
@@ -0,0 +1,383 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: taskmisc.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * 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
+
+#ifndef _TOOLS_LIST_HXX
+#include <tools/list.hxx>
+#endif
+#include <tools/debug.hxx>
+#include <vcl/help.hxx>
+
+#include <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 USHORT ImplCeilSqareRoot( USHORT nVal )
+{
+ USHORT 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 )
+{
+ USHORT nCount = (USHORT)mpWinList->Count();
+ if ( nCount < 3 )
+ {
+ ImplVert( rRect );
+ return;
+ }
+
+ USHORT i;
+ USHORT j;
+ USHORT nCols;
+ USHORT nRows;
+ USHORT nActRows;
+ USHORT 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( USHORT 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 100644
index 000000000000..86098af7de4a
--- /dev/null
+++ b/svtools/source/control/taskstat.cxx
@@ -0,0 +1,659 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: taskstat.cxx,v $
+ * $Revision: 1.10 $
+ *
+ * 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
+
+#ifndef _TOOLS_LIST_HXX
+#include <tools/list.hxx>
+#endif
+#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 <svtools/syslocale.hxx>
+#include <taskbar.hxx>
+
+// =======================================================================
+
+#define TASKSTATUSBAR_CLOCXOFFX 3
+#define TASKSTATUSBAR_IMAGEOFFX 1
+
+// =======================================================================
+
+struct ImplTaskSBFldItem
+{
+ TaskStatusFieldItem maItem;
+ USHORT mnId;
+ long mnOffX;
+};
+
+DECLARE_LIST( ImplTaskSBItemList, ImplTaskSBFldItem* )
+
+// =======================================================================
+
+BOOL ITaskStatusNotify::MouseButtonDown( USHORT, const MouseEvent& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ITaskStatusNotify::MouseButtonUp( USHORT, const MouseEvent& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ITaskStatusNotify::MouseMove( USHORT, const MouseEvent& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ITaskStatusNotify::Command( USHORT, const CommandEvent& )
+{
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ITaskStatusNotify::UpdateHelp( USHORT )
+{
+ return 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,
+ USHORT 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 = FALSE;
+ mbOutInterval = 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 )
+{
+ BOOL bUpdate = ImplUpdateClock();
+ if ( ImplUpdateFlashItems() )
+ bUpdate = TRUE;
+ if ( bUpdate )
+ SetItemData( TASKSTATUSBAR_STATUSFIELDID, NULL );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+ImplTaskSBFldItem* TaskStatusBar::ImplGetFieldItem( USHORT 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, BOOL& rFieldRect ) const
+{
+ if ( GetItemId( rPos ) == TASKSTATUSBAR_STATUSFIELDID )
+ {
+ rFieldRect = 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 = FALSE;
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+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, FALSE, FALSE );
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TaskStatusBar::ImplUpdateFlashItems()
+{
+ if ( mbFlashItems )
+ {
+ if ( mbOutInterval )
+ {
+ maTimer.SetTimeout( 900 );
+ mbOutInterval = FALSE;
+ }
+ else
+ {
+ maTimer.SetTimeout( 700 );
+ mbOutInterval = TRUE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::ImplUpdateField( BOOL bItems )
+{
+ maTimer.Stop();
+
+ if ( bItems )
+ {
+ ImplTaskSBFldItem* pItem = mpFieldItemList->First();
+ mnItemWidth = 0;
+ mbFlashItems = FALSE;
+ mbOutInterval = FALSE;
+ while ( pItem )
+ {
+ mnItemWidth += TASKSTATUSBAR_IMAGEOFFX;
+ pItem->mnOffX = mnItemWidth;
+ mnItemWidth += pItem->maItem.GetImage().GetSizePixel().Width();
+ if ( pItem->maItem.GetFlags() & TASKSTATUSFIELDITEM_FLASH )
+ mbFlashItems = TRUE;
+
+ pItem = mpFieldItemList->Next();
+ }
+ }
+ else
+ {
+ if ( mnFieldFlags & TASKSTATUSFIELD_CLOCK )
+ {
+ XubString aStr = SvtSysLocale().GetLocaleData().getTime( Time( 23, 59, 59 ), FALSE, 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 );
+ USHORT 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 = TRUE;
+ ImplUpdateFlashItems();
+ maTimer.Start();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ BOOL bFieldRect;
+ BOOL bBaseClass = FALSE;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ USHORT 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 )
+{
+ BOOL bFieldRect;
+ BOOL bBaseClass = FALSE;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ USHORT 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 )
+{
+ BOOL bFieldRect;
+ BOOL bBaseClass = FALSE;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rMEvt.GetPosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ USHORT 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 )
+{
+ BOOL bFieldRect;
+ BOOL bBaseClass = FALSE;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( rCEvt.GetMousePosPixel(), bFieldRect );
+
+ ITaskStatusNotify* pNotify = mpNotify;
+ USHORT 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 )
+{
+ BOOL bFieldRect;
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ), bFieldRect );
+ if ( bFieldRect )
+ {
+ ITaskStatusNotify* pNotify = mpNotify;
+ USHORT 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 )
+ {
+ ULONG nHelpId = pItem->maItem.GetHelpId();
+ if ( nHelpId )
+ {
+ // Wenn eine Hilfe existiert, dann ausloesen
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ pHelp->Start( nHelpId, 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, USHORT,
+ USHORT nFlags )
+{
+ mnFieldFlags = nFlags;
+ ImplUpdateField( FALSE );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::SetFieldFlags( USHORT nFlags )
+{
+ if ( mnFieldFlags != nFlags )
+ {
+ mnFieldFlags = nFlags;
+ ImplUpdateField( FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::AddStatusFieldItem( USHORT nItemId, const TaskStatusFieldItem& rItem,
+ USHORT 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, (ULONG)nPos );
+
+ ImplUpdateField( TRUE );
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::ModifyStatusFieldItem( USHORT nItemId, const TaskStatusFieldItem& rItem )
+{
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId );
+ if ( pItem )
+ {
+ BOOL bUpdate = (pItem->maItem.GetImage() != rItem.GetImage()) ||
+ (pItem->maItem.GetFlags() != rItem.GetFlags());
+ pItem->maItem = rItem;
+ if ( bUpdate )
+ ImplUpdateField( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void TaskStatusBar::RemoveStatusFieldItem( USHORT nItemId )
+{
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId );
+ if ( pItem )
+ {
+ mpFieldItemList->Remove( pItem );
+ delete pItem;
+ ImplUpdateField( TRUE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+BOOL TaskStatusBar::GetStatusFieldItem( USHORT nItemId, TaskStatusFieldItem& rItem ) const
+{
+ ImplTaskSBFldItem* pItem = ImplGetFieldItem( nItemId );
+ if ( pItem )
+ {
+ rItem = pItem->maItem;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
diff --git a/svtools/source/control/urlcontrol.cxx b/svtools/source/control/urlcontrol.cxx
new file mode 100644
index 000000000000..1252fc17a1d6
--- /dev/null
+++ b/svtools/source/control/urlcontrol.cxx
@@ -0,0 +1,102 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: urlcontrol.cxx,v $
+ * $Revision: 1.6 $
+ *
+ * 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 SVTOOL_URLCONTROL_HXX
+#include <svtools/urlcontrol.hxx>
+#endif
+#ifndef SVTOOLS_FILENOTATION_HXX_
+#include "filenotation.hxx"
+#endif
+
+//.........................................................................
+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..96eb8bb39e99
--- /dev/null
+++ b/svtools/source/control/valueacc.cxx
@@ -0,0 +1,1264 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: valueacc.cxx,v $
+ * $Revision: 1.25 $
+ *
+ * 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< USHORT >(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( USHORT 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->GetLabeledBy();
+ 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 USHORT nItemId = mpParent->GetItemId( Point( aPoint.X, aPoint.Y ) );
+ uno::Reference< accessibility::XAccessible > xRet;
+
+ if( VALUESET_ITEM_NOTFOUND != nItemId )
+ {
+ const USHORT 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();
+ UINT32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueSetAcc::getBackground( )
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed();
+ 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< USHORT >(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< USHORT >(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( USHORT 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( USHORT 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;
+ }
+}
+
+
+USHORT ValueSetAcc::getItemCount (void) const
+{
+ USHORT 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 (USHORT 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<USHORT>(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;
+
+ USHORT nCount = mpParent->mrParent.ImplGetVisibleItemCount();
+ ValueSetItem* pItem;
+ for (USHORT 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)
+{
+ const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
+ String aRet( RTL_CONSTASCII_USTRINGPARAM( "ValueSet item" ) );
+
+ return aRet;
+}
+
+// -----------------------------------------------------------------------------
+
+::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)
+{
+ UINT32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
+ return static_cast<sal_Int32>(nColor);
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 SAL_CALL ValueItemAcc::getBackground( )
+ throw (uno::RuntimeException)
+{
+ UINT32 nColor;
+ if (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 100644
index 000000000000..c176629953ae
--- /dev/null
+++ b/svtools/source/control/valueimp.hxx
@@ -0,0 +1,332 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: valueimp.hxx,v $
+ * $Revision: 1.17 $
+ *
+ * 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;
+ USHORT mnId;
+ USHORT 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;
+
+ 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 );
+ 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.
+ */
+ USHORT 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 (USHORT 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 );
+ 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..4033a9df7bb5
--- /dev/null
+++ b/svtools/source/control/valueset.cxx
@@ -0,0 +1,2754 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: valueset.cxx,v $
+ * $Revision: 1.34 $
+ *
+ * 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 = TRUE;
+ mbHighlight = FALSE ;
+ mbSelection = FALSE;
+ mbNoSelection = TRUE;
+ mbDrawSelection = TRUE;
+ mbBlackSel = FALSE;
+ mbDoubleSel = FALSE;
+ mbScroll = FALSE;
+ mbDropPos = FALSE;
+ mbFullMode = TRUE;
+
+ // #106446#, #106601# force mirroring of virtual device
+ maVirDev.EnableRTL( GetParent()->IsRTLEnabled() );
+
+ ImplInitSettings( TRUE, TRUE, 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(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( BOOL bFont,
+ BOOL bForeground, 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;
+
+ USHORT 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();
+ 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 = (USHORT)((aWinSize.Width()-nScrBarWidth+nSpace) / (mnUserItemWidth+nSpace));
+ if ( !mnCols )
+ mnCols = 1;
+ }
+ else
+ mnCols = 1;
+ }
+ else
+ mnCols = mnUserCols;
+
+ // Zeilenanzahl berechnen
+ mbScroll = 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 = TRUE;
+ if ( mnLines <= mnVisLines )
+ mnFirstLine = 0;
+ else
+ {
+ if ( mnFirstLine > (USHORT)(mnLines-mnVisLines) )
+ mnFirstLine = (USHORT)(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, 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 ( 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 = TRUE;
+ else
+ mbBlackSel = FALSE;
+
+ // Wenn die Items groesser sind, dann die Selektion doppelt so breit
+ // zeichnen
+ if ( (nStyle & WB_DOUBLEBORDER) &&
+ ((nItemWidth >= 25) && (nItemHeight >= 20)) )
+ mbDoubleSel = TRUE;
+ else
+ mbDoubleSel = 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
+ ULONG nFirstItem = mnFirstLine * mnCols;
+ 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 ( ULONG i = 0; i < nItemCount; i++ )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( i );
+
+ if ( (i >= nFirstItem) && (i < nLastItem) )
+ {
+ const 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 = 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;
+
+ BOOL bFocus = HasFocus();
+ BOOL bDrawSel;
+
+ if ( (mbNoSelection && !mbHighlight) || (!mbDrawSelection && mbHighlight) )
+ bDrawSel = FALSE;
+ else
+ bDrawSel = TRUE;
+
+ if ( !bFocus &&
+ ((mbNoSelection && !mbHighlight) || (!mbDrawSelection && mbHighlight)) )
+ {
+ XubString aEmptyStr;
+ ImplDrawItemText( aEmptyStr );
+ return;
+ }
+
+ USHORT 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( USHORT nItemId )
+{
+ Rectangle aRect;
+
+ USHORT nItemPos = GetItemPos( nItemId );
+ if ( nItemPos != sal::static_int_cast<USHORT>(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( USHORT nItemId, BOOL bIsSelection )
+{
+ if ( mnHighItemId != nItemId )
+ {
+ // Alten merken, um vorherige Selektion zu entfernen
+ USHORT nOldItem = mnHighItemId;
+ mnHighItemId = nItemId;
+
+ // Wenn keiner selektiert ist, dann Selektion nicht malen
+ if ( !bIsSelection && mbNoSelection )
+ mbDrawSelection = FALSE;
+
+ // Neu ausgeben und alte Selection wegnehmen
+ ImplHideSelect( nOldItem );
+ ImplDrawSelect();
+ mbDrawSelection = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplDrawDropPos( BOOL bShow )
+{
+ if ( (mnDropPos != VALUESET_ITEM_NOTFOUND) && mpImpl->mpItemList->Count() )
+ {
+ USHORT nItemPos = mnDropPos;
+ USHORT nItemId1;
+ USHORT nItemId2 = 0;
+ BOOL bRight;
+ if ( nItemPos >= mpImpl->mpItemList->Count() )
+ {
+ nItemPos = (USHORT)(mpImpl->mpItemList->Count()-1);
+ bRight = TRUE;
+ }
+ else
+ bRight = 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 ( USHORT 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 ( USHORT 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();
+}
+
+// -----------------------------------------------------------------------
+
+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 FALSE;
+
+ long nScrollOffset;
+ USHORT 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 < (USHORT)(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 = TRUE;
+ ImplDraw();
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::ImplGetItem( const Point& rPos, BOOL bMove ) const
+{
+ if ( mpNoneItem )
+ {
+ if ( mpNoneItem->maRect.IsInside( rPos ) )
+ return VALUESET_ITEM_NONEITEM;
+ }
+
+ Point aDefPos;
+ Rectangle aWinRect( aDefPos, maVirDev.GetOutputSizePixel() );
+
+ ULONG nItemCount = mpImpl->mpItemList->Count();
+ for ( ULONG i = 0; i < nItemCount; i++ )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( i );
+ if ( pItem->maRect.IsInside( rPos ) )
+ {
+ if ( aWinRect.IsInside( rPos ) )
+ return (USHORT)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( USHORT nPos )
+{
+ if ( nPos == VALUESET_ITEM_NONEITEM )
+ return mpNoneItem;
+ else
+ return mpImpl->mpItemList->GetObject( nPos );
+}
+
+// -----------------------------------------------------------------------
+
+ValueSetItem* ValueSet::ImplGetFirstItem()
+{
+ USHORT nItemCount = (USHORT)mpImpl->mpItemList->Count();
+ USHORT i = 0;
+
+ while ( i < nItemCount )
+ {
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( i );
+ if ( pItem->meType != VALUESETITEM_SPACE )
+ return pItem;
+ i++;
+ }
+
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::ImplGetVisibleItemCount() const
+{
+ USHORT 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( USHORT nVisiblePos )
+{
+ ValueSetItem* pRet = NULL;
+ USHORT 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( FALSE ) );
+
+ if( pAcc )
+ pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue );
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ValueSet::ImplHasAccessibleListeners()
+{
+ ValueSetAcc* pAcc = ValueSetAcc::getImplementation( GetAccessible( FALSE ) );
+ return( pAcc && pAcc->HasAccessibleListeners() );
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ValueSet,ImplScrollHdl, ScrollBar*, pScrollBar )
+{
+ USHORT nNewFirstLine = (USHORT)pScrollBar->GetThumbPos();
+ if ( nNewFirstLine != mnFirstLine )
+ {
+ mnFirstLine = nNewFirstLine;
+ mbFormat = TRUE;
+ ImplDraw();
+ }
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+IMPL_LINK( ValueSet,ImplTimerHdl, Timer*, EMPTYARG )
+{
+ ImplTracking( GetPointerPosPixel(), TRUE );
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplTracking( const Point& rPos, 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 = TRUE;
+
+ ImplHighlightItem( pItem->mnId );
+ }
+ else
+ {
+ if( GetStyle() & WB_MENUSTYLEVALUESET )
+ mbHighlight = TRUE;
+
+ ImplHighlightItem( mnSelItemId, FALSE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::ImplEndTracking( const Point& rPos, 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 = FALSE;
+ mbSelection = FALSE;
+ Select();
+ }
+ else
+ {
+ ImplHighlightItem( mnSelItemId, FALSE );
+ mbHighlight = FALSE;
+ mbSelection = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ if ( rMEvt.IsLeft() )
+ {
+ ValueSetItem* pItem = ImplGetItem( ImplGetItem( rMEvt.GetPosPixel() ) );
+ if ( mbSelection )
+ {
+ mbHighlight = 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 = 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(), FALSE );
+ else
+ Control::MouseButtonUp( rMEvt );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::MouseMove( const MouseEvent& rMEvt )
+{
+ // Wegen SelectionMode
+ if ( mbSelection || (GetStyle() & WB_MENUSTYLEVALUESET) )
+ ImplTracking( rMEvt.GetPosPixel(), 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 )
+{
+ USHORT nLastItem = (USHORT)mpImpl->mpItemList->Count();
+ USHORT nItemPos = VALUESET_ITEM_NOTFOUND;
+ USHORT nCurPos;
+ USHORT nCalcPos;
+
+ if ( !nLastItem || !ImplGetFirstItem() )
+ {
+ Control::KeyInput( rKEvt );
+ return;
+ }
+ else
+ nLastItem--;
+
+ if ( mnSelItemId )
+ nCurPos = GetItemPos( mnSelItemId );
+ else
+ nCurPos = VALUESET_ITEM_NONEITEM;
+ nCalcPos = nCurPos;
+
+ //switch off selection mode if key travelling is used
+ BOOL bDefault = 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< USHORT >(
+ nCalcPos - ( nLineCount * mnCols ));
+ else
+ {
+ if( (KEY_UP == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) )
+ {
+ Window* pParent = GetParent();
+ pParent->GrabFocus();
+ pParent->KeyInput( rKEvt );
+ break;
+ }
+ 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< USHORT >(
+ nCalcPos + ( nLineCount * mnCols ));
+ else
+ {
+ if( (KEY_DOWN == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) )
+ {
+ Window* pParent = GetParent();
+ pParent->GrabFocus();
+ pParent->KeyInput( rKEvt );
+ break;
+ }
+ else
+ {
+ 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 = TRUE;
+ break;
+ }
+
+ if(!bDefault)
+ EndSelection();
+ if ( nItemPos != VALUESET_ITEM_NOTFOUND )
+ {
+ USHORT 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( 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( FALSE ) );
+ if( pAcc )
+ pAcc->LoseFocus();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Resize()
+{
+ mbFormat = 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() );
+ USHORT 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( TRUE, FALSE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
+ {
+ ImplInitSettings( FALSE, TRUE, FALSE );
+ Invalidate();
+ }
+ else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
+ {
+ ImplInitSettings( FALSE, FALSE, TRUE );
+ Invalidate();
+ }
+ else if ( (nType == STATE_CHANGE_STYLE) || (nType == STATE_CHANGE_ENABLE) )
+ {
+ mbFormat = TRUE;
+ ImplInitSettings( FALSE, FALSE, 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 = TRUE;
+ ImplInitSettings( TRUE, TRUE, TRUE );
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Select()
+{
+ maSelectHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::DoubleClick()
+{
+ maDoubleClickHdl.Call( this );
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::UserDraw( const UserDrawEvent& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( USHORT nItemId, const Image& rImage, USHORT 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, (ULONG)nPos );
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( USHORT nItemId, const Color& rColor, USHORT 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, (ULONG)nPos );
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( USHORT nItemId, const Image& rImage,
+ const XubString& rText, USHORT 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, (ULONG)nPos );
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( USHORT nItemId, const Color& rColor,
+ const XubString& rText, USHORT 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, (ULONG)nPos );
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertItem( USHORT nItemId, USHORT 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, (ULONG)nPos );
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::InsertSpace( USHORT nItemId, USHORT 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, (ULONG)nPos );
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::RemoveItem( USHORT nItemId )
+{
+ USHORT 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 = TRUE;
+ }
+
+ mbFormat = 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 = TRUE;
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::Clear()
+{
+ ImplDeleteItems();
+
+ // Variablen zuruecksetzen
+ mnFirstLine = 0;
+ mnCurCol = 0;
+ mnOldItemId = 0;
+ mnHighItemId = 0;
+ mnSelItemId = 0;
+ mbNoSelection = TRUE;
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::GetItemCount() const
+{
+ return (USHORT)mpImpl->mpItemList->Count();
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::GetItemPos( USHORT nItemId ) const
+{
+ ValueSetItem* pItem = mpImpl->mpItemList->First();
+ while ( pItem )
+ {
+ if ( pItem->mnId == nItemId )
+ return (USHORT)mpImpl->mpItemList->GetCurPos();
+ pItem = mpImpl->mpItemList->Next();
+ }
+
+ return VALUESET_ITEM_NOTFOUND;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::GetItemId( USHORT nPos ) const
+{
+ ValueSetItem* pItem = mpImpl->mpItemList->GetObject( nPos );
+
+ if ( pItem )
+ return pItem->mnId;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::GetItemId( const Point& rPos ) const
+{
+ USHORT nItemPos = ImplGetItem( rPos );
+ if ( nItemPos != VALUESET_ITEM_NOTFOUND )
+ return GetItemId( nItemPos );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle ValueSet::GetItemRect( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->maRect;
+ else
+ return Rectangle();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::EnableFullItemMode( BOOL bFullMode )
+{
+ mbFullMode = bFullMode;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetColCount( USHORT nNewCols )
+{
+ if ( mnUserCols != nNewCols )
+ {
+ mnUserCols = nNewCols;
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetLineCount( USHORT nNewLines )
+{
+ if ( mnUserVisLines != nNewLines )
+ {
+ mnUserVisLines = nNewLines;
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemWidth( long nNewItemWidth )
+{
+ if ( mnUserItemWidth != nNewItemWidth )
+ {
+ mnUserItemWidth = nNewItemWidth;
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemHeight( long nNewItemHeight )
+{
+ if ( mnUserItemHeight != nNewItemHeight )
+ {
+ mnUserItemHeight = nNewItemHeight;
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetFirstLine( USHORT nNewLine )
+{
+ if ( mnFirstLine != nNewLine )
+ {
+ mnFirstLine = nNewLine;
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SelectItem( USHORT nItemId )
+{
+ USHORT 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 )
+ {
+ USHORT nOldItem = mnSelItemId ? mnSelItemId : 1;
+ mnSelItemId = nItemId;
+ mbNoSelection = FALSE;
+
+ BOOL bNewOut;
+ BOOL bNewLine;
+ if ( !mbFormat && IsReallyVisible() && IsUpdateMode() )
+ bNewOut = TRUE;
+ else
+ bNewOut = FALSE;
+ bNewLine = FALSE;
+
+ // Gegebenenfalls in den sichtbaren Bereich scrollen
+ if ( mbScroll && nItemId )
+ {
+ USHORT nNewLine = (USHORT)(nItemPos / mnCols);
+ if ( nNewLine < mnFirstLine )
+ {
+ mnFirstLine = nNewLine;
+ bNewLine = TRUE;
+ }
+ else if ( nNewLine > (USHORT)(mnFirstLine+mnVisLines-1) )
+ {
+ mnFirstLine = (USHORT)(nNewLine-mnVisLines+1);
+ bNewLine = TRUE;
+ }
+ }
+
+ if ( bNewOut )
+ {
+ if ( bNewLine )
+ {
+ // Falls sich der sichtbare Bereich geaendert hat,
+ // alles neu ausgeben
+ mbFormat = TRUE;
+ ImplDraw();
+ }
+ else
+ {
+ // alte Selection wegnehmen und neue ausgeben
+ ImplHideSelect( nOldItem );
+ ImplDrawSelect();
+ }
+ }
+
+ if( ImplHasAccessibleListeners() )
+ {
+ // focus event (deselect)
+ if( nOldItem )
+ {
+ const USHORT 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 USHORT 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 );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetNoSelection()
+{
+ mbNoSelection = TRUE;
+ mbHighlight = FALSE;
+ mbSelection = FALSE;
+
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplDraw();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemBits( USHORT nItemId, USHORT nItemBits )
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ mpImpl->mpItemList->GetObject( nPos )->mnBits = nItemBits;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::GetItemBits( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->mnBits;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemImage( USHORT nItemId, const Image& rImage )
+{
+ USHORT 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 = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Image ValueSet::GetItemImage( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->maImage;
+ else
+ return Image();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemColor( USHORT nItemId, const Color& rColor )
+{
+ USHORT 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 = TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Color ValueSet::GetItemColor( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->maColor;
+ else
+ return Color();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemData( USHORT nItemId, void* pData )
+{
+ USHORT 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 = TRUE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void* ValueSet::GetItemData( USHORT nItemId ) const
+{
+ USHORT nPos = GetItemPos( nItemId );
+
+ if ( nPos != VALUESET_ITEM_NOTFOUND )
+ return mpImpl->mpItemList->GetObject( nPos )->mpData;
+ else
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetItemText( USHORT nItemId, const XubString& rText )
+{
+ USHORT 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() )
+ {
+ USHORT 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( USHORT nItemId ) const
+{
+ USHORT 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 = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ ImplDraw();
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::SetExtraSpacing( USHORT nNewSpacing )
+{
+ if ( GetStyle() & WB_ITEMBORDER )
+ {
+ mnSpacing = nNewSpacing;
+
+ mbFormat = TRUE;
+ if ( IsReallyVisible() && IsUpdateMode() )
+ Invalidate();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::StartSelection()
+{
+ mnOldItemId = mnSelItemId;
+ mbHighlight = TRUE;
+ mbSelection = TRUE;
+ mnHighItemId = mnSelItemId;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::EndSelection()
+{
+ if ( mbHighlight )
+ {
+ if ( IsTracking() )
+ EndTracking( ENDTRACK_CANCEL );
+
+ ImplHighlightItem( mnSelItemId );
+ mbHighlight = FALSE;
+ }
+ mbSelection = FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL ValueSet::StartDrag( const CommandEvent& rCEvt, Region& rRegion )
+{
+ if ( rCEvt.GetCommand() != COMMAND_STARTDRAG )
+ return 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.
+ USHORT nSelId;
+ if ( rCEvt.IsMouseEvent() )
+ nSelId = GetItemId( rCEvt.GetMousePosPixel() );
+ else
+ nSelId = mnSelItemId;
+
+ // Falls kein Eintrag angeklickt wurde, starten wir kein Dragging
+ if ( !nSelId )
+ return 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 TRUE;
+}
+
+// -----------------------------------------------------------------------
+
+Size ValueSet::CalcWindowSizePixel( const Size& rItemSize, USHORT nDesireCols,
+ USHORT 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, 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;
+}
+
+// -----------------------------------------------------------------------
+
+USHORT ValueSet::ShowDropPos( const Point& rPos )
+{
+ mbDropPos = TRUE;
+
+ // Gegebenenfalls scrollen
+ ImplScroll( rPos );
+
+ // DropPosition ermitteln
+ USHORT nPos = ImplGetItem( rPos, 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 = (USHORT)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( FALSE );
+ mnDropPos = nPos;
+ ImplDrawDropPos( TRUE );
+ }
+
+ return mnDropPos;
+}
+
+// -----------------------------------------------------------------------
+
+void ValueSet::HideDropPos()
+{
+ if ( mbDropPos )
+ {
+ ImplDrawDropPos( FALSE );
+ mbDropPos = FALSE;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool ValueSet::IsRTLActive (void)
+{
+ return Application::GetSettings().GetLayoutRTL() && IsRTLEnabled();
+}
+