diff options
Diffstat (limited to 'svtools/source/control')
24 files changed, 21596 insertions, 0 deletions
diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx new file mode 100644 index 000000000000..bc85863fb7b3 --- /dev/null +++ b/svtools/source/control/calendar.cxx @@ -0,0 +1,2963 @@ +/************************************************************************* + * + * $RCSfile: calendar.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#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 + +#define _SV_CALENDAR_CXX +#include <svtools.hrc> +#include <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) + +// ======================================================================= + +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; + 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) ), + maIntn( Application::GetAppInternational() ), + 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 ), + maIntn( Application::GetAppInternational() ), + 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.aWinBits ); +} + +// ----------------------------------------------------------------------- + +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::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; + + DayOfWeek eStartDay = maIntn.GetWeekStart(); + + 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 ); + + // DayOffWeekText berechnen (werden im schmalen Font ausgegeben) + maDayOfWeekText.Erase(); + long nStartOffX = 0; + USHORT eDay = (USHORT)eStartDay; + for ( USHORT nDayOfWeek = 0; nDayOfWeek < 7; nDayOfWeek++ ) + { + String aDayOfWeek( maIntn.GetAbbrevDayText( (DayOfWeek)eDay ).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; + eDay++; + eDay %= 7; + } + + mbCalc = FALSE; + } + + // Anzahl Tage berechnen + 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 = maIntn.GetWeekStart(); + + 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 nOffX; + long nOffY; + long nDayX; + long nDayY; + ULONG nToday = Date().GetDate(); + USHORT nDay; + USHORT nMonth; + USHORT nYear; + Date aDate = GetFirstMonth(); + DayOfWeek eStartDay = maIntn.GetWeekStart(); + + 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 + nOffX = nX; + nOffY = nY+TITLE_BORDERY; + String aMonthText( maIntn.GetMonthText( nMonth ) ); + aMonthText += ' '; + aMonthText += 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 ) + { + aMonthText = maIntn.GetAbbrevMonthText( nMonth ); + aMonthText += ' '; + aMonthText += nYear; + nMonthTextWidth = GetTextWidth( aMonthText ); + } + long nTempOff = (mnMonthWidth-nMonthTextWidth+1)/2; + if ( nTempOff < nMonthOffX1 ) + nOffX += nMonthOffX1+1; + else + { + if ( nTempOff+nMonthTextWidth > mnMonthWidth-nMonthOffX2 ) + nOffX += mnMonthWidth-nMonthOffX2-nMonthTextWidth; + else + nOffX += nTempOff; + } + SetTextColor( rStyleSettings.GetButtonTextColor() ); + DrawText( Point( nOffX, nOffY ), aMonthText ); + SetTextColor( rStyleSettings.GetWindowTextColor() ); + + // Weekleiste ausgeben + if ( bPaint ) + { + nDayX = nX+mnDaysOffX; + nDayY = nY+mnWeekDayOffY; + nOffY = nDayY + mnDayHeight; + SetLineColor( rStyleSettings.GetWindowTextColor() ); + Point aStartPos( nDayX, nOffY ); + if ( mnWinStyle & WB_WEEKNUMBER ) + aStartPos.X() -= WEEKNUMBER_OFFX-2; + DrawLine( aStartPos, Point( nDayX+(7*mnDayWidth), nOffY ) ); + DrawTextArray( Point( nDayX+mnDayOfWeekAry[0], nDayY ), maDayOfWeekText, &(mnDayOfWeekAry[1]) ); + } + + // Week-Numbers ausgeben + if ( mnWinStyle & WB_WEEKNUMBER ) + { + nDayX = nX+mnDaysOffX; + nDayY = nY+mnWeekDayOffY; + nOffY = nDayY + mnDayHeight; + long nMonthHeight = mnDayHeight*6; + if ( bPaint ) + DrawLine( Point( nDayX-WEEKNUMBER_OFFX+2, nOffY ), Point( nDayX-WEEKNUMBER_OFFX+2, nOffY+nMonthHeight ) ); + else + Erase( Rectangle( nDayX-mnWeekWidth-WEEKNUMBER_OFFX, nOffY, nDayX-WEEKNUMBER_OFFX-1, nOffY+nMonthHeight ) ); + + Font aOldFont = GetFont(); + Font aTempFont = aOldFont; + ImplGetWeekFont( aTempFont ); + SetFont( aTempFont ); + nDayX -= mnWeekWidth; + nDayY = nY+mnDaysOffY; + Date aTempDate = aDate; + for ( USHORT nWeekCount = 0; nWeekCount < 6; nWeekCount++ ) + { + String aWeekText( aTempDate.GetWeekOfYear( eStartDay, maIntn.GetWeekCountStart() ) ); + long nOffX = (mnWeekWidth-WEEKNUMBER_OFFX)-GetTextWidth( aWeekText ); + long nOffY = (mnDayHeight-GetTextHeight())/2; + DrawText( Point( nDayX+nOffX, nDayY+nOffY ), aWeekText ); + nDayY += mnDayHeight; + aTempDate += 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++ ) + { + nOffX = nDayX + (nDay*mnDayWidth); + ImplDrawDate( nOffX, nDayY, nDay+aTempDate.GetDay(), + aTempDate.GetMonth(), aTempDate.GetYear(), + (DayOfWeek)((nDay+(USHORT)eStartDay)%7), FALSE, TRUE, nToday ); + } + } + for ( nDay = 1; nDay <= nDaysInMonth; nDay++ ) + { + nOffX = nDayX + (nDayIndex*mnDayWidth); + ImplDrawDate( nOffX, 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++ ) + { + nOffX = nDayX + (nDayIndex*mnDayWidth); + ImplDrawDate( nOffX, 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, maIntn.GetMonthText( j ) ); + 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 -= nTempMonthOff; + else + { + nNewYear--; + nNewMonth = 12-(nTempMonthOff-nNewMonth); + } + 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( const Point& rPos, 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*, pTimer ) +{ + 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( rMEvt.GetPosPixel(), 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( aMousePos, 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 ); + } + 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& rRect ) +{ + 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 ) + { + USHORT nWeek = aDate.GetWeekOfYear( maIntn.GetWeekStart(), maIntn.GetWeekCountStart() ); + 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::SetInternational( const International& rIntn ) +{ + ImplUpdate( TRUE ); + + maIntn = rIntn; +} + +// ----------------------------------------------------------------------- + +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 maFirstDate = GetFirstMonth(); + maFirstDate += maFirstDate.GetDaysInMonth(); + aTempDate++; + while ( nDateOff > aTempDate.GetDaysInMonth() ) + { + maFirstDate += maFirstDate.GetDaysInMonth(); + long nDaysInMonth = aTempDate.GetDaysInMonth(); + aTempDate += nDaysInMonth; + nDateOff -= nDaysInMonth; + } + SetFirstDate( maFirstDate ); + } + 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)maIntn.GetWeekStart())) % 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)maIntn.GetWeekStart())) % 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 ) +{ + 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_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; +} diff --git a/svtools/source/control/calendar.src b/svtools/source/control/calendar.src new file mode 100644 index 000000000000..2919e3d55148 --- /dev/null +++ b/svtools/source/control/calendar.src @@ -0,0 +1,166 @@ +/************************************************************************* + * + * $RCSfile: calendar.src,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include "svtools.hrc" +String STR_SVT_CALENDAR_DAY +{ + Text = "Tag" ; + Text [ ENGLISH ] = "Day" ; + Text [ english_us ] = "Day" ; + Text [ italian ] = "Giorno" ; + Text [ spanish ] = "Día" ; + Text [ french ] = "Jour" ; + Text [ dutch ] = "Dag" ; + Text [ swedish ] = "Dag" ; + Text [ danish ] = "Dag" ; + Text [ portuguese_brazilian ] = "Tag" ; + Text [ portuguese ] = "Dia" ; + Text[ chinese_simplified ] = "Ìì"; + Text[ russian ] = "Äåíü"; + Text[ polish ] = "dzieñ"; + Text[ japanese ] = "“ú"; + Text[ chinese_traditional ] = "¤Ñ"; + Text[ arabic ] = "íæã"; + Text[ dutch ] = "Dag"; + Text[ chinese_simplified ] = "Ìì"; + Text[ greek ] = "ÇìÝñá"; + Text[ korean ] = "ÀÏÀÚ"; + Text[ turkish ] = "Gün"; + Text[ language_user1 ] = " "; +}; +String STR_SVT_CALENDAR_WEEK +{ + Text = "Woche" ; + Text [ ENGLISH ] = "Week" ; + Text [ dutch ] = "Week" ; + Text [ english_us ] = "Week" ; + Text [ italian ] = "Settim." ; + Text [ spanish ] = "Semana" ; + Text [ french ] = "Semaine" ; + Text [ swedish ] = "Vecka" ; + Text [ danish ] = "Uge" ; + Text [ portuguese ] = "Semana" ; + Text [ portuguese_brazilian ] = "Woche" ; + Text[ chinese_simplified ] = "ÖÜ"; + Text[ russian ] = "Íåäåëÿ"; + Text[ polish ] = "tydzieñ"; + Text[ japanese ] = "T"; + Text[ chinese_traditional ] = "©P"; + Text[ arabic ] = "ÃÓÈæÚ"; + Text[ dutch ] = "Week"; + Text[ chinese_simplified ] = "ÖÜ"; + Text[ greek ] = "ÅâäïìÜäá"; + Text[ korean ] = "ÁÖ"; + Text[ turkish ] = "Hafta"; + Text[ language_user1 ] = " "; +}; +String STR_SVT_CALENDAR_TODAY +{ + Text = "Heute" ; + Text [ ENGLISH ] = "Today" ; + Text [ portuguese ] = "Hoje" ; + Text [ english_us ] = "Today" ; + Text [ portuguese_brazilian ] = "Heute" ; + Text [ swedish ] = "Idag" ; + Text [ danish ] = "I dag" ; + Text [ italian ] = "Oggi" ; + Text [ spanish ] = "Hoy" ; + Text [ french ] = "Aujourd'hui" ; + Text [ dutch ] = "Vandaag" ; + Text[ chinese_simplified ] = "½ñÌì"; + Text[ russian ] = "Ñåãîäíÿ"; + Text[ polish ] = "dzisiaj"; + Text[ japanese ] = "¡“ú"; + Text[ chinese_traditional ] = "¤µ¤Ñ"; + Text[ arabic ] = "Çáíæã"; + Text[ dutch ] = "Vandaag"; + Text[ chinese_simplified ] = "½ñÌì"; + Text[ greek ] = "ÓÞìåñá"; + Text[ korean ] = "¿À´Ã"; + Text[ turkish ] = "Bugün"; + Text[ language_user1 ] = " "; +}; +String STR_SVT_CALENDAR_NONE +{ + Text = "Keines" ; + Text [ ENGLISH ] = "None" ; + Text [ portuguese ] = "Nenhum" ; + Text [ english_us ] = "None" ; + Text [ portuguese_brazilian ] = "Keines" ; + Text [ swedish ] = "Ingen" ; + Text [ danish ] = "Ingen" ; + Text [ italian ] = "Senza" ; + Text [ spanish ] = "Ninguno" ; + Text [ french ] = "Aucun(e)" ; + Text [ dutch ] = "Geen" ; + Text[ chinese_simplified ] = "ÎÞ"; + Text[ russian ] = "Áåç"; + Text[ polish ] = "brak"; + Text[ japanese ] = "‚È‚µ"; + Text[ chinese_traditional ] = "µL"; + Text[ arabic ] = "ÈÏæä"; + Text[ dutch ] = "Geen"; + Text[ chinese_simplified ] = "ÎÞ"; + Text[ greek ] = "ÊáíÝíá"; + Text[ korean ] = "¾øÀ½"; + Text[ turkish ] = "Yok"; + Text[ language_user1 ] = " "; +}; diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx new file mode 100644 index 000000000000..2af1f99aeadf --- /dev/null +++ b/svtools/source/control/ctrlbox.cxx @@ -0,0 +1,1227 @@ +/************************************************************************* + * + * $RCSfile: ctrlbox.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _CTRLBOX_CXX + +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _APP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _FIELD_HXX +#include <vcl/field.hxx> +#endif + +#include <svtdata.hxx> +#include <svtools.hrc> +#include <ctrlbox.hxx> +#include <ctrltool.hxx> + +#define IMGTEXTSPACE 2 +#define SYMBOLFONTTEXT "AbCdEfGhIj" +#define EXTRAFONTSIZE 5 + +// ======================================================================== +// 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::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( COL_BLACK ); + 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* ); + +// ----------------------------------------------------------------------- + +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( aColor ); + 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" ); + } + + rStr.Insert( aIntn.GetNum( nLine1+nLine2+nDistance, 2 ), 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 ) ); +} + +// ----------------------------------------------------------------------- + +LineListBox::LineListBox( Window* pParent, WinBits nWinStyle ) : + ListBox( pParent, nWinStyle ), + aIntn( Application::GetAppInternational() ), + aColor( COL_BLACK ) +{ + ImplInit(); +} + +// ----------------------------------------------------------------------- + +LineListBox::LineListBox( Window* pParent, const ResId& rResId ) : + ListBox( pParent, rResId ), + aIntn( Application::GetAppInternational() ), + aColor( 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::SetColor( const Color& rColor ) +{ + // Farben austauschen + aColor = rColor; + + // Variablen anlegen + ULONG n = 0; + ULONG nCount = pLineList->Count(); + if ( !nCount ) + return; + + XubString aStr; + Bitmap aBmp; + + // Eintrage mit Linien austauschen + SetUpdateMode( FALSE ); + USHORT nSelEntry = GetSelectEntryPos(); + while ( n < nCount ) + { + ImpLineListData* pData = pLineList->GetObject( n ); + if ( pData ) + { + // ListBox-Daten austauschen + ListBox::RemoveEntry( (USHORT)n ); + ImpGetLine( pData->nLine1, pData->nLine2, pData->nDistance, + aBmp, aStr ); + ListBox::InsertEntry( aStr, aBmp, (USHORT)n ); + } + + n++; + } + + if ( nSelEntry != LISTBOX_ENTRY_NOTFOUND ) + SelectEntryPos( nSelEntry ); + + SetUpdateMode( TRUE ); + Invalidate(); +} + +// =================================================================== +// 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 ), + maImagePrinterFont( SvtResId( RID_IMG_PRINTERFONT ) ), + maImageBitmapFont( SvtResId( RID_IMG_BITMAPFONT ) ), + maImageScalableFont( SvtResId( RID_IMG_SCALABLEFONT ) ) +{ + mpFontList = NULL; + mbWYSIWYG = FALSE; + mbSymbols = FALSE; +} + +// ------------------------------------------------------------------- + +FontNameBox::FontNameBox( Window* pParent, const ResId& rResId ) : + ComboBox( pParent, rResId ), + maImagePrinterFont( SvtResId( RID_IMG_PRINTERFONT ) ), + maImageBitmapFont( SvtResId( RID_IMG_BITMAPFONT ) ), + maImageScalableFont( SvtResId( RID_IMG_SCALABLEFONT ) ) +{ + mpFontList = NULL; + mbWYSIWYG = FALSE; + mbSymbols = FALSE; +} + +// ------------------------------------------------------------------- + +FontNameBox::~FontNameBox() +{ + ImplDestroyFontList(); +} + +// ------------------------------------------------------------------- + +void FontNameBox::ImplDestroyFontList() +{ + if ( mpFontList ) + { + ImplFontNameListData* pInfo = mpFontList->First(); + while ( pInfo ) + { + delete pInfo; + pInfo = mpFontList->Next(); + } + delete mpFontList; + } +} + +// ------------------------------------------------------------------- + +void FontNameBox::Fill( const FontList* pList ) +{ + // Vorherigen Namen merken und Box loeschen + XubString aOldText = GetText(); + Clear(); + + ImplDestroyFontList(); + mpFontList = new ImplFontList; + + // Fonts eintragen + 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(); + + // Text wieder setzen + 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; + 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; + } + + // Maximale Breite schaetzen + Size aOneCharSz( GetTextWidth( XubString( 'X' ) ), GetTextHeight() ); + Size aSz( aOneCharSz ); + aSz.Width() *= nMaxLen; + // Nur XX% der Breite, weil die ListBox die normalen Breiten berechnet... + aSz.Width() *= 1; + aSz.Width() /= 10; + if ( bSymbolFont ) + aSz.Width() += (sizeof( SYMBOLFONTTEXT )-1) * aOneCharSz.Width(); + 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; + if ( bSymbolFont ) + { + XubString 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 aSz( aOldFont.GetSize() ); + aSz.Height() += EXTRAFONTSIZE; + Font aFont( rInfo ); + aFont.SetSize( aSz ); + rUDEvt.GetDevice()->SetFont( aFont ); + rUDEvt.GetDevice()->SetTextColor( aTextColor ); + long nTextHeight = rUDEvt.GetDevice()->GetTextHeight(); + Point aPos( nX, aTopLeft.Y() + (nH-nTextHeight)/2 ); + if ( bSymbolFont ) + rUDEvt.GetDevice()->DrawText( aPos, XubString( RTL_CONSTASCII_USTRINGPARAM( SYMBOLFONTTEXT ) ) ); + else + rUDEvt.GetDevice()->DrawText( aPos, rInfo.GetName() ); + rUDEvt.GetDevice()->SetFont( aOldFont ); + DrawEntry( rUDEvt, FALSE, FALSE); // Separator + } + 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() +{ + // Damit Text nach einem Fill erhalten bleibt + aLastStyle = GetText(); + ComboBox::Select(); +} + +// ------------------------------------------------------------------- + +void FontStyleBox::LoseFocus() +{ + // Damit Text nach einem Fill erhalten bleibt + aLastStyle = GetText(); + ComboBox::LoseFocus(); +} + +// ------------------------------------------------------------------- + +void FontStyleBox::Modify() +{ + International aIntn = Application::GetAppInternational(); + XubString aStr = GetText(); + USHORT nEntryCount = GetEntryCount(); + + if ( GetEntryPos( aStr ) == COMBOBOX_ENTRY_NOTFOUND ) + { + aIntn.ToUpper( aStr ); + for ( USHORT i = 0; i < nEntryCount; i++ ) + { + XubString aEntryText = GetEntry( i ); + aIntn.ToUpper( aEntryText ); + + if ( aStr == aEntryText ) + { + SetText( GetEntry( i ) ); + break; + } + } + } + + ComboBox::Modify(); +} + +// ------------------------------------------------------------------- + +void FontStyleBox::Fill( const XubString& rName, const FontList* pList ) +{ + // Achtung: In dieser Methode muss ComboBox::SetText() aufgerufen werden, + // da sonst aLastStyle ueberschrieben wird + // Vorherige Position merken und Box loeschen + XubString aOldText = GetText(); + USHORT nPos = GetEntryPos( aOldText ); + Clear(); + + // Existiert ein Font mit diesem Namen + sal_Handle hFontInfo = pList->GetFirstFontInfo( rName ); + if ( hFontInfo ) + { + BOOL bFound = FALSE; + BOOL bNormal = FALSE; + BOOL bItalic = FALSE; + BOOL bBold = FALSE; + BOOL bBoldItalic = FALSE; + FontInfo aInfo; + while ( hFontInfo ) + { + aInfo = pList->GetFontInfo( hFontInfo ); + + XubString aStyleText = pList->GetStyleName( aInfo ); + FontWeight eWeight = aInfo.GetWeight(); + FontItalic eItalic = aInfo.GetItalic(); + if ( eWeight <= WEIGHT_NORMAL ) + { + bNormal = TRUE; + if ( eItalic != ITALIC_NONE ) + bItalic = TRUE; + } + else + { + if ( eItalic != ITALIC_NONE ) + bBoldItalic = TRUE; + else + bBold = TRUE; + } + if ( aStyleText == pList->GetItalicStr() ) + bItalic = TRUE; + else if ( aStyleText == pList->GetBoldStr() ) + bBold = TRUE; + else if ( aStyleText == pList->GetBoldItalicStr() ) + bBoldItalic = TRUE; + if ( !bFound && (aStyleText == aLastStyle) ) + bFound = TRUE; + + // Falls doch mal doppelte Strings kommen, dann + // nach Moeglichkeit abfangen + if ( GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND ) + InsertEntry( aStyleText ); + + hFontInfo = pList->GetNextFontInfo( hFontInfo ); + } + + // Bestimmte Styles als Nachbildung + if ( bNormal ) + { + if ( !bItalic ) + { + if ( !bFound && (aLastStyle == pList->GetItalicStr()) ) + bFound = TRUE; + InsertEntry( pList->GetItalicStr() ); + } + if ( !bBold ) + { + if ( !bFound && (aLastStyle == pList->GetBoldStr()) ) + bFound = TRUE; + InsertEntry( pList->GetBoldStr() ); + } + } + if ( !bBoldItalic ) + { + if ( bNormal || bItalic || bBold ) + { + if ( !bFound && (aLastStyle == pList->GetBoldItalicStr()) ) + bFound = TRUE; + InsertEntry( pList->GetBoldItalicStr() ); + } + } + if ( aOldText.Len() ) + { + if ( bFound ) + 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; + + International aIntn = GetInternational(); + aIntn.SetNumTrailingZeros( FALSE ); + SetInternational( aIntn ); + + SetDecimalDigits( 1 ); + SetMin( 20 ); + SetMax( 9999 ); +} + +// ----------------------------------------------------------------------- + +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 ); + + MetricBox::Modify(); + } +} + +// ----------------------------------------------------------------------- + +void FontSizeBox::Fill( const FontInfo& rInfo, const FontList* pList ) +{ + // Merken fuer Relative-Mode + aFontInfo = rInfo; + pFontList = pList; + + // Im Relative-Mode, muessen keine Fontgroessen gesetzt werden + if ( bRelative ) + return; + + // Fontgroessen abfragen + const long* pAry = pList->GetSizeAry( rInfo ); + + // Wenn es das Array mit den Standardgroessen ist, muessen wir im + // Normalfall die ListBox nicht neu fuellen + if ( (pAry == pList->GetStdSizeAry()) && GetEntryCount() ) + { + if ( bStdSize ) + return; + bStdSize = TRUE; + } + else + bStdSize = FALSE; + + Selection aSelection = GetSelection(); + XubString aStr = GetText(); + + Clear(); + + while ( *pAry ) + { + InsertValue( *pAry ); + pAry++; + } + + 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: mehr als 100 Werte machen keinen Sinn + while ( i <= nPtRelMax && n++ < 100 ) + { + InsertValue( i ); + i += nPtRelStep; + } + } + else + { + SetDecimalDigits( 0 ); + SetMin( nRelMin ); + SetMax( nRelMax ); + SetCustomUnitText( '%' ); + SetUnit( FUNIT_CUSTOM ); + + Clear(); + USHORT i = nRelMin; + while ( i <= nRelMax ) + { + InsertValue( 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( long nValue ) const +{ + XubString sRet( MetricBox::CreateFieldText( nValue ) ); + if ( bRelativeMode && bPtRelative && (0 <= nValue) && sRet.Len() ) + sRet.Insert( '+', 0 ); + return sRet; +} diff --git a/svtools/source/control/ctrlbox.src b/svtools/source/control/ctrlbox.src new file mode 100644 index 000000000000..db8eb8810ec7 --- /dev/null +++ b/svtools/source/control/ctrlbox.src @@ -0,0 +1,85 @@ +/************************************************************************* + * + * $RCSfile: ctrlbox.src,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include "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_PRINTERFONT +{ + ImageBitmap = Bitmap { File = "prnfont.bmp" ; }; + MaskColor = IMAGE_STDBTN_COLOR ; +}; + +IMAGE RID_IMG_BITMAPFONT +{ + ImageBitmap = Bitmap { File = "bmpfont.bmp" ; }; + MaskColor = IMAGE_STDBTN_COLOR ; +}; + diff --git a/svtools/source/control/ctrldll.cxx b/svtools/source/control/ctrldll.cxx new file mode 100644 index 000000000000..19c26d4e80cf --- /dev/null +++ b/svtools/source/control/ctrldll.cxx @@ -0,0 +1,112 @@ +/************************************************************************* + * + * $RCSfile: ctrldll.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef WIN + +#ifndef _SVWIN_H +#include <svwin.h> +#endif + +#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..ed38c9cc7a93 --- /dev/null +++ b/svtools/source/control/ctrltool.cxx @@ -0,0 +1,865 @@ +/************************************************************************* + * + * $RCSfile: ctrltool.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define CTRLTOOL_CXX + +#include <string.h> + +#ifndef TOOLS_INTN_HXX +#include <tools/intn.hxx> +#endif +#ifndef TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#ifndef _VCL_WINDOW_HXX +#include <vcl/window.hxx> +#endif +#ifndef _VCL_SYSTEM_HXX +#include <vcl/system.hxx> +#endif +#ifndef _SV_SVAPP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _SV_WRKWIN_HXX +#include <vcl/wrkwin.hxx> +#endif + +#define private public + +#include <svtools.hrc> +#include <svtdata.hxx> +#include <ctrltool.hxx> + +// ======================================================================= + +// Standard Fontgroessen fuer scalierbare Fonts +static long aStdSizeAry[] = +{ + 60, + 70, + 80, + 90, + 100, + 110, + 120, + 140, + 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 ) +{ + 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 nCount = Count(); + if ( !nCount ) + { + if ( pIndex ) + *pIndex = LIST_APPEND; + return NULL; + } + else + { + ImplFontListNameInfo* pCmpData = (ImplFontListNameInfo*)List::GetObject( nCount-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 = nCount-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 + USHORT 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, 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; + } +} + +// ----------------------------------------------------------------------- + +XubString FontList::GetStyleName( const FontInfo& rInfo ) const +{ + XubString aStyleName = rInfo.GetStyleName(); + + // Nur wenn kein StyleName gesetzt ist, geben wir einen syntetischen + // Namen zurueck + if ( !aStyleName.Len() ) + { + FontWeight eWeight = rInfo.GetWeight(); + FontItalic eItalic = rInfo.GetItalic(); + if ( eWeight > WEIGHT_BOLD ) + { + if ( eItalic > ITALIC_NONE ) + aStyleName = maBlackItalic; + else + aStyleName = maBlack; + } + else if ( eWeight > WEIGHT_MEDIUM ) + { + if ( eItalic > ITALIC_NONE ) + aStyleName = maBoldItalic; + else + aStyleName = maBold; + } + else if ( eWeight > WEIGHT_LIGHT ) + { + if ( eItalic > ITALIC_NONE ) + aStyleName = maNormalItalic; + else + aStyleName = maNormal; + } + else if ( eWeight != WEIGHT_DONTKNOW ) + { + if ( eItalic > ITALIC_NONE ) + aStyleName = maLightItalic; + else + aStyleName = maLight; + } + else + { + if ( eItalic > ITALIC_NONE ) + aStyleName = maNormalItalic; + else + aStyleName = maNormal; + } + } + + return aStyleName; +} + +// ----------------------------------------------------------------------- + +XubString FontList::GetFontMapText( const FontInfo& rInfo ) const +{ + if ( !rInfo.GetName().Len() ) + { + XubString aEmptryStr; + return aEmptryStr; + } + + ImplFontListNameInfo* pData = ImplFindByName( rInfo.GetName() ); + if ( !pData ) + { + if ( !maMapNotAvailable.Len() ) + ((FontList*)this)->maMapNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_NOTAVAILABLE ) ); + return maMapNotAvailable; + } + + USHORT nType = pData->mnType; + 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; + } + else if ( (nType & (FONTLIST_FONTNAMETYPE_PRINTER | FONTLIST_FONTNAMETYPE_SCREEN)) == FONTLIST_FONTNAMETYPE_SCREEN ) + { + if ( !maMapScreenOnly.Len() ) + ((FontList*)this)->maMapScreenOnly = XubString( SvtResId( STR_SVT_FONTMAP_SCREENONLY ) ); + return maMapScreenOnly; + } + else + { + BOOL bNotSynthetic = FALSE; + BOOL bNoneAvailable = FALSE; + const XubString& rStyleName = rInfo.GetStyleName(); + FontWeight eMinWeight = pData->mpFirst->GetWeight(); + FontWeight eWeight = rInfo.GetWeight(); + FontItalic eItalic = rInfo.GetItalic(); + ImplFontListFontInfo* pFontInfo = pData->mpFirst; + if ( rStyleName.Len() ) + { + while ( pFontInfo ) + { + if ( (eWeight == pFontInfo->GetWeight()) && + (eItalic == pFontInfo->GetItalic()) ) + { + bNotSynthetic = TRUE; + break; + } + + pFontInfo = pFontInfo->mpNext; + } + + if ( !bNotSynthetic ) + { + bNoneAvailable = TRUE; + + // Testen, ob es ein syntetischer Style ist + if ( eMinWeight <= WEIGHT_NORMAL ) + { + if ( (rStyleName == maNormal) || (rStyleName == maLight) || + (rStyleName == maNormalItalic) || (rStyleName == maLightItalic) ) + bNoneAvailable = FALSE; + } + + if ( (rStyleName == maBold) || (rStyleName == maBlack) || + (rStyleName == maBoldItalic) || (rStyleName == maBlackItalic) ) + bNoneAvailable = FALSE; + } + } + else + bNotSynthetic = TRUE; + + if ( bNoneAvailable ) + { + XubString aEmptryStr; + return aEmptryStr; + } + else if ( !bNotSynthetic ) + { + if ( !maMapStyleNotAvailable.Len() ) + ((FontList*)this)->maMapStyleNotAvailable = XubString( SvtResId( STR_SVT_FONTMAP_STYLENOTAVAILABLE ) ); + return maMapStyleNotAvailable; + } + else + { + /* 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; + } + } + */ + + + 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; + while ( pSearchInfo ) + { + if ( rStyleName == GetStyleName( *pSearchInfo ) ) + { + pFontInfo = pSearchInfo; + break; + } + + pSearchInfo = pSearchInfo->mpNext; + } + } + + // Konnten die Daten nicht gefunden werden, dann muessen bestimmte + // Attribute nachgebildet werden + if ( !pFontInfo ) + { + FontInfo aInfo; + + // Falls der Fontname stimmt, uebernehmen wir soviel wie moeglich + if ( pFontNameInfo ) + aInfo = *pFontNameInfo; + else + aInfo.SetName( rName ); + aInfo.SetStyleName( rStyleName ); + + 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 ); + } + + return aInfo; + } + else + return *pFontInfo; +} + +// ----------------------------------------------------------------------- + +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 + if ( !pFontInfo ) + { + FontInfo aInfo; + + // Falls der Fontname stimmt, uebernehmen wir soviel wie moeglich + if ( pFontNameInfo ) + { + aInfo = *pFontNameInfo; + aInfo.SetStyleName( XubString() ); + } + else + aInfo.SetName( rName ); + + aInfo.SetWeight( eWeight ); + aInfo.SetItalic( eItalic ); + return aInfo; + } + else + return *pFontInfo; +} + +// ----------------------------------------------------------------------- + +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(); + + USHORT 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; +} + + diff --git a/svtools/source/control/ctrltool.src b/svtools/source/control/ctrltool.src new file mode 100644 index 000000000000..2ae746c57295 --- /dev/null +++ b/svtools/source/control/ctrltool.src @@ -0,0 +1,425 @@ +/************************************************************************* + * + * $RCSfile: ctrltool.src,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#include "svtools.hrc" + +String STR_SVT_STYLE_LIGHT +{ + Text = "Light" ; + Text [ ENGLISH ] = "Light" ; + Text [ english_us ] = "Light" ; + Text [ italian ] = "Light" ; + Text [ spanish ] = "Light" ; + Text [ french ] = "Estompé" ; + Text [ dutch ] = "Light" ; + Text [ swedish ] = "Ljus" ; + Text [ danish ] = "Light" ; + Text [ portuguese_brazilian ] = "Light" ; + Text [ portuguese ] = "Claro" ; + Text[ russian ] = "Òîíêèé"; + Text[ polish ] = "Light"; + Text[ japanese ] = "׎š"; + Text[ chinese_simplified ] = "ϸ"; + Text[ chinese_traditional ] = "²Ó"; + Text[ arabic ] = "ÝÇÊÍ"; + Text[ greek ] = "Áðáëü"; + Text[ korean ] = "Light"; + Text[ turkish ] = "Ýnce"; + Text[ language_user1 ] = " "; +}; + +String STR_SVT_STYLE_LIGHT_ITALIC +{ + Text = "Light Kursiv" ; + Text [ ENGLISH ] = "Light Italic" ; + Text [ english_us ] = "Light Italic" ; + Text [ italian ] = "Corsivo Light" ; + Text [ spanish ] = "Cursiva light" ; + Text [ french ] = "Italique estompé" ; + Text [ dutch ] = "Light Cursief" ; + Text [ swedish ] = "Ljus kursiv" ; + Text [ danish ] = "Light kursiv" ; + Text [ portuguese_brazilian ] = "Light Italic" ; + Text [ portuguese ] = "Itálico claro" ; + Text[ russian ] = "Òîíêèé êóðñèâ"; + Text[ polish ] = "Kursywa light"; + Text[ japanese ] = "׎š ŽÎ‘Ì"; + Text[ chinese_simplified ] = "ϸбÌå"; + Text[ chinese_traditional ] = "²Ó±×Åé"; + Text[ arabic ] = "ÝÇÊÍ ãÇÆá"; + Text[ greek ] = "ÐëÜãéá ÁðáëÜ"; + Text[ korean ] = "°¡º¿î ÀÌÅŸ¯Ã¼"; + Text[ turkish ] = "Ýnce italik"; + Text[ language_user1 ] = " "; +}; + +String STR_SVT_STYLE_NORMAL +{ + Text = "Standard" ; + Text [ ENGLISH ] = "Regular" ; + Text [ english_us ] = "Regular" ; + Text [ italian ] = "Standard" ; + Text [ spanish ] = "Predeterminado" ; + Text [ french ] = "Normal" ; + Text [ dutch ] = "Normaal" ; + Text [ swedish ] = "Normal" ; + Text [ danish ] = "Normal" ; + Text [ portuguese_brazilian ] = "Normal" ; + Text [ portuguese ] = "Padrão" ; + Text[ russian ] = "Ñòàíäàðò"; + Text[ polish ] = "Standard"; + Text[ japanese ] = "•W€"; + Text[ chinese_simplified ] = "±ê×¼"; + Text[ chinese_traditional ] = "¼Ð·Ç"; + Text[ arabic ] = "ÞíÇÓí"; + Text[ greek ] = "ÐñïåðéëïãÞ"; + Text[ korean ] = "º¸Åë"; + Text[ turkish ] = "Normal"; + Text[ language_user1 ] = " "; +}; + +String STR_SVT_STYLE_NORMAL_ITALIC +{ + Text = "Kursiv" ; + Text [ ENGLISH ] = "Italic" ; + Text [ english_us ] = "Italic" ; + Text [ italian ] = "Corsivo" ; + Text [ spanish ] = "Cursiva" ; + Text [ french ] = "Italique" ; + Text [ dutch ] = "Cursief" ; + Text [ swedish ] = "Kursiv" ; + Text [ danish ] = "Kursiv" ; + Text [ portuguese_brazilian ] = "Italic" ; + Text [ portuguese ] = "Itálico" ; + Text[ russian ] = "Êóðñèâ"; + Text[ polish ] = "Kursywa"; + Text[ japanese ] = "ŽÎ‘Ì"; + Text[ chinese_simplified ] = "бÌå"; + Text[ chinese_traditional ] = "±×Åé"; + Text[ arabic ] = "ãÇÆá"; + Text[ greek ] = "ÐëÜãéá"; + Text[ korean ] = "±â¿ïÀÓ²Ã"; + Text[ turkish ] = "Ýtalik"; + Text[ language_user1 ] = " "; +}; + +String STR_SVT_STYLE_BOLD +{ + Text = "Fett" ; + Text [ ENGLISH ] = "Bold" ; + Text [ english_us ] = "Bold" ; + Text [ italian ] = "Grassetto" ; + Text [ spanish ] = "Negrita" ; + Text [ french ] = "Gras" ; + Text [ dutch ] = "Vet" ; + Text [ swedish ] = "Fet" ; + Text [ danish ] = "Fed" ; + Text [ portuguese_brazilian ] = "Bold" ; + Text [ portuguese ] = "Negrito" ; + Text[ russian ] = "Æèðíûé"; + Text[ polish ] = "Pogrubienie"; + Text[ japanese ] = "‘¾Žš"; + Text[ chinese_simplified ] = "´ÖÌå"; + Text[ chinese_traditional ] = "²ÊÅé"; + Text[ arabic ] = "ÚÑíÖ"; + Text[ greek ] = "¸íôïíï"; + Text[ korean ] = "±½°Ô"; + Text[ turkish ] = "Kalýn"; + Text[ language_user1 ] = " "; +}; + +String STR_SVT_STYLE_BOLD_ITALIC +{ + Text = "Fett Kursiv" ; + Text [ ENGLISH ] = "Bold Italic" ; + Text [ english_us ] = "Bold Italic" ; + Text [ italian ] = "Corsivo Grassetto" ; + Text [ spanish ] = "Cursiva negrita" ; + Text [ french ] = "Italique gras" ; + Text [ dutch ] = "Vet Cursief" ; + Text [ swedish ] = "Fet kursiv" ; + Text [ danish ] = "Fed kursiv" ; + Text [ portuguese_brazilian ] = "Bold Italic" ; + Text [ portuguese ] = "Negrito itálico" ; + Text[ russian ] = "Æèðíûé êóðñèâ"; + Text[ polish ] = "Pogrubiona kursywa"; + Text[ japanese ] = "‘¾Žš‚̎ΑÌ"; + Text[ chinese_simplified ] = "´ÖбÌå"; + Text[ chinese_traditional ] = "²Ê±×Åé"; + Text[ arabic ] = "ÚÑíÖ ãÇÆá"; + Text[ greek ] = "ÐëÜãéá ¸íôïíá"; + Text[ korean ] = "±½Àº ÀÌÅŸ¯Ã¼"; + Text[ turkish ] = "Kalýn italik"; + Text[ language_user1 ] = " "; +}; + +String STR_SVT_STYLE_BLACK +{ + Text = "Black" ; + Text [ ENGLISH ] = "Black" ; + Text [ english_us ] = "Black" ; + Text [ italian ] = "Black" ; + Text [ spanish ] = "Black" ; + Text [ french ] = "Extra gras" ; + Text [ dutch ] = "Black" ; + Text [ swedish ] = "Svart" ; + Text [ danish ] = "Black" ; + Text [ portuguese_brazilian ] = "Black" ; + Text [ portuguese ] = "Preto" ; + Text[ russian ] = "×åðíûé"; + Text[ polish ] = "Czarny"; + Text[ japanese ] = "•"; + Text[ chinese_simplified ] = "ºÚÌå"; + Text[ language_user1 ] = " "; + Text[ chinese_traditional ] = "¶ÂÅé"; + Text[ arabic ] = "ÃÓæÏ"; + Text[ greek ] = "Ìáýñï"; + Text[ korean ] = "°Ë°Ô"; + Text[ turkish ] = "Siyah"; +}; + +String STR_SVT_STYLE_BLACK_ITALIC +{ + Text = "Black Kursiv" ; + Text [ ENGLISH ] = "Black Italic" ; + Text [ english_us ] = "Black Italic" ; + Text [ italian ] = "Corsivo Black" ; + Text [ spanish ] = "Cursiva black" ; + Text [ french ] = "Italique extra gras" ; + Text [ dutch ] = "Black Cursief" ; + Text [ swedish ] = "Svart kursiv" ; + Text [ danish ] = "Black kursiv" ; + Text [ portuguese_brazilian ] = "Black Italic" ; + Text [ portuguese ] = "Preto itálico" ; + Text[ russian ] = "×åðíûé êóðñèâ"; + Text[ polish ] = "Czarna kursywa"; + Text[ japanese ] = "•‚̎ΑÌ"; + Text[ chinese_simplified ] = "ºÚбÌå"; + Text[ language_user1 ] = " "; + Text[ chinese_traditional ] = "¶Â±×Åé"; + Text[ arabic ] = "ÃÓæÏ ãÇÆá"; + Text[ greek ] = "ÐëÜãéá Ìáýñï"; + Text[ korean ] = "°ËÁ¤ ÀÌÅŸ¯Ã¼"; + Text[ turkish ] = "Siyah italik"; +}; + +/* +Finnische Texte: + "Light", + "Light Kursivoitu", + "Normaali", + "Kursivoitu", + "Lihavoitu", + "Lihavoitu Kursivoitu", + "Black", + "Black Kursivoitu" +*/ + +String STR_SVT_FONTMAP_BOTH +{ + TEXT = "Für Ausdruck und Anzeige am Bildschirm wird die gleiche Schriftart verwendet." ; + TEXT [ English ] = "The same font will be used on both your printer and your screen." ; + TEXT [ norwegian ] = "The same font will be used on both your printer and your screen." ; + TEXT [ italian ] = "Questo tipo di carattere verrà utilizzato sia per lo schermo che per la stampante." ; + TEXT [ portuguese_brazilian ] = "Esta mesma fonte ser utilizada na impressora e na tela." ; + TEXT [ portuguese ] = "O tipo de letra utilizado para a impressora e para o ecrã é o mesmo." ; + TEXT [ finnish ] = "Tätä fonttia voidaan käyttää kirjoittimessa ja näytössä." ; + TEXT [ danish ] = "Denne skrifttype vil blive brugt både på skærmen og på printeren." ; + TEXT [ french ] = "La même police est utilisée pour l'impression et l'affichage à l'écran." ; + TEXT [ swedish ] = "Samma teckensnitt används för både skrivare och bildskärm." ; + TEXT [ dutch ] = "Dit lettertype wordt voor zowel de printer als het scherm gebruikt." ; + TEXT [ spanish ] = "Se usará la misma fuente en la impresora y en pantalla" ; + TEXT [ english_us ] = "The same font will be used on both your printer and your screen." ; + TEXT[ chinese_simplified ] = "ÆÁÄ»ÏÔʾºÍ´òӡʹÓÃͬһÖÖ×ÖÌå¡£"; + TEXT[ russian ] = "Äëÿ ïå÷àòè è âûâîäà íà ýêðàí èñïîëüçóåòñÿ îäèí è òîò æå øðèôò"; + TEXT[ polish ] = "U¿yj tej samej czcionki dla wydruku i ekranu"; + TEXT[ japanese ] = "ˆóü‚Ɖæ–Ê•\\Ž¦‚É‚Í“¯‚¶Ì«ÝÄ‚ÌŽí—Þ‚ªŽg—p‚³‚ê‚Ä‚¢‚Ü‚·B"; + TEXT[ chinese_traditional ] = "¿Ã¹õÅã¥Ü©M¦C¦L¨Ï¥Î²Î¤@ªº¦r«¬"; + TEXT[ arabic ] = "ÓæÝ íÊã ÇÓÊÎÏÇã äÝÓ ÇáÎØ ááØÇÈÚÉ æÇáÔÇÔÉ."; + TEXT[ greek ] = "Ç ãñáììáôïóåéñÜ áõôÞ èá ÷ñçóéìïðïéçèåß ãéá ôçí ïèüíç êáé ãéá ôïí åêôõðùôÞ."; + TEXT[ korean ] = "´ç½ÅÀÇ ½Ã½ºÅÛ°ú ȸ鿡´Â °°Àº ±Û²ÃÀÌ »ç¿ëµÉ °Í ÀÔ´Ï´Ù."; + TEXT[ turkish ] = "Yazdýrma ve ekranda görüntüleme için ayný yazýtipi kullanýlacak."; + TEXT[ language_user1 ] = " "; +}; + +String STR_SVT_FONTMAP_PRINTERONLY +{ + TEXT = "Druckerschrift. Die Bildschirmanzeige kann etwas abweichen." ; + TEXT [ English ] = "This is a printer font. The screen image may not exactly match." ; + TEXT [ norwegian ] = "This is a printer font. The screen image may not exactly match." ; + TEXT [ italian ] = "Il tipo di carattere visualizzato differisce da quello stampato." ; + TEXT [ portuguese_brazilian ] = "Esta é uma fonte de impressora. A imagem na tela pode não corresponder exatamente." ; + TEXT [ portuguese ] = "Letra de impressora. A letra vista no ecrã pode apresentar um pequeno desvio." ; + TEXT [ finnish ] = "Tämä on kirjoitinfontti. Näytön sisältö ei ehkä ole aivan samanlainen." ; + TEXT [ danish ] = "Dette er en printerskrifttype. Skærmbilledet svarer muligvis ikke helt til printerskrifttypen." ; + TEXT [ french ] = "Police d'imprimante. L'affichage et l'impression ne seront pas toujours identiques." ; + TEXT [ swedish ] = "Detta är ett skrivarteckensnitt. Visningen på skärmbilden kan avvika något." ; + TEXT [ dutch ] = "Dit is een printerlettertype. De weergave op het scherm kan iets afwijken." ; + TEXT [ spanish ] = "Fuente de impresora. La imagen en pantalla podría ser diferente." ; + TEXT [ english_us ] = "This is a printer font. The screen image may differ." ; + TEXT[ chinese_simplified ] = "ÕâÊÇ´òÓ¡×ÖÌå¡£ÆÁÄ»ÏÔʾµÄ×ÖÌåÓëÆä¿ÉÄÜ»áÓÐЩƫ²î¡£"; + TEXT[ russian ] = "Øðèôò ïå÷àòè. Íà ýêðàíå ìîæåò íåìíîãî îòëè÷àòüñÿ."; + TEXT[ polish ] = "Czcionka drukarkowa. Obraz czcionek na ekranie mo¿e siê trochê ró¿niæ."; + TEXT[ japanese ] = "ÌßØÝÀ—p‚ÌÌ«ÝÄ‚Å‚·B‰æ–Ê•\\Ž¦‚Æ‚Í‚µˆÙ‚È‚è‚Ü‚·B"; + TEXT[ chinese_traditional ] = "¦C¦L¦r«¬¡C¿Ã¹õÅã¥Ü¦r«¬¥i¯à²¤·L¦³¨Ç°¾®t¡C"; + TEXT[ arabic ] = "åÐÇ ÎØ ÇáØÇÈÚÉ. ÞÏ íÎÊáÝ ÇáãÙåÑ Úáì ÇáÔÇÔÉ ÈÚÖ ÇáÔÆ."; + TEXT[ greek ] = "ÃñáììáôïóåéñÜ åêôõðùôÞ. Ç åìöÜíéóç ôçò óôçí ïèüíç åßíáé äõíáôüí íá äéáöÝñåé."; + TEXT[ korean ] = "ÀÌ°ÍÀº Àμ⠱۲ÃÀÔ´Ï´Ù. ȸéÀÇ À̹ÌÁö¿Í´Â ´Ù¸¦°Í ÀÔ´Ï´Ù."; + TEXT[ turkish ] = "Yazýcý yazýtipi. Ekrandaki görüntü biraz farklý olabilir."; +}; + +String STR_SVT_FONTMAP_SCREENONLY +{ + TEXT = "Bildschirmschrift. Der Ausdruck kann etwas abweichen." ; + TEXT [ English ] = "This is a screen font. The printer image may not exactly match." ; + TEXT [ norwegian ] = "This is a screen font. The printer image may not exactly match." ; + TEXT [ italian ] = "Questo è un carattere per lo schermo. La stampa può essere leggermente diversa." ; + TEXT [ portuguese_brazilian ] = "Esta é uma fonte de tela. A imagem impressa pode não corresponder exatamente." ; + TEXT [ portuguese ] = "Letra de ecrã. A letra impressa pode apresentar um pequeno desvio." ; + TEXT [ finnish ] = "Tämä on näyttöfontti. Tulosteen sisältö ei ehkä ole aivan samanlainen." ; + TEXT [ danish ] = "Dette er en skærmskrifttype. Udskriften kan muligvis afvige lidt." ; + TEXT [ french ] = "Police d'écran. L'impression et l'affichage ne seront pas toujours identiques." ; + TEXT [ swedish ] = "Detta är ett skärmteckensnitt. Utskriften kan vara lätt avvikande." ; + TEXT [ dutch ] = "Dit is een schermlettertype. De afdruk kan iets afwijken." ; + TEXT [ spanish ] = "Fuente de pantalla. La imagen en la impresora podría ser diferente." ; + TEXT [ english_us ] = "This is a screen font. The printer image may differ." ; + TEXT[ chinese_simplified ] = "ÕâÊÇÆÁÄ»×ÖÌå¡£´òÓ¡³öÀ´µÄ×ÖÌåÓëÆä¿ÉÄÜ»áÓÐһЩƫ²î¡£"; + TEXT[ russian ] = "Øðèôò ýêðàíà.  ïå÷àòè ìîãóò áûòü îòêëîíåíèÿ."; + TEXT[ polish ] = "To jest czcionka ekranowa. Wydruk bêdzie siê trochê ró¿ni³."; + TEXT[ japanese ] = "‰æ–Ê—p‚ÌÌ«ÝÄ‚Å‚·Bˆóü²Ò°¼Þ‚Æ‚Í‚µˆÙ‚È‚è‚Ü‚·B"; + TEXT[ chinese_traditional ] = "¿Ã¹õ¦r«¬¡C¦C¦L¥X¥i¯à·|¦³¤@¨Ç°¾®t¡C"; + TEXT[ arabic ] = "åÐÇ ÎØ ÔÇÔÉ. ÞÏ íÎÊáÝ ÇáãÙåÑ Úáì ÇáæÑÞ ÇáãØÈæÚ ÈÚÖ ÇáÔÆ."; + TEXT[ greek ] = "ÃñáììáôïóåéñÜ ïèüíçò. Ç åìöÜíéóç ôçò óôçí åêôýðùóç åßíáé äõíáôüí íá äéáöÝñåé."; + TEXT[ korean ] = "ÀÌ°ÍÀº ȸé ÆùÆ® ÀÔ´Ï´Ù. Àμâ À̹ÌÁö¿Í´Â ´Ù¸¦ °Í ÀÔ´Ï´Ù."; + TEXT[ turkish ] = "Ekran yazýtipi. Yazdýrma biraz farklý olabilir."; +}; + +String STR_SVT_FONTMAP_SIZENOTAVAILABLE +{ + TEXT = "Diese Schriftgröße ist nicht installiert. Die am besten passende vorhandene Größe wird benutzt." ; + TEXT [ English ] = "This font size is not installed. The closest available size will be used." ; + TEXT[ english_us ] = "This font size has not been installed. The closest available size will be used."; + TEXT[ portuguese ] = "Este tamanho de letra não está instalado. Será utilizado o tamanho disponível mais adequado."; + TEXT[ russian ] = "Òàêîé ðàçìåð øðèôòà íå èíñòàëëèðîâàí. Ïîýòîìó áóäåò èñïîëüçîâàí íàèáîëåå ïîäõîäÿùèé ðàçìåð."; + TEXT[ greek ] = "Ôï ìÝãåèïò ôçò ãñáììáôïóåéñÜò äåí Ý÷åé åãêáôáóôáèåß. ×ñçóéìïðïéåßôáé ôï ðëçóéÝóôåñï ìÝãåèïò."; + TEXT[ dutch ] = "Deze schriftgrootte is niet geïnstalleerd. De meest passende voorhanden zijnde grootte wordt toegepast."; + TEXT[ french ] = "Cette taille de police n'a pas été installée. La taille disponible la plus appropriée va être utilisée."; + TEXT[ spanish ] = "Este tamaño de fuente no está instalado. Se usará el tamaño disponible más adecuado."; + TEXT[ italian ] = "Il font delle dimensioni indicate non è installato. Il programma utilizzerà le dimensioni disponibili."; + TEXT[ danish ] = "Denne skriftstørrelse er ikke installeret. Den tilgængelige størrelse, som passer bedst, vil blive brugt i stedet."; + TEXT[ swedish ] = "Den här teckenstorleken är inte installerad. Den tillgängliga storlek som passar bäst används."; + TEXT[ polish ] = "Dany rozmiar czcionki nie jest zaistalowany. U¿yty zostanie najbardziej pasuj¹cy, ju¿ istniej¹ca rozmiar."; + TEXT[ portuguese_brazilian ] = "This font size is not installed. The closest available size will be used."; + TEXT[ japanese ] = "‚±‚ÌÌ«ÝÄ»²½Þ‚Ͳݽİق³‚ê‚Ä‚¢‚Ü‚¹‚ñBÅ‚à“KØ‚È»²½Þ‚ª‘I‚΂ê‚Ü‚·B"; + TEXT[ korean ] = "ÀÌ ±Û²ÃÀÇ Å©±â´Â ¼³Ä¡µÇÁö ¾Ê¾Ò½À´Ï´Ù. À¯È¿ÇÑ °¡Àå À¯»çÇÑ Å©±â°¡ »ç¿ëµÉ°Í ÀÔ´Ï´Ù."; + TEXT[ chinese_simplified ] = "ûÓа²×°ÕâÖÖ×ÖÌå´óС¡£Ê¹ÓõÄÊÇÏÖÓеÄ×î½Ó½üµÄ×ÖÌå´óС¡£"; + TEXT[ chinese_traditional ] = "¨S¦³¦w¸Ë³oÓ¦r«¬¡C±Ä¥Î³Ìªñ¦üªº¦r«¬¡C"; + TEXT[ arabic ] = "ÍÌã ÇáÎØ åÐÇ ÛíÑ ãËÈÊ. ÓæÝ íÊã ÇÓÊÎÏÇã ÃßËÑ ÇáÃÍÌÇã ÇáãæÌæÏÉ ÞÑÈÇð áå."; + TEXT[ turkish ] = "Bu yazýtipi boyu yüklenmedi. Mevcut boylardan en uygun olaný kullanýlacak."; +}; + +String STR_SVT_FONTMAP_STYLENOTAVAILABLE +{ + TEXT = "Dieser Schriftstil wird nachgebildet oder der am besten passende Stil wird verwendet." ; + TEXT [ English ] = "This font style will be generated or the closest matching style will be used." ; + TEXT[ english_us ] = "This font style will be simulated or the closest matching style will be used."; + TEXT[ portuguese ] = "Este estilo de letra será simulado ou será utilizado o estilo disponível mais adequado."; + TEXT[ russian ] = "Áóäåò ñîçäàí ëèáî òàêîé ñòèëü øðèôòà, ëèáî áóäåò èñïîëüçîâàí íàèáîëåå ïîõîæèé."; + TEXT[ greek ] = "Ôï óôõë áõôü ãñáììáôïóåéñÜò èá áíôéãñáöåß Þ èá ÷ñçóéìïðïéçèåß ôï ðëçóéÝóôåñï óôõë.."; + TEXT[ dutch ] = "Dit lettertype wordt nagebootst of het meest overeenkomende voorhanden zijnde type wordt gebruikt."; + TEXT[ french ] = "Ce style de police sera imité ou le style le plus approprié sera utilisé."; + TEXT[ spanish ] = "Se imitará este estilo de fuente o se usará el más adecuado."; + TEXT[ italian ] = "Verrà riprodotto lo stile di questo font oppure verrà utilizzato quello che gli è più simile."; + TEXT[ danish ] = "Denne skrifttype bliver reproduceret eller den type, som passer bedst, vil blive brugt istedet."; + TEXT[ swedish ] = "Det här teckensnittet efterbildas eller närmast motsvarande teckensnitt används."; + TEXT[ polish ] = "Dany styl czcionki zostanie skopiowany lub zostanie u¿yty najlepiej pasuj¹cy styl."; + TEXT[ portuguese_brazilian ] = "This font style will be generated or the closest matching style will be used."; + TEXT[ japanese ] = "‚±‚ÌÌ«ÝĽÀ²Ù‚ÍC³‚³‚ê‚é‚©A‚Ü‚½‚ÍÅ‚à“K؂ȽÀ²Ù‚ªŽg—p‚³‚ê‚Ü‚·B"; + TEXT[ korean ] = "ÀÌ ±Û²Ãü¿¡ °¡Àå À¯»çÇÑ ±Û²Ãü°¡ »ç¿ëµÉ°Í ÀÔ´Ï´Ù."; + TEXT[ chinese_simplified ] = "Éú³ÉÕâÖÖ×ÖÌå»òʹÓÃ×î½Ó½üµÄ×ÖÌå¡£"; + TEXT[ chinese_traditional ] = "¼Ò¥é³oÓ¦r«¬©Î±Ä¥Î³Ìªñ¦üªº¦r«¬¡C"; + TEXT[ arabic ] = "ÓæÝ íÊã ÊÞáíÏ äãØ ÇáÎØ åÐÇ¡ Ãæ ÓæÝ íÊã ÇÓÊÎÏÇã ÃÞÑÈ äãØð áå."; + TEXT[ turkish ] = "Bu yazýtipi taklit edilecek ya da en uygun olan biçim kullanýlacak."; + TEXT[ language_user1 ] = " "; +}; + +String STR_SVT_FONTMAP_NOTAVAILABLE +{ + TEXT = "Diese Schriftart ist nicht installiert. Die am besten passende vorhandene Schriftart wird benutzt." ; + TEXT [ English ] = "This font is not installed. The closest available font will be used." ; + TEXT[ english_us ] = "This font has not been installed. The closest available font will be used."; + TEXT[ portuguese ] = "Este tipo de letra não está instalado. Será utilizado o tipo de letra disponível mais adequado."; + TEXT[ russian ] = "Ýòîò òèï øðèôòà íå èíñòàëëèðîâàí. Ïîýòîìó áóäåò èñïîëüçîâàí îäèí èç íàèáîëåå ïîäõîäÿùèõ."; + TEXT[ greek ] = "Ç ãñáììáôïóåéñÜ äåí Ý÷åé åãêáôáóôáèåß. ×ñçóéìïðïéåßôáé ç ðëçóéÝóôåñç (áðü Üðïøç ÷áñáêôçñéóôéêþí) ãñáììáôïóåéñÜ."; + TEXT[ dutch ] = "Dit lettertype is niet geïnstalleerd. Het meest overeenkomende voorhanden zijnde type wordt gebruikt."; + TEXT[ french ] = "Ce type de police n'a pas été installé. Le type de police le plus approprié va être utilisé."; + TEXT[ spanish ] = "Esta fuente no está instalada. Se usará la fuente existente más adecuada."; + TEXT[ italian ] = "Questo font non è installato. Il programma utilizzerà il font che gli è più simile."; + TEXT[ danish ] = "Denne skrifttype er ikke installeret. Den tilgængelige skrifttype, som passer bedst, vil blive brugt i stedet."; + TEXT[ swedish ] = "Det här teckensnittet är inte installerat. Det tillgängliga teckensnitt som passar bäst används."; + TEXT[ polish ] = "Dana czcionka nie jest zainstalowana.U¿yta zostanie najbardziej pasuj¹ca, ju¿ istniej¹ca czcionka."; + TEXT[ portuguese_brazilian ] = "This font is not installed. The closest available font will be used."; + TEXT[ japanese ] = "‚±‚ÌÌ«ÝĂͲݽİق³‚ê‚Ä‚¢‚Ü‚¹‚ñBÅ‚à“KØ‚ÈÌ«ÝÄ‚ª‘I‚΂ê‚Ü‚·B"; + TEXT[ korean ] = "ÀÌ ±Û²ÃÀº ¼³Ä¡µÇÁö ¾Ê¾Ò½À´Ï´Ù. À¯È¿ÇÑ °¡Àå À¯»çÇÑ ±Û²ÃÀÌ »ç¿ëµÉ°Í ÀÔ´Ï´Ù."; + TEXT[ chinese_simplified ] = "ûÓа²×°ÕâÖÖ×ÖÌ塣ʹÓõÄÊÇÏÖÓеÄ×î½Ó½üµÄ×ÖÌå¡£"; + TEXT[ chinese_traditional ] = "¨S¦³¦w¸Ë³oÓ¦r«¬¡C±Ä¥Î³Ìªñ¦üªº¦r«¬¡C"; + TEXT[ arabic ] = "åÐÇ ÇáÎØ ÛíÑ ãËÈÊ. ÓæÝ íÊã ÇÓÊÎÏÇã ÃßËÑ ÇáÎØæØ ÇáãæÌæÏÉ ÞÑÈÇð áå."; + TEXT[ turkish ] = "Bu yazýtipi yüklenmedi. Mevcut yazýtiplerinden en uygun olaný kullanýlacak."; +}; diff --git a/svtools/source/control/filectrl.cxx b/svtools/source/control/filectrl.cxx new file mode 100644 index 000000000000..e52b4107c3d4 --- /dev/null +++ b/svtools/source/control/filectrl.cxx @@ -0,0 +1,307 @@ +/************************************************************************* + * + * $RCSfile: filectrl.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _SV_FIELCTRL_CXX + +#ifndef _URLOBJ_HXX //autogen wg. INetURLObject +#include <tools/urlobj.hxx> +#endif +#ifndef _SV_SVAPP_HXX //autogen +#include <vcl/svapp.hxx> +#endif +#ifndef _VCL_FILEDLG_HXX +#include <vcl/filedlg.hxx> +#endif + +#include <filedlg.hxx> +#include <svtdata.hxx> + +#include <filectrl.hxx> +#include <filectrl.hrc> + +#pragma hdrstop + +// ======================================================================= + +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 ), + mpVclDlg( 0 ), + mpFDlg( 0 ) +{ + 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 ) +{ + XubString aNewText; + mpVclDlg = GetpApp()->CreateFileDialog( this, mbOpenDlg ? WB_OPEN : WB_SAVEAS ); + + if ( mpVclDlg ) + { + mpVclDlg->SetPath( maEdit.GetText() ); + + maDialogCreatedHdl.Call( this ); + + if ( mpVclDlg->Execute() ) + aNewText = mpVclDlg->GetPath(); + DELETEZ( mpVclDlg ); + } + else + { + mpFDlg = new FileDialog( this, mbOpenDlg ? WB_OPEN : WB_SAVEAS ); + mpFDlg->SetPath( maEdit.GetText() ); + + maDialogCreatedHdl.Call( this ); + + if ( mpFDlg->Execute() ) + aNewText = mpFDlg->GetPath(); + DELETEZ( mpFDlg ); + } + + if ( aNewText.Len() ) + { + INetURLObject aObj( aNewText ); + if ( aObj.GetProtocol() == INET_PROT_FILE ) + aNewText = aObj.PathToFileName(); + SetText( aNewText ); + maEdit.GetModifyHdl().Call( &maEdit ); + } + + 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..2f56127d657d --- /dev/null +++ b/svtools/source/control/filectrl.src @@ -0,0 +1,85 @@ +/************************************************************************* + * + * $RCSfile: filectrl.src,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include "filectrl.hrc" +String STR_FILECTRL_BUTTONTEXT +{ + Text = "Durchsuchen..." ; + Text [ ENGLISH ] = "Browse..." ; + Text [ english_us ] = "Browse..." ; + Text [ portuguese_brazilian ] = "Durchsuchen..." ; + Text [ swedish ] = "Genomsök..." ; + Text [ danish ] = "Gennemse..." ; + Text [ italian ] = "Sfoglia..." ; + Text [ spanish ] = "Examinar..." ; + Text [ french ] = "Parcourir..." ; + Text [ dutch ] = "Bladeren..." ; + Text [ portuguese ] = "Pesquisar..." ; + Text[ chinese_simplified ] = "ä¯ÀÀ..."; + Text[ russian ] = "Îáçîð..."; + Text[ polish ] = "Przegl¹daj..."; + Text[ japanese ] = "ŒŸõ..."; + Text[ chinese_traditional ] = "ÂsÄý..."; + Text[ arabic ] = "ÇÓÊÚÑÇÖ..."; + Text[ greek ] = "ÁíáæÞôçóç..."; + Text[ korean ] = "ã¾Æº¸±â..."; + Text[ turkish ] = "Tara..."; +}; diff --git a/svtools/source/control/fmtfield.cxx b/svtools/source/control/fmtfield.cxx new file mode 100644 index 000000000000..6ddf7ee51eb6 --- /dev/null +++ b/svtools/source/control/fmtfield.cxx @@ -0,0 +1,1017 @@ +/************************************************************************* + * + * $RCSfile: fmtfield.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <stdio.h> + +#ifndef _TOOLS_DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif + +#ifndef _SV_SVAPP_HXX //autogen +#include <vcl/svapp.hxx> +#endif + +#ifndef _ZFORMAT_HXX //autogen +#include "zformat.hxx" +#endif + +#ifndef _FMTFIELD_HXX_ +#include "fmtfield.hxx" +#endif // _FMTFIELD_HXX_ + +//============================================================================== +// regulaerer Ausdruck, um komplette Zahlen und alles, was waehrend der Eingabe einer kompletten Zahl als Fragment vorkommt, +// abzudecken : +// [+/-][{ziffer}*.]*{ziffer}*[,{ziffer}*][e[+/-]{ziffer}*] +const char __FAR_DATA szNumericInput[] = "_[\\x2D\\x2B]?([0-9]*\\x++)*[0-9]*(\\x##[0-9]*)?(e[\\x2D\\x2B]?[0-9]*)?_"; + // (die beiden _ sind fuer die Normierung, damit kann ich erzwingen, dass nie ein Teilstring gefunden wird) + +//============================================================================== +SvNumberFormatter* FormattedField::StaticFormatter::s_cFormatter = NULL; +ULONG FormattedField::StaticFormatter::s_nReferences = 0; + +//------------------------------------------------------------------------------ +SvNumberFormatter* FormattedField::StaticFormatter::GetFormatter() +{ + if (!s_cFormatter) + s_cFormatter = new SvNumberFormatter(Application::GetAppInternational().GetLanguage()); + 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_bStrictFormat(TRUE) \ + ,m_nFormatKey(0) \ + ,m_pFormatter(NULL) \ + ,m_dMinValue(0) \ + ,m_dMaxValue(0) \ + ,m_bHasMin(FALSE) \ + ,m_bHasMax(FALSE) \ + ,m_dCurrentValue(0) \ + ,m_bValueDirty(TRUE) \ + ,m_bEnableEmptyField(TRUE) \ + ,m_dDefaultValue(0) \ + ,m_dSpinSize(1) \ + ,m_dSpinFirst(-1000000) \ + ,m_dSpinLast(1000000) \ + ,m_bTreatAsNumber(TRUE) \ + ,m_pLastOutputColor(NULL) + +//------------------------------------------------------------------------------ +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) + ImplSetText(*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::SetTextFormatted(const XubString& rStr) +{ + DBG_CHKTHIS(FormattedField, NULL); + +#if DBG_UTIL + if (ImplGetFormatter()->IsTextFormat(m_nFormatKey)) + DBG_WARNING("FormattedField::SetTextFormatted : valid only with text formats !"); +#endif + + m_sCurrentTextValue = rStr; + + String sFormatted; + 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::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 + { + ImplSetText(m_sLastValidText, &m_aLastSelection); + } + + SpinField::Modify(); +} + +//------------------------------------------------------------------------------ +void FormattedField::ImplSetText(const XubString& rNew, Selection* pNewSel) +{ + DBG_CHKTHIS(FormattedField, NULL); + + 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; + m_nFormatKey = 0; + } + else + { + XubString sOldFormat; + LanguageType aOldLang; + GetFormat(sOldFormat, aOldLang); + + ULONG 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::ResetConformanceTester : 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); + ULONG 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)) + 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; + ULONG 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; + ULONG 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; + ReFormat(); +} + +//------------------------------------------------------------------------------ +void FormattedField::ReFormat() +{ + if (!IsEmptyFieldEnabled() || GetText().Len()) + if (TreatingAsNumber()) + ImplSetValue(GetValue(), 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 + { + String sOld = GetText(); + ReFormat(); + if (GetText() != sOld) + Modify(); + } + } + + 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 + { + ImplGetFormatter()->GetOutputString(dVal, m_nFormatKey, sNewText, &m_pLastOutputColor); + } + + ImplSetText(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 !"); + + ULONG 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) + { + ULONG nTempFormat = 0; + 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 % + // -> dranhaengen + sText += '%'; + // (damit wird aus einer Eingabe '3' ein '3%', und der Formatter macht dann daraus + // ein double 0.03. Ansonsten wuerden wir hier bei einer Eingabe von '3' ein double + // 3 zurueckliefern, was 300 Prozent entspricht ... + } + 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)) + 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(); +} + +//------------------------------------------------------------------------------ +void FormattedField::Down() +{ + DBG_CHKTHIS(FormattedField, NULL); + SetValue(GetValue() - m_dSpinSize); + SetModifyFlag(); + Modify(); +} + +//------------------------------------------------------------------------------ +void FormattedField::First() +{ + DBG_CHKTHIS(FormattedField, NULL); + if (m_bHasMin) + { + SetValue(m_dMinValue); + SetModifyFlag(); + Modify(); + } +} + +//------------------------------------------------------------------------------ +void FormattedField::Last() +{ + DBG_CHKTHIS(FormattedField, NULL); + if (m_bHasMax) + { + SetValue(m_dMaxValue); + SetModifyFlag(); + Modify(); + } +} + +//============================================================================== +//------------------------------------------------------------------------------ +DoubleNumericField::~DoubleNumericField() +{ + delete m_pConformanceTester; +} + +//------------------------------------------------------------------------------ +void DoubleNumericField::FormatChanged(FORMAT_CHANGE_TYPE nWhat) +{ + ResetConformanceTester(); + FormattedField::FormatChanged(nWhat); +} + +//------------------------------------------------------------------------------ +BOOL DoubleNumericField::CheckText(const XubString& sText) const +{ + // Ich wuerde das CheckText gern ueber den NumberFormatter laufen lassen (da gibt es schliesslich ein IsNumberFormat), + // aber der erkennt leider keine Fragmente (also zum Beispiel '1e', was waehrend der Eingabe zwangslaeufig irgendwann mal + // vorkommt), also dieser Umweg ueber einen SearchText. + + 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() - 1)) + return TRUE; + + return FALSE; +} + +//------------------------------------------------------------------------------ +void DoubleNumericField::ResetConformanceTester() +{ + String sDescription = String::CreateFromAscii(szNumericInput); + // the thousands and the decimal separator are language dependent + const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey); + char cSepHexCode[3]; + + unsigned char cSeparator = pFormatEntry ? International(pFormatEntry->GetLanguage()).GetNumThousandSep() : ','; + sprintf(cSepHexCode, "%0X", cSeparator); + sDescription.SearchAndReplaceAscii("++", String::CreateFromAscii(cSepHexCode)); + + cSeparator = pFormatEntry ? International(pFormatEntry->GetLanguage()).GetNumDecimalSep() : '.'; + sprintf(cSepHexCode, "%0X", cSeparator); + sDescription.SearchAndReplaceAscii("##", String::CreateFromAscii(cSepHexCode)); + + delete m_pConformanceTester; + m_pConformanceTester = new SearchText(SearchParam(sDescription, SearchParam::SRCH_REGEXP, FALSE), GetpApp()->GetAppInternational()); +} + + +//============================================================================== + +//------------------------------------------------------------------------------ +DoubleCurrencyField::DoubleCurrencyField(Window* pParent, WinBits nStyle) + :FormattedField(pParent, nStyle) + ,m_bChangingFormat(FALSE) +{ + m_bPrependCurrSym = FALSE; + + // initialize with a system currency format + SvNumberFormatter* pFormatter = StandardFormatter(); + const NfCurrencyEntry* pSystemCurrency = pFormatter->MatchSystemCurrency(); + if (!pSystemCurrency) + pSystemCurrency = &pFormatter->GetCurrencyEntry(LANGUAGE_SYSTEM); + if (pSystemCurrency) + m_sCurrencySymbol = pSystemCurrency->GetSymbol(); + else + // no more options ... + m_sCurrencySymbol.AssignAscii("DM"); + UpdateCurrencyFormat(); +} + +//------------------------------------------------------------------------------ +DoubleCurrencyField::DoubleCurrencyField(Window* pParent, const ResId& rResId) + :FormattedField(pParent, rResId) + ,m_bChangingFormat(FALSE) +{ + m_bPrependCurrSym = FALSE; + + // initialize with a system currency format + SvNumberFormatter* pFormatter = StandardFormatter(); + const NfCurrencyEntry* pSystemCurrency = pFormatter->MatchSystemCurrency(); + if (!pSystemCurrency) + pSystemCurrency = &pFormatter->GetCurrencyEntry(LANGUAGE_SYSTEM); + if (pSystemCurrency) + m_sCurrencySymbol = pSystemCurrency->GetSymbol(); + else + // no more options ... + m_sCurrencySymbol.AssignAscii("DM"); + 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 + International aIntl(eLanguage); + XubString sNewFormat; + if (bThSep) + { + sNewFormat = '#'; + sNewFormat += aIntl.GetNumThousandSep(); + sNewFormat.AppendAscii("##0"); + } + else + sNewFormat = '0'; + + if (nDigits) + { + sNewFormat += aIntl.GetNumDecimalSep(); + + XubString sTemp; + sTemp.Fill(nDigits, '0'); + sNewFormat += sTemp; + } + + if (getPrependCurrSym()) + { + XubString sSymbol = getCurrencySymbol(); + sSymbol.EraseLeadingChars(' '); + sSymbol.EraseTrailingChars(' '); + + XubString sTemp = sSymbol; + sTemp += ' '; + 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 += ';'; + sTemp += sSymbol; + sTemp.AppendAscii(" -"); + sTemp += sNewFormat; + + sNewFormat = sTemp; + } + else + { + XubString sTemp = getCurrencySymbol(); + sTemp.EraseLeadingChars(' '); + sTemp.EraseTrailingChars(' '); + + sNewFormat += ' '; + sNewFormat += sTemp; + } + + // 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..7bde8d02b60a --- /dev/null +++ b/svtools/source/control/headbar.cxx @@ -0,0 +1,1673 @@ +/************************************************************************* + * + * $RCSfile: headbar.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _SV_HEADBAR_CXX + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif +#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 + +#ifndef _HEADBAR_HXX +#include <headbar.hxx> +#endif + +// ======================================================================= + +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.aWinBits ); +} + +// ----------------------------------------------------------------------- + +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 nFlags ) +{ + 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 + if ( mbButtonStyle && !(nBits & HIB_FLAT) ) + { + if ( aRect.GetWidth() >= 2 ) + { + if ( bHigh ) + pDev->SetLineColor( rStyleSettings.GetShadowColor() ); + else + pDev->SetLineColor( rStyleSettings.GetLightColor() ); + pDev->DrawLine( aRect.TopLeft(), Point( aRect.Left(), aRect.Bottom() ) ); + pDev->DrawLine( aRect.TopLeft(), Point( aRect.Right()-1, aRect.Top() ) ); + if ( !bHigh ) + { + pDev->SetLineColor( rStyleSettings.GetShadowColor() ); + pDev->DrawLine( Point( aRect.Right()-1, aRect.Top()+1 ), + Point( aRect.Right()-1, aRect.Bottom() ) ); + pDev->DrawLine( Point( aRect.Left()+1, aRect.Bottom() ), + Point( aRect.Right()-1, aRect.Bottom() ) ); + } + } + + aRect.Left()++; + aRect.Top()++; + aRect.Right()--; + aRect.Bottom()--; + + // Wenn selektiert, verschiebt sich das Rechteck um 1 Pixel + if ( bHigh ) + aRect.Move( 1, 1 ); + } + + // 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; + 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 ( IsEnabled() ) + pDev->DrawText( Point( nTxtPos, nTxtPosY ), pItem->maOutText ); + else + pDev->DrawCtrlText( Point( nTxtPos, nTxtPosY ), pItem->maOutText, 0, STRING_LEN, TEXT_DRAW_DISABLE ); + } + + // Wenn Image vorhanden, Position berechnen und ausgeben + long nImagePosY; + 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 ) ); + } + + 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() ) ); + } + } + + 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 ); + 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 ); + } + + 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; +} diff --git a/svtools/source/control/makefile.mk b/svtools/source/control/makefile.mk new file mode 100644 index 000000000000..f3f0e97e9b47 --- /dev/null +++ b/svtools/source/control/makefile.mk @@ -0,0 +1,141 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source License Version 1.1 (the "License"); You may not use this file +# except in compliance with the License. You may obtain a copy of the +# License at http://www.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=SVTOOLS +TARGET=ctrl +TARGETSTAT=_ctrl +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +CXXFILES= ctrltool.cxx \ + ctrlbox.cxx \ + stdctrl.cxx \ + stdmenu.cxx \ + valueset.cxx \ + tabbar.cxx \ + headbar.cxx \ + prgsbar.cxx \ + ruler.cxx \ + taskbar.cxx \ + taskbox.cxx \ + taskstat.cxx \ + taskmisc.cxx \ + calendar.cxx \ + filectrl.cxx \ + scrwin.cxx \ + reginfo.cxx \ + groupset.cxx \ + fmtfield.cxx + +.IF "$(GUI)"!="DOS" +SRCFILES= ctrltool.src \ + ctrlbox.src \ + calendar.src \ + filectrl.src +.ENDIF + +SLOFILES= $(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)$/groupset.obj \ + $(SLO)$/fmtfield.obj + +# statisch fuer setup + +OBJFILES= $(OBJ)$/prgsbar.obj \ + $(OBJ)$/stdctrl.obj \ + $(OBJ)$/reginfo.obj \ + $(OBJ)$/tabbar.obj + + +LIB1TARGET= $(SLB)$/$(TARGET).lib +LIB1OBJFILES= $(SLOFILES) + +LIB2TARGET= $(LB)$/$(TARGETSTAT).lib +LIB2OBJFILES= $(OBJFILES) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/svtools/source/control/prgsbar.cxx b/svtools/source/control/prgsbar.cxx new file mode 100644 index 000000000000..e370d9d87c22 --- /dev/null +++ b/svtools/source/control/prgsbar.cxx @@ -0,0 +1,270 @@ +/************************************************************************* + * + * $RCSfile: prgsbar.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _SV_PRGSBAR_CXX + +#ifndef _TOOLS_DEBUGS_HXX +#include <tools/debug.hxx> +#endif +#ifndef _VCL_STATUS_HXX +#include <vcl/status.hxx> +#endif +#ifndef _PRGSBAR_HXX +#include <prgsbar.hxx> +#endif + +// ======================================================================= + +#define PROGRESSBAR_OFFSET 3 +#define PROGRESSBAR_WIN_OFFSET 2 + +// ======================================================================= + +void ProgressBar::ImplInit() +{ + mnPercent = 0; + mbCalcNew = TRUE; + + ImplInitSettings( TRUE, TRUE, TRUE ); +} + +// ----------------------------------------------------------------------- + +ProgressBar::ProgressBar( Window* pParent, WinBits nWinStyle ) : + Window( 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 ) + { + 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 ); +} + +// ----------------------------------------------------------------------- + +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..40c76ca1f9fe --- /dev/null +++ b/svtools/source/control/reginfo.cxx @@ -0,0 +1,785 @@ +/************************************************************************* + * + * $RCSfile: reginfo.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#ifdef MAC +#include "mac_start.h" + +#ifndef __TYPES__ + #include <Types.h> +#endif + +#ifndef __RESOURCES__ + #include <Resources.h> +#endif + +#ifndef __FILES__ + #include <Files.h> +#endif + +#ifndef __ERRORS__ + #include <Errors.h> +#endif + +#ifndef __FOLDERS__ + #include <Folders.h> +#endif + +#ifndef __SCRIPT__ + #include <script.h> +#endif + +#ifndef __FINDER__ + #include <finder.h> +#endif +#include "mac_end.h" +#endif + +#include "reginfo.hxx" + +#ifndef _DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif + +#ifndef _OSL_THREAD_H_ +#include <osl/thread.h> +#endif + +String aEmptyString; + +#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 aEmptyString; + 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 aEmptyString; + String aRes; + if(ReadKey_Impl( rKey, pImp->aGroupHdl, aRes)) + return aRes; + else + return aEmptyString; +} + +String RegInfo::ReadKey( const String& rKey, const String &rDefault ) const +{ + DBG_HDL aEmptyString; + 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 <tools/svpm.h> + +struct RegInfo_Impl +{ + char *pKeyList; + String aCurrentApp; + void BuildKeyList( const String &rGroup ); +}; + +void RegInfo_Impl::BuildKeyList( const String &rGroup ) +{ + USHORT nLen = 0; + do + { + nLen+=1000; + delete[] pKeyList; + pKeyList = new char[nLen]; + *(int *)pKeyList = 0; + } + while( PrfQueryProfileString( + HINI_USERPROFILE, rGroup, + 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("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(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 ) +{ + PrfWriteProfileString( + HINI_USERPROFILE, MakeAppGroupString_Impl( rGroup ), 0, 0); +} + + +String RegInfo::ReadKey( const String& rKey ) const +{ + char *pBuffer= new char[MAXREGVALUE]; + *pBuffer=0; + PrfQueryProfileString( + HINI_USERPROFILE, pImp->aCurrentApp, rKey, 0, pBuffer, MAXREGVALUE); + String aRet(pBuffer); + delete[] pBuffer; + return aRet; +} + + +String RegInfo::ReadKey( const String& rKey, const String &rDefault ) const +{ + char *pBuffer= new char[MAXREGVALUE]; + *pBuffer=0; + PrfQueryProfileString( + HINI_USERPROFILE, pImp->aCurrentApp, rKey, rDefault, pBuffer, MAXREGVALUE); + String aRet(pBuffer); + delete[] pBuffer; + return aRet; +} + + +void RegInfo::WriteKey( const String& rKey, const String& rValue ) +{ + PrfWriteProfileString( + HINI_USERPROFILE, pImp->aCurrentApp, rKey, rValue); +} + +void RegInfo::DeleteKey( const String& rKey ) +{ + PrfWriteProfileString( + HINI_USERPROFILE, pImp->aCurrentApp, rKey, 0); +} + +#elif defined(MAC) + +/* Idee: + + In eine Resource SVðð (SV<Apfel><Apfel>) sind die Resource IDs + der Gruppen Ÿber den Namen der Resource zugŠnglich. + + †ber die aktuelle Gruppe sind die Values Ÿber den Namen der Resource + als Key zugŠnglich ... +*/ + +// Wir tuen so, als wŠren es "normale" SV-Resourcen + +#define kAPPInfo 'SVðð' + +//**************************************************** + +#pragma options align=mac68k + +typedef struct +{ + OSType nResType; // kAPPInfo + k +} + SVGroupInfo, *SVGroupInfoPtr, **SVGroupInfoHdl; + +//**************************************************** + +typedef struct +{ + USHORT nValueLen; + char aValue[1]; // LŠnge wie in nLen +} + SVKeyInfo, *SVKeyInfoPtr, **SVKeyInfoHdl; + +//**************************************************** + +#pragma options align=reset + +//**************************************************** + +struct RegInfo_Impl +{ + short nResFile; + OSType nCurrentGroup; + String aCurrentName; + + SVGroupInfoHdl GetNamedInfo(const String& rName); + + BOOL FindInfoFile( const String& rName, FSSpec *pResult ); +}; + +//**************************************************** + +SVGroupInfoHdl RegInfo_Impl::GetNamedInfo(const String& rName) +{ + String aName(rName); + short nOldRes = CurResFile(); + UseResFile(nResFile); + + SVGroupInfoHdl hResult = (SVGroupInfoHdl) Get1NamedResource(kAPPInfo,rName.GetPascalStr()); + + UseResFile(nOldRes); + + return hResult; +} + +//**************************************************** + +BOOL RegInfo_Impl::FindInfoFile( const String& rName, FSSpec *pResult ) +{ + OSErr nErr; + long nDirID; + short nVRefNum; + BOOL bResult = FALSE; + + nErr = FindFolder( kOnSystemDisk, kPreferencesFolderType, + kCreateFolder, &nVRefNum, &nDirID ); + + if ( nErr == noErr ) + { + nErr = FSMakeFSSpec( nVRefNum, nDirID, rName.GetPascalStr(), pResult ); + if ( nErr == fnfErr ) + { + FSpCreateResFile( pResult, 'SDsv', 'DATA', smRoman ); + nErr = FSMakeFSSpec( nVRefNum, nDirID, rName.GetPascalStr(), pResult ); + } + if ( nErr == noErr ) + { + FInfo aInfo; + nErr = FSpGetFInfo( pResult, &aInfo ); + if ( ( nErr == noErr ) && ! ( aInfo.fdFlags & kIsInvisible ) ) + { + aInfo.fdFlags |= kIsInvisible; + nErr = FSpSetFInfo( pResult, &aInfo ); + } + bResult = TRUE; + } + } + + return bResult; +} + +//**************************************************** + +RegInfo::RegInfo() +{ + FSSpec aFile; + + if ( !pImp->FindInfoFile( "svdbt.dll", &aFile ) ) + { + pImp = NULL; + return; + } + + pImp=new RegInfo_Impl; + + short nOldRes = CurResFile(); + pImp->nResFile = FSpOpenResFile( &aFile, fsRdWrPerm ); + pImp->nCurrentGroup = 0L; + UseResFile( nOldRes ); + + if ( pImp->nResFile < 0 ) + { + delete pImp; + pImp = NULL; + } +} + +//**************************************************** + +RegInfo::~RegInfo() +{ + if (pImp) + { + CloseResFile( pImp->nResFile ); + delete pImp; + } +} + +//**************************************************** + +String RegInfo::GetKeyName( USHORT nKey ) const +{ + String aResult; + + if (!pImp || !pImp -> nCurrentGroup) + return aResult; + + short nOldRes = CurResFile(); + UseResFile(pImp -> nResFile); + + SVKeyInfoHdl hKeyInfo = (SVKeyInfoHdl) Get1IndResource(pImp -> nCurrentGroup,nKey + 1); + + if (hKeyInfo) + { + Str255 aName; + ResType nType; + short nMacKey; + + GetResInfo((Handle) hKeyInfo,&nMacKey,&nType,aName); + if (ResError() == noErr) + aResult = String((char*) &aName[1], aName[0]); + } + + UseResFile(nOldRes); + return aResult; +} + +//**************************************************** + +USHORT RegInfo::GetKeyCount() const +{ + USHORT nResult = 0; + + if (pImp -> nCurrentGroup) + { + short nOldRes = CurResFile(); + UseResFile(pImp -> nResFile); + + nResult = Count1Resources(pImp -> nCurrentGroup); + UseResFile(nOldRes); + } + return nResult; +} + +//**************************************************** + +void RegInfo::SetAppGroup( const String& rGroup ) +{ + if (!pImp) + return; + + pImp->aCurrentName = rGroup; + SVGroupInfoHdl hGroup = pImp -> GetNamedInfo(rGroup); + if (hGroup) + { + pImp->nCurrentGroup = (*hGroup)-> nResType; + ReleaseResource((Handle) hGroup); + } + else + pImp->nCurrentGroup = 0L; +} + +//**************************************************** + +void RegInfo::DeleteAppGroup( const String &rGroup ) +{ + SVGroupInfoHdl hToDelete = pImp -> GetNamedInfo(rGroup); + if (hToDelete) + { + if ((*hToDelete)-> nResType == pImp->nCurrentGroup) + { + pImp->nCurrentGroup = 0L; + pImp->aCurrentName.Erase(); + } + RemoveResource((Handle) hToDelete); + } +} + +//**************************************************** + +String RegInfo::ReadKey( const String& rKey ) const +{ + String aResult; + + if (!pImp || !pImp -> nCurrentGroup) + return aResult; + + short nOldRes = CurResFile(); + UseResFile(pImp -> nResFile); + + SVKeyInfoHdl hKeyInfo = (SVKeyInfoHdl) Get1NamedResource(pImp->nCurrentGroup,rKey.GetPascalStr()); + + if (hKeyInfo) + { + HLock((Handle) hKeyInfo); + aResult = String((*hKeyInfo)->aValue, (*hKeyInfo)->nValueLen); + HUnlock((Handle) hKeyInfo); + + ReleaseResource((Handle) hKeyInfo); + } + + UseResFile(nOldRes); + return aResult; +} + +//**************************************************** + +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 ) +{ + if (!pImp) + return; + + short nOldRes = CurResFile(); + UseResFile(pImp -> nResFile); + + // Wenn wir noch keine Resource zur aktuellen Gruppe haben ... + if (!pImp -> nCurrentGroup) + { + // ... dann muessen wir hier eine Anlegen + + if (!pImp -> aCurrentName.Len()) + return; // Kein aktueller Name ??? + + short nNewId = Unique1ID(kAPPInfo); + + SVGroupInfoHdl hNewInfo = (SVGroupInfoHdl) NewHandle(sizeof(SVGroupInfo)); + + // Die Neue Resource liegt im Bereich Ÿber "SVðð" + pImp -> nCurrentGroup = kAPPInfo + nNewId; + + (*(hNewInfo))-> nResType = pImp -> nCurrentGroup; + DBG_ASSERT(CurResFile() == pImp -> nResFile,"wrong ResFile"); + AddResource((Handle) hNewInfo ,kAPPInfo, nNewId, pImp -> aCurrentName.GetPascalStr()); + ReleaseResource((Handle) hNewInfo); + } + + SVKeyInfoHdl hKeyInfo = (SVKeyInfoHdl) Get1NamedResource(pImp -> nCurrentGroup,rKey.GetPascalStr()); + int nNewSize = rValue.Len() + sizeof(USHORT); + + // Haben wir zu diesem Key schon eine Resource ? + if (hKeyInfo) + { + int nSize = GetHandleSize((Handle) hKeyInfo); + OSErr nMemErr = noErr; + if (nSize < nNewSize) + { + SetHandleSize((Handle) hKeyInfo,nNewSize); + nMemErr = MemError(); + } + + if (nMemErr == noErr) + { + (*hKeyInfo)->nValueLen = rValue.Len(); + BlockMoveData(rValue.GetStr(), (*hKeyInfo)->aValue, rValue.Len()); + ChangedResource((Handle) hKeyInfo); + } + else // Handle konnte nicht groesser werden + RemoveResource((Handle) hKeyInfo); + } + else + { + // Resource zu diesemm Key neu anlegen + + hKeyInfo = (SVKeyInfoHdl) NewHandle(nNewSize); + if (hKeyInfo) + { + short nNewId = Unique1ID(pImp -> nCurrentGroup); + + (*hKeyInfo)->nValueLen = rValue.Len(); + BlockMoveData(rValue.GetStr(), (*hKeyInfo)->aValue, rValue.Len()); + + AddResource((Handle) hKeyInfo ,pImp -> nCurrentGroup, nNewId, rKey.GetPascalStr()); + } + } + + UseResFile(nOldRes); +} + +//**************************************************** + +void RegInfo::DeleteKey( const String& rKey ) +{ + // Wenn wir noch keine aktuellen Gruppe haben ... + if (!pImp -> nCurrentGroup) + return; + + String aKey(rKey); + + short nOldRes = CurResFile(); + UseResFile(pImp -> nResFile); + + SVKeyInfoHdl hKeyInfo = (SVKeyInfoHdl) Get1NamedResource(pImp -> nCurrentGroup,rKey.GetPascalStr()); + + if (hKeyInfo) + RemoveResource((Handle) hKeyInfo); + + UseResFile(nOldRes); +} + +//**************************************************** + +#else + +RegInfo::RegInfo() +{ +} + + +RegInfo::~RegInfo() +{ +} + +String RegInfo::GetKeyName( USHORT nKey ) const +{ + return aEmptyString; +} + +USHORT RegInfo::GetKeyCount() const +{ + return 0; +} + +void RegInfo::SetAppGroup( const String& rGroup ) +{ + return ; +} + +void RegInfo::DeleteAppGroup( const String &rGroup ) +{ + return; +} + +String RegInfo::ReadKey( const String& rKey ) const +{ + return aEmptyString; +} + +String RegInfo::ReadKey( const String& rKey, const String &rDefault ) const +{ + return aEmptyString; +} + +void RegInfo::WriteKey( const String& rKey, const String& rValue ) +{ + return; +} + +void RegInfo::DeleteKey( const String& rKey ) +{ + return; +} + +#endif diff --git a/svtools/source/control/ruler.cxx b/svtools/source/control/ruler.cxx new file mode 100644 index 000000000000..6124f5f8b042 --- /dev/null +++ b/svtools/source/control/ruler.cxx @@ -0,0 +1,3064 @@ +/************************************************************************* + * + * $RCSfile: ruler.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> + +#ifndef _INTN_HXX +#include <tools/intn.hxx> +#endif +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _SV_SVAPP_HXX +#ifdef VCL +#include <vcl/svapp.hxx> +#else +#include <vcl/svapp.hxx> +#endif +#endif +#ifndef _POLY_HXX +#include <vcl/poly.hxx> +#endif + +#define _SV_RULER_CXX +#define private public +#include <ruler.hxx> + +// ======================================================================= + +#define RULER_OFF 2 +#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 + +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; +}; + +// ======================================================================= + +ImplRulerData::ImplRulerData() +{ + memset( this, 0, sizeof( ImplRulerData ) ); + + // PageBreite == EditWinBreite + bAutoPageWidth = TRUE; +} + +// ----------------------------------------------------------------------- + +ImplRulerData::~ImplRulerData() +{ + if ( pLines ) + delete pLines; + + if ( pArrows ) + delete pArrows; + + if ( pBorders ) + delete pBorders; + + if ( pIndents ) + delete pIndents; + + if ( pTabs ) + delete pTabs; +} + +// ----------------------------------------------------------------------- + +ImplRulerData& ImplRulerData::operator=( const ImplRulerData& rData ) +{ + if ( pLines ) + delete pLines; + + if ( pArrows ) + delete pArrows; + + if ( pBorders ) + delete pBorders; + + if ( pIndents ) + delete pIndents; + + if ( pTabs ) + 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; + + // 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 = &maData; // 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 ) +{ + ImplInit( nWinStyle ); +} + +// ----------------------------------------------------------------------- + +Ruler::~Ruler() +{ + if ( mnUpdateEvtId ) + Application::RemoveUserEvent( mnUpdateEvtId ); +} + +// ----------------------------------------------------------------------- + +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 + if ( mnWinStyle & WB_HORZ ) + nTickWidth = aPixSize.Width(); + else + 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 ) + nX = nStart-nTxtWidth2; + else + nX = nStart+nTxtWidth2; + ImplVDrawText( nX, nCenter-nTxtHeight2, 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; + nY = 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 ); + } + } + + 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; + International aIntn = Application::GetAppInternational(); + + aIntn.SetNumTrailingZeros( FALSE ); + 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 = aIntn.GetNum( nLogWidth, aImplRulerUnitTab[mnUnitIndex].nUnitDigits ); + + // 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 + { + 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 i; + long n; + long nIndentHeight = (mnVirHeight/2) - 1; + long nIndentWidth2 = nIndentHeight-3; + Polygon aPoly( 5 ); + + for ( i = 0; i < mpData->nIndents; i++ ) + { + if ( mpData->pIndents[i].nStyle & RULER_STYLE_INVISIBLE ) + continue; + + USHORT nStyle = mpData->pIndents[i].nStyle; + USHORT nIndentStyle = nStyle & RULER_INDENT_STYLE; + + n = mpData->pIndents[i].nPos+mpData->nNullVirOff; + + if ( (n >= nMin) && (n <= nMax) ) + { + 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 ); + } + + ImplDrawIndent( aPoly, nStyle ); + } + } +} + +// ----------------------------------------------------------------------- + +static void ImplCenterTabPos( Point& rPos, USHORT nStyle ) +{ + rPos.Y() += RULER_TAB_HEIGHT/2; + if ( nStyle == RULER_TAB_LEFT ) + rPos.X() -= RULER_TAB_WIDTH/2; + else if ( nStyle == RULER_TAB_RIGHT ) + rPos.X() += RULER_TAB_WIDTH/2; +} + +// ----------------------------------------------------------------------- + +static void ImplDrawRulerTab( OutputDevice* pDevice, + const Point& rPos, USHORT nStyle ) +{ + if ( nStyle & RULER_STYLE_INVISIBLE ) + return; + + USHORT nTabStyle = nStyle & RULER_TAB_STYLE; + + if ( nTabStyle == RULER_TAB_DEFAULT ) + { + pDevice->DrawRect( Rectangle( rPos.X() - RULER_TAB_DWIDTH2 + 1, + rPos.Y() - RULER_TAB_DHEIGHT2 + 1, + rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH, + rPos.Y() ) ); + pDevice->DrawRect( Rectangle( rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3, + rPos.Y() - RULER_TAB_DHEIGHT + 1, + rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3 + RULER_TAB_DWIDTH4 - 1, + rPos.Y() ) ); + + } + else if ( nTabStyle == RULER_TAB_LEFT ) + { + pDevice->DrawRect( Rectangle( rPos.X(), + rPos.Y() - RULER_TAB_HEIGHT2 + 1, + rPos.X() + RULER_TAB_WIDTH - 1, + rPos.Y() ) ); + pDevice->DrawRect( Rectangle( rPos.X(), + rPos.Y() - RULER_TAB_HEIGHT + 1, + rPos.X() + RULER_TAB_WIDTH2 - 1, + rPos.Y() ) ); + } + else if ( nTabStyle == RULER_TAB_RIGHT ) + { + pDevice->DrawRect( Rectangle( rPos.X() - RULER_TAB_WIDTH + 1, + rPos.Y() - RULER_TAB_HEIGHT2 + 1, + rPos.X(), + rPos.Y() ) ); + pDevice->DrawRect( Rectangle( rPos.X() - RULER_TAB_WIDTH2 + 1, + rPos.Y() - RULER_TAB_HEIGHT + 1, + rPos.X(), + rPos.Y() ) ); + } + else + { + pDevice->DrawRect( Rectangle( rPos.X() - RULER_TAB_CWIDTH2 + 1, + rPos.Y() - RULER_TAB_HEIGHT2 + 1, + rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH, + rPos.Y() ) ); + pDevice->DrawRect( Rectangle( rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3, + rPos.Y() - RULER_TAB_HEIGHT + 1, + rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3 + RULER_TAB_CWIDTH4 - 1, + rPos.Y() ) ); + + if ( nTabStyle == RULER_TAB_DECIMAL ) + { + pDevice->DrawRect( Rectangle( rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH - 1, + rPos.Y() - RULER_TAB_HEIGHT + 1 + 1, + rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH, + rPos.Y() - RULER_TAB_HEIGHT + 1 + 2 ) ); + } + } +} + +// ----------------------------------------------------------------------- + +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() ); + + ImplDrawRulerTab( pDevice, rPos, nStyle ); +} + +// ----------------------------------------------------------------------- + +void Ruler::ImplDrawTabs( long nMin, long nMax, long nVirBottom ) +{ + for ( USHORT i = 0; i < mpData->nTabs; i++ ) + { + if ( mpData->pTabs[i].nStyle & RULER_STYLE_INVISIBLE ) + continue; + + long n = mpData->pTabs[i].nPos+mpData->nNullVirOff; + if ( (n >= nMin) && (n <= nMax) ) + ImplDrawTab( &maVirDev, Point( n, nVirBottom ), 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.GetButtonTextColor(); + 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, nP2, nVirTop ); + if ( b3DLook ) + maVirDev.SetLineColor( rStyleSettings.GetLightColor() ); + ImplVDrawLine( nVirLeft, nVirBottom, nP2, nVirBottom ); + + // 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 ); + if ( nM2 < nP2 ) + ImplVDrawRect( nM2+1, nVirTop, nP2, nVirBottom ); + if ( nM2-nM1 > 0 ) + { + maVirDev.SetFillColor( rStyleSettings.GetWindowColor() ); + ImplVDrawRect( nM1, nVirTop, nM2-1, nVirBottom ); + } + if ( b3DLook ) + { + maVirDev.SetLineColor( rStyleSettings.GetLightColor() ); + if ( nM1 > nVirLeft ) + { + ImplVDrawLine( nP1+1, nVirTop, nM1-1, nVirTop ); + if ( nP1 >= nVirLeft ) + { + ImplVDrawLine( nP1+1, nVirTop, nP1+1, nVirBottom ); + ImplVDrawLine( nP1, nVirBottom+1, nP1+1, nVirBottom+1 ); + } + } + if ( nM2 < nP2 ) + { + ImplVDrawLine( nM2+1, nVirTop, nM2+1, nVirBottom ); + ImplVDrawLine( nM2+1, nVirTop, nP2, nVirTop ); + if ( nP2 <= nVirRight+1 ) + { + ImplVDrawLine( nP2, nVirTop-1, nP2, nVirBottom ); + ImplVDrawLine( nP2-1, nVirBottom+1, nP2, nVirBottom+1 ); + } + } + maVirDev.SetLineColor( rStyleSettings.GetShadowColor() ); + if ( nM1 > nVirLeft ) + { + ImplVDrawLine( nM1-1, nVirTop, nM1-1, nVirBottom ); + ImplVDrawLine( nP1, nVirBottom, nM1-1, nVirBottom ); + if ( nP1 >= nVirLeft ) + { + ImplVDrawLine( nP1, nVirTop, nP1, nVirBottom ); + ImplVDrawLine( nP1, nVirBottom, nP1+1, nVirBottom ); + } + } + if ( nM2 < nP2 ) + { + ImplVDrawLine( nM2+1, nVirBottom, nP2-1, nVirBottom ); + if ( nP2 <= nVirRight+1 ) + ImplVDrawLine( nP2-1, nVirTop, nP2-1, nVirBottom ); + } + if ( nM2-nM1 > 0 ) + { + maVirDev.SetLineColor( rStyleSettings.GetDarkShadowColor() ); + if ( nM1 >= nVirLeft ) + ImplVDrawLine( nM1, nVirTop, nM1, nVirBottom ); + ImplVDrawLine( nM1, nVirTop, nM2-1, nVirTop ); + maVirDev.SetLineColor( rStyleSettings.GetShadowColor() ); + ImplVDrawLine( nM1, nVirBottom, nM2-1, nVirBottom ); + if ( nM2 <= nVirRight ) + ImplVDrawLine( nM2, nVirTop, nM2, nVirBottom ); + } + } + 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 = 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, 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; + 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(); + if ( mnWinStyle & WB_HORZ ) + { + aOffPos.X() = mnVirOff; + aOffPos.Y() = RULER_OFF; + } + else + { + aOffPos.X() = RULER_OFF; + aOffPos.Y() = 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 ) + { + 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; + Point aCenter = aRect.Center(); + ImplCenterTabPos( aCenter, nTabStyle ); + ImplDrawTab( this, aCenter, 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 ) const +{ + USHORT i; + USHORT nStyle; + long nHitBottom; + long nX; + long nY; + long n1; + long n2; + + if ( !mbActive ) + return FALSE; + + // Position ermitteln + if ( mnWinStyle & WB_HORZ ) + { + nX = rPos.X(); + nY = rPos.Y(); + } + else + { + nX = rPos.Y(); + nY = rPos.X(); + } + nHitBottom = mnVirHeight+(RULER_OFF*2); + + // Initialisieren + memset( pHitTest, 0, sizeof( ImplRulerHitTest ) ); + + // 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 ( !(nStyle & RULER_STYLE_INVISIBLE) ) + { + nStyle &= RULER_INDENT_STYLE; + n1 = mpData->pIndents[i-1].nPos; + + if ( nStyle == RULER_INDENT_BOTTOM ) + { + 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 + 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--; + n2++; + } + + 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 + if ( (mpData->nMargin1Style & (RULER_MARGIN_SIZEABLE | RULER_STYLE_INVISIBLE)) == RULER_MARGIN_SIZEABLE ) + { + n1 = mpData->nMargin1; + if ( (nX >= n1-RULER_MOUSE_MARGINWIDTH) && (nX <= n1+RULER_MOUSE_MARGINWIDTH) ) + { + 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-RULER_MOUSE_MARGINWIDTH) && (nX <= n1+RULER_MOUSE_MARGINWIDTH) ) + { + 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; + + 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 ) ) + { + 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 ) ) + { + 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; + maDragData = maData; + mpData = &maDragData; + + // 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 = &maData; + } + + 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 = maDragData; + maDragData = maData; + 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 + maDragData = 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 ) + maDragData = maData; + else + maData = maDragData; + mpData = &maData; + 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 + if ( nNewHeight ) + { + mbCalc = TRUE; + mnVirHeight = nNewHeight - mnBorderWidth - (RULER_OFF*2); + ImplInitExtraField( FALSE ); + } + 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; + + // 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; + +#ifdef DBG_UTIL + default: + DBG_ERRORFILE( "Ruler::SetUnit() - Wrong Unit" ); + break; +#endif + } + + 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 ) + { + if ( mpData->pLines ) + 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 ) + { + if ( mpData->pArrows ) + 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 ) + { + if ( mpData->pBorders ) + 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 ) +{ + DBG_ASSERT( mnWinStyle & WB_HORZ, + "Ruler::SetIndents() not allowed when WB_VERT" ); + + if ( !n || !pIndentAry ) + { + if ( !mpData->pIndents ) + return; + delete mpData->pIndents; + mpData->nIndents = 0; + mpData->pIndents = NULL; + } + else + { + if ( mpData->nIndents != n ) + { + if ( mpData->pIndents ) + 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 ) +{ + DBG_ASSERT( mnWinStyle & WB_HORZ, + "Ruler::SetTabs() not allowed when WB_VERT" ); + + if ( !n || !pTabAry ) + { + if ( !mpData->pTabs ) + return; + delete mpData->pTabs; + mpData->nTabs = 0; + mpData->pTabs = NULL; + } + else + { + if ( mpData->nTabs != n ) + { + if ( mpData->pTabs ) + 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; + + pDevice->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); + pDevice->SetLineColor(); + pDevice->SetFillColor( pDevice->GetSettings().GetStyleSettings().GetWindowTextColor() ); + ImplCenterTabPos( aPos, nTabStyle ); + ImplDrawRulerTab( pDevice, aPos, nTabStyle ); + pDevice->Pop(); +} diff --git a/svtools/source/control/scrwin.cxx b/svtools/source/control/scrwin.cxx new file mode 100644 index 000000000000..10ef086ed9fd --- /dev/null +++ b/svtools/source/control/scrwin.cxx @@ -0,0 +1,603 @@ +/************************************************************************* + * + * $RCSfile: scrwin.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#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), 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 nDeltaX, long nDeltaY ) +{ +} + +//------------------------------------------------------------------- + +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 ) +{ + 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..026a6642d209 --- /dev/null +++ b/svtools/source/control/stdctrl.cxx @@ -0,0 +1,77 @@ +/************************************************************************* + * + * $RCSfile: stdctrl.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <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 ); +} diff --git a/svtools/source/control/stdmenu.cxx b/svtools/source/control/stdmenu.cxx new file mode 100644 index 000000000000..46707d960e3d --- /dev/null +++ b/svtools/source/control/stdmenu.cxx @@ -0,0 +1,446 @@ +/************************************************************************* + * + * $RCSfile: stdmenu.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <string.h> + +#ifndef _INTN_HXX +#include <tools/intn.hxx> +#endif +#ifndef _APP_HXX +#include <vcl/svapp.hxx> +#endif + +#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 ) +{ + // Menu loeschen + Clear(); + + // Fonts eintragen + International aIntn = Application::GetAppInternational(); + USHORT nFontCount = pList->GetFontNameCount(); + for ( USHORT i = 0; i < nFontCount; i++ ) + { + const XubString& rName = pList->GetFontName( i ).GetName(); + + // Sortieren, nach der in der Applikation eingestellten + // International-Klasse + USHORT j = GetItemCount(); + while ( j ) + { + XubString aText = GetItemText( GetItemId( j-1 ) ); + if ( aIntn.Compare( rName, aText ) == COMPARE_GREATER ) + 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(); +} + +// ----------------------------------------------------------------------- + +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 ) + { + USHORT nPos = 0; + USHORT nId = FONTSTYLEMENU_FIRSTID; + BOOL bNormal = FALSE; + BOOL bItalic = FALSE; + BOOL bBold = FALSE; + BOOL bBoldItalic = FALSE; + FontInfo aInfo; + while ( hFontInfo ) + { + aInfo = pList->GetFontInfo( hFontInfo ); + + XubString aStyleText = pList->GetStyleName( aInfo ); + FontWeight eWeight = aInfo.GetWeight(); + FontItalic eItalic = aInfo.GetItalic(); + if ( eWeight <= WEIGHT_NORMAL ) + { + bNormal = TRUE; + if ( eItalic != ITALIC_NONE ) + bItalic = TRUE; + } + else + { + if ( eItalic != ITALIC_NONE ) + bBoldItalic = TRUE; + else + bBold = TRUE; + } + if ( aStyleText == pList->GetItalicStr() ) + bItalic = TRUE; + else if ( aStyleText == pList->GetBoldStr() ) + bBold = TRUE; + else if ( aStyleText == pList->GetBoldItalicStr() ) + bBoldItalic = TRUE; + + InsertItem( nId, aStyleText, + MIB_RADIOCHECK | MIB_AUTOCHECK, nPos ); + nPos++; + nId++; + + hFontInfo = pList->GetNextFontInfo( hFontInfo ); + } + + // 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() : + maIntn( Application::GetAppInternational() ) +{ + mpHeightAry = NULL; + + maIntn.SetNumTrailingZeros( FALSE ); + maIntn.SetNumDigits( 1 ); + + SetMenuFlags( GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS ); +} + +// ----------------------------------------------------------------------- + +FontSizeMenu::~FontSizeMenu() +{ + if ( mpHeightAry ) + delete mpHeightAry; +} + +// ----------------------------------------------------------------------- + +void FontSizeMenu::Select() +{ + mnCurHeight = mpHeightAry[GetCurItemId()-1]; + maSelectHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void FontSizeMenu::Highlight() +{ + long nTempHeight = mnCurHeight; + USHORT nCurItemId = GetCurItemId(); + if ( !nCurItemId ) + mnCurHeight = 0; + else + mnCurHeight = mpHeightAry[nCurItemId-1]; + maHighlightHdl.Call( this ); + mnCurHeight = nTempHeight; +} + +// ----------------------------------------------------------------------- + +void FontSizeMenu::Fill( const FontInfo& rInfo, const FontList* pList ) +{ + // Menu loeschen + Clear(); + + // Groessen ermitteln + const long* pAry = pList->GetSizeAry( rInfo ); + + // Array kopieren + if ( mpHeightAry ) + delete mpHeightAry; + USHORT n = 0; + while ( pAry[n] ) + n++; + mpHeightAry = new long[n]; + memcpy( mpHeightAry, pAry, n*sizeof(long) ); + + // Groessen einfuegen + USHORT nId = 1; + while ( *pAry ) + { + InsertItem( nId, maIntn.GetNum( *pAry ), + MIB_RADIOCHECK | MIB_AUTOCHECK ); + nId++; + pAry++; + } + + SetCurHeight( mnCurHeight ); +} + +// ----------------------------------------------------------------------- + +void FontSizeMenu::SetCurHeight( long nHeight ) +{ + mnCurHeight = nHeight; + + // Menueintrag checken + XubString aHeight = maIntn.GetNum( nHeight ); + 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 == aHeight ) + { + CheckItem( nItemId, TRUE ); + return; + } + } + + 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..eaa4fee223e8 --- /dev/null +++ b/svtools/source/control/tabbar.cxx @@ -0,0 +1,2588 @@ +/************************************************************************* + * + * $RCSfile: tabbar.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _TOOLS_TIME_HXX +#include <tools/time.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _VCL_POLY_HXX +#include <vcl/poly.hxx> +#endif +#ifndef _VCL_APP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _VCL_HELP_HXX +#include <vcl/help.hxx> +#endif +#ifndef _VCL_DECOVIEW_HXX +#include <vcl/decoview.hxx> +#endif +#ifndef _VCL_BUTTON_HXX +#include <vcl/button.hxx> +#endif +#ifndef _VCL_EDIT_HXX +#include <vcl/edit.hxx> +#endif + +#define _SV_TABBAR_CXX +#define private public +#include <tabbar.hxx> + +// ======================================================================= + +#define TABBAR_OFFSET_X 7 +#define TABBAR_OFFSET_X2 2 +#define TABBAR_DRAG_SCROLLOFF 5 +#define TABBAR_MINSIZE 5 + +// ======================================================================= + +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 ); + virtual BOOL QueryDrop( const DropEvent& rDEvt ); + virtual BOOL Drop( const DropEvent& rEvt ); +}; + +// ======================================================================= + +long ImplTabButton::PreNotify( NotifyEvent& rNEvt ) +{ + if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN ) + { + if ( GetParent()->IsInEditMode() ) + { + GetParent()->EndEditMode(); + return TRUE; + } + } + + return PushButton::PreNotify( rNEvt ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplTabButton::QueryDrop( const DropEvent& rDEvt ) +{ + TabBar* pParent = GetParent(); + Point aPos = OutputToScreenPixel( rDEvt.GetPosPixel() ); + aPos = pParent->ScreenToOutputPixel( aPos ); + BYTE nWindowType = rDEvt.GetWindowType(); + if ( rDEvt.IsLeaveWindow() ) + { + Size aWinSize = pParent->GetSizePixel(); + if ( ((aPos.X() >= 0) && (aPos.X() < aWinSize.Width())) && + ((aPos.Y() >= 0) && (aPos.Y() < aWinSize.Height())) ) + nWindowType = 0; + } + DropEvent aNewDEvt( aPos, rDEvt.GetData(), rDEvt.GetAction(), nWindowType ); + return pParent->QueryDrop( aNewDEvt ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplTabButton::Drop( const DropEvent& rDEvt ) +{ + TabBar* pParent = GetParent(); + Point aPos = OutputToScreenPixel( rDEvt.GetPosPixel() ); + aPos = pParent->ScreenToOutputPixel( aPos ); + DropEvent aNewDEvt( aPos, rDEvt.GetData(), rDEvt.GetAction(), rDEvt.GetWindowType() ); + return pParent->Drop( aNewDEvt ); +} + +// ======================================================================= + +// ---------------- +// - ImplTabSizer - +// ---------------- + +class ImplTabSizer : public Window +{ +private: + Point maStartPos; + long mnOff; + +public: + ImplTabSizer( TabBar* pParent, WinBits nWinStyle = 0 ); + + TabBar* GetParent() const { return (TabBar*)Window::GetParent(); } + void ImplTrack( const Point& rMousePos ); + + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + virtual void Tracking( const TrackingEvent& rTEvt ); + virtual void Paint( const Rectangle& rRect ); + virtual BOOL QueryDrop( const DropEvent& rDEvt ); + virtual BOOL Drop( const DropEvent& rEvt ); +}; + +// ----------------------------------------------------------------------- + +ImplTabSizer::ImplTabSizer( TabBar* pParent, WinBits nWinStyle ) : + Window( pParent, nWinStyle & WB_3DLOOK ) +{ + SetPointer( Pointer( POINTER_HSIZEBAR ) ); + SetSizePixel( Size( 7, 0 ) ); +} + +// ----------------------------------------------------------------------- + +void ImplTabSizer::ImplTrack( const Point& rMousePos ) +{ + TabBar* pParent = GetParent(); + Point aWinPos = pParent->GetPosPixel(); + Size aWinSize = GetSizePixel(); + + aWinPos = pParent->GetParent()->OutputToScreenPixel( aWinPos ); + pParent->mnSplitSize = rMousePos.X() - aWinPos.X() + (aWinSize.Width()-mnOff); + 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() ) + { + Point aMousePos = rMEvt.GetPosPixel(); + maStartPos = OutputToScreenPixel( aMousePos ); + mnOff = aMousePos.X(); + 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 ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplTabSizer::QueryDrop( const DropEvent& rDEvt ) +{ + TabBar* pParent = GetParent(); + Point aPos = OutputToScreenPixel( rDEvt.GetPosPixel() ); + aPos = pParent->ScreenToOutputPixel( aPos ); + BYTE nWindowType = rDEvt.GetWindowType(); + if ( rDEvt.IsLeaveWindow() ) + { + Size aWinSize = pParent->GetSizePixel(); + if ( ((aPos.X() >= 0) && (aPos.X() < aWinSize.Width())) && + ((aPos.Y() >= 0) && (aPos.Y() < aWinSize.Height())) ) + nWindowType = 0; + } + DropEvent aNewDEvt( aPos, rDEvt.GetData(), rDEvt.GetAction(), nWindowType ); + return pParent->QueryDrop( aNewDEvt ); +} + +// ----------------------------------------------------------------------- + +BOOL ImplTabSizer::Drop( const DropEvent& rDEvt ) +{ + TabBar* pParent = GetParent(); + Point aPos = OutputToScreenPixel( rDEvt.GetPosPixel() ); + aPos = pParent->ScreenToOutputPixel( aPos ); + DropEvent aNewDEvt( aPos, rDEvt.GetData(), rDEvt.GetAction(), rDEvt.GetWindowType() ); + return pParent->Drop( aNewDEvt ); +} + +// ======================================================================= + +// 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*, pCancel ) +{ + 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; +} + +// ======================================================================= + +void TabBar::ImplInit( WinBits nWinStyle ) +{ + mpItemList = new ImplTabBarList; + mpFirstBtn = NULL; + mpPrevBtn = NULL; + mpNextBtn = NULL; + mpLastBtn = NULL; + mpSizer = NULL; + mpEdit = NULL; + mnMaxPageWidth = 0; + mnCurMaxWidth = 0; + mnOffX = 0; + mnOffY = 0; + mnOutWidth = 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; + + if ( nWinStyle & WB_3DTAB ) + mnOffY++; + + if ( nWinStyle & WB_DRAG ) + EnableDrop(); + + ImplInitControls(); + ImplInitSettings( TRUE, TRUE ); + SetSizePixel( Size( 100, CalcWindowSizePixel().Height() ) ); +} + +// ----------------------------------------------------------------------- + +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; + if ( mpSizer ) + delete mpSizer; + + // 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 aFont; + aFont = rStyleSettings.GetToolFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + aFont.SetWeight( WEIGHT_BOLD ); + SetZoomedPointFont( 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.GetFaceColor(); + if ( IsControlForeground() ) + rFaceTextColor = GetControlForeground(); + else + rFaceTextColor = rStyleSettings.GetButtonTextColor(); + if ( mbSelColor ) + rSelectColor = maSelColor; + else + rSelectColor = rStyleSettings.GetWindowColor(); + 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 = mnOutWidth-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 > mnOutWidth) ) + 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; + } + + 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 = mnOutWidth-mnOffX-TABBAR_OFFSET_X; + 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 ( !mpSizer ) + mpSizer = new ImplTabSizer( this, mnWinStyle & (WB_DRAG | WB_3DLOOK) ); + mpSizer->Show(); + + if ( mnWinStyle & WB_DRAG ) + mpSizer->EnableDrop(); + } + else + { + if ( mpSizer ) + { + delete mpSizer; + mpSizer = NULL; + } + } + + Link aLink = LINK( this, TabBar, ImplClickHdl ); + + if ( mnWinStyle & (WB_MINSCROLL | WB_SCROLL) ) + { + if ( !mpPrevBtn ) + { + mpPrevBtn = new ImplTabButton( this, WB_REPEAT ); + mpPrevBtn->SetSymbol( SYMBOL_PREV ); + mpPrevBtn->SetClickHdl( aLink ); + if ( mnWinStyle & WB_DRAG ) + mpPrevBtn->EnableDrop(); + } + mpPrevBtn->Show(); + + if ( !mpNextBtn ) + { + mpNextBtn = new ImplTabButton( this, WB_REPEAT ); + mpNextBtn->SetSymbol( SYMBOL_NEXT ); + mpNextBtn->SetClickHdl( aLink ); + if ( mnWinStyle & WB_DRAG ) + mpNextBtn->EnableDrop(); + } + mpNextBtn->Show(); + } + else + { + if ( mpPrevBtn ) + { + delete mpPrevBtn; + mpPrevBtn = NULL; + } + if ( mpNextBtn ) + { + delete mpNextBtn; + mpNextBtn = NULL; + } + } + + if ( mnWinStyle & WB_SCROLL ) + { + if ( !mpFirstBtn ) + { + mpFirstBtn = new ImplTabButton( this ); + mpFirstBtn->SetSymbol( SYMBOL_FIRST ); + mpFirstBtn->SetClickHdl( aLink ); + if ( mnWinStyle & WB_DRAG ) + mpFirstBtn->EnableDrop(); + } + mpFirstBtn->Show(); + + if ( !mpLastBtn ) + { + mpLastBtn = new ImplTabButton( this ); + mpLastBtn->SetSymbol( SYMBOL_LAST ); + mpLastBtn->SetClickHdl( aLink ); + if ( mnWinStyle & WB_DRAG ) + mpLastBtn->EnableDrop(); + } + mpLastBtn->Show(); + } + else + { + if ( mpFirstBtn ) + { + delete mpFirstBtn; + mpFirstBtn = NULL; + } + if ( mpLastBtn ) + { + delete mpLastBtn; + mpLastBtn = NULL; + } + } +} + +// ----------------------------------------------------------------------- + +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; + } + + if ( !rMEvt.IsLeft() ) + { + Window::MouseButtonDown( rMEvt ); + return; + } + + ImplTabBarItem* pItem; + USHORT nSelId = GetPageId( rMEvt.GetPosPixel() ); + + 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(); + Select(); + } + } + 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 ( DeactivatePage() ) + { + SetCurPageId( nSelId ); + Update(); + ActivatePage(); + Select(); + } + } + 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 ); + + // 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 ); +} + +// ----------------------------------------------------------------------- + +void TabBar::Resize() +{ + Size aNewSize = GetOutputSizePixel(); + + // Sizer anordnen + if ( mpSizer ) + { + Size aSizerSize = mpSizer->GetSizePixel(); + Point aNewSizerPos( aNewSize.Width()-aSizerSize.Width(), 0 ); + Size aNewSizerSize( aSizerSize.Width(), aNewSize.Height() ); + mpSizer->SetPosSizePixel( aNewSizerPos, aNewSizerSize ); + mnOutWidth = aNewSize.Width() - aSizerSize.Width() - 1; + } + else + mnOutWidth = aNewSize.Width()-1; + + // Scroll-Buttons anordnen + long nHeight = aNewSize.Height(); + if ( nHeight != maWinSize.Height() ) + { + long nX = 0; + Size aBtnSize( nHeight, nHeight ); + if ( mpFirstBtn ) + { + mpFirstBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); + nX += nHeight; + } + if ( mpPrevBtn ) + { + mpPrevBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); + nX += nHeight; + } + if ( mpNextBtn ) + { + mpNextBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); + nX += nHeight; + } + if ( mpLastBtn ) + { + mpLastBtn->SetPosSizePixel( Point( nX, 0 ), aBtnSize ); + nX += nHeight; + } + mnOffX = nX; + } + + // Groesse merken + maWinSize = aNewSize; + + // 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 ); + 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 > mnOutWidth) ) + { + 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(); + } +} + +// ----------------------------------------------------------------------- + +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::Select() +{ + maSelectHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void TabBar::DoubleClick() +{ + maDoubleClickHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void TabBar::Split() +{ + maSplitHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +void TabBar::ActivatePage() +{ + maActivatePageHdl.Call( this ); +} + +// ----------------------------------------------------------------------- + +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::InsertPage( USHORT nPageId, const XubString& rText, + TabBarPageBits nBits, USHORT nPos ) +{ + DBG_ASSERT( nPageId, "TabBar::InsertPage(): PageId == 0" ); + DBG_ASSERT( GetPagePos( nPageId ) == TAB_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(); +} + +// ----------------------------------------------------------------------- + +void TabBar::RemovePage( USHORT nPageId ) +{ + USHORT nPos = GetPagePos( nPageId ); + + // Existiert Item + if ( nPos != TAB_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(); + } +} + +// ----------------------------------------------------------------------- + +void TabBar::MovePage( USHORT nPageId, USHORT nNewPos ) +{ + USHORT nPos = GetPagePos( nPageId ); + + if ( nPos < nNewPos ) + nNewPos--; + + if ( nPos == nNewPos ) + return; + + // Existiert Item + if ( nPos != TAB_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(); + } +} + +// ----------------------------------------------------------------------- + +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(); +} + +// ----------------------------------------------------------------------- + +void TabBar::EnablePage( USHORT nPageId, BOOL bEnable ) +{ + USHORT nPos = GetPagePos( nPageId ); + + if ( nPos != TAB_PAGE_NOTFOUND ) + { + ImplTabBarItem* pItem = mpItemList->GetObject( nPos ); + + if ( pItem->mbEnable != bEnable ) + { + pItem->mbEnable = bEnable; + + // Leiste neu ausgeben + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate( pItem->maRect ); + } + } +} + +// ----------------------------------------------------------------------- + +BOOL TabBar::IsPageEnabled( USHORT nPageId ) const +{ + USHORT nPos = GetPagePos( nPageId ); + + if ( nPos != TAB_PAGE_NOTFOUND ) + return mpItemList->GetObject( nPos )->mbEnable; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +void TabBar::SetPageBits( USHORT nPageId, TabBarPageBits nBits ) +{ + USHORT nPos = GetPagePos( nPageId ); + + if ( nPos != TAB_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 != TAB_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 TAB_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 != TAB_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 != TAB_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 = mnOutWidth; + if ( nWidth > TABBAR_OFFSET_X ) + nWidth -= TABBAR_OFFSET_X; + + if ( pItem->maRect.IsEmpty() ) + 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; + } + } + } + + // Leiste neu ausgeben + if ( bUpdate ) + { + Invalidate( pItem->maRect ); + if ( pOldItem ) + Invalidate( pOldItem->maRect ); + } + } +} + +// ----------------------------------------------------------------------- + +void TabBar::SetFirstPageId( USHORT nPageId ) +{ + USHORT nPos = GetPagePos( nPageId ); + + // Wenn Item nicht existiert, dann FALSE zurueckgeben + if ( nPos != TAB_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 != TAB_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 != TAB_PAGE_NOTFOUND ) + return mpItemList->GetObject( nPos )->mbSelect; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL TabBar::StartEditMode( USHORT nPageId ) +{ + USHORT nPos = GetPagePos( nPageId ); + if ( mpEdit || (nPos == TAB_PAGE_NOTFOUND) || (mnOutWidth < 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 > mnOutWidth ) + nWidth = mnOutWidth-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 == TAB_RENAMING_YES ) + SetPageText( mnEditId, maEditText ); + else if ( nAllowRenaming == TAB_RENAMING_NO ) + bEnd = FALSE; + else // nAllowRenaming == TAB_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::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 != TAB_PAGE_NOTFOUND ) + { + mpItemList->GetObject( nPos )->maText = rText; + mbSizeFormat = TRUE; + + // Leiste neu ausgeben + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } +} + +// ----------------------------------------------------------------------- + +XubString TabBar::GetPageText( USHORT nPageId ) const +{ + USHORT nPos = GetPagePos( nPageId ); + if ( nPos != TAB_PAGE_NOTFOUND ) + return mpItemList->GetObject( nPos )->maText; + else + return XubString(); +} + +// ----------------------------------------------------------------------- + +void TabBar::SetHelpText( USHORT nPageId, const XubString& rText ) +{ + USHORT nPos = GetPagePos( nPageId ); + if ( nPos != TAB_PAGE_NOTFOUND ) + mpItemList->GetObject( nPos )->maHelpText = rText; +} + +// ----------------------------------------------------------------------- + +XubString TabBar::GetHelpText( USHORT nPageId ) const +{ + USHORT nPos = GetPagePos( nPageId ); + if ( nPos != TAB_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 ); + } + + return pItem->maHelpText; + } + else + return XubString(); +} + +// ----------------------------------------------------------------------- + +void TabBar::SetHelpId( USHORT nPageId, ULONG nHelpId ) +{ + USHORT nPos = GetPagePos( nPageId ); + if ( nPos != TAB_PAGE_NOTFOUND ) + mpItemList->GetObject( nPos )->mnHelpId = nHelpId; +} + +// ----------------------------------------------------------------------- + +ULONG TabBar::GetHelpId( USHORT nPageId ) const +{ + USHORT nPos = GetPagePos( nPageId ); + if ( nPos != TAB_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 ( DeactivatePage() ) + { + SetCurPageId( nSelId ); + Update(); + ActivatePage(); + Select(); + } + else + return FALSE; + } + } + mbInSelect = FALSE; + + +#ifdef MAC + PolyPolygon aPolyPoly; + + ImplTabBarItem* pItem = mpItemList->First(); + while ( pItem ) + { + if ( pItem->mbSelect && !pItem->maRect.IsEmpty() ) + { + // Polygon fuer DragRegion aufbauen + Rectangle aRect = pItem->maRect; + Polygon aPoly( 4 ); + aPoly[0] = Point( aRect.Left(), mnOffY ); + aPoly[1] = Point( aRect.Left()+TABBAR_OFFSET_X, aRect.Bottom() ); + aPoly[2] = Point( aRect.Right()-TABBAR_OFFSET_X, aRect.Bottom() ); + aPoly[3] = Point( aRect.Right(), mnOffY ); + aPolyPoly.Insert( aPoly ); + } + + pItem = mpItemList->Next(); + } + + Region aRegion( aPolyPoly ); +#else + Region aRegion; +#endif + + // 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() > mnOutWidth-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, mnOutWidth, maWinSize.Height() ); + SetFillColor(); + 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 ( DeactivatePage() ) + { + SetCurPageId( mnSwitchId ); + Update(); + ActivatePage(); + Select(); + 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, GetTextHeight()+3 ); +} diff --git a/svtools/source/control/taskbar.cxx b/svtools/source/control/taskbar.cxx new file mode 100644 index 000000000000..131bede4df03 --- /dev/null +++ b/svtools/source/control/taskbar.cxx @@ -0,0 +1,645 @@ +/************************************************************************* + * + * $RCSfile: taskbar.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _TASKBAR_CXX + +#ifndef _TOOLS_LIST_HXX +#include <tools/list.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _VCL_FLOATWIN_HXX +#include <vcl/floatwin.hxx> +#endif + +#include <taskbar.hxx> + +// ======================================================================= + +class ImplTaskBarFloat : public FloatingWindow +{ +public: + TaskBar* mpTaskBar; + +public: + ImplTaskBarFloat( TaskBar* pTaskBar ); + + void Paint(); +}; + +// ----------------------------------------------------------------------- + +ImplTaskBarFloat::ImplTaskBarFloat( TaskBar* pTaskBar ) : + FloatingWindow( pTaskBar, 0 ) +{ + mpTaskBar = pTaskBar; +} + +// ----------------------------------------------------------------------- + +void ImplTaskBarFloat::Paint() +{ +} + +// ======================================================================= + +#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(); + +#ifdef MAC + if ( !Application::IsFullScreenMode() ) + aSize.Width() -= 17; +#endif + + 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); + +#ifdef MAC + if ( !Application::IsFullScreenMode() ) + aSize.Width() -= 17; +#endif + + 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..73a9798a12ee --- /dev/null +++ b/svtools/source/control/taskbox.cxx @@ -0,0 +1,406 @@ +/************************************************************************* + * + * $RCSfile: taskbox.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _TASKBAR_CXX + +#ifndef _TOOLS_LIST_HXX +#include <tools/list.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _SV_IMAGE_HXX +#include <vcl/image.hxx> +#endif +#ifndef _SV_SYSTEM_HXX +#include <vcl/system.hxx> +#endif +#ifndef _SV_HELP_HXX +#include <vcl/help.hxx> +#endif + +#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; + ImplFormat(); + 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 = OutputToScreenPixel( 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 ); +} + +// ----------------------------------------------------------------------- + +BOOL TaskToolBox::QueryDrop( DropEvent& rDEvt ) +{ + if ( !rDEvt.IsLeaveWindow() ) + { + USHORT nItemId = GetItemId( rDEvt.GetPosPixel() ); + if ( nItemId ) + ActivateTaskItem( nItemId ); + } + return ToolBox::QueryDrop( rDEvt ); +} + +// ----------------------------------------------------------------------- + +void TaskToolBox::Select() +{ + USHORT nItemId = GetCurItemId(); + ActivateTaskItem( nItemId, TRUE ); +} + +// ----------------------------------------------------------------------- + +void TaskToolBox::ImplFormat() +{ + 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; + } + + ImplFormat(); +} + diff --git a/svtools/source/control/taskmisc.cxx b/svtools/source/control/taskmisc.cxx new file mode 100644 index 000000000000..1438417d2a88 --- /dev/null +++ b/svtools/source/control/taskmisc.cxx @@ -0,0 +1,416 @@ +/************************************************************************* + * + * $RCSfile: taskmisc.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _TASKBAR_CXX + +#ifndef _TOOLS_LIST_HXX +#include <tools/list.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _SV_HELP_HXX +#include <vcl/help.hxx> +#endif + +#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 -= 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; + long nLeftBorder; + long nTopBorder; + long nRightBorder; + long nBottomBorder; + long nStartOverWidth; + long nStartOverHeight; + long nOverWidth; + long nOverHeight; + 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..4c83b4bd09e9 --- /dev/null +++ b/svtools/source/control/taskstat.cxx @@ -0,0 +1,769 @@ +/************************************************************************* + * + * $RCSfile: taskstat.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define _TASKBAR_CXX + +#ifndef _TOOLS_LIST_HXX +#include <tools/list.hxx> +#endif +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _SV_IMAGE_HXX +#include <vcl/image.hxx> +#endif +#ifndef _SV_SYSTEM_HXX +#include <vcl/system.hxx> +#endif +#ifndef _SV_HELP_HXX +#include <vcl/help.hxx> +#endif +#ifndef _SV_SVAPP_HXX +#include <vcl/svapp.hxx> +#endif + +#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 nItemd, const MouseEvent& rMEvt ) +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL ITaskStatusNotify::MouseButtonUp( USHORT nItemd, const MouseEvent& rMEvt ) +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL ITaskStatusNotify::MouseMove( USHORT nItemd, const MouseEvent& rMEvt ) +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL ITaskStatusNotify::Command( USHORT nItemd, const CommandEvent& rCEvt ) +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL ITaskStatusNotify::QueryDrop( USHORT nItemd, DropEvent& rDEvt, BOOL& bRet ) +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL ITaskStatusNotify::Drop( USHORT nItemd, const DropEvent& rDEvt, BOOL& bRet ) +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +BOOL ITaskStatusNotify::UpdateHelp( USHORT nItemd ) +{ + 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 = maIntn.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 = maIntn.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 ); +} + +// ----------------------------------------------------------------------- + +BOOL TaskStatusBar::QueryDrop( DropEvent& rDEvt ) +{ + BOOL bFieldRect; + BOOL bBaseClass = FALSE; + BOOL bRet = FALSE; + ImplTaskSBFldItem* pItem = ImplGetFieldItem( rDEvt.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->QueryDrop( nItemId, rDEvt, bRet ); + + if ( bBaseClass ) + { + StatusBar::QueryDrop( rDEvt ); + return TRUE; + } + else + return bRet; +} + +// ----------------------------------------------------------------------- + +BOOL TaskStatusBar::Drop( const DropEvent& rDEvt ) +{ + BOOL bFieldRect; + BOOL bBaseClass = FALSE; + BOOL bRet = FALSE; + ImplTaskSBFldItem* pItem = ImplGetFieldItem( rDEvt.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->Drop( nItemId, rDEvt, bRet ); + + if ( bBaseClass ) + return StatusBar::Drop( rDEvt ); + else + return bRet; +} + +// ----------------------------------------------------------------------- + +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 + { + XubString aStr = maIntn.GetLongDate( Date() ); + 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 ); + 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 nOffset, USHORT nPos, + 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/valueset.cxx b/svtools/source/control/valueset.cxx new file mode 100644 index 000000000000..79f0acb6a098 --- /dev/null +++ b/svtools/source/control/valueset.cxx @@ -0,0 +1,2461 @@ +/************************************************************************* + * + * $RCSfile: valueset.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:58:57 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _LIST_HXX +#include <tools/list.hxx> +#endif +#ifndef _DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifdef VCL +#ifndef _SV_DECOVIEW_HXX +#include <vcl/decoview.hxx> +#endif +#include <vcl/svapp.hxx> +#endif +#ifndef _IMAGE_HXX +#include <vcl/image.hxx> +#endif +#ifndef _SCRBAR_HXX +#include <vcl/scrbar.hxx> +#endif +#ifndef _HELP_HXX +#include <vcl/help.hxx> +#endif + +#define _SV_VALUESET_CXX +#define private public +#include <valueset.hxx> + +// ======================================================================= + +#define ITEM_OFFSET 4 +#define ITEM_OFFSET_DOUBLE 6 +#define NAME_OFFSET 2 +#define NAME_OFFSET_FLAT 1 +#define SCRBAR_OFFSET 2 +#define VALUESET_ITEM_NONEITEM 0xFFFE + +#define VALUESET_SCROLL_OFFSET 4 + +enum ValueSetItemType { VALUESETITEM_NONE, VALUESETITEM_IMAGE, + VALUESETITEM_COLOR, VALUESETITEM_USERDRAW, + VALUESETITEM_SPACE }; + +struct ValueSetItem +{ + USHORT mnId; + USHORT mnBits; + ValueSetItemType meType; + Image maImage; + Color maColor; + XubString maText; + void* mpData; + Rectangle maRect; + + ValueSetItem(); + ~ValueSetItem(); +}; + +DECLARE_LIST( ValueItemList, ValueSetItem* ); + +// ======================================================================= + +ValueSetItem::ValueSetItem() +{ + mnBits = 0; + mpData = NULL; +} + +// ----------------------------------------------------------------------- + +ValueSetItem::~ValueSetItem() +{ +} + +// ======================================================================= + +void ValueSet::ImplInit( WinBits nWinStyle ) +{ + Size aWinSize = GetSizePixel(); + mpItemList = new ValueItemList; + 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; + + ImplInitSettings( TRUE, TRUE, TRUE ); +} + +// ----------------------------------------------------------------------- + +ValueSet::ValueSet( Window* pParent, WinBits nWinStyle ) : + Control( pParent, nWinStyle ), + maVirDev( *this ), + maColor( COL_TRANSPARENT ) +{ + ImplInit( nWinStyle ); +} + +// ----------------------------------------------------------------------- + +ValueSet::ValueSet( Window* pParent, const ResId& rResId ) : + Control( pParent, rResId ), + maVirDev( *this ), + maColor( COL_TRANSPARENT ) +{ + ImplInit( rResId.aWinBits ); +} + +// ----------------------------------------------------------------------- + +ValueSet::~ValueSet() +{ + if ( mpScrBar ) + delete mpScrBar; + + if ( mpNoneItem ) + delete mpNoneItem; + + ValueSetItem* pItem = mpItemList->First(); + while ( pItem ) + { + delete pItem; + pItem = mpItemList->Next(); + } + delete mpItemList; +} + +// ----------------------------------------------------------------------- + +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_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( rStyleSettings.GetWindowTextColor() ); + maVirDev.SetTextFillColor(); + maVirDev.SetFillColor( 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 + { + if ( IsColor() ) + maVirDev.SetFillColor( maColor ); + else + maVirDev.SetFillColor( GetSettings().GetStyleSettings().GetWindowColor() ); + 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; + if ( (aImageSize.Width() > aRectSize.Width()) || + (aImageSize.Height() > aRectSize.Height()) ) + { + maVirDev.SetClipRegion( Region( aRect ) ); + maVirDev.DrawImage( aPos, pItem->maImage ); + maVirDev.SetClipRegion(); + } + else + maVirDev.DrawImage( aPos, pItem->maImage ); + } + } + } +} + +// ----------------------------------------------------------------------- + +void ValueSet::Format() +{ + Size aWinSize = GetOutputSizePixel(); + Size aOrgWinSize = aWinSize; + ULONG nItemCount = mpItemList->Count(); + WinBits nStyle = GetStyle(); + long nTxtHeight = GetTextHeight(); + long nStartX; + long nY; + long nNameOff; + long nOff; + long nSpace; + 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 ) + { + long nNameOffset = (nStyle & WB_FLATVALUESET) ? NAME_OFFSET_FLAT : NAME_OFFSET; + aWinSize.Height() -= nTxtHeight+(nNameOffset*2); + nNameOff = nNameOffset+2+nSpace; + } + else + nNameOff = 0; + + // Offset und Groesse beruecksichtigen, wenn NoneField vorhanden + if ( nStyle & WB_NONEFIELD ) + { + nY = nTxtHeight+nOff; + nNoneSpace = nSpace; + if ( nStyle & WB_RADIOSEL ) + nY += 8; + } + else + { + nY = 0; + nNoneSpace = 0; + } + + // 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)mpItemList->Count() / mnCols; + if ( mpItemList->Count() % mnCols ) + mnLines++; + else if ( !mnLines ) + mnLines = 1; + + long nCalcHeight = aWinSize.Height()-nY-nNameOff; + 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; + } + + // Windowgroessen runden und virtuelles Device anlegen + aWinSize.Width() = (nItemWidth*mnCols)+nColSpace+nScrBarWidth; + aWinSize.Height() = (nItemHeight*mnVisLines)+nY+nNameOff+nLineSpace; + nStartX = (aOrgWinSize.Width()-aWinSize.Width())/2; + maVirDev.SetSettings( GetSettings() ); + maVirDev.SetBackground( GetBackground() ); + maVirDev.SetOutputSizePixel( Size( aOrgWinSize.Width(), + aWinSize.Height() ), TRUE ); + + // Bei zu kleinen Items machen wir nichts + long nMinHeight = 2; + if ( nStyle & WB_ITEMBORDER ) + nMinHeight = 4; + if ( (nItemWidth <= 0) || (nItemHeight <= nMinHeight) || !nItemCount ) + { + for ( ULONG i = 0; i < nItemCount; i++ ) + { + ValueSetItem* pItem = mpItemList->GetObject( i ); + pItem->maRect.SetEmpty(); + } + + if ( nStyle & WB_NONEFIELD ) + { + if ( mpNoneItem ) + { + mpNoneItem->maRect.SetEmpty(); + mpNoneItem->maText = GetText(); + } + } + else + { + if ( mpNoneItem ) + { + delete mpNoneItem; + mpNoneItem = NULL; + } + } + + 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; + + // Trennlinie zum Namefield zeichnen + if ( nStyle & WB_NAMEFIELD ) + { + if ( !(nStyle & WB_FLATVALUESET) ) + { + Point aPos1( nStartX+ITEM_OFFSET, aWinSize.Height()-2 ); + Point aPos2( nStartX+aWinSize.Width()-ITEM_OFFSET-1, + aWinSize.Height()-2 ); + if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) ) + { + maVirDev.SetLineColor( rStyleSettings.GetShadowColor() ); + maVirDev.DrawLine( aPos1, aPos2 ); + aPos1.Y()++; + aPos2.Y()++; + maVirDev.SetLineColor( rStyleSettings.GetLightColor() ); + } + else + maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() ); + maVirDev.DrawLine( aPos1, aPos2 ); + } + + // TextOffset befindet sich unter der Kante + long nNameOffset = (nStyle & WB_FLATVALUESET) ? NAME_OFFSET_FLAT : NAME_OFFSET; + mnTextOffset = aWinSize.Height()+nNameOffset; + } + + // Items berechnen und zeichnen + maVirDev.SetLineColor(); + long x = nStartX; + long y = nY+nNoneSpace; + ULONG nFirstItem = mnFirstLine * mnCols; + ULONG nLastItem = nFirstItem + (mnVisLines * mnCols); + for ( ULONG i = 0; i < nItemCount; i++ ) + { + ValueSetItem* pItem = mpItemList->GetObject( i ); + + if ( (i >= nFirstItem) && (i < nLastItem) ) + { + pItem->maRect.Left() = x; + pItem->maRect.Top() = y; + pItem->maRect.Right() = pItem->maRect.Left()+nItemWidth-1; + pItem->maRect.Bottom() = pItem->maRect.Top()+nItemHeight-1; + + ImplFormatItem( pItem ); + + if ( !((i+1) % mnCols) ) + { + x = nStartX; + y += nItemHeight+nSpace; + } + else + x += nItemWidth+nSpace; + } + else + pItem->maRect.SetEmpty(); + } + + // NoSelection-Field erzeugen und anzeigen + if ( nStyle & WB_NONEFIELD ) + { + if ( !mpNoneItem ) + mpNoneItem = new ValueSetItem; + + mpNoneItem->mnId = 0; + mpNoneItem->meType = VALUESETITEM_NONE; + mpNoneItem->maRect.Left() = nStartX; + mpNoneItem->maRect.Right() = mpNoneItem->maRect.Left()+aWinSize.Width()-1; + mpNoneItem->maRect.Bottom() = nY-1; + + ImplFormatItem( mpNoneItem ); + } + else + { + if ( mpNoneItem ) + { + delete mpNoneItem; + mpNoneItem = NULL; + } + } + + // ScrollBar anordnen, Werte setzen und anzeigen + if ( mpScrBar ) + { + Point aPos( nStartX+(nItemWidth*mnCols)+nColSpace+SCRBAR_OFFSET, + nY+nNoneSpace+1 ); + Size aSize( nScrBarWidth-SCRBAR_OFFSET, + ((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 ); + + // Rechteck loeschen und Text ausgeben + if ( GetStyle() & WB_FLATVALUESET ) + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + SetLineColor(); + SetFillColor( rStyleSettings.GetFaceColor() ); + DrawRect( Rectangle( Point( 0, mnTextOffset ), Point( aWinSize.Width(), aWinSize.Height() ) ) ); + SetTextColor( rStyleSettings.GetButtonTextColor() ); + } + else + Erase( Rectangle( Point( 0, mnTextOffset ), Point( aWinSize.Width(), aWinSize.Height() ) ) ); + DrawText( Point( (aWinSize.Width()-nTxtWidth) / 2, mnTextOffset ), 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; + + if ( mbHighlight ) + nItemId = mnHighItemId; + + ValueSetItem* pItem; + if ( nItemId ) + pItem = mpItemList->GetObject( GetItemPos( nItemId ) ); + else + { + if ( mpNoneItem ) + pItem = mpNoneItem; + else + { + pItem = ImplGetFirstItem(); + if ( !bFocus || !pItem ) + return; + } + } + + if ( pItem->maRect.IsEmpty() ) + return; + + // Selection malen + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + Rectangle aRect = pItem->maRect; + Control::SetFillColor(); + + // Selectionsausgabe festlegen + WinBits nStyle = GetStyle(); + 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 ); + + if ( bDrawSel ) + { + SetLineColor( rStyleSettings.GetHighlightColor() ); + 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( rStyleSettings.GetHighlightColor() ); + 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( rStyleSettings.GetHighlightTextColor() ); + } + else + SetLineColor( Color( COL_LIGHTGRAY ) ); + DrawRect( aRect2 ); + + if ( bFocus ) + ShowFocus( aRect2 ); + } + + ImplDrawItemText( pItem->maText ); +} + +// ----------------------------------------------------------------------- + +void ValueSet::ImplHideSelect( USHORT nItemId ) +{ + Rectangle aRect; + + if ( nItemId ) + aRect = mpItemList->GetObject( GetItemPos( nItemId ) )->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) && mpItemList->Count() ) + { + USHORT nItemPos = mnDropPos; + USHORT nItemId1; + USHORT nItemId2 = 0; + BOOL bRight; + if ( nItemPos >= mpItemList->Count() ) + { + nItemPos = (USHORT)(mpItemList->Count()-1); + bRight = TRUE; + } + else + bRight = FALSE; + + nItemId1 = GetItemId( nItemPos ); + if ( (nItemId1 != mnSelItemId) && (nItemId1 != mnHighItemId) ) + nItemId1 = 0; + Rectangle aRect2 = mpItemList->GetObject( nItemPos )->maRect; + Rectangle aRect1; + if ( bRight ) + { + aRect1 = aRect2; + aRect2.SetEmpty(); + } + else if ( nItemPos > 0 ) + { + aRect1 = 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 ) + { + 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 ); + + 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 = 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 = 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 ) +{ + if ( mpNoneItem ) + { + if ( mpNoneItem->maRect.IsInside( rPos ) ) + return VALUESET_ITEM_NONEITEM; + } + + ULONG nItemCount = mpItemList->Count(); + for ( ULONG i = 0; i < nItemCount; i++ ) + { + ValueSetItem* pItem = mpItemList->GetObject( i ); + if ( pItem->maRect.IsInside( rPos ) ) + return (USHORT)i; + } + + // Wenn Spacing gesetzt ist, wird der vorher selektierte + // Eintrag zurueckgegeben, wenn die Maus noch nicht das Fenster + // verlassen hat + if ( bMove && mnSpacing && mnHighItemId ) + { + Point aDefPos; + Rectangle aWinRect( aDefPos, maVirDev.GetOutputSizePixel() ); + 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 mpItemList->GetObject( nPos ); +} + +// ----------------------------------------------------------------------- + +ValueSetItem* ValueSet::ImplGetFirstItem() +{ + USHORT nItemCount = (USHORT)mpItemList->Count(); + USHORT i = 0; + + while ( i < nItemCount ) + { + ValueSetItem* pItem = mpItemList->GetObject( i ); + if ( pItem->meType != VALUESETITEM_SPACE ) + return pItem; + i++; + } + + return NULL; +} + +// ----------------------------------------------------------------------- + +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*, pTimer ) +{ + 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) ) + ImplHighlightItem( pItem->mnId ); + else + 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 ) + 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)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 ( 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: + 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 ); + break; + + case KEY_RIGHT: + 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: + do + { + if ( nCalcPos == VALUESET_ITEM_NONEITEM ) + { + if ( nLastItem+1 <= mnCols ) + nItemPos = mnCurCol; + else + { + nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+mnCurCol; + if ( nItemPos+mnCols <= nLastItem ) + nItemPos += mnCols; + } + } + else if ( nCalcPos >= mnCols ) + nItemPos = nCalcPos-mnCols; + else + { + if ( mpNoneItem ) + { + mnCurCol = nCalcPos%mnCols; + nItemPos = VALUESET_ITEM_NONEITEM; + } + else + { + if ( nLastItem+1 <= mnCols ) + nItemPos = nCalcPos; + else + { + nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+nCalcPos; + if ( nItemPos+mnCols <= nLastItem ) + nItemPos += mnCols; + } + } + } + nCalcPos = nItemPos; + } + while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE ); + break; + + case KEY_DOWN: + do + { + if ( nCalcPos == VALUESET_ITEM_NONEITEM ) + nItemPos = mnCurCol; + else if ( nCalcPos+mnCols <= nLastItem ) + nItemPos = nCalcPos+mnCols; + else + { + if ( mpNoneItem ) + { + mnCurCol = nCalcPos%mnCols; + nItemPos = VALUESET_ITEM_NONEITEM; + } + else + nItemPos = nCalcPos%mnCols; + } + nCalcPos = nItemPos; + } + while ( ImplGetItem( nItemPos )->meType == VALUESETITEM_SPACE ); + break; + + default: + Control::KeyInput( rKEvt ); + break; + } + + if ( nItemPos != VALUESET_ITEM_NOTFOUND ) + { + USHORT nItemId; + if ( nItemPos != VALUESET_ITEM_NONEITEM ) + nItemId = GetItemId( nItemPos ); + else + nItemId = 0; + if ( nItemId != mnSelItemId ) + { + SelectItem( nItemId ); + 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& rRect ) +{ + 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() +{ + ImplDrawSelect(); + Control::GetFocus(); +} + +// ----------------------------------------------------------------------- + +void ValueSet::LoseFocus() +{ + if ( mbNoSelection && mnSelItemId ) + ImplHideSelect( mnSelItemId ); + else + HideFocus(); + Control::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() ); + ULONG nItemCount = mpItemList->Count(); + for ( ULONG i = 0; i < nItemCount; i++ ) + { + ValueSetItem* pItem = mpItemList->GetObject( i ); + if ( pItem->maRect.IsInside( aPos ) ) + { + 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 ) + { + 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; + pItem->mnId = nItemId; + pItem->meType = VALUESETITEM_IMAGE; + pItem->maImage = rImage; + 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; + pItem->mnId = nItemId; + pItem->meType = VALUESETITEM_COLOR; + pItem->maColor = rColor; + 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; + pItem->mnId = nItemId; + pItem->meType = VALUESETITEM_IMAGE; + pItem->maImage = rImage; + pItem->maText = rText; + 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; + pItem->mnId = nItemId; + pItem->meType = VALUESETITEM_COLOR; + pItem->maColor = rColor; + pItem->maText = rText; + 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; + pItem->mnId = nItemId; + pItem->meType = VALUESETITEM_USERDRAW; + 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; + pItem->mnId = nItemId; + pItem->meType = VALUESETITEM_SPACE; + 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 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 ) +{ + ValueSetItem* pItem = mpItemList->First(); + while ( pItem ) + { + delete pItem; + pItem = mpItemList->Next(); + } + + pItem = rValueSet.mpItemList->First(); + while ( pItem ) + { + mpItemList->Insert( new ValueSetItem( *pItem ) ); + pItem = rValueSet.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() +{ + ValueSetItem* pItem = mpItemList->First(); + while ( pItem ) + { + delete pItem; + pItem = mpItemList->Next(); + } + mpItemList->Clear(); + + // 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)mpItemList->Count(); +} + +// ----------------------------------------------------------------------- + +USHORT ValueSet::GetItemPos( USHORT nItemId ) const +{ + ValueSetItem* pItem = mpItemList->First(); + while ( pItem ) + { + if ( pItem->mnId == nItemId ) + return (USHORT)mpItemList->GetCurPos(); + pItem = mpItemList->Next(); + } + + return VALUESET_ITEM_NOTFOUND; +} + +// ----------------------------------------------------------------------- + +USHORT ValueSet::GetItemId( USHORT nPos ) const +{ + ValueSetItem* pItem = mpItemList->GetObject( nPos ); + + if ( pItem ) + return pItem->mnId; + else + return 0; +} + +// ----------------------------------------------------------------------- + +USHORT ValueSet::GetItemId( const Point& rPos ) const +{ + ValueSetItem* pItem = mpItemList->First(); + while ( pItem ) + { + if ( pItem->maRect.IsInside( rPos ) ) + return pItem->mnId; + + pItem = mpItemList->Next(); + } + + return 0; +} + +// ----------------------------------------------------------------------- + +Rectangle ValueSet::GetItemRect( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != VALUESET_ITEM_NOTFOUND ) + return mpItemList->GetObject( nPos )->maRect; + else + return Rectangle(); +} + +// ----------------------------------------------------------------------- + +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 nPos; + + if ( nItemId ) + { + nPos = GetItemPos( nItemId ); + if ( nPos == VALUESET_ITEM_NOTFOUND ) + return; + if ( mpItemList->GetObject( nPos )->meType == VALUESETITEM_SPACE ) + return; + } + + if ( (mnSelItemId != nItemId) || mbNoSelection ) + { + USHORT nOldItem = mnSelItemId; + 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)(nPos / 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(); + } + } + } +} + +// ----------------------------------------------------------------------- + +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 ) + mpItemList->GetObject( nPos )->mnBits = nItemBits; +} + +// ----------------------------------------------------------------------- + +USHORT ValueSet::GetItemBits( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != VALUESET_ITEM_NOTFOUND ) + return 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 = 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 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 = 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 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 = 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 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 = mpItemList->GetObject( nPos ); + pItem->maText = rText; + + if ( !mbFormat && IsReallyVisible() && IsUpdateMode() ) + { + USHORT nTempId = mnSelItemId; + + if ( mbHighlight ) + nTempId = mnHighItemId; + + if ( nTempId == nItemId ) + ImplDrawItemText( pItem->maText ); + } +} + +// ----------------------------------------------------------------------- + +XubString ValueSet::GetItemText( USHORT nItemId ) const +{ + USHORT nPos = GetItemPos( nItemId ); + + if ( nPos != VALUESET_ITEM_NOTFOUND ) + return 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(); + } + +#ifdef MAC + Region aRegion( GetItemRect( nSelId ) ); +#else + Region aRegion; +#endif + + // 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)mpItemList->Count() / nCalcCols; + if ( 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 ) + { + long nNameOffset = (nStyle & WB_FLATVALUESET) ? NAME_OFFSET_FLAT : NAME_OFFSET; + aSize.Height() += nTxtHeight + (nNameOffset*3) + 2 + nSpace; + } + + 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)mpItemList->Count(); + } + else + { + // Im letzten viertel, dann wird ein Item spaeter eingefuegt + Rectangle aRect = 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; + } +} |