diff options
Diffstat (limited to 'sfx2/source/dialog')
64 files changed, 28882 insertions, 0 deletions
diff --git a/sfx2/source/dialog/about.cxx b/sfx2/source/dialog/about.cxx new file mode 100644 index 000000000000..fab379f9f215 --- /dev/null +++ b/sfx2/source/dialog/about.cxx @@ -0,0 +1,425 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// include --------------------------------------------------------------- +#include <aboutbmpnames.hxx> + +#ifndef _SV_APP_HXX +#include <vcl/svapp.hxx> +#endif +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#ifndef GCC +#endif + +#include <tools/stream.hxx> +#include <tools/urlobj.hxx> +#include <rtl/bootstrap.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/bootstrap.hxx> +#include <com/sun/star/uno/Any.h> +#include <unotools/configmgr.hxx> +#include <vcl/graph.hxx> +#include <svtools/filter.hxx> + +#include <sfx2/sfxuno.hxx> +#include "about.hxx" +#include "sfxresid.hxx" +#include <sfx2/sfxdefs.hxx> +#include <sfx2/app.hxx> + +#include "dialog.hrc" + +// defines --------------------------------------------------------------- + +#define SCROLL_OFFSET 1 +#define SPACE_OFFSET 5 +#define SCROLL_TIMER 30 + +#define WELCOME_URL DEFINE_CONST_UNICODE( "http://www.openoffice.org/welcome/credits.html" ) + +// class AboutDialog ----------------------------------------------------- +static void layoutText( FixedInfo &rText, long &nY, long nTextWidth, Size a6Size ) +{ + Point aTextPos = rText.GetPosPixel(); + aTextPos.X() = a6Size.Width() * 2; + aTextPos.Y() = nY; + rText.SetPosPixel( aTextPos ); + + Size aTxtSiz = rText.GetSizePixel(); + aTxtSiz.Width() = nTextWidth; + Size aCalcSize = rText.CalcMinimumSize( nTextWidth ); + aTxtSiz.Height() = aCalcSize.Height(); + rText.SetSizePixel( aTxtSiz ); + + nY += aTxtSiz.Height(); +} + +static bool impl_loadBitmap( + const rtl::OUString &rPath, const rtl::OUString &rBmpFileName, + Image &rLogo ) +{ + rtl::OUString uri( rPath ); + rtl::Bootstrap::expandMacros( uri ); + INetURLObject aObj( uri ); + aObj.insertName( rBmpFileName ); + SvFileStream aStrm( aObj.PathToFileName(), STREAM_STD_READ ); + if ( !aStrm.GetError() ) + { + // Use graphic class to also support more graphic formats (bmp,png,...) + Graphic aGraphic; + + GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); + pGF->ImportGraphic( aGraphic, String(), aStrm, GRFILTER_FORMAT_DONTKNOW ); + + // Default case, we load the intro bitmap from a seperate file + // (e.g. staroffice_intro.bmp or starsuite_intro.bmp) + BitmapEx aBmp = aGraphic.GetBitmapEx(); + rLogo = Image( aBmp ); + return true; + } + return false; +} + +/** loads the application logo as used in the about dialog and impress slideshow pause screen */ +Image SfxApplication::GetApplicationLogo() +{ + Image aAppLogo; + + rtl::OUString aAbouts( RTL_CONSTASCII_USTRINGPARAM( ABOUT_BITMAP_STRINGLIST ) ); + bool bLoaded = false; + sal_Int32 nIndex = 0; + do + { + bLoaded = impl_loadBitmap( + rtl::OUString::createFromAscii( "$BRAND_BASE_DIR/program" ), + aAbouts.getToken( 0, ',', nIndex ), aAppLogo ); + } + while ( !bLoaded && ( nIndex >= 0 ) ); + + // fallback to "about.bmp" + if ( !bLoaded ) + { + bLoaded = impl_loadBitmap( + rtl::OUString::createFromAscii( "$BRAND_BASE_DIR/program/edition" ), + rtl::OUString::createFromAscii( "about.png" ), aAppLogo ); + if ( !bLoaded ) + bLoaded = impl_loadBitmap( + rtl::OUString::createFromAscii( "$BRAND_BASE_DIR/program/edition" ), + rtl::OUString::createFromAscii( "about.bmp" ), aAppLogo ); + } + + if ( !bLoaded ) + { + bLoaded = impl_loadBitmap( + rtl::OUString::createFromAscii( "$BRAND_BASE_DIR/program" ), + rtl::OUString::createFromAscii( "about.png" ), aAppLogo ); + if ( !bLoaded ) + bLoaded = impl_loadBitmap( + rtl::OUString::createFromAscii( "$BRAND_BASE_DIR/program" ), + rtl::OUString::createFromAscii( "about.bmp" ), aAppLogo ); + } + + return aAppLogo; +} + +AboutDialog::AboutDialog( Window* pParent, const ResId& rId, const String& rVerStr ) : + + SfxModalDialog ( pParent, rId ), + + aOKButton ( this, ResId( ABOUT_BTN_OK, *rId.GetResMgr() ) ), + aVersionText ( this, ResId( ABOUT_FTXT_VERSION, *rId.GetResMgr() ) ), + aCopyrightText ( this, ResId( ABOUT_FTXT_COPYRIGHT, *rId.GetResMgr() ) ), + aBuildData ( this ), + aDeveloperAry ( ResId( ABOUT_STR_DEVELOPER_ARY, *rId.GetResMgr() ) ), + aDevVersionStr ( rVerStr ), + aAccelStr ( ResId( ABOUT_STR_ACCEL, *rId.GetResMgr() ) ), + aCopyrightTextStr( ResId( ABOUT_STR_COPYRIGHT, *rId.GetResMgr() ) ), + aTimer (), + nOff ( 0 ), + m_nDeltaWidth ( 0 ), + m_nPendingScrolls( 0 ), + bNormal ( TRUE ) +{ + rtl::OUString sProduct; + utl::ConfigManager::GetDirectConfigProperty(utl::ConfigManager::PRODUCTNAME) >>= sProduct; + + // load image from module path + aAppLogo = SfxApplication::GetApplicationLogo(); + + // Transparenter Font + Font aFont = GetFont(); + aFont.SetTransparent( TRUE ); + SetFont( aFont ); + + // if necessary more info + String sVersion = aVersionText.GetText(); + sVersion.SearchAndReplaceAscii( "$(VER)", Application::GetDisplayName() ); + sVersion += '\n'; + sVersion += rVerStr; + aVersionText.SetText( sVersion ); + + // Initialisierung fuer Aufruf Entwickler + if ( aAccelStr.Len() && ByteString(U2S(aAccelStr)).IsAlphaAscii() ) + { + Accelerator *pAccel = 0, *pPrevAccel = 0, *pFirstAccel = 0; + aAccelStr.ToUpperAscii(); + + for ( USHORT i = 0; i < aAccelStr.Len(); ++i ) + { + pPrevAccel = pAccel; + pAccel = new Accelerator; + aAccelList.Insert( pAccel, LIST_APPEND ); + USHORT nKey = aAccelStr.GetChar(i) - 'A' + KEY_A; + pAccel->InsertItem( 1, KeyCode( nKey, KEY_MOD1 ) ); + if ( i > 0 ) + pPrevAccel->SetAccel( 1, pAccel ); + if ( i == 0 ) + pFirstAccel = pAccel; + } + pAccel->SetSelectHdl( LINK( this, AboutDialog, AccelSelectHdl ) ); + GetpApp()->InsertAccel( pFirstAccel ); + } + + // set for background and text the correct system color + const StyleSettings& rSettings = GetSettings().GetStyleSettings(); + Color aWhiteCol( rSettings.GetWindowColor() ); + Wallpaper aWall( aWhiteCol ); + SetBackground( aWall ); + Font aNewFont( aCopyrightText.GetFont() ); + aNewFont.SetTransparent( TRUE ); + + aVersionText.SetFont( aNewFont ); + aCopyrightText.SetFont( aNewFont ); + + aVersionText.SetBackground(); + aCopyrightText.SetBackground(); + + Color aTextColor( rSettings.GetWindowTextColor() ); + aVersionText.SetControlForeground( aTextColor ); + aCopyrightText.SetControlForeground( aTextColor ); + aBuildData.SetBackground( aWall ); + + Font aSmallFont = rSettings.GetInfoFont(); + Size aSmaller = aNewFont.GetSize(); + aSmaller.Width() = (long) (aSmaller.Width() * 0.75); + aSmaller.Height() = (long) (aSmaller.Height() * 0.75); + aNewFont.SetSize( aSmaller ); + aBuildData.SetFont( aNewFont ); + aBuildData.SetBackground( aWall ); +#ifdef BUILD_VER_STRING + String aBuildString( DEFINE_CONST_UNICODE( BUILD_VER_STRING ) ); +#else + String aBuildString; +#endif + aBuildData.SetText( aBuildString ); + aBuildData.Show(); + + // determine size and position of the dialog & elements + Size aAppLogoSiz = aAppLogo.GetSizePixel(); + Size aOutSiz = GetOutputSizePixel(); + aOutSiz.Width() = aAppLogoSiz.Width(); + + Size a6Size = aVersionText.LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); + long nY = aAppLogoSiz.Height() + ( a6Size.Height() * 2 ); + long nDlgMargin = a6Size.Width() * 4 ; + long nCtrlMargin = a6Size.Height() * 2; + long nTextWidth = aOutSiz.Width() - nDlgMargin; + + aCopyrightText.SetText( aCopyrightTextStr ); + + layoutText( aVersionText, nY, nTextWidth, a6Size ); + nY += nCtrlMargin; + + // OK-Button-Position (at the bottom and centered) + Size aOKSiz = aOKButton.GetSizePixel(); + Point aOKPnt = aOKButton.GetPosPixel(); + + // Multiline edit with Copyright-Text + Point aCopyPnt = aCopyrightText.GetPosPixel(); + Size aCopySize = aCopyrightText.GetSizePixel(); + aCopySize.Width() = nTextWidth; + aCopySize.Height() = aOutSiz.Height() - nY - ( aOKSiz.Height() * 2 ) - nCtrlMargin; + + aCopyPnt.X() = ( aOutSiz.Width() - aCopySize.Width() ) / 2; + aCopyPnt.Y() = nY; + aCopyrightText.SetPosSizePixel( aCopyPnt, aCopySize ); + + nY += aCopySize.Height() + nCtrlMargin; + aOKPnt.X() = ( aOutSiz.Width() - aOKSiz.Width() ) / 2; + aOKPnt.Y() = nY; + aOKButton.SetPosPixel( aOKPnt ); + + // Change the width of the dialog + SetOutputSizePixel( aOutSiz ); + + FreeResource(); + + // explizite Help-Id + SetHelpId( SID_ABOUT ); +} + +// ----------------------------------------------------------------------- + +AboutDialog::~AboutDialog() +{ + // L"oschen des Entwickleraufrufs + if ( aAccelList.Count() ) + { + GetpApp()->RemoveAccel( aAccelList.First() ); + Accelerator* pAccel = aAccelList.Last(); + + while ( pAccel ) + { + delete pAccel; + pAccel = aAccelList.Prev(); + } + } +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( AboutDialog, TimerHdl, Timer *, pTimer ) +{ + (void)pTimer; //unused + ++m_nPendingScrolls; + Invalidate( INVALIDATE_NOERASE | INVALIDATE_NOCHILDREN ); + return 0; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( AboutDialog, AccelSelectHdl, Accelerator *, pAccelerator ) +{ +#ifdef YURI_DARIO + aCopyrightText.SetHelpText( DEFINE_CONST_UNICODE("Conoscere qualcuno ovunque egli sia, con cui comprendersi nonostante le distanze\n" + "e le differenze, puo' trasformare la terra in un giardino. baci Valeria") ); +#endif + + (void)pAccelerator; //unused + // init Timer + aTimer.SetTimeoutHdl( LINK( this, AboutDialog, TimerHdl ) ); + + // init scroll mode + nOff = GetOutputSizePixel().Height(); + MapMode aMapMode( MAP_PIXEL ); + SetMapMode( aMapMode ); + bNormal = FALSE; + + // start scroll Timer + aTimer.SetTimeout( SCROLL_TIMER ); + aTimer.Start(); + return 0; +} + +// ----------------------------------------------------------------------- + +BOOL AboutDialog::Close() +{ + // stop Timer and finish the dialog + aTimer.Stop(); + EndDialog( RET_OK ); + return( FALSE ); +} + +// ----------------------------------------------------------------------- + +void AboutDialog::Paint( const Rectangle& rRect ) +{ + SetClipRegion( rRect ); + + if ( bNormal ) // not in scroll mode + { + Point aPos( m_nDeltaWidth / 2, 0 ); + DrawImage( aPos, aAppLogo ); + return; + } + + // scroll the content + const int nDeltaY = -SCROLL_OFFSET * m_nPendingScrolls; + if( !nDeltaY ) + return; + nOff += nDeltaY; + Scroll( 0, nDeltaY, SCROLL_NOERASE ); + m_nPendingScrolls = 0; + + // draw the credits text + const Font aOrigFont = GetFont(); + const int nFullWidth = GetOutputSizePixel().Width(); + + int nY = nOff; + const int nDevCnt = static_cast<int>( aDeveloperAry.Count() ); + for( int i = 0; i < nDevCnt; ++i ) + { + if( nY >= rRect.Bottom() ) + break; + + int nPos2 = nY + GetTextHeight() + 3; + if( nPos2 >= rRect.Top() + nDeltaY ) + { + const String aStr = aDeveloperAry.GetString(i); + const long nVal = aDeveloperAry.GetValue(i); + + if ( nVal ) + { + // emphasize the headers + Font aFont = aOrigFont; + aFont.SetWeight( (FontWeight)nVal ); + SetFont( aFont ); + nPos2 = nY + GetTextHeight() + 3; + } + + // clear text background + Rectangle aEraseRect( Point(0,nY), Size( nFullWidth, nPos2-nY)); + Erase( aEraseRect ); + + // draw centered text + const long nTextWidth = GetTextWidth( aStr ); + long nX = (nFullWidth - 5 - nTextWidth) / 2; + if( nX < 0 ) + nX = SPACE_OFFSET; + const Point aPnt( nX, nY ); + DrawText( aPnt, aStr ); + + // restore the font if needed + if( nVal ) + SetFont( aOrigFont ); + } + nY = nPos2; + } + + // close dialog if the whole text has been scrolled + if ( nY <= 0 ) + { + bNormal = TRUE; + Close(); + } +} diff --git a/sfx2/source/dialog/alienwarn.cxx b/sfx2/source/dialog/alienwarn.cxx new file mode 100644 index 000000000000..6fd765dcb616 --- /dev/null +++ b/sfx2/source/dialog/alienwarn.cxx @@ -0,0 +1,177 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include "alienwarn.hxx" +#include "sfxresid.hxx" +#include <sfx2/sfxuno.hxx> + +#include "alienwarn.hrc" +#include "dialog.hrc" +#include <vcl/msgbox.hxx> +#include <unotools/saveopt.hxx> + +// class SfxAlienWarningDialog ------------------------------------------- + +SfxAlienWarningDialog::SfxAlienWarningDialog( Window* pParent, const String& _rFormatName ) : + + SfxModalDialog( pParent, SfxResId( RID_DLG_ALIEN_WARNING ) ), + + m_aKeepCurrentBtn ( this, SfxResId( PB_NO ) ), + m_aSaveODFBtn ( this, SfxResId( PB_YES ) ), + m_aMoreInfoBtn ( this, SfxResId( PB_MOREINFO ) ), + m_aOptionLine ( this, SfxResId( FL_OPTION ) ), + m_aWarningOnBox ( this, SfxResId( CB_WARNING_OFF ) ), + m_aQueryImage ( this, SfxResId( FI_QUERY ) ), + m_aInfoText ( this, SfxResId( FT_INFOTEXT ) ) + +{ + FreeResource(); + + // set questionmark image + m_aQueryImage.SetImage( QueryBox::GetStandardImage() ); + + // replace formatname + String sInfoText = m_aInfoText.GetText(); + sInfoText.SearchAndReplaceAll( DEFINE_CONST_UNICODE("%FORMATNAME"), _rFormatName ); + m_aInfoText.SetText( sInfoText ); + + // load value of "warning on" checkbox from save options + m_aWarningOnBox.Check( SvtSaveOptions().IsWarnAlienFormat() == sal_True ); + + // set focus to "Keep Current Format" button + m_aKeepCurrentBtn.GrabFocus(); + + // pb: #i43989# we have no online help for this dialog at the moment + // -> hide the "more info" button + //m_aMoreInfoBtn.Hide(); + + // calculate and set the size of the dialog and its controls + InitSize(); +} + +// ----------------------------------------------------------------------- + +SfxAlienWarningDialog::~SfxAlienWarningDialog() +{ + // save value of "warning off" checkbox, if necessary + SvtSaveOptions aSaveOpt; + sal_Bool bChecked = m_aWarningOnBox.IsChecked(); + if ( aSaveOpt.IsWarnAlienFormat() != bChecked ) + aSaveOpt.SetWarnAlienFormat( bChecked ); +} + +// ----------------------------------------------------------------------- + +void SfxAlienWarningDialog::InitSize() +{ + // if the button text is too wide, then broaden the button + long nTxtW = m_aMoreInfoBtn.GetCtrlTextWidth( m_aMoreInfoBtn.GetText() ); + long nCtrlW = m_aMoreInfoBtn.GetSizePixel().Width(); + if ( nTxtW >= nCtrlW ) + { + long nDelta = nTxtW - nCtrlW; + nDelta += IMPL_EXTRA_BUTTON_WIDTH; + Point aNextPoint = m_aKeepCurrentBtn.GetPosPixel(); + aNextPoint.X() += m_aKeepCurrentBtn.GetSizePixel().Width(); + Point aNewPoint = m_aMoreInfoBtn.GetPosPixel(); + aNewPoint.X() -= nDelta; + if ( aNextPoint.X() >= aNewPoint.X() ) + { + long nSpace = aNextPoint.X() - aNewPoint.X(); + nSpace += 2; + nDelta -= nSpace; + aNewPoint.X() += nSpace; + } + Size aNewSize = m_aMoreInfoBtn.GetSizePixel(); + aNewSize.Width() += nDelta; + m_aMoreInfoBtn.SetPosSizePixel( aNewPoint, aNewSize ); + } + + // text of checkbox to wide -> add new line + nTxtW = m_aWarningOnBox.GetCtrlTextWidth( m_aWarningOnBox.GetText() ) + IMPL_EXTRA_BUTTON_WIDTH; + nCtrlW = m_aWarningOnBox.GetSizePixel().Width(); + if ( nTxtW >= nCtrlW ) + { + long nTextHeight = m_aWarningOnBox.GetTextHeight(); + Size aNewSize = m_aWarningOnBox.GetSizePixel(); + aNewSize.Height() += nTextHeight; + m_aWarningOnBox.SetSizePixel( aNewSize ); + aNewSize = GetSizePixel(); + aNewSize.Height() += nTextHeight; + SetSizePixel( aNewSize ); + } + + // align the size of the information text control (FixedText) to its content + Size aMinSize = m_aInfoText.CalcMinimumSize( m_aInfoText.GetSizePixel().Width() ); + long nTxtH = aMinSize.Height(); + long nCtrlH = m_aInfoText.GetSizePixel().Height(); + long nDelta = ( nCtrlH - nTxtH ); + Size aNewSize = m_aInfoText.GetSizePixel(); + aNewSize.Height() -= nDelta; + m_aInfoText.SetSizePixel( aNewSize ); + + // new position for the succeeding windows + Window* pWins[] = + { + &m_aSaveODFBtn, &m_aKeepCurrentBtn, &m_aMoreInfoBtn, &m_aOptionLine, &m_aWarningOnBox + }; + Window** pCurrent = pWins; + for ( sal_uInt32 i = 0; i < sizeof( pWins ) / sizeof( pWins[ 0 ] ); ++i, ++pCurrent ) + { + Point aNewPos = (*pCurrent)->GetPosPixel(); + aNewPos.Y() -= nDelta; + (*pCurrent)->SetPosPixel( aNewPos ); + } + + // new size of the dialog + aNewSize = GetSizePixel(); + aNewSize.Height() -= nDelta; + SetSizePixel( aNewSize ); + + // recalculate the size and position of the buttons + m_aMoreInfoBtn.Hide(); + nTxtW = m_aKeepCurrentBtn.GetCtrlTextWidth( m_aKeepCurrentBtn.GetText() ); + long nTemp = m_aSaveODFBtn.GetCtrlTextWidth( m_aSaveODFBtn.GetText() ); + if ( nTemp > nTxtW ) + nTxtW = nTemp; + nTxtW += IMPL_EXTRA_BUTTON_WIDTH; + Size a3Size = LogicToPixel( Size( 3, 3 ), MAP_APPFONT ); + Point aPos = m_aKeepCurrentBtn.GetPosPixel(); + aPos.X() = ( aNewSize.Width() - (2*nTxtW) - a3Size.Width() ) / 2; + long nDefX = m_aWarningOnBox.GetPosPixel().X(); + if ( nDefX < aPos.X() ) + aPos.X() = nDefX; + aNewSize = m_aKeepCurrentBtn.GetSizePixel(); + aNewSize.Width() = nTxtW; + m_aKeepCurrentBtn.SetPosSizePixel( aPos, aNewSize ); + aPos.X() += nTxtW + a3Size.Width(); + m_aSaveODFBtn.SetPosSizePixel( aPos, aNewSize ); +} + diff --git a/sfx2/source/dialog/alienwarn.hrc b/sfx2/source/dialog/alienwarn.hrc new file mode 100644 index 000000000000..e3a23dc57836 --- /dev/null +++ b/sfx2/source/dialog/alienwarn.hrc @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SFX_ALIENWARN_HRC +#define _SFX_ALIENWARN_HRC + +#include <svtools/controldims.hrc> + +// dialog ids + +#define FI_QUERY 10 +#define FT_INFOTEXT 11 +#define PB_YES 12 +#define PB_NO 13 +#define PB_MOREINFO 14 +#define FL_OPTION 15 +#define CB_WARNING_OFF 16 + +// --------- general metrics --------- + +#define SYMBOL_EDGE 20 +#define DIALOG_WIDTH 220 +#define INFO_TEXT_LINES 11 + +#define AW_COL_1 (RSC_SP_DLG_INNERBORDER_LEFT) +#define AW_COL_2 (AW_COL_1+SYMBOL_EDGE+RSC_SP_CTRL_DESC_X) +#define AW_COL_3 (AW_COL_2+RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_CTRL_DESC_X) +#define AW_COL_4 (DIALOG_WIDTH-RSC_SP_DLG_INNERBORDER_RIGHT-RSC_CD_PUSHBUTTON_WIDTH) + +#define AW_ROW_1 (RSC_SP_DLG_INNERBORDER_TOP) +#define AW_ROW_2 (AW_ROW_1+INFO_TEXT_LINES*RSC_CD_FIXEDTEXT_HEIGHT+RSC_SP_CTRL_Y) +#define AW_ROW_3 (AW_ROW_2+RSC_CD_PUSHBUTTON_HEIGHT+RSC_SP_CTRL_DESC_Y) +#define AW_ROW_4 (AW_ROW_3+RSC_CD_FIXEDLINE_HEIGHT+RSC_SP_CTRL_DESC_Y) + +#define DIALOG_HEIGHT (AW_ROW_4+RSC_CD_CHECKBOX_HEIGHT+RSC_SP_DLG_INNERBORDER_BOTTOM) + +#endif + diff --git a/sfx2/source/dialog/alienwarn.src b/sfx2/source/dialog/alienwarn.src new file mode 100644 index 000000000000..7aa6f3230778 --- /dev/null +++ b/sfx2/source/dialog/alienwarn.src @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "alienwarn.hrc" +#include "dialog.hrc" +#include "helpid.hrc" + +ModalDialog RID_DLG_ALIEN_WARNING +{ + HelpId = HID_WARNING_ALIENFORMAT; + Size = MAP_APPFONT( DIALOG_WIDTH, DIALOG_HEIGHT ); + OutputSize = TRUE; + Closeable = FALSE; + Moveable = TRUE; + SVLook = TRUE; + + Text = "%PRODUCTNAME %PRODUCTVERSION %PRODUCTEXTENSION"; + + FixedImage FI_QUERY + { + Pos = MAP_APPFONT( AW_COL_1, AW_ROW_1 ); + Size = MAP_APPFONT( SYMBOL_EDGE, SYMBOL_EDGE ); + }; + FixedText FT_INFOTEXT + { + Pos = MAP_APPFONT( AW_COL_2, AW_ROW_1 ); + Size = MAP_APPFONT( DIALOG_WIDTH-AW_COL_2-RSC_SP_DLG_INNERBORDER_RIGHT, INFO_TEXT_LINES*RSC_CD_FIXEDTEXT_HEIGHT ); + NoLabel = TRUE; + Wordbreak = TRUE; + Text [ en-US-old ] = "This document may contain formatting or content that cannot be saved in the %FORMATNAME file format. Do you want to save the document in this format anyway?\n\n- Click 'Yes' to save in %FORMATNAME file format.\n- Click 'No' to use the latest OpenDocument file format and be sure all formatting and content is saved correctly."; + Text [ en-US ] = "This document may contain formatting or content that cannot be saved in the %FORMATNAME file format. Do you want to save the document in this format anyway?\n\nUse the latest ODF file format and be sure all formatting and content is saved correctly."; + }; + OKButton PB_NO + { + Pos = MAP_APPFONT( AW_COL_2, AW_ROW_2 ); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + DefButton = TRUE ; + Text [ en-US ] = "~Keep Current Format"; + }; + CancelButton PB_YES + { + Pos = MAP_APPFONT( AW_COL_3, AW_ROW_2 ); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + Text [ en-US ] = "~Save in ODF Format"; + }; + HelpButton PB_MOREINFO + { + Pos = MAP_APPFONT( AW_COL_4, AW_ROW_2 ); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + Hide = TRUE ; + Text [ en-US ] = "~More Information..."; + }; + FixedLine FL_OPTION + { + Pos = MAP_APPFONT( 0, AW_ROW_3 ); + Size = MAP_APPFONT( DIALOG_WIDTH, RSC_CD_FIXEDLINE_HEIGHT ); + }; + CheckBox CB_WARNING_OFF + { + Pos = MAP_APPFONT( AW_COL_2, AW_ROW_4 ); + Size = MAP_APPFONT( DIALOG_WIDTH-AW_COL_2-RSC_SP_DLG_INNERBORDER_RIGHT, RSC_CD_CHECKBOX_HEIGHT ); + WordBreak = TRUE ; + Text [ en-US ] = "~Ask when not saving in ODF format"; + }; +}; + + diff --git a/sfx2/source/dialog/basedlgs.cxx b/sfx2/source/dialog/basedlgs.cxx new file mode 100644 index 000000000000..2ea5ef5fe4b1 --- /dev/null +++ b/sfx2/source/dialog/basedlgs.cxx @@ -0,0 +1,1082 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// include --------------------------------------------------------------- + +#include <stdlib.h> +#include <vcl/fixed.hxx> +#include <vcl/help.hxx> +#include <vcl/msgbox.hxx> +#include <svl/eitem.hxx> +#include <unotools/viewoptions.hxx> +#include <svtools/fixedhyper.hxx> +#include <svtools/controldims.hrc> + +#include <sfx2/basedlgs.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/tabdlg.hxx> +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/childwin.hxx> +#include <sfx2/viewsh.hxx> +#include "sfxhelp.hxx" +#include "workwin.hxx" +#include "sfxresid.hxx" +#include "dialog.hrc" + +using namespace ::com::sun::star::uno; +using namespace ::rtl; + +#define USERITEM_NAME OUString::createFromAscii( "UserItem" ) + +class SfxModelessDialog_Impl : public SfxListener +{ +public: + ByteString aWinState; + SfxChildWindow* pMgr; + BOOL bConstructed; + void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + + Timer aMoveTimer; +}; + +void SfxModelessDialog_Impl::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.IsA(TYPE(SfxSimpleHint)) ) + { + switch( ( (SfxSimpleHint&) rHint ).GetId() ) + { + case SFX_HINT_DYING: + pMgr->Destroy(); + break; + } + } +} + +class SfxFloatingWindow_Impl : public SfxListener +{ +public: + ByteString aWinState; + SfxChildWindow* pMgr; + BOOL bConstructed; + Timer aMoveTimer; + + void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); +}; + +void SfxFloatingWindow_Impl::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.IsA(TYPE(SfxSimpleHint)) ) + { + switch( ( (SfxSimpleHint&) rHint ).GetId() ) + { + case SFX_HINT_DYING: + pMgr->Destroy(); + break; + } + } +} + +// class SfxModalDefParentHelper ----------------------------------------- + +SfxModalDefParentHelper::SfxModalDefParentHelper( Window *pWindow) +{ + pOld = Application::GetDefDialogParent(); + Application::SetDefDialogParent( pWindow ); +} + +// ----------------------------------------------------------------------- + +SfxModalDefParentHelper::~SfxModalDefParentHelper() +{ + Application::SetDefDialogParent( pOld ); +} + +// ----------------------------------------------------------------------- + +void SfxModalDialog::SetDialogData_Impl() +{ + // save settings (position and user data) + SvtViewOptions aDlgOpt( E_DIALOG, String::CreateFromInt32( nUniqId ) ); + aDlgOpt.SetWindowState( + OUString::createFromAscii( GetWindowState( WINDOWSTATE_MASK_POS ).GetBuffer() ) ); + if ( aExtraData.Len() ) + aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aExtraData ) ) ); +} + +// ----------------------------------------------------------------------- + +void SfxModalDialog::GetDialogData_Impl() + +/* [Beschreibung] + + Hilfsfunktion; liest die Dialogposition aus der Ini-Datei + und setzt diese am "ubergebenen Window. +*/ + +{ + SvtViewOptions aDlgOpt( E_DIALOG, String::CreateFromInt32( nUniqId ) ); + if ( aDlgOpt.Exists() ) + { + // load settings + SetWindowState( ByteString( aDlgOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US ) ); + Any aUserItem = aDlgOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + aExtraData = String( aTemp ); + } +} + +// ----------------------------------------------------------------------- + +void SfxModalDialog::init() +{ + GetDialogData_Impl(); + aTimer.SetTimeout( 100 ); + aTimer.SetTimeoutHdl( LINK( this, SfxModalDialog, TimerHdl_Impl ) ); + aTimer.Start(); +} + +// ----------------------------------------------------------------------- + +SfxModalDialog::SfxModalDialog(Window* pParent, const ResId &rResId ) + +/* [Beschreibung] + + Konstruktor der allgemeinen Basisklasse f"ur modale Dialoge; + ResId wird als ID im ini-file verwendet. + Die dort gespeicherte Position wird gesetzt. +*/ + +: ModalDialog(pParent, rResId), + nUniqId(rResId.GetId()), + pInputSet(0), + pOutputSet(0) +{ + init(); +} + +// ----------------------------------------------------------------------- + +SfxModalDialog::SfxModalDialog(Window* pParent, + sal_uInt32 nUniqueId, + WinBits nWinStyle) : +/* [Beschreibung] + + Konstruktor der allgemeinen Basisklasse f"ur modale Dialoge; + ID f"ur das ini-file wird explizit "ubergeben. + Die dort gespeicherte Position wird gesetzt. +*/ + + ModalDialog(pParent, nWinStyle), + nUniqId(nUniqueId), + pInputSet(0), + pOutputSet(0) +{ + init(); +} + +// ----------------------------------------------------------------------- + +SfxModalDialog::~SfxModalDialog() + +/* [Beschreibung] + + Dtor; schreibt Dialogposition in das ini-file +*/ + +{ +/* + SfxHelpPI *pHelpPI = SFX_APP()->GetHelpPI(); + if ( pHelpPI ) + pHelpPI->ResetTopic(); +*/ + SetDialogData_Impl(); + aTimer.Stop(); + delete pOutputSet; +} + +void SfxModalDialog::CreateOutputItemSet( SfxItemPool& rPool ) +{ + DBG_ASSERT( !pOutputSet, "Double creation of OutputSet!" ); + if (!pOutputSet) + pOutputSet = new SfxAllItemSet( rPool ); +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxModalDialog, TimerHdl_Impl, Timer*, EMPTYARG ) +{ +/* + SfxHelpPI *pHelpPI = SFX_APP()->GetHelpPI(); + if ( pHelpPI ) + pHelpPI->LoadTopic( GetHelpId() ); + */ + return 0L; +} + +void SfxModalDialog::CreateOutputItemSet( const SfxItemSet& rSet ) +{ + DBG_ASSERT( !pOutputSet, "Double creation of OutputSet!" ); + if (!pOutputSet) + { + pOutputSet = new SfxItemSet( rSet ); + pOutputSet->ClearItem(); + } +} + +//------------------------------------------------------------------------- +void SfxModelessDialog::StateChanged( StateChangedType nStateChange ) +{ + if ( nStateChange == STATE_CHANGE_INITSHOW ) + { + if ( pImp->aWinState.Len() ) + { + SetWindowState( pImp->aWinState ); + } + else + { + Point aPos = GetPosPixel(); + if ( !aPos.X() ) + { + aSize = GetSizePixel(); + + Size aParentSize = GetParent()->GetOutputSizePixel(); + Size aDlgSize = GetSizePixel(); + aPos.X() += ( aParentSize.Width() - aDlgSize.Width() ) / 2; + aPos.Y() += ( aParentSize.Height() - aDlgSize.Height() ) / 2; + + Point aPoint; + Rectangle aRect = GetDesktopRectPixel(); + aPoint.X() = aRect.Right() - aDlgSize.Width(); + aPoint.Y() = aRect.Bottom() - aDlgSize.Height(); + + aPoint = OutputToScreenPixel( aPoint ); + + if ( aPos.X() > aPoint.X() ) + aPos.X() = aPoint.X() ; + if ( aPos.Y() > aPoint.Y() ) + aPos.Y() = aPoint.Y(); + + if ( aPos.X() < 0 ) aPos.X() = 0; + if ( aPos.Y() < 0 ) aPos.Y() = 0; + + SetPosPixel( aPos ); + } + } + + pImp->bConstructed = TRUE; + } + + ModelessDialog::StateChanged( nStateChange ); +} + +void SfxModelessDialog::Initialize(SfxChildWinInfo *pInfo) + +/* [Beschreibung] + + Initialisierung der Klasse SfxModelessDialog "uber ein SfxChildWinInfo. + Die Initialisierung erfolgt erst in einem 2.Schritt + nach dem ctor und sollte vom ctor der abgeleiteten Klasse + oder von dem des SfxChildWindows aufgerufen werden. +*/ + +{ + pImp->aWinState = pInfo->aWinState; +} + +void SfxModelessDialog::Resize() + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse FloatingWindow merkt sich ggf. eine + ver"anderte Gr"o\se. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + auch SfxFloatingWindow::Resize() gerufen werden. +*/ + +{ + ModelessDialog::Resize(); + if ( pImp->bConstructed && pImp->pMgr ) + { + // start timer for saving window status information + pImp->aMoveTimer.Start(); + } +} + +void SfxModelessDialog::Move() +{ + ModelessDialog::Move(); + if ( pImp->bConstructed && pImp->pMgr && IsReallyVisible() ) + { + // start timer for saving window status information + pImp->aMoveTimer.Start(); + } +} + +/* + Implements a timer event that is triggered by a move or resize of the window + This will save config information to Views.xcu with a small delay +*/ +IMPL_LINK( SfxModelessDialog, TimerHdl, Timer*, EMPTYARG) +{ + pImp->aMoveTimer.Stop(); + if ( pImp->bConstructed && pImp->pMgr ) + { + if ( !IsRollUp() ) + aSize = GetSizePixel(); + ULONG nMask = WINDOWSTATE_MASK_POS | WINDOWSTATE_MASK_STATE; + if ( GetStyle() & WB_SIZEABLE ) + nMask |= ( WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT ); + pImp->aWinState = GetWindowState( nMask ); + GetBindings().GetWorkWindow_Impl()->ConfigChild_Impl( SFX_CHILDWIN_DOCKINGWINDOW, SFX_ALIGNDOCKINGWINDOW, pImp->pMgr->GetType() ); + } + return 0; +} + +// ----------------------------------------------------------------------- + +SfxModelessDialog::SfxModelessDialog( SfxBindings *pBindinx, + SfxChildWindow *pCW, + Window* pParent, WinBits nWinBits ) : + ModelessDialog (pParent, nWinBits), + pBindings(pBindinx), + pImp( new SfxModelessDialog_Impl ) +{ + pImp->pMgr = pCW; + pImp->bConstructed = FALSE; + sal_uInt32 nId = GetHelpId(); + SetHelpId(0); + SetUniqueId( nId ); + if ( pBindinx ) + pImp->StartListening( *pBindinx ); + pImp->aMoveTimer.SetTimeout(50); + pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxModelessDialog,TimerHdl)); +} + +// ----------------------------------------------------------------------- + +SfxModelessDialog::SfxModelessDialog( SfxBindings *pBindinx, + SfxChildWindow *pCW, Window *pParent, + const ResId& rResId ) : + ModelessDialog(pParent, rResId), + pBindings(pBindinx), + pImp( new SfxModelessDialog_Impl ) +{ + pImp->pMgr = pCW; + pImp->bConstructed = FALSE; + sal_uInt32 nId = GetHelpId(); + SetHelpId(0); + SetUniqueId( nId ); + if ( pBindinx ) + pImp->StartListening( *pBindinx ); + pImp->aMoveTimer.SetTimeout(50); + pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxModelessDialog,TimerHdl)); +} + +// ----------------------------------------------------------------------- + +long SfxModelessDialog::Notify( NotifyEvent& rEvt ) + +/* [Beschreibung] + + Wenn ein ModelessDialog aktiviert wird, wird sein ViewFrame aktiviert. + Notwendig ist das bei PlugInFrames. +*/ + +{ + if ( rEvt.GetType() == EVENT_GETFOCUS ) + { + pBindings->SetActiveFrame( pImp->pMgr->GetFrame() ); + pImp->pMgr->Activate_Impl(); + Window* pWindow = rEvt.GetWindow(); + ULONG nHelpId = 0; + while ( !nHelpId && pWindow ) + { + nHelpId = pWindow->GetHelpId(); + pWindow = pWindow->GetParent(); + } + + if ( nHelpId ) + SfxHelp::OpenHelpAgent( &pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame(), nHelpId ); + } + else if ( rEvt.GetType() == EVENT_LOSEFOCUS && !HasChildPathFocus() ) + { + pBindings->SetActiveFrame( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > () ); + pImp->pMgr->Deactivate_Impl(); + } + else if( rEvt.GetType() == EVENT_KEYINPUT ) + { + // KeyInput zuerst f"ur Dialogfunktionen zulassen ( TAB etc. ) + if ( !ModelessDialog::Notify( rEvt ) && SfxViewShell::Current() ) + // dann auch global g"ultige Acceleratoren verwenden + return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() ); + return sal_True; + } + + return ModelessDialog::Notify( rEvt ); +} + +// ----------------------------------------------------------------------- + +SfxModelessDialog::~SfxModelessDialog() + +/* [Beschreibung] + + Dtor +*/ + +{ + if ( pImp->pMgr->GetFrame().is() && pImp->pMgr->GetFrame() == pBindings->GetActiveFrame() ) + pBindings->SetActiveFrame( NULL ); + delete pImp; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxModelessDialog::Close() + +/* [Beschreibung] + + Das Fenster wird geschlossen, indem das ChildWindow durch Ausf"uhren des + ChildWindow-Slots zerst"ort wird. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + danach SfxModelessDialogWindow::Close() gerufen werden, wenn nicht das + Close() mit "return sal_False" abgebrochen wird. + +*/ + +{ + // Execute mit Parametern, da Toggle von einigen ChildWindows ignoriert + // werden kann + SfxBoolItem aValue( pImp->pMgr->GetType(), sal_False); + pBindings->GetDispatcher_Impl()->Execute( + pImp->pMgr->GetType(), + SFX_CALLMODE_RECORD|SFX_CALLMODE_SYNCHRON, &aValue, 0L ); + return sal_True; +} + +//------------------------------------------------------------------------- + +void SfxModelessDialog::FillInfo(SfxChildWinInfo& rInfo) const + +/* [Beschreibung] + + F"ullt ein SfxChildWinInfo mit f"ur SfxModelessDialof spezifischen Daten, + damit sie in die INI-Datei geschrieben werden koennen. + Es wird angenommen, da\s rInfo alle anderen evt. relevanten Daten in + der ChildWindow-Klasse erh"alt. + ModelessDialogs haben keine spezifischen Informationen, so dass die + Basisimplementierung nichts tut und daher nicht gerufen werden mu\s. +*/ + +{ + rInfo.aSize = aSize; + if ( IsRollUp() ) + rInfo.nFlags |= SFX_CHILDWIN_ZOOMIN; +} + +// ----------------------------------------------------------------------- + +long SfxFloatingWindow::Notify( NotifyEvent& rEvt ) + +/* [Beschreibung] + + Wenn ein ModelessDialog aktiviert wird, wird sein ViewFrame aktiviert. + Notwendig ist das bei PlugInFrames. +*/ + +{ + if ( rEvt.GetType() == EVENT_GETFOCUS ) + { + pBindings->SetActiveFrame( pImp->pMgr->GetFrame() ); + pImp->pMgr->Activate_Impl(); + Window* pWindow = rEvt.GetWindow(); + ULONG nHelpId = 0; + while ( !nHelpId && pWindow ) + { + nHelpId = pWindow->GetHelpId(); + pWindow = pWindow->GetParent(); + } + + if ( nHelpId ) + SfxHelp::OpenHelpAgent( &pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame(), nHelpId ); + } + else if ( rEvt.GetType() == EVENT_LOSEFOCUS ) + { + if ( !HasChildPathFocus() ) + { + pBindings->SetActiveFrame( NULL ); + pImp->pMgr->Deactivate_Impl(); + } + } + else if( rEvt.GetType() == EVENT_KEYINPUT ) + { + // KeyInput zuerst f"ur Dialogfunktionen zulassen + if ( !FloatingWindow::Notify( rEvt ) && SfxViewShell::Current() ) + // dann auch global g"ultige Acceleratoren verwenden + return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() ); + return sal_True; + } + + return FloatingWindow::Notify( rEvt ); +} + +// ----------------------------------------------------------------------- + +SfxFloatingWindow::SfxFloatingWindow( SfxBindings *pBindinx, + SfxChildWindow *pCW, + Window* pParent, WinBits nWinBits) : + FloatingWindow (pParent, nWinBits), + pBindings(pBindinx), + pImp( new SfxFloatingWindow_Impl ) +{ + pImp->pMgr = pCW; + pImp->bConstructed = FALSE; + sal_uInt32 nId = GetHelpId(); + SetHelpId(0); + SetUniqueId( nId ); + if ( pBindinx ) + pImp->StartListening( *pBindinx ); + pImp->aMoveTimer.SetTimeout(50); + pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxFloatingWindow,TimerHdl)); +} + +// ----------------------------------------------------------------------- + +SfxFloatingWindow::SfxFloatingWindow( SfxBindings *pBindinx, + SfxChildWindow *pCW, + Window* pParent, + const ResId& rResId) : + FloatingWindow(pParent, rResId), + pBindings(pBindinx), + pImp( new SfxFloatingWindow_Impl ) +{ + pImp->pMgr = pCW; + pImp->bConstructed = FALSE; + sal_uInt32 nId = GetHelpId(); + SetHelpId(0); + SetUniqueId( nId ); + if ( pBindinx ) + pImp->StartListening( *pBindinx ); + pImp->aMoveTimer.SetTimeout(50); + pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxFloatingWindow,TimerHdl)); +} + +//------------------------------------------------------------------------- + +sal_Bool SfxFloatingWindow::Close() + +/* [Beschreibung] + + Das Fenster wird geschlossen, indem das ChildWindow durch Ausf"uhren des + ChildWindow-Slots zerst"ort wird. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + danach SfxFloatingWindow::Close() gerufen werden, wenn nicht das Close() + mit "return sal_False" abgebrochen wird. + +*/ + +{ + // Execute mit Parametern, da Toggle von einigen ChildWindows ignoriert + // werden kann + SfxBoolItem aValue( pImp->pMgr->GetType(), sal_False); + pBindings->GetDispatcher_Impl()->Execute( + pImp->pMgr->GetType(), + SFX_CALLMODE_RECORD|SFX_CALLMODE_SYNCHRON, &aValue, 0L ); + return sal_True; +} + +// ----------------------------------------------------------------------- + +SfxFloatingWindow::~SfxFloatingWindow() + +/* [Beschreibung] + + Dtor +*/ + +{ + if ( pImp->pMgr->GetFrame() == pBindings->GetActiveFrame() ) + pBindings->SetActiveFrame( NULL ); + delete pImp; +} + +//------------------------------------------------------------------------- + +void SfxFloatingWindow::Resize() + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse FloatingWindow merkt sich ggf. eine + ver"anderte Gr"o\se. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + auch SfxFloatingWindow::Resize() gerufen werden. +*/ + +{ + FloatingWindow::Resize(); + if ( pImp->bConstructed && pImp->pMgr ) + { + // start timer for saving window status information + pImp->aMoveTimer.Start(); + } +} + +void SfxFloatingWindow::Move() +{ + FloatingWindow::Move(); + if ( pImp->bConstructed && pImp->pMgr ) + { + // start timer for saving window status information + pImp->aMoveTimer.Start(); + } +} + +/* + Implements a timer event that is triggered by a move or resize of the window + This will save config information to Views.xcu with a small delay +*/ +IMPL_LINK( SfxFloatingWindow, TimerHdl, Timer*, EMPTYARG) +{ + pImp->aMoveTimer.Stop(); + if ( pImp->bConstructed && pImp->pMgr ) + { + if ( !IsRollUp() ) + aSize = GetSizePixel(); + ULONG nMask = WINDOWSTATE_MASK_POS | WINDOWSTATE_MASK_STATE; + if ( GetStyle() & WB_SIZEABLE ) + nMask |= ( WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT ); + pImp->aWinState = GetWindowState( nMask ); + GetBindings().GetWorkWindow_Impl()->ConfigChild_Impl( SFX_CHILDWIN_DOCKINGWINDOW, SFX_ALIGNDOCKINGWINDOW, pImp->pMgr->GetType() ); + } + return 0; +} + +//------------------------------------------------------------------------- +void SfxFloatingWindow::StateChanged( StateChangedType nStateChange ) +{ + if ( nStateChange == STATE_CHANGE_INITSHOW ) + { + // FloatingWindows are not centered by default + if ( pImp->aWinState.Len() ) + SetWindowState( pImp->aWinState ); + pImp->bConstructed = TRUE; + } + + FloatingWindow::StateChanged( nStateChange ); +} + + +void SfxFloatingWindow::Initialize(SfxChildWinInfo *pInfo) + +/* [Beschreibung] + + Initialisierung der Klasse SfxFloatingWindow "uber ein SfxChildWinInfo. + Die Initialisierung erfolgt erst in einem 2.Schritt + nach dem ctor und sollte vom ctor der abgeleiteten Klasse + oder von dem des SfxChildWindows aufgerufen werden. +*/ +{ + pImp->aWinState = pInfo->aWinState; +} + +//------------------------------------------------------------------------- + +void SfxFloatingWindow::FillInfo(SfxChildWinInfo& rInfo) const + +/* [Beschreibung] + + F"ullt ein SfxChildWinInfo mit f"ur SfxFloatingWindow spezifischen Daten, + damit sie in die INI-Datei geschrieben werden koennen. + Es wird angenommen, da\s rInfo alle anderen evt. relevanten Daten in + der ChildWindow-Klasse erh"alt. + Eingetragen werden hier gemerkte Gr"o\se und das ZoomIn-Flag. + Wird diese Methode "uberschrieben, mu\s zuerst die Basisimplementierung + gerufen werden. +*/ + +{ + rInfo.aSize = aSize; + if ( IsRollUp() ) + rInfo.nFlags |= SFX_CHILDWIN_ZOOMIN; +} + +// SfxSingleTabDialog ---------------------------------------------------- + +IMPL_LINK( SfxSingleTabDialog, OKHdl_Impl, Button *, EMPTYARG ) + +/* [Beschreibung] + + Ok_Handler; f"ur die gesetzte Page wird FillItemSet() gerufen. +*/ + +{ + if ( !GetInputItemSet() ) + { + // TabPage without ItemSet + EndDialog( RET_OK ); + return 1; + } + + if ( !GetOutputItemSet() ) + { + CreateOutputItemSet( *GetInputItemSet() ); + } + sal_Bool bModified = sal_False; + + if ( pImpl->m_pSfxPage->HasExchangeSupport() ) + { + int nRet = pImpl->m_pSfxPage->DeactivatePage( GetOutputSetImpl() ); + if ( nRet != SfxTabPage::LEAVE_PAGE ) + return 0; + else + bModified = ( GetOutputItemSet()->Count() > 0 ); + } + else + bModified = pImpl->m_pSfxPage->FillItemSet( *GetOutputSetImpl() ); + + if ( bModified ) + { + // auch noch schnell User-Daten im IniManager abspeichern + pImpl->m_pSfxPage->FillUserData(); + String sData( pImpl->m_pSfxPage->GetUserData() ); + SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( GetUniqId() ) ); + aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( sData ) ) ); + EndDialog( RET_OK ); + } + else + EndDialog( RET_CANCEL ); + return 0; +} + +// ----------------------------------------------------------------------- + +SfxSingleTabDialog::SfxSingleTabDialog +( + Window *pParent, + const SfxItemSet& rSet, + sal_uInt16 nUniqueId +) : + +/* [Beschreibung] + + Konstruktor der allgemeinen Basisklasse f"ur SingleTab-Dialoge; + ID f"ur das ini-file wird "ubergeben. +*/ + + SfxModalDialog( pParent, nUniqueId, WinBits( WB_STDMODAL | WB_3DLOOK ) ), + + pOKBtn ( 0 ), + pCancelBtn ( 0 ), + pHelpBtn ( 0 ), + pImpl ( new SingleTabDlgImpl ) +{ + DBG_WARNING( "please use the ctor with ViewFrame" ); + SetInputSet( &rSet ); +} + +// ----------------------------------------------------------------------- + +SfxSingleTabDialog::SfxSingleTabDialog +( + Window* pParent, + sal_uInt16 nUniqueId, + const SfxItemSet* pInSet +) + +/* [Beschreibung] + + Konstruktor der allgemeinen Basisklasse f"ur SingleTab-Dialoge; + ID f"ur das ini-file wird "ubergeben. + Sollte nicht mehr benutzt werden. + */ + +: SfxModalDialog( pParent, nUniqueId, WinBits( WB_STDMODAL | WB_3DLOOK ) ), + + pOKBtn ( 0 ), + pCancelBtn ( 0 ), + pHelpBtn ( 0 ), + pImpl ( new SingleTabDlgImpl ) +{ + DBG_WARNING( "bitte den Ctor mit ViewFrame verwenden" ); + SetInputSet( pInSet ); +} + +// ----------------------------------------------------------------------- + +SfxSingleTabDialog::SfxSingleTabDialog +( + Window* pParent, + sal_uInt16 nUniqueId, + const String& rInfoURL +) + +/* [Beschreibung] + + Konstruktor der allgemeinen Basisklasse f"ur SingleTab-Dialoge; + ID f"ur das ini-file wird "ubergeben. + */ + +: SfxModalDialog( pParent, nUniqueId, WinBits( WB_STDMODAL | WB_3DLOOK ) ), + + pOKBtn ( NULL ), + pCancelBtn ( NULL ), + pHelpBtn ( NULL ), + pImpl ( new SingleTabDlgImpl ) +{ + pImpl->m_sInfoURL = rInfoURL; +} + +// ----------------------------------------------------------------------- + +SfxSingleTabDialog::~SfxSingleTabDialog() +{ + delete pOKBtn; + delete pCancelBtn; + delete pHelpBtn; + delete pImpl->m_pTabPage; + delete pImpl->m_pSfxPage; + delete pImpl->m_pLine; + delete pImpl->m_pInfoImage; + delete pImpl; +} + +// ----------------------------------------------------------------------- + +void SfxSingleTabDialog::SetPage( TabPage* pNewPage ) +{ + if ( !pImpl->m_pLine ) + pImpl->m_pLine = new FixedLine( this ); + + if ( !pOKBtn ) + { + pOKBtn = new OKButton( this, WB_DEFBUTTON ); + pOKBtn->SetClickHdl( LINK( this, SfxSingleTabDialog, OKHdl_Impl ) ); + } + + if ( pImpl->m_sInfoURL.Len() > 0 && !pImpl->m_pInfoImage ) + { + pImpl->m_pInfoImage = new ::svt::FixedHyperlinkImage( this ); + Image aInfoImage = Image( SfxResId( IMG_INFO ) ); + Size aImageSize = aInfoImage.GetSizePixel(); + aImageSize.Width() += 4; + aImageSize.Height() += 4; + pImpl->m_pInfoImage->SetSizePixel( aImageSize ); + pImpl->m_pInfoImage->SetImage( aInfoImage ); + pImpl->m_pInfoImage->SetURL( pImpl->m_sInfoURL ); + pImpl->m_pInfoImage->SetClickHdl( pImpl->m_aInfoLink ); + } + + if ( pImpl->m_pTabPage ) + delete pImpl->m_pTabPage; + if ( pImpl->m_pSfxPage ) + delete pImpl->m_pSfxPage; + pImpl->m_pTabPage = pNewPage; + + if ( pImpl->m_pTabPage ) + { + // Gr"ossen und Positionen anpassen + pImpl->m_pTabPage->SetPosPixel( Point() ); + Size aOutSz( pImpl->m_pTabPage->GetSizePixel() ); + Size aOffSz = LogicToPixel( Size( RSC_SP_CTRL_X, RSC_SP_CTRL_Y ), MAP_APPFONT ); + Size aFLSz = LogicToPixel( Size( aOutSz.Width(), RSC_CD_FIXEDLINE_HEIGHT ) ); + Size aBtnSz = LogicToPixel( Size( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ), MAP_APPFONT ); + + Point aPnt( 0, aOutSz.Height() ); + pImpl->m_pLine->SetPosSizePixel( aPnt, aFLSz ); + aPnt.X() = aOutSz.Width() - aOffSz.Width() - aBtnSz.Width(); + aPnt.Y() += aFLSz.Height() + ( aOffSz.Height() / 2 ); + pOKBtn->SetPosSizePixel( aPnt, aBtnSz ); + + if ( pImpl->m_pInfoImage ) + { + aPnt.X() = aOffSz.Width(); + long nDelta = ( pImpl->m_pInfoImage->GetSizePixel().Height() - aBtnSz.Height() ) / 2; + aPnt.Y() -= nDelta; + pImpl->m_pInfoImage->SetPosPixel( aPnt ); + pImpl->m_pInfoImage->Show(); + } + + aOutSz.Height() += aFLSz.Height() + ( aOffSz.Height() / 2 ) + aBtnSz.Height() + aOffSz.Height(); + SetOutputSizePixel( aOutSz ); + + pImpl->m_pLine->Show(); + pOKBtn->Show(); + pImpl->m_pTabPage->Show(); + + // Text der TabPage in den Dialog setzen + SetText( pImpl->m_pTabPage->GetText() ); + + // Dialog bekommt HelpId der TabPage + SetHelpId( pImpl->m_pTabPage->GetHelpId() ); + SetUniqueId( pImpl->m_pTabPage->GetUniqueId() ); + } +} + +// ----------------------------------------------------------------------- + +void SfxSingleTabDialog::SetTabPage( SfxTabPage* pTabPage, + GetTabPageRanges pRangesFunc ) +/* [Beschreibung] + + Setzen einer (neuen) TabPage; eine bereits vorhandene Page + wird gel"oscht. + Die "ubergebene Page wird durch Aufruf von Reset() mit dem + initial "ubergebenen Itemset initialisiert. +*/ + +{ + if ( !pOKBtn ) + { + pOKBtn = new OKButton( this, WB_DEFBUTTON ); + pOKBtn->SetClickHdl( LINK( this, SfxSingleTabDialog, OKHdl_Impl ) ); + } + if ( !pCancelBtn ) + pCancelBtn = new CancelButton( this ); + if ( !pHelpBtn ) + pHelpBtn = new HelpButton( this ); + + if ( pImpl->m_pTabPage ) + delete pImpl->m_pTabPage; + if ( pImpl->m_pSfxPage ) + delete pImpl->m_pSfxPage; + pImpl->m_pSfxPage = pTabPage; + fnGetRanges = pRangesFunc; + + if ( pImpl->m_pSfxPage ) + { + // erstmal die User-Daten besorgen, dann erst Reset() + SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( GetUniqId() ) ); + String sUserData; + Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + sUserData = String( aTemp ); + pImpl->m_pSfxPage->SetUserData( sUserData ); + pImpl->m_pSfxPage->Reset( *GetInputItemSet() ); + pImpl->m_pSfxPage->Show(); + + // Gr"ossen und Positionen anpassen + pImpl->m_pSfxPage->SetPosPixel( Point() ); + Size aOutSz( pImpl->m_pSfxPage->GetSizePixel() ); + Size aBtnSiz = LogicToPixel( Size( 50, 14 ), MAP_APPFONT ); + Point aPnt( aOutSz.Width(), LogicToPixel( Point( 0, 6 ), MAP_APPFONT ).Y() ); + aOutSz.Width() += aBtnSiz.Width() + LogicToPixel( Size( 6, 0 ), MAP_APPFONT ).Width(); + SetOutputSizePixel( aOutSz ); + pOKBtn->SetPosSizePixel( aPnt, aBtnSiz ); + pOKBtn->Show(); + aPnt.Y() = LogicToPixel( Point( 0, 23 ), MAP_APPFONT ).Y(); + pCancelBtn->SetPosSizePixel( aPnt, aBtnSiz ); + pCancelBtn->Show(); + aPnt.Y() = LogicToPixel( Point( 0, 43 ), MAP_APPFONT ).Y(); + pHelpBtn->SetPosSizePixel( aPnt, aBtnSiz ); + + if ( Help::IsContextHelpEnabled() ) + pHelpBtn->Show(); + + // Text der TabPage in den Dialog setzen + SetText( pImpl->m_pSfxPage->GetText() ); + + // Dialog bekommt HelpId der TabPage + SetHelpId( pImpl->m_pSfxPage->GetHelpId() ); + SetUniqueId( pImpl->m_pSfxPage->GetUniqueId() ); + } +} + +// ----------------------------------------------------------------------- + +void SfxSingleTabDialog::SetInfoLink( const Link& rLink ) +{ + pImpl->m_aInfoLink = rLink; +} + +//-------------------------------------------------------------------- +// Vergleichsfunktion fuer qsort + +#ifdef WNT +int __cdecl BaseDlgsCmpUS_Impl( const void* p1, const void* p2 ) +#else +#if defined(OS2) && defined(ICC) +int _Optlink BaseDlgsCmpUS_Impl( const void* p1, const void* p2 ) +#else +extern "C" int BaseDlgsCmpUS_Impl( const void* p1, const void* p2 ) +#endif +#endif +{ + return *(sal_uInt16*)p1 - *(sal_uInt16*)p2; +} + +// ----------------------------------------------------------------------- + +/* + Bildet das Set "uber die Ranges der Page. Die Page muss die statische + Methode f"ur das Erfragen ihrer Ranges bei SetTabPage angegeben haben, + liefert also ihr Set onDemand. + */ +const sal_uInt16* SfxSingleTabDialog::GetInputRanges( const SfxItemPool& rPool ) +{ + if ( GetInputItemSet() ) + { + DBG_ERROR( "Set bereits vorhanden!" ); + return GetInputItemSet()->GetRanges(); + } + + if ( pRanges ) + return pRanges; + SvUShorts aUS(16, 16); + + if ( fnGetRanges) + { + const sal_uInt16 *pTmpRanges = (fnGetRanges)(); + const sal_uInt16 *pIter = pTmpRanges; + sal_uInt16 nLen; + for ( nLen = 0; *pIter; ++nLen, ++pIter ) + ; + aUS.Insert( pTmpRanges, nLen, aUS.Count() ); + } + + //! Doppelte Ids entfernen? + sal_uInt16 nCount = aUS.Count(); + + for ( sal_uInt16 i = 0; i < nCount; ++i ) + aUS[i] = rPool.GetWhich( aUS[i]) ; + + // sortieren + if ( aUS.Count() > 1 ) + qsort( (void*)aUS.GetData(), aUS.Count(), sizeof(sal_uInt16), BaseDlgsCmpUS_Impl ); + + pRanges = new sal_uInt16[aUS.Count() + 1]; + memcpy( pRanges, aUS.GetData(), sizeof(sal_uInt16) * aUS.Count() ); + pRanges[aUS.Count()] = 0; + return pRanges; +} + diff --git a/sfx2/source/dialog/dialog.hrc b/sfx2/source/dialog/dialog.hrc new file mode 100644 index 000000000000..7f03bf416431 --- /dev/null +++ b/sfx2/source/dialog/dialog.hrc @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SFX_DIALOG_HRC +#define _SFX_DIALOG_HRC + +#include <sfx2/sfx.hrc> + +// defines --------------------------------------------------------------- + +#define ID_NEW 1 +#define ID_EDIT 2 +#define ID_DELETE 3 + +#define RC_DIALOG_BEGIN RID_SFX_DIALOG_START + +#define RID_DLG_ALIEN_WARNING ( RC_DIALOG_BEGIN + 0) +#define STR_RESET ( RC_DIALOG_BEGIN + 0) + +#define DLG_PASSWD ( RC_DIALOG_BEGIN + 8) +#define STR_TABPAGE_MANAGESTYLES ( RC_DIALOG_BEGIN + 12) +#define MSG_TABPAGE_INVALIDNAME ( RC_DIALOG_BEGIN + 13) +#define MSG_TABPAGE_INVALIDSTYLE ( RC_DIALOG_BEGIN + 14) +#define DLG_NEW_STYLE_BY_EXAMPLE ( RC_DIALOG_BEGIN + 15) +#define MSG_POOL_STYLE_NAME ( RC_DIALOG_BEGIN + 16) +#define MSG_TABPAGE_INVALIDPARENT ( RC_DIALOG_BEGIN + 18) + +#define STR_DELETE_STYLE ( RC_DIALOG_BEGIN + 18) +#define STR_DELETE_STYLE_USED ( RC_DIALOG_BEGIN + 20) + +#define MN_CONTEXT_TEMPLDLG ( RC_DIALOG_BEGIN + 46) + +#define DLG_VERSIONS ( RC_DIALOG_BEGIN + 69 ) +#define DLG_COMMENTS ( RC_DIALOG_BEGIN + 70 ) + +#define MSG_ERROR_WRONG_CONFIRM ( RC_DIALOG_BEGIN + 76 ) + +#define STR_APPLY ( RC_DIALOG_BEGIN + 87 ) + +#define TP_COMMONPRINTOPTIONS ( RC_DIALOG_BEGIN + 90 ) +#define RID_WARN_PRINTTRANSPARENCY ( RC_DIALOG_BEGIN + 91 ) + +#define RID_ERRBOX_MAIL_CONFIG ( RC_DIALOG_BEGIN + 92 ) + +#define IMG_LST_STYLE_DESIGNER_HC ( RC_DIALOG_BEGIN + 99 ) + +// 100-106 in tbxcust.hrc +#define STR_MACRO_LOSS ( RC_DIALOG_BEGIN + 107 ) +#define STR_CANCEL_RECORDING ( RC_DIALOG_BEGIN + 108 ) + +#define RID_DLG_SEARCH ( RC_DIALOG_BEGIN + 109 ) + +#define STR_PDF_EXPORT_SEND ( RC_DIALOG_BEGIN + 120 ) +#define IMG_INFO ( RC_DIALOG_BEGIN + 122 ) +#define RID_EDIT_DURATIONS ( RC_DIALOG_BEGIN + 123 ) +#define SFX_PB_EDIT ( RC_DIALOG_BEGIN + 124 ) + +#endif // #ifndef _SFX_DIALOG_HRC + +// eof ------------------------------------------------------------------------ + diff --git a/sfx2/source/dialog/dialog.src b/sfx2/source/dialog/dialog.src new file mode 100644 index 000000000000..c39425510ae2 --- /dev/null +++ b/sfx2/source/dialog/dialog.src @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + // include --------------------------------------------------------------- +#include <sfx2/sfx.hrc> +#include "dialog.hrc" +#include "helpid.hrc" +#include "sfxlocal.hrc" + +String STR_RESET +{ + Text [ en-US ] = "~Reset" ; +}; +String STR_APPLY +{ + Text [ en-US ] = "Apply"; +}; +String STR_TABPAGE_MANAGESTYLES +{ + Text [ en-US ] = "Organizer" ; +}; +InfoBox MSG_TABPAGE_INVALIDNAME +{ + BUTTONS = WB_OK ; + DEFBUTTON = WB_DEF_OK ; + Message [ en-US ] = "This name is already in use." ; +}; +InfoBox MSG_TABPAGE_INVALIDSTYLE +{ + BUTTONS = WB_OK ; + DEFBUTTON = WB_DEF_OK ; + Message [ en-US ] = "This Style does not exist." ; +}; +InfoBox MSG_TABPAGE_INVALIDPARENT +{ + BUTTONS = WB_OK ; + DEFBUTTON = WB_DEF_OK ; + Message [ en-US ] = "This Style cannot be used as a base Style,\nbecause it would result in a recursive reference." ; +}; +InfoBox MSG_POOL_STYLE_NAME +{ + Message [ en-US ] = "Name already exists as a default Style.\nPlease choose another name." ; +}; +String STR_DELETE_STYLE +{ + Text [ en-US ] = "Do you really want to delete Style $1?" ; +}; +String STR_DELETE_STYLE_USED +{ + Text [ en-US ] = "You are deleting an applied Style!\n" ; +}; +Menu MN_CONTEXT_TEMPLDLG +{ + ItemList = + { + MenuItem + { + Identifier = ID_NEW ; + Text [ en-US ] = "New..." ; + HelpId = HID_STYLIST_NEW ; + }; + MenuItem + { + Identifier = ID_EDIT ; + Text [ en-US ] = "Modify..." ; + HelpId = HID_STYLIST_EDIT ; + }; + MenuItem + { + Identifier = ID_DELETE ; + Text [ en-US ] = "Delete..." ; + HelpId = HID_STYLIST_DELETE ; + }; + }; +}; + + //------------------------------------------------------------------------ +String SID_NAVIGATOR +{ + Text [ en-US ] = "Navigator"; +}; +String SID_TASKPANE +{ + Text [ en-US ] = "Task Pane"; +}; + +ErrorBox MSG_ERROR_WRONG_CONFIRM +{ + BUTTONS = WB_OK ; + DEFBUTTON = WB_DEF_OK ; + Message [ en-US ] = "Faulty password confirmation"; +}; + +String STR_PDF_EXPORT_SEND +{ + Text [ en-US ] = "Send" ; +}; + +Image IMG_INFO +{ + ImageBitmap = Bitmap + { + File = "info.png" ; + }; +}; + +// ******************************************************************* EOF + diff --git a/sfx2/source/dialog/dinfdlg.cxx b/sfx2/source/dialog/dinfdlg.cxx new file mode 100644 index 000000000000..3d848d4d5648 --- /dev/null +++ b/sfx2/source/dialog/dinfdlg.cxx @@ -0,0 +1,2466 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <tools/urlobj.hxx> +#include <vcl/msgbox.hxx> +#include <svl/eitem.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/filedlghelper.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/cmdoptions.hxx> +#include <comphelper/processfactory.hxx> +#include <svl/urihelper.hxx> +#include <unotools/useroptions.hxx> +#include <svtools/imagemgr.hxx> +#include <tools/datetime.hxx> + +#include <memory> + +#include <comphelper/string.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/security/DocumentSignatureInformation.hpp> +#include <com/sun/star/security/XDocumentDigitalSignatures.hpp> +#include <unotools/localedatawrapper.hxx> +#include <unotools/syslocale.hxx> +#include <rtl/math.hxx> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/XPropertyContainer.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/Duration.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> + +#include <vcl/timer.hxx> +#include "sfx2/dinfdlg.hxx" +#include "sfx2/securitypage.hxx" +#include "sfxresid.hxx" +#include "dinfedt.hxx" +#include <sfx2/frame.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/request.hxx> +//#include "exptypes.hxx" +#include "helper.hxx" +#include <sfx2/objsh.hxx> +#include <sfx2/docfile.hxx> +#include <comphelper/storagehelper.hxx> + +#include <sfx2/sfx.hrc> +#include "dinfdlg.hrc" +#include "sfxlocal.hrc" +#include <dialog.hrc> +#include <vcl/help.hxx> + +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::uno; + + +struct CustomProperty +{ + ::rtl::OUString m_sName; + com::sun::star::uno::Any m_aValue; + + CustomProperty( const ::rtl::OUString& sName, + const com::sun::star::uno::Any& rValue ) : + m_sName( sName ), m_aValue( rValue ) {} + + inline bool operator==( const CustomProperty& rProp ) + { return m_sName.equals( rProp.m_sName ) && m_aValue == rProp.m_aValue; } +}; + + +static +bool operator==(const util::DateTime &i_rLeft, const util::DateTime &i_rRight) +{ + return i_rLeft.Year == i_rRight.Year + && i_rLeft.Month == i_rRight.Month + && i_rLeft.Day == i_rRight.Day + && i_rLeft.Hours == i_rRight.Hours + && i_rLeft.Minutes == i_rRight.Minutes + && i_rLeft.Seconds == i_rRight.Seconds + && i_rLeft.HundredthSeconds == i_rRight.HundredthSeconds; +} + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1_AUTOFACTORY(SfxDocumentInfoItem, SfxStringItem); + +const USHORT HI_NAME = 1; +const USHORT HI_TYPE = 2; +const USHORT HI_VALUE = 3; +const USHORT HI_ACTION = 4; + +static const char DOCUMENT_SIGNATURE_MENU_CMD[] = "Signature"; + +//------------------------------------------------------------------------ +String CreateSizeText( ULONG nSize, BOOL bExtraBytes = TRUE, BOOL bSmartExtraBytes = FALSE ); +String CreateSizeText( ULONG nSize, BOOL bExtraBytes, BOOL bSmartExtraBytes ) +{ + String aUnitStr = ' '; + aUnitStr += String( SfxResId(STR_BYTES) ); + ULONG nSize1 = nSize; + ULONG nSize2 = nSize1; + ULONG nMega = 1024 * 1024; + ULONG nGiga = nMega * 1024; + double fSize = nSize; + int nDec = 0; + BOOL bGB = FALSE; + + if ( nSize1 >= 10000 && nSize1 < nMega ) + { + nSize1 /= 1024; + aUnitStr = ' '; + aUnitStr += String( SfxResId(STR_KB) ); + fSize /= 1024; + nDec = 0; + } + else if ( nSize1 >= nMega && nSize1 < nGiga ) + { + nSize1 /= nMega; + aUnitStr = ' '; + aUnitStr += String( SfxResId(STR_MB) ); + fSize /= nMega; + nDec = 2; + } + else if ( nSize1 >= nGiga ) + { + nSize1 /= nGiga; + aUnitStr = ' '; + aUnitStr += String( SfxResId(STR_GB) ); + bGB = TRUE; + fSize /= nGiga; + nDec = 3; + } + const LocaleDataWrapper& rLocaleWrapper = SvtSysLocale().GetLocaleData(); + String aSizeStr( rLocaleWrapper.getNum( nSize1, 0 ) ); + aSizeStr += aUnitStr; + if ( bExtraBytes && ( nSize1 < nSize2 ) ) + { + aSizeStr = ::rtl::math::doubleToUString( fSize, + rtl_math_StringFormat_F, nDec, + rLocaleWrapper.getNumDecimalSep().GetChar(0) ); + aSizeStr += aUnitStr; + + aSizeStr += DEFINE_CONST_UNICODE(" ("); + aSizeStr += rLocaleWrapper.getNum( nSize2, 0 ); + aSizeStr += ' '; + aSizeStr += String( SfxResId(STR_BYTES) ); + aSizeStr += ')'; + } + else if ( bGB && bSmartExtraBytes ) + { + nSize1 = nSize / nMega; + aSizeStr = DEFINE_CONST_UNICODE(" ("); + aSizeStr += rLocaleWrapper.getNum( nSize1, 0 ); + aSizeStr += aUnitStr; + aSizeStr += ')'; + } + return aSizeStr; +} + +String ConvertDateTime_Impl( const String& rName, + const util::DateTime& uDT, const LocaleDataWrapper& rWrapper ) +{ + Date aD(uDT.Day, uDT.Month, uDT.Year); + Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds); + const String pDelim ( DEFINE_CONST_UNICODE( ", ")); + String aStr( rWrapper.getDate( aD ) ); + aStr += pDelim; + aStr += rWrapper.getTime( aT, TRUE, FALSE ); + String aAuthor = rName; + aAuthor.EraseLeadingChars(); + if ( aAuthor.Len() ) + { + aStr += pDelim; + aStr += aAuthor; + } + return aStr; +} + +//------------------------------------------------------------------------ + +SfxDocumentInfoItem::SfxDocumentInfoItem() + : SfxStringItem() + , m_AutoloadDelay(0) + , m_AutoloadURL() + , m_isAutoloadEnabled(sal_False) + , m_DefaultTarget() + , m_TemplateName() + , m_Author() + , m_CreationDate() + , m_ModifiedBy() + , m_ModificationDate() + , m_PrintedBy() + , m_PrintDate() + , m_EditingCycles(0) + , m_EditingDuration(0) + , m_Description() + , m_Keywords() + , m_Subject() + , m_Title() + , m_bHasTemplate( sal_True ) + , m_bDeleteUserData( sal_False ) + , m_bUseUserData( sal_True ) +{ +} + +//------------------------------------------------------------------------ + +SfxDocumentInfoItem::SfxDocumentInfoItem( const String& rFile, + const uno::Reference<document::XDocumentProperties>& i_xDocProps, + sal_Bool bIs ) + : SfxStringItem( SID_DOCINFO, rFile ) + , m_AutoloadDelay( i_xDocProps->getAutoloadSecs() ) + , m_AutoloadURL( i_xDocProps->getAutoloadURL() ) + , m_isAutoloadEnabled( (m_AutoloadDelay > 0) || m_AutoloadURL.getLength() ) + , m_DefaultTarget( i_xDocProps->getDefaultTarget() ) + , m_TemplateName( i_xDocProps->getTemplateName() ) + , m_Author( i_xDocProps->getAuthor() ) + , m_CreationDate( i_xDocProps->getCreationDate() ) + , m_ModifiedBy( i_xDocProps->getModifiedBy() ) + , m_ModificationDate( i_xDocProps->getModificationDate() ) + , m_PrintedBy( i_xDocProps->getPrintedBy() ) + , m_PrintDate( i_xDocProps->getPrintDate() ) + , m_EditingCycles( i_xDocProps->getEditingCycles() ) + , m_EditingDuration( i_xDocProps->getEditingDuration() ) + , m_Description( i_xDocProps->getDescription() ) + , m_Keywords( ::comphelper::string::convertCommaSeparated( + i_xDocProps->getKeywords()) ) + , m_Subject( i_xDocProps->getSubject() ) + , m_Title( i_xDocProps->getTitle() ) + , m_bHasTemplate( sal_True ) + , m_bDeleteUserData( sal_False ) + , m_bUseUserData( bIs ) +{ + try + { + Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties(); + if ( xContainer.is() ) + { + Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY ); + const Sequence< beans::Property > lProps = xSet->getPropertySetInfo()->getProperties(); + const beans::Property* pProps = lProps.getConstArray(); + sal_Int32 nCount = lProps.getLength(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + // "fix" property? => not a custom property => ignore it! + if (!(pProps[i].Attributes & + ::com::sun::star::beans::PropertyAttribute::REMOVABLE)) + { + DBG_ASSERT(false, "non-removable user-defined property?"); + continue; + } + + uno::Any aValue = xSet->getPropertyValue(pProps[i].Name); + CustomProperty* pProp = new CustomProperty( pProps[i].Name, aValue ); + m_aCustomProperties.push_back( pProp ); + } + } + } + catch ( Exception& ) {} +} + +//------------------------------------------------------------------------ + +SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem& rItem ) + : SfxStringItem( rItem ) + , m_AutoloadDelay( rItem.getAutoloadDelay() ) + , m_AutoloadURL( rItem.getAutoloadURL() ) + , m_isAutoloadEnabled( rItem.isAutoloadEnabled() ) + , m_DefaultTarget( rItem.getDefaultTarget() ) + , m_TemplateName( rItem.getTemplateName() ) + , m_Author( rItem.getAuthor() ) + , m_CreationDate( rItem.getCreationDate() ) + , m_ModifiedBy( rItem.getModifiedBy() ) + , m_ModificationDate( rItem.getModificationDate() ) + , m_PrintedBy( rItem.getPrintedBy() ) + , m_PrintDate( rItem.getPrintDate() ) + , m_EditingCycles( rItem.getEditingCycles() ) + , m_EditingDuration( rItem.getEditingDuration() ) + , m_Description( rItem.getDescription() ) + , m_Keywords( rItem.getKeywords() ) + , m_Subject( rItem.getSubject() ) + , m_Title( rItem.getTitle() ) + , m_bHasTemplate( rItem.m_bHasTemplate ) + , m_bDeleteUserData( rItem.m_bDeleteUserData ) + , m_bUseUserData( rItem.m_bUseUserData ) +{ + for ( sal_uInt32 i = 0; i < rItem.m_aCustomProperties.size(); i++ ) + { + CustomProperty* pProp = new CustomProperty( rItem.m_aCustomProperties[i]->m_sName, + rItem.m_aCustomProperties[i]->m_aValue ); + m_aCustomProperties.push_back( pProp ); + } +} + +//------------------------------------------------------------------------ + +SfxDocumentInfoItem::~SfxDocumentInfoItem() +{ + ClearCustomProperties(); +} + +//------------------------------------------------------------------------ + +SfxPoolItem* SfxDocumentInfoItem::Clone( SfxItemPool * ) const +{ + return new SfxDocumentInfoItem( *this ); +} + +//------------------------------------------------------------------------ + +int SfxDocumentInfoItem::operator==( const SfxPoolItem& rItem) const +{ + if (!(rItem.Type() == Type() && SfxStringItem::operator==(rItem))) { + return false; + } + const SfxDocumentInfoItem& rInfoItem( + static_cast<const SfxDocumentInfoItem&>(rItem)); + + return + m_AutoloadDelay == rInfoItem.m_AutoloadDelay && + m_AutoloadURL == rInfoItem.m_AutoloadURL && + m_isAutoloadEnabled == rInfoItem.m_isAutoloadEnabled && + m_DefaultTarget == rInfoItem.m_DefaultTarget && + m_Author == rInfoItem.m_Author && + m_CreationDate == rInfoItem.m_CreationDate && + m_ModifiedBy == rInfoItem.m_ModifiedBy && + m_ModificationDate == rInfoItem.m_ModificationDate && + m_PrintedBy == rInfoItem.m_PrintedBy && + m_PrintDate == rInfoItem.m_PrintDate && + m_EditingCycles == rInfoItem.m_EditingCycles && + m_EditingDuration == rInfoItem.m_EditingDuration && + m_Description == rInfoItem.m_Description && + m_Keywords == rInfoItem.m_Keywords && + m_Subject == rInfoItem.m_Subject && + m_Title == rInfoItem.m_Title && + m_aCustomProperties.size() == rInfoItem.m_aCustomProperties.size() && + std::equal(m_aCustomProperties.begin(), m_aCustomProperties.end(), + rInfoItem.m_aCustomProperties.begin()); +} + +//------------------------------------------------------------------------ + +void SfxDocumentInfoItem::resetUserData(const ::rtl::OUString & i_rAuthor) +{ + setAuthor(i_rAuthor); + DateTime now; + setCreationDate( util::DateTime( + now.Get100Sec(), now.GetSec(), now.GetMin(), now.GetHour(), + now.GetDay(), now.GetMonth(), now.GetYear() ) ); + setModifiedBy(::rtl::OUString()); + setPrintedBy(::rtl::OUString()); + setModificationDate(util::DateTime()); + setPrintDate(util::DateTime()); + setEditingDuration(0); + setEditingCycles(1); +} + +//------------------------------------------------------------------------ + +void SfxDocumentInfoItem::UpdateDocumentInfo( + const uno::Reference<document::XDocumentProperties>& i_xDocProps, + bool i_bDoNotUpdateUserDefined) const +{ + if (isAutoloadEnabled()) { + i_xDocProps->setAutoloadSecs(getAutoloadDelay()); + i_xDocProps->setAutoloadURL(getAutoloadURL()); + } else { + i_xDocProps->setAutoloadSecs(0); + i_xDocProps->setAutoloadURL(::rtl::OUString()); + } + i_xDocProps->setDefaultTarget(getDefaultTarget()); +// i_xDocProps->setTemplateName(getTemplateName()); + i_xDocProps->setAuthor(getAuthor()); + i_xDocProps->setCreationDate(getCreationDate()); + i_xDocProps->setModifiedBy(getModifiedBy()); + i_xDocProps->setModificationDate(getModificationDate()); + i_xDocProps->setPrintedBy(getPrintedBy()); + i_xDocProps->setPrintDate(getPrintDate()); + i_xDocProps->setEditingCycles(getEditingCycles()); + i_xDocProps->setEditingDuration(getEditingDuration()); + i_xDocProps->setDescription(getDescription()); + i_xDocProps->setKeywords( + ::comphelper::string::convertCommaSeparated(getKeywords())); + i_xDocProps->setSubject(getSubject()); + i_xDocProps->setTitle(getTitle()); + + // this is necessary in case of replaying a recorded macro: + // in this case, the macro may contain the 4 old user-defined DocumentInfo + // fields, but not any of the DocumentInfo properties; + // as a consequence, most of the UserDefined properties of the + // DocumentProperties would be summarily deleted here, which does not + // seem like a good idea. + if (i_bDoNotUpdateUserDefined) + return; + + try + { + Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties(); + Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY ); + Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo(); + const Sequence< beans::Property > lProps = xSetInfo->getProperties(); + const beans::Property* pProps = lProps.getConstArray(); + sal_Int32 nCount = lProps.getLength(); + for ( sal_Int32 j = 0; j < nCount; ++j ) + { + if ((pProps[j].Attributes & + ::com::sun::star::beans::PropertyAttribute::REMOVABLE)) + { + xContainer->removeProperty( pProps[j].Name ); + } + } + + for ( sal_uInt32 k = 0; k < m_aCustomProperties.size(); ++k ) + { + try + { + xContainer->addProperty( m_aCustomProperties[k]->m_sName, + beans::PropertyAttribute::REMOVABLE, m_aCustomProperties[k]->m_aValue ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" ); + } + } + } + catch ( Exception& ) + { + DBG_ERRORFILE( "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" ); + } +} + +//------------------------------------------------------------------------ + +sal_Bool SfxDocumentInfoItem::IsDeleteUserData() const +{ + return m_bDeleteUserData; +} + +void SfxDocumentInfoItem::SetDeleteUserData( sal_Bool bSet ) +{ + m_bDeleteUserData = bSet; +} + +sal_Bool SfxDocumentInfoItem::IsUseUserData() const +{ + return m_bUseUserData; +} + +void SfxDocumentInfoItem::SetUseUserData( sal_Bool bSet ) +{ + m_bUseUserData = bSet; +} + +std::vector< CustomProperty* > SfxDocumentInfoItem::GetCustomProperties() const +{ + std::vector< CustomProperty* > aRet; + for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ ) + { + CustomProperty* pProp = new CustomProperty( m_aCustomProperties[i]->m_sName, + m_aCustomProperties[i]->m_aValue ); + aRet.push_back( pProp ); + } + + return aRet; +} + +void SfxDocumentInfoItem::ClearCustomProperties() +{ + for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ ) + delete m_aCustomProperties[i]; + m_aCustomProperties.clear(); +} + +void SfxDocumentInfoItem::AddCustomProperty( const ::rtl::OUString& sName, const Any& rValue ) +{ + CustomProperty* pProp = new CustomProperty( sName, rValue ); + m_aCustomProperties.push_back( pProp ); +} + +sal_Bool SfxDocumentInfoItem::QueryValue( Any& rVal, BYTE nMemberId ) const +{ + String aValue; + sal_Int32 nValue = 0; + sal_Bool bValue = sal_False; + BOOL bIsInt = FALSE; + BOOL bIsString = FALSE; + nMemberId &= ~CONVERT_TWIPS; + switch ( nMemberId ) + { + case MID_DOCINFO_USEUSERDATA: + bValue = IsUseUserData(); + break; + case MID_DOCINFO_DELETEUSERDATA: + bValue = IsDeleteUserData(); + break; + case MID_DOCINFO_AUTOLOADENABLED: + bValue = isAutoloadEnabled(); + break; + case MID_DOCINFO_AUTOLOADSECS: + bIsInt = TRUE; + nValue = getAutoloadDelay(); + break; + case MID_DOCINFO_AUTOLOADURL: + bIsString = TRUE; + aValue = getAutoloadURL(); + break; + case MID_DOCINFO_DEFAULTTARGET: + bIsString = TRUE; + aValue = getDefaultTarget(); + break; + case MID_DOCINFO_DESCRIPTION: + bIsString = TRUE; + aValue = getDescription(); + break; + case MID_DOCINFO_KEYWORDS: + bIsString = TRUE; + aValue = getKeywords(); + break; + case MID_DOCINFO_SUBJECT: + bIsString = TRUE; + aValue = getSubject(); + break; + case MID_DOCINFO_TITLE: + bIsString = TRUE; + aValue = getTitle(); + break; + default: + DBG_ERROR("Wrong MemberId!"); + return sal_False; + } + + if ( bIsString ) + rVal <<= ::rtl::OUString( aValue ); + else if ( bIsInt ) + rVal <<= nValue; + else + rVal <<= bValue; + return sal_True; +} + +sal_Bool SfxDocumentInfoItem::PutValue( const Any& rVal, BYTE nMemberId ) +{ + ::rtl::OUString aValue; + sal_Int32 nValue=0; + sal_Bool bValue = sal_False; + sal_Bool bRet = sal_False; + nMemberId &= ~CONVERT_TWIPS; + switch ( nMemberId ) + { + case MID_DOCINFO_USEUSERDATA: + bRet = (rVal >>= bValue); + if ( bRet ) + SetUseUserData( bValue ); + break; + case MID_DOCINFO_DELETEUSERDATA: + // QUESTION: deleting user data was done here; seems to be superfluous! + bRet = (rVal >>= bValue); + if ( bRet ) + SetDeleteUserData( bValue ); + break; + case MID_DOCINFO_AUTOLOADENABLED: + bRet = (rVal >>= bValue); + if ( bRet ) + setAutoloadEnabled(bValue); + break; + case MID_DOCINFO_AUTOLOADSECS: + bRet = (rVal >>= nValue); + if ( bRet ) + setAutoloadDelay(nValue); + break; + case MID_DOCINFO_AUTOLOADURL: + bRet = (rVal >>= aValue); + if ( bRet ) + setAutoloadURL(aValue); + break; + case MID_DOCINFO_DEFAULTTARGET: + bRet = (rVal >>= aValue); + if ( bRet ) + setDefaultTarget(aValue); + break; + case MID_DOCINFO_DESCRIPTION: + bRet = (rVal >>= aValue); + if ( bRet ) + setDescription(aValue); + break; + case MID_DOCINFO_KEYWORDS: + bRet = (rVal >>= aValue); + if ( bRet ) + setKeywords(aValue); + break; + case MID_DOCINFO_SUBJECT: + bRet = (rVal >>= aValue); + if ( bRet ) + setSubject(aValue); + break; + case MID_DOCINFO_TITLE: + bRet = (rVal >>= aValue); + if ( bRet ) + setTitle(aValue); + break; + default: + DBG_ERROR("Wrong MemberId!"); + return sal_False; + } + + return bRet; +} + +//------------------------------------------------------------------------ + +SfxDocumentDescPage::SfxDocumentDescPage( Window * pParent, const SfxItemSet& rItemSet ) : + + SfxTabPage( pParent, SfxResId( TP_DOCINFODESC ), rItemSet ), + + aTitleFt ( this, SfxResId( FT_TITLE ) ), + aTitleEd ( this, SfxResId( ED_TITLE ) ), + aThemaFt ( this, SfxResId( FT_THEMA ) ), + aThemaEd ( this, SfxResId( ED_THEMA ) ), + aKeywordsFt ( this, SfxResId( FT_KEYWORDS ) ), + aKeywordsEd ( this, SfxResId( ED_KEYWORDS ) ), + aCommentFt ( this, SfxResId( FT_COMMENT ) ), + aCommentEd ( this, SfxResId( ED_COMMENT ) ), + + pInfoItem ( NULL ) + +{ + FreeResource(); +} + +//------------------------------------------------------------------------ + +SfxTabPage *SfxDocumentDescPage::Create(Window *pParent, const SfxItemSet &rItemSet) +{ + return new SfxDocumentDescPage(pParent, rItemSet); +} + +//------------------------------------------------------------------------ + +BOOL SfxDocumentDescPage::FillItemSet(SfxItemSet &rSet) +{ + // Pruefung, ob eine Aenderung vorliegt + const BOOL bTitleMod = aTitleEd.IsModified(); + const BOOL bThemeMod = aThemaEd.IsModified(); + const BOOL bKeywordsMod = aKeywordsEd.IsModified(); + const BOOL bCommentMod = aCommentEd.IsModified(); + if( !( bTitleMod || bThemeMod || bKeywordsMod || bCommentMod ) ) + { + return FALSE; + } + + // Erzeugung der Ausgabedaten + const SfxPoolItem* pItem = NULL; + SfxDocumentInfoItem* pInfo = NULL; + SfxTabDialog* pDlg = GetTabDialog(); + const SfxItemSet* pExSet = NULL; + + if ( pDlg ) + pExSet = pDlg->GetExampleSet(); + + if ( pExSet && SFX_ITEM_SET != pExSet->GetItemState( SID_DOCINFO, TRUE, &pItem ) ) + pInfo = pInfoItem; + else if ( pItem ) + pInfo = new SfxDocumentInfoItem( *(const SfxDocumentInfoItem *)pItem ); + + if ( !pInfo ) + { + DBG_ERRORFILE( "SfxDocumentDescPage::FillItemSet(): no item found" ); + return FALSE; + } + + if( bTitleMod ) + { + pInfo->setTitle( aTitleEd.GetText() ); + } + if( bThemeMod ) + { + pInfo->setSubject( aThemaEd.GetText() ); + } + if( bKeywordsMod ) + { + pInfo->setKeywords( aKeywordsEd.GetText() ); + } + if( bCommentMod ) + { + pInfo->setDescription( aCommentEd.GetText() ); + } + rSet.Put( SfxDocumentInfoItem( *pInfo ) ); + if( pInfo != pInfoItem ) + { + delete pInfo; + } + + return TRUE; +} + +//------------------------------------------------------------------------ + +void SfxDocumentDescPage::Reset(const SfxItemSet &rSet) +{ + pInfoItem = &(SfxDocumentInfoItem &)rSet.Get(SID_DOCINFO); + + aTitleEd.SetText( pInfoItem->getTitle() ); + aThemaEd.SetText( pInfoItem->getSubject() ); + aKeywordsEd.SetText( pInfoItem->getKeywords() ); + aCommentEd.SetText( pInfoItem->getDescription() ); + + SFX_ITEMSET_ARG( &rSet, pROItem, SfxBoolItem, SID_DOC_READONLY, FALSE ); + if ( pROItem && pROItem->GetValue() ) + { + aTitleEd.SetReadOnly( TRUE ); + aThemaEd.SetReadOnly( TRUE ); + aKeywordsEd.SetReadOnly( TRUE ); + aCommentEd.SetReadOnly( TRUE ); + } +} + +//------------------------------------------------------------------------ + +namespace +{ + String GetDateTimeString( sal_Int32 _nDate, sal_Int32 _nTime ) + { + LocaleDataWrapper aWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + + Date aDate( _nDate ); + Time aTime( _nTime ); + String aStr( aWrapper.getDate( aDate ) ); + aStr.AppendAscii( ", " ); + aStr += aWrapper.getTime( aTime ); + return aStr; + } + + // copy from xmlsecurity/source/dialog/resourcemanager.cxx + String GetContentPart( const String& _rRawString, const String& _rPartId ) + { + String s; + + xub_StrLen nContStart = _rRawString.Search( _rPartId ); + if( nContStart != STRING_NOTFOUND ) + { + nContStart = nContStart + _rPartId.Len(); + ++nContStart; // now it's start of content, directly after Id + + xub_StrLen nContEnd = _rRawString.Search( sal_Unicode( ',' ), nContStart ); + + s = String( _rRawString, nContStart, nContEnd - nContStart ); + } + + return s; + } + +} + +SfxDocumentPage::SfxDocumentPage( Window* pParent, const SfxItemSet& rItemSet ) : + + SfxTabPage( pParent, SfxResId( TP_DOCINFODOC ), rItemSet ), + + aBmp1 ( this, SfxResId( BMP_FILE_1 ) ), + aNameED ( this, SfxResId( ED_FILE_NAME ) ), + + aLine1FL ( this, SfxResId( FL_FILE_1 ) ), + aTypeFT ( this, SfxResId( FT_FILE_TYP ) ), + aShowTypeFT ( this, SfxResId( FT_FILE_SHOW_TYP ) ), + aReadOnlyCB ( this, SfxResId( CB_FILE_READONLY ) ), + aFileFt ( this, SfxResId( FT_FILE ) ), + aFileValFt ( this, SfxResId( FT_FILE_VAL ) ), + aSizeFT ( this, SfxResId( FT_FILE_SIZE ) ), + aShowSizeFT ( this, SfxResId( FT_FILE_SHOW_SIZE ) ), + + aLine2FL ( this, SfxResId( FL_FILE_2 ) ), + aCreateFt ( this, SfxResId( FT_CREATE ) ), + aCreateValFt ( this, SfxResId( FT_CREATE_VAL ) ), + aChangeFt ( this, SfxResId( FT_CHANGE ) ), + aChangeValFt ( this, SfxResId( FT_CHANGE_VAL ) ), + aSignedFt ( this, SfxResId( FT_SIGNED ) ), + aSignedValFt ( this, SfxResId( FT_SIGNED_VAL ) ), + aSignatureBtn ( this, SfxResId( BTN_SIGNATURE ) ), + aPrintFt ( this, SfxResId( FT_PRINT ) ), + aPrintValFt ( this, SfxResId( FT_PRINT_VAL ) ), + aTimeLogFt ( this, SfxResId( FT_TIMELOG ) ), + aTimeLogValFt ( this, SfxResId( FT_TIMELOG_VAL ) ), + aDocNoFt ( this, SfxResId( FT_DOCNO ) ), + aDocNoValFt ( this, SfxResId( FT_DOCNO_VAL ) ), + aUseUserDataCB ( this, SfxResId( CB_USE_USERDATA ) ), + aDeleteBtn ( this, SfxResId( BTN_DELETE ) ), + + aLine3FL ( this, SfxResId( FL_FILE_3 ) ), + aTemplFt ( this, SfxResId( FT_TEMPL ) ), + aTemplValFt ( this, SfxResId( FT_TEMPL_VAL ) ), + + aUnknownSize ( SfxResId( STR_UNKNOWNSIZE ) ), + aMultiSignedStr ( SfxResId( STR_MULTSIGNED ) ), + + bEnableUseUserData ( FALSE ), + bHandleDelete ( FALSE ) + +{ + FreeResource(); + + ImplUpdateSignatures(); + aDeleteBtn.SetClickHdl( LINK( this, SfxDocumentPage, DeleteHdl ) ); + aSignatureBtn.SetClickHdl( LINK( this, SfxDocumentPage, SignatureHdl ) ); + + // if the button text is too wide, then broaden it + const long nOffset = 12; + String sText = aSignatureBtn.GetText(); + long nTxtW = aSignatureBtn.GetTextWidth( sText ); + if ( sText.Search( '~' ) == STRING_NOTFOUND ) + nTxtW += nOffset; + long nBtnW = aSignatureBtn.GetSizePixel().Width(); + if ( nTxtW >= nBtnW ) + { + long nDelta = Max( nTxtW - nBtnW, nOffset/3 ); + Size aNewSize = aSignatureBtn.GetSizePixel(); + aNewSize.Width() += nDelta; + aSignatureBtn.SetSizePixel( aNewSize ); + aDeleteBtn.SetSizePixel( aNewSize ); + // and give them a new position + Point aNewPos = aSignatureBtn.GetPosPixel(); + aNewPos.X() -= nDelta; + aSignatureBtn.SetPosPixel( aNewPos ); + aNewPos = aDeleteBtn.GetPosPixel(); + aNewPos.X() -= nDelta; + aDeleteBtn.SetPosPixel( aNewPos ); + + aNewSize = aSignedValFt.GetSizePixel(); + aNewSize.Width() -= nDelta; + aSignedValFt.SetSizePixel( aNewSize ); + aNewSize = aUseUserDataCB.GetSizePixel(); + aNewSize.Width() -= nDelta; + aUseUserDataCB.SetSizePixel( aNewSize ); + } + // See i96288 + // Check if the document signature command is enabled + // on the main list enable/disable the pushbutton accordingly + SvtCommandOptions aCmdOptions; + if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( DOCUMENT_SIGNATURE_MENU_CMD ) ) ) ) + aSignatureBtn.Disable(); +} + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxDocumentPage, DeleteHdl, PushButton*, EMPTYARG ) +{ + String aName; + if ( bEnableUseUserData && aUseUserDataCB.IsChecked() ) + aName = SvtUserOptions().GetFullName(); + LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + DateTime now; + util::DateTime uDT( + now.Get100Sec(), now.GetSec(), now.GetMin(), now.GetHour(), + now.GetDay(), now.GetMonth(), now.GetYear() ); + aCreateValFt.SetText( ConvertDateTime_Impl( aName, uDT, aLocaleWrapper ) ); + XubString aEmpty; + aChangeValFt.SetText( aEmpty ); + aPrintValFt.SetText( aEmpty ); + const Time aTime( 0 ); + aTimeLogValFt.SetText( aLocaleWrapper.getDuration( aTime ) ); + aDocNoValFt.SetText( '1' ); + bHandleDelete = TRUE; + return 0; +} + +IMPL_LINK( SfxDocumentPage, SignatureHdl, PushButton*, EMPTYARG ) +{ + SfxObjectShell* pDoc = SfxObjectShell::Current(); + if( pDoc ) + { + pDoc->SignDocumentContent(); + + ImplUpdateSignatures(); + } + + return 0; +} + +void SfxDocumentPage::ImplUpdateSignatures() +{ + SfxObjectShell* pDoc = SfxObjectShell::Current(); + if( pDoc ) + { + SfxMedium* pMedium = pDoc->GetMedium(); + if ( pMedium && pMedium->GetName().Len() && pMedium->GetStorage().is() ) + { + Reference< security::XDocumentDigitalSignatures > xD( + comphelper::getProcessServiceFactory()->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ) ), uno::UNO_QUERY ); + + if( xD.is() ) + { + String s; + Sequence< security::DocumentSignatureInformation > aInfos; + aInfos = xD->verifyDocumentContentSignatures( pMedium->GetZipStorageToSign_Impl(), + uno::Reference< io::XInputStream >() ); + if( aInfos.getLength() > 1 ) + { + s = aMultiSignedStr; + } + else if( aInfos.getLength() == 1 ) + { + String aCN_Id( String::CreateFromAscii( "CN" ) ); + const security::DocumentSignatureInformation& rInfo = aInfos[ 0 ]; + s = GetDateTimeString( rInfo.SignatureDate, rInfo.SignatureTime ); + s.AppendAscii( ", " ); + s += GetContentPart( rInfo.Signer->getSubjectName(), aCN_Id ); + } + aSignedValFt.SetText( s ); + } + } + } +} + +//------------------------------------------------------------------------ + +SfxTabPage* SfxDocumentPage::Create( Window* pParent, const SfxItemSet& rItemSet ) +{ + return new SfxDocumentPage( pParent, rItemSet ); +} + +//------------------------------------------------------------------------ + +void SfxDocumentPage::EnableUseUserData() +{ + bEnableUseUserData = TRUE; + aUseUserDataCB.Show(); + aDeleteBtn.Show(); +} + +//------------------------------------------------------------------------ + +BOOL SfxDocumentPage::FillItemSet( SfxItemSet& rSet ) +{ + BOOL bRet = FALSE; + + if ( !bHandleDelete && bEnableUseUserData && + aUseUserDataCB.GetState() != aUseUserDataCB.GetSavedValue() && + GetTabDialog() && GetTabDialog()->GetExampleSet() ) + { + const SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet(); + const SfxPoolItem* pItem; + + if ( pExpSet && SFX_ITEM_SET == pExpSet->GetItemState( SID_DOCINFO, TRUE, &pItem ) ) + { + SfxDocumentInfoItem* pInfoItem = (SfxDocumentInfoItem*)pItem; + BOOL bUseData = ( STATE_CHECK == aUseUserDataCB.GetState() ); + pInfoItem->SetUseUserData( bUseData ); +/* + if ( !bUseData ) + { + // "Benutzerdaten verwenden" ausgeschaltet -> + // den Benutzer aus den Stamps l"oschen + String aEmptyUser; + aInfo.SetCreated( + SfxStamp( aEmptyUser, aInfo.GetCreated().GetTime() ) ); + aInfo.SetChanged( + SfxStamp( aEmptyUser, aInfo.GetChanged().GetTime() ) ); + aInfo.SetPrinted( + SfxStamp( aEmptyUser, aInfo.GetPrinted().GetTime() ) ); + } +*/ + rSet.Put( SfxDocumentInfoItem( *pInfoItem ) ); + bRet = TRUE; + } + } + + if ( bHandleDelete ) + { + const SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet(); + const SfxPoolItem* pItem; + if ( pExpSet && SFX_ITEM_SET == pExpSet->GetItemState( SID_DOCINFO, TRUE, &pItem ) ) + { + SfxDocumentInfoItem* pInfoItem = (SfxDocumentInfoItem*)pItem; + BOOL bUseAuthor = bEnableUseUserData && aUseUserDataCB.IsChecked(); + SfxDocumentInfoItem newItem( *pInfoItem ); + newItem.resetUserData( bUseAuthor + ? SvtUserOptions().GetFullName() + : ::rtl::OUString() ); + pInfoItem->SetUseUserData( STATE_CHECK == aUseUserDataCB.GetState() ); + newItem.SetUseUserData( STATE_CHECK == aUseUserDataCB.GetState() ); + + newItem.SetDeleteUserData( TRUE ); + rSet.Put( newItem ); + bRet = TRUE; + } + } + + if ( aNameED.IsModified() && aNameED.GetText().Len() ) + { + rSet.Put( SfxStringItem( ID_FILETP_TITLE, aNameED.GetText() ) ); + bRet = TRUE; + } + + if ( /* aReadOnlyCB.IsModified() */ TRUE ) + { + rSet.Put( SfxBoolItem( ID_FILETP_READONLY, aReadOnlyCB.IsChecked() ) ); + bRet = TRUE; + } + + return bRet; +} + +//------------------------------------------------------------------------ + +void SfxDocumentPage::Reset( const SfxItemSet& rSet ) +{ + // Bestimmung der Dokumentinformationen + const SfxDocumentInfoItem *pInfoItem = + &(const SfxDocumentInfoItem &)rSet.Get(SID_DOCINFO); + + // template data + if ( pInfoItem->HasTemplate() ) + { + aTemplValFt.SetText( pInfoItem->getTemplateName() ); + } + else + { + aTemplFt.Hide(); + aTemplValFt.Hide(); + } + + // determine file name + String aFile( pInfoItem->GetValue() ); + String aFactory( aFile ); + if ( aFile.Len() > 2 && aFile.GetChar(0) == '[' ) + { + USHORT nPos = aFile.Search( ']' ); + aFactory = aFile.Copy( 1, nPos-1 ); + aFile = aFile.Copy( nPos+1 ); + } + + // determine name + String aName; + const SfxPoolItem* pItem = 0; + if ( SFX_ITEM_SET != rSet.GetItemState( ID_FILETP_TITLE, FALSE, &pItem ) ) + { + INetURLObject aURL(aFile); + aName = aURL.GetName( INetURLObject::DECODE_WITH_CHARSET ); + if ( !aName.Len() || aURL.GetProtocol() == INET_PROT_PRIVATE ) + aName = String( SfxResId( STR_NONAME ) ); + aNameED.SetReadOnly( TRUE ); + } + else + { + DBG_ASSERT( pItem->IsA( TYPE( SfxStringItem ) ), "SfxDocumentPage:<SfxStringItem> erwartet" ); + aName = ( ( SfxStringItem* ) pItem )->GetValue(); + } + aNameED.SetText( aName ); + aNameED.ClearModifyFlag(); + + // determine RO-Flag + if ( SFX_ITEM_UNKNOWN == rSet.GetItemState( ID_FILETP_READONLY, FALSE, &pItem ) + || !pItem ) + aReadOnlyCB.Hide(); + else + aReadOnlyCB.Check( ( (SfxBoolItem*)pItem )->GetValue() ); + + // determine context symbol + INetURLObject aURL; + aURL.SetSmartProtocol( INET_PROT_FILE ); + aURL.SetSmartURL( aFactory); + const String& rMainURL = aURL.GetMainURL( INetURLObject::NO_DECODE ); + aBmp1.SetImage( SvFileInformationManager::GetImage( aURL, TRUE ) ); + + // determine size and type + String aSizeText( aUnknownSize ); + if ( aURL.GetProtocol() == INET_PROT_FILE ) + aSizeText = CreateSizeText( SfxContentHelper::GetSize( aURL.GetMainURL( INetURLObject::NO_DECODE ) ) ); + aShowSizeFT.SetText( aSizeText ); + + String aDescription = SvFileInformationManager::GetDescription( INetURLObject(rMainURL) ); + if ( aDescription.Len() == 0 ) + aDescription = String( SfxResId( STR_SFX_NEWOFFICEDOC ) ); + aShowTypeFT.SetText( aDescription ); + + // determine location + aURL.SetSmartURL( aFile); + if ( aURL.GetProtocol() == INET_PROT_FILE ) + { + INetURLObject aPath( aURL ); + aPath.setFinalSlash(); + aPath.removeSegment(); + // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS + aPath.removeFinalSlash(); + String aText( aPath.PathToFileName() ); //! (pb) MaxLen? + aFileValFt.SetText( aText ); + } + else if ( aURL.GetProtocol() != INET_PROT_PRIVATE ) + aFileValFt.SetText( aURL.GetPartBeforeLastName() ); + + // handle access data + sal_Bool m_bUseUserData = pInfoItem->IsUseUserData(); + LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + aCreateValFt.SetText( ConvertDateTime_Impl( pInfoItem->getAuthor(), + pInfoItem->getCreationDate(), aLocaleWrapper ) ); + util::DateTime aTime( pInfoItem->getModificationDate() ); +// if ( aTime.IsValid() ) + if ( aTime.Month > 0 ) + aChangeValFt.SetText( ConvertDateTime_Impl( + pInfoItem->getModifiedBy(), aTime, aLocaleWrapper ) ); + aTime = pInfoItem->getPrintDate(); +// if ( aTime.IsValid()) + if ( aTime.Month > 0 ) + aPrintValFt.SetText( ConvertDateTime_Impl( pInfoItem->getPrintedBy(), + aTime, aLocaleWrapper ) ); + const long nTime = pInfoItem->getEditingDuration(); + if ( m_bUseUserData ) + { + const Time aT( nTime/3600, (nTime%3600)/60, nTime%60 ); + aTimeLogValFt.SetText( aLocaleWrapper.getDuration( aT ) ); + aDocNoValFt.SetText( String::CreateFromInt32( + pInfoItem->getEditingCycles() ) ); + } + + TriState eState = (TriState)m_bUseUserData; + + if ( STATE_DONTKNOW == eState ) + aUseUserDataCB.EnableTriState( TRUE ); + + aUseUserDataCB.SetState( eState ); + aUseUserDataCB.SaveValue(); + aUseUserDataCB.Enable( bEnableUseUserData ); + bHandleDelete = FALSE; + aDeleteBtn.Enable( bEnableUseUserData ); +} + +//------------------------------------------------------------------------ + +SfxInternetPage::SfxInternetPage( Window* pParent, const SfxItemSet& rItemSet ) : + + SfxTabPage( pParent, SfxResId( TP_DOCINFORELOAD ), rItemSet ), + + aRBNoAutoUpdate ( this, SfxResId( RB_NOAUTOUPDATE ) ), + + aRBReloadUpdate ( this, SfxResId( RB_RELOADUPDATE ) ), + + aRBForwardUpdate ( this, SfxResId( RB_FORWARDUPDATE ) ), + aFTEvery ( this, SfxResId( FT_EVERY ) ), + aNFReload ( this, SfxResId( ED_RELOAD ) ), + aFTReloadSeconds ( this, SfxResId( FT_RELOADSECS ) ), + aFTAfter ( this, SfxResId( FT_AFTER ) ), + aNFAfter ( this, SfxResId( ED_FORWARD ) ), + aFTAfterSeconds ( this, SfxResId( FT_FORWARDSECS ) ), + aFTURL ( this, SfxResId( FT_URL ) ), + aEDForwardURL ( this, SfxResId( ED_URL ) ), + aPBBrowseURL ( this, SfxResId( PB_BROWSEURL ) ), + aFTFrame ( this, SfxResId( FT_FRAME ) ), + aCBFrame ( this, SfxResId( CB_FRAME ) ), + + aForwardErrorMessg ( SfxResId( STR_FORWARD_ERRMSSG ) ), + pInfoItem ( NULL ), + pFileDlg ( NULL ), + eState ( S_Init ) + +{ + FreeResource(); + pInfoItem = &( SfxDocumentInfoItem& ) rItemSet.Get( SID_DOCINFO ); + TargetList aList; + SfxViewFrame* pFrame = SfxViewFrame::Current(); + if( pFrame ) + { + pFrame = pFrame->GetTopViewFrame(); + if( pFrame ) + { + pFrame->GetTargetList( aList ); + + String* pObj; + for( USHORT nPos = ( USHORT ) aList.Count() ; nPos ; ) + { + pObj = aList.GetObject( --nPos ); + aCBFrame.InsertEntry( *pObj ); + delete pObj; + } + } + } + + aRBNoAutoUpdate.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlNoUpdate ) ); + aRBReloadUpdate.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlReload ) ); + aRBForwardUpdate.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlForward ) ); + aPBBrowseURL.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlBrowseURL ) ); + + aForwardErrorMessg.SearchAndReplaceAscii( "%PLACEHOLDER%", aRBForwardUpdate.GetText() ); + + ChangeState( S_NoUpdate ); +} + +//------------------------------------------------------------------------ + +SfxInternetPage::~SfxInternetPage() +{ + delete pFileDlg; +} + +//------------------------------------------------------------------------ + +void SfxInternetPage::ChangeState( STATE eNewState ) +{ + DBG_ASSERT( eNewState != S_Init, "*SfxInternetPage::ChangeState(): new state init is supposed to not work here!" ); + + if( eState == eNewState ) + return; + + switch( eState ) + { + case S_Init: + EnableNoUpdate( TRUE ); + EnableReload( FALSE ); + EnableForward( FALSE ); + break; + case S_NoUpdate: + EnableNoUpdate( FALSE ); + if( eNewState == S_Reload ) + EnableReload( TRUE ); + else + EnableForward( TRUE ); + break; + case S_Reload: + EnableReload( FALSE ); + if( eNewState == S_NoUpdate ) + EnableNoUpdate( TRUE ); + else + EnableForward( TRUE ); + break; + case S_Forward: + EnableForward( FALSE ); + if( eNewState == S_NoUpdate ) + EnableNoUpdate( TRUE ); + else + EnableReload( TRUE ); + break; + default: + DBG_ERROR( "*SfxInternetPage::SetState(): unhandled state!" ); + } + + eState = eNewState; +} + +//------------------------------------------------------------------------ + +void SfxInternetPage::EnableNoUpdate( BOOL bEnable ) +{ + if( bEnable ) + aRBNoAutoUpdate.Check(); +} + +//------------------------------------------------------------------------ + +void SfxInternetPage::EnableReload( BOOL bEnable ) +{ + aFTEvery.Enable( bEnable ); + aNFReload.Enable( bEnable ); + aFTReloadSeconds.Enable( bEnable ); + + if( bEnable ) + aRBReloadUpdate.Check(); +} + +//------------------------------------------------------------------------ + +void SfxInternetPage::EnableForward( BOOL bEnable ) +{ + aFTAfter.Enable( bEnable ); + aNFAfter.Enable( bEnable ); + aFTAfterSeconds.Enable( bEnable ); + aFTURL.Enable( bEnable ); + aEDForwardURL.Enable( bEnable ); + aPBBrowseURL.Enable( bEnable ); + aFTFrame.Enable( bEnable ); + aCBFrame.Enable( bEnable ); + + if( bEnable ) + aRBForwardUpdate.Check(); +} + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxInternetPage, ClickHdlNoUpdate, Control*, pCtrl ) +{ + (void)pCtrl; //unused + ChangeState( S_NoUpdate ); + return 0; +} + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxInternetPage, ClickHdlReload, Control*, pCtrl ) +{ + (void)pCtrl; //unused + ChangeState( S_Reload ); + return 0; +} + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxInternetPage, ClickHdlForward, Control*, pCtrl ) +{ + (void)pCtrl; //unused + ChangeState( S_Forward ); + return 0; +} + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxInternetPage, ClickHdlBrowseURL, PushButton*, EMPTYARG ) +{ + if ( !pFileDlg ) + pFileDlg = new sfx2::FileDialogHelper( TemplateDescription::FILEOPEN_SIMPLE, WB_OPEN ); + pFileDlg->SetDisplayDirectory( aEDForwardURL.GetText() ); + pFileDlg->StartExecuteModal( LINK( this, SfxInternetPage, DialogClosedHdl ) ); + + return 0; +} + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxInternetPage, DialogClosedHdl, sfx2::FileDialogHelper*, EMPTYARG ) +{ + DBG_ASSERT( pFileDlg, "SfxInternetPage::DialogClosedHdl(): no file dialog" ); + + if ( ERRCODE_NONE == pFileDlg->GetError() ) + aEDForwardURL.SetText( pFileDlg->GetPath() ); + + return 0; +} + +//------------------------------------------------------------------------ + +BOOL SfxInternetPage::FillItemSet( SfxItemSet& rSet ) +{ + const SfxPoolItem* pItem = NULL; + SfxDocumentInfoItem* pInfo = NULL; + SfxTabDialog* pDlg = GetTabDialog(); + const SfxItemSet* pExSet = NULL; + + if( pDlg ) + pExSet = pDlg->GetExampleSet(); + + if( pExSet && SFX_ITEM_SET != pExSet->GetItemState( SID_DOCINFO, TRUE, &pItem ) ) + pInfo = pInfoItem; + else if ( pItem ) + pInfo = new SfxDocumentInfoItem( *(const SfxDocumentInfoItem*)pItem ); + + if ( !pInfo ) + { + DBG_ERRORFILE( "SfxInternetPage::FillItemSet(): no item found" ); + return FALSE; + } + + DBG_ASSERT( eState != S_Init, "*SfxInternetPage::FillItemSet(): state init is not acceptable at this point!" ); + + BOOL bEnableReload = FALSE; + ::std::auto_ptr< String > aURL( NULL ); + ::std::auto_ptr< String > aFrame( NULL ); + ULONG nDelay = 0; + + switch( eState ) + { + case S_NoUpdate: + break; + case S_Reload: + bEnableReload = TRUE; + aURL = ::std::auto_ptr< String >( new String() ); + aFrame = ::std::auto_ptr< String >( new String() ); + nDelay = static_cast<ULONG>(aNFReload.GetValue()); + break; + case S_Forward: + DBG_ASSERT( aEDForwardURL.GetText().Len(), "+SfxInternetPage::FillItemSet(): empty URL should be not possible for forward option!" ); + + bEnableReload = TRUE; + aURL = ::std::auto_ptr< String >( new String( URIHelper::SmartRel2Abs( INetURLObject(aBaseURL), aEDForwardURL.GetText(), URIHelper::GetMaybeFileHdl(), true ) ) ); + aFrame = ::std::auto_ptr< String >( new String( aCBFrame.GetText() ) ); + nDelay = static_cast<ULONG>(aNFAfter.GetValue()); + break; + default: + break; + } + + pInfo->setAutoloadEnabled( bEnableReload ); + + if( bEnableReload ) + { + pInfo->setAutoloadURL( *aURL.get() ); + pInfo->setDefaultTarget( *aFrame.get() ); + pInfo->setAutoloadDelay( nDelay ); + } + + rSet.Put( *pInfo ); + if( pInfo != pInfoItem ) + delete pInfo; + return TRUE; +} + +//------------------------------------------------------------------------ + +SfxTabPage *SfxInternetPage::Create( Window* pParent, const SfxItemSet& rItemSet ) +{ + return new SfxInternetPage(pParent, rItemSet); +} + +//------------------------------------------------------------------------ + +void SfxInternetPage::Reset( const SfxItemSet& rSet ) +{ + pInfoItem = &( SfxDocumentInfoItem& ) rSet.Get( SID_DOCINFO ); + SFX_ITEMSET_ARG( &rSet, pURLItem, SfxStringItem, SID_BASEURL, FALSE ); + DBG_ASSERT( pURLItem, "No BaseURL provided for InternetTabPage!" ); + if ( pURLItem ) + aBaseURL = pURLItem->GetValue(); + + STATE eNewState = S_NoUpdate; + + if( pInfoItem->isAutoloadEnabled() ) + { + const String& rURL = pInfoItem->getAutoloadURL(); + + if( rURL.Len() ) + { + aNFAfter.SetValue( pInfoItem->getAutoloadDelay() ); + aEDForwardURL.SetText( rURL ); + aCBFrame.SetText( pInfoItem->getDefaultTarget() ); + eNewState = S_Forward; + } + else + { + aNFReload.SetValue( pInfoItem->getAutoloadDelay() ); + eNewState = S_Reload; + } + } + + ChangeState( eNewState ); + + // #102907# ------------------------ + SFX_ITEMSET_ARG( &rSet, pROItem, SfxBoolItem, SID_DOC_READONLY, FALSE ); + if ( pROItem && pROItem->GetValue() ) + { + aRBNoAutoUpdate.Disable(); + aRBReloadUpdate.Disable(); + aRBForwardUpdate.Disable(); + aNFReload.Disable(); + aNFAfter.Disable(); + aEDForwardURL.Disable(); + aPBBrowseURL.Disable(); + aCBFrame.Disable(); + aFTEvery.Disable(); + aFTReloadSeconds.Disable(); + aFTAfter.Disable(); + aFTAfterSeconds.Disable(); + aFTURL.Disable(); + aFTFrame.Disable(); + } +} + +//------------------------------------------------------------------------ + +int SfxInternetPage::DeactivatePage( SfxItemSet* /*pSet*/ ) +{ + int nRet = LEAVE_PAGE; + + if( eState == S_Forward && !aEDForwardURL.GetText().Len() ) + { + ErrorBox aErrBox( this, WB_OK, aForwardErrorMessg ); + aErrBox.Execute(); + + nRet = KEEP_PAGE; + } + + return nRet; +} + +//------------------------------------------------------------------------ + +SfxDocumentInfoDialog::SfxDocumentInfoDialog( Window* pParent, + const SfxItemSet& rItemSet ) : + + SfxTabDialog( 0, pParent, SfxResId( SID_DOCINFO ), &rItemSet ) + +{ + FreeResource(); + + const SfxDocumentInfoItem* pInfoItem = + &(const SfxDocumentInfoItem &)rItemSet.Get( SID_DOCINFO ); + +#ifdef DBG_UTIL + SFX_ITEMSET_ARG( &rItemSet, pURLItem, SfxStringItem, SID_BASEURL, FALSE ); + DBG_ASSERT( pURLItem, "No BaseURL provided for InternetTabPage!" ); +#endif + + // Bestimmung des Titels + const SfxPoolItem* pItem = 0; + String aTitle( GetText() ); + if ( SFX_ITEM_SET != + rItemSet.GetItemState( SID_EXPLORER_PROPS_START, FALSE, &pItem ) ) + { + // Dateiname + String aFile( pInfoItem->GetValue() ); + + INetURLObject aURL; + aURL.SetSmartProtocol( INET_PROT_FILE ); + aURL.SetSmartURL( aFile); + if ( INET_PROT_PRIV_SOFFICE != aURL.GetProtocol() ) + { + String aLastName( aURL.GetLastName() ); + if ( aLastName.Len() ) + aTitle += aLastName; + else + aTitle += aFile; + } + else + aTitle += String( SfxResId( STR_NONAME ) ); + } + else + { + DBG_ASSERT( pItem->IsA( TYPE( SfxStringItem ) ), + "SfxDocumentInfoDialog:<SfxStringItem> erwartet" ); + aTitle += ( ( SfxStringItem* ) pItem )->GetValue(); + } + SetText( aTitle ); + + // Eigenschaftenseiten + AddTabPage(TP_DOCINFODESC, SfxDocumentDescPage::Create, 0); + AddTabPage(TP_DOCINFODOC, SfxDocumentPage::Create, 0); + AddTabPage(TP_CUSTOMPROPERTIES, SfxCustomPropertiesPage::Create, 0); + AddTabPage(TP_DOCINFORELOAD, SfxInternetPage::Create, 0); + AddTabPage(TP_DOCINFOSECURITY, SfxSecurityPage::Create, 0); +} + +// ----------------------------------------------------------------------- + +void SfxDocumentInfoDialog::PageCreated( USHORT nId, SfxTabPage &rPage ) +{ + if ( TP_DOCINFODOC == nId ) + ( (SfxDocumentPage&)rPage ).EnableUseUserData(); +} + +// class CustomPropertiesYesNoButton ------------------------------------- + +CustomPropertiesYesNoButton::CustomPropertiesYesNoButton( Window* pParent, const ResId& rResId ) : + Control( pParent, rResId ), + m_aYesButton( this, ResId( RB_PROPERTY_YES, *rResId.GetResMgr() ) ), + m_aNoButton ( this, ResId( RB_PROPERTY_NO, *rResId.GetResMgr() ) ) +{ + FreeResource(); + Wallpaper aWall( Color( COL_TRANSPARENT ) ); + SetBackground( aWall ); + SetBorderStyle( WINDOW_BORDER_MONO ); + CheckNo(); + m_aYesButton.SetBackground( aWall ); + m_aNoButton.SetBackground( aWall ); +} +class DurationDialog_Impl : public ModalDialog +{ + FixedLine aDurationFL; + + OKButton aOKPB; + CancelButton aCancelPB; + HelpButton aHelpPB; + + CheckBox aNegativeCB; + FixedText aYearFT; + NumericField aYearNF; + FixedText aMonthFT; + NumericField aMonthNF; + FixedText aDayFT; + NumericField aDayNF; + FixedText aHourFT; + NumericField aHourNF; + FixedText aMinuteFT; + NumericField aMinuteNF; + FixedText aSecondFT; + NumericField aSecondNF; + FixedText aMSecondFT; + NumericField aMSecondNF; + +public: + + DurationDialog_Impl( Window* pParent, const util::Duration& rDuration ); + ~DurationDialog_Impl(); + + util::Duration GetDuration() const; +}; +/*-- 20.11.2009 15:40:46--------------------------------------------------- + + -----------------------------------------------------------------------*/ +DurationDialog_Impl::DurationDialog_Impl( + Window* pParent, const util::Duration& rDuration) + : ModalDialog( pParent, SfxResId( RID_EDIT_DURATIONS ) ), + aDurationFL(this, SfxResId( FL_DURATION )), + aOKPB( this, SfxResId( PB_OK )), + aCancelPB( this, SfxResId( PB_CANCEL )), + aHelpPB( this, SfxResId( PB_HELP )), + aNegativeCB(this, SfxResId( CB_NEGATIVE )), + aYearFT( this, SfxResId( FT_YEAR )), + aYearNF( this, SfxResId( ED_YEAR )), + aMonthFT( this, SfxResId( FT_MONTH )), + aMonthNF( this, SfxResId( ED_MONTH )), + aDayFT( this, SfxResId( FT_DAY )), + aDayNF( this, SfxResId( ED_DAY )), + aHourFT( this, SfxResId( FT_HOUR )), + aHourNF( this, SfxResId( ED_HOUR )), + aMinuteFT( this, SfxResId( FT_MINUTE )), + aMinuteNF( this, SfxResId( ED_MINUTE )), + aSecondFT( this, SfxResId( FT_SECOND )), + aSecondNF( this, SfxResId( ED_SECOND )), + aMSecondFT( this, SfxResId( FT_MSECOND )), + aMSecondNF( this, SfxResId( ED_MSECOND )) +{ + FreeResource(); + aNegativeCB.Check(rDuration.Negative); + aYearNF.SetValue(rDuration.Years); + aMonthNF.SetValue(rDuration.Months ); + aDayNF.SetValue(rDuration.Days ); + aHourNF.SetValue(rDuration.Hours ); + aMinuteNF.SetValue(rDuration.Minutes); + aSecondNF.SetValue(rDuration.Seconds); + aMSecondNF.SetValue(rDuration.MilliSeconds); +} +/*-- 20.11.2009 16:08:55--------------------------------------------------- + + -----------------------------------------------------------------------*/ +DurationDialog_Impl::~DurationDialog_Impl() +{ +} +/*-- 20.11.2009 15:41:47--------------------------------------------------- + + -----------------------------------------------------------------------*/ +util::Duration DurationDialog_Impl::GetDuration() const +{ + util::Duration aRet; + aRet.Negative = aNegativeCB.IsChecked(); + aRet.Years = aYearNF.GetValue(); + aRet.Months = aMonthNF.GetValue( ); + aRet.Days = aDayNF.GetValue( ); + aRet.Hours = aHourNF.GetValue( ); + aRet.Minutes = aMinuteNF.GetValue(); + aRet.Seconds = aSecondNF.GetValue(); + aRet.MilliSeconds = aMSecondNF.GetValue(); + return aRet; +} + +/*-- 20.11.2009 15:30:58--------------------------------------------------- + + -----------------------------------------------------------------------*/ +CustomPropertiesDurationField::CustomPropertiesDurationField( Window* pParent, const ResId& rResId, CustomPropertyLine* pLine ) : + Edit( pParent, rResId ), m_pLine( pLine ) + +{ + SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) ); +} +/*-- 23.11.2009 08:46:02--------------------------------------------------- + + -----------------------------------------------------------------------*/ +CustomPropertiesDurationField::~CustomPropertiesDurationField() +{ +} +/*-- 23.11.2009 09:23:35--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt ) +{ + if( rHEvt.GetMode() & HELPMODE_QUICK ) + { + Size aSize( GetSizePixel() ); + Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize ); + if(Help::IsBalloonHelpEnabled()) + Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), GetText() ); + else + Help::ShowQuickHelp( this, aItemRect, GetText(), + QUICKHELP_LEFT|QUICKHELP_VCENTER ); + } +} +/*-- 20.11.2009 15:30:58--------------------------------------------------- + + -----------------------------------------------------------------------*/ +void CustomPropertiesDurationField::SetDuration( const util::Duration& rDuration ) +{ + m_aDuration = rDuration; + String sText(rDuration.Negative ? '-' : '+'); + sText += m_pLine->m_sDurationFormat; + sText.SearchAndReplace(String::CreateFromAscii( "%1"), String::CreateFromInt32( rDuration.Years ) ); + sText.SearchAndReplace(String::CreateFromAscii( "%2"), String::CreateFromInt32( rDuration.Months ) ); + sText.SearchAndReplace(String::CreateFromAscii( "%3"), String::CreateFromInt32( rDuration.Days ) ); + sText.SearchAndReplace(String::CreateFromAscii( "%4"), String::CreateFromInt32( rDuration.Hours ) ); + sText.SearchAndReplace(String::CreateFromAscii( "%5"), String::CreateFromInt32( rDuration.Minutes) ); + sText.SearchAndReplace(String::CreateFromAscii( "%6"), String::CreateFromInt32( rDuration.Seconds) ); + SetText( sText ); +} +/*-- 23.11.2009 08:51:15--------------------------------------------------- + + -----------------------------------------------------------------------*/ +CustomPropertiesEditButton::CustomPropertiesEditButton( Window* pParent, const ResId& rResId, CustomPropertyLine* pLine ) : + PushButton( pParent, rResId ), m_pLine( pLine ) +{ + SetClickHdl( LINK( this, CustomPropertiesEditButton, ClickHdl )); +} +/*-- 23.11.2009 08:51:15--------------------------------------------------- + + -----------------------------------------------------------------------*/ +CustomPropertiesEditButton::~CustomPropertiesEditButton() +{ +} +/*-- 23.11.2009 08:47:37--------------------------------------------------- + + -----------------------------------------------------------------------*/ +IMPL_LINK( CustomPropertiesEditButton, ClickHdl, PushButton*, EMPTYARG ) +{ + DurationDialog_Impl* pDurationDlg = new DurationDialog_Impl( this, m_pLine->m_aDurationField.GetDuration() ); + if( RET_OK == pDurationDlg->Execute() ) + m_pLine->m_aDurationField.SetDuration( pDurationDlg->GetDuration() ); + delete pDurationDlg; + return 1; +} +//-------------------------------------------------------------------------- +void CustomPropertiesYesNoButton::Resize() +{ + const long nWidth = GetSizePixel().Width(); + const long n3Width = LogicToPixel( Size( 3, 3 ), MAP_APPFONT ).Width(); + const long nNewWidth = ( nWidth / 2 ) - n3Width - 2; + Size aSize = m_aYesButton.GetSizePixel(); + const long nDelta = aSize.Width() - nNewWidth; + aSize.Width() = nNewWidth; + m_aYesButton.SetSizePixel( aSize ); + Point aPos = m_aNoButton.GetPosPixel(); + aPos.X() -= nDelta; + m_aNoButton.SetPosSizePixel( aPos, aSize ); +} + +// struct CustomPropertyLine --------------------------------------------- + +CustomPropertyLine::CustomPropertyLine( Window* pParent ) : + m_aNameBox ( pParent, SfxResId( SFX_CB_PROPERTY_NAME ) ), + m_aTypeBox ( pParent, SfxResId( SFX_LB_PROPERTY_TYPE ), this ), + m_aValueEdit ( pParent, SfxResId( SFX_ED_PROPERTY_VALUE ), this ), + m_aDateField ( pParent, SfxResId( SFX_FLD_DATE), this), + m_aTimeField ( pParent, SfxResId( SFX_FLD_TIME), this), + m_sDurationFormat( SfxResId( SFX_ST_DURATION_FORMAT )), + m_aDurationField( pParent, SfxResId( SFX_FLD_DURATION), this), + m_aEditButton( pParent, SfxResId( SFX_PB_EDIT ), this), + m_aYesNoButton ( pParent, SfxResId( SFX_WIN_PROPERTY_YESNO ) ), + m_aRemoveButton ( pParent, SfxResId( SFX_PB_PROPERTY_REMOVE ), this ), + m_bIsRemoved ( false ), + m_bTypeLostFocus( false ) + +{ + m_aTimeField.SetExtFormat( EXTTIMEF_24H_LONG ); + m_aDateField.SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY ); + + m_aRemoveButton.SetModeImage( SfxResId( SFX_IMG_PROPERTY_REMOVE ), BMP_COLOR_NORMAL ); + m_aRemoveButton.SetModeImage( SfxResId( SFX_IMG_PROPERTY_REMOVE_HC ), BMP_COLOR_HIGHCONTRAST ); +} + +void CustomPropertyLine::SetRemoved() +{ + DBG_ASSERT( !m_bIsRemoved, "CustomPropertyLine::SetRemoved(): line already removed" ); + m_bIsRemoved = true; + m_aNameBox.Hide(); + m_aTypeBox.Hide(); + m_aValueEdit.Hide(); + m_aDateField.Hide(); + m_aTimeField.Hide(); + m_aDurationField.Hide(); + m_aEditButton.Hide(); + m_aYesNoButton.Hide(); + m_aRemoveButton.Hide(); +} + +// class CustomPropertiesWindow ------------------------------------------ + +CustomPropertiesWindow::CustomPropertiesWindow( Window* pParent, const ResId& rResId ) : + + Window( pParent, rResId ), + m_aNameBox ( this, SfxResId( SFX_CB_PROPERTY_NAME ) ), + m_aTypeBox ( this, SfxResId( SFX_LB_PROPERTY_TYPE ) ), + m_aValueEdit ( this, SfxResId( SFX_ED_PROPERTY_VALUE ) ), + m_aDateField ( this, SfxResId( SFX_FLD_DATE) ), + m_aTimeField ( this, SfxResId( SFX_FLD_TIME) ), + m_aDurationField( this, SfxResId( SFX_FLD_DURATION) ), + m_aEditButton( this, SfxResId( SFX_PB_EDIT )), + m_aYesNoButton ( this, SfxResId( SFX_WIN_PROPERTY_YESNO ) ), + m_aRemoveButton ( this, SfxResId( SFX_PB_PROPERTY_REMOVE ) ), + m_nScrollPos (0), + m_aNumberFormatter( ::comphelper::getProcessServiceFactory(), + Application::GetSettings().GetLanguage() ) + +{ + m_aEditLoseFocusTimer.SetTimeout( 300 ); + m_aEditLoseFocusTimer.SetTimeoutHdl( LINK( this, CustomPropertiesWindow, EditTimeoutHdl ) ); + m_aBoxLoseFocusTimer.SetTimeout( 300 ); + m_aBoxLoseFocusTimer.SetTimeoutHdl( LINK( this, CustomPropertiesWindow, BoxTimeoutHdl ) ); +} + +CustomPropertiesWindow::~CustomPropertiesWindow() +{ + m_aEditLoseFocusTimer.Stop(); + m_aBoxLoseFocusTimer.Stop(); + ClearAllLines(); +} + +IMPL_LINK( CustomPropertiesWindow, TypeHdl, CustomPropertiesTypeBox*, pBox ) +{ + sal_Int64 nType = sal_Int64( (long)pBox->GetEntryData( pBox->GetSelectEntryPos() ) ); + CustomPropertyLine* pLine = pBox->GetLine(); + pLine->m_aValueEdit.Show( (CUSTOM_TYPE_TEXT == nType) || (CUSTOM_TYPE_NUMBER == nType) ); + pLine->m_aDateField.Show( (CUSTOM_TYPE_DATE == nType) || (CUSTOM_TYPE_DATETIME == nType) ); + pLine->m_aTimeField.Show( CUSTOM_TYPE_DATETIME == nType ); + pLine->m_aDurationField.Show( CUSTOM_TYPE_DURATION == nType ); + pLine->m_aEditButton.Show( CUSTOM_TYPE_DURATION == nType ); + pLine->m_aYesNoButton.Show( CUSTOM_TYPE_BOOLEAN == nType ); + //adjust positions of date and time controls + if( nType == CUSTOM_TYPE_DATE ) + { + pLine->m_aDateField.SetPosSizePixel(pLine->m_aValueEdit.GetPosPixel(), pLine->m_aValueEdit.GetSizePixel()); + } + else if( nType == CUSTOM_TYPE_DATETIME) + { + pLine->m_aDateField.SetPosSizePixel( pLine->m_aDatePos, pLine->m_aDateTimeSize ); + pLine->m_aTimeField.SetPosSizePixel(pLine->m_aTimePos, pLine->m_aDateTimeSize ); + } + + return 0; +} + +IMPL_LINK( CustomPropertiesWindow, RemoveHdl, CustomPropertiesRemoveButton*, pButton ) +{ + CustomPropertyLine* pLine = pButton->GetLine(); + std::vector< CustomPropertyLine* >::iterator pFound = + std::find( m_aCustomPropertiesLines.begin(), m_aCustomPropertiesLines.end(), pLine ); + if ( pFound != m_aCustomPropertiesLines.end() ) + { + pLine = *pFound; + pLine->SetRemoved(); + std::vector< CustomPropertyLine* >::iterator pIter = pFound + 1; + const long nDelta = GetLineHeight(); + for ( ; pIter != m_aCustomPropertiesLines.end(); ++pIter ) + { + pLine = *pIter; + if ( pLine->m_bIsRemoved ) + continue; + + Window* pWindows[] = { &pLine->m_aNameBox, &pLine->m_aTypeBox, &pLine->m_aValueEdit, + &pLine->m_aDateField, &pLine->m_aTimeField, + &pLine->m_aDurationField, &pLine->m_aEditButton, + &pLine->m_aYesNoButton, &pLine->m_aRemoveButton, NULL }; + Window** pCurrent = pWindows; + while ( *pCurrent ) + { + Point aPos = (*pCurrent)->GetPosPixel(); + aPos.Y() -= nDelta; + (*pCurrent)->SetPosPixel( aPos ); + pCurrent++; + } + } + } + + m_aRemovedHdl.Call(0); + return 0; +} + +IMPL_LINK( CustomPropertiesWindow, EditLoseFocusHdl, CustomPropertiesEdit*, pEdit ) +{ + if ( pEdit ) + { + CustomPropertyLine* pLine = pEdit->GetLine(); + if ( !pLine->m_bTypeLostFocus ) + { + m_pCurrentLine = pLine; + m_aEditLoseFocusTimer.Start(); + } + else + pLine->m_bTypeLostFocus = false; + } + return 0; +} + +IMPL_LINK( CustomPropertiesWindow, BoxLoseFocusHdl, CustomPropertiesTypeBox*, pBox ) +{ + if ( pBox ) + { + m_pCurrentLine = pBox->GetLine(); + m_aBoxLoseFocusTimer.Start(); + } + + return 0; +} + +IMPL_LINK( CustomPropertiesWindow, EditTimeoutHdl, Timer*, EMPTYARG ) +{ + ValidateLine( m_pCurrentLine, false ); + return 0; +} + +IMPL_LINK( CustomPropertiesWindow, BoxTimeoutHdl, Timer*, EMPTYARG ) +{ + ValidateLine( m_pCurrentLine, true ); + return 0; +} + +bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine* pLine ) const +{ + bool bIsValid = true; + pLine->m_bTypeLostFocus = false; + sal_Int64 nType = sal_Int64( + (long)pLine->m_aTypeBox.GetEntryData( pLine->m_aTypeBox.GetSelectEntryPos() ) ); + String sValue = pLine->m_aValueEdit.GetText(); + if ( sValue.Len() == 0 ) + return true; + + double fDummy = 0.0; + sal_uInt32 nIndex = 0xFFFFFFFF; + if ( CUSTOM_TYPE_NUMBER == nType ) + nIndex = const_cast< SvNumberFormatter& >( + m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM ); + else if ( CUSTOM_TYPE_DATE == nType ) + nIndex = const_cast< SvNumberFormatter& >( + m_aNumberFormatter).GetFormatIndex( NF_DATE_SYS_DDMMYYYY ); + + if ( nIndex != 0xFFFFFFFF ) + { + sal_uInt32 nTemp = nIndex; + bIsValid = const_cast< SvNumberFormatter& >( + m_aNumberFormatter ).IsNumberFormat( sValue, nIndex, fDummy ) != FALSE; + if ( bIsValid && nTemp != nIndex ) + // sValue is a number but the format doesn't match the index + bIsValid = false; + } + + return bIsValid; +} + +void CustomPropertiesWindow::ValidateLine( CustomPropertyLine* pLine, bool bIsFromTypeBox ) +{ + if ( !IsLineValid( pLine ) ) + { + if ( bIsFromTypeBox ) // LoseFocus of TypeBox + pLine->m_bTypeLostFocus = true; + Window* pParent = GetParent()->GetParent(); + if ( QueryBox( pParent, SfxResId( SFX_QB_WRONG_TYPE ) ).Execute() == RET_OK ) + pLine->m_aTypeBox.SelectEntryPos( m_aTypeBox.GetEntryPos( (void*)CUSTOM_TYPE_TEXT ) ); + else + pLine->m_aValueEdit.GrabFocus(); + } +} + +void CustomPropertiesWindow::InitControls( HeaderBar* pHeaderBar, const ScrollBar* pScrollBar ) +{ + DBG_ASSERT( pHeaderBar, "CustomPropertiesWindow::InitControls(): invalid headerbar" ); + DBG_ASSERT( pScrollBar, "CustomPropertiesWindow::InitControls(): invalid scrollbar" ); + + m_aNameBox.Hide(); + m_aTypeBox.Hide(); + m_aValueEdit.Hide(); + m_aDateField.Hide(); + m_aTimeField.Hide(); + m_aDurationField.Hide(); + m_aEditButton.Hide(); + m_aYesNoButton.Hide(); + m_aRemoveButton.Hide(); + + const long nOffset = 4; + const long nScrollBarWidth = pScrollBar->GetSizePixel().Width(); + const long nButtonWidth = m_aRemoveButton.GetSizePixel().Width() + nScrollBarWidth + nOffset; + long nTypeWidth = m_aTypeBox.CalcMinimumSize().Width() + ( 2 * nOffset ); + long nFullWidth = pHeaderBar->GetSizePixel().Width(); + long nItemWidth = ( nFullWidth - nTypeWidth - nButtonWidth ) / 2; + pHeaderBar->SetItemSize( HI_NAME, nItemWidth ); + pHeaderBar->SetItemSize( HI_TYPE, nTypeWidth ); + pHeaderBar->SetItemSize( HI_VALUE, nItemWidth ); + pHeaderBar->SetItemSize( HI_ACTION, nButtonWidth ); + + Window* pWindows[] = { &m_aNameBox, &m_aTypeBox, &m_aValueEdit, &m_aRemoveButton, NULL }; + Window** pCurrent = pWindows; + USHORT nPos = 0; + while ( *pCurrent ) + { + Rectangle aRect = pHeaderBar->GetItemRect( pHeaderBar->GetItemId( nPos++ ) ); + Size aSize = (*pCurrent)->GetSizePixel(); + Point aPos = (*pCurrent)->GetPosPixel(); + long nWidth = aRect.getWidth() - nOffset; + if ( *pCurrent == &m_aRemoveButton ) + nWidth -= pScrollBar->GetSizePixel().Width(); + aSize.Width() = nWidth; + aPos.X() = aRect.getX() + ( nOffset / 2 ); + (*pCurrent)->SetPosSizePixel( aPos, aSize ); + + if ( *pCurrent == &m_aValueEdit ) + { + Point aDurationPos( aPos ); + m_aDurationField.SetPosPixel( aDurationPos ); + Size aDurationSize(aSize); + aDurationSize.Width() -= (m_aEditButton.GetSizePixel().Width() + 3 ); + m_aDurationField.SetSizePixel(aDurationSize); + aDurationPos.X() = aPos.X() - m_aEditButton.GetSizePixel().Width() + aSize.Width(); + m_aEditButton.SetPosPixel(aDurationPos); + aSize = m_aYesNoButton.GetSizePixel(); + aPos = m_aYesNoButton.GetPosPixel(); + aSize.Width() = nWidth; + aPos.X() = aRect.getX() + ( nOffset / 2 ); + m_aYesNoButton.SetPosSizePixel( aPos, aSize ); + aSize.Width() /= 2; + aSize.Width() -= 2; + m_aDateField.SetPosSizePixel( aPos, aSize ); + aPos.X() += aSize.Width() + 4; + m_aTimeField.SetPosSizePixel( aPos, aSize ); + } + + pCurrent++; + } + + m_nLineHeight = + ( m_aRemoveButton.GetPosPixel().Y() * 2 ) + m_aRemoveButton.GetSizePixel().Height(); +} + +USHORT CustomPropertiesWindow::GetVisibleLineCount() const +{ + USHORT nCount = 0; + std::vector< CustomPropertyLine* >::const_iterator pIter; + for ( pIter = m_aCustomPropertiesLines.begin(); + pIter != m_aCustomPropertiesLines.end(); ++pIter ) + { + CustomPropertyLine* pLine = *pIter; + if ( !pLine->m_bIsRemoved ) + nCount++; + } + return nCount; +} + +void CustomPropertiesWindow::AddLine( const ::rtl::OUString& sName, Any& rAny ) +{ + CustomPropertyLine* pNewLine = new CustomPropertyLine( this ); + pNewLine->m_aTypeBox.SetSelectHdl( LINK( this, CustomPropertiesWindow, TypeHdl ) ); + pNewLine->m_aRemoveButton.SetClickHdl( LINK( this, CustomPropertiesWindow, RemoveHdl ) ); + pNewLine->m_aValueEdit.SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, EditLoseFocusHdl ) ); + //add lose focus handlers of date/time fields + + pNewLine->m_aTypeBox.SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, BoxLoseFocusHdl ) ); + long nPos = GetVisibleLineCount() * GetLineHeight(); + m_aCustomPropertiesLines.push_back( pNewLine ); + Window* pWindows[] = { &m_aNameBox, &m_aTypeBox, &m_aValueEdit, + &m_aDateField, &m_aTimeField, + &m_aDurationField, &m_aEditButton, + &m_aYesNoButton, &m_aRemoveButton, NULL }; + Window* pNewWindows[] = + { &pNewLine->m_aNameBox, &pNewLine->m_aTypeBox, &pNewLine->m_aValueEdit, + &pNewLine->m_aDateField, &pNewLine->m_aTimeField, + &pNewLine->m_aDurationField, &pNewLine->m_aEditButton, + &pNewLine->m_aYesNoButton, &pNewLine->m_aRemoveButton, NULL }; + Window** pCurrent = pWindows; + Window** pNewCurrent = pNewWindows; + while ( *pCurrent ) + { + Size aSize = (*pCurrent)->GetSizePixel(); + Point aPos = (*pCurrent)->GetPosPixel(); + aPos.Y() += nPos; + aPos.Y() += m_nScrollPos; + (*pNewCurrent)->SetPosSizePixel( aPos, aSize ); + (*pNewCurrent)->Show(); + pCurrent++; + pNewCurrent++; + } + // + pNewLine->m_aDatePos = pNewLine->m_aDateField.GetPosPixel(); + pNewLine->m_aTimePos = pNewLine->m_aTimeField.GetPosPixel(); + pNewLine->m_aDateTimeSize = pNewLine->m_aDateField.GetSizePixel(); + + double nTmpValue = 0; + bool bTmpValue = false; + ::rtl::OUString sTmpValue; + util::DateTime aTmpDateTime; + util::Date aTmpDate; + util::Duration aTmpDuration; + SvtSysLocale aSysLocale; + const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData(); + pNewLine->m_aNameBox.SetText( sName ); + sal_Int32 nType = CUSTOM_TYPE_UNKNOWN; + String sValue; + + if ( rAny >>= nTmpValue ) + { + sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM ); + m_aNumberFormatter.GetInputLineString( nTmpValue, nIndex, sValue ); + pNewLine->m_aValueEdit.SetText( sValue ); + nType = CUSTOM_TYPE_NUMBER; + } + else if ( rAny >>= bTmpValue ) + { + sValue = ( bTmpValue ? rLocaleWrapper.getTrueWord() : rLocaleWrapper.getFalseWord() ); + nType = CUSTOM_TYPE_BOOLEAN; + } + else if ( rAny >>= sTmpValue ) + { + pNewLine->m_aValueEdit.SetText( sTmpValue ); + nType = CUSTOM_TYPE_TEXT; + } + else if ( rAny >>= aTmpDate ) + { + nType = CUSTOM_TYPE_DATE; + pNewLine->m_aDateField.SetDate( Date( aTmpDate.Day, aTmpDate.Month, aTmpDate.Year ) ); + + } + else if ( rAny >>= aTmpDuration ) + { + nType = CUSTOM_TYPE_DURATION; + pNewLine->m_aDurationField.SetDuration( aTmpDuration ); + } + else if ( rAny >>= aTmpDateTime ) + { + pNewLine->m_aDateField.SetDate( Date( aTmpDateTime.Day, aTmpDateTime.Month, aTmpDateTime.Year ) ); + pNewLine->m_aTimeField.SetTime( Time( aTmpDateTime.Hours, aTmpDateTime.Minutes, aTmpDateTime.Seconds, aTmpDateTime.HundredthSeconds ) ); + + nType = CUSTOM_TYPE_DATETIME; + } + + if ( nType != CUSTOM_TYPE_UNKNOWN ) + { + if ( CUSTOM_TYPE_BOOLEAN == nType ) + { + if ( bTmpValue ) + pNewLine->m_aYesNoButton.CheckYes(); + else + pNewLine->m_aYesNoButton.CheckNo(); + } + pNewLine->m_aTypeBox.SelectEntryPos( m_aTypeBox.GetEntryPos( (void*)nType ) ); + } + + TypeHdl( &pNewLine->m_aTypeBox ); + pNewLine->m_aNameBox.GrabFocus(); +} + +bool CustomPropertiesWindow::AreAllLinesValid() const +{ + bool bRet = true; + std::vector< CustomPropertyLine* >::const_iterator pIter; + for ( pIter = m_aCustomPropertiesLines.begin(); + pIter != m_aCustomPropertiesLines.end(); ++pIter ) + { + CustomPropertyLine* pLine = *pIter; + if ( !IsLineValid( pLine ) ) + { + bRet = false; + break; + } + } + + return bRet; +} + +void CustomPropertiesWindow::ClearAllLines() +{ + std::vector< CustomPropertyLine* >::iterator pIter; + for ( pIter = m_aCustomPropertiesLines.begin(); + pIter != m_aCustomPropertiesLines.end(); ++pIter ) + { + CustomPropertyLine* pLine = *pIter; + pLine->SetRemoved(); + delete pLine; + } + m_aCustomPropertiesLines.clear(); + m_nScrollPos = 0; +} + +void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos ) +{ + m_nScrollPos += nNewPos; + std::vector< CustomPropertyLine* >::iterator pIter; + for ( pIter = m_aCustomPropertiesLines.begin(); + pIter != m_aCustomPropertiesLines.end(); ++pIter ) + { + CustomPropertyLine* pLine = *pIter; + if ( pLine->m_bIsRemoved ) + continue; + + Window* pWindows[] = { &pLine->m_aNameBox, &pLine->m_aTypeBox, &pLine->m_aValueEdit, &pLine->m_aDurationField, + &pLine->m_aYesNoButton, &pLine->m_aRemoveButton, NULL }; + Window** pCurrent = pWindows; + while ( *pCurrent ) + { + Point aPos = (*pCurrent)->GetPosPixel(); + aPos.Y() += nNewPos; + (*pCurrent)->SetPosPixel( aPos ); + pCurrent++; + } + } +} + +bool CustomPropertiesWindow::DoesCustomPropertyExist( const String& rName ) const +{ + bool bRet = false; + std::vector< CustomPropertyLine* >::const_iterator pIter; + for ( pIter = m_aCustomPropertiesLines.begin(); + pIter != m_aCustomPropertiesLines.end(); ++pIter ) + { + CustomPropertyLine* pLine = *pIter; + if ( !pLine->m_bIsRemoved && pLine->m_aNameBox.GetText() == rName ) + { + bRet = true; + break; + } + } + + return bRet; +} + +Sequence< beans::PropertyValue > CustomPropertiesWindow::GetCustomProperties() const +{ + Sequence< beans::PropertyValue > aPropertiesSeq( m_aCustomPropertiesLines.size() ); + sal_Int32 i = 0; + std::vector< CustomPropertyLine* >::const_iterator pIter; + for ( pIter = m_aCustomPropertiesLines.begin(); + pIter != m_aCustomPropertiesLines.end(); ++pIter, ++i ) + { + CustomPropertyLine* pLine = *pIter; + if ( pLine->m_bIsRemoved ) + continue; + + String sPropertyName = pLine->m_aNameBox.GetText(); + if ( sPropertyName.Len() > 0 ) + { + aPropertiesSeq[i].Name = sPropertyName; + sal_Int64 nType = sal_Int64( + (long)pLine->m_aTypeBox.GetEntryData( pLine->m_aTypeBox.GetSelectEntryPos() ) ); + if ( CUSTOM_TYPE_NUMBER == nType ) + { + double nValue = 0; + sal_uInt32 nIndex = const_cast< SvNumberFormatter& >( + m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM ); + BOOL bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ). + IsNumberFormat( pLine->m_aValueEdit.GetText(), nIndex, nValue ); + if ( bIsNum ) + aPropertiesSeq[i].Value <<= makeAny( nValue ); + } + else if ( CUSTOM_TYPE_BOOLEAN == nType ) + { + bool bValue = pLine->m_aYesNoButton.IsYesChecked(); + aPropertiesSeq[i].Value <<= makeAny( bValue ); + } + else if ( CUSTOM_TYPE_DATETIME == nType ) + { + Date aTmpDate = pLine->m_aDateField.GetDate(); + Time aTmpTime = pLine->m_aTimeField.GetTime(); + util::DateTime aDateTime(aTmpTime.Get100Sec(), aTmpTime.GetSec(), aTmpTime.GetMin(), aTmpTime.GetHour(), + aTmpDate.GetDay(), aTmpDate.GetMonth(), aTmpDate.GetYear() ); + aPropertiesSeq[i].Value <<= aDateTime; + } + else if ( CUSTOM_TYPE_DURATION == nType ) + { + aPropertiesSeq[i].Value <<= pLine->m_aDurationField.GetDuration(); + } + else if ( CUSTOM_TYPE_DATE == nType ) + { + Date aTmpDate = pLine->m_aDateField.GetDate(); + util::Date aDate(aTmpDate.GetDay(), aTmpDate.GetMonth(), aTmpDate.GetYear()); + aPropertiesSeq[i].Value <<= aDate; + + } + else + { + ::rtl::OUString sValue( pLine->m_aValueEdit.GetText() ); + aPropertiesSeq[i].Value <<= makeAny( sValue ); + } + } + } + + return aPropertiesSeq; +} + +// class CustomPropertiesControl ----------------------------------------- + +CustomPropertiesControl::CustomPropertiesControl( Window* pParent, const ResId& rResId ) : + + Control( pParent, rResId ), + + m_aHeaderBar ( this, WB_BUTTONSTYLE | WB_BOTTOMBORDER ), + m_aPropertiesWin( this, ResId( WIN_PROPERTIES, *rResId.GetResMgr() ) ), + m_aVertScroll ( this, ResId( SB_VERTICAL, *rResId.GetResMgr() ) ), + + m_bIsInitialized( false ), + m_nThumbPos ( 0 ) + +{ + m_aPropertiesWin.SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); + m_aVertScroll.EnableDrag(); + m_aVertScroll.Show(); + long nWidth = GetOutputSizePixel().Width(); + m_aHeaderBar.SetPosSizePixel( Point(), Size( nWidth, m_aVertScroll.GetPosPixel().Y() ) ); + const HeaderBarItemBits nHeadBits = HIB_VCENTER | HIB_FIXED | HIB_FIXEDPOS | HIB_LEFT; + nWidth = nWidth / 4; + ResMgr* pResMgr = rResId.GetResMgr(); + m_aHeaderBar.InsertItem( HI_NAME, String( ResId( STR_HEADER_NAME, *pResMgr ) ), nWidth, nHeadBits ); + m_aHeaderBar.InsertItem( HI_TYPE, String( ResId( STR_HEADER_TYPE, *pResMgr ) ), nWidth, nHeadBits ); + m_aHeaderBar.InsertItem( HI_VALUE, String( ResId( STR_HEADER_VALUE, *pResMgr ) ), nWidth, nHeadBits ); + m_aHeaderBar.InsertItem( HI_ACTION, String( ResId( STR_HEADER_ACTION, *pResMgr ) ), nWidth, nHeadBits ); + m_aHeaderBar.Show(); + + FreeResource(); + + XubString sTEST = m_aHeaderBar.GetItemText( HI_NAME ); + + m_aPropertiesWin.InitControls( &m_aHeaderBar, &m_aVertScroll ); + m_aPropertiesWin.SetRemovedHdl( LINK( this, CustomPropertiesControl, RemovedHdl ) ); + + m_aVertScroll.SetRangeMin( 0 ); + sal_Int32 nScrollOffset = m_aPropertiesWin.GetLineHeight(); + sal_Int32 nVisibleEntries = m_aPropertiesWin.GetSizePixel().Height() / nScrollOffset; + m_aVertScroll.SetRangeMax( nVisibleEntries ); + m_aVertScroll.SetPageSize( nVisibleEntries - 1 ); + m_aVertScroll.SetVisibleSize( nVisibleEntries ); + + Point aPos = m_aHeaderBar.GetPosPixel(); + Size aSize = m_aHeaderBar.GetSizePixel(); + aPos = m_aVertScroll.GetPosPixel(); + aSize = m_aVertScroll.GetSizePixel(); + + Link aScrollLink = LINK( this, CustomPropertiesControl, ScrollHdl ); + m_aVertScroll.SetScrollHdl( aScrollLink ); +// m_aVertScroll.SetEndScrollHdl( aScrollLink ); +} + +CustomPropertiesControl::~CustomPropertiesControl() +{ +} + +void CustomPropertiesControl::Initialize() +{ +} + +IMPL_LINK( CustomPropertiesControl, ScrollHdl, ScrollBar*, pScrollBar ) +{ + sal_Int32 nOffset = m_aPropertiesWin.GetLineHeight(); + nOffset *= ( m_nThumbPos - pScrollBar->GetThumbPos() ); + m_nThumbPos = pScrollBar->GetThumbPos(); + m_aPropertiesWin.DoScroll( nOffset ); + return 0; +} + +IMPL_LINK( CustomPropertiesControl, RemovedHdl, void*, EMPTYARG ) +{ + m_aVertScroll.SetRangeMax( m_aPropertiesWin.GetVisibleLineCount() + 1 ); + if ( m_aPropertiesWin.GetOutputSizePixel().Height() < m_aPropertiesWin.GetVisibleLineCount() * m_aPropertiesWin.GetLineHeight() ) + m_aVertScroll.DoScrollAction ( SCROLL_LINEUP ); + return 0; +} + +void CustomPropertiesControl::AddLine( const ::rtl::OUString& sName, Any& rAny, bool bInteractive ) +{ + m_aPropertiesWin.AddLine( sName, rAny ); + m_aVertScroll.SetRangeMax( m_aPropertiesWin.GetVisibleLineCount() + 1 ); + if ( bInteractive && m_aPropertiesWin.GetOutputSizePixel().Height() < m_aPropertiesWin.GetVisibleLineCount() * m_aPropertiesWin.GetLineHeight() ) + m_aVertScroll.DoScroll( m_aPropertiesWin.GetVisibleLineCount() + 1 ); +} + +// class SfxCustomPropertiesPage ----------------------------------------- + +SfxCustomPropertiesPage::SfxCustomPropertiesPage( Window* pParent, const SfxItemSet& rItemSet ) : + + SfxTabPage( pParent, SfxResId( TP_CUSTOMPROPERTIES ), rItemSet ), + m_aPropertiesFT ( this, SfxResId( FT_PROPERTIES ) ), + m_aPropertiesCtrl ( this, SfxResId( CTRL_PROPERTIES ) ), + m_aAddBtn ( this, SfxResId( BTN_ADD ) ) + +{ + FreeResource(); + + m_aAddBtn.SetClickHdl( LINK( this, SfxCustomPropertiesPage, AddHdl ) ); +} + +IMPL_LINK( SfxCustomPropertiesPage, AddHdl, PushButton*, EMPTYARG ) +{ + Any aAny; + m_aPropertiesCtrl.AddLine( ::rtl::OUString(), aAny, true ); + return 0; +} + +BOOL SfxCustomPropertiesPage::FillItemSet( SfxItemSet& rSet ) +{ + BOOL bModified = FALSE; + const SfxPoolItem* pItem = NULL; + SfxDocumentInfoItem* pInfo = NULL; + bool bMustDelete = false; + + if ( GetTabDialog() && GetTabDialog()->GetExampleSet() ) + { + if( SFX_ITEM_SET != + GetTabDialog()->GetExampleSet()->GetItemState( SID_DOCINFO, TRUE, &pItem ) ) + pInfo = &( SfxDocumentInfoItem& )rSet.Get( SID_DOCINFO ); + else + { + bMustDelete = true; + pInfo = new SfxDocumentInfoItem( *( const SfxDocumentInfoItem* ) pItem ); + } + } + + if ( pInfo ) + { + pInfo->ClearCustomProperties(); + Sequence< beans::PropertyValue > aPropertySeq = m_aPropertiesCtrl.GetCustomProperties(); + sal_Int32 i = 0, nCount = aPropertySeq.getLength(); + for ( ; i < nCount; ++i ) + { + if ( aPropertySeq[i].Name.getLength() > 0 ) + pInfo->AddCustomProperty( aPropertySeq[i].Name, aPropertySeq[i].Value ); + } + } + + bModified = TRUE; //!!! + if ( bModified ) + rSet.Put( *pInfo ); + if ( bMustDelete ) + delete pInfo; + return bModified; +} + +void SfxCustomPropertiesPage::Reset( const SfxItemSet& rItemSet ) +{ + m_aPropertiesCtrl.ClearAllLines(); + const SfxDocumentInfoItem* pInfoItem = &(const SfxDocumentInfoItem &)rItemSet.Get(SID_DOCINFO); + std::vector< CustomProperty* > aCustomProps = pInfoItem->GetCustomProperties(); + for ( sal_uInt32 i = 0; i < aCustomProps.size(); i++ ) + { + m_aPropertiesCtrl.AddLine( aCustomProps[i]->m_sName, aCustomProps[i]->m_aValue, false ); + } +} + +int SfxCustomPropertiesPage::DeactivatePage( SfxItemSet* /*pSet*/ ) +{ + int nRet = LEAVE_PAGE; + if ( !m_aPropertiesCtrl.AreAllLinesValid() ) + nRet = KEEP_PAGE; + return nRet; +} + +SfxTabPage* SfxCustomPropertiesPage::Create( Window* pParent, const SfxItemSet& rItemSet ) +{ + return new SfxCustomPropertiesPage( pParent, rItemSet ); +} + diff --git a/sfx2/source/dialog/dinfdlg.hrc b/sfx2/source/dialog/dinfdlg.hrc new file mode 100644 index 000000000000..5453e3606026 --- /dev/null +++ b/sfx2/source/dialog/dinfdlg.hrc @@ -0,0 +1,177 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _DINFDLG_HRC +#define _DINFDLG_HRC + +#include <svtools/controldims.hrc> + +// const ----------------------------------------------------------------- + +#define CUSTOM_TYPE_UNKNOWN 0 +#define CUSTOM_TYPE_TEXT 1 +#define CUSTOM_TYPE_NUMBER 2 +#define CUSTOM_TYPE_DATE 3 +#define CUSTOM_TYPE_BOOLEAN 4 +#define CUSTOM_TYPE_DURATION 5 +#define CUSTOM_TYPE_DATETIME 6 + +// 4 TP_DOCINFORELOAD +#define PAGE_WIDTH 260 +#define WIDTH_CTRL_SPACE 3 +#define WIDTH_0 10 +#define WIDTH_1 48 +#define WIDTH_2 28 +#define WIDTH_FT1 (WIDTH_1 - WIDTH_CTRL_SPACE) +#define COL_0 6 +#define COL_1 (COL_0+WIDTH_0) +#define COL_2 (COL_1+WIDTH_1) +#define COL_3 (COL_2+WIDTH_2) +#define COL_4 (COL_3+WIDTH_CTRL_SPACE) +#define COL_7 (PAGE_WIDTH-2*WIDTH_0) +#define COL_6 (COL_7-WIDTH_0) +#define COL_5 (COL_6-WIDTH_CTRL_SPACE) +#define COL_LAST COL_7 + +#define ROWDIFF_FT_EDTFLD ((RSC_CD_TEXTBOX_HEIGHT-RSC_CD_FIXEDTEXT_HEIGHT)/2) +#define ROW_0 6 +#define ROW_1 (ROW_0+16) +#define ROW_2 (ROW_1+13) +#define ROW_3 (ROW_2+16) +#define ROW_4 (ROW_3+13) +#define ROW_5 (ROW_4+16) +#define ROW_6 (ROW_5+16) + +// defines --------------------------------------------------------------- + +#define FT_FILE 1 +#define FT_FILE_VAL 2 +#define FT_CHANGE 3 +#define FT_CHANGE_VAL 4 +#define FT_CREATE 7 +#define FT_CREATE_VAL 8 +#define FT_TITLE 9 +#define ED_TITLE 10 +#define FT_THEMA 11 +#define ED_THEMA 12 +#define FT_KEYWORDS 13 +#define ED_KEYWORDS 14 +#define FT_INFO1 15 +#define ED_INFO1 16 +#define FT_INFO2 17 +#define ED_INFO2 18 +#define FT_INFO3 19 +#define ED_INFO3 20 +#define FT_INFO4 21 +#define ED_INFO4 22 +#define FT_COMMENT 23 +#define ED_COMMENT 24 +#define GB_INFO 30 +#define FT_TEMPL 32 +#define FT_TEMPL_VAL 33 +#define BTN_EDITLABEL 34 +#define FT_TIMELOG 35 +#define FT_TIMELOG_VAL 36 +#define FT_DOCNO 37 +#define FT_DOCNO_VAL 38 +#define FT_URL 43 +#define ED_URL 44 +#define CB_FILE_READONLY 48 +#define CB_USE_USERDATA 49 +#define BMP_FILE_1 50 +#define ED_FILE_NAME 51 +#define FL_FILE_1 52 +#define FT_FILE_TYP 53 +#define FT_FILE_SHOW_TYP 54 +#define FT_FILE_SIZE 55 +#define FT_FILE_SHOW_SIZE 56 +#define FL_FILE_2 57 +#define FT_PRINT 58 +#define FT_PRINT_VAL 59 +#define STR_UNKNOWNSIZE 60 +#define FL_FILE_3 61 +#define BTN_DELETE 62 + +#define RB_NOAUTOUPDATE 63 +#define RB_RELOADUPDATE 64 +#define RB_FORWARDUPDATE 65 +#define FT_EVERY 66 +#define ED_RELOAD 67 +#define FT_RELOADSECS 68 +#define FT_AFTER 69 +#define ED_FORWARD 70 +#define FT_FORWARDSECS 71 +#define FT_FRAME 72 +#define CB_FRAME 73 +#define PB_BROWSEURL 74 +#define STR_FORWARD_ERRMSSG 75 + +#define FT_SIGNED 76 +#define FT_SIGNED_VAL 77 +#define STR_MULTSIGNED 78 +#define BTN_SIGNATURE 79 + +#define WIN_PROPERTIES 90 +#define SB_VERTICAL 91 +#define FT_PROPERTIES 92 +#define CTRL_PROPERTIES 93 +#define BTN_ADD 94 +#define LB_PROPNAME 95 +#define ED_PROPVALUE 96 +#define RB_PROPYES 96 +#define RB_PROPNO 97 +#define LB_PROPTYPE 98 +#define PB_REMOVEPROP 99 +#define RB_PROPERTY_YES 100 +#define RB_PROPERTY_NO 101 + +#define STR_HEADER_NAME 90 +#define STR_HEADER_TYPE 91 +#define STR_HEADER_VALUE 92 +#define STR_HEADER_ACTION 93 + +#define PB_OK 100 +#define PB_CANCEL 101 +#define PB_HELP 102 +#define CB_NEGATIVE 103 +#define FT_YEAR 104 +#define ED_YEAR 105 +#define FT_MONTH 106 +#define ED_MONTH 107 +#define FT_DAY 108 +#define ED_DAY 109 +#define FT_HOUR 110 +#define ED_HOUR 111 +#define FT_MINUTE 112 +#define ED_MINUTE 113 +#define FT_SECOND 114 +#define ED_SECOND 115 +#define FT_MSECOND 116 +#define ED_MSECOND 117 +#define FL_DURATION 118 + +#endif + diff --git a/sfx2/source/dialog/dinfdlg.src b/sfx2/source/dialog/dinfdlg.src new file mode 100755 index 000000000000..53b0f35685cb --- /dev/null +++ b/sfx2/source/dialog/dinfdlg.src @@ -0,0 +1,906 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + // include --------------------------------------------------------------- + +#include "sfx2/sfx.hrc" +#include "helpid.hrc" +#include "sfxlocal.hrc" +#include "dinfdlg.hrc" +#include "dialog.hrc" + + // TP_DOCINFODESC -------------------------------------------------------- +String STR_SFX_NEWOFFICEDOC +{ + Text [ en-US ] = "%PRODUCTNAME document" ; +}; + +TabPage TP_DOCINFODESC +{ + HelpId = HID_DOCINFODESC ; + Hide = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + FixedText FT_TITLE + { + Pos = MAP_APPFONT ( 6 , 7 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Title" ; + }; + Edit ED_TITLE + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 6 ) ; + Size = MAP_APPFONT ( 184 , RSC_CD_TEXTBOX_HEIGHT ) ; + TabStop = TRUE ; + Left = TRUE ; + }; + FixedText FT_THEMA + { + Pos = MAP_APPFONT ( 6 , 22 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Subject" ; + }; + Edit ED_THEMA + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 21 ) ; + Size = MAP_APPFONT ( 184 , RSC_CD_TEXTBOX_HEIGHT ) ; + TabStop = TRUE ; + Left = TRUE ; + }; + FixedText FT_KEYWORDS + { + Pos = MAP_APPFONT ( 6 , 37 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Keywords" ; + }; + Edit ED_KEYWORDS + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 36 ) ; + Size = MAP_APPFONT ( 184 , RSC_CD_TEXTBOX_HEIGHT ) ; + TabStop = TRUE ; + Left = TRUE ; + }; + FixedText FT_COMMENT + { + Pos = MAP_APPFONT ( 6 , 52 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Comments" ; + }; + MultiLineEdit ED_COMMENT + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 51 ) ; + Size = MAP_APPFONT ( 184 , 128 ) ; + IgnoreTab = TRUE ; + Left = TRUE ; + VScroll = TRUE ; + }; +}; + + // TP_DOCINFODOC --------------------------------------------------------- + +TabPage TP_DOCINFODOC +{ + HelpId = HID_DOCINFODOC ; + Hide = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + FixedImage BMP_FILE_1 + { + Pos = MAP_APPFONT ( 6 , 7 ) ; + Size = MAP_APPFONT ( 20 , 20 ) ; + }; + Edit ED_FILE_NAME + { + Pos = MAP_APPFONT ( 54 , 12 ) ; + Size = MAP_APPFONT ( 200 , RSC_CD_TEXTBOX_HEIGHT ) ; + Border = TRUE ; + }; + FixedLine FL_FILE_1 + { + Pos = MAP_APPFONT ( 6 , 31 ) ; + Size = MAP_APPFONT ( 248 , 1 ) ; + }; + FixedText FT_FILE_TYP + { + Pos = MAP_APPFONT ( 6 , 37 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Type:" ; + }; + Edit FT_FILE_SHOW_TYP + { + Pos = MAP_APPFONT ( 78 , 37 ) ; + Size = MAP_APPFONT ( 106 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + CheckBox CB_FILE_READONLY + { + Pos = MAP_APPFONT ( 163 , 37 ) ; + Size = MAP_APPFONT ( 91 , RSC_CD_CHECKBOX_HEIGHT ) ; + Text [ en-US ] = "~Read-only" ; + }; + FixedText FT_FILE + { + Pos = MAP_APPFONT ( 6 , 49 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Location:" ; + }; + Edit FT_FILE_VAL + { + Pos = MAP_APPFONT ( 78 , 49 ) ; + Size = MAP_APPFONT ( 176 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + FixedText FT_FILE_SIZE + { + Pos = MAP_APPFONT ( 6 , 61 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Size:" ; + }; + Edit FT_FILE_SHOW_SIZE + { + Pos = MAP_APPFONT ( 78 , 61 ) ; + Size = MAP_APPFONT ( 176 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + FixedLine FL_FILE_2 + { + Pos = MAP_APPFONT ( 6 , 74 ) ; + Size = MAP_APPFONT ( 248 , 1 ) ; + }; + FixedText FT_CREATE + { + Pos = MAP_APPFONT ( 6 , 80 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Created:" ; + }; + Edit FT_CREATE_VAL + { + Pos = MAP_APPFONT ( 78 , 80 ) ; + Size = MAP_APPFONT ( 176 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + FixedText FT_CHANGE + { + Pos = MAP_APPFONT ( 6 , 92 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Modified:" ; + }; + Edit FT_CHANGE_VAL + { + Pos = MAP_APPFONT ( 78 , 92 ) ; + Size = MAP_APPFONT ( 176 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + FixedText FT_SIGNED + { + Pos = MAP_APPFONT ( 6 , 104 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Digitally signed:" ; + }; + Edit FT_SIGNED_VAL + { + Pos = MAP_APPFONT ( 78 , 104 ) ; + Size = MAP_APPFONT ( 123 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + PushButton BTN_SIGNATURE + { + Pos = MAP_APPFONT ( 204 , 101 ) ; + Size = MAP_APPFONT ( RSC_CD_PUSHBUTTON_WIDTH , RSC_CD_PUSHBUTTON_HEIGHT ) ; + Text [ en-US ] = "Digital Signature..."; + }; + String STR_MULTSIGNED + { + Text [ en-US ] = "Multiply signed document" ; + }; + FixedText FT_PRINT + { + Pos = MAP_APPFONT ( 6 , 116 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Last printed:" ; + }; + Edit FT_PRINT_VAL + { + Pos = MAP_APPFONT ( 78 , 116 ) ; + Size = MAP_APPFONT ( 176 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + FixedText FT_TIMELOG + { + Pos = MAP_APPFONT ( 6 , 128 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Total editing time:" ; + }; + Edit FT_TIMELOG_VAL + { + Pos = MAP_APPFONT ( 78 , 128 ) ; + Size = MAP_APPFONT ( 30 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + FixedText FT_DOCNO + { + Pos = MAP_APPFONT ( 6 , 140 ) ; + Size = MAP_APPFONT ( 70 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Revision number:" ; + }; + Edit FT_DOCNO_VAL + { + Pos = MAP_APPFONT ( 78 , 140 ) ; + Size = MAP_APPFONT ( 30 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + PushButton BTN_DELETE + { + Pos = MAP_APPFONT ( 204 , 150 ) ; + Size = MAP_APPFONT ( RSC_CD_PUSHBUTTON_WIDTH , RSC_CD_PUSHBUTTON_HEIGHT ) ; + Hide = TRUE; + Text [ en-US ] = "Reset"; + }; + CheckBox CB_USE_USERDATA + { + Pos = MAP_APPFONT ( 6 , 152 ) ; + Size = MAP_APPFONT ( 192 , RSC_CD_CHECKBOX_HEIGHT ) ; + Hide = TRUE; + Text [ en-US ] = "~Apply user data"; + }; + FixedLine FL_FILE_3 + { + Pos = MAP_APPFONT ( 5 , 167 ) ; + Size = MAP_APPFONT ( 248 , 1 ) ; + }; + FixedText FT_TEMPL + { + Pos = MAP_APPFONT ( 5 , 172 ) ; + Size = MAP_APPFONT ( 45 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "Template:" ; + }; + Edit FT_TEMPL_VAL + { + Pos = MAP_APPFONT ( 78 , 172 ) ; + Size = MAP_APPFONT ( 180 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + }; + String STR_UNKNOWNSIZE + { + Text [ en-US ] = "unknown" ; + }; +}; + + // TP_DOCINFOUSER -------------------------------------------------------- + +TabPage TP_DOCINFOUSER +{ + HelpId = HID_DOCINFOUSER ; + Hide = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + FixedText FT_INFO1 + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + }; + Edit ED_INFO1 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 17 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_TEXTBOX_HEIGHT ) ; + Left = TRUE ; + }; + FixedText FT_INFO2 + { + Pos = MAP_APPFONT ( 6 , 32 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + }; + Edit ED_INFO2 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 43 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_TEXTBOX_HEIGHT ) ; + Left = TRUE ; + }; + FixedText FT_INFO3 + { + Pos = MAP_APPFONT ( 6 , 58 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + }; + Edit ED_INFO3 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 69 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_TEXTBOX_HEIGHT ) ; + Left = TRUE ; + }; + FixedText FT_INFO4 + { + Pos = MAP_APPFONT ( 6 , 84 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + }; + Edit ED_INFO4 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 95 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_TEXTBOX_HEIGHT ) ; + Left = TRUE ; + }; + PushButton BTN_EDITLABEL + { + Pos = MAP_APPFONT ( 194 , 165 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_PUSHBUTTON_HEIGHT ) ; + Text [ en-US ] = "~Info fields..." ; + }; +}; + + // TP_DOCINFOUSER -------------------------------------------------------- + +TabPage TP_DOCINFORELOAD +{ + HelpId = HID_DOCINFORELOAD ; + Hide = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + RadioButton RB_NOAUTOUPDATE + { + TabStop = TRUE ; + Pos = MAP_APPFONT( COL_0 , ROW_0 ) ; + Size = MAP_APPFONT( COL_7 - COL_1 , RSC_CD_RADIOBUTTON_HEIGHT ) ; + Text [ en-US ] = "Do not refresh automatically" ; + }; + + RadioButton RB_RELOADUPDATE + { + TabStop = TRUE ; + Pos = MAP_APPFONT( COL_0, ROW_1 ) ; + Size = MAP_APPFONT( COL_7 - COL_1, RSC_CD_RADIOBUTTON_HEIGHT ) ; + Text [ en-US ] = "Refresh this document" ; + }; + FixedText FT_EVERY + { + Pos = MAP_APPFONT ( COL_1 , ROW_2 ) ; + Size = MAP_APPFONT ( WIDTH_FT1 , RSC_CD_RADIOBUTTON_HEIGHT ) ; + Text [ en-US ] = "every" ; + }; + NumericField ED_RELOAD + { + Border = TRUE ; + Pos = MAP_APPFONT ( COL_2 , ROW_2 - ROWDIFF_FT_EDTFLD ) ; + Size = MAP_APPFONT ( WIDTH_2 , RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 1 ; + First = 1 ; + Last = 60 ; + SpinSize = 1 ; + Value = 60 ; + }; + FixedText FT_RELOADSECS + { + Pos = MAP_APPFONT ( COL_4 , ROW_2 ) ; + Size = MAP_APPFONT ( COL_7 - COL_4 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "seconds" ; + }; + + RadioButton RB_FORWARDUPDATE + { + TabStop = TRUE ; + Pos = MAP_APPFONT( COL_0, ROW_3 ) ; + Size = MAP_APPFONT( COL_7 - COL_1, RSC_CD_RADIOBUTTON_HEIGHT ) ; + Text [ en-US ] = "Redirect from this document" ; + }; + FixedText FT_AFTER + { + Pos = MAP_APPFONT ( COL_1 , ROW_4 ) ; + Size = MAP_APPFONT ( WIDTH_FT1 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "after" ; + }; + NumericField ED_FORWARD + { + Border = TRUE ; + Pos = MAP_APPFONT ( COL_2 , ROW_4 - ROWDIFF_FT_EDTFLD ) ; + Size = MAP_APPFONT ( WIDTH_2 , RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 1 ; + First = 1 ; + Last = 60 ; + SpinSize = 1 ; + Value = 5 ; + }; + FixedText FT_FORWARDSECS + { + Pos = MAP_APPFONT ( COL_4 , ROW_4 ) ; + Size = MAP_APPFONT ( COL_7 - COL_4 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "seconds" ; + }; + FixedText FT_URL + { + Pos = MAP_APPFONT ( COL_1 , ROW_5 ) ; + Size = MAP_APPFONT ( WIDTH_FT1 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "to URL" ; + }; + Edit ED_URL + { + Border = TRUE ; + Pos = MAP_APPFONT ( COL_2 , ROW_5 - ROWDIFF_FT_EDTFLD ) ; + Size = MAP_APPFONT ( COL_5 - COL_2 , RSC_CD_TEXTBOX_HEIGHT ) ; + }; + PushButton PB_BROWSEURL + { + Pos = MAP_APPFONT ( COL_6 , ROW_5 - ROWDIFF_FT_EDTFLD ) ; + Size = MAP_APPFONT ( COL_7 - COL_6 , RSC_CD_PUSHBUTTON_HEIGHT ) ; + Text = "..." ; + }; + FixedText FT_FRAME + { + Pos = MAP_APPFONT ( COL_1 , ROW_6 ) ; + Size = MAP_APPFONT ( WIDTH_FT1 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "to frame" ; + }; + ComboBox CB_FRAME + { + Pos = MAP_APPFONT ( COL_2 , ROW_6 - ROWDIFF_FT_EDTFLD ) ; + Size = MAP_APPFONT ( COL_7 - COL_2 , RSC_CD_DROPDOWN_HEIGHT * 10 ) ; + DropDown = TRUE ; + }; + String STR_FORWARD_ERRMSSG + { + Text [ en-US ] = "If you select the option \"%PLACEHOLDER%\", you must enter a URL." ; + }; + +}; + +// TP_CUSTOMPROPERTIES --------------------------------------------------- + +TabPage TP_CUSTOMPROPERTIES +{ + HelpId = HID_TP_CUSTOMPROPERTIES ; + Hide = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + FixedText FT_PROPERTIES + { + Pos = MAP_APPFONT ( 6 , 7 ) ; + Size = MAP_APPFONT ( 248 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Properties" ; + }; + Control CTRL_PROPERTIES + { + HelpId = HID_CTRL_CUSTOMPROPERTIES; + Pos = MAP_APPFONT ( 6 , 18 ) ; + Size = MAP_APPFONT ( 248 , 141 ) ; + Border = TRUE; + DialogControl = TRUE; + //OutputSize = TRUE ; + Window WIN_PROPERTIES + { + OutputSize = TRUE ; + Pos = MAP_APPFONT ( 0 , 10 ) ; + Size = MAP_APPFONT ( 240 , 134 ) ; + DialogControl = TRUE; + }; + ScrollBar SB_VERTICAL + { + Pos = MAP_APPFONT ( 238 , 10 ) ; + Size = MAP_APPFONT ( 8 , 129 ) ; + VScroll = TRUE; + }; + String STR_HEADER_NAME + { + Text [ en-US ] = "Name" ; + }; + String STR_HEADER_TYPE + { + Text [ en-US ] = "Type" ; + }; + String STR_HEADER_VALUE + { + Text [ en-US ] = "Value" ; + }; + String STR_HEADER_ACTION + { + Text [ en-US ] = "" ; + }; + }; + PushButton BTN_ADD + { + Pos = MAP_APPFONT( 204 , 165 ); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + Text [ en-US ] = "~Add"; + }; +}; + +ComboBox SFX_CB_PROPERTY_NAME +{ + Pos = MAP_APPFONT ( 0 , 2 ) ; + Size = MAP_APPFONT ( 60 , 72 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + AutoSize = TRUE ; + AutoHScroll = TRUE ; + DDExtraWidth = TRUE ; + QuickHelpText [ en-US ] = "Property Name" ; + StringList [ en-US ] = + { + "Checked by"; + "Client"; + "Date completed"; + "Department"; + "Destinations"; + "Disposition"; + "Division"; + "Document number"; + "Editor"; + "E-Mail"; + "Forward to"; + "Group"; + "Info"; + "Language"; + "Mailstop"; + "Matter"; + "Office"; + "Owner"; + "Project"; + "Publisher"; + "Purpose"; + "Received from"; + "Recorded by"; + "Recorded date"; + "Reference"; + "Source"; + "Status"; + "Telephone number"; + "Typist"; + "URL"; + }; +}; +ListBox SFX_LB_PROPERTY_TYPE +{ + Pos = MAP_APPFONT ( 63 , 2 ) ; + Size = MAP_APPFONT ( 60 , 80 ) ; + DropDown = TRUE; + Border = TRUE; + CurPos = 0; + StringList [ en-US ] = + { + < "Text" ; CUSTOM_TYPE_TEXT ; > ; + < "DateTime" ; CUSTOM_TYPE_DATETIME ; > ; + < "Date" ; CUSTOM_TYPE_DATE ; > ; + < "Duration" ; CUSTOM_TYPE_DURATION ; > ; + < "Number" ; CUSTOM_TYPE_NUMBER ; > ; + < "Yes or no" ; CUSTOM_TYPE_BOOLEAN ; > ; + }; +}; +Edit SFX_ED_PROPERTY_VALUE +{ + Border = TRUE ; + Pos = MAP_APPFONT ( 127 , 2 ) ; + Size = MAP_APPFONT ( 61 , RSC_CD_TEXTBOX_HEIGHT ) ; + TabStop = TRUE ; + Left = TRUE ; +}; +DateField SFX_FLD_DATE +{ + Border = TRUE ; + Pos = MAP_APPFONT ( 127 , 2 ) ; + Size = MAP_APPFONT ( 29 , RSC_CD_TEXTBOX_HEIGHT ) ; + TabStop = TRUE ; + Left = TRUE ; + Spin = TRUE; +}; +TimeField SFX_FLD_TIME +{ + Border = TRUE ; + Pos = MAP_APPFONT ( 159 , 2 ) ; + Size = MAP_APPFONT ( 29 , RSC_CD_TEXTBOX_HEIGHT ) ; + TabStop = TRUE ; + Left = TRUE ; + Spin = TRUE; +}; + +Edit SFX_FLD_DURATION +{ + Readonly = TRUE; + Border = TRUE ; + Pos = MAP_APPFONT ( 159 , 2 ) ; + Size = MAP_APPFONT ( 61 - RSC_CD_TEXTBOX_HEIGHT - 2, RSC_CD_TEXTBOX_HEIGHT ) ; + TabStop = TRUE ; +}; +PushButton SFX_PB_EDIT +{ + Pos = MAP_APPFONT ( 159 , 2 ) ; + Size = MAP_APPFONT ( RSC_CD_TEXTBOX_HEIGHT , RSC_CD_TEXTBOX_HEIGHT ) ; + Text = "..."; +}; +String SFX_ST_DURATION_FORMAT +{ + Text [en-US] = " Y: %1 M: %2 D: %3 H: %4 M: %5 S: %6"; +}; + +Control SFX_WIN_PROPERTY_YESNO +{ + HelpId = HID_CTRL_CUSTOMPROPS_YES_NO; + OutputSize = TRUE ; + Pos = MAP_APPFONT ( 127 , 2 ) ; + Size = MAP_APPFONT ( 61 , RSC_CD_TEXTBOX_HEIGHT ) ; + Border = TRUE ; + DialogControl = TRUE ; + RadioButton RB_PROPERTY_YES + { + TabStop = TRUE ; + Pos = MAP_APPFONT( 1 , 1 ) ; + Size = MAP_APPFONT( 28 , RSC_CD_RADIOBUTTON_HEIGHT ) ; + Text [ en-US ] = "Yes" ; + }; + RadioButton RB_PROPERTY_NO + { + TabStop = TRUE ; + Pos = MAP_APPFONT( 32 , 1 ) ; + Size = MAP_APPFONT( 29 , RSC_CD_RADIOBUTTON_HEIGHT ) ; + Text [ en-US ] = "No" ; + }; +}; + +ImageButton SFX_PB_PROPERTY_REMOVE +{ + Pos = MAP_APPFONT( 190 , 1 ); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_HEIGHT, RSC_CD_PUSHBUTTON_HEIGHT ); + QuickHelpText [ en-US ] = "Remove Property" ; +}; +Image SFX_IMG_PROPERTY_REMOVE +{ + ImageBitmap = Bitmap { File = "deleterow.bmp" ; }; + MaskColor = Color { Red=0xffff; Green=0x0000; Blue=0xffff; }; +}; +Image SFX_IMG_PROPERTY_REMOVE_HC +{ + ImageBitmap = Bitmap { File = "deleterow_h.bmp" ; }; + MaskColor = Color { Red=0xffff; Green=0x0000; Blue=0xffff; }; +}; + +QueryBox SFX_QB_WRONG_TYPE +{ + Buttons = WB_OK_CANCEL ; + DefButton = WB_DEF_OK ; + Message [ en-US ] = "The value entered does not match the specified type.\nThe value will be stored as text." ; +}; + +TabDialog SID_DOCINFO +{ + OutputSize = TRUE ; + SVLook = TRUE ; + Moveable = TRUE ; + Text [ en-US ] = "Properties of " ; + TabControl 1 + { + SVLook = TRUE ; + PageList = + { + PageItem + { + Identifier = TP_DOCINFODOC ; + Text [ en-US ] = "General" ; + }; + PageItem + { + Identifier = TP_DOCINFODESC ; + Text [ en-US ] = "Description" ; + }; + PageItem + { + Identifier = TP_CUSTOMPROPERTIES ; + Text [ en-US ] = "Custom Properties" ; + }; + PageItem + { + Identifier = TP_DOCINFORELOAD ; + Text [ en-US ] = "Internet" ; + }; + PageItem + { + Identifier = TP_DOCINFOSECURITY ; + Text [ en-US ] = "Security" ; + }; + }; + }; +}; + +ModalDialog RID_EDIT_DURATIONS +{ + HelpId = HID_DLG_CUSTOMPROPS_DURATION; + OutputSize = TRUE ; + Size = MAP_APPFONT ( 176 , 140 ) ; + Text [ en-US ] = "Edit Duration" ; + Moveable = TRUE ; + OKButton PB_OK + { + Pos = MAP_APPFONT ( 120 , 7 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + DefButton = TRUE; + }; + CancelButton PB_CANCEL + { + Pos = MAP_APPFONT ( 120 , 24 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; + HelpButton PB_HELP + { + Pos = MAP_APPFONT ( 120 , 48 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; + FixedLine FL_DURATION + { + Pos = MAP_APPFONT ( 6 , 8 ) ; + Size = MAP_APPFONT ( 108 , 8 ) ; + Text [ en-US ] = "Duration" ; + }; + CheckBox CB_NEGATIVE + { + Pos = MAP_APPFONT ( 6 , 21 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Text [ en-US ] = "~Negative" ; + }; + FixedText FT_YEAR + { + Pos = MAP_APPFONT ( 6 , 38 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Years" ; + }; + NumericField ED_YEAR + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 36 ) ; + Size = MAP_APPFONT ( 40, RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 0 ; + First = 1 ; + Last = 100 ; + SpinSize = 1 ; + Value = 0 ; + }; + FixedText FT_MONTH + { + Pos = MAP_APPFONT ( 6 , 52 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Months" ; + }; + NumericField ED_MONTH + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 50 ) ; + Size = MAP_APPFONT ( 40, RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 0 ; + First = 1 ; + Last = 100 ; + SpinSize = 1 ; + Value = 0 ; + }; + FixedText FT_DAY + { + Pos = MAP_APPFONT ( 6 , 66 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Days" ; + }; + NumericField ED_DAY + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 64 ) ; + Size = MAP_APPFONT ( 40, RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 0 ; + First = 1 ; + Last = 100 ; + SpinSize = 1 ; + Value = 0 ; + }; + FixedText FT_HOUR + { + Pos = MAP_APPFONT ( 6 , 80 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "H~ours" ; + }; + NumericField ED_HOUR + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 78 ) ; + Size = MAP_APPFONT ( 40, RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 0 ; + First = 1 ; + Last = 100 ; + SpinSize = 1 ; + Value = 0 ; + }; + FixedText FT_MINUTE + { + Pos = MAP_APPFONT ( 6 , 94 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "Min~utes" ; + }; + NumericField ED_MINUTE + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70, 92) ; + Size = MAP_APPFONT ( 40, RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 0 ; + First = 1 ; + Last = 100 ; + SpinSize = 1 ; + Value = 0 ; + }; + FixedText FT_SECOND + { + Pos = MAP_APPFONT ( 6, 108 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "~Seconds" ; + }; + NumericField ED_SECOND + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 106 ) ; + Size = MAP_APPFONT ( 40, RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 0 ; + First = 1 ; + Last = 100 ; + SpinSize = 1 ; + Value = 0 ; + }; + FixedText FT_MSECOND + { + Pos = MAP_APPFONT ( 6 , 122 ) ; + Size = MAP_APPFONT ( 60 , RSC_CD_FIXEDTEXT_HEIGHT ) ; + Left = TRUE ; + Text [ en-US ] = "Millise~conds" ; + }; + NumericField ED_MSECOND + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 120 ) ; + Size = MAP_APPFONT ( 40, RSC_CD_TEXTBOX_HEIGHT ) ; + Repeat = TRUE ; + Spin = TRUE ; + Minimum = 0 ; + First = 1 ; + Last = 1000 ; + SpinSize = 1 ; + Value = 0 ; + }; + + + +}; diff --git a/sfx2/source/dialog/dinfedt.cxx b/sfx2/source/dialog/dinfedt.cxx new file mode 100644 index 000000000000..85f9f955e355 --- /dev/null +++ b/sfx2/source/dialog/dinfedt.cxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#ifndef GCC +#endif + +#include "dinfedt.hxx" +#include "sfxresid.hxx" + +#include <sfx2/sfx.hrc> +#include "dinfedt.hrc" + +// class InfoEdit_Impl --------------------------------------------------- + +void InfoEdit_Impl::KeyInput( const KeyEvent& rKEvent ) +{ + if ( rKEvent.GetCharCode() != '~' ) + Edit::KeyInput( rKEvent ); +} + +// class SfxDocInfoEditDlg ----------------------------------------------- + +SfxDocInfoEditDlg::SfxDocInfoEditDlg( Window* pParent ) : + + ModalDialog( pParent, SfxResId( DLG_DOCINFO_EDT ) ), + + aInfoFL ( this, SfxResId( FL_INFO ) ), + aInfo1ED ( this, SfxResId( ED_INFO1 ) ), + aInfo2ED ( this, SfxResId( ED_INFO2 ) ), + aInfo3ED ( this, SfxResId( ED_INFO3 ) ), + aInfo4ED ( this, SfxResId( ED_INFO4 ) ), + aOkBT ( this, SfxResId( BT_OK ) ), + aCancelBT ( this, SfxResId( BT_CANCEL ) ), + aHelpBtn ( this, SfxResId( BTN_HELP ) ) + +{ + FreeResource(); +} + diff --git a/sfx2/source/dialog/dinfedt.hrc b/sfx2/source/dialog/dinfedt.hrc new file mode 100644 index 000000000000..ef52362af2cb --- /dev/null +++ b/sfx2/source/dialog/dinfedt.hrc @@ -0,0 +1,38 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#define BT_OK 1 +#define BT_CANCEL 2 +#define BTN_HELP 3 +#define FT_INFO1 4 +#define ED_INFO1 5 +#define FT_INFO2 6 +#define ED_INFO2 7 +#define FT_INFO3 8 +#define ED_INFO3 9 +#define FT_INFO4 10 +#define ED_INFO4 11 +#define FL_INFO 12 diff --git a/sfx2/source/dialog/dinfedt.src b/sfx2/source/dialog/dinfedt.src new file mode 100644 index 000000000000..7f4875487536 --- /dev/null +++ b/sfx2/source/dialog/dinfedt.src @@ -0,0 +1,121 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <sfx2/sfx.hrc> +#include "helpid.hrc" +#include "dinfedt.hrc" + +ModalDialog DLG_DOCINFO_EDT +{ + HelpId = HID_DOCINFO_EDT ; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 166 , 79 ) ; + Text [ en-US ] = "Edit Field Names" ; + Moveable = TRUE ; + FixedLine FL_INFO + { + Pos = MAP_APPFONT ( 6 , 3 ) ; + Size = MAP_APPFONT ( 98 , 8 ) ; + Text [ en-US ] = "Names" ; + }; + Edit ED_INFO1 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 12 , 14 ) ; + Size = MAP_APPFONT ( 86 , 12 ) ; + }; + Edit ED_INFO2 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 12 , 29 ) ; + Size = MAP_APPFONT ( 86 , 12 ) ; + }; + Edit ED_INFO3 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 12 , 44 ) ; + Size = MAP_APPFONT ( 86 , 12 ) ; + }; + Edit ED_INFO4 + { + Border = TRUE ; + Pos = MAP_APPFONT ( 12 , 59 ) ; + Size = MAP_APPFONT ( 86 , 12 ) ; + }; + OKButton BT_OK + { + Pos = MAP_APPFONT ( 110 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton BT_CANCEL + { + Pos = MAP_APPFONT ( 110 , 23 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + HelpButton BTN_HELP + { + Pos = MAP_APPFONT ( 110 , 43 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/dockwin.cxx b/sfx2/source/dialog/dockwin.cxx new file mode 100644 index 000000000000..7b4e4289a49c --- /dev/null +++ b/sfx2/source/dialog/dockwin.cxx @@ -0,0 +1,1994 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <svl/eitem.hxx> +#include <vcl/decoview.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <rtl/instance.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <comphelper/processfactory.hxx> + +#include <sfx2/dockwin.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include "workwin.hxx" +#include "splitwin.hxx" +#include <sfx2/viewsh.hxx> +#include "sfxhelp.hxx" +#include <sfx2/objsh.hxx> + +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/container/XNameAccess.hpp> + +#define MAX_TOGGLEAREA_WIDTH 20 +#define MAX_TOGGLEAREA_HEIGHT 20 + +using namespace ::com::sun::star; + +// implemented in 'sfx2/source/appl/childwin.cxx' +extern sal_Bool GetPosSizeFromString( const String& rStr, Point& rPos, Size& rSize ); +extern sal_Bool GetSplitSizeFromString( const String& rStr, Size& rSize ); + +// If you want to change the number you also have to: +// - Add new slot ids to sfxsids.hrc +// - Add new slots to frmslots.sdi +// - Add new slot definitions to sfx.sdi +static const int NUM_OF_DOCKINGWINDOWS = 10; + +class SfxTitleDockingWindow; +class SfxTitleDockingWindow : public SfxDockingWindow +{ + Window* m_pWrappedWindow; + USHORT m_nID; + +public: + SfxTitleDockingWindow( + SfxBindings* pBindings , + SfxChildWindow* pChildWin , + Window* pParent , + WinBits nBits, + USHORT nID); + virtual ~SfxTitleDockingWindow(); + + Window* GetWrappedWindow() const { return m_pWrappedWindow; } + void SetWrappedWindow(Window* const pWindow); + + virtual void StateChanged( StateChangedType nType ); + virtual long Notify( NotifyEvent& rNEvt ); + virtual void Resize(); + virtual void Resizing( Size& rSize ); + virtual BOOL Close(); +}; + +namespace +{ + struct WindowState + { + ::rtl::OUString sTitle; + }; +} + +static uno::WeakReference< container::XNameAccess > m_xWindowStateConfiguration; +static uno::WeakReference< frame::XModuleManager > m_xModuleManager; + +static bool lcl_getWindowState( const uno::Reference< container::XNameAccess >& xWindowStateMgr, const ::rtl::OUString& rResourceURL, WindowState& rWindowState ) +{ + bool bResult = false; + + try + { + uno::Any a; + uno::Sequence< beans::PropertyValue > aWindowState; + a = xWindowStateMgr->getByName( rResourceURL ); + if ( a >>= aWindowState ) + { + for ( sal_Int32 n = 0; n < aWindowState.getLength(); n++ ) + { + if ( aWindowState[n].Name.equalsAscii( "UIName" )) + { + aWindowState[n].Value >>= rWindowState.sTitle; + } + } + } + + bResult = true; + } + catch ( container::NoSuchElementException& ) + { + bResult = false; + } + + return bResult; +} + +SfxDockingWrapper::SfxDockingWrapper( Window* pParentWnd , + USHORT nId , + SfxBindings* pBindings , + SfxChildWinInfo* pInfo ) + : SfxChildWindow( pParentWnd , nId ) +{ + uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + const rtl::OUString aDockWindowResourceURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/dockingwindow/" )); + + SfxTitleDockingWindow* pTitleDockWindow = new SfxTitleDockingWindow( pBindings, this, pParentWnd, + WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE, nId); + pWindow = pTitleDockWindow; + eChildAlignment = SFX_ALIGN_NOALIGNMENT; + + // Use factory manager to retrieve XWindow factory. That can be used to instanciate + // the real window factory. + uno::Reference< lang::XSingleComponentFactory > xFactoryMgr( + xServiceManager->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ui.WindowContentFactoryManager"))), + uno::UNO_QUERY ); + + if (xFactoryMgr.is()) + { + SfxDispatcher* pDispatcher = pBindings->GetDispatcher(); + uno::Reference< frame::XFrame > xFrame( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY ); + uno::Sequence< uno::Any > aArgs(2); + beans::PropertyValue aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aPropValue.Value = uno::makeAny( xFrame ); + aArgs[0] <<= aPropValue; + aPropValue.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ResourceURL" )); + + // create a resource URL from the nId provided by the sfx2 + ::rtl::OUString aResourceURL( aDockWindowResourceURL ); + aResourceURL += ::rtl::OUString::valueOf(sal_Int32(nId)); + aPropValue.Value = uno::makeAny( aResourceURL ); + aArgs[1] <<= aPropValue; + + uno::Reference< awt::XWindow > xWindow; + try + { + uno::Reference< beans::XPropertySet > xProps( xServiceManager, uno::UNO_QUERY ); + uno::Reference< uno::XComponentContext > xContext; + + if ( xProps.is() ) + xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + if ( xContext.is() ) + { + xWindow = uno::Reference< awt::XWindow>( + xFactoryMgr->createInstanceWithArgumentsAndContext( aArgs, xContext ), + uno::UNO_QUERY ); + } + + uno::Reference< frame::XModuleManager > xModuleManager( m_xModuleManager ); + if ( !xModuleManager.is() ) + { + xModuleManager = uno::Reference< frame::XModuleManager >( + xServiceManager->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ))), + uno::UNO_QUERY ); + m_xModuleManager = xModuleManager; + } + + uno::Reference< container::XNameAccess > xWindowStateConfiguration( m_xWindowStateConfiguration ); + if ( !xWindowStateConfiguration.is() ) + { + xWindowStateConfiguration = uno::Reference< container::XNameAccess >( + xServiceManager->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.WindowStateConfiguration" ))), + uno::UNO_QUERY ); + m_xWindowStateConfiguration = xWindowStateConfiguration; + } + + ::rtl::OUString sModuleIdentifier = xModuleManager->identify( xFrame ); + + uno::Reference< container::XNameAccess > xModuleWindowState( + xWindowStateConfiguration->getByName( sModuleIdentifier ), + uno::UNO_QUERY ); + if ( xModuleWindowState.is() ) + { + WindowState aDockWinState; + if ( lcl_getWindowState( xModuleWindowState, aResourceURL, aDockWinState )) + pTitleDockWindow->SetText( aDockWinState.sTitle ); + } + } + catch ( beans::UnknownPropertyException& ) + { + } + catch ( uno::RuntimeException& ) + { + } + catch ( uno::Exception& ) + { + } + + Window* pContentWindow = VCLUnoHelper::GetWindow(xWindow); + if ( pContentWindow ) + pContentWindow->SetStyle( pContentWindow->GetStyle() | WB_DIALOGCONTROL | WB_CHILDDLGCTRL ); + pTitleDockWindow->SetWrappedWindow(pContentWindow); + } + + pWindow->SetOutputSizePixel( Size( 270, 240 ) ); + + ( ( SfxDockingWindow* ) pWindow )->Initialize( pInfo ); + SetHideNotDelete( TRUE ); +} + +SfxChildWindow* SfxDockingWrapper::CreateImpl( +Window *pParent, sal_uInt16 nId, SfxBindings *pBindings, SfxChildWinInfo* pInfo ) +{ + SfxChildWindow *pWin = new SfxDockingWrapper(pParent, nId, pBindings, pInfo); return pWin; +} + +sal_uInt16 SfxDockingWrapper::GetChildWindowId () +{ + DBG_ASSERT( false, "This method shouldn't be called!" ); + return 0; +} + +void SfxDockingWrapper::RegisterChildWindow (sal_Bool bVis, SfxModule *pMod, sal_uInt16 nFlags) +{ + // pre-register a couple of docking windows + for (int i=0; i < NUM_OF_DOCKINGWINDOWS; i++ ) + { + USHORT nID = USHORT(SID_DOCKWIN_START+i); + SfxChildWinFactory *pFact = new SfxChildWinFactory( SfxDockingWrapper::CreateImpl, nID, 0xffff ); + pFact->aInfo.nFlags |= nFlags; + pFact->aInfo.bVisible = bVis; + SfxChildWindow::RegisterChildWindow(pMod, pFact); + } +} + +SfxChildWinInfo SfxDockingWrapper::GetInfo() const +{ + SfxChildWinInfo aInfo = SfxChildWindow::GetInfo(); + ((SfxDockingWindow*)GetWindow())->FillInfo( aInfo ); + return aInfo; +}; + +SfxTitleDockingWindow::SfxTitleDockingWindow( SfxBindings* pBind , + SfxChildWindow* pChildWin , + Window* pParent , + WinBits nBits, + USHORT nID ) : + SfxDockingWindow( pBind , + pChildWin , + pParent , + nBits ), + m_pWrappedWindow(0), + m_nID(nID) +{ +} + +SfxTitleDockingWindow::~SfxTitleDockingWindow() +{ + delete m_pWrappedWindow; +} + +void SfxTitleDockingWindow::SetWrappedWindow( Window* const pWindow ) +{ + m_pWrappedWindow = pWindow; + if (m_pWrappedWindow) + { + m_pWrappedWindow->SetParent(this); + m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() ); + m_pWrappedWindow->Show(); + } +} + +long SfxTitleDockingWindow::Notify( NotifyEvent& rNEvt ) +{ + return SfxDockingWindow::Notify( rNEvt ); +} + +void SfxTitleDockingWindow::StateChanged( StateChangedType nType ) +{ + if ( nType == STATE_CHANGE_INITSHOW ) + { + Window* pWindow = GetWrappedWindow(); + if ( pWindow ) + { + pWindow->SetSizePixel( GetOutputSizePixel() ); + pWindow->Show(); + } + } + + SfxDockingWindow::StateChanged(nType); +} + +void SfxTitleDockingWindow::Resize() +{ + SfxDockingWindow::Resize(); + if (m_pWrappedWindow) + m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() ); +} + +void SfxTitleDockingWindow::Resizing( Size &rSize ) +{ + SfxDockingWindow::Resizing( rSize ); + if (m_pWrappedWindow) + m_pWrappedWindow->SetSizePixel( GetOutputSizePixel() ); +} + +BOOL SfxTitleDockingWindow::Close() +{ + return SfxDockingWindow::Close(); +} + +namespace +{ + struct ChildrenRegisteredMap : public rtl::Static< bool, ChildrenRegisteredMap > {}; +} + +static bool lcl_checkDockingWindowID( USHORT nID ) +{ + if (nID < SID_DOCKWIN_START || nID >= USHORT(SID_DOCKWIN_START+NUM_OF_DOCKINGWINDOWS)) + return false; + else + return true; +} + +static SfxWorkWindow* lcl_getWorkWindowFromXFrame( const uno::Reference< frame::XFrame >& rFrame ) +{ + // We need to find the corresponding SfxFrame of our XFrame + SfxFrame* pFrame = SfxFrame::GetFirst(); + SfxFrame* pXFrame = 0; + while ( pFrame ) + { + uno::Reference< frame::XFrame > xViewShellFrame( pFrame->GetFrameInterface() ); + if ( xViewShellFrame == rFrame ) + { + pXFrame = pFrame; + break; + } + else + pFrame = SfxFrame::GetNext( *pFrame ); + } + + // If we have a SfxFrame we can retrieve the work window (Sfx layout manager for docking windows) + if ( pXFrame ) + return pXFrame->GetWorkWindow_Impl(); + else + return NULL; +} + +/* + Factory function used by the framework layout manager to "create" a docking window with a special name. + The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot range located + in sfxsids.hrc (currently SID_DOCKWIN_START = 9800). +*/ +void SAL_CALL SfxDockingWindowFactory( const uno::Reference< frame::XFrame >& rFrame, const rtl::OUString& rDockingWindowName ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + USHORT nID = USHORT(rDockingWindowName.toInt32()); + + // Check the range of the provided ID otherwise nothing will happen + if ( lcl_checkDockingWindowID( nID )) + { + SfxWorkWindow* pWorkWindow = lcl_getWorkWindowFromXFrame( rFrame ); + if ( pWorkWindow ) + { + SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID); + if ( !pChildWindow ) + { + // Register window at the workwindow child window list + pWorkWindow->SetChildWindow_Impl( nID, true, false ); + } + } + } +} + +/* + Function used by the framework layout manager to determine the visibility state of a docking window with + a special name. The string rDockingWindowName MUST BE a valid ID! The ID is pre-defined by a certain slot + range located in sfxsids.hrc (currently SID_DOCKWIN_START = 9800). +*/ +bool SAL_CALL IsDockingWindowVisible( const uno::Reference< frame::XFrame >& rFrame, const rtl::OUString& rDockingWindowName ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + USHORT nID = USHORT(rDockingWindowName.toInt32()); + + // Check the range of the provided ID otherwise nothing will happen + if ( lcl_checkDockingWindowID( nID )) + { + SfxWorkWindow* pWorkWindow = lcl_getWorkWindowFromXFrame( rFrame ); + if ( pWorkWindow ) + { + SfxChildWindow* pChildWindow = pWorkWindow->GetChildWindow_Impl(nID); + if ( pChildWindow ) + return true; + } + } + + return false; +} + +class SfxDockingWindow_Impl +{ +friend class SfxDockingWindow; + + SfxChildAlignment eLastAlignment; + SfxChildAlignment eDockAlignment; + BOOL bConstructed; + Size aMinSize; + SfxSplitWindow* pSplitWin; + BOOL bSplitable; +// BOOL bAutoHide; + Timer aMoveTimer; + + // Folgende members sind nur in der Zeit von StartDocking bis EndDocking + // g"ultig: + BOOL bEndDocked; + Size aSplitSize; + long nHorizontalSize; + long nVerticalSize; + USHORT nLine; + USHORT nPos; + USHORT nDockLine; + USHORT nDockPos; + BOOL bNewLine; + BOOL bDockingPrevented; + ByteString aWinState; + + SfxChildAlignment GetLastAlignment() const + { return eLastAlignment; } + void SetLastAlignment(SfxChildAlignment eAlign) + { eLastAlignment = eAlign; } + SfxChildAlignment GetDockAlignment() const + { return eDockAlignment; } + void SetDockAlignment(SfxChildAlignment eAlign) + { eDockAlignment = eAlign; } +}; + +//------------------------------------------------------------------------- + +void SfxDockingWindow::Resize() + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse DockingWindow merkt sich ggf. eine + ver"anderte FloatingSize. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + auch SfxDockingWindow::Resize() gerufen werden. +*/ +{ + DockingWindow::Resize(); + Invalidate(); + if ( pImp->bConstructed && pMgr ) + { + if ( IsFloatingMode() ) + { + // start timer for saving window status information + pImp->aMoveTimer.Start(); + } + else + { + Size aSize( GetSizePixel() ); + switch ( pImp->GetDockAlignment() ) + { + case SFX_ALIGN_LEFT: + case SFX_ALIGN_FIRSTLEFT: + case SFX_ALIGN_LASTLEFT: + case SFX_ALIGN_RIGHT: + case SFX_ALIGN_FIRSTRIGHT: + case SFX_ALIGN_LASTRIGHT: + pImp->nHorizontalSize = aSize.Width(); + pImp->aSplitSize = aSize; + break; + case SFX_ALIGN_TOP: + case SFX_ALIGN_LOWESTTOP: + case SFX_ALIGN_HIGHESTTOP: + case SFX_ALIGN_BOTTOM: + case SFX_ALIGN_HIGHESTBOTTOM: + case SFX_ALIGN_LOWESTBOTTOM: + pImp->nVerticalSize = aSize.Height(); + pImp->aSplitSize = aSize; + break; + default: + break; + } + } + } +} + +//------------------------------------------------------------------------- + +BOOL SfxDockingWindow::PrepareToggleFloatingMode() + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse DockingWindow erm"oglicht ein Eingreifen + in das Umschalten des floating mode. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + danach SfxDockingWindow::PrepareToggleFloatingMode() gerufen werden, + wenn nicht FALSE zur"uckgegeben wird. +*/ + +{ + if (!pImp->bConstructed) + return TRUE; + + if ( (Application::IsInModalMode() && IsFloatingMode()) || !pMgr ) + return FALSE; + + if ( pImp->bDockingPrevented ) + return FALSE; + + if (!IsFloatingMode()) + { + // Testen, ob FloatingMode erlaubt ist + if ( CheckAlignment(GetAlignment(),SFX_ALIGN_NOALIGNMENT) != SFX_ALIGN_NOALIGNMENT ) + return FALSE; + + if ( pImp->pSplitWin ) + { + // Das DockingWindow sitzt in einem SplitWindow und wird abgerissen + pImp->pSplitWin->RemoveWindow(this/*, FALSE*/); + pImp->pSplitWin = 0; + } + } + else if ( pMgr ) + { + pImp->aWinState = GetFloatingWindow()->GetWindowState(); + + // Testen, ob es erlaubt ist, anzudocken + if (CheckAlignment(GetAlignment(),pImp->GetLastAlignment()) == SFX_ALIGN_NOALIGNMENT) + return FALSE; + + // Testen, ob das Workwindow gerade ein Andocken erlaubt + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + if ( !pWorkWin->IsDockingAllowed() || !pWorkWin->IsInternalDockingAllowed() ) + return FALSE; + } + + return TRUE; +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::ToggleFloatingMode() + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse DockingWindow setzt die internen + Daten des SfxDockingWindow und sorgt f"ur korrektes Alignment am + parent window. + Durch PrepareToggleFloatMode und Initialize ist sichergestellt, da\s + pImp->GetLastAlignment() immer eine erlaubtes Alignment liefert. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + zuerst SfxDockingWindow::ToggleFloatingMode() gerufen werden. +*/ +{ + if ( !pImp->bConstructed || !pMgr ) + return; // Kein Handler-Aufruf + + // Altes Alignment merken und dann umschalten. + // Sv hat jetzt schon umgeschaltet, aber Alignment am SfxDockingWindow + // ist noch das alte! + // Was war ich bisher ? + SfxChildAlignment eLastAlign = GetAlignment(); + + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW; + if ( pImp->bSplitable ) + eIdent = SFX_CHILDWIN_SPLITWINDOW; + + if (IsFloatingMode()) + { + SetAlignment(SFX_ALIGN_NOALIGNMENT); + if ( pImp->aWinState.Len() ) + GetFloatingWindow()->SetWindowState( pImp->aWinState ); + else + GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() ); +/* + if ( pImp->bSplitable && !pImp->bEndDocked ) + // Wenn das Fenster vorher in einem SplitWindow lag, kommt von + // Sv kein Show + Show(); +*/ + } + else + { + if (pImp->GetDockAlignment() == eLastAlign) + { + // Wenn ToggleFloatingMode aufgerufen wurde, das DockAlignment + // aber noch unver"andert ist, mu\s das ein Toggeln durch DClick + // gewesen sein, also LastAlignment verwenden + SetAlignment (pImp->GetLastAlignment()); + if ( !pImp->bSplitable ) + SetSizePixel( CalcDockingSize(GetAlignment()) ); + } + else + { + // Toggeln wurde durch Draggen ausgel"ost + pImp->nLine = pImp->nDockLine; + pImp->nPos = pImp->nDockPos; + SetAlignment (pImp->GetDockAlignment()); + } + + if ( pImp->bSplitable ) + { + // Das DockingWindow kommt jetzt in ein SplitWindow + pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment()); + + // Das LastAlignment ist jetzt immer noch das zuletzt angedockte + SfxSplitWindow *pSplit = pWorkWin->GetSplitWindow_Impl(pImp->GetLastAlignment()); + + DBG_ASSERT( pSplit, "LastAlignment kann nicht stimmen!" ); + if ( pSplit && pSplit != pImp->pSplitWin ) + pSplit->ReleaseWindow_Impl(this); + if ( pImp->GetDockAlignment() == eLastAlign ) + pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize ); + else + pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize, pImp->nLine, pImp->nPos, pImp->bNewLine ); + if ( !pImp->pSplitWin->IsFadeIn() ) + pImp->pSplitWin->FadeIn(); + } + } + + // altes Alignment festhalten f"ur n"achstes Togglen; erst jetzt setzen + // wg. Abmelden beim SplitWindow! + pImp->SetLastAlignment(eLastAlign); + + // DockAlignment zur"ucksetzen, falls noch EndDocking gerufen wird + pImp->SetDockAlignment(GetAlignment()); + + // SfxChildWindow korrekt andocken bzw. entdocken + if ( pMgr ) + pWorkWin->ConfigChild_Impl( eIdent, SFX_TOGGLEFLOATMODE, pMgr->GetType() ); +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::StartDocking() + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse DockingWindow holt vom parent window + das innere und "au\sere docking rectangle. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + am Ende SfxDockingWindow::StartDocking() gerufen werden. +*/ +{ + if ( !pImp->bConstructed || !pMgr ) + return; + SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW; + if ( pImp->bSplitable ) + eIdent = SFX_CHILDWIN_SPLITWINDOW; + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + pWorkWin->ConfigChild_Impl( eIdent, SFX_SETDOCKINGRECTS, pMgr->GetType() ); + pImp->SetDockAlignment(GetAlignment()); + + if ( pImp->pSplitWin ) + { + // Die aktuellen Docking-Daten besorgen + pImp->pSplitWin->GetWindowPos(this, pImp->nLine, pImp->nPos); + pImp->nDockLine = pImp->nLine; + pImp->nDockPos = pImp->nPos; + pImp->bNewLine = FALSE; + } +} + +//------------------------------------------------------------------------- + +BOOL SfxDockingWindow::Docking( const Point& rPos, Rectangle& rRect ) + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse DockingWindow berechnet das aktuelle + tracking rectangle. Dazu benutzt sie die Methode CalcAlignment(rPos,rRect), + deren Verhalten von abgeleiteten Klassen beeinflu\st werden kann (s.u.). + Diese Methode sollte nach M"oglichkeit nicht "uberschrieben werden. +*/ +{ + if ( Application::IsInModalMode() ) + return TRUE; + + if ( !pImp->bConstructed || !pMgr ) + { + rRect.SetSize( Size() ); + return IsFloatingMode(); + } + + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + if ( pImp->bDockingPrevented || !pWorkWin->IsInternalDockingAllowed() ) + return FALSE; + + BOOL bFloatMode = FALSE; + + if ( GetOuterRect().IsInside( rPos ) && !IsDockingPrevented() ) + { + // Maus innerhalb OuterRect : Alignment und Rectangle berechnen + SfxChildAlignment eAlign = CalcAlignment(rPos, rRect); + if (eAlign == SFX_ALIGN_NOALIGNMENT) + bFloatMode = TRUE; + pImp->SetDockAlignment(eAlign); + } + else + { + // Maus nicht innerhalb OuterRect : muss FloatingWindow sein + // Ist das erlaubt ? + if (CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT) != SFX_ALIGN_NOALIGNMENT) + return FALSE; + bFloatMode = TRUE; + if ( SFX_ALIGN_NOALIGNMENT != pImp->GetDockAlignment() ) + { + // wg. SV-Bug darf rRect nur ver"andert werden, wenn sich das + // Alignment "andert ! + pImp->SetDockAlignment(SFX_ALIGN_NOALIGNMENT); + rRect.SetSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT)); + } + } + + if ( !pImp->bSplitable ) + { + // Bei individuell angedocktem Window wird die Position durch das + // Alignment und die docking rects festgelegt. + Size aSize = rRect.GetSize(); + Point aPos; + + switch ( pImp->GetDockAlignment() ) + { + case SFX_ALIGN_LEFT: + case SFX_ALIGN_FIRSTLEFT: + case SFX_ALIGN_LASTLEFT: + aPos = aInnerRect.TopLeft(); + if ( pImp->GetDockAlignment() == GetAlignment() ) + aPos.X() -= aSize.Width(); + break; + + case SFX_ALIGN_TOP: + case SFX_ALIGN_LOWESTTOP: + case SFX_ALIGN_HIGHESTTOP: + aPos = Point(aOuterRect.Left(), aInnerRect.Top()); + if ( pImp->GetDockAlignment() == GetAlignment() ) + aPos.Y() -= aSize.Height(); + break; + + case SFX_ALIGN_RIGHT: + case SFX_ALIGN_FIRSTRIGHT: + case SFX_ALIGN_LASTRIGHT: + aPos = Point(aInnerRect.Right() - rRect.GetSize().Width(), + aInnerRect.Top()); + if ( pImp->GetDockAlignment() == GetAlignment() ) + aPos.X() += aSize.Width(); + break; + + case SFX_ALIGN_BOTTOM: + case SFX_ALIGN_HIGHESTBOTTOM: + case SFX_ALIGN_LOWESTBOTTOM: + aPos = Point(aOuterRect.Left(), + aInnerRect.Bottom() - rRect.GetSize().Height()); + if ( pImp->GetDockAlignment() == GetAlignment() ) + aPos.Y() += aSize.Height(); + break; + default: + break; + } + + rRect.SetPos(aPos); + } + + return bFloatMode; +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::EndDocking( const Rectangle& rRect, BOOL bFloatMode ) + +/* [Beschreibung] + + Diese virtuelle Methode der Klasse DockingWindow sorgt f"ur das korrekte + Alignment am parent window. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + zuerst SfxDockingWindow::EndDocking() gerufen werden. +*/ +{ + if ( !pImp->bConstructed || IsDockingCanceled() || !pMgr ) + return; + + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + BOOL bReArrange = FALSE; + SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW; + if ( pImp->bSplitable ) + { + eIdent = SFX_CHILDWIN_SPLITWINDOW; + + // Wenn sich das Alignment "andert und das Fenster befindet sich + // im angedockten Zustand in einem SplitWindow, mu\s umgemeldet werden + // Wenn neu angedockt wird, machen PrepareToggleFloatingMode() + // und ToggleFloatingMode() das Ummelden. + if ( !bFloatMode ) + bReArrange = TRUE; + } + + if ( bReArrange ) + { + if ( GetAlignment() != pImp->GetDockAlignment() ) + { + // Vor dem Show() mu\s das Ummelden passiert sein, daher kann nicht + // die Basisklasse gerufen werden + if ( IsFloatingMode() || !pImp->bSplitable ) + Show( FALSE, SHOW_NOFOCUSCHANGE ); + + // Die Gr"o\se f"urs Toggeln setzen + pImp->aSplitSize = rRect.GetSize(); + if ( IsFloatingMode() ) + { + SetFloatingMode( bFloatMode ); + if ( IsFloatingMode() || !pImp->bSplitable ) + Show( TRUE, SHOW_NOFOCUSCHANGE ); + } + else + { + pImp->pSplitWin->RemoveWindow(this,FALSE); + pImp->nLine = pImp->nDockLine; + pImp->nPos = pImp->nDockPos; + pImp->pSplitWin->ReleaseWindow_Impl(this); + pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(pImp->GetDockAlignment()); + pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize, pImp->nDockLine, pImp->nDockPos, pImp->bNewLine ); + if ( !pImp->pSplitWin->IsFadeIn() ) + pImp->pSplitWin->FadeIn(); + } + } + else if ( pImp->nLine != pImp->nDockLine || pImp->nPos != pImp->nDockPos || pImp->bNewLine ) + { + // Ich wurde innerhalb meines Splitwindows verschoben. + if ( pImp->nLine != pImp->nDockLine ) + pImp->aSplitSize = rRect.GetSize(); + pImp->pSplitWin->MoveWindow( this, pImp->aSplitSize, pImp->nDockLine, pImp->nDockPos, pImp->bNewLine ); + } + } + else + { + pImp->bEndDocked = TRUE; + DockingWindow::EndDocking(rRect, bFloatMode); + pImp->bEndDocked = FALSE; + } + + SetAlignment( IsFloatingMode() ? SFX_ALIGN_NOALIGNMENT : pImp->GetDockAlignment() ); +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::Resizing( Size& /*rSize*/ ) + +/* [Beschreibung] + + Virtuelle Methode der Klasse DockingWindow. + Hier kann das interaktive Umgr"o\sern im FloatingMode beeinflu\t werden, + z.B. indem nur diskrete Werte f"ur Breite und/oder H"ohe zugelassen werden. + Die Basisimplementation verhindert, da\s die OutputSize kleiner wird als + eine mit SetMinOutputSizePixel() gesetzte Gr"o\se. +*/ + +{ +/* + if(rSize.Width() < pImp->aMinSize.Width()) + rSize.Width() = pImp->aMinSize.Width(); + if(rSize.Height() < pImp->aMinSize.Height()) + rSize.Height() = pImp->aMinSize.Height(); +*/ +} + +//------------------------------------------------------------------------- + +SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW, + Window* pParent, WinBits nWinBits) : + DockingWindow (pParent, nWinBits), + pBindings(pBindinx), + pMgr(pCW), + pImp(NULL) + +/* [Beschreibung] + + ctor der Klasse SfxDockingWindow. Es wird ein SfxChildWindow ben"otigt, + da das Andocken im Sfx "uber SfxChildWindows realisiert wird. +*/ + +{ + ULONG nId = GetHelpId(); + if ( !nId && pCW ) + nId = pCW->GetType(); + SetHelpId( 0 ); + SetUniqueId( nId ); + + pImp = new SfxDockingWindow_Impl; + pImp->bConstructed = FALSE; + pImp->pSplitWin = 0; + pImp->bEndDocked = FALSE; + pImp->bDockingPrevented = FALSE; + + pImp->bSplitable = TRUE; +// pImp->bAutoHide = FALSE; + + // Zun"achst auf Defaults setzen; das Alignment wird in der Subklasse gesetzt + pImp->nLine = pImp->nDockLine = 0; + pImp->nPos = pImp->nDockPos = 0; + pImp->bNewLine = FALSE; + pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT); + pImp->aMoveTimer.SetTimeout(50); + pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxDockingWindow,TimerHdl)); + +// DBG_ASSERT(pMgr,"DockingWindow erfordert ein SfxChildWindow!"); +} + +//------------------------------------------------------------------------- + +SfxDockingWindow::SfxDockingWindow( SfxBindings *pBindinx, SfxChildWindow *pCW, + Window* pParent, const ResId& rResId) : + DockingWindow(pParent, rResId), + pBindings(pBindinx), + pMgr(pCW), + pImp(NULL) + +/* [Beschreibung] + + ctor der Klasse SfxDockingWindow. Es wird ein SfxChildWindow ben"otigt, + da das Andocken im Sfx "uber SfxChildWindows realisiert wird. +*/ + +{ + ULONG nId = GetHelpId(); + SetHelpId(0); + SetUniqueId( nId ); + + pImp = new SfxDockingWindow_Impl; + pImp->bConstructed = FALSE; + pImp->pSplitWin = 0; + pImp->bEndDocked = FALSE; + pImp->bDockingPrevented = FALSE; + + pImp->bSplitable = TRUE; +// pImp->bAutoHide = FALSE; + + // Zun"achst auf Defaults setzen; das Alignment wird in der Subklasse gesetzt + pImp->nLine = pImp->nDockLine = 0; + pImp->nPos = pImp->nDockPos = 0; + pImp->bNewLine = FALSE; + pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT); + pImp->aMoveTimer.SetTimeout(50); + pImp->aMoveTimer.SetTimeoutHdl(LINK(this,SfxDockingWindow,TimerHdl)); + +// DBG_ASSERT(pMgr,"DockingWindow erfordert ein SfxChildWindow!"); +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::Initialize(SfxChildWinInfo *pInfo) +/* [Beschreibung] + + Initialisierung der Klasse SfxDockingWindow "uber ein SfxChildWinInfo. + Die Initialisierung erfolgt erst in einem 2.Schritt nach dem ctor und sollte + vom ctor der abgeleiteten Klasse oder vom ctor des SfxChildWindows + aufgerufen werden. +*/ +{ + if ( !pMgr ) + { + // Bugfix #39771 + pImp->SetDockAlignment( SFX_ALIGN_NOALIGNMENT ); + pImp->bConstructed = TRUE; + return; + } + + if ( pInfo->nFlags & SFX_CHILDWIN_FORCEDOCK ) + pImp->bDockingPrevented = TRUE; + + pImp->aSplitSize = GetOutputSizePixel(); + if ( !GetFloatingSize().Width() ) + { + Size aMinSize( GetMinOutputSizePixel() ); + SetFloatingSize( pImp->aSplitSize ); + if ( pImp->aSplitSize.Width() < aMinSize.Width() ) + pImp->aSplitSize.Width() = aMinSize.Width(); + if ( pImp->aSplitSize.Height() < aMinSize.Height() ) + pImp->aSplitSize.Height() = aMinSize.Height(); + } + + sal_Bool bVertHorzRead( sal_False ); + if ( pInfo->aExtraString.Len() ) + { + // get information about alignment, split size and position in SplitWindow + String aStr; + USHORT nPos = pInfo->aExtraString.SearchAscii("AL:"); + if ( nPos != STRING_NOTFOUND ) + { + // alignment information + USHORT n1 = pInfo->aExtraString.Search('(', nPos); + if ( n1 != STRING_NOTFOUND ) + { + USHORT n2 = pInfo->aExtraString.Search(')', n1); + if ( n2 != STRING_NOTFOUND ) + { + // extract alignment information from extrastring + aStr = pInfo->aExtraString.Copy(nPos, n2 - nPos + 1); + pInfo->aExtraString.Erase(nPos, n2 - nPos + 1); + aStr.Erase(nPos, n1-nPos+1); + } + } + } + + if ( aStr.Len() ) + { + // accept window state only if alignment is also set + pImp->aWinState = pInfo->aWinState; + + // check for valid alignment + SfxChildAlignment eLocalAlignment = (SfxChildAlignment) (USHORT) aStr.ToInt32(); + if ( pImp->bDockingPrevented ) + // docking prevented, ignore old configuration and take alignment from default + aStr.Erase(); + else + SetAlignment( eLocalAlignment ); + + SfxChildAlignment eAlign = CheckAlignment(GetAlignment(),GetAlignment()); + if ( eAlign != GetAlignment() ) + { + DBG_ERROR("Invalid Alignment!"); + SetAlignment( eAlign ); + aStr.Erase(); + } + + // get last alignment (for toggeling) + nPos = aStr.Search(','); + if ( nPos != STRING_NOTFOUND ) + { + aStr.Erase(0, nPos+1); + pImp->SetLastAlignment( (SfxChildAlignment) (USHORT) aStr.ToInt32() ); + } + + nPos = aStr.Search(','); + if ( nPos != STRING_NOTFOUND ) + { + // get split size and position in SplitWindow + Point aPos; + aStr.Erase(0, nPos+1); + if ( GetPosSizeFromString( aStr, aPos, pImp->aSplitSize ) ) + { + pImp->nLine = pImp->nDockLine = (USHORT) aPos.X(); + pImp->nPos = pImp->nDockPos = (USHORT) aPos.Y(); + pImp->nVerticalSize = pImp->aSplitSize.Height(); + pImp->nHorizontalSize = pImp->aSplitSize.Width(); + if ( GetSplitSizeFromString( aStr, pImp->aSplitSize )) + bVertHorzRead = sal_True; + } + } + } + else { + DBG_ERROR( "Information is missing!" ); + } + } + + if ( !bVertHorzRead ) + { + pImp->nVerticalSize = pImp->aSplitSize.Height(); + pImp->nHorizontalSize = pImp->aSplitSize.Width(); + } + + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + if ( GetAlignment() != SFX_ALIGN_NOALIGNMENT ) + { + // check if SfxWorkWindow is able to allow docking at its border + if ( + !pWorkWin->IsDockingAllowed() || + !pWorkWin->IsInternalDockingAllowed() || + ( (GetFloatStyle() & WB_STANDALONE) && Application::IsInModalMode()) ) + { + SetAlignment( SFX_ALIGN_NOALIGNMENT ); + } + } + + // detect floating mode + // toggeling mode will not execute code in handlers, because pImp->bConstructed is not set yet + BOOL bFloatMode = IsFloatingMode(); + if ( bFloatMode != ((GetAlignment() == SFX_ALIGN_NOALIGNMENT)) ) + { + bFloatMode = !bFloatMode; + SetFloatingMode( bFloatMode ); + if ( bFloatMode ) + { + if ( pImp->aWinState.Len() ) + GetFloatingWindow()->SetWindowState( pImp->aWinState ); + else + GetFloatingWindow()->SetOutputSizePixel( GetFloatingSize() ); + } + } + + if ( IsFloatingMode() ) + { + // validate last alignment + SfxChildAlignment eLastAlign = pImp->GetLastAlignment(); + if ( eLastAlign == SFX_ALIGN_NOALIGNMENT) + eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_LEFT); + if ( eLastAlign == SFX_ALIGN_NOALIGNMENT) + eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_RIGHT); + if ( eLastAlign == SFX_ALIGN_NOALIGNMENT) + eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_TOP); + if ( eLastAlign == SFX_ALIGN_NOALIGNMENT) + eLastAlign = CheckAlignment(eLastAlign, SFX_ALIGN_BOTTOM); + pImp->SetLastAlignment(eLastAlign); + } + else + { + // docked window must have NOALIGNMENT as last alignment + pImp->SetLastAlignment(SFX_ALIGN_NOALIGNMENT); + + if ( pImp->bSplitable ) + { +// pImp->bAutoHide = ( pInfo->nFlags & SFX_CHILDWIN_AUTOHIDE) != 0; + pImp->pSplitWin = pWorkWin->GetSplitWindow_Impl(GetAlignment()); + pImp->pSplitWin->InsertWindow(this, pImp->aSplitSize); + } + else + { + //?????? Currently not supported + // Fenster ist individuell angedockt; Gr"o\se berechnen. + // Dazu mu\s sie mit der FloatingSize initialisiert werden, falls + // irgendwer sich darauf verl"a\st, da\s eine vern"unftige Gr"o\se + // gesetzt ist + SetSizePixel(GetFloatingSize()); + SetSizePixel(CalcDockingSize(GetAlignment())); + } + } + + // save alignment + pImp->SetDockAlignment( GetAlignment() ); +} + +void SfxDockingWindow::Initialize_Impl() +{ + if ( !pMgr ) + { + // Bugfix #39771 + pImp->bConstructed = TRUE; + return; + } + + FloatingWindow* pFloatWin = GetFloatingWindow(); + BOOL bSet = FALSE; + if ( pFloatWin ) + { + bSet = !pFloatWin->IsDefaultPos(); + } + else + { + Point aPos = GetFloatingPos(); + if ( aPos != Point() ) + bSet = TRUE; + } + + if ( !bSet) + { + SfxViewFrame *pFrame = pBindings->GetDispatcher_Impl()->GetFrame(); + Window* pEditWin = pFrame->GetViewShell()->GetWindow(); + Point aPos = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() ); + aPos = GetParent()->ScreenToOutputPixel( aPos ); + SetFloatingPos( aPos ); + } + + if ( pFloatWin ) + { + // initialize floating window + if ( !pImp->aWinState.Len() ) + // window state never set before, get if from defaults + pImp->aWinState = pFloatWin->GetWindowState(); + + // trick: use VCL method SetWindowState to adjust position and size + pFloatWin->SetWindowState( pImp->aWinState ); + + // remember floating size for calculating alignment and tracking rectangle + SetFloatingSize( pFloatWin->GetSizePixel() ); + + // some versions of VCL didn't call resize in the current situation + //Resize(); + } + + // allow calling of docking handlers + pImp->bConstructed = TRUE; +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::FillInfo(SfxChildWinInfo& rInfo) const + +/* [Beschreibung] + + F"ullt ein SfxChildWinInfo mit f"ur SfxDockingWindow spezifischen Daten, + damit sie in die INI-Datei geschrieben werden koennen. + Es wird angenommen, da\s rInfo alle anderen evt. relevanten Daten in + der ChildWindow-Klasse erh"alt. + Eingetragen werden hier gemerkten Gr"o\sen, das ZoomIn-Flag und die + f"ur das Docking relevanten Informationen. + Wird diese Methode "uberschrieben, mu\s zuerst die Basisimplementierung + gerufen werden. +*/ + +{ + if ( !pMgr ) + return; + + if ( GetFloatingWindow() && pImp->bConstructed ) + pImp->aWinState = GetFloatingWindow()->GetWindowState(); + + rInfo.aWinState = pImp->aWinState; + rInfo.aExtraString = DEFINE_CONST_UNICODE("AL:("); + rInfo.aExtraString += String::CreateFromInt32((USHORT) GetAlignment()); + rInfo.aExtraString += ','; + rInfo.aExtraString += String::CreateFromInt32 ((USHORT) pImp->GetLastAlignment()); + if ( pImp->bSplitable ) + { + Point aPos(pImp->nLine, pImp->nPos); + rInfo.aExtraString += ','; + rInfo.aExtraString += String::CreateFromInt32( aPos.X() ); + rInfo.aExtraString += '/'; + rInfo.aExtraString += String::CreateFromInt32( aPos.Y() ); + rInfo.aExtraString += '/'; + rInfo.aExtraString += String::CreateFromInt32( pImp->nHorizontalSize ); + rInfo.aExtraString += '/'; + rInfo.aExtraString += String::CreateFromInt32( pImp->nVerticalSize ); + rInfo.aExtraString += ','; + rInfo.aExtraString += String::CreateFromInt32( pImp->aSplitSize.Width() ); + rInfo.aExtraString += ';'; + rInfo.aExtraString += String::CreateFromInt32( pImp->aSplitSize.Height() ); + } + + rInfo.aExtraString += ')'; +} + +//------------------------------------------------------------------------- + +SfxDockingWindow::~SfxDockingWindow() +{ + ReleaseChildWindow_Impl(); + delete pImp; +} + +void SfxDockingWindow::ReleaseChildWindow_Impl() +{ + if ( pMgr && pMgr->GetFrame() == pBindings->GetActiveFrame() ) + pBindings->SetActiveFrame( NULL ); + + if ( pMgr && pImp->pSplitWin && pImp->pSplitWin->IsItemValid( GetType() ) ) + pImp->pSplitWin->RemoveWindow(this); + + pMgr=NULL; +} + +//------------------------------------------------------------------------- + +SfxChildAlignment SfxDockingWindow::CalcAlignment(const Point& rPos, Rectangle& rRect) + +/* [Beschreibung] + + Diese Methode berechnet f"ur gegebene Mausposition und tracking rectangle, + welches Alignment sich daraus ergeben w"urde. Beim Wechsel des Alignments + kann sich auch das tracking rectangle "andern, so dass ein ver"andertes + rectangle zur"uckgegeben wird. + + Der Klassenbenutzer kann das Verhalten dieser Methode und damit das Verhalten + seiner DockinWindow-Klasse beim Docken beeinflussen, indem er die hier + aufgerufene virtuelle Methode + + SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign) + + "uberschreibt (s.u.). +*/ + +{ + // calculate hypothetical sizes for different modes + Size aFloatingSize(CalcDockingSize(SFX_ALIGN_NOALIGNMENT)); + Size aVerticalSize(CalcDockingSize(SFX_ALIGN_LEFT)); + Size aHorizontalSize(CalcDockingSize(SFX_ALIGN_TOP)); + + // check if docking is permitted + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + if ( !pWorkWin->IsDockingAllowed() ) + { + rRect.SetSize( aFloatingSize ); + return pImp->GetDockAlignment(); + } + + // calculate borders to shrink inner area before checking for intersection with tracking rectangle + long nLRBorder, nTBBorder; + if ( pImp->bSplitable ) + { + // take the smaller size of docked and floating mode + Size aSize = pImp->aSplitSize; + if ( GetFloatingSize().Height() < aSize.Height() ) + aSize.Height() = GetFloatingSize().Height(); + if ( GetFloatingSize().Width() < aSize.Width() ) + aSize.Width() = GetFloatingSize().Width(); + + nLRBorder = aSize.Width(); + nTBBorder = aSize.Height(); + } + else + { + nLRBorder = aVerticalSize.Width(); + nTBBorder = aHorizontalSize.Height(); + } + + // limit border to predefined constant values + if ( nLRBorder > MAX_TOGGLEAREA_WIDTH ) + nLRBorder = MAX_TOGGLEAREA_WIDTH; + if ( nTBBorder > MAX_TOGGLEAREA_WIDTH ) + nTBBorder = MAX_TOGGLEAREA_WIDTH; + + // shrink area for floating mode if possible + Rectangle aInRect = GetInnerRect(); + if ( aInRect.GetWidth() > nLRBorder ) + aInRect.Left() += nLRBorder/2; + if ( aInRect.GetWidth() > nLRBorder ) + aInRect.Right() -= nLRBorder/2; + if ( aInRect.GetHeight() > nTBBorder ) + aInRect.Top() += nTBBorder/2; + if ( aInRect.GetHeight() > nTBBorder ) + aInRect.Bottom() -= nTBBorder/2; + + // calculate alignment resulting from docking rectangle + BOOL bBecomesFloating = FALSE; + SfxChildAlignment eDockAlign = pImp->GetDockAlignment(); + Rectangle aDockingRect( rRect ); + if ( !IsFloatingMode() ) + { + // don't use tracking rectangle for alignment check, because it will be too large + // to get a floating mode as result - switch to floating size + // so the calculation only depends on the position of the rectangle, not the current + // docking state of the window + aDockingRect.SetSize( GetFloatingSize() ); + + // in this mode docking is never done by keyboard, so it's OK to use the mouse position + aDockingRect.SetPos( pWorkWin->GetWindow()->OutputToScreenPixel( pWorkWin->GetWindow()->GetPointerPosPixel() ) ); + } + + Point aPos = aDockingRect.TopLeft(); + Rectangle aIntersect = GetOuterRect().GetIntersection( aDockingRect ); + if ( aIntersect.IsEmpty() ) + // docking rectangle completely outside docking area -> floating mode + bBecomesFloating = TRUE; + else + { + // create a small test rect around the mouse position and use this one + // instead of the passed rRect to not dock too easily or by accident + Rectangle aSmallDockingRect; + aSmallDockingRect.SetSize( Size( MAX_TOGGLEAREA_WIDTH, MAX_TOGGLEAREA_HEIGHT ) ); + Point aNewPos(rPos); + aNewPos.X() -= aSmallDockingRect.GetWidth()/2; + aNewPos.Y() -= aSmallDockingRect.GetHeight()/2; + aSmallDockingRect.SetPos(rPos); + Rectangle aIntersectRect = aInRect.GetIntersection( aSmallDockingRect ); + if ( aIntersectRect == aSmallDockingRect ) + // docking rectangle completely inside (shrinked) inner area -> floating mode + bBecomesFloating = TRUE; + } + + if ( bBecomesFloating ) + { + eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT); + } + else + { + // docking rectangle is in the "sensible area" + Point aInPosTL( aPos.X()-aInRect.Left(), aPos.Y()-aInRect.Top() ); + Point aInPosBR( aPos.X()-aInRect.Left() + aDockingRect.GetWidth(), aPos.Y()-aInRect.Top() + aDockingRect.GetHeight() ); + Size aInSize = aInRect.GetSize(); + BOOL bNoChange = FALSE; + + // check if alignment is still unchanged + switch ( GetAlignment() ) + { + case SFX_ALIGN_LEFT: + case SFX_ALIGN_FIRSTLEFT: + case SFX_ALIGN_LASTLEFT: + if (aInPosTL.X() <= 0) + { + eDockAlign = GetAlignment(); + bNoChange = TRUE; + } + break; + case SFX_ALIGN_TOP: + case SFX_ALIGN_LOWESTTOP: + case SFX_ALIGN_HIGHESTTOP: + if ( aInPosTL.Y() <= 0) + { + eDockAlign = GetAlignment(); + bNoChange = TRUE; + } + break; + case SFX_ALIGN_RIGHT: + case SFX_ALIGN_FIRSTRIGHT: + case SFX_ALIGN_LASTRIGHT: + if ( aInPosBR.X() >= aInSize.Width()) + { + eDockAlign = GetAlignment(); + bNoChange = TRUE; + } + break; + case SFX_ALIGN_BOTTOM: + case SFX_ALIGN_LOWESTBOTTOM: + case SFX_ALIGN_HIGHESTBOTTOM: + if ( aInPosBR.Y() >= aInSize.Height()) + { + eDockAlign = GetAlignment(); + bNoChange = TRUE; + } + break; + default: + break; + } + + if ( !bNoChange ) + { + // alignment will change, test alignment according to distance of the docking rectangles edges + BOOL bForbidden = TRUE; + if ( aInPosTL.X() <= 0) + { + eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_LEFT); + bForbidden = ( eDockAlign != SFX_ALIGN_LEFT && + eDockAlign != SFX_ALIGN_FIRSTLEFT && + eDockAlign != SFX_ALIGN_LASTLEFT ); + } + + if ( bForbidden && aInPosTL.Y() <= 0) + { + eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_TOP); + bForbidden = ( eDockAlign != SFX_ALIGN_TOP && + eDockAlign != SFX_ALIGN_HIGHESTTOP && + eDockAlign != SFX_ALIGN_LOWESTTOP ); + } + + if ( bForbidden && aInPosBR.X() >= aInSize.Width()) + { + eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_RIGHT); + bForbidden = ( eDockAlign != SFX_ALIGN_RIGHT && + eDockAlign != SFX_ALIGN_FIRSTRIGHT && + eDockAlign != SFX_ALIGN_LASTRIGHT ); + } + + if ( bForbidden && aInPosBR.Y() >= aInSize.Height()) + { + eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_BOTTOM); + bForbidden = ( eDockAlign != SFX_ALIGN_BOTTOM && + eDockAlign != SFX_ALIGN_HIGHESTBOTTOM && + eDockAlign != SFX_ALIGN_LOWESTBOTTOM ); + } + + // the calculated alignment was rejected by the window -> take floating mode + if ( bForbidden ) + eDockAlign = CheckAlignment(pImp->GetDockAlignment(),SFX_ALIGN_NOALIGNMENT); + } + } + + if ( eDockAlign == SFX_ALIGN_NOALIGNMENT ) + { + //Im FloatingMode erh"alt das tracking rectangle die floating size + // wg. SV-Bug darf rRect nur ver"andert werden, wenn sich das + // Alignment "andert ! + if ( eDockAlign != pImp->GetDockAlignment() ) + aDockingRect.SetSize( aFloatingSize ); + } + else if ( pImp->bSplitable ) + { + USHORT nLine, nPos; + SfxSplitWindow *pSplitWin = pWorkWin->GetSplitWindow_Impl(eDockAlign); + aPos = pSplitWin->ScreenToOutputPixel( aPos ); + if ( pSplitWin->GetWindowPos( aPos, nLine, nPos ) ) + { + // mouse over splitwindow, get line and position + pImp->nDockLine = nLine; + pImp->nDockPos = nPos; + pImp->bNewLine = FALSE; + } + else + { + if ( 0 ) + { + // mouse touches outer border -> treated as floating mode + eDockAlign = SFX_ALIGN_NOALIGNMENT; + aDockingRect.SetSize( aFloatingSize ); + rRect = aDockingRect; + return eDockAlign; + } + + // mouse touches inner border -> create new line + if ( eDockAlign == GetAlignment() && pImp->pSplitWin && + pImp->nLine == pImp->pSplitWin->GetLineCount()-1 && pImp->pSplitWin->GetWindowCount(pImp->nLine) == 1 ) + { + // if this window is the only one in the last line, it can't be docked as new line in the same splitwindow + pImp->nDockLine = pImp->nLine; + pImp->nDockPos = pImp->nPos; + pImp->bNewLine = FALSE; + } + else + { + // create new line + pImp->nDockLine = pSplitWin->GetLineCount(); + pImp->nDockPos = 0; + pImp->bNewLine = TRUE; + } + } + + BOOL bChanged = pImp->nLine != pImp->nDockLine || pImp->nPos != pImp->nDockPos || eDockAlign != GetAlignment(); + if ( !bChanged && !IsFloatingMode() ) + { + // window only sightly moved, no change of any property + rRect.SetSize( pImp->aSplitSize ); + rRect.SetPos( aDockingRect.TopLeft() ); + return eDockAlign; + } + + // calculate new size and position + Size aSize; + Point aPoint = aDockingRect.TopLeft(); + Size aInnerSize = GetInnerRect().GetSize(); + if ( eDockAlign == SFX_ALIGN_LEFT || eDockAlign == SFX_ALIGN_RIGHT ) + { + if ( pImp->bNewLine ) + { + // set height to height of free area + aSize.Height() = aInnerSize.Height(); + aSize.Width() = pImp->nHorizontalSize; + if ( eDockAlign == SFX_ALIGN_LEFT ) + { + aPoint = aInnerRect.TopLeft(); + } + else + { + aPoint = aInnerRect.TopRight(); + aPoint.X() -= aSize.Width(); + } + } + else + { + // get width from splitwindow + aSize.Width() = pSplitWin->GetLineSize(nLine); + aSize.Height() = pImp->aSplitSize.Height(); + } + } + else + { + if ( pImp->bNewLine ) + { + // set width to width of free area + aSize.Width() = aInnerSize.Width(); + aSize.Height() = pImp->nVerticalSize; + if ( eDockAlign == SFX_ALIGN_TOP ) + { + aPoint = aInnerRect.TopLeft(); + } + else + { + aPoint = aInnerRect.BottomLeft(); + aPoint.Y() -= aSize.Height(); + } + } + else + { + // get height from splitwindow + aSize.Height() = pSplitWin->GetLineSize(nLine); + aSize.Width() = pImp->aSplitSize.Width(); + } + } + + aDockingRect.SetSize( aSize ); + aDockingRect.SetPos( aPoint ); + } + else + { + // window can be docked, but outside our splitwindows + // tracking rectangle only needs to be modified if alignment was changed + if ( eDockAlign != pImp->GetDockAlignment() ) + { + switch ( eDockAlign ) + { + case SFX_ALIGN_LEFT: + case SFX_ALIGN_RIGHT: + case SFX_ALIGN_FIRSTLEFT: + aDockingRect.SetPos( aInnerRect.TopLeft() ); + aDockingRect.SetSize( aVerticalSize ); + break; + case SFX_ALIGN_LASTLEFT: + case SFX_ALIGN_FIRSTRIGHT: + case SFX_ALIGN_LASTRIGHT: + { + Point aPt( aInnerRect.TopRight() ); + aPt.X() -= aDockingRect.GetWidth(); + aDockingRect.SetPos( aPt ); + aDockingRect.SetSize( aVerticalSize ); + break; + } + + case SFX_ALIGN_TOP: + case SFX_ALIGN_BOTTOM: + case SFX_ALIGN_LOWESTTOP: + aDockingRect.SetPos( aInnerRect.TopLeft() ); + aDockingRect.SetSize( aHorizontalSize ); + break; + case SFX_ALIGN_HIGHESTTOP: + case SFX_ALIGN_LOWESTBOTTOM: + case SFX_ALIGN_HIGHESTBOTTOM: + { + Point aPt( aInnerRect.BottomLeft() ); + aPt.Y() -= aDockingRect.GetHeight(); + aDockingRect.SetPos( aPt ); + aDockingRect.SetSize( aHorizontalSize ); + break; + } + default: + break; + } + } + } + + rRect = aDockingRect; + return eDockAlign; +} + +//------------------------------------------------------------------------- + +Size SfxDockingWindow::CalcDockingSize(SfxChildAlignment eAlign) + +/* [Beschreibung] + + Virtuelle Methode der Klasse SfxDockingWindow. + Hier wird festgelegt, wie sich die Gr"o\se des DockingWindows abh"angig vom + Alignment "andert. + Die Basisimplementation setzt im Floating Mode die Gr"o\se auf die gemerkte + Floating Size. + Bei horizontalem Alignment wird die Breite auf die Breite des "au\seren + DockingRects, bei vertikalem Alignment die H"ohe auf die H"ohe des inneren + DockingRects (ergibt sich aus der Reihenfolge, in der im SFX ChildWindows + ausgegeben werden). Die jeweils andere Gr"o\se wird auf die aktuelle + Floating Size gesetzt, hier k"onnte eine abgeleitete Klasse "andernd + eingreifen. + Die DockingSize mu\s f"ur Left/Right und Top/Bottom jeweils gleich sein. +*/ + +{ + // Achtung: falls das Resizing auch im angedockten Zustand geht, mu\s dabei + // auch die Floating Size angepa\st werden !? + + Size aSize = GetFloatingSize(); + switch (eAlign) + { + case SFX_ALIGN_TOP: + case SFX_ALIGN_BOTTOM: + case SFX_ALIGN_LOWESTTOP: + case SFX_ALIGN_HIGHESTTOP: + case SFX_ALIGN_LOWESTBOTTOM: + case SFX_ALIGN_HIGHESTBOTTOM: + aSize.Width() = aOuterRect.Right() - aOuterRect.Left(); + break; + case SFX_ALIGN_LEFT: + case SFX_ALIGN_RIGHT: + case SFX_ALIGN_FIRSTLEFT: + case SFX_ALIGN_LASTLEFT: + case SFX_ALIGN_FIRSTRIGHT: + case SFX_ALIGN_LASTRIGHT: + aSize.Height() = aInnerRect.Bottom() - aInnerRect.Top(); + break; + case SFX_ALIGN_NOALIGNMENT: + break; + default: + break; + } + + return aSize; +} + +//------------------------------------------------------------------------- + +SfxChildAlignment SfxDockingWindow::CheckAlignment(SfxChildAlignment, + SfxChildAlignment eAlign) + +/* [Beschreibung] + + Virtuelle Methode der Klasse SfxDockingWindow. + Hier kann eine abgeleitete Klasse bestimmte Alignments verbieten. + Die Basisimplementation verbietet kein Alignment. +*/ + +{ + return eAlign; +} + +//------------------------------------------------------------------------- + +BOOL SfxDockingWindow::Close() + +/* [Beschreibung] + + Das Fenster wird geschlossen, indem das ChildWindow durch Ausf"uhren des + ChildWindow-Slots zerst"ort wird. + Wird diese Methode von einer abgeleiteten Klasse "uberschrieben, mu\s + danach SfxDockingWindow::Close() gerufen werden, wenn nicht das Close() + mit "return FALSE" abgebrochen wird. + +*/ +{ + // Execute mit Parametern, da Toggle von einigen ChildWindows ignoriert + // werden kann + if ( !pMgr ) + return TRUE; + + SfxBoolItem aValue( pMgr->GetType(), FALSE); + pBindings->GetDispatcher_Impl()->Execute( + pMgr->GetType(), SFX_CALLMODE_RECORD | SFX_CALLMODE_ASYNCHRON, &aValue, 0L ); + return TRUE; +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::Paint(const Rectangle& /*rRect*/) + +/* [Beschreibung] + + Es wird im angedockten Zustand eine Begrenzungslinie an der angedockten + Kante und ein Rahmen ausgegeben. Dabei wird SVLOOK ber"ucksichtigt. +*/ + +{ + if ( pImp->bSplitable || IsFloatingMode() ) + return; + + Rectangle aRect = Rectangle(Point(0, 0), + GetOutputSizePixel()); + switch (GetAlignment()) + { + case SFX_ALIGN_TOP: + { + DrawLine(aRect.BottomLeft(), aRect.BottomRight()); + aRect.Bottom()--; + break; + } + + case SFX_ALIGN_BOTTOM: + { + DrawLine(aRect.TopLeft(), aRect.TopRight()); + aRect.Top()++; + break; + } + + case SFX_ALIGN_LEFT: + { + DrawLine(aRect.TopRight(), aRect.BottomRight()); + aRect.Right()--; + break; + } + + case SFX_ALIGN_RIGHT: + { + DrawLine(aRect.TopLeft(), aRect.BottomLeft()); + aRect.Left()++; + break; + } + default: + break; + } + + DecorationView aView( this ); + aView.DrawFrame( aRect, FRAME_DRAW_OUT ); +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::SetMinOutputSizePixel( const Size& rSize ) + +/* [Beschreibung] + + Mit dieser Methode kann eine minimale OutpuSize gesetzt werden, die + im Resizing()-Handler abgefragt wird. +*/ + +{ + pImp->aMinSize = rSize; + DockingWindow::SetMinOutputSizePixel( rSize ); +} + +//------------------------------------------------------------------------- + +Size SfxDockingWindow::GetMinOutputSizePixel() const + +/* [Beschreibung] + + Die gesetzte minimale Gr"o\se wird zur"uckgegeben. +*/ + +{ + return pImp->aMinSize; +} + +//------------------------------------------------------------------------- + +long SfxDockingWindow::Notify( NotifyEvent& rEvt ) +{ + if ( rEvt.GetType() == EVENT_GETFOCUS ) + { + pBindings->SetActiveFrame( pMgr->GetFrame() ); + + if ( pImp->pSplitWin ) + pImp->pSplitWin->SetActiveWindow_Impl( this ); + else + pMgr->Activate_Impl(); + + Window* pWindow = rEvt.GetWindow(); + ULONG nHelpId = 0; + while ( !nHelpId && pWindow ) + { + nHelpId = pWindow->GetHelpId(); + pWindow = pWindow->GetParent(); + } + + if ( nHelpId ) + SfxHelp::OpenHelpAgent( &pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame(), nHelpId ); + + // In VCL geht Notify zun"achst an das Fenster selbst, + // also base class rufen, sonst erf"ahrt der parent nichts + // if ( rEvt.GetWindow() == this ) PB: #i74693# not necessary any longer + DockingWindow::Notify( rEvt ); + return TRUE; + } + else if( rEvt.GetType() == EVENT_KEYINPUT ) + { + // KeyInput zuerst f"ur Dialogfunktionen zulassen + if ( !DockingWindow::Notify( rEvt ) && SfxViewShell::Current() ) + // dann auch global g"ultige Acceleratoren verwenden + return SfxViewShell::Current()->GlobalKeyInput_Impl( *rEvt.GetKeyEvent() ); + return TRUE; + } + else if ( rEvt.GetType() == EVENT_LOSEFOCUS && !HasChildPathFocus() ) + { + pBindings->SetActiveFrame( NULL ); + pMgr->Deactivate_Impl(); + } + + return DockingWindow::Notify( rEvt ); +} + + +USHORT SfxDockingWindow::GetWinBits_Impl() const +{ + USHORT nBits = 0; +// if ( pImp->bAutoHide ) +// nBits |= SWIB_AUTOHIDE; + return nBits; +} + +//------------------------------------------------------------------------- + +void SfxDockingWindow::SetItemSize_Impl( const Size& rSize ) +{ + pImp->aSplitSize = rSize; + + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW; + if ( pImp->bSplitable ) + eIdent = SFX_CHILDWIN_SPLITWINDOW; + pWorkWin->ConfigChild_Impl( eIdent, SFX_ALIGNDOCKINGWINDOW, pMgr->GetType() ); +} + +void SfxDockingWindow::Disappear_Impl() +{ + if ( pImp->pSplitWin && pImp->pSplitWin->IsItemValid( GetType() ) ) + pImp->pSplitWin->RemoveWindow(this); +} + +void SfxDockingWindow::Reappear_Impl() +{ + if ( pImp->pSplitWin && !pImp->pSplitWin->IsItemValid( GetType() ) ) + { + pImp->pSplitWin->InsertWindow( this, pImp->aSplitSize ); + } +} + +BOOL SfxDockingWindow::IsAutoHide_Impl() const +{ + if ( pImp->pSplitWin ) + return !pImp->pSplitWin->IsFadeIn(); + else + return FALSE; +} + +BOOL SfxDockingWindow::IsPinned_Impl() const +{ + if ( pImp->pSplitWin ) + return pImp->pSplitWin->IsPinned(); + else + return TRUE; +} +void SfxDockingWindow::AutoShow( BOOL bShow ) +{ + AutoShow_Impl(bShow); +} + +void SfxDockingWindow::AutoShow_Impl( BOOL bShow ) +{ + if ( pImp->pSplitWin ) + { + if ( bShow ) + pImp->pSplitWin->FadeIn(); + else + pImp->pSplitWin->FadeOut(); + } +} + +/* +void SfxDockingWindow::Pin_Impl( BOOL bPinned ) +{ + if ( pImp->pSplitWin ) + pImp->pSplitWin->Pin_Impl( bPinned ); +} +*/ + +SfxSplitWindow* SfxDockingWindow::GetSplitWindow_Impl() const +{ + return pImp->pSplitWin; +} + +void SfxDockingWindow::FadeIn( BOOL /*bFadeIn*/ ) +{ +} + +void SfxDockingWindow::StateChanged( StateChangedType nStateChange ) +{ + if ( nStateChange == STATE_CHANGE_INITSHOW ) + Initialize_Impl(); + + DockingWindow::StateChanged( nStateChange ); +} + +void SfxDockingWindow::Move() +{ + if ( pImp ) + pImp->aMoveTimer.Start(); +} + +IMPL_LINK( SfxDockingWindow, TimerHdl, Timer*, EMPTYARG) +{ + pImp->aMoveTimer.Stop(); + if ( IsReallyVisible() && IsFloatingMode() ) + { + if( !GetFloatingWindow()->IsRollUp() ) + SetFloatingSize( GetOutputSizePixel() ); + pImp->aWinState = GetFloatingWindow()->GetWindowState(); + SfxChildIdentifier eIdent = SFX_CHILDWIN_DOCKINGWINDOW; + if ( pImp->bSplitable ) + eIdent = SFX_CHILDWIN_SPLITWINDOW; + SfxWorkWindow *pWorkWin = pBindings->GetWorkWindow_Impl(); + pWorkWin->ConfigChild_Impl( eIdent, SFX_ALIGNDOCKINGWINDOW, pMgr->GetType() ); + } + return 0; +} + diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx new file mode 100644 index 000000000000..7198c84b7127 --- /dev/null +++ b/sfx2/source/dialog/filedlghelper.cxx @@ -0,0 +1,2904 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <sfx2/filedlghelper.hxx> +#include <sal/types.h> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/XControlInformation.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFolderPicker.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker2.hpp> +#include <com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/types.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/stillreadwriteinteraction.hxx> +#include <tools/urlobj.hxx> +#include <vcl/help.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/ucbhelper.hxx> +#include <unotools/localfilehelper.hxx> +#include <vos/thread.hxx> +#include <vos/mutex.hxx> +#include <vos/security.hxx> +#include <vcl/cvtgrf.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/mnemonic.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/securityoptions.hxx> +#include <svl/itemset.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svtools/filter.hxx> +#include <unotools/viewoptions.hxx> +#include <unotools/moduleoptions.hxx> +#include <svtools/helpid.hrc> +#include <svl/pickerhelper.hxx> +#include <comphelper/docpasswordrequest.hxx> +#include <comphelper/docpasswordhelper.hxx> +#include <ucbhelper/content.hxx> +#include <ucbhelper/commandenvironment.hxx> +#include <comphelper/storagehelper.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <sfx2/app.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfac.hxx> +#include "openflag.hxx" +#include <sfx2/passwd.hxx> +#include "sfxresid.hxx" +#include <sfx2/sfxsids.hrc> +#include "filedlghelper.hrc" +#include "filtergrouping.hxx" +#include <sfx2/request.hxx> +#include "filedlgimpl.hxx" + +#include <sfxlocal.hrc> + +//----------------------------------------------------------------------------- + +using namespace ::com::sun::star; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::rtl; +using namespace ::cppu; + +//----------------------------------------------------------------------------- + +#define IODLG_CONFIGNAME String(DEFINE_CONST_UNICODE("FilePicker_Save")) +#define IMPGRF_CONFIGNAME String(DEFINE_CONST_UNICODE("FilePicker_Graph")) +#define USERITEM_NAME ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "UserItem" )) + +//----------------------------------------------------------------------------- + +namespace sfx2 +{ + +const OUString* GetLastFilterConfigId( FileDialogHelper::Context _eContext ) +{ + static const OUString aSD_EXPORT_IDENTIFIER( RTL_CONSTASCII_USTRINGPARAM( "SdExportLastFilter" ) ); + static const OUString aSI_EXPORT_IDENTIFIER( RTL_CONSTASCII_USTRINGPARAM( "SiExportLastFilter" ) ); + static const OUString aSW_EXPORT_IDENTIFIER( RTL_CONSTASCII_USTRINGPARAM( "SwExportLastFilter" ) ); + + const OUString* pRet = NULL; + + switch( _eContext ) + { + case FileDialogHelper::SD_EXPORT: pRet = &aSD_EXPORT_IDENTIFIER; break; + case FileDialogHelper::SI_EXPORT: pRet = &aSI_EXPORT_IDENTIFIER; break; + case FileDialogHelper::SW_EXPORT: pRet = &aSW_EXPORT_IDENTIFIER; break; + default: break; + } + + return pRet; +} + +String EncodeSpaces_Impl( const String& rSource ); +String DecodeSpaces_Impl( const String& rSource ); + +// ------------------------------------------------------------------------ +// ----------- FileDialogHelper_Impl --------------------------- +// ------------------------------------------------------------------------ + +// ------------------------------------------------------------------------ +// XFilePickerListener Methods +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper_Impl::fileSelectionChanged( const FilePickerEvent& aEvent ) throw ( RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + mpAntiImpl->FileSelectionChanged( aEvent ); +} + +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper_Impl::directoryChanged( const FilePickerEvent& aEvent ) throw ( RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + mpAntiImpl->DirectoryChanged( aEvent ); +} + +// ------------------------------------------------------------------------ +OUString SAL_CALL FileDialogHelper_Impl::helpRequested( const FilePickerEvent& aEvent ) throw ( RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + return mpAntiImpl->HelpRequested( aEvent ); +} + +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper_Impl::controlStateChanged( const FilePickerEvent& aEvent ) throw ( RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + mpAntiImpl->ControlStateChanged( aEvent ); +} + +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper_Impl::dialogSizeChanged() throw ( RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + mpAntiImpl->DialogSizeChanged(); +} + +// ------------------------------------------------------------------------ +// XDialogClosedListener Methods +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper_Impl::dialogClosed( const DialogClosedEvent& _rEvent ) throw ( RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + mpAntiImpl->DialogClosed( _rEvent ); + postExecute( _rEvent.DialogResult ); +} + +// ------------------------------------------------------------------------ +// handle XFilePickerListener events +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::handleFileSelectionChanged( const FilePickerEvent& ) +{ + if ( mbHasVersions ) + updateVersions(); + + if ( mbShowPreview ) + maPreViewTimer.Start(); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::handleDirectoryChanged( const FilePickerEvent& ) +{ + if ( mbShowPreview ) + TimeOutHdl_Impl( NULL ); +} + +// ------------------------------------------------------------------------ +OUString FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent& aEvent ) +{ + //!!! todo: cache the help strings (here or TRA) + + ULONG nHelpId = 0; + // mapping from element id -> help id + switch ( aEvent.ElementId ) + { + case ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION : + nHelpId = HID_FILESAVE_AUTOEXTENSION; + break; + + case ExtendedFilePickerElementIds::CHECKBOX_PASSWORD : + nHelpId = HID_FILESAVE_SAVEWITHPASSWORD; + break; + + case ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS : + nHelpId = HID_FILESAVE_CUSTOMIZEFILTER; + break; + + case ExtendedFilePickerElementIds::CHECKBOX_READONLY : + nHelpId = HID_FILEOPEN_READONLY; + break; + + case ExtendedFilePickerElementIds::CHECKBOX_LINK : + nHelpId = HID_FILEDLG_LINK_CB; + break; + + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : + nHelpId = HID_FILEDLG_PREVIEW_CB; + break; + + case ExtendedFilePickerElementIds::PUSHBUTTON_PLAY : + nHelpId = HID_FILESAVE_DOPLAY; + break; + + case ExtendedFilePickerElementIds::LISTBOX_VERSION_LABEL : + case ExtendedFilePickerElementIds::LISTBOX_VERSION : + nHelpId = HID_FILEOPEN_VERSION; + break; + + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE_LABEL : + case ExtendedFilePickerElementIds::LISTBOX_TEMPLATE : + nHelpId = HID_FILESAVE_TEMPLATE; + break; + + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE_LABEL : + case ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE : + nHelpId = HID_FILEOPEN_IMAGE_TEMPLATE; + break; + + case ExtendedFilePickerElementIds::CHECKBOX_SELECTION : + nHelpId = HID_FILESAVE_SELECTION; + break; + + default: + DBG_ERRORFILE( "invalid element id" ); + } + + OUString aHelpText; + Help* pHelp = Application::GetHelp(); + if ( pHelp ) + aHelpText = String( pHelp->GetHelpText( nHelpId, NULL ) ); + return aHelpText; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::handleControlStateChanged( const FilePickerEvent& aEvent ) +{ + switch ( aEvent.ElementId ) + { + case CommonFilePickerElementIds::LISTBOX_FILTER: + updateFilterOptionsBox(); + enablePasswordBox( sal_False ); + updateSelectionBox(); + // only use it for export and with our own dialog + if ( mbExport && !mbSystemPicker ) + updateExportButton(); + break; + + case ExtendedFilePickerElementIds::CHECKBOX_PREVIEW: + updatePreviewState(); + break; + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::handleDialogSizeChanged() +{ + if ( mbShowPreview ) + TimeOutHdl_Impl( NULL ); +} + +// ------------------------------------------------------------------------ +// XEventListener Methods +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper_Impl::disposing( const EventObject& ) throw ( RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + dispose(); +} + +// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::dispose() +{ + if ( mxFileDlg.is() ) + { + // remove the event listener + uno::Reference< XFilePickerNotifier > xNotifier( mxFileDlg, UNO_QUERY ); + if ( xNotifier.is() ) + xNotifier->removeFilePickerListener( this ); + + ::comphelper::disposeComponent( mxFileDlg ); + mxFileDlg.clear(); + } +} + +// ------------------------------------------------------------------------ +String FileDialogHelper_Impl::getCurrentFilterUIName() const +{ + String aFilterName; + uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); + + if( xFltMgr.is() ) + { + aFilterName = xFltMgr->getCurrentFilter(); + + if ( aFilterName.Len() && isShowFilterExtensionEnabled() ) + aFilterName = getFilterName( aFilterName ); + } + + return aFilterName; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::LoadLastUsedFilter( const OUString& _rContextIdentifier ) +{ + SvtViewOptions aDlgOpt( E_DIALOG, IODLG_CONFIGNAME ); + + if( aDlgOpt.Exists() ) + { + OUString aLastFilter; + if( aDlgOpt.GetUserItem( _rContextIdentifier ) >>= aLastFilter ) + setFilter( aLastFilter ); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::SaveLastUsedFilter( const OUString& _rContextIdentifier ) +{ + SvtViewOptions( E_DIALOG, IODLG_CONFIGNAME ).SetUserItem( _rContextIdentifier, + makeAny( getFilterWithExtension( getFilter() ) ) ); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::SaveLastUsedFilter( void ) +{ + const OUString* pConfigId = GetLastFilterConfigId( meContext ); + if( pConfigId ) + SaveLastUsedFilter( *pConfigId ); +} + +// ------------------------------------------------------------------------ +const SfxFilter* FileDialogHelper_Impl::getCurentSfxFilter() +{ + String aFilterName = getCurrentFilterUIName(); + + const SfxFilter* pFilter = NULL; + if ( mpMatcher && aFilterName.Len() ) + pFilter = mpMatcher->GetFilter4UIName( aFilterName, m_nMustFlags, m_nDontFlags ); + + return pFilter; +} + +// ------------------------------------------------------------------------ +sal_Bool FileDialogHelper_Impl::updateExtendedControl( sal_Int16 _nExtendedControlId, sal_Bool _bEnable ) +{ + sal_Bool bIsEnabled = sal_False; + + uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + if ( xCtrlAccess.is() ) + { + try + { + xCtrlAccess->enableControl( _nExtendedControlId, _bEnable ); + bIsEnabled = _bEnable; + } + catch( const IllegalArgumentException& ) + { + DBG_ERROR( "FileDialogHelper_Impl::updateExtendedControl: caught an exception!" ); + } + } + return bIsEnabled; +} + +// ------------------------------------------------------------------------ +sal_Bool FileDialogHelper_Impl::CheckFilterOptionsCapability( const SfxFilter* _pFilter ) +{ + sal_Bool bResult = sal_False; + + if( mxFilterCFG.is() && _pFilter ) + { + try { + Sequence < PropertyValue > aProps; + Any aAny = mxFilterCFG->getByName( _pFilter->GetName() ); + if ( aAny >>= aProps ) + { + ::rtl::OUString aServiceName; + sal_Int32 nPropertyCount = aProps.getLength(); + for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty ) + { + if( aProps[nProperty].Name.equals( DEFINE_CONST_OUSTRING( "UIComponent") ) ) + { + aProps[nProperty].Value >>= aServiceName; + if( aServiceName.getLength() ) + bResult = sal_True; + } + } + } + } + catch( Exception& ) + { + } + } + + return bResult; +} + +// ------------------------------------------------------------------------ +sal_Bool FileDialogHelper_Impl::isInOpenMode() const +{ + sal_Bool bRet = sal_False; + + switch ( m_nDialogType ) + { + case FILEOPEN_SIMPLE: + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + case FILEOPEN_PLAY: + case FILEOPEN_READONLY_VERSION: + case FILEOPEN_LINK_PREVIEW: + bRet = sal_True; + } + + return bRet; +} + +// ------------------------------------------------------------------------ + +void FileDialogHelper_Impl::updateFilterOptionsBox() +{ + if ( !m_bHaveFilterOptions ) + return; + + updateExtendedControl( + ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, + CheckFilterOptionsCapability( getCurentSfxFilter() ) + ); +} + +// ------------------------------------------------------------------------ + +void FileDialogHelper_Impl::updateExportButton() +{ + uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + if ( xCtrlAccess.is() ) + { + OUString sEllipses( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); + OUString sOldLabel( xCtrlAccess->getLabel( CommonFilePickerElementIds::PUSHBUTTON_OK ) ); + + // initialize button label; we need the label with the mnemonic char + if ( !maButtonLabel.getLength() || maButtonLabel.indexOf( MNEMONIC_CHAR ) == -1 ) + { + // cut the ellipses, if necessary + sal_Int32 nIndex = sOldLabel.indexOf( sEllipses ); + if ( -1 == nIndex ) + nIndex = sOldLabel.getLength(); + maButtonLabel = sOldLabel.copy( 0, nIndex ); + } + + OUString sLabel = maButtonLabel; + // filter with options -> append ellipses on export button label + if ( CheckFilterOptionsCapability( getCurentSfxFilter() ) ) + sLabel += OUString( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); + + if ( sOldLabel != sLabel ) + { + try + { + xCtrlAccess->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK, sLabel ); + } + catch( const IllegalArgumentException& ) + { + DBG_ERRORFILE( "FileDialogHelper_Impl::updateExportButton: caught an exception!" ); + } + } + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::updateSelectionBox() +{ + if ( !mbHasSelectionBox ) + return; + + // Does the selection box exist? + sal_Bool bSelectionBoxFound = sal_False; + uno::Reference< XControlInformation > xCtrlInfo( mxFileDlg, UNO_QUERY ); + if ( xCtrlInfo.is() ) + { + Sequence< ::rtl::OUString > aCtrlList = xCtrlInfo->getSupportedControls(); + sal_uInt32 nCount = aCtrlList.getLength(); + for ( sal_uInt32 nCtrl = 0; nCtrl < nCount; ++nCtrl ) + if ( aCtrlList[ nCtrl ].equalsAscii("SelectionBox") ) + { + bSelectionBoxFound = sal_False; + break; + } + } + + if ( bSelectionBoxFound ) + { + const SfxFilter* pFilter = getCurentSfxFilter(); + mbSelectionFltrEnabled = updateExtendedControl( + ExtendedFilePickerElementIds::CHECKBOX_SELECTION, + ( mbSelectionEnabled && pFilter && ( pFilter->GetFilterFlags() & SFX_FILTER_SUPPORTSSELECTION ) != 0 ) ); + uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, makeAny( (sal_Bool)mbSelection ) ); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::enablePasswordBox( sal_Bool bInit ) +{ + if ( ! mbHasPassword ) + return; + + sal_Bool bWasEnabled = mbIsPwdEnabled; + + const SfxFilter* pCurrentFilter = getCurentSfxFilter(); + mbIsPwdEnabled = updateExtendedControl( + ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, + pCurrentFilter && ( pCurrentFilter->GetFilterFlags() & SFX_FILTER_ENCRYPTION ) + ); + + if( bInit ) + { + // in case of inintialization previous state is not interesting + if( mbIsPwdEnabled ) + { + uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + if( mbPwdCheckBoxState ) + xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, makeAny( sal_True ) ); + } + } + else if( !bWasEnabled && mbIsPwdEnabled ) + { + uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + if( mbPwdCheckBoxState ) + xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, makeAny( sal_True ) ); + } + else if( bWasEnabled && !mbIsPwdEnabled ) + { + // remember user settings until checkbox is enabled + uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 ); + sal_Bool bPassWord = sal_False; + mbPwdCheckBoxState = ( aValue >>= bPassWord ) && bPassWord; + xCtrlAccess->setValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0, makeAny( sal_False ) ); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::updatePreviewState( sal_Bool _bUpdatePreviewWindow ) +{ + if ( mbHasPreview ) + { + uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + + // check, wether or not we have to display a preview + if ( xCtrlAccess.is() ) + { + try + { + Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 ); + sal_Bool bShowPreview = sal_False; + + if ( aValue >>= bShowPreview ) + { + mbShowPreview = bShowPreview; + + // #97633 + // setShowState has currently no effect for the + // OpenOffice FilePicker (see svtools/source/filepicker/iodlg.cxx) + uno::Reference< XFilePreview > xFilePreview( mxFileDlg, UNO_QUERY ); + if ( xFilePreview.is() ) + xFilePreview->setShowState( mbShowPreview ); + + if ( _bUpdatePreviewWindow ) + TimeOutHdl_Impl( NULL ); + } + } + catch( Exception ) + { + DBG_ERRORFILE( "FileDialogHelper_Impl::updatePreviewState: caught an exception!" ); + } + } + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::updateVersions() +{ + Sequence < OUString > aEntries; + Sequence < OUString > aPathSeq = mxFileDlg->getFiles(); + + if ( aPathSeq.getLength() == 1 ) + { + INetURLObject aObj( aPathSeq[0] ); + + if ( ( aObj.GetProtocol() == INET_PROT_FILE ) && + ( utl::UCBContentHelper::IsDocument( aObj.GetMainURL( INetURLObject::NO_DECODE ) ) ) ) + { + try + { + uno::Reference< embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL( + aObj.GetMainURL( INetURLObject::NO_DECODE ), + embed::ElementModes::READ ); + + DBG_ASSERT( xStorage.is(), "The method must return the storage or throw an exception!" ); + if ( !xStorage.is() ) + throw uno::RuntimeException(); + + uno::Sequence < util::RevisionTag > xVersions = SfxMedium::GetVersionList( xStorage ); + + aEntries.realloc( xVersions.getLength() + 1 ); + aEntries[0] = OUString( String ( SfxResId( STR_SFX_FILEDLG_ACTUALVERSION ) ) ); + + for ( sal_Int32 i=0; i<xVersions.getLength(); i++ ) + aEntries[ i + 1 ] = xVersions[i].Identifier; + + // TODO/LATER: not sure that this information must be shown in future ( binfilter? ) +//REMOVE else +//REMOVE { +//REMOVE SfxFilterFlags nMust = SFX_FILTER_IMPORT | SFX_FILTER_OWN; +//REMOVE SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED | SFX_FILTER_STARONEFILTER; +//REMOVE if ( SFX_APP()->GetFilterMatcher().GetFilter4ClipBoardId( pStor->GetFormat(), nMust, nDont ) ) +//REMOVE { +//REMOVE aEntries.realloc( 1 ); +//REMOVE aEntries[0] = OUString( String ( SfxResId( STR_SFX_FILEDLG_ACTUALVERSION ) ) ); +//REMOVE } +//REMOVE } + } + catch( uno::Exception& ) + { + } + } + } + + uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY ); + Any aValue; + + try + { + xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, + ControlActions::DELETE_ITEMS, aValue ); + } + catch( IllegalArgumentException ){} + + sal_Int32 nCount = aEntries.getLength(); + + if ( nCount ) + { + try + { + aValue <<= aEntries; + xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, + ControlActions::ADD_ITEMS, aValue ); + + Any aPos; + aPos <<= (sal_Int32) 0; + xDlg->setValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, + ControlActions::SET_SELECT_ITEM, aPos ); + } + catch( IllegalArgumentException ){} + } +} + +// ----------------------------------------------------------------------- +class OReleaseSolarMutex +{ +private: + const sal_Int32 m_nAquireCount; +public: + OReleaseSolarMutex( ) + :m_nAquireCount( Application::ReleaseSolarMutex() ) + { + } + ~OReleaseSolarMutex( ) + { + Application::AcquireSolarMutex( m_nAquireCount ); + } +}; + +// ----------------------------------------------------------------------- +IMPL_LINK( FileDialogHelper_Impl, TimeOutHdl_Impl, Timer*, EMPTYARG ) +{ + if ( !mbHasPreview ) + return 0; + + maGraphic.Clear(); + + Any aAny; + uno::Reference < XFilePreview > xFilePicker( mxFileDlg, UNO_QUERY ); + + if ( ! xFilePicker.is() ) + return 0; + + Sequence < OUString > aPathSeq = mxFileDlg->getFiles(); + + if ( mbShowPreview && ( aPathSeq.getLength() == 1 ) ) + { + OUString aURL = aPathSeq[0]; + + if ( ERRCODE_NONE == getGraphic( aURL, maGraphic ) ) + { + // #89491 + // changed the code slightly; + // before: the bitmap was scaled and + // surrounded a white frame + // now: the bitmap will only be scaled + // and the filepicker implementation + // is responsible for placing it at its + // proper position and painting a frame + + Bitmap aBmp = maGraphic.GetBitmap(); + + // scale the bitmap to the correct size + sal_Int32 nOutWidth = xFilePicker->getAvailableWidth(); + sal_Int32 nOutHeight = xFilePicker->getAvailableHeight(); + sal_Int32 nBmpWidth = aBmp.GetSizePixel().Width(); + sal_Int32 nBmpHeight = aBmp.GetSizePixel().Height(); + + double nXRatio = (double) nOutWidth / nBmpWidth; + double nYRatio = (double) nOutHeight / nBmpHeight; + + if ( nXRatio < nYRatio ) + aBmp.Scale( nXRatio, nXRatio ); + else + aBmp.Scale( nYRatio, nYRatio ); + + // #94505# Convert to true color, to allow CopyPixel + aBmp.Convert( BMP_CONVERSION_24BIT ); + + // and copy it into the Any + SvMemoryStream aData; + + aData << aBmp; + + const Sequence < sal_Int8 > aBuffer( + static_cast< const sal_Int8* >(aData.GetData()), + aData.GetEndOfData() ); + + aAny <<= aBuffer; + } + } + + try + { + OReleaseSolarMutex aReleaseForCallback; + // clear the preview window + xFilePicker->setImage( FilePreviewImageFormats::BITMAP, aAny ); + } + catch( IllegalArgumentException ) + { + } + + return 0; +} + +// ------------------------------------------------------------------------ +ErrCode FileDialogHelper_Impl::getGraphic( const OUString& rURL, + Graphic& rGraphic ) const +{ + if ( utl::UCBContentHelper::IsFolder( rURL ) ) + return ERRCODE_IO_NOTAFILE; + + if ( !mpGraphicFilter ) + return ERRCODE_IO_NOTSUPPORTED; + + // select graphic filter from dialog filter selection + OUString aCurFilter( getFilter() ); + + sal_uInt16 nFilter = aCurFilter.getLength() && mpGraphicFilter->GetImportFormatCount() + ? mpGraphicFilter->GetImportFormatNumber( aCurFilter ) + : GRFILTER_FORMAT_DONTKNOW; + + INetURLObject aURLObj( rURL ); + + if ( aURLObj.HasError() || INET_PROT_NOT_VALID == aURLObj.GetProtocol() ) + { + aURLObj.SetSmartProtocol( INET_PROT_FILE ); + aURLObj.SetSmartURL( rURL ); + } + + ErrCode nRet = ERRCODE_NONE; + + sal_uInt32 nFilterImportFlags = GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG; + // non-local? + if ( INET_PROT_FILE != aURLObj.GetProtocol() ) + { + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( rURL, STREAM_READ ); + + if( pStream ) + nRet = mpGraphicFilter->ImportGraphic( rGraphic, rURL, *pStream, nFilter, NULL, nFilterImportFlags ); + else + nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, NULL, nFilterImportFlags ); + delete pStream; + } + else + { + nRet = mpGraphicFilter->ImportGraphic( rGraphic, aURLObj, nFilter, NULL, nFilterImportFlags ); + } + + return nRet; +} + +// ------------------------------------------------------------------------ +ErrCode FileDialogHelper_Impl::getGraphic( Graphic& rGraphic ) const +{ + ErrCode nRet = ERRCODE_NONE; + + if ( ! maGraphic ) + { + OUString aPath;; + Sequence < OUString > aPathSeq = mxFileDlg->getFiles(); + + if ( aPathSeq.getLength() == 1 ) + { + aPath = aPathSeq[0]; + } + + if ( aPath.getLength() ) + nRet = getGraphic( aPath, rGraphic ); + else + nRet = ERRCODE_IO_GENERAL; + } + else + rGraphic = maGraphic; + + return nRet; +} + +// ------------------------------------------------------------------------ +sal_Bool lcl_isSystemFilePicker( const uno::Reference< XFilePicker >& _rxFP ) +{ + try + { + uno::Reference< XServiceInfo > xSI( _rxFP, UNO_QUERY ); + if ( xSI.is() && xSI->supportsService( DEFINE_CONST_OUSTRING( "com.sun.star.ui.dialogs.SystemFilePicker" ) ) ) + return sal_True; + } + catch( const Exception& ) + { + } + return sal_False; +} + + +// ------------------------------------------------------------------------ +// ----------- FileDialogHelper_Impl --------------------------- +// ------------------------------------------------------------------------ + +FileDialogHelper_Impl::FileDialogHelper_Impl( + FileDialogHelper* _pAntiImpl, + sal_Int16 nDialogType, + sal_Int64 nFlags, + sal_Int16 nDialog, + Window* _pPreferredParentWindow, + const String& sStandardDir, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList + ) + :m_nDialogType ( nDialogType ) + ,meContext ( FileDialogHelper::UNKNOWN_CONTEXT ) +{ + const char* pServiceName=0; + if ( nDialog == SFX2_IMPL_DIALOG_SYSTEM ) + pServiceName = FILE_OPEN_SERVICE_NAME_OOO; + else if ( nDialog == SFX2_IMPL_DIALOG_OOO ) + pServiceName = FILE_OPEN_SERVICE_NAME_OOO; + else + pServiceName = FILE_OPEN_SERVICE_NAME; + OUString aService = ::rtl::OUString::createFromAscii( pServiceName ); + + uno::Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + + // create the file open dialog + // the flags can be SFXWB_INSERT or SFXWB_MULTISELECTION + + mpPreferredParentWindow = _pPreferredParentWindow; + mpAntiImpl = _pAntiImpl; + mnError = ERRCODE_NONE; + mbHasAutoExt = sal_False; + mbHasPassword = sal_False; + m_bHaveFilterOptions = sal_False; + mbIsPwdEnabled = sal_True; + mbHasVersions = sal_False; + mbHasPreview = sal_False; + mbShowPreview = sal_False; + mbHasLink = sal_False; + mbDeleteMatcher = sal_False; + mbInsert = SFXWB_INSERT == ( nFlags & SFXWB_INSERT ); + mbExport = SFXWB_EXPORT == ( nFlags & SFXWB_EXPORT ); + mbIsSaveDlg = sal_False; + mbPwdCheckBoxState = sal_False; + mbSelection = sal_False; + mbSelectionEnabled = sal_True; + mbHasSelectionBox = sal_False; + mbSelectionFltrEnabled = sal_False; + + // default settings + m_nDontFlags = SFX_FILTER_INTERNAL | SFX_FILTER_NOTINFILEDLG | SFX_FILTER_NOTINSTALLED; + if( WB_OPEN == ( nFlags & WB_OPEN ) ) + m_nMustFlags = SFX_FILTER_IMPORT; + else + m_nMustFlags = SFX_FILTER_EXPORT; + + + mpMatcher = NULL; + mpGraphicFilter = NULL; + mnPostUserEventId = 0; + + // create the picker component + mxFileDlg = mxFileDlg.query( xFactory->createInstance( aService ) ); + mbSystemPicker = lcl_isSystemFilePicker( mxFileDlg ); + + uno::Reference< XFilePickerNotifier > xNotifier( mxFileDlg, UNO_QUERY ); + uno::Reference< XInitialization > xInit( mxFileDlg, UNO_QUERY ); + + if ( ! mxFileDlg.is() || ! xNotifier.is() ) + { + mnError = ERRCODE_ABORT; + return; + } + + + if ( xInit.is() ) + { + sal_Int16 nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE; + + switch ( m_nDialogType ) + { + case FILEOPEN_SIMPLE: + nTemplateDescription = TemplateDescription::FILEOPEN_SIMPLE; + break; + + case FILESAVE_SIMPLE: + nTemplateDescription = TemplateDescription::FILESAVE_SIMPLE; + mbIsSaveDlg = sal_True; + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD: + nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD; + mbHasPassword = sal_True; + mbHasAutoExt = sal_True; + mbIsSaveDlg = sal_True; + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS; + mbHasPassword = sal_True; + + m_bHaveFilterOptions = sal_True; + if( xFactory.is() ) + { + mxFilterCFG = uno::Reference< XNameAccess >( + xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ), + UNO_QUERY ); + } + + mbHasAutoExt = sal_True; + mbIsSaveDlg = sal_True; + break; + + case FILESAVE_AUTOEXTENSION_SELECTION: + nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION; + mbHasAutoExt = sal_True; + mbIsSaveDlg = sal_True; + mbHasSelectionBox = sal_True; + if ( mbExport && !mxFilterCFG.is() && xFactory.is() ) + { + mxFilterCFG = uno::Reference< XNameAccess >( + xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.document.FilterFactory" ) ), + UNO_QUERY ); + } + break; + + case FILESAVE_AUTOEXTENSION_TEMPLATE: + nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE; + mbHasAutoExt = sal_True; + mbIsSaveDlg = sal_True; + break; + + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE; + mbHasPreview = sal_True; + mbHasLink = sal_True; + + // aPreviewTimer + maPreViewTimer.SetTimeout( 500 ); + maPreViewTimer.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) ); + break; + + case FILEOPEN_PLAY: + nTemplateDescription = TemplateDescription::FILEOPEN_PLAY; + break; + + case FILEOPEN_READONLY_VERSION: + nTemplateDescription = TemplateDescription::FILEOPEN_READONLY_VERSION; + mbHasVersions = sal_True; + break; + + case FILEOPEN_LINK_PREVIEW: + nTemplateDescription = TemplateDescription::FILEOPEN_LINK_PREVIEW; + mbHasPreview = sal_True; + mbHasLink = sal_True; + // aPreviewTimer + maPreViewTimer.SetTimeout( 500 ); + maPreViewTimer.SetTimeoutHdl( LINK( this, FileDialogHelper_Impl, TimeOutHdl_Impl ) ); + break; + + case FILESAVE_AUTOEXTENSION: + nTemplateDescription = TemplateDescription::FILESAVE_AUTOEXTENSION; + mbHasAutoExt = sal_True; + mbIsSaveDlg = sal_True; + break; + + default: + DBG_ERRORFILE( "FileDialogHelper::ctor with unknown type" ); + break; + } + + + + //Sequence < Any > aInitArguments( mbSystemPicker || !mpPreferredParentWindow ? 1 : 3 ); + Sequence < Any > aInitArguments( !mpPreferredParentWindow ? 3 : 4 ); + + // This is a hack. We currently know that the internal file picker implementation + // supports the extended arguments as specified below. + // TODO: + // a) adjust the service description so that it includes the TemplateDescription and ParentWindow args + // b) adjust the implementation of the system file picker to that it recognizes it + if ( mbSystemPicker ) + { + aInitArguments[0] <<= nTemplateDescription; + } + else + { + aInitArguments[0] <<= NamedValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TemplateDescription" ) ), + makeAny( nTemplateDescription ) + ); + + ::rtl::OUString sStandardDirTemp = ::rtl::OUString( sStandardDir ); + + aInitArguments[1] <<= NamedValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StandardDir" ) ), + makeAny( sStandardDirTemp ) + ); + + aInitArguments[2] <<= NamedValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BlackList" ) ), + makeAny( rBlackList ) + ); + + + if ( mpPreferredParentWindow ) + aInitArguments[3] <<= NamedValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ) ), + makeAny( VCLUnoHelper::GetInterface( mpPreferredParentWindow ) ) + ); + + + } + + try + { + xInit->initialize( aInitArguments ); + } + catch( const Exception& ) + { + DBG_ERROR( "FileDialogHelper_Impl::FileDialogHelper_Impl: could not initialize the picker!" ); + } + } + + + // set multiselection mode + if ( nFlags & SFXWB_MULTISELECTION ) + mxFileDlg->setMultiSelectionMode( sal_True ); + + if ( mbHasLink ) // generate graphic filter only on demand + addGraphicFilter(); + + // Export dialog + if ( mbExport ) + { + mxFileDlg->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_EXPORT ) ) ) ); + try { + com::sun::star::uno::Reference < XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY_THROW ); + xCtrlAccess->enableControl( ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR, sal_True ); + } + catch( const Exception & ) { } + } + + // the "insert file" dialog needs another title + if ( mbInsert ) + { + mxFileDlg->setTitle( OUString( String( SfxResId( STR_SFX_EXPLORERFILE_INSERT ) ) ) ); + uno::Reference < XFilePickerControlAccess > xExtDlg( mxFileDlg, UNO_QUERY ); + if ( xExtDlg.is() ) + { + try + { + xExtDlg->setLabel( CommonFilePickerElementIds::PUSHBUTTON_OK, + OUString( String( SfxResId( STR_SFX_EXPLORERFILE_BUTTONINSERT ) ) ) ); + } + catch( IllegalArgumentException ){} + } + } + + // add the event listener + xNotifier->addFilePickerListener( this ); +} + +// ------------------------------------------------------------------------ +FileDialogHelper_Impl::~FileDialogHelper_Impl() +{ + // Remove user event if we haven't received it yet + if ( mnPostUserEventId ) + Application::RemoveUserEvent( mnPostUserEventId ); + mnPostUserEventId = 0; + + delete mpGraphicFilter; + + if ( mbDeleteMatcher ) + delete mpMatcher; + + maPreViewTimer.SetTimeoutHdl( Link() ); + + ::comphelper::disposeComponent( mxFileDlg ); +} + +#define nMagic -1 + +class PickerThread_Impl : public ::vos::OThread +{ + uno::Reference < XFilePicker > mxPicker; + ::vos::OMutex maMutex; + virtual void SAL_CALL run(); + sal_Int16 mnRet; +public: + PickerThread_Impl( const uno::Reference < XFilePicker >& rPicker ) + : mxPicker( rPicker ), mnRet(nMagic) {} + + sal_Int16 GetReturnValue() + { ::vos::OGuard aGuard( maMutex ); return mnRet; } + + void SetReturnValue( sal_Int16 aRetValue ) + { ::vos::OGuard aGuard( maMutex ); mnRet = aRetValue; } +}; + +void SAL_CALL PickerThread_Impl::run() +{ + try + { + sal_Int16 n = mxPicker->execute(); + SetReturnValue( n ); + } + catch( RuntimeException& ) + { + SetReturnValue( ExecutableDialogResults::CANCEL ); + DBG_ERRORFILE( "RuntimeException caught" ); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::setControlHelpIds( const sal_Int16* _pControlId, const sal_Int32* _pHelpId ) +{ + DBG_ASSERT( _pControlId && _pHelpId, "FileDialogHelper_Impl::setControlHelpIds: invalid array pointers!" ); + if ( !_pControlId || !_pHelpId ) + return; + + // forward these ids to the file picker + try + { + const ::rtl::OUString sHelpIdPrefix( RTL_CONSTASCII_USTRINGPARAM( "HID:" ) ); + // the ids for the single controls + uno::Reference< XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY ); + if ( xControlAccess.is() ) + { + while ( *_pControlId ) + { + // calc the help id of the element + ::rtl::OUString sId( sHelpIdPrefix ); + sId += ::rtl::OUString::valueOf( *_pHelpId ); + // set the help id + xControlAccess->setValue( *_pControlId, ControlActions::SET_HELP_URL, makeAny( sId ) ); + + ++_pControlId; ++_pHelpId; + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "FileDialogHelper_Impl::setControlHelpIds: caught an exception while setting the help ids!" ); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::setDialogHelpId( const sal_Int32 _nHelpId ) +{ + svt::SetDialogHelpId( mxFileDlg, _nHelpId ); +} + +// ------------------------------------------------------------------------ +IMPL_LINK( FileDialogHelper_Impl, InitControls, void*, NOTINTERESTEDIN ) +{ + (void)NOTINTERESTEDIN; + mnPostUserEventId = 0; + enablePasswordBox( sal_True ); + updateFilterOptionsBox( ); + updateSelectionBox( ); + + return 0L; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::preExecute() +{ + loadConfig( ); + setDefaultValues( ); + updatePreviewState( sal_False ); + + implInitializeFileName( ); + // #106079# / 2002-12-09 / fs@openoffice.org + +#if !(defined(MACOSX) && defined(QUARTZ)) && !defined(WNT) + // allow for dialog implementations which need to be executed before they return valid values for + // current filter and such + + // On Vista (at least SP1) it's the same as on MacOSX, the modal dialog won't let message pass + // through before it returns from execution + mnPostUserEventId = Application::PostUserEvent( LINK( this, FileDialogHelper_Impl, InitControls ) ); +#else + // However, the Mac OS X implementation's pickers run modally in execute and so the event doesn't + // get through in time... so we call the methods directly + enablePasswordBox( sal_True ); + updateFilterOptionsBox( ); + updateSelectionBox( ); +#endif +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::postExecute( sal_Int16 _nResult ) +{ + if ( ExecutableDialogResults::CANCEL != _nResult ) + saveConfig(); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::implInitializeFileName( ) +{ + if ( maFileName.getLength() ) + { + INetURLObject aObj( maPath ); + aObj.Append( maFileName ); + + // in case we're operating as save dialog, and "auto extension" is checked, + // cut the extension from the name + // #106079# / 2002-12-09 / fs@openoffice.org + if ( mbIsSaveDlg && mbHasAutoExt ) + { + try + { + sal_Bool bAutoExtChecked = sal_False; + + uno::Reference < XFilePickerControlAccess > xControlAccess( mxFileDlg, UNO_QUERY ); + if ( xControlAccess.is() + && ( xControlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 ) + >>= bAutoExtChecked + ) + ) + { + if ( bAutoExtChecked ) + { // cut the extension + aObj.removeExtension( ); + mxFileDlg->setDefaultName( aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ) ); + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "FileDialogHelper_Impl::implInitializeFileName: could not ask for the auto-extension current-value!" ); + } + } + } +} + +// ------------------------------------------------------------------------ +sal_Int16 FileDialogHelper_Impl::implDoExecute() +{ + preExecute(); + + sal_Int16 nRet = ExecutableDialogResults::CANCEL; + +//On MacOSX the native file picker has to run in the primordial thread because of drawing issues +//On Linux the native gtk file picker, when backed by gnome-vfs2, needs to be run in the same +//primordial thread as the ucb gnome-vfs2 provider was initialized in. +/* +#ifdef WNT + if ( mbSystemPicker ) + { + PickerThread_Impl* pThread = new PickerThread_Impl( mxFileDlg ); + pThread->create(); + while ( pThread->GetReturnValue() == nMagic ) + Application::Yield(); + pThread->join(); + nRet = pThread->GetReturnValue(); + delete pThread; + } + else +#endif +*/ + { + try + { +#ifdef WNT + if ( mbSystemPicker ) + { + OReleaseSolarMutex aSolarMutex; + nRet = mxFileDlg->execute(); + } + else +#endif + nRet = mxFileDlg->execute(); + } + catch( const Exception& ) + { + DBG_ERRORFILE( "FileDialogHelper_Impl::implDoExecute: caught an exception!" ); + } + } + + postExecute( nRet ); + + return nRet; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::implStartExecute() +{ + DBG_ASSERT( mxFileDlg.is(), "invalid file dialog" ); + + preExecute(); + + if ( mbSystemPicker ) + { + } + else + { + try + { + uno::Reference< XAsynchronousExecutableDialog > xAsyncDlg( mxFileDlg, UNO_QUERY ); + if ( xAsyncDlg.is() ) + xAsyncDlg->startExecuteModal( this ); + } + catch( const Exception& ) + { + DBG_ERRORFILE( "FileDialogHelper_Impl::implDoExecute: caught an exception!" ); + } + } +} + +// ------------------------------------------------------------------------ +String FileDialogHelper_Impl::implEnsureURLExtension(const String& sURL, + const String& /*sExtension*/) +{ + return sURL; + /* + // This feature must be active for file save/export only ! + if ( + (! mbIsSaveDlg) && + (! mbExport ) + ) + return sURL; + + // no extension available (because "ALL *.*" was selected) ? + // Nod idea what else should happen here .-) + if (sExtension.Len() < 1) + return sURL; + + // Some FilePicker implementations already add the right extension ... + // or might be the user used the right one already ... + // Dont create duplicate extension. + INetURLObject aURL(sURL); + if (aURL.getExtension().equals(sExtension)) + return sURL; + + // Ignore any other extension set by the user. + // Make sure suitable extension is used always. + // e.g. "test.bla.odt" for "ODT" + ::rtl::OUStringBuffer sNewURL(256); + sNewURL.append (sURL ); + sNewURL.appendAscii("." ); + sNewURL.append (sExtension); + return sNewURL.makeStringAndClear(); + */ +} + +// ------------------------------------------------------------------------ +void lcl_saveLastURLs(SvStringsDtor*& rpURLList , + ::comphelper::SequenceAsVector< ::rtl::OUString >& lLastURLs ) +{ + lLastURLs.clear(); + USHORT c = rpURLList->Count(); + USHORT i = 0; + for (i=0; i<c; ++i) + lLastURLs.push_back(*(rpURLList->GetObject(i))); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::implGetAndCacheFiles(const uno::Reference< XInterface >& xPicker , + SvStringsDtor*& rpURLList, + const SfxFilter* pFilter ) +{ + rpURLList = NULL; + + String sExtension; + if (pFilter) + { + sExtension = pFilter->GetDefaultExtension (); + sExtension.EraseAllChars( '*' ); + sExtension.EraseAllChars( '.' ); + } + + // a) the new way (optional!) + uno::Reference< XFilePicker2 > xPickNew(xPicker, UNO_QUERY); + if (xPickNew.is()) + { + rpURLList = new SvStringsDtor; + Sequence< OUString > lFiles = xPickNew->getSelectedFiles(); + ::sal_Int32 nFiles = lFiles.getLength(); + for (::sal_Int32 i = 0; i < nFiles; i++) + { + String* pURL = new String(implEnsureURLExtension(lFiles[i], sExtension)); + rpURLList->Insert( pURL, rpURLList->Count() ); + } + } + + // b) the olde way ... non optional. + else + { + uno::Reference< XFilePicker > xPickOld(xPicker, UNO_QUERY_THROW); + Sequence< OUString > lFiles = xPickOld->getFiles(); + ::sal_Int32 nFiles = lFiles.getLength(); + if ( nFiles == 1 ) + { + rpURLList = new SvStringsDtor; + String* pURL = new String(implEnsureURLExtension(lFiles[0], sExtension)); + rpURLList->Insert( pURL, 0 ); + } + else + if ( nFiles > 1 ) + { + rpURLList = new SvStringsDtor; + + INetURLObject aPath( lFiles[0] ); + aPath.setFinalSlash(); + + for (::sal_Int32 i = 1; i < nFiles; i++) + { + if (i == 1) + aPath.Append( lFiles[i] ); + else + aPath.setName( lFiles[i] ); + + String* pURL = new String(implEnsureURLExtension(aPath.GetMainURL( INetURLObject::NO_DECODE ), sExtension) ); + rpURLList->Insert( pURL, rpURLList->Count() ); + } + } + } + + lcl_saveLastURLs(rpURLList, mlLastURLs); +} + +// ------------------------------------------------------------------------ +ErrCode FileDialogHelper_Impl::execute( SvStringsDtor*& rpURLList, + SfxItemSet *& rpSet, + String& rFilter ) +{ + // rFilter is a pure output parameter, it shouldn't be used for anything else + // changing this would surely break code + // rpSet is in/out parameter, usually just a media-descriptor that can be changed by dialog + + uno::Reference< XFilePickerControlAccess > xCtrlAccess( mxFileDlg, UNO_QUERY ); + + // retrieves parameters from rpSet + // for now only Password is used + if ( rpSet ) + { + // check password checkbox if the document had password before + if( mbHasPassword ) + { + SFX_ITEMSET_ARG( rpSet, pPassItem, SfxStringItem, SID_PASSWORD, FALSE ); + mbPwdCheckBoxState = ( pPassItem != NULL ); + + // in case the document has password to modify, the dialog should be shown + SFX_ITEMSET_ARG( rpSet, pPassToModifyItem, SfxUnoAnyItem, SID_MODIFYPASSWORDINFO, FALSE ); + mbPwdCheckBoxState |= ( pPassToModifyItem && pPassToModifyItem->GetValue().hasValue() ); + } + + SFX_ITEMSET_ARG( rpSet, pSelectItem, SfxBoolItem, SID_SELECTION, FALSE ); + if ( pSelectItem ) + mbSelection = pSelectItem->GetValue(); + else + mbSelectionEnabled = sal_False; + + // the password will be set in case user decide so + rpSet->ClearItem( SID_PASSWORD ); + rpSet->ClearItem( SID_RECOMMENDREADONLY ); + rpSet->ClearItem( SID_MODIFYPASSWORDINFO ); + + } + + if ( mbHasPassword && !mbPwdCheckBoxState ) + { + SvtSecurityOptions aSecOpt; + mbPwdCheckBoxState = ( + aSecOpt.IsOptionSet( SvtSecurityOptions::E_DOCWARN_RECOMMENDPASSWORD ) ); + } + + rpURLList = NULL; + + if ( ! mxFileDlg.is() ) + return ERRCODE_ABORT; + + if ( ExecutableDialogResults::CANCEL != implDoExecute() ) + { + // create an itemset if there is no + if( !rpSet ) + rpSet = new SfxAllItemSet( SFX_APP()->GetPool() ); + + // the item should remain only if it was set by the dialog + rpSet->ClearItem( SID_SELECTION ); + + if( mbExport ) + { + try + { + Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 ); + sal_Bool bSelection = sal_False; + if ( aValue >>= bSelection ) + rpSet->Put( SfxBoolItem( SID_SELECTION, bSelection ) ); + } + catch( IllegalArgumentException ) + { + DBG_ERROR( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" ); + } + } + + + // set the read-only flag. When inserting a file, this flag is always set + if ( mbInsert ) + rpSet->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) ); + else + { + if ( ( FILEOPEN_READONLY_VERSION == m_nDialogType ) && xCtrlAccess.is() ) + { + try + { + Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ); + sal_Bool bReadOnly = sal_False; + if ( ( aValue >>= bReadOnly ) && bReadOnly ) + rpSet->Put( SfxBoolItem( SID_DOC_READONLY, bReadOnly ) ); + } + catch( IllegalArgumentException ) + { + DBG_ERROR( "FileDialogHelper_Impl::execute: caught an IllegalArgumentException!" ); + } + } + } + if ( mbHasVersions && xCtrlAccess.is() ) + { + try + { + Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, + ControlActions::GET_SELECTED_ITEM_INDEX ); + sal_Int32 nVersion = 0; + if ( ( aValue >>= nVersion ) && nVersion > 0 ) + // open a special version; 0 == current version + rpSet->Put( SfxInt16Item( SID_VERSION, (short)nVersion ) ); + } + catch( IllegalArgumentException ){} + } + + // set the filter + getRealFilter( rFilter ); + + const SfxFilter* pCurrentFilter = getCurentSfxFilter(); + + // fill the rpURLList + implGetAndCacheFiles( mxFileDlg, rpURLList, pCurrentFilter ); + if ( rpURLList == NULL || rpURLList->GetObject(0) == NULL ) + return ERRCODE_ABORT; + + // check, wether or not we have to display a password box + if ( pCurrentFilter && mbHasPassword && mbIsPwdEnabled && xCtrlAccess.is() ) + { + try + { + Any aValue = xCtrlAccess->getValue( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, 0 ); + sal_Bool bPassWord = sal_False; + if ( ( aValue >>= bPassWord ) && bPassWord ) + { + // ask for a password + uno::Reference < ::com::sun::star::task::XInteractionHandler > xInteractionHandler( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.comp.uui.UUIInteractionHandler")), UNO_QUERY ); + + if( xInteractionHandler.is() ) + { + // TODO: need a save way to distinguish MS filters from other filters + // for now MS-filters are the only alien filters that support encryption + sal_Bool bMSType = !pCurrentFilter->IsOwnFormat(); + ::comphelper::DocPasswordRequestType eType = bMSType ? + ::comphelper::DocPasswordRequestType_MS : + ::comphelper::DocPasswordRequestType_STANDARD; + + ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest( new ::comphelper::DocPasswordRequest( eType, ::com::sun::star::task::PasswordRequestMode_PASSWORD_CREATE, *(rpURLList->GetObject(0)), ( pCurrentFilter->GetFilterFlags() & SFX_FILTER_PASSWORDTOMODIFY ) != 0 ) ); + + uno::Reference< com::sun::star::task::XInteractionRequest > rRequest( pPasswordRequest.get() ); + xInteractionHandler->handle( rRequest ); + if ( pPasswordRequest->isPassword() ) + { + if ( pPasswordRequest->getPassword().getLength() ) + rpSet->Put( SfxStringItem( SID_PASSWORD, pPasswordRequest->getPassword() ) ); + + if ( pPasswordRequest->getRecommendReadOnly() ) + rpSet->Put( SfxBoolItem( SID_RECOMMENDREADONLY, sal_True ) ); + + if ( bMSType ) + { + // the empty password has 0 as Hash + sal_Int32 nHash = SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ).equals( pCurrentFilter->GetServiceName() ) ); + if ( nHash ) + rpSet->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO, uno::makeAny( nHash ) ) ); + } + else + { + uno::Sequence< beans::PropertyValue > aModifyPasswordInfo = ::comphelper::DocPasswordHelper::GenerateNewModifyPasswordInfo( pPasswordRequest->getPasswordToModify() ); + if ( aModifyPasswordInfo.getLength() ) + rpSet->Put( SfxUnoAnyItem( SID_MODIFYPASSWORDINFO, uno::makeAny( aModifyPasswordInfo ) ) ); + } + } + else + return ERRCODE_ABORT; + } + } + } + catch( IllegalArgumentException ){} + } + + SaveLastUsedFilter(); + return ERRCODE_NONE; + } + else + return ERRCODE_ABORT; +} + +// ------------------------------------------------------------------------ +ErrCode FileDialogHelper_Impl::execute() +{ + if ( ! mxFileDlg.is() ) + return ERRCODE_ABORT; + + sal_Int16 nRet = implDoExecute(); + + maPath = mxFileDlg->getDisplayDirectory(); + + if ( ExecutableDialogResults::CANCEL == nRet ) + return ERRCODE_ABORT; + else + { + return ERRCODE_NONE; + } +} + +// ------------------------------------------------------------------------ +OUString FileDialogHelper_Impl::getPath() const +{ + OUString aPath; + + if ( mxFileDlg.is() ) + aPath = mxFileDlg->getDisplayDirectory(); + + if ( !aPath.getLength() ) + aPath = maPath; + + return aPath; +} + +// ------------------------------------------------------------------------ +OUString FileDialogHelper_Impl::getFilter() const +{ + String aFilter = getCurrentFilterUIName(); + + if( !aFilter.Len() ) + aFilter = maCurFilter; + + return aFilter; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::getRealFilter( String& _rFilter ) const +{ + _rFilter = getCurrentFilterUIName(); + + if ( !_rFilter.Len() ) + _rFilter = maCurFilter; + + if ( _rFilter.Len() && mpMatcher ) + { + const SfxFilter* pFilter = + mpMatcher->GetFilter4UIName( _rFilter, m_nMustFlags, m_nDontFlags ); + _rFilter = pFilter ? pFilter->GetFilterName() : _rFilter.Erase(); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::displayFolder( const ::rtl::OUString& _rPath ) +{ + if ( ! _rPath.getLength() ) + // nothing to do + return; + + /* + if ( !::utl::UCBContentHelper::IsFolder( _rPath ) ) + // only valid folders accepted here + return; + */ + + maPath = _rPath; + if ( mxFileDlg.is() ) + { + try + { + mxFileDlg->setDisplayDirectory( maPath ); + } + catch( const IllegalArgumentException& ) + { + DBG_ERROR( "FileDialogHelper_Impl::displayFolder: caught an exception!" ); + } + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::setFileName( const ::rtl::OUString& _rFile ) +{ + maFileName = _rFile; + if ( mxFileDlg.is() ) + { + try + { + mxFileDlg->setDefaultName( maFileName ); + } + catch( const IllegalArgumentException& ) + { + DBG_ERROR( "FileDialogHelper_Impl::setFileName: caught an exception!" ); + } + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::setFilter( const OUString& rFilter ) +{ + DBG_ASSERT( rFilter.indexOf(':') == -1, "Old filter name used!"); + + maCurFilter = rFilter; + + if ( rFilter.getLength() && mpMatcher ) + { + const SfxFilter* pFilter = mpMatcher->GetFilter4FilterName( + rFilter, m_nMustFlags, m_nDontFlags ); + if ( pFilter ) + maCurFilter = pFilter->GetUIName(); + } + + uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); + + if ( maCurFilter.getLength() && xFltMgr.is() ) + { + try + { + xFltMgr->setCurrentFilter( maCurFilter ); + } + catch( IllegalArgumentException ){} + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::createMatcher( const String& rFactory ) +{ + mpMatcher = new SfxFilterMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) ); + mbDeleteMatcher = sal_True; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::addFilters( sal_Int64 nFlags, + const String& rFactory, + SfxFilterFlags nMust, + SfxFilterFlags nDont ) +{ + uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); + + if ( ! xFltMgr.is() ) + return; + + // we still need a matcher to convert UI names to filter names + if ( !rFactory.Len() ) + { + SfxApplication *pSfxApp = SFX_APP(); + mpMatcher = &pSfxApp->GetFilterMatcher(); + mbDeleteMatcher = sal_False; + } + else + { + mpMatcher = new SfxFilterMatcher( rFactory ); + mbDeleteMatcher = sal_True; + } + + uno::Reference< XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + uno::Reference< XContainerQuery > xFilterCont( + xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.document.FilterFactory")), + UNO_QUERY); + if ( ! xFilterCont.is() ) + return; + + m_nMustFlags |= nMust; + m_nDontFlags |= nDont; + + // create the list of filters + ::rtl::OUStringBuffer sQuery(256); + sQuery.appendAscii("getSortedFilterList()"); + sQuery.appendAscii(":module=" ); + sQuery.append (rFactory ); // use long name here ! + sQuery.appendAscii(":iflags=" ); + sQuery.append (::rtl::OUString::valueOf((sal_Int32)m_nMustFlags)); + sQuery.appendAscii(":eflags=" ); + sQuery.append (::rtl::OUString::valueOf((sal_Int32)m_nDontFlags)); + + uno::Reference< XEnumeration > xResult = xFilterCont->createSubSetEnumerationByQuery(sQuery.makeStringAndClear()); + TSortedFilterList aIter (xResult); + + // no matcher any longer used ... + mbDeleteMatcher = sal_False; + + // append the filters + ::rtl::OUString sFirstFilter; + if ( WB_OPEN == ( nFlags & WB_OPEN ) ) + ::sfx2::appendFiltersForOpen( aIter, xFltMgr, sFirstFilter, *this ); + else if ( mbExport ) + ::sfx2::appendExportFilters( aIter, xFltMgr, sFirstFilter, *this ); + else + ::sfx2::appendFiltersForSave( aIter, xFltMgr, sFirstFilter, *this, rFactory ); + + // set our initial selected filter (if we do not already have one) + if ( !maSelectFilter.getLength() ) + maSelectFilter = sFirstFilter; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::addFilter( const OUString& rFilterName, + const OUString& rExtension ) +{ + uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); + + if ( ! xFltMgr.is() ) + return; + + try + { + xFltMgr->appendFilter( rFilterName, rExtension ); + + if ( !maSelectFilter.getLength() ) + maSelectFilter = rFilterName; + } + catch( IllegalArgumentException ) + { +#ifdef DBG_UTIL + ByteString aMsg( "Could not append Filter" ); + aMsg += ByteString( String( rFilterName ), RTL_TEXTENCODING_UTF8 ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#endif + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::addGraphicFilter() +{ + uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); + + if ( ! xFltMgr.is() ) + return; + + // create the list of filters + mpGraphicFilter = new GraphicFilter; + USHORT i, j, nCount = mpGraphicFilter->GetImportFormatCount(); + + // compute the extension string for all known import filters + String aExtensions; + + for ( i = 0; i < nCount; i++ ) + { + j = 0; + String sWildcard; + while( TRUE ) + { + sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ ); + if ( !sWildcard.Len() ) + break; + if ( aExtensions.Search( sWildcard ) == STRING_NOTFOUND ) + { + if ( aExtensions.Len() ) + aExtensions += sal_Unicode(';'); + aExtensions += sWildcard; + } + } + } + +#if defined(WNT) + if ( aExtensions.Len() > 240 ) + aExtensions = DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL ); +#endif + sal_Bool bIsInOpenMode = isInOpenMode(); + + try + { + OUString aAllFilterName = String( SfxResId( STR_SFX_IMPORT_ALL ) ); + aAllFilterName = ::sfx2::addExtension( aAllFilterName, aExtensions, bIsInOpenMode, *this ); + + xFltMgr->appendFilter( aAllFilterName, aExtensions ); + maSelectFilter = aAllFilterName; + } + catch( IllegalArgumentException ) + { + DBG_ERRORFILE( "Could not append Filter" ); + } + + // Now add the filter + for ( i = 0; i < nCount; i++ ) + { + String aName = mpGraphicFilter->GetImportFormatName( i ); + String aExt; + j = 0; + String sWildcard; + while( TRUE ) + { + sWildcard = mpGraphicFilter->GetImportWildcard( i, j++ ); + if ( !sWildcard.Len() ) + break; + if ( aExt.Search( sWildcard ) == STRING_NOTFOUND ) + { + if ( aExt.Len() ) + aExt += sal_Unicode(';'); + aExt += sWildcard; + } + } + aName = ::sfx2::addExtension( aName, aExt, bIsInOpenMode, *this ); + try + { + xFltMgr->appendFilter( aName, aExt ); + } + catch( IllegalArgumentException ) + { + DBG_ERRORFILE( "Could not append Filter" ); + } + } +} + +// ------------------------------------------------------------------------ +#define GRF_CONFIG_STR " " +#define STD_CONFIG_STR "1 " + +void FileDialogHelper_Impl::saveConfig() +{ + uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY ); + Any aValue; + + if ( ! xDlg.is() ) + return; + + if ( mbHasPreview ) + { + SvtViewOptions aDlgOpt( E_DIALOG, IMPGRF_CONFIGNAME ); + String aUserData = DEFINE_CONST_UNICODE( GRF_CONFIG_STR ); + + try + { + aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0 ); + sal_Bool bValue = sal_False; + aValue >>= bValue; + aUserData.SetToken( 0, ' ', String::CreateFromInt32( (sal_Int32) bValue ) ); + + aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 ); + bValue = sal_False; + aValue >>= bValue; + aUserData.SetToken( 1, ' ', String::CreateFromInt32( (sal_Int32) bValue ) ); + + INetURLObject aObj( getPath() ); + + if ( aObj.GetProtocol() == INET_PROT_FILE ) + aUserData.SetToken( 2, ' ', aObj.GetMainURL( INetURLObject::NO_DECODE ) ); + + String aFilter = getFilter(); + aFilter = EncodeSpaces_Impl( aFilter ); + aUserData.SetToken( 3, ' ', aFilter ); + + aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aUserData ) ) ); + } + catch( IllegalArgumentException ){} + } + else + { + sal_Bool bWriteConfig = sal_False; + SvtViewOptions aDlgOpt( E_DIALOG, IODLG_CONFIGNAME ); + String aUserData = DEFINE_CONST_UNICODE( STD_CONFIG_STR ); + + if ( aDlgOpt.Exists() ) + { + Any aUserItem = aDlgOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + aUserData = String( aTemp ); + } + + if ( mbHasAutoExt ) + { + try + { + aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0 ); + sal_Bool bAutoExt = sal_True; + aValue >>= bAutoExt; + aUserData.SetToken( 0, ' ', String::CreateFromInt32( (sal_Int32) bAutoExt ) ); + bWriteConfig = sal_True; + } + catch( IllegalArgumentException ){} + } + + if ( ! mbIsSaveDlg ) + { + OUString aPath = getPath(); + if ( aPath.getLength() && + utl::LocalFileHelper::IsLocalFile( aPath ) ) + { + aUserData.SetToken( 1, ' ', aPath ); + bWriteConfig = sal_True; + } + } + + if( mbHasSelectionBox && mbSelectionFltrEnabled ) + { + try + { + aValue = xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0 ); + sal_Bool bSelection = sal_True; + aValue >>= bSelection; + if ( aUserData.GetTokenCount(' ') < 3 ) + aUserData.Append(' '); + aUserData.SetToken( 2, ' ', String::CreateFromInt32( (sal_Int32) bSelection ) ); + bWriteConfig = sal_True; + } + catch( IllegalArgumentException ){} + } + + if ( bWriteConfig ) + aDlgOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aUserData ) ) ); + } + + SfxApplication *pSfxApp = SFX_APP(); + pSfxApp->SetLastDir_Impl( getPath() ); +} + +// ------------------------------------------------------------------------ +namespace +{ + static ::rtl::OUString getInitPath( const String& _rFallback, const xub_StrLen _nFallbackToken ) + { + SfxApplication *pSfxApp = SFX_APP(); + String sPath = pSfxApp->GetLastDir_Impl(); + + if ( !sPath.Len() ) + sPath = _rFallback.GetToken( _nFallbackToken, ' ' ); + + // check if the path points to a valid (accessible) directory + sal_Bool bValid = sal_False; + if ( sPath.Len() ) + { + String sPathCheck( sPath ); + if ( sPathCheck.GetBuffer()[ sPathCheck.Len() - 1 ] != '/' ) + sPathCheck += '/'; + sPathCheck += '.'; + try + { + ::ucbhelper::Content aContent( sPathCheck, uno::Reference< ucb::XCommandEnvironment >() ); + bValid = aContent.isFolder(); + } + catch( Exception& ) {} + } + + if ( !bValid ) + sPath.Erase(); + + return sPath; + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::loadConfig() +{ + uno::Reference < XFilePickerControlAccess > xDlg( mxFileDlg, UNO_QUERY ); + Any aValue; + + if ( ! xDlg.is() ) + return; + + if ( mbHasPreview ) + { + SvtViewOptions aViewOpt( E_DIALOG, IMPGRF_CONFIGNAME ); + String aUserData; + + if ( aViewOpt.Exists() ) + { + Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + aUserData = String( aTemp ); + } + + if ( aUserData.Len() > 0 ) + { + try + { + // respect the last "insert as link" state + sal_Bool bLink = (sal_Bool) aUserData.GetToken( 0, ' ' ).ToInt32(); + if ( !xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0 ).hasValue() ) + { + aValue <<= bLink; + xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, aValue ); + } + + // respect the last "show preview" state + sal_Bool bShowPreview = (sal_Bool) aUserData.GetToken( 1, ' ' ).ToInt32(); + if ( !xDlg->getValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0 ).hasValue() ) + { + aValue <<= bShowPreview; + xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, aValue ); + } + + if ( !maPath.getLength() ) + displayFolder( getInitPath( aUserData, 2 ) ); + + if ( ! maCurFilter.getLength() ) + { + String aFilter = aUserData.GetToken( 3, ' ' ); + aFilter = DecodeSpaces_Impl( aFilter ); + setFilter( aFilter ); + } + + // set the member so we know that we have to show the preview + mbShowPreview = bShowPreview; + } + catch( IllegalArgumentException ){} + } + + if ( !maPath.getLength() ) + displayFolder( SvtPathOptions().GetGraphicPath() ); + } + else + { + SvtViewOptions aViewOpt( E_DIALOG, IODLG_CONFIGNAME ); + String aUserData; + + if ( aViewOpt.Exists() ) + { + Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + aUserData = String( aTemp ); + } + + if ( ! aUserData.Len() ) + aUserData = DEFINE_CONST_UNICODE( STD_CONFIG_STR ); + + if ( ! maPath.getLength() ) + displayFolder( getInitPath( aUserData, 1 ) ); + + if ( mbHasAutoExt ) + { + sal_Int32 nFlag = aUserData.GetToken( 0, ' ' ).ToInt32(); + aValue <<= (sal_Bool) nFlag; + try + { + xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, aValue ); + } + catch( IllegalArgumentException ){} + } + + if( mbHasSelectionBox ) + { + sal_Int32 nFlag = aUserData.GetToken( 2, ' ' ).ToInt32(); + aValue <<= (sal_Bool) nFlag; + try + { + xDlg->setValue( ExtendedFilePickerElementIds::CHECKBOX_SELECTION, 0, aValue ); + } + catch( IllegalArgumentException ){} + } + + if ( !maPath.getLength() ) + displayFolder( SvtPathOptions().GetWorkPath() ); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper_Impl::setDefaultValues() +{ + // when no filter is set, we set the curentFilter to <all> + if ( !maCurFilter.getLength() && maSelectFilter.getLength() ) + { + uno::Reference< XFilterManager > xFltMgr( mxFileDlg, UNO_QUERY ); + try + { + xFltMgr->setCurrentFilter( maSelectFilter ); + } + catch( IllegalArgumentException ) + {} + } + + // when no path is set, we use the standard 'work' folder + if ( ! maPath.getLength() ) + { + OUString aWorkFolder = SvtPathOptions().GetWorkPath(); + try + { + mxFileDlg->setDisplayDirectory( aWorkFolder ); + } + catch( const Exception& ) + { + DBG_ERROR( "FileDialogHelper_Impl::setDefaultValues: caught an exception while setting the display directory!" ); + } + + // INetURLObject aStdDirObj( SvtPathOptions().GetWorkPath() ); + //SetStandardDir( aStdDirObj.GetMainURL( INetURLObject::NO_DECODE ) ); + } +} + +sal_Bool FileDialogHelper_Impl::isShowFilterExtensionEnabled() const +{ + return !maFilters.empty(); +} + +void FileDialogHelper_Impl::addFilterPair( const OUString& rFilter, + const OUString& rFilterWithExtension ) +{ + maFilters.push_back( FilterPair( rFilter, rFilterWithExtension ) ); + +} + +OUString FileDialogHelper_Impl::getFilterName( const OUString& rFilterWithExtension ) const +{ + OUString sRet; + for( ::std::vector< FilterPair >::const_iterator pIter = maFilters.begin(); pIter != maFilters.end(); ++pIter ) + { + if ( (*pIter).Second == rFilterWithExtension ) + { + sRet = (*pIter).First; + break; + } + } + return sRet; +} + +OUString FileDialogHelper_Impl::getFilterWithExtension( const OUString& rFilter ) const +{ + OUString sRet; + for( ::std::vector< FilterPair >::const_iterator pIter = maFilters.begin(); pIter != maFilters.end(); ++pIter ) + { + if ( (*pIter).First == rFilter ) + { + sRet = (*pIter).Second; + break; + } + } + return sRet; +} + +void FileDialogHelper_Impl::SetContext( FileDialogHelper::Context _eNewContext ) +{ + meContext = _eNewContext; + + sal_Int32 nNewHelpId = 0; + OUString aConfigId; + + switch( _eNewContext ) + { +// #104952# dependency to SVX not allowed! When used again, another solution has to be found +// case FileDialogHelper::SW_INSERT_GRAPHIC: +// case FileDialogHelper::SC_INSERT_GRAPHIC: +// case FileDialogHelper::SD_INSERT_GRAPHIC: nNewHelpId = SID_INSERT_GRAPHIC; break; + case FileDialogHelper::SW_INSERT_SOUND: + case FileDialogHelper::SC_INSERT_SOUND: + case FileDialogHelper::SD_INSERT_SOUND: nNewHelpId = SID_INSERT_SOUND; break; + case FileDialogHelper::SW_INSERT_VIDEO: + case FileDialogHelper::SC_INSERT_VIDEO: + case FileDialogHelper::SD_INSERT_VIDEO: nNewHelpId = SID_INSERT_VIDEO; break; + default: break; + } + + const OUString* pConfigId = GetLastFilterConfigId( _eNewContext ); + if( pConfigId ) + LoadLastUsedFilter( *pConfigId ); + +// if( nNewHelpId ) +// this->setDialogHelpId( nNewHelpId ); +} + +// ------------------------------------------------------------------------ +// ----------- FileDialogHelper --------------------------- +// ------------------------------------------------------------------------ + +FileDialogHelper::FileDialogHelper( + sal_Int64 nFlags, + const String& rFact, + SfxFilterFlags nMust, + SfxFilterFlags nDont ) +{ + mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags ); + mxImp = mpImp; + + // create the list of filters + mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); +} + +FileDialogHelper::FileDialogHelper( + sal_Int64 nFlags, + const String& rFact, + sal_Int16 nDialog, + SfxFilterFlags nMust, + SfxFilterFlags nDont, + const String& rStandardDir, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList) +{ + mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags, nDialog, NULL , rStandardDir, rBlackList ); + mxImp = mpImp; + + // create the list of filters + mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); +} + +FileDialogHelper::FileDialogHelper( + sal_Int64 nFlags, + const String& rFact, + sal_Int16 nDialog, + SfxFilterFlags nMust, + SfxFilterFlags nDont ) +{ + mpImp = new FileDialogHelper_Impl( this, getDialogType( nFlags ), nFlags, nDialog ); + mxImp = mpImp; + + // create the list of filters + mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); +} + +// ------------------------------------------------------------------------ +FileDialogHelper::FileDialogHelper( sal_Int64 nFlags ) +{ + sal_Int16 nDialogType = getDialogType( nFlags ); + + mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags ); + mxImp = mpImp; +} + +// ------------------------------------------------------------------------ +FileDialogHelper::FileDialogHelper( + sal_Int16 nDialogType, + sal_Int64 nFlags, + const String& rFact, + SfxFilterFlags nMust, + SfxFilterFlags nDont ) +{ + mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags ); + mxImp = mpImp; + + // create the list of filters + mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); +} + +// ------------------------------------------------------------------------ +FileDialogHelper::FileDialogHelper( + sal_Int16 nDialogType, + sal_Int64 nFlags, + const String& rFact, + sal_Int16 nDialog, + SfxFilterFlags nMust, + SfxFilterFlags nDont, + const String& rStandardDir, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList) +{ + mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, nDialog, NULL, rStandardDir, rBlackList ); + mxImp = mpImp; + + // create the list of filters + mpImp->addFilters( nFlags, SfxObjectShell::GetServiceNameFromFactory(rFact), nMust, nDont ); +} + +// ------------------------------------------------------------------------ +FileDialogHelper::FileDialogHelper( + sal_Int16 nDialogType, + sal_Int64 nFlags, + Window* _pPreferredParent ) +{ + mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, _pPreferredParent ); + mxImp = mpImp; +} + +// ------------------------------------------------------------------------ +FileDialogHelper::FileDialogHelper( + sal_Int16 nDialogType, + sal_Int64 nFlags, + const ::rtl::OUString& aFilterUIName, + const ::rtl::OUString& aExtName, + const ::rtl::OUString& rStandardDir, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList, + Window* _pPreferredParent ) +{ + mpImp = new FileDialogHelper_Impl( this, nDialogType, nFlags, SFX2_IMPL_DIALOG_CONFIG, _pPreferredParent,rStandardDir, rBlackList ); + mxImp = mpImp; + + // the wildcard here is expected in form "*.extension" + ::rtl::OUString aWildcard; + if ( aExtName.indexOf( (sal_Unicode)'*' ) != 0 ) + { + if ( aExtName.getLength() && aExtName.indexOf( (sal_Unicode)'.' ) != 0 ) + aWildcard = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*." ) ); + else + aWildcard = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*" ) ); + } + + aWildcard += aExtName; + + ::rtl::OUString aUIString = + ::sfx2::addExtension( aFilterUIName, aWildcard, ( WB_OPEN == ( nFlags & WB_OPEN ) ), *mpImp ); + AddFilter( aUIString, aWildcard ); +} + +// ------------------------------------------------------------------------ +FileDialogHelper::~FileDialogHelper() +{ + mpImp->dispose(); + mxImp.clear(); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::CreateMatcher( const String& rFactory ) +{ + mpImp->createMatcher( SfxObjectShell::GetServiceNameFromFactory(rFactory) ); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::SetControlHelpIds( const sal_Int16* _pControlId, const sal_Int32* _pHelpId ) +{ + mpImp->setControlHelpIds( _pControlId, _pHelpId ); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::SetDialogHelpId( const sal_Int32 _nHelpId ) +{ + mpImp->setDialogHelpId( _nHelpId ); +} + +void FileDialogHelper::SetContext( Context _eNewContext ) +{ + mpImp->SetContext( _eNewContext ); +} + +// ------------------------------------------------------------------------ +IMPL_LINK( FileDialogHelper, ExecuteSystemFilePicker, void*, EMPTYARG ) +{ + m_nError = mpImp->execute(); + if ( m_aDialogClosedLink.IsSet() ) + m_aDialogClosedLink.Call( this ); + + return 0L; +} + +// ------------------------------------------------------------------------ +// rDirPath has to be a directory +ErrCode FileDialogHelper::Execute( SvStringsDtor*& rpURLList, + SfxItemSet *& rpSet, + String& rFilter, + const String& rDirPath ) +{ + SetDisplayFolder( rDirPath ); + return mpImp->execute( rpURLList, rpSet, rFilter ); +} + + +// ------------------------------------------------------------------------ +ErrCode FileDialogHelper::Execute() +{ + return mpImp->execute(); +} + +// ------------------------------------------------------------------------ +ErrCode FileDialogHelper::Execute( SfxItemSet *& rpSet, + String& rFilter ) +{ + ErrCode nRet; + SvStringsDtor* pURLList; + + nRet = mpImp->execute( pURLList, rpSet, rFilter ); + + delete pURLList; + + return nRet; +} + +void FileDialogHelper::StartExecuteModal( const Link& rEndDialogHdl ) +{ + m_aDialogClosedLink = rEndDialogHdl; + m_nError = ERRCODE_NONE; + if ( mpImp->isSystemFilePicker() ) + Application::PostUserEvent( LINK( this, FileDialogHelper, ExecuteSystemFilePicker ) ); + else + mpImp->implStartExecute(); +} + +// ------------------------------------------------------------------------ + +short FileDialogHelper::GetDialogType() const +{ + return mpImp ? mpImp->m_nDialogType : 0; +} + +// ------------------------------------------------------------------------ + +sal_Bool FileDialogHelper::IsPasswordEnabled() const +{ + return mpImp ? mpImp->isPasswordEnabled() : sal_False; +} + +// ------------------------------------------------------------------------ + +String FileDialogHelper::GetRealFilter() const +{ + String sFilter; + if ( mpImp ) + mpImp->getRealFilter( sFilter ); + return sFilter; +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::SetTitle( const String& rNewTitle ) +{ + if ( mpImp->mxFileDlg.is() ) + mpImp->mxFileDlg->setTitle( rNewTitle ); +} + +// ------------------------------------------------------------------------ +String FileDialogHelper::GetPath() const +{ + OUString aPath; + + if ( mpImp->mlLastURLs.size() > 0) + return mpImp->mlLastURLs[0]; + + if ( mpImp->mxFileDlg.is() ) + { + Sequence < OUString > aPathSeq = mpImp->mxFileDlg->getFiles(); + + if ( aPathSeq.getLength() == 1 ) + { + aPath = aPathSeq[0]; + } + } + + return aPath; +} + +// ------------------------------------------------------------------------ +Sequence < OUString > FileDialogHelper::GetMPath() const +{ + if ( mpImp->mlLastURLs.size() > 0) + return mpImp->mlLastURLs.getAsConstList(); + + if ( mpImp->mxFileDlg.is() ) + return mpImp->mxFileDlg->getFiles(); + else + { + Sequence < OUString > aEmpty; + return aEmpty; + } +} + +// ------------------------------------------------------------------------ +Sequence< ::rtl::OUString > FileDialogHelper::GetSelectedFiles() const +{ + // a) the new way (optional!) + uno::Sequence< ::rtl::OUString > aResultSeq; + uno::Reference< XFilePicker2 > xPickNew(mpImp->mxFileDlg, UNO_QUERY); + if (xPickNew.is()) + { + aResultSeq = xPickNew->getSelectedFiles(); + } + // b) the olde way ... non optional. + else + { + uno::Reference< XFilePicker > xPickOld(mpImp->mxFileDlg, UNO_QUERY_THROW); + Sequence< OUString > lFiles = xPickOld->getFiles(); + ::sal_Int32 nFiles = lFiles.getLength(); + if ( nFiles > 1 ) + { + aResultSeq = Sequence< ::rtl::OUString >( nFiles-1 ); + + INetURLObject aPath( lFiles[0] ); + aPath.setFinalSlash(); + + for (::sal_Int32 i = 1; i < nFiles; i++) + { + if (i == 1) + aPath.Append( lFiles[i] ); + else + aPath.setName( lFiles[i] ); + + aResultSeq[i-1] = ::rtl::OUString(aPath.GetMainURL( INetURLObject::NO_DECODE )); + } + } + else + aResultSeq = lFiles; + } + + return aResultSeq; +} + +// ------------------------------------------------------------------------ +String FileDialogHelper::GetDisplayDirectory() const +{ + return mpImp->getPath(); +} + +// ------------------------------------------------------------------------ +String FileDialogHelper::GetCurrentFilter() const +{ + return mpImp->getFilter(); +} + +// ------------------------------------------------------------------------ +ErrCode FileDialogHelper::GetGraphic( Graphic& rGraphic ) const +{ + return mpImp->getGraphic( rGraphic ); +} + +// ------------------------------------------------------------------------ +static int impl_isFolder( const OUString& rPath ) +{ + uno::Reference< task::XInteractionHandler > xHandler; + try + { + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + xHandler.set( xFactory->createInstance( DEFINE_CONST_OUSTRING( "com.sun.star.task.InteractionHandler" ) ), + uno::UNO_QUERY_THROW ); + } + catch ( Exception const & ) + { + } + + ::rtl::Reference< ::comphelper::StillReadWriteInteraction > aHandler = new ::comphelper::StillReadWriteInteraction( xHandler ); + + try + { + ::ucbhelper::Content aContent( + rPath, new ::ucbhelper::CommandEnvironment( static_cast< task::XInteractionHandler* > ( aHandler.get() ), uno::Reference< ucb::XProgressHandler >() ) ); + if ( aContent.isFolder() ) + return 1; + + return 0; + } + catch ( Exception const & ) + { + } + + return -1; +} + +void FileDialogHelper::SetDisplayDirectory( const String& _rPath ) +{ + if ( !_rPath.Len() ) + return; + + // if the given path isn't a folder, we cut off the last part + // and take it as filename and the rest of the path should be + // the folder + + INetURLObject aObj( _rPath ); + + ::rtl::OUString sFileName = aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ); + aObj.removeSegment(); + ::rtl::OUString sPath = aObj.GetMainURL( INetURLObject::NO_DECODE ); + + int nIsFolder = impl_isFolder( _rPath ); + if ( nIsFolder == 0 || + ( nIsFolder == -1 && impl_isFolder( sPath ) == 1 ) ) + { + mpImp->setFileName( sFileName ); + mpImp->displayFolder( sPath ); + } + else + { + INetURLObject aObjPathName( _rPath ); + ::rtl::OUString sFolder( aObjPathName.GetMainURL( INetURLObject::NO_DECODE ) ); + if ( sFolder.getLength() == 0 ) + { + // _rPath is not a valid path -> fallback to home directory + vos:: OSecurity aSecurity; + aSecurity.getHomeDir( sFolder ); + } + mpImp->displayFolder( sFolder ); + } +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::SetDisplayFolder( const String& _rURL ) +{ + mpImp->displayFolder( _rURL ); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::SetFileName( const String& _rFileName ) +{ + mpImp->setFileName( _rFileName ); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::AddFilter( const String& rFilterName, + const String& rExtension ) +{ + mpImp->addFilter( rFilterName, rExtension ); +} + +// ------------------------------------------------------------------------ +void FileDialogHelper::SetCurrentFilter( const String& rFilter ) +{ + String sFilter( rFilter ); + if ( mpImp->isShowFilterExtensionEnabled() ) + sFilter = mpImp->getFilterWithExtension( rFilter ); + mpImp->setFilter( sFilter ); +} + +// ------------------------------------------------------------------------ +uno::Reference < XFilePicker > FileDialogHelper::GetFilePicker() const +{ + return mpImp->mxFileDlg; +} + +// ------------------------------------------------------------------------ +sal_Int16 FileDialogHelper::getDialogType( sal_Int64 nFlags ) const +{ + sal_Int16 nDialogType = FILEOPEN_SIMPLE; + + if ( nFlags & WB_SAVEAS ) + { + if ( nFlags & SFXWB_PASSWORD ) + nDialogType = FILESAVE_AUTOEXTENSION_PASSWORD; + else + nDialogType = FILESAVE_SIMPLE; + } + else if ( nFlags & SFXWB_GRAPHIC ) + { + if ( nFlags & SFXWB_SHOWSTYLES ) + nDialogType = FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE; + else + nDialogType = FILEOPEN_LINK_PREVIEW; + } + else if ( SFXWB_INSERT != ( nFlags & SFXWB_INSERT ) ) + nDialogType = FILEOPEN_READONLY_VERSION; + + return nDialogType; +} + +// ------------------------------------------------------------------------ +// XFilePickerListener Methods +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper::FileSelectionChanged( const FilePickerEvent& aEvent ) +{ + mpImp->handleFileSelectionChanged( aEvent ); +} + +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper::DirectoryChanged( const FilePickerEvent& aEvent ) +{ + mpImp->handleDirectoryChanged( aEvent ); +} + +// ------------------------------------------------------------------------ +OUString SAL_CALL FileDialogHelper::HelpRequested( const FilePickerEvent& aEvent ) +{ + return mpImp->handleHelpRequested( aEvent ); +} + +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper::ControlStateChanged( const FilePickerEvent& aEvent ) +{ + mpImp->handleControlStateChanged( aEvent ); +} + +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper::DialogSizeChanged() +{ + mpImp->handleDialogSizeChanged(); +} + +// ------------------------------------------------------------------------ +void SAL_CALL FileDialogHelper::DialogClosed( const DialogClosedEvent& _rEvent ) +{ + m_nError = ( RET_OK == _rEvent.DialogResult ) ? ERRCODE_NONE : ERRCODE_ABORT; + if ( m_aDialogClosedLink.IsSet() ) + m_aDialogClosedLink.Call( this ); +} + +// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ + +ErrCode FileOpenDialog_Impl( sal_Int64 nFlags, + const String& rFact, + SvStringsDtor *& rpURLList, + String& rFilter, + SfxItemSet *& rpSet, + const String* pPath, + sal_Int16 nDialog, + const String& rStandardDir, + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList ) +{ + ErrCode nRet; + FileDialogHelper aDialog( nFlags, rFact, nDialog, 0, 0, rStandardDir, rBlackList ); + + String aPath; + if ( pPath ) + aPath = *pPath; + + nRet = aDialog.Execute( rpURLList, rpSet, rFilter, aPath ); + DBG_ASSERT( rFilter.SearchAscii(": ") == STRING_NOTFOUND, "Old filter name used!"); + + return nRet; +} + + +// ------------------------------------------------------------------------ +String EncodeSpaces_Impl( const String& rSource ) +{ + String sRet( rSource ); + sRet.SearchAndReplaceAll( DEFINE_CONST_UNICODE( " " ), DEFINE_CONST_UNICODE( "%20" ) ); + return sRet; +} + +// ------------------------------------------------------------------------ +String DecodeSpaces_Impl( const String& rSource ) +{ + String sRet( rSource ); + sRet.SearchAndReplaceAll( DEFINE_CONST_UNICODE( "%20" ), DEFINE_CONST_UNICODE( " " ) ); + return sRet; +} + +// ------------------------------------------------------------------------ + +} // end of namespace sfx2 + diff --git a/sfx2/source/dialog/filedlghelper.src b/sfx2/source/dialog/filedlghelper.src new file mode 100644 index 000000000000..61df13350510 --- /dev/null +++ b/sfx2/source/dialog/filedlghelper.src @@ -0,0 +1,173 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// includes ****************************************************************** + +#include "sfxlocal.hrc" +#include "filedlghelper.hrc" + +//#include "helpid.hrc" + +// strings ******************************************************************* + +String STR_SFX_FILEDLG_ACTUALVERSION +{ + Text [ en-US ] = "Current version"; +}; + +String STR_SFX_EXPLORERFILE_EXPORT +{ + Text [ en-US ] = "Export"; +}; + +String STR_SFX_EXPLORERFILE_INSERT +{ + Text [ en-US ] = "Insert" ; +}; + +String STR_SFX_EXPLORERFILE_BUTTONINSERT +{ + Text [ en-US ] = "~Insert" ; +}; + +String STR_SFX_IMPORT_ALL +{ + Text [ en-US ] = "<All formats>" ; +}; + +String STR_CB_AUTO_EXTENSION +{ + Text [ en-US ] = "~Automatic file name extension" ; +}; + +String STR_CB_SELECTION +{ + Text [ en-US ] = "~Selection" ; +}; + +String STR_CB_INSERT_AS_LINK +{ + Text [ en-US ] = "~Link" ; +}; + +String STR_CB_SHOW_PREVIEW +{ + Text [ en-US ] = "Pr~eview" ; +}; + +String STR_CB_READONLY +{ + Text [ en-US ] = "~Read-only" ; +}; + +String STR_CB_PASSWORD +{ + Text [ en-US ] = "Save with ~password" ; +}; + +String STR_CB_FILTER_OPTIONS +{ + Text [ en-US ] = "Edit ~filter settings"; +}; + +String STR_PB_PLAY +{ + Text [ en-US ] = "~Play" ; +}; + +String STR_PB_STOP +{ + Text [ en-US ] = "Sto~p" ; +}; + +String STR_PB_OPEN +{ + Text [ en-US ] = "~Open" ; +}; + +String STR_PB_SAVE +{ + Text [ en-US ] = "~Save" ; +}; + +String STR_LB_IMAGE_TEMPLATE +{ + Text [ en-US ] = "Style:" ; +}; + +String STR_LB_TEMPLATES +{ + Text [ en-US ] = "~Templates:" ; +}; + +String STR_LB_VERSION +{ + Text [ en-US ] = "~Version:"; +}; + +//******************************************************************** EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/filedlgimpl.hxx b/sfx2/source/dialog/filedlgimpl.hxx new file mode 100644 index 000000000000..6965e14ae84d --- /dev/null +++ b/sfx2/source/dialog/filedlgimpl.hxx @@ -0,0 +1,239 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SFX_FILEDLGIMPL_HXX +#define _SFX_FILEDLGIMPL_HXX + +#include <vcl/timer.hxx> +#include <vcl/graph.hxx> +#include <cppuhelper/implbase2.hxx> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/ui/dialogs/XDialogClosedListener.hpp> +#include <sfx2/fcontnr.hxx> + +#define _SVSTDARR_STRINGSDTOR +#include <svl/svstdarr.hxx> + +#include <sfx2/filedlghelper.hxx> +#include <comphelper/sequenceasvector.hxx> + +class SfxFilterMatcher; +class GraphicFilter; +class FileDialogHelper; + +namespace sfx2 +{ + typedef ::com::sun::star::beans::StringPair FilterPair; + + class FileDialogHelper_Impl : + public ::cppu::WeakImplHelper2< + ::com::sun::star::ui::dialogs::XFilePickerListener, + ::com::sun::star::ui::dialogs::XDialogClosedListener > + { + friend class FileDialogHelper; + + ::com::sun::star::uno::Reference < ::com::sun::star::ui::dialogs::XFilePicker > mxFileDlg; + ::com::sun::star::uno::Reference < ::com::sun::star::container::XNameAccess > mxFilterCFG; + + std::vector< FilterPair > maFilters; + + SfxFilterMatcher* mpMatcher; + GraphicFilter* mpGraphicFilter; + FileDialogHelper* mpAntiImpl; + Window* mpPreferredParentWindow; + + ::comphelper::SequenceAsVector< ::rtl::OUString > mlLastURLs; + + ::rtl::OUString maPath; + ::rtl::OUString maFileName; + ::rtl::OUString maCurFilter; + ::rtl::OUString maSelectFilter; + ::rtl::OUString maButtonLabel; + + Timer maPreViewTimer; + Graphic maGraphic; + + const short m_nDialogType; + + SfxFilterFlags m_nMustFlags; + SfxFilterFlags m_nDontFlags; + + ULONG mnPostUserEventId; + + ErrCode mnError; + + FileDialogHelper::Context meContext; + + sal_Bool mbHasPassword : 1; + sal_Bool mbIsPwdEnabled : 1; + sal_Bool m_bHaveFilterOptions : 1; + sal_Bool mbHasVersions : 1; + sal_Bool mbHasAutoExt : 1; + sal_Bool mbHasLink : 1; + sal_Bool mbHasPreview : 1; + sal_Bool mbShowPreview : 1; + sal_Bool mbIsSaveDlg : 1; + sal_Bool mbExport : 1; + + sal_Bool mbDeleteMatcher : 1; + sal_Bool mbInsert : 1; + sal_Bool mbSystemPicker : 1; + sal_Bool mbPwdCheckBoxState : 1; + sal_Bool mbSelection : 1; + sal_Bool mbSelectionEnabled : 1; + sal_Bool mbHasSelectionBox : 1; + sal_Bool mbSelectionFltrEnabled : 1; + + private: + void addFilters( sal_Int64 nFlags, + const String& rFactory, + SfxFilterFlags nMust, + SfxFilterFlags nDont ); + void addFilter( const ::rtl::OUString& rFilterName, + const ::rtl::OUString& rExtension ); + void addGraphicFilter(); + void enablePasswordBox( sal_Bool bInit ); + void updateFilterOptionsBox(); + void updateExportButton(); + void updateSelectionBox(); + void updateVersions(); + void updatePreviewState( sal_Bool _bUpdatePreviewWindow = sal_True ); + void dispose(); + + void loadConfig(); + void saveConfig(); + + const SfxFilter* getCurentSfxFilter(); + sal_Bool updateExtendedControl( sal_Int16 _nExtendedControlId, sal_Bool _bEnable ); + + ErrCode getGraphic( const ::rtl::OUString& rURL, Graphic& rGraphic ) const; + void setDefaultValues(); + + void preExecute(); + void postExecute( sal_Int16 _nResult ); + sal_Int16 implDoExecute(); + void implStartExecute(); + + void correctVirtualDialogType(); + + void setControlHelpIds( const sal_Int16* _pControlId, const sal_Int32* _pHelpId ); + void setDialogHelpId( const sal_Int32 _nHelpId ); + + sal_Bool CheckFilterOptionsCapability( const SfxFilter* _pFilter ); + + sal_Bool isInOpenMode() const; + String getCurrentFilterUIName() const; + + void LoadLastUsedFilter( const ::rtl::OUString& _rContextIdentifier ); + void SaveLastUsedFilter( const ::rtl::OUString& _rContextIdentifier ); + void SaveLastUsedFilter( void ); + + void implInitializeFileName( ); + + void implGetAndCacheFiles( const ::com::sun::star::uno::Reference< XInterface >& xPicker , + SvStringsDtor*& rpURLList, + const SfxFilter* pFilter ); + String implEnsureURLExtension(const String& sURL , + const String& sExtension); + + DECL_LINK( TimeOutHdl_Impl, Timer* ); + DECL_LINK( HandleEvent, FileDialogHelper* ); + DECL_LINK( InitControls, void* ); + + public: + // XFilePickerListener methods + virtual void SAL_CALL fileSelectionChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL directoryChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL helpRequested( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL controlStateChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL dialogSizeChanged() throw( ::com::sun::star::uno::RuntimeException ); + + // XDialogClosedListener methods + virtual void SAL_CALL dialogClosed( const ::com::sun::star::ui::dialogs::DialogClosedEvent& _rEvent ) throw (::com::sun::star::uno::RuntimeException); + + // XEventListener methods + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw( ::com::sun::star::uno::RuntimeException ); + + // handle XFilePickerListener events + void handleFileSelectionChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ); + void handleDirectoryChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ); + ::rtl::OUString handleHelpRequested( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ); + void handleControlStateChanged( const ::com::sun::star::ui::dialogs::FilePickerEvent& aEvent ); + void handleDialogSizeChanged(); + + // Own methods + FileDialogHelper_Impl( + FileDialogHelper* _pAntiImpl, + const short nDialogType, + sal_Int64 nFlags, + sal_Int16 nDialog = SFX2_IMPL_DIALOG_CONFIG, + Window* _pPreferredParentWindow = NULL, + const String& sStandardDir = String::CreateFromAscii( "" ), + const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >() + ); + virtual ~FileDialogHelper_Impl(); + + ErrCode execute( SvStringsDtor*& rpURLList, + SfxItemSet *& rpSet, + String& rFilter ); + ErrCode execute(); + + void setFilter( const ::rtl::OUString& rFilter ); + + /** sets the directory which should be browsed + + <p>If the given path does not point to a valid (existent and accessible) folder, the request + is silently dropped</p> + */ + void displayFolder( const ::rtl::OUString& rPath ); + void setFileName( const ::rtl::OUString& _rFile ); + + ::rtl::OUString getPath() const; + ::rtl::OUString getFilter() const; + void getRealFilter( String& _rFilter ) const; + + ErrCode getGraphic( Graphic& rGraphic ) const; + void createMatcher( const String& rFactory ); + + sal_Bool isShowFilterExtensionEnabled() const; + void addFilterPair( const ::rtl::OUString& rFilter, + const ::rtl::OUString& rFilterWithExtension ); + ::rtl::OUString getFilterName( const ::rtl::OUString& rFilterWithExtension ) const; + ::rtl::OUString getFilterWithExtension( const ::rtl::OUString& rFilter ) const; + + void SetContext( FileDialogHelper::Context _eNewContext ); + + inline sal_Bool isSystemFilePicker() const { return mbSystemPicker; } + inline sal_Bool isPasswordEnabled() const { return mbIsPwdEnabled; } + }; + +} // end of namespace sfx2 + +#endif // _SFX_FILEDLGIMPL_HXX + diff --git a/sfx2/source/dialog/filtergrouping.cxx b/sfx2/source/dialog/filtergrouping.cxx new file mode 100644 index 000000000000..ea2429be8157 --- /dev/null +++ b/sfx2/source/dialog/filtergrouping.cxx @@ -0,0 +1,1274 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include "filtergrouping.hxx" +#include <sfx2/fcontnr.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/sfx.hrc> +#include <sfx2/docfac.hxx> +#include "sfxresid.hxx" +#include <osl/thread.h> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <unotools/confignode.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <tools/wldcrd.hxx> +#include <tools/diagnose_ex.h> + +#include <list> +#include <vector> +#include <map> +#include <algorithm> + +//........................................................................ +namespace sfx2 +{ +//........................................................................ + +//#define DISABLE_GROUPING_AND_CLASSIFYING + // not using the functionallity herein, yet + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::ui::dialogs; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::beans; + using namespace ::utl; + + //==================================================================== + /** + + Some general words about what's going on here .... + + <p>In our file open dialog, usually we display every filter we know. That's how it was before: every filter + lead to an own line in the filter list box, e.g. "StarWriter 5.0 Dokument" or "Microsoft Word 97".</p> + + <p>But then the PM came. And everything changed ....</p> + + <p>A basic idea are groups: Why simply listing all the single filters? Couldn't we draw nice separators + between the filters which logically belong together? I.e. all the filters which open a document in StarWriter: + couldn't we separate them from all the filters which open the document in StarCalc?<br/> + So spoke the PM, and engineering obeyed.</p> + + <p>So we have groups. They're just a visual aspect: All the filters of a group are presented together, separated + by a line from other groups.</p> + + <p>Let's be honest: How the concrete implementation of the file picker service separates the different groups + is a matter of this implementation. We only do this grouping and suggest it to the FilePicker service ...</p> + + <p>Now for the second concept:<br/> + Thinking about it (and that's what the PM did), both "StarWriter 5.0 Dokument" and "Microsoft Word 97" + describe a text document. It's a text. It's of no interest for the user that one of the texts was saved in + MS' format, and one in our own format.<br/> + So in a first step, we want to have a filter entry "Text documents". This would cover both above-mentioned + filters, as well as any other filters for documents which are texts.</p> + + <p>Such an entry as "Text documents" is - within the scope of this file - called "class" or "filter class".</p> + + <p>In the file-open-dialog, such a class looks like an ordinary filter: it's simply a name in the filter + listbox. Selecting means that all the files matching one of the "sub-filters" are displayed (in the example above, + this would be "*.sdw", "*.doc" and so on).</p> + + <p>Now there are two types of filter classes: global ones and local ones. "Text documents" is a global class. As + well as "Spreadsheets". Or "Web pages".<br/> + Let's have a look at a local class: The filters "MS Word 95" and "MS WinWord 6.0" together form the class + "Microsoft Word 6.0 / 95" (don't ask for the reasons. At least not me. Ask the PM). There are a lot of such + local classes ...</p> + + <p>The difference between global and local classes is as follows: Global classes are presented in an own group. + There is one dedicated group at the top of the list, containing all the global groups - no local groups and no + single filters.</p> + + <p>Ehm - it was a lie. Not really at the top. Before this group, there is this single "All files" entry. It forms + it's own group. But this is uninteresting here.</p> + + <p>Local classes must consist of filters which - without the classification - would all belong to the same group. + Then, they're combined to one entry (in the example above: "Microsoft Word 6.0 / 95"), and this entry is inserted + into the file picker filter list, instead of the single filters which form the class.</p> + + <p>This is an interesting difference between local and global classes: Filters which are part of a global class + are listed in there own group, too. Filters in local classes aren't listed a second time - neither directly (as + the filter itself) nor indirectly (as part of another local group).</p> + + <p>The only exception are filters which are part of a global class <em>and</em> a local class. This is allowed. + Beeing cotained in two local classes isn't.</p> + + <p>So that's all what you need to know: Understand the concept of "filter classes" (a filter class combines + different filters and acts as if it's a filter itself) and the concept of groups (a group just describes a + logical correlation of filters and usually is represented to the user by drawing group separators in the filter + list).</p> + + <p>If you got it, go try understanding this file :).</p> + + */ + + + //==================================================================== + + typedef StringPair FilterDescriptor; // a single filter or a filter class (display name and filter mask) + typedef ::std::list< FilterDescriptor > FilterGroup; // a list of single filter entries + typedef ::std::list< FilterGroup > GroupedFilterList; // a list of all filters, already grouped + + /// the logical name of a filter + typedef ::rtl::OUString FilterName; + + // a struct which holds references from a logical filter name to a filter group entry + // used for quick lookup of classes (means class entries - entries representing a class) + // which a given filter may belong to + typedef ::std::map< ::rtl::OUString, FilterGroup::iterator > FilterGroupEntryReferrer; + + /// a descriptor for a filter class (which in the final dialog is represented by one filter entry) + typedef struct _tagFilterClass + { + ::rtl::OUString sDisplayName; // the display name + Sequence< FilterName > aSubFilters; // the (logical) names of the filter which belong to the class + } FilterClass; + + typedef ::std::list< FilterClass > FilterClassList; + typedef ::std::map< ::rtl::OUString, FilterClassList::iterator > FilterClassReferrer; + + typedef ::std::vector< ::rtl::OUString > StringArray; + +// ======================================================================= +// = reading of configuration data +// ======================================================================= + + //-------------------------------------------------------------------- + void lcl_ReadFilterClass( const OConfigurationNode& _rClassesNode, const ::rtl::OUString& _rLogicalClassName, + FilterClass& /* [out] */ _rClass ) + { + static const ::rtl::OUString sDisplaNameNodeName( RTL_CONSTASCII_USTRINGPARAM( "DisplayName" ) ); + static const ::rtl::OUString sSubFiltersNodeName( RTL_CONSTASCII_USTRINGPARAM( "Filters" ) ); + + // the description node for the current class + OConfigurationNode aClassDesc = _rClassesNode.openNode( _rLogicalClassName ); + + // the values + aClassDesc.getNodeValue( sDisplaNameNodeName ) >>= _rClass.sDisplayName; + aClassDesc.getNodeValue( sSubFiltersNodeName ) >>= _rClass.aSubFilters; + } + + //-------------------------------------------------------------------- + struct CreateEmptyClassRememberPos : public ::std::unary_function< FilterName, void > + { + protected: + FilterClassList& m_rClassList; + FilterClassReferrer& m_rClassesReferrer; + + public: + CreateEmptyClassRememberPos( FilterClassList& _rClassList, FilterClassReferrer& _rClassesReferrer ) + :m_rClassList ( _rClassList ) + ,m_rClassesReferrer ( _rClassesReferrer ) + { + } + + // operate on a single class name + void operator() ( const FilterName& _rLogicalFilterName ) + { + // insert a new (empty) class + m_rClassList.push_back( FilterClass() ); + // get the position of this new entry + FilterClassList::iterator aInsertPos = m_rClassList.end(); + --aInsertPos; + // remember this position + m_rClassesReferrer.insert( FilterClassReferrer::value_type( _rLogicalFilterName, aInsertPos ) ); + } + }; + + //-------------------------------------------------------------------- + struct ReadGlobalFilter : public ::std::unary_function< FilterName, void > + { + protected: + OConfigurationNode m_aClassesNode; + FilterClassReferrer& m_aClassReferrer; + + public: + ReadGlobalFilter( const OConfigurationNode& _rClassesNode, FilterClassReferrer& _rClassesReferrer ) + :m_aClassesNode ( _rClassesNode ) + ,m_aClassReferrer ( _rClassesReferrer ) + { + } + + // operate on a single logical name + void operator() ( const FilterName& _rName ) + { + FilterClassReferrer::iterator aClassRef = m_aClassReferrer.find( _rName ); + if ( m_aClassReferrer.end() == aClassRef ) + { + // we do not know this global class + DBG_ERROR( "ReadGlobalFilter::operator(): unknown filter name!" ); + // TODO: perhaps we should be more tolerant - at the moment, the filter is dropped + // We could silently push_back it to the container .... + } + else + { + // read the data of this class into the node referred to by aClassRef + lcl_ReadFilterClass( m_aClassesNode, _rName, *aClassRef->second ); + } + } + }; + + //-------------------------------------------------------------------- + void lcl_ReadGlobalFilters( const OConfigurationNode& _rFilterClassification, FilterClassList& _rGlobalClasses, StringArray& _rGlobalClassNames ) + { + _rGlobalClasses.clear(); + _rGlobalClassNames.clear(); + + //================================================================ + // get the list describing the order of all global classes + Sequence< ::rtl::OUString > aGlobalClasses; + _rFilterClassification.getNodeValue( DEFINE_CONST_OUSTRING( "GlobalFilters/Order" ) ) >>= aGlobalClasses; + + const ::rtl::OUString* pNames = aGlobalClasses.getConstArray(); + const ::rtl::OUString* pNamesEnd = pNames + aGlobalClasses.getLength(); + + // copy the logical names + _rGlobalClassNames.resize( aGlobalClasses.getLength() ); + ::std::copy( pNames, pNamesEnd, _rGlobalClassNames.begin() ); + + // Global classes are presented in an own group, so their order matters (while the order of the + // "local classes" doesn't). + // That's why we can't simply add the global classes to _rGlobalClasses using the order in which they + // are returned from the configuration - it is completely undefined, and we need a _defined_ order. + FilterClassReferrer aClassReferrer; + ::std::for_each( + pNames, + pNamesEnd, + CreateEmptyClassRememberPos( _rGlobalClasses, aClassReferrer ) + ); + // now _rGlobalClasses contains a dummy entry for each global class, + // while aClassReferrer maps from the logical name of the class to the position within _rGlobalClasses where + // it's dummy entry resides + + //================================================================ + // go for all the single class entries + OConfigurationNode aFilterClassesNode = + _rFilterClassification.openNode( DEFINE_CONST_OUSTRING( "GlobalFilters/Classes" ) ); + Sequence< ::rtl::OUString > aFilterClasses = aFilterClassesNode.getNodeNames(); + ::std::for_each( + aFilterClasses.getConstArray(), + aFilterClasses.getConstArray() + aFilterClasses.getLength(), + ReadGlobalFilter( aFilterClassesNode, aClassReferrer ) + ); + } + + //-------------------------------------------------------------------- + struct ReadLocalFilter : public ::std::unary_function< FilterName, void > + { + protected: + OConfigurationNode m_aClassesNode; + FilterClassList& m_rClasses; + + public: + ReadLocalFilter( const OConfigurationNode& _rClassesNode, FilterClassList& _rClasses ) + :m_aClassesNode ( _rClassesNode ) + ,m_rClasses ( _rClasses ) + { + } + + // operate on a single logical name + void operator() ( const FilterName& _rName ) + { + // read the data for this class + FilterClass aClass; + lcl_ReadFilterClass( m_aClassesNode, _rName, aClass ); + + // insert the class descriptor + m_rClasses.push_back( aClass ); + } + }; + + //-------------------------------------------------------------------- + void lcl_ReadLocalFilters( const OConfigurationNode& _rFilterClassification, FilterClassList& _rLocalClasses ) + { + _rLocalClasses.clear(); + + // the node for the local classes + OConfigurationNode aFilterClassesNode = + _rFilterClassification.openNode( DEFINE_CONST_OUSTRING( "LocalFilters/Classes" ) ); + Sequence< ::rtl::OUString > aFilterClasses = aFilterClassesNode.getNodeNames(); + + ::std::for_each( + aFilterClasses.getConstArray(), + aFilterClasses.getConstArray() + aFilterClasses.getLength(), + ReadLocalFilter( aFilterClassesNode, _rLocalClasses ) + ); + } + + //-------------------------------------------------------------------- + void lcl_ReadClassification( FilterClassList& _rGlobalClasses, StringArray& _rGlobalClassNames, FilterClassList& _rLocalClasses ) + { + //================================================================ + // open our config node + OConfigurationTreeRoot aFilterClassification = OConfigurationTreeRoot::createWithServiceFactory( + ::comphelper::getProcessServiceFactory(), + DEFINE_CONST_OUSTRING( "org.openoffice.Office.UI/FilterClassification" ), + -1, + OConfigurationTreeRoot::CM_READONLY + ); + + //================================================================ + // go for the global classes + lcl_ReadGlobalFilters( aFilterClassification, _rGlobalClasses, _rGlobalClassNames ); + + //================================================================ + // fo for the local classes + lcl_ReadLocalFilters( aFilterClassification, _rLocalClasses ); + + } + +// ======================================================================= +// = grouping and classifying +// ======================================================================= + + //-------------------------------------------------------------------- + // a struct which adds helps remembering a reference to a class entry + struct ReferToFilterEntry : public ::std::unary_function< FilterName, void > + { + protected: + FilterGroupEntryReferrer& m_rEntryReferrer; + FilterGroup::iterator m_aClassPos; + + public: + ReferToFilterEntry( FilterGroupEntryReferrer& _rEntryReferrer, const FilterGroup::iterator& _rClassPos ) + :m_rEntryReferrer( _rEntryReferrer ) + ,m_aClassPos( _rClassPos ) + { + } + + // operate on a single filter name + void operator() ( const FilterName& _rName ) + { +#ifdef DBG_UTIL + ::std::pair< FilterGroupEntryReferrer::iterator, bool > aInsertRes = +#endif + m_rEntryReferrer.insert( FilterGroupEntryReferrer::value_type( _rName, m_aClassPos ) ); + DBG_ASSERT( aInsertRes.second, "ReferToFilterEntry::operator(): already have an element for this name!" ); + } + }; + + //-------------------------------------------------------------------- + struct FillClassGroup : public ::std::unary_function< FilterClass, void > + { + protected: + FilterGroup& m_rClassGroup; + FilterGroupEntryReferrer& m_rClassReferrer; + + public: + FillClassGroup( FilterGroup& _rClassGroup, FilterGroupEntryReferrer& _rClassReferrer ) + :m_rClassGroup ( _rClassGroup ) + ,m_rClassReferrer ( _rClassReferrer ) + { + } + + // operate on a single class + void operator() ( const FilterClass& _rClass ) + { + // create an empty filter descriptor for the class + FilterDescriptor aClassEntry; + // set it's name (which is all we know by now) + aClassEntry.First = _rClass.sDisplayName; + + // add it to the group + m_rClassGroup.push_back( aClassEntry ); + // the position of the newly added class + FilterGroup::iterator aClassEntryPos = m_rClassGroup.end(); + --aClassEntryPos; + + // and for all the sub filters of the class, remember the class + // (respectively the position of the class it the group) + ::std::for_each( + _rClass.aSubFilters.getConstArray(), + _rClass.aSubFilters.getConstArray() + _rClass.aSubFilters.getLength(), + ReferToFilterEntry( m_rClassReferrer, aClassEntryPos ) + ); + } + }; + + //-------------------------------------------------------------------- + static const sal_Unicode s_cWildcardSeparator( ';' ); + + //==================================================================== + const ::rtl::OUString& getSeparatorString() + { + static ::rtl::OUString s_sSeparatorString( &s_cWildcardSeparator, 1 ); + return s_sSeparatorString; + } + + //==================================================================== + struct CheckAppendSingleWildcard : public ::std::unary_function< ::rtl::OUString, void > + { + ::rtl::OUString& _rToBeExtended; + + CheckAppendSingleWildcard( ::rtl::OUString& _rBase ) : _rToBeExtended( _rBase ) { } + + void operator() ( const ::rtl::OUString& _rWC ) + { + // check for double wildcards + sal_Int32 nExistentPos = _rToBeExtended.indexOf( _rWC ); + if ( -1 < nExistentPos ) + { // found this wildcard (already part of _rToBeExtended) + const sal_Unicode* pBuffer = _rToBeExtended.getStr(); + if ( ( 0 == nExistentPos ) + || ( s_cWildcardSeparator == pBuffer[ nExistentPos - 1 ] ) + ) + { // the wildcard really starts at this position (it starts at pos 0 or the previous character is a separator + sal_Int32 nExistentWCEnd = nExistentPos + _rWC.getLength(); + if ( ( _rToBeExtended.getLength() == nExistentWCEnd ) + || ( s_cWildcardSeparator == pBuffer[ nExistentWCEnd ] ) + ) + { // it's really the complete wildcard we found + // (not something like _rWC beeing "*.t" and _rToBeExtended containing "*.txt") + // -> outta here + return; + } + } + } + + if ( _rToBeExtended.getLength() ) + _rToBeExtended += getSeparatorString(); + _rToBeExtended += _rWC; + } + }; + + //==================================================================== + // a helper struct which adds a fixed (Sfx-)filter to a filter group entry given by iterator + struct AppendWildcardToDescriptor : public ::std::unary_function< FilterGroupEntryReferrer::value_type, void > + { + protected: + ::std::vector< ::rtl::OUString > aWildCards; + + public: + AppendWildcardToDescriptor( const String& _rWildCard ); + + // operate on a single class entry + void operator() ( const FilterGroupEntryReferrer::value_type& _rClassReference ) + { + // simply add our wildcards + ::std::for_each( + aWildCards.begin(), + aWildCards.end(), + CheckAppendSingleWildcard( _rClassReference.second->Second ) + ); + } + }; + + //==================================================================== + AppendWildcardToDescriptor::AppendWildcardToDescriptor( const String& _rWildCard ) + { + DBG_ASSERT( _rWildCard.Len(), + "AppendWildcardToDescriptor::AppendWildcardToDescriptor: invalid wildcard!" ); + DBG_ASSERT( _rWildCard.GetBuffer()[0] != s_cWildcardSeparator, + "AppendWildcardToDescriptor::AppendWildcardToDescriptor: wildcard already separated!" ); + + aWildCards.reserve( _rWildCard.GetTokenCount( s_cWildcardSeparator ) ); + + const sal_Unicode* pTokenLoop = _rWildCard.GetBuffer(); + const sal_Unicode* pTokenLoopEnd = pTokenLoop + _rWildCard.Len(); + const sal_Unicode* pTokenStart = pTokenLoop; + for ( ; pTokenLoop != pTokenLoopEnd; ++pTokenLoop ) + { + if ( ( s_cWildcardSeparator == *pTokenLoop ) && ( pTokenLoop > pTokenStart ) ) + { // found a new token separator (and a non-empty token) + aWildCards.push_back( ::rtl::OUString( pTokenStart, pTokenLoop - pTokenStart ) ); + + // search the start of the next token + while ( ( pTokenStart != pTokenLoopEnd ) && ( *pTokenStart != s_cWildcardSeparator ) ) + ++pTokenStart; + + if ( pTokenStart == pTokenLoopEnd ) + // reached the end + break; + + ++pTokenStart; + pTokenLoop = pTokenStart; + } + } + if ( pTokenLoop > pTokenStart ) + // the last one .... + aWildCards.push_back( ::rtl::OUString( pTokenStart, pTokenLoop - pTokenStart ) ); + } + + //-------------------------------------------------------------------- + void lcl_InitGlobalClasses( GroupedFilterList& _rAllFilters, const FilterClassList& _rGlobalClasses, FilterGroupEntryReferrer& _rGlobalClassesRef ) + { + // we need an extra group in our "all filters" container + _rAllFilters.push_front( FilterGroup() ); + FilterGroup& rGlobalFilters = _rAllFilters.front(); + // it's important to work on the reference: we want to access the members of this filter group + // by an iterator (FilterGroup::const_iterator) + // the referrer for the global classes + + // initialize the group + ::std::for_each( + _rGlobalClasses.begin(), + _rGlobalClasses.end(), + FillClassGroup( rGlobalFilters, _rGlobalClassesRef ) + ); + // now we have: + // in rGlobalFilters: a list of FilterDescriptor's, where each's discriptor's display name is set to the name of a class + // in aGlobalClassesRef: a mapping from logical filter names to positions within rGlobalFilters + // this way, if we encounter an arbitrary filter, we can easily (and efficient) check if it belongs to a global class + // and modify the descriptor for this class accordingly + } + + //-------------------------------------------------------------------- + typedef ::std::vector< ::std::pair< FilterGroupEntryReferrer::mapped_type, FilterGroup::iterator > > + MapGroupEntry2GroupEntry; + // this is not really a map - it's just called this way because it is used as a map + + struct FindGroupEntry : public ::std::unary_function< MapGroupEntry2GroupEntry::value_type, sal_Bool > + { + FilterGroupEntryReferrer::mapped_type aLookingFor; + FindGroupEntry( FilterGroupEntryReferrer::mapped_type _rLookingFor ) : aLookingFor( _rLookingFor ) { } + + sal_Bool operator() ( const MapGroupEntry2GroupEntry::value_type& _rMapEntry ) + { + return _rMapEntry.first == aLookingFor ? sal_True : sal_False; + } + }; + + struct CopyGroupEntryContent : public ::std::unary_function< MapGroupEntry2GroupEntry::value_type, void > + { + void operator() ( const MapGroupEntry2GroupEntry::value_type& _rMapEntry ) + { +#ifdef DBG_UTIL + FilterDescriptor aHaveALook = *_rMapEntry.first; +#endif + *_rMapEntry.second = *_rMapEntry.first; + } + }; + + //-------------------------------------------------------------------- + struct CopyNonEmptyFilter : public ::std::unary_function< FilterDescriptor, void > + { + FilterGroup& rTarget; + CopyNonEmptyFilter( FilterGroup& _rTarget ) :rTarget( _rTarget ) { } + + void operator() ( const FilterDescriptor& _rFilter ) + { + if ( _rFilter.Second.getLength() ) + rTarget.push_back( _rFilter ); + } + }; + + //-------------------------------------------------------------------- + void lcl_GroupAndClassify( TSortedFilterList& _rFilterMatcher, GroupedFilterList& _rAllFilters ) + { + _rAllFilters.clear(); + + // =============================================================== + // read the classification of filters + FilterClassList aGlobalClasses, aLocalClasses; + StringArray aGlobalClassNames; + lcl_ReadClassification( aGlobalClasses, aGlobalClassNames, aLocalClasses ); + + // =============================================================== + // for the global filter classes + FilterGroupEntryReferrer aGlobalClassesRef; + lcl_InitGlobalClasses( _rAllFilters, aGlobalClasses, aGlobalClassesRef ); + + // insert as much placeholders (FilterGroup's) into _rAllFilter for groups as we have global classes + // (this assumes that both numbers are the same, which, speaking strictly, must not hold - but it does, as we know ...) + sal_Int32 nGlobalClasses = aGlobalClasses.size(); + while ( nGlobalClasses-- ) + _rAllFilters.push_back( FilterGroup() ); + + // =============================================================== + // for the local classes: + // if n filters belong to a local class, they do not appear in their respective group explicitly, instead + // and entry for the class is added to the group and the extensions of the filters are collected under + // this entry + FilterGroupEntryReferrer aLocalClassesRef; + FilterGroup aCollectedLocals; + ::std::for_each( + aLocalClasses.begin(), + aLocalClasses.end(), + FillClassGroup( aCollectedLocals, aLocalClassesRef ) + ); + // to map from the position within aCollectedLocals to positions within the real groups + // (where they finally belong to) + MapGroupEntry2GroupEntry aLocalFinalPositions; + + // =============================================================== + // now add the filters + // the group which we currently work with + GroupedFilterList::iterator aCurrentGroup = _rAllFilters.end(); // no current group + // the filter container of the current group - if this changes between two filters, a new group is reached + String aCurrentServiceName; + + String sFilterWildcard; + ::rtl::OUString sFilterName; + // loop through all the filters + for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter; pFilter = _rFilterMatcher.Next() ) + { + sFilterName = pFilter->GetFilterName(); + sFilterWildcard = pFilter->GetWildcard().GetWildCard(); + AppendWildcardToDescriptor aExtendWildcard( sFilterWildcard ); + + DBG_ASSERT( sFilterWildcard.Len(), "sfx2::lcl_GroupAndClassify: invalid wildcard of this filter!" ); + + // =========================================================== + // check for a change in the group + String aServiceName = pFilter->GetServiceName(); + if ( aServiceName != aCurrentServiceName ) + { // we reached a new group + + ::rtl::OUString sDocServName = aServiceName; + + // look for the place in _rAllFilters where this ne group belongs - this is determined + // by the order of classes in aGlobalClassNames + GroupedFilterList::iterator aGroupPos = _rAllFilters.begin(); + DBG_ASSERT( aGroupPos != _rAllFilters.end(), + "sfx2::lcl_GroupAndClassify: invalid all-filters array here!" ); + // the loop below will work on invalid objects else ... + ++aGroupPos; + StringArray::iterator aGlobalIter = aGlobalClassNames.begin(); + while ( ( aGroupPos != _rAllFilters.end() ) + && ( aGlobalIter != aGlobalClassNames.end() ) + && ( *aGlobalIter != sDocServName ) + ) + { + ++aGlobalIter; + ++aGroupPos; + } + if ( aGroupPos != _rAllFilters.end() ) + // we found a global class name which matchies the doc service name -> fill the filters of this + // group in the respective prepared group + aCurrentGroup = aGroupPos; + else + // insert a new entry in our overall-list + aCurrentGroup = _rAllFilters.insert( _rAllFilters.end(), FilterGroup() ); + + // remember the container to properly detect the next group + aCurrentServiceName = aServiceName; + } + + DBG_ASSERT( aCurrentGroup != _rAllFilters.end(), "sfx2::lcl_GroupAndClassify: invalid current group!" ); + + // =========================================================== + // check if the filter is part of a global group + ::std::pair< FilterGroupEntryReferrer::iterator, FilterGroupEntryReferrer::iterator > + aBelongsTo = aGlobalClassesRef.equal_range( sFilterName ); + // add the filter to the entries for these classes + // (if they exist - if not, the range is empty and the for_each is a no-op) + ::std::for_each( + aBelongsTo.first, + aBelongsTo.second, + aExtendWildcard + ); + + // =========================================================== + // add the filter to it's group + + // for this, check if the filter is part of a local filter + FilterGroupEntryReferrer::iterator aBelongsToLocal = aLocalClassesRef.find( sFilterName ); + if ( aLocalClassesRef.end() != aBelongsToLocal ) + { +/* +#ifdef DBG_UTIL + const ::rtl::OUString& rLocalClassDisplayName = aBelongsToLocal->second->First; + const ::rtl::OUString& rLocalClassExtension = aBelongsToLocal->second->Second; +#endif +*/ + // okay, there is a local class which the filter belongs to + // -> append the wildcard + aExtendWildcard( *aBelongsToLocal ); + + MapGroupEntry2GroupEntry::iterator aThisGroupFinalPos = + ::std::find_if( aLocalFinalPositions.begin(), aLocalFinalPositions.end(), FindGroupEntry( aBelongsToLocal->second ) ); + + if ( aLocalFinalPositions.end() == aThisGroupFinalPos ) + { // the position within aCollectedLocals has not been mapped to a final position + // within the "real" group (aCollectedLocals is only temporary) + // -> do this now (as we just encountered the first filter belonging to this local class + // add a new entry which is the "real" group entry + aCurrentGroup->push_back( FilterDescriptor( aBelongsToLocal->second->First, String() ) ); + // the position where we inserted the entry + FilterGroup::iterator aInsertPos = aCurrentGroup->end(); + --aInsertPos; + // remember this pos + aLocalFinalPositions.push_back( MapGroupEntry2GroupEntry::value_type( aBelongsToLocal->second, aInsertPos ) ); + } + } + else + aCurrentGroup->push_back( FilterDescriptor( pFilter->GetUIName(), sFilterWildcard ) ); + } + + // now just complete the infos for the local groups: + // During the above loop, they have been collected in aCollectedLocals, but this is only temporary + // They have to be copied into their final positions (which are stored in aLocalFinalPositions) + ::std::for_each( + aLocalFinalPositions.begin(), + aLocalFinalPositions.end(), + CopyGroupEntryContent() + ); + + // and remove local groups which do not apply - e.g. have no entries due to the limited content of the + // current SfxFilterMatcherIter + + FilterGroup& rGlobalFilters = _rAllFilters.front(); + FilterGroup aNonEmptyGlobalFilters; + ::std::for_each( + rGlobalFilters.begin(), + rGlobalFilters.end(), + CopyNonEmptyFilter( aNonEmptyGlobalFilters ) + ); + rGlobalFilters.swap( aNonEmptyGlobalFilters ); + } + + //-------------------------------------------------------------------- + struct AppendFilter : public ::std::unary_function< FilterDescriptor, void > + { + protected: + Reference< XFilterManager > m_xFilterManager; + FileDialogHelper_Impl* m_pFileDlgImpl; + bool m_bAddExtension; + + public: + AppendFilter( const Reference< XFilterManager >& _rxFilterManager, + FileDialogHelper_Impl* _pImpl, bool _bAddExtension ) : + + m_xFilterManager( _rxFilterManager ), + m_pFileDlgImpl ( _pImpl ), + m_bAddExtension ( _bAddExtension ) + + { + DBG_ASSERT( m_xFilterManager.is(), "AppendFilter::AppendFilter: invalid filter manager!" ); + DBG_ASSERT( m_pFileDlgImpl, "AppendFilter::AppendFilter: invalid filedlg impl!" ); + } + + // operate on a single filter + void operator() ( const FilterDescriptor& _rFilterEntry ) + { + String sDisplayText = m_bAddExtension + ? addExtension( _rFilterEntry.First, _rFilterEntry.Second, sal_True, *m_pFileDlgImpl ) + : _rFilterEntry.First; + m_xFilterManager->appendFilter( sDisplayText, _rFilterEntry.Second ); + } + }; + +// ======================================================================= +// = handling for the "all files" entry +// ======================================================================= + + //-------------------------------------------------------------------- + sal_Bool lcl_hasAllFilesFilter( TSortedFilterList& _rFilterMatcher, String& /* [out] */ _rAllFilterName ) + { + ::rtl::OUString sUIName; + sal_Bool bHasAll = sal_False; + _rAllFilterName = String( SfxResId( STR_SFX_FILTERNAME_ALL ) ); + + // =============================================================== + // check if there's already a filter <ALL> + for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter && !bHasAll; pFilter = _rFilterMatcher.Next() ) + { + if ( pFilter->GetUIName() == _rAllFilterName ) + bHasAll = sal_True; + } + return bHasAll; + } + + //-------------------------------------------------------------------- + void lcl_EnsureAllFilesEntry( TSortedFilterList& _rFilterMatcher, GroupedFilterList& _rFilters ) + { + // =============================================================== + String sAllFilterName; + if ( !lcl_hasAllFilesFilter( _rFilterMatcher, sAllFilterName ) ) + { + // get the first group of filters (by definition, this group contains the global classes) + DBG_ASSERT( !_rFilters.empty(), "lcl_EnsureAllFilesEntry: invalid filter list!" ); + if ( !_rFilters.empty() ) + { + FilterGroup& rGlobalClasses = *_rFilters.begin(); + rGlobalClasses.push_front( FilterDescriptor( sAllFilterName, DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL ) ) ); + } + } + } + +#ifdef DISABLE_GROUPING_AND_CLASSIFYING + //-------------------------------------------------------------------- + void lcl_EnsureAllFilesEntry( TSortedFilterList& _rFilterMatcher, const Reference< XFilterManager >& _rxFilterManager, ::rtl::OUString& _rFirstNonEmpty ) + { + // =============================================================== + String sAllFilterName; + if ( !lcl_hasAllFilesFilter( _rFilterMatcher, sAllFilterName ) ) + { + try + { + _rxFilterManager->appendFilter( sAllFilterName, DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL ) ); + _rFirstNonEmpty = sAllFilterName; + } + catch( const IllegalArgumentException& ) + { +#ifdef DBG_UTIL + ByteString aMsg( "sfx2::lcl_EnsureAllFilesEntry: could not append Filter" ); + aMsg += ByteString( String( sAllFilterName ), RTL_TEXTENCODING_UTF8 ); + DBG_ERROR( aMsg.GetBuffer() ); +#endif + } + } + + } +#endif + +// ======================================================================= +// = filling an XFilterManager +// ======================================================================= + + //-------------------------------------------------------------------- + struct AppendFilterGroup : public ::std::unary_function< FilterGroup, void > + { + protected: + Reference< XFilterManager > m_xFilterManager; + Reference< XFilterGroupManager > m_xFilterGroupManager; + FileDialogHelper_Impl* m_pFileDlgImpl; + + public: + AppendFilterGroup( const Reference< XFilterManager >& _rxFilterManager, FileDialogHelper_Impl* _pImpl ) + :m_xFilterManager ( _rxFilterManager ) + ,m_xFilterGroupManager ( _rxFilterManager, UNO_QUERY ) + ,m_pFileDlgImpl ( _pImpl ) + { + DBG_ASSERT( m_xFilterManager.is(), "AppendFilterGroup::AppendFilterGroup: invalid filter manager!" ); + DBG_ASSERT( m_pFileDlgImpl, "AppendFilterGroup::AppendFilterGroup: invalid filedlg impl!" ); + } + + void appendGroup( const FilterGroup& _rGroup, bool _bAddExtension ) + { + try + { + if ( m_xFilterGroupManager.is() ) + { // the file dialog implementation supports visual grouping of filters + // create a representation of the group which is understandable by the XFilterGroupManager + if ( _rGroup.size() ) + { + Sequence< StringPair > aFilters( _rGroup.size() ); + ::std::copy( + _rGroup.begin(), + _rGroup.end(), + aFilters.getArray() + ); + if ( _bAddExtension ) + { + StringPair* pFilters = aFilters.getArray(); + StringPair* pEnd = pFilters + aFilters.getLength(); + for ( ; pFilters != pEnd; ++pFilters ) + pFilters->First = addExtension( pFilters->First, pFilters->Second, sal_True, *m_pFileDlgImpl ); + } + m_xFilterGroupManager->appendFilterGroup( ::rtl::OUString(), aFilters ); + } + } + else + { + ::std::for_each( + _rGroup.begin(), + _rGroup.end(), + AppendFilter( m_xFilterManager, m_pFileDlgImpl, _bAddExtension ) ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + // operate on a single filter group + void operator() ( const FilterGroup& _rGroup ) + { + appendGroup( _rGroup, true ); + } + }; + + //-------------------------------------------------------------------- + TSortedFilterList::TSortedFilterList(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration >& xFilterList) + : m_nIterator(0) + { + if (!xFilterList.is()) + return; + + m_lFilters.clear(); + while(xFilterList->hasMoreElements()) + { + ::comphelper::SequenceAsHashMap lFilterProps (xFilterList->nextElement()); + ::rtl::OUString sFilterName = lFilterProps.getUnpackedValueOrDefault( + ::rtl::OUString::createFromAscii("Name"), + ::rtl::OUString()); + if (sFilterName.getLength()) + m_lFilters.push_back(sFilterName); + } + } + + //-------------------------------------------------------------------- + const SfxFilter* TSortedFilterList::First() + { + m_nIterator = 0; + return impl_getFilter(m_nIterator); + } + + //-------------------------------------------------------------------- + const SfxFilter* TSortedFilterList::Next() + { + ++m_nIterator; + return impl_getFilter(m_nIterator); + } + + //-------------------------------------------------------------------- + const SfxFilter* TSortedFilterList::impl_getFilter(sal_Int32 nIndex) + { + if (nIndex<0 || nIndex>=(sal_Int32)m_lFilters.size()) + return 0; + const ::rtl::OUString& sFilterName = m_lFilters[nIndex]; + if (!sFilterName.getLength()) + return 0; + return SfxFilter::GetFilterByName(String(sFilterName)); + } + + //-------------------------------------------------------------------- + void appendFiltersForSave( TSortedFilterList& _rFilterMatcher, + const Reference< XFilterManager >& _rxFilterManager, + ::rtl::OUString& _rFirstNonEmpty, FileDialogHelper_Impl& _rFileDlgImpl, + const ::rtl::OUString& _rFactory ) + { + DBG_ASSERT( _rxFilterManager.is(), "sfx2::appendFiltersForSave: invalid manager!" ); + if ( !_rxFilterManager.is() ) + return; + + ::rtl::OUString sUIName; + ::rtl::OUString sExtension; + + // retrieve the default filter for this application module. + // It must be set as first of the generated filter list. + const SfxFilter* pDefaultFilter = SfxFilterContainer::GetDefaultFilter_Impl(_rFactory); + // --> PB 2004-11-01 #i32434# only use one extension + // (and always the first if there are more than one) + sExtension = pDefaultFilter->GetWildcard().GetWildCard().GetToken( 0, ';' ); + // <-- + sUIName = addExtension( pDefaultFilter->GetUIName(), sExtension, sal_False, _rFileDlgImpl ); + try + { + _rxFilterManager->appendFilter( sUIName, sExtension ); + if ( !_rFirstNonEmpty.getLength() ) + _rFirstNonEmpty = sUIName; + } + catch( IllegalArgumentException ) + { +#ifdef DBG_UTIL + ByteString aMsg( "Could not append DefaultFilter" ); + aMsg += ByteString( String( sUIName ), osl_getThreadTextEncoding() ); + DBG_ERRORFILE( aMsg.GetBuffer() ); +#endif + } + + for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter; pFilter = _rFilterMatcher.Next() ) + { + if (pFilter->GetName() == pDefaultFilter->GetName()) + continue; + + // --> PB 2004-09-21 #i32434# only use one extension + // (and always the first if there are more than one) + sExtension = pFilter->GetWildcard().GetWildCard().GetToken( 0, ';' ); + // <-- + sUIName = addExtension( pFilter->GetUIName(), sExtension, sal_False, _rFileDlgImpl ); + try + { + _rxFilterManager->appendFilter( sUIName, sExtension ); + if ( !_rFirstNonEmpty.getLength() ) + _rFirstNonEmpty = sUIName; + } + catch( IllegalArgumentException ) + { + #ifdef DBG_UTIL + ByteString aMsg( "Could not append Filter" ); + aMsg += ByteString( String( sUIName ), osl_getThreadTextEncoding() ); + DBG_ERRORFILE( aMsg.GetBuffer() ); + #endif + } + } + } + + struct ExportFilter + { + ExportFilter( const rtl::OUString& _aUIName, const rtl::OUString& _aWildcard ) : + aUIName( _aUIName ), aWildcard( _aWildcard ) {} + + rtl::OUString aUIName; + rtl::OUString aWildcard; + }; + + //-------------------------------------------------------------------- + void appendExportFilters( TSortedFilterList& _rFilterMatcher, + const Reference< XFilterManager >& _rxFilterManager, + ::rtl::OUString& _rFirstNonEmpty, FileDialogHelper_Impl& _rFileDlgImpl ) + { + DBG_ASSERT( _rxFilterManager.is(), "sfx2::appendExportFilters: invalid manager!" ); + if ( !_rxFilterManager.is() ) + return; + + sal_Int32 nHTMLIndex = -1; + sal_Int32 nXHTMLIndex = -1; + sal_Int32 nPDFIndex = -1; + sal_Int32 nFlashIndex = -1; + ::rtl::OUString sUIName; + ::rtl::OUString sExtensions; + std::vector< ExportFilter > aImportantFilterGroup; + std::vector< ExportFilter > aFilterGroup; + Reference< XFilterGroupManager > xFilterGroupManager( _rxFilterManager, UNO_QUERY ); + ::rtl::OUString sTypeName; + const ::rtl::OUString sWriterHTMLType( DEFINE_CONST_OUSTRING("writer_web_HTML") ); + const ::rtl::OUString sGraphicHTMLType( DEFINE_CONST_OUSTRING("graphic_HTML") ); + const ::rtl::OUString sXHTMLType( DEFINE_CONST_OUSTRING("XHTML_File") ); + const ::rtl::OUString sPDFType( DEFINE_CONST_OUSTRING("pdf_Portable_Document_Format") ); + const ::rtl::OUString sFlashType( DEFINE_CONST_OUSTRING("graphic_SWF") ); + + for ( const SfxFilter* pFilter = _rFilterMatcher.First(); pFilter; pFilter = _rFilterMatcher.Next() ) + { + sTypeName = pFilter->GetTypeName(); + sUIName = pFilter->GetUIName(); + sExtensions = pFilter->GetWildcard().GetWildCard(); + ExportFilter aExportFilter( sUIName, sExtensions ); + String aExt = sExtensions; + + if ( nHTMLIndex == -1 && + ( sTypeName.equals( sWriterHTMLType ) || sTypeName.equals( sGraphicHTMLType ) ) ) + { + aImportantFilterGroup.insert( aImportantFilterGroup.begin(), aExportFilter ); + nHTMLIndex = 0; + } + else if ( nXHTMLIndex == -1 && sTypeName.equals( sXHTMLType ) ) + { + std::vector< ExportFilter >::iterator aIter = aImportantFilterGroup.begin(); + if ( nHTMLIndex == -1 ) + aImportantFilterGroup.insert( aIter, aExportFilter ); + else + aImportantFilterGroup.insert( ++aIter, aExportFilter ); + nXHTMLIndex = 0; + } + else if ( nPDFIndex == -1 && sTypeName.equals( sPDFType ) ) + { + std::vector< ExportFilter >::iterator aIter = aImportantFilterGroup.begin(); + if ( nHTMLIndex != -1 ) + aIter++; + if ( nXHTMLIndex != -1 ) + aIter++; + aImportantFilterGroup.insert( aIter, aExportFilter ); + nPDFIndex = 0; + } + else if ( nFlashIndex == -1 && sTypeName.equals( sFlashType ) ) + { + std::vector< ExportFilter >::iterator aIter = aImportantFilterGroup.begin(); + if ( nHTMLIndex != -1 ) + aIter++; + if ( nXHTMLIndex != -1 ) + aIter++; + if ( nPDFIndex != -1 ) + aIter++; + aImportantFilterGroup.insert( aIter, aExportFilter ); + nFlashIndex = 0; + } + else + aFilterGroup.push_back( aExportFilter ); + } + + if ( xFilterGroupManager.is() ) + { + // Add both html/pdf filter as a filter group to get a separator between both groups + if ( aImportantFilterGroup.size() > 0 ) + { + Sequence< StringPair > aFilters( aImportantFilterGroup.size() ); + for ( sal_Int32 i = 0; i < (sal_Int32)aImportantFilterGroup.size(); i++ ) + { + aFilters[i].First = addExtension( aImportantFilterGroup[i].aUIName, + aImportantFilterGroup[i].aWildcard, + sal_False, _rFileDlgImpl ); + aFilters[i].Second = aImportantFilterGroup[i].aWildcard; + } + + try + { + xFilterGroupManager->appendFilterGroup( ::rtl::OUString(), aFilters ); + } + catch( IllegalArgumentException ) + { + } + } + + if ( aFilterGroup.size() > 0 ) + { + Sequence< StringPair > aFilters( aFilterGroup.size() ); + for ( sal_Int32 i = 0; i < (sal_Int32)aFilterGroup.size(); i++ ) + { + aFilters[i].First = addExtension( aFilterGroup[i].aUIName, + aFilterGroup[i].aWildcard, + sal_False, _rFileDlgImpl ); + aFilters[i].Second = aFilterGroup[i].aWildcard; + } + + try + { + xFilterGroupManager->appendFilterGroup( ::rtl::OUString(), aFilters ); + } + catch( IllegalArgumentException ) + { + } + } + } + else + { + // Fallback solution just add both filter groups as single filters + sal_Int32 n; + + for ( n = 0; n < (sal_Int32)aImportantFilterGroup.size(); n++ ) + { + try + { + rtl::OUString aUIName = addExtension( aImportantFilterGroup[n].aUIName, + aImportantFilterGroup[n].aWildcard, + sal_False, _rFileDlgImpl ); + _rxFilterManager->appendFilter( aUIName, aImportantFilterGroup[n].aWildcard ); + if ( !_rFirstNonEmpty.getLength() ) + _rFirstNonEmpty = sUIName; + + } + catch( IllegalArgumentException ) + { + #ifdef DBG_UTIL + ByteString aMsg( "Could not append Filter" ); + aMsg += ByteString( String( sUIName ), osl_getThreadTextEncoding() ); + DBG_ERRORFILE( aMsg.GetBuffer() ); + #endif + } + } + + for ( n = 0; n < (sal_Int32)aFilterGroup.size(); n++ ) + { + try + { + rtl::OUString aUIName = addExtension( aFilterGroup[n].aUIName, + aFilterGroup[n].aWildcard, + sal_False, _rFileDlgImpl ); + _rxFilterManager->appendFilter( aUIName, aFilterGroup[n].aWildcard ); + if ( !_rFirstNonEmpty.getLength() ) + _rFirstNonEmpty = sUIName; + + } + catch( IllegalArgumentException ) + { + #ifdef DBG_UTIL + ByteString aMsg( "Could not append Filter" ); + aMsg += ByteString( String( sUIName ), osl_getThreadTextEncoding() ); + DBG_ERRORFILE( aMsg.GetBuffer() ); + #endif + } + } + } + } + + //-------------------------------------------------------------------- + void appendFiltersForOpen( TSortedFilterList& _rFilterMatcher, + const Reference< XFilterManager >& _rxFilterManager, + ::rtl::OUString& _rFirstNonEmpty, FileDialogHelper_Impl& _rFileDlgImpl ) + { + DBG_ASSERT( _rxFilterManager.is(), "sfx2::appendFiltersForOpen: invalid manager!" ); + if ( !_rxFilterManager.is() ) + return; + +#ifdef DISABLE_GROUPING_AND_CLASSIFYING + // =============================================================== + // ensure that there's an entry "all" (with wildcard *.*) + lcl_EnsureAllFilesEntry( _rFilterMatcher, _rxFilterManager, _rFirstNonEmpty ); + + // =============================================================== + appendFilters( _rFilterMatcher, _rxFilterManager, _rFirstNonEmpty ); +#else + + // =============================================================== + // group and classify the filters + GroupedFilterList aAllFilters; + lcl_GroupAndClassify( _rFilterMatcher, aAllFilters ); + + // =============================================================== + // ensure that we have the one "all files" entry + lcl_EnsureAllFilesEntry( _rFilterMatcher, aAllFilters ); + + // =============================================================== + // the first non-empty string - which we assume is the first overall entry + if ( !aAllFilters.empty() ) + { + const FilterGroup& rFirstGroup = *aAllFilters.begin(); // should be the global classes + if ( !rFirstGroup.empty() ) + _rFirstNonEmpty = rFirstGroup.begin()->First; + // append first group, without extension + AppendFilterGroup aGroup( _rxFilterManager, &_rFileDlgImpl ); + aGroup.appendGroup( rFirstGroup, false ); + } + + // =============================================================== + // append the filters to the manager + if ( !aAllFilters.empty() ) + { + ::std::list< FilterGroup >::iterator pIter = aAllFilters.begin(); + ++pIter; + ::std::for_each( + pIter, // first filter group was handled seperately, see above + aAllFilters.end(), + AppendFilterGroup( _rxFilterManager, &_rFileDlgImpl ) ); + } +#endif + } + + ::rtl::OUString addExtension( const ::rtl::OUString& _rDisplayText, + const ::rtl::OUString& _rExtension, + sal_Bool _bForOpen, FileDialogHelper_Impl& _rFileDlgImpl ) + { + static ::rtl::OUString sAllFilter( RTL_CONSTASCII_USTRINGPARAM( "(*.*)" ) ); + static ::rtl::OUString sOpenBracket( RTL_CONSTASCII_USTRINGPARAM( " (" ) ); + static ::rtl::OUString sCloseBracket( RTL_CONSTASCII_USTRINGPARAM( ")" ) ); + ::rtl::OUString sRet = _rDisplayText; + + if ( sRet.indexOf( sAllFilter ) == -1 ) + { + String sExt = _rExtension; + if ( !_bForOpen ) + // show '*' in extensions only when opening a document + sExt.EraseAllChars( '*' ); + sRet += sOpenBracket; + sRet += sExt; + sRet += sCloseBracket; + } + _rFileDlgImpl.addFilterPair( _rDisplayText, sRet ); + return sRet; + } + +//........................................................................ +} // namespace sfx2 +//........................................................................ + + diff --git a/sfx2/source/dialog/filtergrouping.hxx b/sfx2/source/dialog/filtergrouping.hxx new file mode 100644 index 000000000000..8075186614dd --- /dev/null +++ b/sfx2/source/dialog/filtergrouping.hxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SFX2_FILTERGROUPING_HXX +#define SFX2_FILTERGROUPING_HXX + +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include "filedlgimpl.hxx" + +class SfxFilterMatcherIter; + +//........................................................................ +namespace sfx2 +{ +//........................................................................ + + class TSortedFilterList + { + private: + + ::std::vector< ::rtl::OUString > m_lFilters; + sal_Int32 m_nIterator; + + public: + + TSortedFilterList(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration >& xFilterList); + const SfxFilter* First(); + const SfxFilter* Next(); + + private: + const SfxFilter* impl_getFilter(sal_Int32 nIndex); + }; + + //-------------------------------------------------------------------- + /** adds the given filters to the filter manager. + <p>To be used when saving generic files.</p> + */ + void appendFiltersForSave( + TSortedFilterList& _rFilterMatcher, + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilterManager >& _rFilterManager, + ::rtl::OUString& /* [out] */ _rFirstNonEmpty, + FileDialogHelper_Impl& _rFileDlgImpl, + const ::rtl::OUString& _rFactory + ); + + void appendExportFilters( + TSortedFilterList& _rFilterMatcher, + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilterManager >& _rFilterManager, + ::rtl::OUString& /* [out] */ _rFirstNonEmpty, + FileDialogHelper_Impl& _rFileDlgImpl + ); + + //-------------------------------------------------------------------- + /** adds the given filters to the filter manager. + <p>To be used when opening generic files.</p> + */ + void appendFiltersForOpen( + TSortedFilterList& _rFilterMatcher, + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilterManager >& _rFilterManager, + ::rtl::OUString& /* [out] */ _rFirstNonEmpty, + FileDialogHelper_Impl& _rFileDlgImpl + ); + + //-------------------------------------------------------------------- + /** adds the given extension to the display text. + <p>To be used when opening or save generic files.</p> + */ + ::rtl::OUString addExtension( + const ::rtl::OUString& _rDisplayText, + const ::rtl::OUString& _rExtension, + sal_Bool _bForOpen, + FileDialogHelper_Impl& _rFileDlgImpl + ); + +//........................................................................ +} // namespace sfx2 +//........................................................................ + +#endif // SFX2_FILTERGROUPING_HXX + + diff --git a/sfx2/source/dialog/intro.cxx b/sfx2/source/dialog/intro.cxx new file mode 100644 index 000000000000..637b89898a3a --- /dev/null +++ b/sfx2/source/dialog/intro.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#ifndef GCC +#endif + +#include "intro.hxx" + +#include <tools/stream.hxx> +#include <tools/urlobj.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/configmgr.hxx> +#include <com/sun/star/uno/Any.h> + +#include <sfx2/sfxuno.hxx> + +// ----------------------------------------------------------------------- + +void IntroWindow_Impl::Init() +{ + Size aSize = aIntroBmp.GetSizePixel(); + SetOutputSizePixel( aSize ); + Size aScreenSize( GetDesktopRectPixel().GetSize() ); + Size aWinSize( GetSizePixel() ); + Point aWinPos( ( aScreenSize.Width() - aWinSize.Width() ) / 2, + ( aScreenSize.Height() - aWinSize.Height() ) / 2 ); + SetPosPixel( aWinPos ); + + if ( GetColorCount() >= 16 ) + { + Show(); + Update(); + } +} + +// ----------------------------------------------------------------------- + +IntroWindow_Impl::IntroWindow_Impl( const Bitmap& rBmp ) : + + WorkWindow( NULL, (WinBits)0 ), + + aIntroBmp( rBmp ) + +{ + Hide(); + + // load bitmap depends on productname ("StarOffice", "StarSuite",...) + ::com::sun::star::uno::Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + rtl::OUString aTmp; + aRet >>= aTmp; + String aBmpFileName = aTmp; + aBmpFileName += String( DEFINE_CONST_UNICODE("_intro.bmp") ); + INetURLObject aObj( SvtPathOptions().GetModulePath(), INET_PROT_FILE ); + aObj.insertName( aBmpFileName ); + SvFileStream aStrm( aObj.PathToFileName(), STREAM_STD_READ ); + if ( !aStrm.GetError() ) + aStrm >> aIntroBmp; + + Init(); +} + +// ----------------------------------------------------------------------- + +IntroWindow_Impl::~IntroWindow_Impl() +{ + Hide(); +} + +// ----------------------------------------------------------------------- + +void IntroWindow_Impl::Paint( const Rectangle& ) +{ + DrawBitmap( Point(), aIntroBmp ); + Flush(); +} + +// ----------------------------------------------------------------------- + +void IntroWindow_Impl::Slide() +{ +} + + diff --git a/sfx2/source/dialog/itemconnect.cxx b/sfx2/source/dialog/itemconnect.cxx new file mode 100644 index 000000000000..51ed3bc5304a --- /dev/null +++ b/sfx2/source/dialog/itemconnect.cxx @@ -0,0 +1,408 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <sfx2/itemconnect.hxx> + +#include <boost/shared_ptr.hpp> +#include <list> +#include <svl/itempool.hxx> + +// ============================================================================ + +namespace sfx { + +// ============================================================================ +// Helpers +// ============================================================================ + +namespace { + +TriState lclConvertToTriState( bool bKnown, bool bIsKnownFlag, bool bIsUnknownFlag ) +{ + return (bKnown && bIsKnownFlag) ? STATE_CHECK : ((!bKnown && bIsUnknownFlag) ? STATE_NOCHECK : STATE_DONTKNOW); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +USHORT ItemWrapperHelper::GetWhichId( const SfxItemSet& rItemSet, USHORT nSlot ) +{ + return rItemSet.GetPool()->GetWhich( nSlot ); +} + +bool ItemWrapperHelper::IsKnownItem( const SfxItemSet& rItemSet, USHORT nSlot ) +{ + return rItemSet.GetItemState( GetWhichId( rItemSet, nSlot ), TRUE ) != SFX_ITEM_UNKNOWN; +} + +const SfxPoolItem* ItemWrapperHelper::GetUniqueItem( const SfxItemSet& rItemSet, USHORT nSlot ) +{ + USHORT nWhich = GetWhichId( rItemSet, nSlot ); + return (rItemSet.GetItemState( nWhich, TRUE ) >= SFX_ITEM_DEFAULT) ? rItemSet.GetItem( nWhich, TRUE ) : 0; +} + +const SfxPoolItem& ItemWrapperHelper::GetDefaultItem( const SfxItemSet& rItemSet, USHORT nSlot ) +{ + return rItemSet.GetPool()->GetDefaultItem( GetWhichId( rItemSet, nSlot ) ); +} + +void ItemWrapperHelper::RemoveDefaultItem( SfxItemSet& rDestSet, const SfxItemSet& rOldSet, USHORT nSlot ) +{ + USHORT nWhich = GetWhichId( rDestSet, nSlot ); + if( rOldSet.GetItemState( nWhich, FALSE ) == SFX_ITEM_DEFAULT ) + rDestSet.ClearItem( nWhich ); +} + +// ============================================================================ +// Base control wrapper classes +// ============================================================================ + +ControlWrapperBase::~ControlWrapperBase() +{ +} + +// ============================================================================ +// Single control wrappers +// ============================================================================ + +DummyWindowWrapper::DummyWindowWrapper( Window& rWindow ) : + SingleControlWrapperType( rWindow ) +{ +} + +bool DummyWindowWrapper::IsControlDontKnow() const +{ + return false; +} + +void DummyWindowWrapper::SetControlDontKnow( bool ) +{ +} + +void* DummyWindowWrapper::GetControlValue() const +{ + return 0; +} + +void DummyWindowWrapper::SetControlValue( void* ) +{ +} + +// ---------------------------------------------------------------------------- + +CheckBoxWrapper::CheckBoxWrapper( CheckBox& rCheckBox ) : + SingleControlWrapperType( rCheckBox ) +{ +} + +bool CheckBoxWrapper::IsControlDontKnow() const +{ + return GetControl().GetState() == STATE_DONTKNOW; +} + +void CheckBoxWrapper::SetControlDontKnow( bool bSet ) +{ + GetControl().EnableTriState( bSet ); + GetControl().SetState( bSet ? STATE_DONTKNOW : STATE_NOCHECK ); +} + +BOOL CheckBoxWrapper::GetControlValue() const +{ + return GetControl().IsChecked(); +} + +void CheckBoxWrapper::SetControlValue( BOOL bValue ) +{ + GetControl().Check( bValue ); +} + +// ---------------------------------------------------------------------------- + +EditWrapper::EditWrapper( Edit& rEdit ) : + SingleControlWrapperType( rEdit ) +{ +} + +bool EditWrapper::IsControlDontKnow() const +{ + // no "don't know" state - empty string is a valid value of an Edit + return false; +} + +void EditWrapper::SetControlDontKnow( bool bSet ) +{ + if( bSet ) + GetControl().SetText( String() ); +} + +String EditWrapper::GetControlValue() const +{ + return GetControl().GetText(); +} + +void EditWrapper::SetControlValue( String aValue ) +{ + GetControl().SetText( aValue ); +} + +// ---------------------------------------------------------------------------- + +ColorListBoxWrapper::ColorListBoxWrapper(ColorListBox & rListBox): + SingleControlWrapper< ColorListBox, Color >(rListBox) +{} + +ColorListBoxWrapper::~ColorListBoxWrapper() +{} + +bool ColorListBoxWrapper::IsControlDontKnow() const +{ + return GetControl().GetSelectEntryCount() == 0; +} + +void ColorListBoxWrapper::SetControlDontKnow( bool bSet ) +{ + if( bSet ) GetControl().SetNoSelection(); +} + +Color ColorListBoxWrapper::GetControlValue() const +{ + return GetControl().GetSelectEntryColor(); +} + +void ColorListBoxWrapper::SetControlValue( Color aColor ) +{ + GetControl().SelectEntry( aColor ); +} + +// ============================================================================ +// Multi control wrappers +// ============================================================================ + +typedef std::vector< ControlWrapperBase* > ControlWrpVec; +typedef ControlWrpVec::iterator ControlWrpVecI; +typedef ControlWrpVec::const_iterator ControlWrpVecCI; + +struct MultiControlWrapperHelper_Impl +{ + ControlWrpVec maVec; +}; + +MultiControlWrapperHelper::MultiControlWrapperHelper() : + mxImpl( new MultiControlWrapperHelper_Impl ) +{ +} + +MultiControlWrapperHelper::~MultiControlWrapperHelper() +{ +} + +void MultiControlWrapperHelper::RegisterControlWrapper( ControlWrapperBase& rWrapper ) +{ + mxImpl->maVec.push_back( &rWrapper ); +} + +void MultiControlWrapperHelper::ModifyControl( TriState eEnable, TriState eShow ) +{ + for( ControlWrpVecI aIt = mxImpl->maVec.begin(), aEnd = mxImpl->maVec.end(); aIt != aEnd; ++aIt ) + (*aIt)->ModifyControl( eEnable, eShow ); +} + +bool MultiControlWrapperHelper::IsControlDontKnow() const +{ + bool bIs = !mxImpl->maVec.empty(); + for( ControlWrpVecCI aIt = mxImpl->maVec.begin(), aEnd = mxImpl->maVec.end(); bIs && (aIt != aEnd); ++aIt ) + bIs &= (*aIt)->IsControlDontKnow(); + return bIs; +} + +void MultiControlWrapperHelper::SetControlDontKnow( bool bSet ) +{ + for( ControlWrpVecI aIt = mxImpl->maVec.begin(), aEnd = mxImpl->maVec.end(); aIt != aEnd; ++aIt ) + (*aIt)->SetControlDontKnow( bSet ); +} + +// ============================================================================ +// Base connection classes +// ============================================================================ + +ItemConnectionBase::ItemConnectionBase( ItemConnFlags nFlags ) : + mnFlags( nFlags ) +{ +} + +ItemConnectionBase::~ItemConnectionBase() +{ +} + +void ItemConnectionBase::Activate( bool bActive ) +{ + if( bActive ) mnFlags &= ~ITEMCONN_INACTIVE; else mnFlags |= ITEMCONN_INACTIVE; +} + +bool ItemConnectionBase::IsActive() const +{ + return !(mnFlags & ITEMCONN_INACTIVE); +} + +void ItemConnectionBase::DoApplyFlags( const SfxItemSet& rItemSet ) +{ + if( IsActive() ) + ApplyFlags( rItemSet ); +} + +void ItemConnectionBase::DoReset( const SfxItemSet& rItemSet ) +{ + if( IsActive() ) + Reset( rItemSet ); +} + +bool ItemConnectionBase::DoFillItemSet( SfxItemSet& rDestSet, const SfxItemSet& rOldSet ) +{ + return IsActive() && FillItemSet( rDestSet, rOldSet ); +} + +TriState ItemConnectionBase::GetEnableState( bool bKnown ) const +{ + return lclConvertToTriState( bKnown, mnFlags & ITEMCONN_ENABLE_KNOWN, mnFlags & ITEMCONN_DISABLE_UNKNOWN ); +} + +TriState ItemConnectionBase::GetShowState( bool bKnown ) const +{ + return lclConvertToTriState( bKnown, mnFlags & ITEMCONN_SHOW_KNOWN, mnFlags & ITEMCONN_HIDE_UNKNOWN ); +} + +// ============================================================================ +// Standard connections +// ============================================================================ + +DummyItemConnection::DummyItemConnection( USHORT nSlot, Window& rWindow, ItemConnFlags nFlags ) : + ItemConnectionBase( nFlags ), + DummyWindowWrapper( rWindow ), + mnSlot( nSlot ) +{ +} + +void DummyItemConnection::ApplyFlags( const SfxItemSet& rItemSet ) +{ + bool bKnown = ItemWrapperHelper::IsKnownItem( rItemSet, mnSlot ); + ModifyControl( GetEnableState( bKnown ), GetShowState( bKnown ) ); +} + +void DummyItemConnection::Reset( const SfxItemSet& /*rItemSet*/ ) +{ +} + +bool DummyItemConnection::FillItemSet( SfxItemSet& /*rDestSet*/, const SfxItemSet& /*rOldSet*/ ) +{ + return false; // item set not changed +} + +// ============================================================================ +// Array of connections +// ============================================================================ + +class ItemConnectionArrayImpl +{ +public: + void Append( ItemConnectionBase* pConnection ); + + void ApplyFlags( const SfxItemSet& rItemSet ); + void Reset( const SfxItemSet& rItemSet ); + bool FillItemSet( SfxItemSet& rDestSet, const SfxItemSet& rOldSet ); + +private: + typedef boost::shared_ptr< ItemConnectionBase > ItemConnectionRef; + typedef std::list< ItemConnectionRef > ItemConnectionList; + typedef ItemConnectionList::iterator ItemConnectionListIt; + + ItemConnectionList maList; +}; + +void ItemConnectionArrayImpl::Append( ItemConnectionBase* pConnection ) +{ + if( pConnection ) + maList.push_back( ItemConnectionRef( pConnection ) ); +} + +void ItemConnectionArrayImpl::ApplyFlags( const SfxItemSet& rItemSet ) +{ + for( ItemConnectionListIt aIt = maList.begin(), aEnd = maList.end(); aIt != aEnd; ++aIt ) + (*aIt)->DoApplyFlags( rItemSet ); +} + +void ItemConnectionArrayImpl::Reset( const SfxItemSet& rItemSet ) +{ + for( ItemConnectionListIt aIt = maList.begin(), aEnd = maList.end(); aIt != aEnd; ++aIt ) + (*aIt)->DoReset( rItemSet ); +} + +bool ItemConnectionArrayImpl::FillItemSet( SfxItemSet& rDestSet, const SfxItemSet& rOldSet ) +{ + bool bChanged = false; + for( ItemConnectionListIt aIt = maList.begin(), aEnd = maList.end(); aIt != aEnd; ++aIt ) + bChanged |= (*aIt)->DoFillItemSet( rDestSet, rOldSet ); + return bChanged; +} + +// ---------------------------------------------------------------------------- + +ItemConnectionArray::ItemConnectionArray() : + mxImpl( new ItemConnectionArrayImpl ) +{ +} + +ItemConnectionArray::~ItemConnectionArray() +{ +} + +void ItemConnectionArray::AddConnection( ItemConnectionBase* pConnection ) +{ + mxImpl->Append( pConnection ); +} + +void ItemConnectionArray::ApplyFlags( const SfxItemSet& rItemSet ) +{ + mxImpl->ApplyFlags( rItemSet ); +} + +void ItemConnectionArray::Reset( const SfxItemSet& rItemSet ) +{ + mxImpl->Reset( rItemSet ); +} + +bool ItemConnectionArray::FillItemSet( SfxItemSet& rDestSet, const SfxItemSet& rOldSet ) +{ + return mxImpl->FillItemSet( rDestSet, rOldSet ); +} + +// ============================================================================ + +} // namespace sfx + diff --git a/sfx2/source/dialog/mailmodel.cxx b/sfx2/source/dialog/mailmodel.cxx new file mode 100644 index 000000000000..0e0c6ec22ee1 --- /dev/null +++ b/sfx2/source/dialog/mailmodel.cxx @@ -0,0 +1,960 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +// includes -------------------------------------------------------------- +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/system/XSimpleMailClientSupplier.hpp> +#include <com/sun/star/system/SimpleMailClientFlags.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> +#ifndef _COM_SUN_STAR_SECURITY_DOCUMENTSIGNATURESINFORMATION_HPP_ +#include <com/sun/star/security/DocumentSignatureInformation.hpp> +#endif +#include <com/sun/star/security/XDocumentDigitalSignatures.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/ucb/InsertCommandArgument.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/document/XExporter.hpp> + +#ifndef _RTL_TEXTENC_H +#include <rtl/textench.h> +#endif +#include <rtl/uri.h> +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <vcl/msgbox.hxx> + +#include <mailmodelapi.hxx> +#include "sfxtypes.hxx" +#include "sfxresid.hxx" +#include <sfx2/sfxsids.hrc> +#include "dialog.hrc" + +#include <unotools/tempfile.hxx> +#include <unotools/configitem.hxx> +#include <ucbhelper/content.hxx> +#include <tools/urlobj.hxx> +#include <unotools/useroptions.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/storagehelper.hxx> +#include <comphelper/sequenceasvector.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/mediadescriptor.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> + +// -------------------------------------------------------------- +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::system; +using namespace ::rtl; + +namespace css = ::com::sun::star; + +// class AddressList_Impl ------------------------------------------------ + +typedef String* AddressItemPtr_Impl; +DECLARE_LIST( AddressList_Impl, AddressItemPtr_Impl ) + +// class SfxMailModel ----------------------------------------------- + +static const char PDF_DOCUMENT_TYPE[] = "pdf_Portable_Document_Format"; +static const sal_uInt32 PDF_DOCUMENT_TYPE_LEN = 28; + +void SfxMailModel::ClearList( AddressList_Impl* pList ) +{ + if ( pList ) + { + ULONG i, nCount = pList->Count(); + for ( i = 0; i < nCount; ++i ) + delete pList->GetObject(i); + pList->Clear(); + } +} + +void SfxMailModel::MakeValueList( AddressList_Impl* pList, String& rValueList ) +{ + rValueList.Erase(); + if ( pList ) + { + ULONG i, nCount = pList->Count(); + for ( i = 0; i < nCount; ++i ) + { + if ( rValueList.Len() > 0 ) + rValueList += ','; + rValueList += *pList->GetObject(i); + } + } +} + +sal_Bool HasDocumentValidSignature( const css::uno::Reference< css::frame::XModel >& xModel ) +{ + try + { + css::uno::Reference< css::beans::XPropertySet > xPropSet( xModel, css::uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasValidSignatures" ))); + sal_Bool bReturn = sal_Bool(); + if ( a >>= bReturn ) + return bReturn; + } + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + + return sal_False; +} + +SfxMailModel::SaveResult SfxMailModel::ShowFilterOptionsDialog( + uno::Reference< lang::XMultiServiceFactory > xSMGR, + uno::Reference< frame::XModel > xModel, + const rtl::OUString& rFilterName, + const rtl::OUString& rType, + bool bModified, + sal_Int32& rNumArgs, + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ) +{ + SaveResult eRet( SAVE_ERROR ); + + try + { + uno::Sequence < beans::PropertyValue > aProps; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xFilterCFG = + uno::Reference< container::XNameAccess >( + xSMGR->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY ); + css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); + + if ( !xFilterCFG.is() ) + return eRet; + + uno::Any aAny = xFilterCFG->getByName( rFilterName ); + + if ( aAny >>= aProps ) + { + sal_Int32 nPropertyCount = aProps.getLength(); + for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty ) + { + if( aProps[nProperty].Name.equals( ::rtl::OUString::createFromAscii( "UIComponent" )) ) + { + ::rtl::OUString aServiceName; + aProps[nProperty].Value >>= aServiceName; + if( aServiceName.getLength() ) + { + uno::Reference< ui::dialogs::XExecutableDialog > xFilterDialog( + xSMGR->createInstance( aServiceName ), uno::UNO_QUERY ); + uno::Reference< beans::XPropertyAccess > xFilterProperties( + xFilterDialog, uno::UNO_QUERY ); + + if( xFilterDialog.is() && xFilterProperties.is() ) + { + uno::Sequence< beans::PropertyValue > aPropsForDialog(1); + uno::Reference< document::XExporter > xExporter( xFilterDialog, uno::UNO_QUERY ); + + if ( rType.equalsAsciiL( PDF_DOCUMENT_TYPE, PDF_DOCUMENT_TYPE_LEN )) + { + //add an internal property, used to tell the dialog we want to set a different + //string for the ok button + //used in filter/source/pdf/impdialog.cxx + String aOkSendText( SfxResId( STR_PDF_EXPORT_SEND )); + + uno::Sequence< beans::PropertyValue > aFilterDataValue(1); + aFilterDataValue[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_OkButtonString" )); + aFilterDataValue[0].Value = css::uno::makeAny( ::rtl::OUString( aOkSendText )); + + //add to the filterdata property, the only one the PDF export filter dialog will care for + aPropsForDialog[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterData" )); + aPropsForDialog[0].Value = css::uno::makeAny( aFilterDataValue ); + + //when executing the dialog will merge the persistent FilterData properties + xFilterProperties->setPropertyValues( aPropsForDialog ); + } + + if( xExporter.is() ) + xExporter->setSourceDocument( + uno::Reference< lang::XComponent >( xModel, uno::UNO_QUERY ) ); + + if( xFilterDialog->execute() ) + { + //get the filter data + uno::Sequence< beans::PropertyValue > aPropsFromDialog = xFilterProperties->getPropertyValues(); + + //add them to the args + for ( sal_Int32 nInd = 0; nInd < aPropsFromDialog.getLength(); nInd++ ) + { + if( aPropsFromDialog[ nInd ].Name.equals( ::rtl::OUString::createFromAscii( "FilterData" ) ) ) + { + //found the filterdata, add to the storing argument + rArgs.realloc( ++rNumArgs ); + rArgs[rNumArgs-1].Name = aPropsFromDialog[ nInd ].Name; + rArgs[rNumArgs-1].Value = aPropsFromDialog[ nInd ].Value; + break; + } + } + eRet = SAVE_SUCCESSFULL; + } + else + { + // cancel from dialog, then do not send + // If the model is not modified, it could be modified by the dispatch calls. + // Therefore set back to modified = false. This should not hurt if we call + // on a non-modified model. + if ( !bModified ) + { + try + { + xModifiable->setModified( sal_False ); + } + catch( com::sun::star::beans::PropertyVetoException& ) + { + } + } + eRet = SAVE_CANCELLED; + } + } + break; + } + } + } + } + } + catch( css::uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + } + + return eRet; +} + +sal_Int32 SfxMailModel::GetCount() const +{ + return maAttachedDocuments.size(); +} + +sal_Bool SfxMailModel::IsEmpty() const +{ + return maAttachedDocuments.empty(); +} + +SfxMailModel::SaveResult SfxMailModel::SaveDocumentAsFormat( + const rtl::OUString& aSaveFileName, + const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, + const rtl::OUString& rType, + rtl::OUString& rFileNamePath ) +{ + SaveResult eRet( SAVE_ERROR ); + bool bSendAsPDF = (rType.equalsAsciiL( PDF_DOCUMENT_TYPE, PDF_DOCUMENT_TYPE_LEN )); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + if (!xSMGR.is()) + return eRet; + + const rtl::OUString aModuleManager( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" )); + css::uno::Reference< css::frame::XModuleManager > xModuleManager( xSMGR->createInstance( aModuleManager ), css::uno::UNO_QUERY_THROW ); + if ( !xModuleManager.is() ) + return eRet; + + rtl::OUString aModule; + try + { + aModule = xModuleManager->identify( xFrameOrModel ); + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + + css::uno::Reference< css::frame::XFrame > xFrame( xFrameOrModel, css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XModel > xModel( xFrameOrModel, css::uno::UNO_QUERY ); + if ( xFrame.is() ) + { + css::uno::Reference< css::frame::XController > xController = xFrame->getController(); + if ( xController.is() ) + xModel = xController->getModel(); + } + + // We need at least a valid module name and model reference + if (( aModule.getLength() > 0 ) && xModel.is() ) + { + bool bModified( false ); + bool bHasLocation( false ); + bool bStoreTo( false ); + + css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY ); + + if ( xModifiable.is() ) + bModified = xModifiable->isModified(); + if ( xStorable.is() ) + { + rtl::OUString aLocation = xStorable->getLocation(); + INetURLObject aFileObj( aLocation ); + + bool bPrivateProtocol = ( aFileObj.GetProtocol() == INET_PROT_PRIV_SOFFICE ); + + bHasLocation = ( aLocation.getLength() > 0 ) && !bPrivateProtocol; + OSL_ASSERT( !bPrivateProtocol ); + } + if ( rType.getLength() > 0 ) + bStoreTo = true; + + if ( xStorable.is() ) + { + rtl::OUString aFilterName; + rtl::OUString aTypeName( rType ); + rtl::OUString aFileName; + rtl::OUString aExtension; + + css::uno::Reference< css::container::XContainerQuery > xContainerQuery( + xSMGR->createInstance( rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.FilterFactory" ))), + css::uno::UNO_QUERY ); + + if ( bStoreTo ) + { + // Retrieve filter from type + css::uno::Sequence< css::beans::NamedValue > aQuery( bSendAsPDF ? 3 : 2 ); + aQuery[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" )); + aQuery[0].Value = css::uno::makeAny( aTypeName ); + aQuery[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentService" )); + aQuery[1].Value = css::uno::makeAny( aModule ); + if( bSendAsPDF ) + { + // #i91419# + // FIXME: we want just an export filter. However currently we need + // exact flag value as detailed in the filter configuration to get it + // this seems to be a bug + // without flags we get an import filter here, which is also unwanted + aQuery[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Flags" )); + aQuery[2].Value = css::uno::makeAny( sal_Int32(0x80042) ); // EXPORT ALIEN 3RDPARTY + } + + css::uno::Reference< css::container::XEnumeration > xEnumeration = + xContainerQuery->createSubSetEnumerationByProperties( aQuery ); + + if ( xEnumeration->hasMoreElements() ) + { + ::comphelper::SequenceAsHashMap aFilterPropsHM( xEnumeration->nextElement() ); + aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( + ::rtl::OUString::createFromAscii( "Name" ), + ::rtl::OUString() ); + } + + if ( bHasLocation ) + { + // Retrieve filter from media descriptor + ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); + rtl::OUString aOrgFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )), + ::rtl::OUString() ); + if ( aOrgFilterName == aFilterName ) + { + // We should save the document in the original format. Therefore this + // is not a storeTo operation. To support signing in this case, reset + // bStoreTo flag. + bStoreTo = false; + } + } + } + else + { + if ( bHasLocation ) + { + // Retrieve filter from media descriptor + ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); + aFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )), + ::rtl::OUString() ); + } + + if ( !bHasLocation || ( aFilterName.getLength() == 0 )) + { + // Retrieve the user defined default filter + css::uno::Reference< css::container::XNameAccess > xNameAccess( xModuleManager, css::uno::UNO_QUERY ); + try + { + ::comphelper::SequenceAsHashMap aFilterPropsHM( xNameAccess->getByName( aModule ) ); + aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( + ::rtl::OUString::createFromAscii( "ooSetupFactoryDefaultFilter" ), + ::rtl::OUString() ); + css::uno::Reference< css::container::XNameAccess > xNameAccess2( + xContainerQuery, css::uno::UNO_QUERY ); + if ( xNameAccess2.is() ) + { + ::comphelper::SequenceAsHashMap aFilterPropsHM2( xNameAccess2->getByName( aFilterName ) ); + aTypeName = aFilterPropsHM2.getUnpackedValueOrDefault( + ::rtl::OUString::createFromAscii( "Type" ), + ::rtl::OUString() ); + } + } + catch ( css::container::NoSuchElementException& ) + { + } + catch ( css::beans::UnknownPropertyException& ) + { + } + } + } + + // No filter found => error + // No type and no location => error + if (( aFilterName.getLength() == 0 ) || + (( aTypeName.getLength() == 0 ) && !bHasLocation )) + return eRet; + + // Determine filen name and extension + if ( bHasLocation && !bStoreTo ) + { + INetURLObject aFileObj( xStorable->getLocation() ); + aExtension = (rtl::OUString)aFileObj.getExtension(); + } + else + { + css::uno::Reference< container::XNameAccess > xTypeDetection( + xSMGR->createInstance( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.TypeDetection" ))), + css::uno::UNO_QUERY ); + + + if ( xTypeDetection.is() ) + { + try + { + ::comphelper::SequenceAsHashMap aTypeNamePropsHM( xTypeDetection->getByName( aTypeName ) ); + uno::Sequence< ::rtl::OUString > aExtensions = aTypeNamePropsHM.getUnpackedValueOrDefault( + ::rtl::OUString::createFromAscii( "Extensions" ), + ::uno::Sequence< ::rtl::OUString >() ); + if ( aExtensions.getLength() ) + aExtension = aExtensions[0]; + } + catch ( css::container::NoSuchElementException& ) + { + } + } + } + + // Use provided save file name. If empty determine file name + aFileName = aSaveFileName; + if ( aFileName.getLength() == 0 ) + { + if ( !bHasLocation ) + { + // Create a noname file name with the correct extension + const rtl::OUString aNoNameFileName( RTL_CONSTASCII_USTRINGPARAM( "noname" )); + aFileName = aNoNameFileName; + } + else + { + // Determine file name from model + INetURLObject aFileObj( xStorable->getLocation() ); + aFileName = aFileObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::NO_DECODE ); + } + } + + // No file name => error + if ( aFileName.getLength() == 0 ) + return eRet; + + OSL_ASSERT( aFilterName.getLength() > 0 ); + OSL_ASSERT( aFileName.getLength() > 0 ); + + // Creates a temporary directory to store a predefined file into it. + // This makes it possible to store the file for "send document as e-mail" + // with the original file name. We cannot use the original file as + // some mail programs need exclusive access. + ::utl::TempFile aTempDir( NULL, sal_True ); + + INetURLObject aFilePathObj( aTempDir.GetURL() ); + aFilePathObj.insertName( aFileName ); + aFilePathObj.setExtension( aExtension ); + + rtl::OUString aFileURL = aFilePathObj.GetMainURL( INetURLObject::NO_DECODE ); + + sal_Int32 nNumArgs(0); + const rtl::OUString aPasswordPropName( RTL_CONSTASCII_USTRINGPARAM( "Password" )); + css::uno::Sequence< css::beans::PropertyValue > aArgs( ++nNumArgs ); + aArgs[nNumArgs-1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); + aArgs[nNumArgs-1].Value = css::uno::makeAny( aFilterName ); + + ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); + rtl::OUString aPassword = aMediaDescrPropsHM.getUnpackedValueOrDefault( + aPasswordPropName, + ::rtl::OUString() ); + if ( aPassword.getLength() > 0 ) + { + aArgs.realloc( ++nNumArgs ); + aArgs[nNumArgs-1].Name = aPasswordPropName; + aArgs[nNumArgs-1].Value = css::uno::makeAny( aPassword ); + } + + if ( bModified || !bHasLocation || bStoreTo ) + { + // Document is modified, is newly created or should be stored in a special format + try + { + css::uno::Reference< css::util::XURLTransformer > xURLTransformer( + xSMGR->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))), + css::uno::UNO_QUERY ); + + css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( xFrame, css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XDispatch > xDispatch; + + css::util::URL aURL; + css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs; + + if( !bSendAsPDF ) + { + if ( xURLTransformer.is() ) + { + aURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:PrepareMailExport" )); + xURLTransformer->parseStrict( aURL ); + } + + if ( xDispatchProvider.is() ) + { + xDispatch = css::uno::Reference< css::frame::XDispatch >( + xDispatchProvider->queryDispatch( aURL, ::rtl::OUString(), 0 )); + if ( xDispatch.is() ) + { + try + { + xDispatch->dispatch( aURL, aDispatchArgs ); + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + } + } + } + + //check if this is the pdf otput filter (i#64555) + if( bSendAsPDF ) + { + SaveResult eShowPDFFilterDialog = ShowFilterOptionsDialog( + xSMGR, xModel, aFilterName, rType, bModified, nNumArgs, aArgs ); + + // don't continue on dialog cancel or error + if ( eShowPDFFilterDialog != SAVE_SUCCESSFULL ) + return eShowPDFFilterDialog; + } + + xStorable->storeToURL( aFileURL, aArgs ); + rFileNamePath = aFileURL; + eRet = SAVE_SUCCESSFULL; + + if( !bSendAsPDF ) + { + // #i30432# notify that export is finished - the Writer may want to restore removed content + if ( xURLTransformer.is() ) + { + aURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:MailExportFinished" )); + xURLTransformer->parseStrict( aURL ); + } + + if ( xDispatchProvider.is() ) + { + xDispatch = css::uno::Reference< css::frame::XDispatch >( + xDispatchProvider->queryDispatch( aURL, ::rtl::OUString(), 0 )); + if ( xDispatch.is() ) + { + try + { + xDispatch->dispatch( aURL, aDispatchArgs ); + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + } + } + } + // If the model is not modified, it could be modified by the dispatch calls. + // Therefore set back to modified = false. This should not hurt if we call + // on a non-modified model. + if ( !bModified ) + { + try + { + xModifiable->setModified( sal_False ); + } + catch( com::sun::star::beans::PropertyVetoException& ) + { + } + } + } + catch ( com::sun::star::io::IOException& ) + { + eRet = SAVE_ERROR; + } + } + else + { + // We need 1:1 copy of the document to preserve an added signature. + aArgs.realloc( ++nNumArgs ); + aArgs[nNumArgs-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyStreamIfPossible" ) ); + aArgs[nNumArgs-1].Value = css::uno::makeAny( (sal_Bool)sal_True ); + + try + { + xStorable->storeToURL( aFileURL, aArgs ); + rFileNamePath = aFileURL; + eRet = SAVE_SUCCESSFULL; + } + catch ( com::sun::star::io::IOException& ) + { + eRet = SAVE_ERROR; + } + } + } + } + + return eRet; +} + +SfxMailModel::SfxMailModel() : + mpToList ( NULL ), + mpCcList ( NULL ), + mpBccList ( NULL ), + mePriority ( PRIO_NORMAL ), + mbLoadDone ( sal_True ) +{ +} + +SfxMailModel::~SfxMailModel() +{ + ClearList( mpToList ); + delete mpToList; + ClearList( mpCcList ); + delete mpCcList; + ClearList( mpBccList ); + delete mpBccList; +} + +void SfxMailModel::AddAddress( const String& rAddress, AddressRole eRole ) +{ + // don't add a empty address + if ( rAddress.Len() > 0 ) + { + AddressList_Impl* pList = NULL; + if ( ROLE_TO == eRole ) + { + if ( !mpToList ) + // create the list + mpToList = new AddressList_Impl; + pList = mpToList; + } + else if ( ROLE_CC == eRole ) + { + if ( !mpCcList ) + // create the list + mpCcList = new AddressList_Impl; + pList = mpCcList; + } + else if ( ROLE_BCC == eRole ) + { + if ( !mpBccList ) + // create the list + mpBccList = new AddressList_Impl; + pList = mpBccList; + } + else + { + DBG_ERRORFILE( "invalid address role" ); + } + + if ( pList ) + { + // add address to list + AddressItemPtr_Impl pAddress = new String( rAddress ); + pList->Insert( pAddress, LIST_APPEND ); + } + } +} + +SfxMailModel::SendMailResult SfxMailModel::AttachDocument( + const ::rtl::OUString& sDocumentType, + const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, + const ::rtl::OUString& sAttachmentTitle ) +{ + rtl::OUString sFileName; + + SaveResult eSaveResult = SaveDocumentAsFormat( sAttachmentTitle, xFrameOrModel, sDocumentType, sFileName ); + if ( eSaveResult == SAVE_SUCCESSFULL && ( sFileName.getLength() > 0 ) ) + maAttachedDocuments.push_back(sFileName); + return eSaveResult == SAVE_SUCCESSFULL ? SEND_MAIL_OK : SEND_MAIL_ERROR; +} + +SfxMailModel::SendMailResult SfxMailModel::Send( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + OSL_ENSURE(!maAttachedDocuments.empty(),"No document added!"); + SendMailResult eResult = SEND_MAIL_ERROR; + if ( !maAttachedDocuments.empty() ) + { + css::uno::Reference < XMultiServiceFactory > xMgr = ::comphelper::getProcessServiceFactory(); + if ( xMgr.is() ) + { + css::uno::Reference< XSimpleMailClientSupplier > xSimpleMailClientSupplier; + + // Prefer the SimpleSystemMail service if available + xSimpleMailClientSupplier = css::uno::Reference< XSimpleMailClientSupplier >( + xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleSystemMail" ))), + UNO_QUERY ); + + if ( ! xSimpleMailClientSupplier.is() ) + { + xSimpleMailClientSupplier = css::uno::Reference< XSimpleMailClientSupplier >( + xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleCommandMail" ))), + UNO_QUERY ); + } + + if ( xSimpleMailClientSupplier.is() ) + { + css::uno::Reference< XSimpleMailClient > xSimpleMailClient = xSimpleMailClientSupplier->querySimpleMailClient(); + + if ( !xSimpleMailClient.is() ) + { + // no mail client support => message box! + return SEND_MAIL_ERROR; + } + + // we have a simple mail client + css::uno::Reference< XSimpleMailMessage > xSimpleMailMessage = xSimpleMailClient->createSimpleMailMessage(); + if ( xSimpleMailMessage.is() ) + { + sal_Int32 nSendFlags = SimpleMailClientFlags::DEFAULTS; + if ( maFromAddress.Len() == 0 ) + { + // from address not set, try figure out users e-mail address + CreateFromAddress_Impl( maFromAddress ); + } + xSimpleMailMessage->setOriginator( maFromAddress ); + + sal_Int32 nToCount = mpToList ? mpToList->Count() : 0; + sal_Int32 nCcCount = mpCcList ? mpCcList->Count() : 0; + sal_Int32 nCcSeqCount = nCcCount; + + // set recipient (only one) for this simple mail server!! + if ( nToCount > 1 ) + { + nCcSeqCount = nToCount - 1 + nCcCount; + xSimpleMailMessage->setRecipient( *mpToList->GetObject( 0 )); + nSendFlags = SimpleMailClientFlags::NO_USER_INTERFACE; + } + else if ( nToCount == 1 ) + { + xSimpleMailMessage->setRecipient( *mpToList->GetObject( 0 )); + nSendFlags = SimpleMailClientFlags::NO_USER_INTERFACE; + } + + // all other recipient must be handled with CC recipients! + if ( nCcSeqCount > 0 ) + { + sal_Int32 nIndex = 0; + Sequence< OUString > aCcRecipientSeq; + + aCcRecipientSeq.realloc( nCcSeqCount ); + if ( nCcSeqCount > nCcCount ) + { + for ( sal_Int32 i = 1; i < nToCount; ++i ) + { + aCcRecipientSeq[nIndex++] = *mpToList->GetObject(i); + } + } + + for ( sal_Int32 i = 0; i < nCcCount; i++ ) + { + aCcRecipientSeq[nIndex++] = *mpCcList->GetObject(i); + } + xSimpleMailMessage->setCcRecipient( aCcRecipientSeq ); + } + + sal_Int32 nBccCount = mpBccList ? mpBccList->Count() : 0; + if ( nBccCount > 0 ) + { + Sequence< OUString > aBccRecipientSeq( nBccCount ); + for ( sal_Int32 i = 0; i < nBccCount; ++i ) + { + aBccRecipientSeq[i] = *mpBccList->GetObject(i); + } + xSimpleMailMessage->setBccRecipient( aBccRecipientSeq ); + } + + Sequence< OUString > aAttachmentSeq(&(maAttachedDocuments[0]),maAttachedDocuments.size()); + + xSimpleMailMessage->setSubject( maSubject ); + xSimpleMailMessage->setAttachement( aAttachmentSeq ); + + sal_Bool bSend( sal_False ); + try + { + xSimpleMailClient->sendSimpleMailMessage( xSimpleMailMessage, nSendFlags ); + bSend = sal_True; + } + catch ( IllegalArgumentException& ) + { + } + catch ( Exception& ) + { + } + + if ( bSend == sal_False ) + { + css::uno::Reference< css::awt::XWindow > xParentWindow = xFrame->getContainerWindow(); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow ); + + ErrorBox aBox( pParentWindow, SfxResId( RID_ERRBOX_MAIL_CONFIG )); + aBox.Execute(); + eResult = SEND_MAIL_CANCELLED; + } + else + eResult = SEND_MAIL_OK; + } + } + } + } + else + eResult = SEND_MAIL_CANCELLED; + + return eResult; +} + +SfxMailModel::SendMailResult SfxMailModel::SaveAndSend( const css::uno::Reference< css::frame::XFrame >& xFrame, const rtl::OUString& rTypeName ) +{ + SaveResult eSaveResult; + SendMailResult eResult = SEND_MAIL_ERROR; + rtl::OUString aFileName; + + eSaveResult = SaveDocumentAsFormat( rtl::OUString(), xFrame, rTypeName, aFileName ); + + if ( eSaveResult == SAVE_SUCCESSFULL ) + { + maAttachedDocuments.push_back( aFileName ); + return Send( xFrame ); + } + else if ( eSaveResult == SAVE_CANCELLED ) + eResult = SEND_MAIL_CANCELLED; + + return eResult; +} + +// functions ------------------------------------------------------------- + +BOOL CreateFromAddress_Impl( String& rFrom ) + +/* [Beschreibung] + + Diese Funktion versucht mit Hilfe des IniManagers eine From-Adresse + zu erzeugen. daf"ur werden die Felder 'Vorname', 'Name' und 'EMail' + aus der Applikations-Ini-Datei ausgelesen. Sollten diese Felder + nicht gesetzt sein, wird FALSE zur"uckgegeben. + + [R"uckgabewert] + + TRUE: Adresse konnte erzeugt werden. + FALSE: Adresse konnte nicht erzeugt werden. +*/ + +{ + SvtUserOptions aUserCFG; + String aName = aUserCFG.GetLastName (); + String aFirstName = aUserCFG.GetFirstName (); + if ( aFirstName.Len() || aName.Len() ) + { + if ( aFirstName.Len() ) + { + rFrom = TRIM( aFirstName ); + + if ( aName.Len() ) + rFrom += ' '; + } + rFrom += TRIM( aName ); + // unerlaubte Zeichen entfernen + rFrom.EraseAllChars( '<' ); + rFrom.EraseAllChars( '>' ); + rFrom.EraseAllChars( '@' ); + } + String aEmailName = aUserCFG.GetEmail(); + + // unerlaubte Zeichen entfernen + aEmailName.EraseAllChars( '<' ); + aEmailName.EraseAllChars( '>' ); + + if ( aEmailName.Len() ) + { + if ( rFrom.Len() ) + rFrom += ' '; + ( ( rFrom += '<' ) += TRIM( aEmailName ) ) += '>'; + } + else + rFrom.Erase(); + return ( rFrom.Len() > 0 ); +} diff --git a/sfx2/source/dialog/mailmodelapi.cxx b/sfx2/source/dialog/mailmodelapi.cxx new file mode 100644 index 000000000000..16d12f469205 --- /dev/null +++ b/sfx2/source/dialog/mailmodelapi.cxx @@ -0,0 +1,695 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +// includes -------------------------------------------------------------- +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/mozilla/XPluginInstance.hpp> +#include <com/sun/star/ucb/XDataContainer.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/system/XSimpleMailClientSupplier.hpp> +#include <com/sun/star/system/SimpleMailClientFlags.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#ifndef _RTL_TEXTENC_H +#include <rtl/textench.h> +#endif +#include <vos/mutex.hxx> +#include <rtl/uri.h> +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <unotools/streamhelper.hxx> +#include <unotools/configitem.hxx> +#include <comphelper/mediadescriptor.hxx> +#include <vos/thread.hxx> +#include <vcl/msgbox.hxx> + +#include "mailmodelapi.hxx" +#include <sfx2/docfilt.hxx> +#include <sfx2/docfac.hxx> +#include "sfxtypes.hxx" + +#include "dialog.hrc" +#include "sfxresid.hxx" +#include <sfx2/sfxuno.hxx> +#include <sfx2/fcontnr.hxx> +#include "guisaveas.hxx" + +#include <unotools/tempfile.hxx> +#include <vcl/svapp.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <unotools/useroptions.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/extract.hxx> +#include <ucbhelper/content.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/urlobj.hxx> + +extern sal_Bool GetPasswd_Impl( const SfxItemSet* pSet, String& rPasswd ); + +// -------------------------------------------------------------- +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::mozilla; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::system; +using namespace ::rtl; + +namespace +{ + // functions ------------------------------------------------------------- + + BOOL CreateFromAddress_Impl( String& rFrom ) + + /* [Beschreibung] + + Diese Funktion versucht mit Hilfe des IniManagers eine From-Adresse + zu erzeugen. daf"ur werden die Felder 'Vorname', 'Name' und 'EMail' + aus der Applikations-Ini-Datei ausgelesen. Sollten diese Felder + nicht gesetzt sein, wird FALSE zur"uckgegeben. + + [R"uckgabewert] + + TRUE: Adresse konnte erzeugt werden. + FALSE: Adresse konnte nicht erzeugt werden. + */ + + { + SvtUserOptions aUserCFG; + String aName = aUserCFG.GetLastName (); + String aFirstName = aUserCFG.GetFirstName (); + if ( aFirstName.Len() || aName.Len() ) + { + if ( aFirstName.Len() ) + { + rFrom = TRIM( aFirstName ); + + if ( aName.Len() ) + rFrom += ' '; + } + rFrom += TRIM( aName ); + // unerlaubte Zeichen entfernen + rFrom.EraseAllChars( '<' ); + rFrom.EraseAllChars( '>' ); + rFrom.EraseAllChars( '@' ); + } + String aEmailName = aUserCFG.GetEmail(); + // unerlaubte Zeichen entfernen + aEmailName.EraseAllChars( '<' ); + aEmailName.EraseAllChars( '>' ); + + if ( aEmailName.Len() ) + { + if ( rFrom.Len() ) + rFrom += ' '; + ( ( rFrom += '<' ) += TRIM( aEmailName ) ) += '>'; + } + else + rFrom.Erase(); + return ( rFrom.Len() > 0 ); + } + +} + +// class OThread +class OMailSendThreadImpl : public ::vos::OThread +{ + public: + OMailSendThreadImpl( + Reference< XSimpleMailClient > xSimpleMailClient, + Reference< XSimpleMailMessage > xSimpleMailMessage, + const Reference< XFrame >& _xCurrentFrame, + long nSendFlags ) : + m_nSendFlags( nSendFlags ), + m_bSend( sal_False ), + m_xSimpleMailClient( xSimpleMailClient ), + m_xSimpleMailMessage( xSimpleMailMessage ), + m_xCurrentFrame(_xCurrentFrame) {} + + virtual ~OMailSendThreadImpl(); + + virtual void SAL_CALL run(); + virtual void SAL_CALL onTerminated(); + + private: + long m_nSendFlags; + sal_Bool m_bSend; + Reference< XSimpleMailClient > m_xSimpleMailClient; + Reference< XSimpleMailMessage > m_xSimpleMailMessage; + Reference< XFrame > m_xCurrentFrame; +}; + +OMailSendThreadImpl::~OMailSendThreadImpl() +{ +} + +void SAL_CALL OMailSendThreadImpl::run() +{ + try + { + m_xSimpleMailClient->sendSimpleMailMessage( m_xSimpleMailMessage, m_nSendFlags ); + m_bSend = sal_True; + } + catch ( IllegalArgumentException& ) + { + m_bSend = sal_False; + } + catch ( Exception& ) + { + m_bSend = sal_False; + } + + if ( m_bSend == sal_False ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + Reference< ::com::sun::star::awt::XWindow > xParentWindow = m_xCurrentFrame->getContainerWindow(); + Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow ); + + ErrorBox aBox( pParentWindow, SfxResId( RID_ERRBOX_MAIL_CONFIG )); + aBox.Execute(); + } +} + +void SAL_CALL OMailSendThreadImpl::onTerminated() +{ + delete this; +} + +// class AddressList_Impl ------------------------------------------------ + +typedef String* AddressItemPtr_Impl; +DECLARE_LIST( AddressList_Impl, AddressItemPtr_Impl ) + +// class SfxMailModel ----------------------------------------------- + +void SfxMailModel::ClearList( AddressList_Impl* pList ) +{ + if ( pList ) + { + ULONG i, nCount = pList->Count(); + for ( i = 0; i < nCount; ++i ) + delete pList->GetObject(i); + pList->Clear(); + } +} + +void SfxMailModel::MakeValueList( AddressList_Impl* pList, String& rValueList ) +{ + rValueList.Erase(); + if ( pList ) + { + ULONG i, nCount = pList->Count(); + for ( i = 0; i < nCount; ++i ) + { + if ( rValueList.Len() > 0 ) + rValueList += ','; + rValueList += *pList->GetObject(i); + } + } +} +namespace +{ + String lcl_getFactoryName(const Reference<XInterface>& _xModel) + { + rtl::OUString sModuleIdentifier; + rtl::OUString sFactoryShortName; + Reference < XModuleManager > xModuleManager( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.ModuleManager")) ), UNO_QUERY ); + + if ( _xModel.is() ) + { + try + { + sModuleIdentifier = xModuleManager->identify( _xModel ); + } + catch ( ::com::sun::star::frame::UnknownModuleException& ) + { + DBG_WARNING( "SfxHelp::GetHelpModuleName_Impl(): unknown module (help in help?)" ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "SfxHelp::GetHelpModuleName_Impl(): exception of XModuleManager::identif y()" ); + } + } + + return sModuleIdentifier; + } + + String lcl_createTempFileName(const Reference < XModel >& _xModel,const ::rtl::OUString& _sAttachmentTitle) + { + // create temp file name with leading chars and extension + Reference < XStorable > xStor( _xModel, UNO_QUERY ); + String aLeadingStr; + if ( xStor.is() ) + { + sal_Bool bHasName = xStor->hasLocation(); + + if ( !bHasName ) + { + if ( _sAttachmentTitle.getLength() ) + aLeadingStr = _sAttachmentTitle; + else + aLeadingStr = String( DEFINE_CONST_UNICODE("noname") ); + } + else + { + INetURLObject aFileObj(_xModel->getURL()); + if ( aFileObj.hasExtension() ) + { + aFileObj.removeExtension(); + if ( _sAttachmentTitle.getLength() ) + aLeadingStr = _sAttachmentTitle; + else + aLeadingStr = aFileObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); + aLeadingStr += String::CreateFromAscii( "_" ); + } + else + { + if ( _sAttachmentTitle.getLength() ) + aLeadingStr = _sAttachmentTitle; + else + aLeadingStr = aFileObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); + aLeadingStr += String::CreateFromAscii( "_" ); + } + } + } + return aLeadingStr; + } + +} +SfxMailModel::SaveResult SfxMailModel::SaveDocument( const ::rtl::OUString& _sAttachmentTitle + , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _xModel + , String& rFileName) +{ + SaveResult eRet = SAVE_CANCELLED; + try + { + Reference<XModifiable> xMod(_xModel,UNO_QUERY); + + // save the document + if ( xMod.is() ) + { + // detect filter + const SfxFilter* pFilter = SfxFilter::GetDefaultFilter(lcl_getFactoryName(_xModel)); +// sal_Bool bHasFilter = pFilter != NULL; + + sal_Bool bRet = sal_False; + // create temp file name with leading chars and extension + Reference < XStorable > xStor( _xModel, UNO_QUERY ); + if ( xStor.is() ) + { + String* pExt = NULL; + INetURLObject aFileObj(_xModel->getURL()); + if ( aFileObj.hasExtension() ) + pExt = new String( String::CreateFromAscii( "." ) + (OUString) aFileObj.getExtension() ); + + String aLeadingStr = lcl_createTempFileName(_xModel,_sAttachmentTitle); + + if ( pFilter && !pExt ) + { + pExt = new String( pFilter->GetWildcard()().GetToken(0) ); + // erase the '*' from the extension (e.g. "*.sdw") + pExt->Erase( 0, 1 ); + } + + { + ::utl::TempFile aTempFile( aLeadingStr, pExt ); + rFileName = aTempFile.GetURL(); + } + delete pExt; + // save document to temp file + + // save document to temp file + Sequence < PropertyValue > aArgs( _xModel->getArgs() ); + ::comphelper::MediaDescriptor aMedia(aArgs); + + if ( pFilter ) + { + ::rtl::OUString sFilter(pFilter->GetFilterName()); + ::rtl::OUString sFilterName(RTL_CONSTASCII_USTRINGPARAM("FilterName")); + if ( !aMedia.createItemIfMissing(sFilterName,sFilter) ) + aMedia[sFilterName] <<= sFilter; + } + + ::rtl::OUString sURL(RTL_CONSTASCII_USTRINGPARAM("URL")); + if ( !aMedia.createItemIfMissing(sURL,::rtl::OUString(rFileName)) ) + aMedia[sURL] <<= ::rtl::OUString(rFileName); + + ::rtl::OUString sSaveTo(RTL_CONSTASCII_USTRINGPARAM("SaveTo")); + if ( !aMedia.createItemIfMissing(sSaveTo,sal_True) ) + aMedia[sSaveTo] <<= sal_True; + + ::rtl::OUString sReadOnly(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")); + if ( !aMedia.createItemIfMissing(sReadOnly,sal_False) ) + aMedia[sReadOnly] <<= sal_False; + + aMedia >> aArgs; + + try + { + Reference < XMultiServiceFactory > xMgr = ::comphelper::getProcessServiceFactory(); + SfxStoringHelper aHelper(xMgr); + aHelper.GUIStoreModel(_xModel,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SaveAs")),aArgs, sal_False, ::rtl::OUString() ); + // xStor->storeToURL(rFileName,aArgs); + bRet = sal_True; + } + catch(Exception&) + { + } + } + + // restore old settings +/* TODO + if ( !bModified && xDocShell->IsEnableSetModified() ) + xDocShell->SetModified( FALSE ); +*/ + eRet = bRet ? SAVE_SUCCESSFULL : SAVE_ERROR; + } + } + catch(Exception&) + { + OSL_ENSURE(0,"Exception catched!"); + } + + return eRet; +} +SfxMailModel::SaveResult SfxMailModel::SaveDocAsPDF( const ::rtl::OUString& _sAttachmentTitle + , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _xModel + , String& rFileName) +{ + SaveResult eRet = SAVE_CANCELLED; + try + { + Reference<XModifiable> xMod(_xModel,UNO_QUERY); + + // save the document + if ( xMod.is() ) + { + // Get PDF Filter from document + ::rtl::OUString sPDFMediaType(RTL_CONSTASCII_USTRINGPARAM("application/pdf")); + + sal_Bool bRet = sal_False; + // create temp file name with leading chars and extension + Reference < XStorable > xStor( _xModel, UNO_QUERY ); + if ( xStor.is() ) + { + String aLeadingStr = lcl_createTempFileName(_xModel,_sAttachmentTitle); + String aPDFExtension = String::CreateFromAscii( ".pdf" ); + ::utl::TempFile aTempFile( aLeadingStr, &aPDFExtension ); + + rFileName = aTempFile.GetURL(); + + // save document to temp file + Sequence < PropertyValue > aArgs( _xModel->getArgs() ); + ::comphelper::MediaDescriptor aMedia(aArgs); + + ::rtl::OUString sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType")); + if ( !aMedia.createItemIfMissing(sMediaType,sPDFMediaType) ) + aMedia[sMediaType] <<= sPDFMediaType; + + ::rtl::OUString sURL(RTL_CONSTASCII_USTRINGPARAM("URL")); + if ( !aMedia.createItemIfMissing(sURL,::rtl::OUString(rFileName)) ) + aMedia[sURL] <<= ::rtl::OUString(rFileName); + aMedia >> aArgs; + + try + { + Reference < XMultiServiceFactory > xMgr = ::comphelper::getProcessServiceFactory(); + SfxStoringHelper aHelper(xMgr); + aHelper.GUIStoreModel(_xModel,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ExportToPDF")),aArgs, sal_False, ::rtl::OUString); + // xStor->storeToURL(rFileName,aArgs); + bRet = sal_True; + } + catch(Exception&) + { + } + + eRet = bRet ? SAVE_SUCCESSFULL : SAVE_CANCELLED; + + // restore old settings + /* TODO + if ( !bModified && xDocShell->IsEnableSetModified() ) + xDocShell->SetModified( FALSE ); + */ + } + } + } + catch(Exception&) + { + OSL_ENSURE(0,"Exception catched!"); + } + + return eRet; +} +// ----------------------------------------------------------------------------- +SfxMailModel::SendMailResult SfxMailModel::AttachDocument( MailDocType _eMailDocType + , const Reference< XModel >& _xModel + , const ::rtl::OUString& _sAttachmentTitle) +{ + SaveResult eSaveResult; + String aFileName; + +// sal_Bool bSuccessfull = sal_False; + if ( _eMailDocType == TYPE_SELF ) + eSaveResult = SaveDocument( _sAttachmentTitle,_xModel,aFileName); + else + eSaveResult = SaveDocAsPDF( _sAttachmentTitle,_xModel,aFileName); + + if ( eSaveResult == SAVE_SUCCESSFULL && aFileName.Len() ) + maAttachedDocuments.push_back(aFileName); + return eSaveResult == SAVE_SUCCESSFULL ? SEND_MAIL_OK : SEND_MAIL_ERROR; +} +// ----------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxMailModel, DoneHdl, void*, EMPTYARG ) +{ + mbLoadDone = sal_True; + return 0; +} +// ----------------------------------------------------------------------------- +IMPL_LINK_INLINE_END( SfxMailModel, DoneHdl, void*, EMPTYARG ) + +SfxMailModel::SfxMailModel( const Reference< XFrame >& _xFrame) : + + mpToList ( NULL ), + mpCcList ( NULL ), + mpBccList ( NULL ), + m_xCurrentFrame ( _xFrame ), + mePriority ( PRIO_NORMAL ), + mbLoadDone ( sal_True ) + +{ +} + +SfxMailModel::~SfxMailModel() +{ + ClearList( mpToList ); + delete mpToList; + ClearList( mpCcList ); + delete mpCcList; + ClearList( mpBccList ); + delete mpBccList; +} + +void SfxMailModel::AddAddress( const String& rAddress, AddressRole eRole ) +{ + // don't add a empty address + if ( rAddress.Len() > 0 ) + { + AddressList_Impl* pList = NULL; + if ( ROLE_TO == eRole ) + { + if ( !mpToList ) + // create the list + mpToList = new AddressList_Impl; + pList = mpToList; + } + else if ( ROLE_CC == eRole ) + { + if ( !mpCcList ) + // create the list + mpCcList = new AddressList_Impl; + pList = mpCcList; + } + else if ( ROLE_BCC == eRole ) + { + if ( !mpBccList ) + // create the list + mpBccList = new AddressList_Impl; + pList = mpBccList; + } + else + { + DBG_ERRORFILE( "invalid address role" ); + } + + if ( pList ) + { + // add address to list + AddressItemPtr_Impl pAddress = new String( rAddress ); + pList->Insert( pAddress, LIST_APPEND ); + } + } +} + +SfxMailModel::SendMailResult SfxMailModel::Send( ) +{ + OSL_ENSURE(!maAttachedDocuments.empty(),"No document added!"); + SendMailResult eResult = SEND_MAIL_ERROR; + if ( !maAttachedDocuments.empty() ) + { + + Reference < XMultiServiceFactory > xMgr = ::comphelper::getProcessServiceFactory(); + if ( xMgr.is() ) + { + Reference< XSimpleMailClientSupplier > xSimpleMailClientSupplier; + + // Prefer the SimpleSystemMail service if available + xSimpleMailClientSupplier = Reference< XSimpleMailClientSupplier >( + xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleSystemMail" ))), + UNO_QUERY ); + + if ( ! xSimpleMailClientSupplier.is() ) + { + xSimpleMailClientSupplier = Reference< XSimpleMailClientSupplier >( + xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleCommandMail" ))), + UNO_QUERY ); + } + + if ( xSimpleMailClientSupplier.is() ) + { + Reference< XSimpleMailClient > xSimpleMailClient = xSimpleMailClientSupplier->querySimpleMailClient(); + + if ( !xSimpleMailClient.is() ) + { + // no mail client support => message box! + return SEND_MAIL_ERROR; + } + + // we have a simple mail client + Reference< XSimpleMailMessage > xSimpleMailMessage = xSimpleMailClient->createSimpleMailMessage(); + if ( xSimpleMailMessage.is() ) + { + sal_Int32 nSendFlags = SimpleMailClientFlags::DEFAULTS; + if ( maFromAddress.Len() == 0 ) + { + // from address not set, try figure out users e-mail address + CreateFromAddress_Impl( maFromAddress ); + } + xSimpleMailMessage->setOriginator( maFromAddress ); + + sal_Int32 nToCount = mpToList ? mpToList->Count() : 0; + sal_Int32 nCcCount = mpCcList ? mpCcList->Count() : 0; + sal_Int32 nCcSeqCount = nCcCount; + + // set recipient (only one) for this simple mail server!! + if ( nToCount > 1 ) + { + nCcSeqCount = nToCount - 1 + nCcCount; + xSimpleMailMessage->setRecipient( *mpToList->GetObject( 0 )); + nSendFlags = SimpleMailClientFlags::NO_USER_INTERFACE; + } + else if ( nToCount == 1 ) + { + xSimpleMailMessage->setRecipient( *mpToList->GetObject( 0 )); + nSendFlags = SimpleMailClientFlags::NO_USER_INTERFACE; + } + + // all other recipient must be handled with CC recipients! + if ( nCcSeqCount > 0 ) + { + sal_Int32 nIndex = 0; + Sequence< OUString > aCcRecipientSeq; + + aCcRecipientSeq.realloc( nCcSeqCount ); + if ( nCcSeqCount > nCcCount ) + { + for ( sal_Int32 i = 1; i < nToCount; ++i ) + { + aCcRecipientSeq[nIndex++] = *mpToList->GetObject(i); + } + } + + for ( sal_Int32 i = 0; i < nCcCount; i++ ) + { + aCcRecipientSeq[nIndex++] = *mpCcList->GetObject(i); + } + xSimpleMailMessage->setCcRecipient( aCcRecipientSeq ); + } + + sal_Int32 nBccCount = mpBccList ? mpBccList->Count() : 0; + if ( nBccCount > 0 ) + { + Sequence< OUString > aBccRecipientSeq( nBccCount ); + for ( sal_Int32 i = 0; i < nBccCount; ++i ) + { + aBccRecipientSeq[i] = *mpBccList->GetObject(i); + } + xSimpleMailMessage->setBccRecipient( aBccRecipientSeq ); + } + + Sequence< OUString > aAttachmentSeq(&(maAttachedDocuments[0]),maAttachedDocuments.size()); + + xSimpleMailMessage->setSubject( maSubject ); + xSimpleMailMessage->setAttachement( aAttachmentSeq ); + + // Bugfix: #95743# + // Due to the current clipboard implementation we cannot stop the main thread + // because the clipboard implementation calls the main thread from another thread + // and this would result in a deadlock! + // Currently we create a thread to send a message and process all remaining error + // handling in this thread!! + + OMailSendThreadImpl* pMailSendThread = new OMailSendThreadImpl( xSimpleMailClient, xSimpleMailMessage, m_xCurrentFrame,nSendFlags ); + pMailSendThread->create(); + + // Return always true as the real error handling occurss in the OMailSendThreadImpl-implementation! + eResult = SEND_MAIL_OK; + } + } + } + } + else + eResult = SEND_MAIL_CANCELLED; + + return eResult; +} diff --git a/sfx2/source/dialog/mailwindow.src b/sfx2/source/dialog/mailwindow.src new file mode 100644 index 000000000000..e5648e7f414f --- /dev/null +++ b/sfx2/source/dialog/mailwindow.src @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "dialog.hrc" +#include "helpid.hrc" + +// RID_ERRBOX_MAIL_CONFIG --------------------------------------------------- + +ErrorBox RID_ERRBOX_MAIL_CONFIG +{ + BUTTONS = WB_OK ; + DEFBUTTON = WB_DEF_OK ; + MESSAGE [ en-US ] = "%PRODUCTNAME was unable to find a working e-mail configuration. Please save this document locally instead and attach it from within your e-mail client." ; +}; + +// ------------------------------------------------------------------- EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/makefile.mk b/sfx2/source/dialog/makefile.mk new file mode 100755 index 000000000000..4c56cd683e34 --- /dev/null +++ b/sfx2/source/dialog/makefile.mk @@ -0,0 +1,127 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=sfx2 +TARGET=dialog + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------------- + +EXCEPTIONSFILES=\ + $(SLO)$/filedlghelper.obj \ + $(SLO)$/filtergrouping.obj \ + $(SLO)$/itemconnect.obj \ + $(SLO)$/mailmodel.obj \ + $(SLO)$/partwnd.obj \ + $(SLO)$/recfloat.obj \ + $(SLO)$/templdlg.obj \ + $(SLO)$/dinfdlg.obj \ + $(SLO)$/dockwin.obj \ + $(SLO)$/taskpane.obj + +SLOFILES =\ + $(EXCEPTIONSFILES) \ + $(SLO)$/about.obj \ + $(SLO)$/alienwarn.obj \ + $(SLO)$/basedlgs.obj \ + $(SLO)$/dinfedt.obj \ + $(SLO)$/intro.obj \ + $(SLO)$/mgetempl.obj \ + $(SLO)$/navigat.obj \ + $(SLO)$/newstyle.obj \ + $(SLO)$/passwd.obj \ + $(SLO)$/printopt.obj \ + $(SLO)$/sfxdlg.obj \ + $(SLO)$/splitwin.obj \ + $(SLO)$/srchdlg.obj \ + $(SLO)$/styfitem.obj \ + $(SLO)$/styledlg.obj \ + $(SLO)$/tabdlg.obj \ + $(SLO)$/tplcitem.obj \ + $(SLO)$/tplpitem.obj \ + $(SLO)$/versdlg.obj \ + $(SLO)$/securitypage.obj \ + $(SLO)$/titledockwin.obj + +SRS1NAME=$(TARGET) +SRC1FILES =\ + recfloat.src \ + alienwarn.src \ + dialog.src \ + dinfdlg.src \ + dinfedt.src \ + filedlghelper.src \ + mailwindow.src \ + mgetempl.src \ + newstyle.src \ + passwd.src \ + templdlg.src \ + versdlg.src \ + printopt.src \ + srchdlg.src \ + securitypage.src \ + titledockwin.src \ + taskpane.src + +.IF "$(BUILD_VER_STRING)"!="" +.IF "$(GUI)"=="UNX" +CFLAGS+=-DBUILD_VER_STRING='"$(BUILD_VER_STRING)"' +.ELSE # "$(GUI)"=="UNX" +CFLAGS+=-DBUILD_VER_STRING="$(subst,",\" "$(BUILD_VER_STRING)")" +.ENDIF # "$(GUI)"=="UNX" +.ENDIF + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +$(INCCOM)$/cuilib.hxx: makefile.mk +.IF "$(GUI)"=="UNX" + $(RM) $@ + @echo \#define DLL_NAME \"libcui$(DLLPOSTFIX)$(DLLPOST)\" >$@ +.ELSE + @echo $(EMQ)#define DLL_NAME $(EMQ)"cui$(DLLPOSTFIX)$(DLLPOST)$(EMQ)" >$@ +.ENDIF + +$(SLO)$/sfxdlg.obj : $(INCCOM)$/cuilib.hxx + +$(SLO)$/about.obj : $(INCCOM)$/aboutbmpnames.hxx + +.INCLUDE .IGNORE : $(MISC)$/about_bmp_names.mk + +.IF "$(ABOUT_BITMAPS:f)"!="$(LASTTIME_ABOUT_BITMAPS)" +DO_PHONY=.PHONY +.ENDIF # "$(ABOUT_BITMAPS:f)"!="$(LASTTIME_ABOUT_BITMAPS)" + +$(INCCOM)$/aboutbmpnames.hxx $(DO_PHONY): + echo const char ABOUT_BITMAP_STRINGLIST[]=$(EMQ)"$(ABOUT_BITMAPS:f:t",")$(EMQ)"$(EMQ); > $@ + echo LASTTIME_ABOUT_BITMAPS=$(ABOUT_BITMAPS:f) > $(MISC)$/about_bmp_names.mk diff --git a/sfx2/source/dialog/mgetempl.cxx b/sfx2/source/dialog/mgetempl.cxx new file mode 100644 index 000000000000..1f5472cf2052 --- /dev/null +++ b/sfx2/source/dialog/mgetempl.cxx @@ -0,0 +1,672 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// include --------------------------------------------------------------- + +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <vcl/field.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/style.hxx> +#ifndef GCC +#endif + +#include <sfx2/styfitem.hxx> +#include <sfx2/styledlg.hxx> +#include <sfx2/app.hxx> +#include <sfx2/mgetempl.hxx> +#include <sfx2/objsh.hxx> +#include "sfxtypes.hxx" +#include "sfxresid.hxx" +#include <sfx2/module.hxx> + +#include <sfx2/sfx.hrc> +#include "dialog.hrc" +#include "mgetempl.hrc" + +#ifndef _SFX_STYLE_HRC +#include <svl/style.hrc> +#endif + +// SfxManageStyleSheetPage ----------------------------------------------- + +SfxManageStyleSheetPage::SfxManageStyleSheetPage( Window* pParent, const SfxItemSet& rAttrSet ) : + + SfxTabPage( pParent, SfxResId( TP_MANAGE_STYLES ), rAttrSet ), + + aNameFt ( this, SfxResId( FT_NAME ) ), + aNameEd ( this, SfxResId( ED_NAME ) ), + aAutoCB ( this, SfxResId( CB_AUTO ) ), + + aFollowFt ( this, SfxResId( FT_NEXT ) ), + aFollowLb ( this, SfxResId( LB_NEXT ) ), + + aBaseFt ( this, SfxResId( FT_BASE ) ), + aBaseLb ( this, SfxResId( LB_BASE ) ), + + aFilterFt ( this, SfxResId( FT_REGION ) ), + aFilterLb ( this, SfxResId( LB_REGION ) ), + + aDescFt ( this, SfxResId( FT_DESC ) ), + aDescED ( this, SfxResId( ED_DESC ) ), + aDescGb ( this, SfxResId( GB_DESC ) ), + + pStyle( &( (SfxStyleDialog*)pParent->GetParent() )->GetStyleSheet() ), + + pItem ( 0 ), + bModified ( FALSE ), + aName ( pStyle->GetName() ), + aFollow ( pStyle->GetFollow() ), + aParent ( pStyle->GetParent() ), + nFlags ( pStyle->GetMask() ) + +/* [Beschreibung] + + Konstruktor; initialisiert die ListBoxen mit den Vorlagen + +*/ + +{ + FreeResource(); + + if ( IsBackground() ) + aDescED.SetBackground( GetBackground() ); + FixedInfo* pInfo = new FixedInfo( this ); + aDescED.SetFont( pInfo->GetFont() ); + delete pInfo; + + aDescED.Hide(); + aDescFt.Show(); + + // diese Page braucht ExchangeSupport + SetExchangeSupport(); + + ResMgr* pResMgr = SFX_APP()->GetModule_Impl()->GetResMgr(); + DBG_ASSERT( pResMgr, "kein ResMgr am Modul" ); + pFamilies = new SfxStyleFamilies( ResId( DLG_STYLE_DESIGNER, *pResMgr ) ); + + SfxStyleSheetBasePool* pPool = 0; + SfxObjectShell* pDocShell = SfxObjectShell::Current(); + + if ( pDocShell ) + pPool = pDocShell->GetStyleSheetPool(); + DBG_ASSERT( pPool, "kein Pool oder keine DocShell" ); + + if ( pPool ) + { + pPool->SetSearchMask( pStyle->GetFamily() ); + pPool->First(); // fuer SW - interne Liste updaten + } + + if ( !pStyle->GetName().Len() && pPool ) + { + // NullString als Name -> Name generieren + String aNoName( SfxResId( STR_NONAME ) ); + USHORT nNo = 1; + String aNo( aNoName ); + aNoName += String::CreateFromInt32( nNo ); + while ( pPool->Find( aNoName ) ) + { + ++nNo; + aNoName = aNo; + aNoName += String::CreateFromInt32( nNo ); + } + pStyle->SetName( aNoName ); + aName = aNoName; + aFollow = pStyle->GetFollow(); + aParent = pStyle->GetParent(); + } + aNameEd.SetText(pStyle->GetName()); + + if ( !pStyle->IsUserDefined() ) + aNameEd.SetReadOnly(); + + if ( pStyle->HasFollowSupport() && pPool ) + { + SfxStyleSheetBase* pPoolStyle = pPool->First(); + + while ( pPoolStyle ) + { + aFollowLb.InsertEntry( pPoolStyle->GetName() ); + pPoolStyle = pPool->Next(); + } + + // eine neue Vorlage ist noch nicht im Pool + if ( LISTBOX_ENTRY_NOTFOUND == aFollowLb.GetEntryPos( pStyle->GetName() ) ) + aFollowLb.InsertEntry( pStyle->GetName() ); + } + else + { + aFollowFt.Hide(); + aFollowLb.Hide(); + + aFilterFt.SetPosPixel( aBaseFt.GetPosPixel() ); + aFilterLb.SetPosPixel( aBaseLb.GetPosPixel() ); + + aBaseFt.SetPosPixel( aFollowFt.GetPosPixel() ); + aBaseLb.SetPosPixel( aFollowLb.GetPosPixel() ); + } + + if ( pStyle->HasParentSupport() && pPool ) + { + if ( pStyle->HasClearParentSupport() ) + // die Basisvorlage darf auf NULL gesetzt werden + aBaseLb.InsertEntry( String( SfxResId( STR_NONE ) ) ); + + SfxStyleSheetBase* pPoolStyle = pPool->First(); + + while ( pPoolStyle ) + { + const String aStr( pPoolStyle->GetName() ); + // eigener Namen nicht als Basisvorlage + if ( aStr != aName ) + aBaseLb.InsertEntry( aStr ); + pPoolStyle = pPool->Next(); + } + } + else + { + aBaseFt.Disable(); + aBaseLb.Disable(); + } + USHORT nCount = pFamilies->Count(); + + USHORT i; + for ( i = 0; i < nCount; ++i ) + { + pItem = pFamilies->GetObject(i); + + if ( pItem->GetFamily() == pStyle->GetFamily() ) + break; + } + + USHORT nStyleFilterIdx = 0xffff; + + if ( i < nCount ) + { + // Filterflags + const SfxStyleFilter& rList = pItem->GetFilterList(); + nCount = (USHORT)rList.Count(); + USHORT nIdx = 0; + USHORT nMask = pStyle->GetMask() & ~SFXSTYLEBIT_USERDEF; + + if ( !nMask ) // Benutzervorlage? + nMask = pStyle->GetMask(); + + for ( i = 0; i < nCount; ++i ) + { + SfxFilterTupel* pTupel = rList.GetObject(i); + + if ( pTupel->nFlags != SFXSTYLEBIT_AUTO && + pTupel->nFlags != SFXSTYLEBIT_USED && +// pTupel->nFlags != SFXSTYLEBIT_USERDEF && + pTupel->nFlags != SFXSTYLEBIT_ALL ) + { + aFilterLb.InsertEntry( pTupel->aName, nIdx ); + aFilterLb.SetEntryData(nIdx, (void*)(long)i); + + if ( ( pTupel->nFlags & nMask ) == nMask ) + nStyleFilterIdx = nIdx; + ++nIdx; + } + } + + if ( nStyleFilterIdx != 0xFFFF ) + aFilterLb.SelectEntryPos( nStyleFilterIdx ); + } + + if ( !aFilterLb.GetEntryCount() || !pStyle->IsUserDefined() ) + { + pItem = 0; + aFilterFt.Disable(); + aFilterLb.Disable(); + } + else + aFilterLb.SaveValue(); + SetDescriptionText_Impl(); + + if ( aFollowLb.IsEnabled() || aBaseLb.IsEnabled() ) + { + aNameEd.SetGetFocusHdl( + LINK( this, SfxManageStyleSheetPage, GetFocusHdl ) ); + aNameEd.SetLoseFocusHdl( + LINK( this, SfxManageStyleSheetPage, LoseFocusHdl ) ); + } + // ist es ein Style mit automatischem Update? (nur SW) + if(SFX_ITEM_SET == rAttrSet.GetItemState(SID_ATTR_AUTO_STYLE_UPDATE)) + { + Size aSize = aNameEd.GetSizePixel(); + aSize.Width() /= 2; + aNameEd.SetSizePixel(aSize); + aAutoCB.Show(); + } +} + +//------------------------------------------------------------------------- + +SfxManageStyleSheetPage::~SfxManageStyleSheetPage() + +/* [Beschreibung] + + Destruktor; Freigabe der Daten + +*/ + +{ + aNameEd.SetGetFocusHdl( Link() ); + aNameEd.SetLoseFocusHdl( Link() ); + delete pFamilies; + pItem = 0; + pStyle = 0; + +} + +//------------------------------------------------------------------------- + +void SfxManageStyleSheetPage::UpdateName_Impl( ListBox* pBox, + const String& rNew ) + +/* [Beschreibung] + + Nach der "Anderung eines Vorlagennamens die ListBox pBox + aktualisieren + + [Parameter] + + ListBox* pBox ListBox, deren Eintr"age aktualisiert + werden sollen + const String& rNew der neue Name + +*/ + +{ + if ( pBox->IsEnabled() ) + { + // ist der aktuelle Eintrag, dessen Namen modifizieren wurde + const BOOL bSelect = pBox->GetSelectEntry() == aBuf; + pBox->RemoveEntry( aBuf ); + pBox->InsertEntry( rNew ); + + if ( bSelect ) + pBox->SelectEntry( rNew ); + } +} + +//------------------------------------------------------------------------- + +void SfxManageStyleSheetPage::SetDescriptionText_Impl() + +/* [Beschreibung] + + Attributbeschreibung setzen. daf"ur die eingestellte Metrik besorgen. +*/ + +{ + SfxMapUnit eUnit = SFX_MAPUNIT_CM; +// FieldUnit eFieldUnit = pSfxApp->GetOptions().GetMetric(); + FieldUnit eFieldUnit( FUNIT_CM ); + SfxModule* pModule = SfxModule::GetActiveModule(); + if ( pModule ) + { + const SfxPoolItem* pPoolItem = pModule->GetItem( SID_ATTR_METRIC ); + if ( pPoolItem ) + eFieldUnit = (FieldUnit)( (SfxUInt16Item*)pPoolItem )->GetValue(); + } + + switch ( eFieldUnit ) + { + case FUNIT_MM: eUnit = SFX_MAPUNIT_MM; break; + + case FUNIT_CM: + case FUNIT_M: + case FUNIT_KM: eUnit = SFX_MAPUNIT_CM; break; + + case FUNIT_POINT: + case FUNIT_PICA: eUnit = SFX_MAPUNIT_POINT; break; + + case FUNIT_INCH: + case FUNIT_FOOT: + case FUNIT_MILE: eUnit = SFX_MAPUNIT_INCH; break; + + default: + DBG_ERRORFILE( "not supported fieldunit" ); + } + aDescFt.SetText( pStyle->GetDescription( eUnit ) ); +} + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxManageStyleSheetPage, GetFocusHdl, Edit *, pEdit ) + +/* [Beschreibung] + + StarView Handler; GetFocus-Handler des Edits mit dem Vorlagennamen. + +*/ + +{ + aBuf = pEdit->GetText().EraseLeadingChars(); + return 0; +} +IMPL_LINK_INLINE_END( SfxManageStyleSheetPage, GetFocusHdl, Edit *, pEdit ) + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxManageStyleSheetPage, LoseFocusHdl, Edit *, pEdit ) + +/* [Beschreibung] + + StarView Handler; LoseFocus-Handler des Edits mit dem Vorlagennamen. + Dieser aktualisiert ggf. die Listbox mit den Folgevorlagen. + In der Listbox mit den Basisvorlagen ist die aktuelle Vorlage + selbst nicht enthalten. + +*/ + +{ + const String aStr( pEdit->GetText().EraseLeadingChars() ); + pEdit->SetText( aStr ); + // ggf. Listbox der Basisvorlagen aktualisieren + if ( aStr != aBuf ) + UpdateName_Impl( &aFollowLb, aStr ); + return 0; +} +IMPL_LINK_INLINE_END( SfxManageStyleSheetPage, LoseFocusHdl, Edit *, pEdit ) + +//------------------------------------------------------------------------- + +BOOL SfxManageStyleSheetPage::FillItemSet( SfxItemSet& rSet ) + +/* [Beschreibung] + + + Handler f"ur das Setzen der (modifizierten) Daten. Wird aus + dem Ok des SfxTabDialog gerufen. + + [Parameter] + + SfxItemSet &rAttrSet das Set, das die Daten entgegennimmt. + + + [R"uckgabewert] + + BOOL TRUE: es hat eine "Anderung der Daten + stattgefunden + FALSE: es hat keine "Anderung der Daten + stattgefunden + + [Querverweise] + + <class SfxTabDialog> + +*/ + +{ + const USHORT nFilterIdx = aFilterLb.GetSelectEntryPos(); + + // Filter setzen + + if ( LISTBOX_ENTRY_NOTFOUND != nFilterIdx && + nFilterIdx != aFilterLb.GetSavedValue() && + aFilterLb.IsEnabled() ) + { + bModified = TRUE; + DBG_ASSERT( pItem, "kein Item" ); + // geht nur bei Benutzervorlagen +#if OSL_DEBUG_LEVEL > 1 + USHORT nIdx = (USHORT)(long)aFilterLb.GetEntryData( nFilterIdx ); + SfxFilterTupel* p; + p = pItem->GetFilterList().GetObject( nIdx ); +#endif + USHORT nMask = pItem->GetFilterList().GetObject( + (USHORT)(long)aFilterLb.GetEntryData( nFilterIdx ) )->nFlags | + SFXSTYLEBIT_USERDEF; + pStyle->SetMask( nMask ); + } + if(aAutoCB.IsVisible() && + aAutoCB.IsChecked() != aAutoCB.GetSavedValue()) + { + rSet.Put(SfxBoolItem(SID_ATTR_AUTO_STYLE_UPDATE, aAutoCB.IsChecked())); + } + + return bModified; +} + +//------------------------------------------------------------------------- + +void SfxManageStyleSheetPage::Reset( const SfxItemSet& /*rAttrSet*/ ) + +/* [Beschreibung] + + + Handler f"ur das Initialisieren der Seite mit den initialen Daten. + + [Parameter] + + const SfxItemSet &rAttrSet das Set mit den Daten + + + [Querverweise] + + <class SfxTabDialog> + +*/ + +{ + bModified = FALSE; + String sCmp( pStyle->GetName() ); + + if ( sCmp != aName ) + pStyle->SetName( aName ); + aNameEd.SetText( aName ); + + if ( aFollowLb.IsEnabled() ) + { + sCmp = pStyle->GetFollow(); + + if ( sCmp != aFollow ) + pStyle->SetFollow( aFollow ); + + if ( !aFollow.Len() ) + aFollowLb.SelectEntry( aName ); + else + aFollowLb.SelectEntry( aFollow ); + } + + if ( aBaseLb.IsEnabled() ) + { + sCmp = pStyle->GetParent(); + + if ( sCmp != aParent ) + pStyle->SetParent( aParent ); + + if ( !aParent.Len() ) + aBaseLb.SelectEntry( String( SfxResId( STR_NONE ) ) ); + else + aBaseLb.SelectEntry( aParent ); + + if ( String( SfxResId( STR_STANDARD ) ) == aName ) + { + // die Standardvorlage kann nicht verkn"upft werden + aBaseFt.Disable(); + aBaseLb.Disable(); + } + } + + if ( aFilterLb.IsEnabled() ) + { + USHORT nCmp = pStyle->GetMask(); + + if ( nCmp != nFlags ) + pStyle->SetMask( nFlags ); + aFilterLb.SelectEntryPos( aFilterLb.GetSavedValue() ); + } +} + +//------------------------------------------------------------------------- + +SfxTabPage* SfxManageStyleSheetPage::Create( Window* pParent, + const SfxItemSet &rAttrSet ) + +/* [Beschreibung] + + + Factory f"ur das Erzeugen der Seite + + [Querverweise] + + <class SfxTabDialog> + +*/ + +{ + return new SfxManageStyleSheetPage( pParent, rAttrSet ); +} + +//------------------------------------------------------------------------- + +void SfxManageStyleSheetPage::ActivatePage( const SfxItemSet& rSet) + +/* [Beschreibung] + + ActivatePage- Handler des SfxTabDialog; wird f"ur die Aktualisierung + des beschreibenden Textes verwendet, da sich dieser durch "Anderungen + der Daten anderer Seiten ge"andert haben kann. + + [Parameter] + + const SfxItemSet& das Set f"ur den Datenaustausch; wird + hier nicht verwendet. + + [Querverweise] + + <SfxTabDialog::ActivatePage(const SfxItemSet &)> + +*/ + +{ + SetDescriptionText_Impl(); + + // ist es ein Style mit automatischem Update? (nur SW) + const SfxPoolItem* pPoolItem; + + if ( SFX_ITEM_SET == + rSet.GetItemState( SID_ATTR_AUTO_STYLE_UPDATE, FALSE, &pPoolItem ) ) + aAutoCB.Check( ( (const SfxBoolItem*)pPoolItem )->GetValue() ); + aAutoCB.SaveValue(); +} + +//------------------------------------------------------------------------- + +int SfxManageStyleSheetPage::DeactivatePage( SfxItemSet* pItemSet ) + +/* [Beschreibung] + + DeactivatePage- Handler des SfxTabDialog; die Daten werden + an der Vorlage eingestellt, damit die richtige Vererbung + f"ur die anderen Seiten des Dialoges vorliegt. + Im Fehlerfall wird das Verlassen der Seite unterbunden. + + [Parameter] + + SfxItemSet* das Set f"ur den Datenaustausch; wird hier nicht verwendet. + + [Querverweise] + + <SfxTabDialog::DeactivatePage(SfxItemSet*)> + +*/ + +{ + int nRet = SfxTabPage::LEAVE_PAGE; + + if ( aNameEd.IsModified() ) + { + // bei <Enter> wird kein LoseFocus() durch StarView ausgel"ost + if ( aNameEd.HasFocus() ) + LoseFocusHdl( &aNameEd ); + + if ( !pStyle->SetName( aNameEd.GetText().EraseLeadingChars() ) ) + { + InfoBox aBox( this, SfxResId( MSG_TABPAGE_INVALIDNAME ) ); + aBox.Execute(); + aNameEd.GrabFocus(); + aNameEd.SetSelection( Selection( SELECTION_MIN, SELECTION_MAX ) ); + return SfxTabPage::KEEP_PAGE; + } + bModified = TRUE; + } + + if ( pStyle->HasFollowSupport() && aFollowLb.IsEnabled() ) + { + const String aFollowEntry( aFollowLb.GetSelectEntry() ); + + if ( pStyle->GetFollow() != aFollowEntry ) + { + if ( !pStyle->SetFollow( aFollowEntry ) ) + { + InfoBox aBox( this, SfxResId( MSG_TABPAGE_INVALIDSTYLE ) ); + aBox.Execute(); + aFollowLb.GrabFocus(); + return SfxTabPage::KEEP_PAGE; + } + bModified = TRUE; + } + } + + if ( aBaseLb.IsEnabled() ) + { + String aParentEntry( aBaseLb.GetSelectEntry() ); + + if ( String( SfxResId( STR_NONE ) ) == aParentEntry || aParentEntry == pStyle->GetName() ) + aParentEntry.Erase(); + + if ( pStyle->GetParent() != aParentEntry ) + { + if ( !pStyle->SetParent( aParentEntry ) ) + { + InfoBox aBox( this, SfxResId( MSG_TABPAGE_INVALIDPARENT ) ); + aBox.Execute(); + aBaseLb.GrabFocus(); + return SfxTabPage::KEEP_PAGE; + } + bModified = TRUE; + nRet |= (int)SfxTabPage::REFRESH_SET; + } + } + + if ( pItemSet ) + FillItemSet( *pItemSet ); + + return nRet; +} + diff --git a/sfx2/source/dialog/mgetempl.hrc b/sfx2/source/dialog/mgetempl.hrc new file mode 100644 index 000000000000..e998baba939d --- /dev/null +++ b/sfx2/source/dialog/mgetempl.hrc @@ -0,0 +1,38 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#define ED_NAME 2 +#define LB_NEXT 4 +#define FT_BASE 5 +#define LB_BASE 6 +#define LB_REGION 8 +#define FT_DESC 9 +#define GB_DESC 10 +#define FT_REGION 7 +#define FT_NEXT 3 +#define FT_NAME 1 +#define ED_DESC 11 +#define CB_AUTO 12 diff --git a/sfx2/source/dialog/mgetempl.src b/sfx2/source/dialog/mgetempl.src new file mode 100644 index 000000000000..f07d0873e454 --- /dev/null +++ b/sfx2/source/dialog/mgetempl.src @@ -0,0 +1,152 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + // include --------------------------------------------------------------- +#include <sfx2/sfx.hrc> +#include "helpid.hrc" +#include "mgetempl.hrc" + // pragma ---------------------------------------------------------------- + + // TP_MANAGE_STYLES ------------------------------------------------------ +TabPage TP_MANAGE_STYLES +{ + HelpId = HID_MANAGE_STYLES ; + Hide = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + FixedText FT_NAME + { + Pos = MAP_APPFONT ( 6 , 8 ) ; + Size = MAP_APPFONT ( 61 , 10 ) ; + Text [ en-US ] = "~Name" ; + }; + Edit ED_NAME + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 6 ) ; + Size = MAP_APPFONT ( 184 , 12 ) ; + }; + CheckBox CB_AUTO + { + Pos = MAP_APPFONT ( 164 , 8 ) ; + Size = MAP_APPFONT ( 90 , 10 ) ; + Hide = TRUE ; + Text [ en-US ] = "~AutoUpdate" ; + }; + FixedText FT_NEXT + { + Pos = MAP_APPFONT ( 6 , 26 ) ; + Size = MAP_APPFONT ( 61 , 10 ) ; + Text [ en-US ] = "Ne~xt Style" ; + }; + ListBox LB_NEXT + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 24 ) ; + Size = MAP_APPFONT ( 184 , 65 ) ; + DropDown = TRUE ; + Sort = TRUE ; + }; + FixedText FT_BASE + { + Pos = MAP_APPFONT ( 6 , 44 ) ; + Size = MAP_APPFONT ( 61 , 10 ) ; + /* ### ACHTUNG: Neuer Text in Resource? ~Verknüpft mit : ~Verkn³pft mit */ + /* ### ACHTUNG: Neuer Text in Resource? ~Verknüpft mit : ~Verkn³pft mit */ + Text [ en-US ] = "Linked with" ; + }; + ListBox LB_BASE + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 42 ) ; + Size = MAP_APPFONT ( 184 , 65 ) ; + DropDown = TRUE ; + Sort = TRUE ; + }; + FixedText FT_REGION + { + Pos = MAP_APPFONT ( 6 , 62 ) ; + Size = MAP_APPFONT ( 61 , 10 ) ; + Text [ en-US ] = "~Category" ; + }; + ListBox LB_REGION + { + Border = TRUE ; + Pos = MAP_APPFONT ( 70 , 60 ) ; + Size = MAP_APPFONT ( 184 , 64 ) ; + DropDown = TRUE ; + }; + FixedText FT_DESC + { + Pos = MAP_APPFONT ( 12 , 88 ) ; + Size = MAP_APPFONT ( 236 , 85 ) ; + WordBreak = TRUE ; + Hide = TRUE ; + }; + MultiLineEdit ED_DESC + { + Pos = MAP_APPFONT ( 12 , 88 ) ; + Size = MAP_APPFONT ( 236 , 85 ) ; + ReadOnly = TRUE ; + IgnoreTab = TRUE; + }; + FixedLine GB_DESC + { + Pos = MAP_APPFONT ( 6 , 77 ) ; + Size = MAP_APPFONT ( 248 , 8 ) ; + Text [ en-US ] = "Contains" ; + }; +}; + // ********************************************************************** EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/navigat.cxx b/sfx2/source/dialog/navigat.cxx new file mode 100644 index 000000000000..d7f258e7ccb3 --- /dev/null +++ b/sfx2/source/dialog/navigat.cxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// includes ******************************************************************* + +#ifndef GCC +#endif + +#include <sfx2/navigat.hxx> +#include <sfx2/sfx.hrc> +#include <sfx2/app.hxx> +#include "sfxresid.hxx" +#include "helpid.hrc" + +SFX_IMPL_DOCKINGWINDOW( SfxNavigatorWrapper , SID_NAVIGATOR ); + +SfxNavigatorWrapper::SfxNavigatorWrapper( Window* pParentWnd , + USHORT nId , + SfxBindings* pBindings , + SfxChildWinInfo* pInfo ) + : SfxChildWindow( pParentWnd , nId ) +{ + pWindow = new SfxNavigator( pBindings, this, pParentWnd, + WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE); + eChildAlignment = SFX_ALIGN_NOALIGNMENT; + + pWindow->SetHelpId ( HID_NAVIGATOR_WINDOW ); + pWindow->SetOutputSizePixel( Size( 270, 240 ) ); + + ( ( SfxDockingWindow* ) pWindow )->Initialize( pInfo ); + SetHideNotDelete( TRUE ); +} + +SfxNavigator::SfxNavigator( SfxBindings* pBind , + SfxChildWindow* pChildWin , + Window* pParent , + WinBits nBits ) + : SfxDockingWindow( pBind , + pChildWin , + pParent , + nBits ) + , pWrapper( pChildWin ) +{ + SetText( String( SfxResId( SID_NAVIGATOR ) ) ); +} + +void SfxNavigator::Resize() +{ + SfxDockingWindow::Resize(); + if ( pWrapper->GetContextWindow() ) + pWrapper->GetContextWindow()->SetSizePixel( GetOutputSizePixel() ); +} + +void SfxNavigator::Resizing( Size &rSize ) +{ + SfxDockingWindow::Resizing( rSize ); + + SfxChildWindowContext *pCon = GetChildWindow_Impl()->GetContext_Impl(); + DBG_ASSERT( pCon, "Kein Context!" ); + if ( pCon ) + pCon->Resizing( rSize ); +} + +BOOL SfxNavigator::Close() +{ + SfxChildWindowContext *pCon = GetChildWindow_Impl()->GetContext_Impl(); + DBG_ASSERT( pCon, "Kein Context!" ); + if ( !pCon || pCon->Close() ) + return SfxDockingWindow::Close(); + else + return FALSE; +} + diff --git a/sfx2/source/dialog/newstyle.cxx b/sfx2/source/dialog/newstyle.cxx new file mode 100644 index 000000000000..7193129838b2 --- /dev/null +++ b/sfx2/source/dialog/newstyle.cxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// INCLUDE --------------------------------------------------------------- +#include <svl/style.hxx> +#ifndef GCC +#endif + +#include <sfx2/newstyle.hxx> +#include "dialog.hrc" +#include "newstyle.hrc" +#include "sfxresid.hxx" + +// PRIVATE METHODES ------------------------------------------------------ + +IMPL_LINK( SfxNewStyleDlg, OKHdl, Control *, pControl ) +{ + (void)pControl; //unused + const String aName( aColBox.GetText() ); + SfxStyleSheetBase* pStyle = rPool.Find( aName, rPool.GetSearchFamily(), SFXSTYLEBIT_ALL ); + if ( pStyle ) + { + if ( !pStyle->IsUserDefined() ) + { + InfoBox( this, SfxResId( MSG_POOL_STYLE_NAME ) ).Execute(); + return 0; + } + + if ( RET_YES == aQueryOverwriteBox.Execute() ) + EndDialog( RET_OK ); + } + else + EndDialog( RET_OK ); + + return 0; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxNewStyleDlg, ModifyHdl, ComboBox *, pBox ) +{ + aOKBtn.Enable( pBox->GetText().EraseAllChars().Len() > 0 ); + return 0; +} +IMPL_LINK_INLINE_END( SfxNewStyleDlg, ModifyHdl, ComboBox *, pBox ) + +// CTOR / DTOR ----------------------------------------------------------- + +SfxNewStyleDlg::SfxNewStyleDlg( Window* pParent, SfxStyleSheetBasePool& rInPool ) : + + ModalDialog( pParent, SfxResId( DLG_NEW_STYLE_BY_EXAMPLE ) ), + + aColFL ( this, SfxResId( FL_COL ) ), + aColBox ( this, SfxResId( LB_COL ) ), + aOKBtn ( this, SfxResId( BT_OK ) ), + aCancelBtn ( this, SfxResId( BT_CANCEL ) ), + aQueryOverwriteBox ( this, SfxResId( MSG_OVERWRITE ) ), + + rPool( rInPool ) + +{ + FreeResource(); + + aOKBtn.SetClickHdl(LINK(this, SfxNewStyleDlg, OKHdl)); + aColBox.SetModifyHdl(LINK(this, SfxNewStyleDlg, ModifyHdl)); + aColBox.SetDoubleClickHdl(LINK(this, SfxNewStyleDlg, OKHdl)); + + SfxStyleSheetBase *pStyle = rPool.First(); + while ( pStyle ) + { + aColBox.InsertEntry(pStyle->GetName()); + pStyle = rPool.Next(); + } +} + +// ----------------------------------------------------------------------- + +__EXPORT SfxNewStyleDlg::~SfxNewStyleDlg() +{ +} + diff --git a/sfx2/source/dialog/newstyle.hrc b/sfx2/source/dialog/newstyle.hrc new file mode 100644 index 000000000000..0efc04869ba9 --- /dev/null +++ b/sfx2/source/dialog/newstyle.hrc @@ -0,0 +1,33 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define BT_OK 100 +#define BT_CANCEL 101 +#define LB_COL 1 +#define FL_COL 2 +#define MSG_OVERWRITE 3 + diff --git a/sfx2/source/dialog/newstyle.src b/sfx2/source/dialog/newstyle.src new file mode 100644 index 000000000000..fa5fa62a2ee4 --- /dev/null +++ b/sfx2/source/dialog/newstyle.src @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <sfx2/sfx.hrc> +#include "dialog.hrc" +#include "newstyle.hrc" + +ModalDialog DLG_NEW_STYLE_BY_EXAMPLE +{ + HelpId = SID_STYLE_NEW_BY_EXAMPLE ; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 177 , 112 ) ; + Text [ en-US ] = "Create Style" ; + Moveable = TRUE ; + FixedLine FL_COL + { + Pos = MAP_APPFONT ( 6 , 3 ) ; + Size = MAP_APPFONT ( 109 , 8 ) ; + Text [ en-US ] = "Style name" ; + }; + ComboBox LB_COL + { + Pos = MAP_APPFONT ( 12 , 14 ) ; + Size = MAP_APPFONT ( 94 , 92 ) ; + TabStop = TRUE ; + }; + OKButton BT_OK + { + Disable = TRUE ; + Pos = MAP_APPFONT ( 121 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton BT_CANCEL + { + Pos = MAP_APPFONT ( 121 , 23 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + QueryBox MSG_OVERWRITE + { + Buttons = WB_YES_NO ; + DefButton = WB_DEF_NO ; + Message [ en-US ] = "Style already exists. Overwrite?" ; + }; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/partwnd.cxx b/sfx2/source/dialog/partwnd.cxx new file mode 100644 index 000000000000..cbbe20bfa203 --- /dev/null +++ b/sfx2/source/dialog/partwnd.cxx @@ -0,0 +1,257 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// includes ****************************************************************** +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif + +#include <toolkit/helper/vclunohelper.hxx> + +#include <sfx2/sfxsids.hrc> +#include "partwnd.hxx" +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/sfxuno.hxx> + +//**************************************************************************** +// SfxPartChildWnd_Impl +//**************************************************************************** + +SFX_IMPL_DOCKINGWINDOW( SfxPartChildWnd_Impl, SID_BROWSER ); + +SfxPartChildWnd_Impl::SfxPartChildWnd_Impl +( + Window* pParentWnd, + sal_uInt16 nId, + SfxBindings* pBindings, + SfxChildWinInfo* pInfo +) + : SfxChildWindow( pParentWnd, nId ) +{ + // Window erzeugen + pWindow = new SfxPartDockWnd_Impl( pBindings, this, pParentWnd, WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK ); + eChildAlignment = SFX_ALIGN_TOP; + if ( pInfo ) + pInfo->nFlags |= SFX_CHILDWIN_FORCEDOCK; + + ((SfxDockingWindow*)pWindow)->SetFloatingSize( Size( 175, 175 ) ); + pWindow->SetSizePixel( Size( 175, 175 ) ); + + ( ( SfxDockingWindow* ) pWindow )->Initialize( pInfo ); + SetHideNotDelete( TRUE ); +} + +SfxPartChildWnd_Impl::~SfxPartChildWnd_Impl() +{ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = GetFrame(); + + // If xFrame=NULL release pMgr! Because this window lives longer then the manager! + // In these case we got a xFrame->dispose() call from outside ... and has release our + // frame reference in our own DisposingListener. + // But don't do it, if xFrame already exist. Then dispose() must come from inside ... + // and we need a valid pMgr for further operations ... + + SfxPartDockWnd_Impl* pWin = (SfxPartDockWnd_Impl*) pWindow; +// if( pWin != NULL && !xFrame.is() ) +// pWin->ReleaseChildWindow_Impl(); +/* + // Release frame and window. + // If frame reference is valid here ... start dieing from inside by calling dispose(). + SetFrame( NULL ); + pWindow = NULL; +*/ + if ( pWin && xFrame == pWin->GetBindings().GetActiveFrame() ) + pWin->GetBindings().SetActiveFrame( NULL ); +/* + if( xFrame.is() ) + { + try + { + ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable > xCloseable ( xFrame, ::com::sun::star::uno::UNO_QUERY ); + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xDisposeable( xFrame, ::com::sun::star::uno::UNO_QUERY ); + if (xCloseable.is()) + xCloseable->close(sal_True); + else + if (xDisposeable.is()) + xDisposeable->dispose(); + } + catch( ::com::sun::star::util::CloseVetoException& ) + { + } + catch( ::com::sun::star::lang::DisposedException& ) + { + } + } + */ +} + +sal_Bool SfxPartChildWnd_Impl::QueryClose() +{ + return ( (SfxPartDockWnd_Impl*)pWindow )->QueryClose(); +} + +//**************************************************************************** +// SfxPartDockWnd_Impl +//**************************************************************************** + +SfxPartDockWnd_Impl::SfxPartDockWnd_Impl +( + SfxBindings* pBind, + SfxChildWindow* pChildWin, + Window* pParent, + WinBits nBits +) + : SfxDockingWindow( pBind, pChildWin, pParent, nBits ) +{ + ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame( + ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.frame.Frame") ), ::com::sun::star::uno::UNO_QUERY ); + xFrame->initialize( VCLUnoHelper::GetInterface ( this ) ); + + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPropSet( + xFrame, ::com::sun::star::uno::UNO_QUERY ); + try + { + const ::rtl::OUString aLayoutManager( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )); + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xLMPropSet; + + ::com::sun::star::uno::Any a = xPropSet->getPropertyValue( aLayoutManager ); + if ( a >>= xLMPropSet ) + { + const ::rtl::OUString aAutomaticToolbars( RTL_CONSTASCII_USTRINGPARAM( "AutomaticToolbars" )); + xLMPropSet->setPropertyValue( aAutomaticToolbars, ::com::sun::star::uno::Any( sal_False )); + } + } + catch( ::com::sun::star::uno::RuntimeException& ) + { + throw; + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + pChildWin->SetFrame( xFrame ); + if ( pBind->GetDispatcher() ) + { + ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFramesSupplier > + xSupp ( pBind->GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY ); + if ( xSupp.is() ) + xSupp->getFrames()->append( xFrame ); + } + else { + DBG_ERROR("Bindings without Dispatcher!"); + } +} + +//**************************************************************************** + +SfxPartDockWnd_Impl::~SfxPartDockWnd_Impl() +{ +} + +//**************************************************************************** + +Rectangle impl_Rectangle_Struct2Object( const ::com::sun::star::awt::Rectangle& aRectangleStruct ) +{ + return Rectangle(aRectangleStruct.X,aRectangleStruct.Y,aRectangleStruct.Width,aRectangleStruct.Height); +} + +void SfxPartDockWnd_Impl::Resize() + +/* [Beschreibung] + Anpassung der Gr"osse der Controls an die neue Windowgr"osse +*/ + +{ + SfxDockingWindow::Resize(); +} + +//**************************************************************************** + +sal_Bool SfxPartDockWnd_Impl::QueryClose() +{ + sal_Bool bClose = sal_True; + SfxChildWindow* pChild = GetChildWindow_Impl(); + if( pChild ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = pChild->GetFrame(); + if( xFrame.is() ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > xCtrl = xFrame->getController(); + if( xCtrl.is() ) + bClose = xCtrl->suspend( sal_True ); + } + } + + return bClose; +} + +//**************************************************************************** + +long SfxPartDockWnd_Impl::Notify( NotifyEvent& rEvt ) +{ + if( rEvt.GetType() == EVENT_GETFOCUS ) + { + SfxChildWindow* pChild = GetChildWindow_Impl(); + if( pChild ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = pChild->GetFrame(); + if( xFrame.is() ) + xFrame->activate(); + } + } + + return SfxDockingWindow::Notify( rEvt ); +} + +void SfxPartDockWnd_Impl::FillInfo( SfxChildWinInfo& rInfo ) const +{ + SfxDockingWindow::FillInfo( rInfo ); + rInfo.bVisible = sal_False; +} + + diff --git a/sfx2/source/dialog/passwd.cxx b/sfx2/source/dialog/passwd.cxx new file mode 100644 index 000000000000..e7cc73ca04bf --- /dev/null +++ b/sfx2/source/dialog/passwd.cxx @@ -0,0 +1,212 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// Include --------------------------------------------------------------- +#include <vcl/msgbox.hxx> +#ifndef GCC +#endif + +#include <sfx2/passwd.hxx> +#include "sfxtypes.hxx" +#include "sfxresid.hxx" + +#include "dialog.hrc" +#include "passwd.hrc" + +#include "vcl/sound.hxx" + +// ----------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxPasswordDialog, EditModifyHdl, Edit *, EMPTYARG ) +{ + if( mbAsciiOnly ) + { + rtl::OUString aTest( maPasswordED.GetText() ); + const sal_Unicode* pTest = aTest.getStr(); + sal_Int32 nLen = aTest.getLength(); + rtl::OUStringBuffer aFilter( nLen ); + bool bReset = false; + for( sal_Int32 i = 0; i < nLen; i++ ) + { + if( *pTest > 0x007f ) + bReset = true; + else + aFilter.append( *pTest ); + pTest++; + } + if( bReset ) + { + Sound::Beep( SOUND_ERROR ); + maPasswordED.SetSelection( Selection( 0, nLen ) ); + maPasswordED.ReplaceSelected( aFilter.makeStringAndClear() ); + } + + } + maOKBtn.Enable( maPasswordED.GetText().Len() >= mnMinLen ); + return 0; +} +IMPL_LINK_INLINE_END( SfxPasswordDialog, EditModifyHdl, Edit *, EMPTYARG ) + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxPasswordDialog, OKHdl, OKButton *, EMPTYARG ) +{ + if ( ( ( mnExtras & SHOWEXTRAS_CONFIRM ) == SHOWEXTRAS_CONFIRM ) && + ( GetConfirm() != GetPassword() ) ) + { + ErrorBox aBox( this, SfxResId( MSG_ERROR_WRONG_CONFIRM ) ); + aBox.Execute(); + maConfirmED.SetText( String() ); + maConfirmED.GrabFocus(); + } + else + EndDialog( RET_OK ); + return 0; +} + +// CTOR / DTOR ----------------------------------------------------------- + +SfxPasswordDialog::SfxPasswordDialog( Window* pParent, const String* pGroupText ) : + + ModalDialog( pParent, SfxResId ( DLG_PASSWD ) ), + + maUserFT ( this, SfxResId( FT_PASSWD_USER ) ), + maUserED ( this, SfxResId( ED_PASSWD_USER ) ), + maPasswordFT ( this, SfxResId( FT_PASSWD_PASSWORD ) ), + maPasswordED ( this, SfxResId( ED_PASSWD_PASSWORD ) ), + maConfirmFT ( this, SfxResId( FT_PASSWD_CONFIRM ) ), + maConfirmED ( this, SfxResId( ED_PASSWD_CONFIRM ) ), + maPasswordBox ( this, SfxResId( GB_PASSWD_PASSWORD ) ), + maOKBtn ( this, SfxResId( BTN_PASSWD_OK ) ), + maCancelBtn ( this, SfxResId( BTN_PASSWD_CANCEL ) ), + maHelpBtn ( this, SfxResId( BTN_PASSWD_HELP ) ), + maConfirmStr ( SfxResId( STR_PASSWD_CONFIRM ) ), + + mnMinLen ( 5 ), + mnExtras ( 0 ), + mbAsciiOnly ( false ) + +{ + FreeResource(); + + Link aLink = LINK( this, SfxPasswordDialog, EditModifyHdl ); + maPasswordED.SetModifyHdl( aLink ); + aLink = LINK( this, SfxPasswordDialog, OKHdl ); + maOKBtn.SetClickHdl( aLink ); + + if ( pGroupText ) + maPasswordBox.SetText( *pGroupText ); +} + +// ----------------------------------------------------------------------- + +void SfxPasswordDialog::SetMinLen( USHORT nLen ) +{ + mnMinLen = nLen; + EditModifyHdl( NULL ); +} + +// ----------------------------------------------------------------------- + +void SfxPasswordDialog::SetMaxLen( USHORT nLen ) +{ + maPasswordED.SetMaxTextLen( nLen ); + maConfirmED.SetMaxTextLen( nLen ); + EditModifyHdl( NULL ); +} + +// ----------------------------------------------------------------------- + +short SfxPasswordDialog::Execute() +{ + if ( mnExtras < SHOWEXTRAS_ALL ) + { + Size a3Size = LogicToPixel( Size( 3, 3 ), MAP_APPFONT ); + Size a6Size = LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); + long nMinHeight = maHelpBtn.GetPosPixel().Y() + + maHelpBtn.GetSizePixel().Height() + a6Size.Height(); + USHORT nRowHided = 1; + + if ( SHOWEXTRAS_NONE == mnExtras ) + { + maUserFT.Hide(); + maUserED.Hide(); + maConfirmFT.Hide(); + maConfirmED.Hide(); + maPasswordFT.Hide(); + + Point aPos = maUserFT.GetPosPixel(); + long nEnd = maUserED.GetPosPixel().X() + maUserED.GetSizePixel().Width(); + maPasswordED.SetPosPixel( aPos ); + Size aSize = maPasswordED.GetSizePixel(); + aSize.Width() = nEnd - aPos.X(); + maPasswordED.SetSizePixel( aSize ); + + nRowHided = 2; + } + else if ( SHOWEXTRAS_USER == mnExtras ) + { + maConfirmFT.Hide(); + maConfirmED.Hide(); + } + else if ( SHOWEXTRAS_CONFIRM == mnExtras ) + { + maUserFT.Hide(); + maUserED.Hide(); + + Point aPwdPos1 = maPasswordFT.GetPosPixel(); + Point aPwdPos2 = maPasswordED.GetPosPixel(); + + Point aPos = maUserFT.GetPosPixel(); + maPasswordFT.SetPosPixel( aPos ); + aPos = maUserED.GetPosPixel(); + maPasswordED.SetPosPixel( aPos ); + + maConfirmFT.SetPosPixel( aPwdPos1 ); + maConfirmED.SetPosPixel( aPwdPos2 ); + } + + Size aBoxSize = maPasswordBox.GetSizePixel(); + aBoxSize.Height() -= ( nRowHided * maUserED.GetSizePixel().Height() ); + aBoxSize.Height() -= ( nRowHided * a3Size.Height() ); + maPasswordBox.SetSizePixel( aBoxSize ); + + long nDlgHeight = maPasswordBox.GetPosPixel().Y() + aBoxSize.Height() + a6Size.Height(); + if ( nDlgHeight < nMinHeight ) + nDlgHeight = nMinHeight; + Size aDlgSize = GetOutputSizePixel(); + aDlgSize.Height() = nDlgHeight; + SetOutputSizePixel( aDlgSize ); + } + + return ModalDialog::Execute(); +} + + diff --git a/sfx2/source/dialog/passwd.hrc b/sfx2/source/dialog/passwd.hrc new file mode 100644 index 000000000000..5be0446fd752 --- /dev/null +++ b/sfx2/source/dialog/passwd.hrc @@ -0,0 +1,49 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SFX_PASSWD_HRC +#define _SFX_PASSWD_HRC + +// defines --------------------------------------------------------------- + +#define GB_PASSWD_PASSWORD 10 +#define FT_PASSWD_USER 11 +#define ED_PASSWD_USER 12 +#define FT_PASSWD_PASSWORD 13 +#define ED_PASSWD_PASSWORD 14 +#define FT_PASSWD_CONFIRM 15 +#define ED_PASSWD_CONFIRM 16 + +#define BTN_PASSWD_OK 20 +#define BTN_PASSWD_CANCEL 21 +#define BTN_PASSWD_HELP 22 + +#define STR_PASSWD_CONFIRM 30 + +#endif + +// ******************************************************************* EOF + diff --git a/sfx2/source/dialog/passwd.src b/sfx2/source/dialog/passwd.src new file mode 100644 index 000000000000..fc58ecfda219 --- /dev/null +++ b/sfx2/source/dialog/passwd.src @@ -0,0 +1,140 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + // include --------------------------------------------------------------- +#include "helpid.hrc" +#include "dialog.hrc" +#include "passwd.hrc" + + // DLG_PASSWD ------------------------------------------------------------ +ModalDialog DLG_PASSWD +{ + HelpId = HID_PASSWD ; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT( 200, 68 ); + Text [ en-US ] = "Enter Password" ; + Moveable = TRUE ; + FixedText FT_PASSWD_USER + { + Pos = MAP_APPFONT( 12, 15 ); + Size = MAP_APPFONT( 42, 10 ); + Text [ en-US ] = "~User"; + }; + Edit ED_PASSWD_USER + { + Border = TRUE; + Pos = MAP_APPFONT( 57, 14 ); + Size = MAP_APPFONT( 75, 12 ); + }; + FixedText FT_PASSWD_PASSWORD + { + Pos = MAP_APPFONT( 12, 30 ); + Size = MAP_APPFONT( 42, 10 ); + Text [ en-US ] = "~Password"; + }; + Edit ED_PASSWD_PASSWORD + { + Border = TRUE; + PassWord = TRUE; + Pos = MAP_APPFONT( 57, 29 ); + Size = MAP_APPFONT( 75, 12 ); + }; + FixedText FT_PASSWD_CONFIRM + { + Pos = MAP_APPFONT( 12, 45 ); + Size = MAP_APPFONT( 42, 10 ); + Text [ en-US ] = "~Confirm"; + }; + Edit ED_PASSWD_CONFIRM + { + Border = TRUE; + PassWord = TRUE; + Pos = MAP_APPFONT( 57, 44 ); + Size = MAP_APPFONT( 75, 12 ); + }; + FixedLine GB_PASSWD_PASSWORD + { + Pos = MAP_APPFONT( 6, 3 ); + Size = MAP_APPFONT( 132, 8 ); + Text [ en-US ] = "Password" ; + }; + OKButton BTN_PASSWD_OK + { + Disable = TRUE; + Pos = MAP_APPFONT( 144, 6 ); + Size = MAP_APPFONT( 50, 14 ); + DefButton = TRUE; + }; + CancelButton BTN_PASSWD_CANCEL + { + Pos = MAP_APPFONT( 144, 23 ); + Size = MAP_APPFONT( 50, 14 ); + }; + HelpButton BTN_PASSWD_HELP + { + Pos = MAP_APPFONT( 144, 43 ); + Size = MAP_APPFONT( 50, 14 ); + }; + String STR_PASSWD_CONFIRM + { + Text [ en-US ] = "Confirm password" ; + }; +}; + +// ********************************************************************** EOF + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/printopt.cxx b/sfx2/source/dialog/printopt.cxx new file mode 100644 index 000000000000..80902204fa88 --- /dev/null +++ b/sfx2/source/dialog/printopt.cxx @@ -0,0 +1,545 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#ifndef GCC +#endif +#include <vcl/msgbox.hxx> +#include <unotools/printwarningoptions.hxx> +#include <svtools/printoptions.hxx> +#include <svl/flagitem.hxx> + + +#include "printopt.hrc" +#include "dialog.hrc" +#include "sfxresid.hxx" +#include <sfx2/viewsh.hxx> +#include <sfx2/printopt.hxx> + +// ----------- +// - statics - +// ----------- + +static USHORT aDPIArray[] = { 72, 96, 150, 200, 300, 600 }; +static BOOL bOutputForPrinter = TRUE; + +#define DPI_COUNT (sizeof(aDPIArray)/sizeof(aDPIArray[0 ])) + +// -------------------------------- +// - SfxCommonPrintOptionsTabPage - +// -------------------------------- + +SfxCommonPrintOptionsTabPage::SfxCommonPrintOptionsTabPage( Window* pParent, const SfxItemSet& rSet ) : + SfxTabPage( pParent, SfxResId( TP_COMMONPRINTOPTIONS ), rSet ), + + aReduceGB( this, SfxResId( GB_REDUCE ) ), + aOutputTypeFT( this, SfxResId( FT_OUTPUTTYPE ) ), + aPrinterOutputRB( this, SfxResId( RB_PRINTEROUTPUT ) ), + aPrintFileOutputRB( this, SfxResId( RB_PRINTFILEOUTPUT ) ), + aOutputGB( this, SfxResId( GB_OUTPUT ) ), + aReduceTransparencyCB( this, SfxResId( CB_REDUCETRANSPARENCY ) ), + aReduceTransparencyAutoRB( this, SfxResId( RB_REDUCETRANSPARENCY_AUTO ) ), + aReduceTransparencyNoneRB( this, SfxResId( RB_REDUCETRANSPARENCY_NONE ) ), + aReduceGradientsCB( this, SfxResId( CB_REDUCEGRADIENTS ) ), + aReduceGradientsStripesRB( this, SfxResId( RB_REDUCEGRADIENTS_STRIPES ) ), + aReduceGradientsColorRB( this, SfxResId( RB_REDUCEGRADIENTS_COLOR ) ), + aReduceGradientsStepCountNF( this, SfxResId( NF_REDUCEGRADIENTS_STEPCOUNT ) ), + aReduceBitmapsCB( this, SfxResId( CB_REDUCEBITMAPS ) ), + aReduceBitmapsOptimalRB( this, SfxResId( RB_REDUCEBITMAPS_OPTIMAL ) ), + aReduceBitmapsNormalRB( this, SfxResId( RB_REDUCEBITMAPS_NORMAL ) ), + aReduceBitmapsResolutionRB( this, SfxResId( RB_REDUCEBITMAPS_RESOLUTION ) ), + aReduceBitmapsResolutionLB( this, SfxResId( LB_REDUCEBITMAPS_RESOLUTION ) ), + aReduceBitmapsTransparencyCB( this, SfxResId( CB_REDUCEBITMAPS_TRANSPARENCY ) ), + aConvertToGreyscalesCB( this, SfxResId( CB_CONVERTTOGREYSCALES ) ), + aWarnGB( this, SfxResId( GB_PRINT_WARN ) ), + aPaperSizeCB( this, SfxResId( CB_PAPERSIZE ) ), + aPaperOrientationCB( this, SfxResId( CB_PAPERORIENTATION ) ), + aTransparencyCB( this, SfxResId( CB_TRANSPARENCY ) ) +{ + FreeResource(); + + aOutputGB.SetStyle( aOutputGB.GetStyle() | WB_NOLABEL ); + + if( bOutputForPrinter ) + { + aPrinterOutputRB.Check( TRUE ); + aOutputGB.SetText( OutputDevice::GetNonMnemonicString( aPrinterOutputRB.GetText() ) ); + } + else + { + aPrintFileOutputRB.Check( TRUE ); + aOutputGB.SetText( OutputDevice::GetNonMnemonicString( aPrintFileOutputRB.GetText() ) ); + } + + aPrinterOutputRB.SetToggleHdl( LINK( this, SfxCommonPrintOptionsTabPage, ToggleOutputPrinterRBHdl ) ); + aPrintFileOutputRB.SetToggleHdl( LINK( this, SfxCommonPrintOptionsTabPage, ToggleOutputPrintFileRBHdl ) ); + + aReduceTransparencyCB.SetClickHdl( LINK( this, SfxCommonPrintOptionsTabPage, ClickReduceTransparencyCBHdl ) ); + aReduceGradientsCB.SetClickHdl( LINK( this, SfxCommonPrintOptionsTabPage, ClickReduceGradientsCBHdl ) ); + aReduceBitmapsCB.SetClickHdl( LINK( this, SfxCommonPrintOptionsTabPage, ClickReduceBitmapsCBHdl ) ); + + aReduceGradientsStripesRB.SetToggleHdl( LINK( this, SfxCommonPrintOptionsTabPage, ToggleReduceGradientsStripesRBHdl ) ); + aReduceBitmapsResolutionRB.SetToggleHdl( LINK( this, SfxCommonPrintOptionsTabPage, ToggleReduceBitmapsResolutionRBHdl ) ); + + // --> PB 2008-06-09 #i89164# + // calculate dynamically the width of radiobutton and listbox + const long nOffset = 10; + Size aOldSize = aReduceBitmapsResolutionRB.GetSizePixel(); + Size aNewSize = aReduceBitmapsResolutionRB.GetOptimalSize( WINDOWSIZE_PREFERRED ); + aNewSize.Width() += nOffset; + aNewSize.Height() = aOldSize.Height(); + long nDelta = aOldSize.Width() - aNewSize.Width(); + aReduceBitmapsResolutionRB.SetSizePixel( aNewSize ); + Point aPos = aReduceBitmapsResolutionLB.GetPosPixel(); + aPos.X() -= nDelta; + aOldSize = aReduceBitmapsResolutionLB.GetSizePixel(); + aNewSize = aReduceBitmapsResolutionLB.GetOptimalSize( WINDOWSIZE_PREFERRED ); + aNewSize.Width() += nOffset; + aNewSize.Height() = aOldSize.Height(); + aReduceBitmapsResolutionLB.SetPosSizePixel( aPos, aNewSize ); + // <-- +} + +// ----------------------------------------------------------------------------- + +SfxCommonPrintOptionsTabPage::~SfxCommonPrintOptionsTabPage() +{ +} + +// ----------------------------------------------------------------------------- + +SfxTabPage* SfxCommonPrintOptionsTabPage::Create( Window* pParent, const SfxItemSet& rAttrSet ) +{ + return( new SfxCommonPrintOptionsTabPage( pParent, rAttrSet ) ); +} + +// ----------------------------------------------------------------------------- + +Window* SfxCommonPrintOptionsTabPage::GetParentLabeledBy( const Window* pWindow ) const +{ + if ( pWindow == (Window *)&aReduceGradientsStepCountNF ) + return (Window *)&aReduceGradientsStripesRB; + else if ( pWindow == (Window *)&aReduceBitmapsResolutionLB ) + return (Window *)&aReduceBitmapsResolutionRB; + else + return SfxTabPage::GetParentLabeledBy( pWindow ); +} + +Window* SfxCommonPrintOptionsTabPage::GetParentLabelFor( const Window* pWindow ) const +{ + if ( pWindow == (Window *)&aReduceGradientsStripesRB ) + return (Window *)&aReduceGradientsStepCountNF; + else if ( pWindow == (Window *)&aReduceBitmapsResolutionRB ) + return (Window *)&aReduceBitmapsResolutionLB; + else + return SfxTabPage::GetParentLabelFor( pWindow ); +} + +// ----------------------------------------------------------------------------- + +BOOL SfxCommonPrintOptionsTabPage::FillItemSet( SfxItemSet& /*rSet*/ ) +{ + SvtPrintWarningOptions aWarnOptions; + SvtPrinterOptions aPrinterOptions; + SvtPrintFileOptions aPrintFileOptions; + BOOL bModified = FALSE; + + + if( aPaperSizeCB.IsChecked() != aPaperSizeCB.GetSavedValue()) + aWarnOptions.SetPaperSize(aPaperSizeCB.IsChecked()); + if( aPaperOrientationCB.IsChecked() != aPaperOrientationCB.GetSavedValue() ) + aWarnOptions.SetPaperOrientation(aPaperOrientationCB.IsChecked()); + + if( aTransparencyCB.IsChecked() != aTransparencyCB.GetSavedValue() ) + aWarnOptions.SetTransparency( aTransparencyCB.IsChecked() ); + + ImplSaveControls( aPrinterOutputRB.IsChecked() ? &maPrinterOptions : &maPrintFileOptions ); + + aPrinterOptions.SetPrinterOptions( maPrinterOptions ); + aPrintFileOptions.SetPrinterOptions( maPrintFileOptions ); + + return bModified; +} + +// ----------------------------------------------------------------------------- + +void SfxCommonPrintOptionsTabPage::Reset( const SfxItemSet& /*rSet*/ ) +{ + SvtPrintWarningOptions aWarnOptions; + SvtPrinterOptions aPrinterOptions; + SvtPrintFileOptions aPrintFileOptions; + + aPaperSizeCB.Check( aWarnOptions.IsPaperSize() ); + aPaperOrientationCB.Check( aWarnOptions.IsPaperOrientation() ); + + aTransparencyCB.Check( aWarnOptions.IsTransparency() ); + + aPaperSizeCB.SaveValue(); + aPaperOrientationCB.SaveValue(); + aTransparencyCB.SaveValue(); + + aPrinterOptions.GetPrinterOptions( maPrinterOptions ); + aPrintFileOptions.GetPrinterOptions( maPrintFileOptions ); + + ImplUpdateControls( aPrinterOutputRB.IsChecked() ? &maPrinterOptions : &maPrintFileOptions ); + + // --> OD 2008-06-25 #i63982# + ImplSetAccessibleNames(); + // <-- +} + +// ----------------------------------------------------------------------------- + +int SfxCommonPrintOptionsTabPage::DeactivatePage( SfxItemSet* pItemSet ) +{ + if( pItemSet ) + FillItemSet( *pItemSet ); + + return LEAVE_PAGE; +} + +// ----------------------------------------------------------------------------- + +void SfxCommonPrintOptionsTabPage::ImplUpdateControls( const PrinterOptions* pCurrentOptions ) +{ + aReduceTransparencyCB.Check( pCurrentOptions->IsReduceTransparency() ); + + if( pCurrentOptions->GetReducedTransparencyMode() == PRINTER_TRANSPARENCY_AUTO ) + aReduceTransparencyAutoRB.Check( TRUE ); + else + aReduceTransparencyNoneRB.Check( TRUE ); + + aReduceGradientsCB.Check( pCurrentOptions->IsReduceGradients() ); + + if( pCurrentOptions->GetReducedGradientMode() == PRINTER_GRADIENT_STRIPES ) + aReduceGradientsStripesRB.Check( TRUE ); + else + aReduceGradientsColorRB.Check( TRUE ); + + aReduceGradientsStepCountNF.SetValue( pCurrentOptions->GetReducedGradientStepCount() ); + + aReduceBitmapsCB.Check( pCurrentOptions->IsReduceBitmaps() ); + + if( pCurrentOptions->GetReducedBitmapMode() == PRINTER_BITMAP_OPTIMAL ) + aReduceBitmapsOptimalRB.Check( TRUE ); + else if( pCurrentOptions->GetReducedBitmapMode() == PRINTER_BITMAP_NORMAL ) + aReduceBitmapsNormalRB.Check( TRUE ); + else + aReduceBitmapsResolutionRB.Check( TRUE ); + + const USHORT nDPI = pCurrentOptions->GetReducedBitmapResolution(); + + if( nDPI < aDPIArray[ 0 ] ) + aReduceBitmapsResolutionLB.SelectEntryPos( 0 ); + else + { + for( long i = ( DPI_COUNT - 1 ); i >= 0; i-- ) + { + if( nDPI >= aDPIArray[ i ] ) + { + aReduceBitmapsResolutionLB.SelectEntryPos( (USHORT) i ); + i = -1; + } + } + } + + aReduceBitmapsResolutionLB.SetText( aReduceBitmapsResolutionLB.GetEntry( aReduceBitmapsResolutionLB.GetSelectEntryPos() ) ); + + aReduceBitmapsTransparencyCB.Check( pCurrentOptions->IsReducedBitmapIncludesTransparency() ); + aConvertToGreyscalesCB.Check( pCurrentOptions->IsConvertToGreyscales() ); + + ClickReduceTransparencyCBHdl( &aReduceTransparencyCB ); + ClickReduceGradientsCBHdl( &aReduceGradientsCB ); + ClickReduceBitmapsCBHdl( &aReduceBitmapsCB ); +} + +// ----------------------------------------------------------------------------- + +void SfxCommonPrintOptionsTabPage::ImplSetAccessibleNames() +{ + static const String cSeparator = String::CreateFromAscii( " - " ); + + String sReduceText = aReduceGB.GetDisplayText(); + sReduceText += cSeparator; + + String sAccessibleName = sReduceText; + sAccessibleName += aPrinterOutputRB.GetDisplayText(); + aPrinterOutputRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sReduceText; + sAccessibleName += aPrintFileOutputRB.GetDisplayText(); + aPrintFileOutputRB.SetAccessibleName( sAccessibleName ); + + String sOutputText = sReduceText; + sOutputText += aOutputGB.GetDisplayText(); + sOutputText += cSeparator; + + sAccessibleName = sOutputText; + sAccessibleName += aReduceTransparencyCB.GetDisplayText(); + aReduceTransparencyCB.SetAccessibleName( sAccessibleName ); + + String sTransparencyText = aReduceTransparencyCB.GetAccessibleName(); + sTransparencyText += cSeparator; + + sAccessibleName = sTransparencyText; + sAccessibleName += aReduceTransparencyAutoRB.GetDisplayText(); + aReduceTransparencyAutoRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sTransparencyText; + sAccessibleName += aReduceTransparencyNoneRB.GetDisplayText(); + aReduceTransparencyNoneRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sOutputText; + sAccessibleName += aReduceGradientsCB.GetDisplayText(); + aReduceGradientsCB.SetAccessibleName( sAccessibleName ); + + String sGradientText = aReduceGradientsCB.GetAccessibleName(); + sGradientText += cSeparator; + + sAccessibleName = sGradientText; + sAccessibleName += aReduceGradientsStripesRB.GetDisplayText(); + aReduceGradientsStripesRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = aReduceGradientsStripesRB.GetAccessibleName(); + aReduceGradientsStepCountNF.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sGradientText; + sAccessibleName += aReduceGradientsColorRB.GetDisplayText(); + aReduceGradientsColorRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sOutputText; + sAccessibleName += aReduceBitmapsCB.GetDisplayText(); + aReduceBitmapsCB.SetAccessibleName( sAccessibleName ); + + String sBitmapText = aReduceBitmapsCB.GetAccessibleName(); + sBitmapText += cSeparator; + + sAccessibleName = sBitmapText; + sAccessibleName += aReduceBitmapsOptimalRB.GetDisplayText(); + aReduceBitmapsOptimalRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sBitmapText; + sAccessibleName += aReduceBitmapsNormalRB.GetDisplayText(); + aReduceBitmapsNormalRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sBitmapText; + sAccessibleName += aReduceBitmapsResolutionRB.GetDisplayText(); + aReduceBitmapsResolutionRB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = aReduceBitmapsResolutionRB.GetAccessibleName(); + aReduceBitmapsResolutionLB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sBitmapText; + sAccessibleName += aReduceBitmapsTransparencyCB.GetDisplayText(); + aReduceBitmapsTransparencyCB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sOutputText; + sAccessibleName += aConvertToGreyscalesCB.GetDisplayText(); + aConvertToGreyscalesCB.SetAccessibleName( sAccessibleName ); + + String sWarnText = aWarnGB.GetDisplayText(); + sWarnText += cSeparator; + + sAccessibleName = sWarnText; + sAccessibleName += aPaperSizeCB.GetDisplayText(); + aPaperSizeCB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sWarnText; + sAccessibleName += aPaperOrientationCB.GetDisplayText(); + aPaperOrientationCB.SetAccessibleName( sAccessibleName ); + + sAccessibleName = sWarnText; + sAccessibleName += aTransparencyCB.GetDisplayText(); + aTransparencyCB.SetAccessibleName( sAccessibleName ); +} + +// ----------------------------------------------------------------------------- + +void SfxCommonPrintOptionsTabPage::ImplSaveControls( PrinterOptions* pCurrentOptions ) +{ + pCurrentOptions->SetReduceTransparency( aReduceTransparencyCB.IsChecked() ); + pCurrentOptions->SetReducedTransparencyMode( aReduceTransparencyAutoRB.IsChecked() ? PRINTER_TRANSPARENCY_AUTO : PRINTER_TRANSPARENCY_NONE ); + pCurrentOptions->SetReduceGradients( aReduceGradientsCB.IsChecked() ); + pCurrentOptions->SetReducedGradientMode( aReduceGradientsStripesRB.IsChecked() ? PRINTER_GRADIENT_STRIPES : PRINTER_GRADIENT_COLOR ); + pCurrentOptions->SetReducedGradientStepCount( (USHORT) aReduceGradientsStepCountNF.GetValue() ); + pCurrentOptions->SetReduceBitmaps( aReduceBitmapsCB.IsChecked() ); + pCurrentOptions->SetReducedBitmapMode( aReduceBitmapsOptimalRB.IsChecked() ? PRINTER_BITMAP_OPTIMAL : + ( aReduceBitmapsNormalRB.IsChecked() ? PRINTER_BITMAP_NORMAL : PRINTER_BITMAP_RESOLUTION ) ); + pCurrentOptions->SetReducedBitmapResolution( aDPIArray[ Min( (USHORT) aReduceBitmapsResolutionLB.GetSelectEntryPos(), + (USHORT)( sizeof( aDPIArray ) / sizeof( aDPIArray[ 0 ] ) - 1 ) ) ] ); + pCurrentOptions->SetReducedBitmapIncludesTransparency( aReduceBitmapsTransparencyCB.IsChecked() ); + pCurrentOptions->SetConvertToGreyscales( aConvertToGreyscalesCB.IsChecked() ); +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonPrintOptionsTabPage, ClickReduceTransparencyCBHdl, CheckBox*, pBox ) +{ + (void)pBox; //unused + const BOOL bReduceTransparency = aReduceTransparencyCB.IsChecked(); + + aReduceTransparencyAutoRB.Enable( bReduceTransparency ); + aReduceTransparencyNoneRB.Enable( bReduceTransparency ); + + aTransparencyCB.Enable( !bReduceTransparency ); + + return 0; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonPrintOptionsTabPage, ClickReduceGradientsCBHdl, CheckBox*, pBox ) +{ + (void)pBox; //unused + const BOOL bEnable = aReduceGradientsCB.IsChecked(); + + aReduceGradientsStripesRB.Enable( bEnable ); + aReduceGradientsColorRB.Enable( bEnable ); + aReduceGradientsStepCountNF.Enable( bEnable ); + + ToggleReduceGradientsStripesRBHdl( &aReduceGradientsStripesRB ); + + return 0; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonPrintOptionsTabPage, ClickReduceBitmapsCBHdl, CheckBox*, pBox ) +{ + (void)pBox; //unused + const BOOL bEnable = aReduceBitmapsCB.IsChecked(); + + aReduceBitmapsOptimalRB.Enable( bEnable ); + aReduceBitmapsNormalRB.Enable( bEnable ); + aReduceBitmapsResolutionRB.Enable( bEnable ); + aReduceBitmapsTransparencyCB.Enable( bEnable ); + aReduceBitmapsResolutionLB.Enable( bEnable ); + + ToggleReduceBitmapsResolutionRBHdl( &aReduceBitmapsResolutionRB ); + + return 0; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonPrintOptionsTabPage, ToggleReduceGradientsStripesRBHdl, RadioButton*, pButton ) +{ + (void)pButton; //unused + const BOOL bEnable = aReduceGradientsCB.IsChecked() && aReduceGradientsStripesRB.IsChecked(); + + aReduceGradientsStepCountNF.Enable( bEnable ); + + return 0; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonPrintOptionsTabPage, ToggleReduceBitmapsResolutionRBHdl, RadioButton*, pButton ) +{ + (void)pButton; //unused + const BOOL bEnable = aReduceBitmapsCB.IsChecked() && aReduceBitmapsResolutionRB.IsChecked(); + + aReduceBitmapsResolutionLB.Enable( bEnable ); + + return 0; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonPrintOptionsTabPage, ToggleOutputPrinterRBHdl, RadioButton*, pButton ) +{ + if( pButton->IsChecked() ) + { + aOutputGB.SetText( OutputDevice::GetNonMnemonicString( pButton->GetText() ) ); + ImplUpdateControls( &maPrinterOptions ); + bOutputForPrinter = TRUE; + // --> OD 2008-06-25 #i63982# + ImplSetAccessibleNames(); + // <-- + } + else + ImplSaveControls( &maPrinterOptions ); + + return 0; +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonPrintOptionsTabPage, ToggleOutputPrintFileRBHdl, RadioButton*, pButton ) +{ + if( pButton->IsChecked() ) + { + aOutputGB.SetText( OutputDevice::GetNonMnemonicString( pButton->GetText() ) ); + ImplUpdateControls( &maPrintFileOptions ); + bOutputForPrinter = FALSE; + // --> OD 2008-06-25 #i63982# + ImplSetAccessibleNames(); + // <-- + } + else + ImplSaveControls( &maPrintFileOptions ); + + return 0; +} + +// ------------------------------- +// - TransparencyPrintWarningBox - +// ------------------------------- + +TransparencyPrintWarningBox::TransparencyPrintWarningBox( Window* pParent ) : + ModalDialog( pParent, SfxResId( RID_WARN_PRINTTRANSPARENCY ) ), + aWarnFI ( this, SfxResId( FI_PRINTTRANSWARN ) ), + aWarnFT ( this, SfxResId( FT_PRINTTRANSWARN ) ), + aYesBtn ( this, SfxResId( BTN_PRINTTRANS_YES ) ), + aNoBtn ( this, SfxResId( BTN_PRINTTRANS_NO ) ), + aCancelBtn ( this, SfxResId( BTN_PRINTTRANS_CANCEL ) ), + aNoWarnCB ( this, SfxResId( CBX_NOPRINTTRANSWARN ) ) +{ + FreeResource(); + + aWarnFT.SetStyle( aWarnFT.GetStyle() | WB_INFO ); + aWarnFI.SetImage( WarningBox::GetStandardImage() ); + + aNoBtn.SetClickHdl( LINK( this, TransparencyPrintWarningBox, ClickNoBtn ) ); +} + +// ----------------------------------------------------------------------------- + +TransparencyPrintWarningBox::~TransparencyPrintWarningBox() +{ +} + +// ----------------------------------------------------------------------------- + +IMPL_LINK( TransparencyPrintWarningBox, ClickNoBtn, PushButton*, pButton ) +{ + (void)pButton; //unused + EndDialog( RET_NO ); + return 0; +} diff --git a/sfx2/source/dialog/printopt.hrc b/sfx2/source/dialog/printopt.hrc new file mode 100644 index 000000000000..38c766c9f56a --- /dev/null +++ b/sfx2/source/dialog/printopt.hrc @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define GB_REDUCE 1 + +#define FT_OUTPUTTYPE 2 +#define RB_PRINTEROUTPUT 3 +#define RB_PRINTFILEOUTPUT 4 + +#define GB_OUTPUT 5 + +#define CB_REDUCETRANSPARENCY 10 +#define RB_REDUCETRANSPARENCY_AUTO 11 +#define RB_REDUCETRANSPARENCY_NONE 12 + +#define CB_REDUCEGRADIENTS 20 +#define RB_REDUCEGRADIENTS_STRIPES 21 +#define RB_REDUCEGRADIENTS_COLOR 22 +#define NF_REDUCEGRADIENTS_STEPCOUNT 23 + +#define CB_REDUCEBITMAPS 30 +#define RB_REDUCEBITMAPS_OPTIMAL 31 +#define RB_REDUCEBITMAPS_NORMAL 32 +#define RB_REDUCEBITMAPS_RESOLUTION 33 +#define CB_REDUCEBITMAPS_TRANSPARENCY 34 +#define LB_REDUCEBITMAPS_RESOLUTION 35 + +#define CB_CONVERTTOGREYSCALES 40 + +#define GB_PRINT_WARN 50 +#define CB_PAPERSIZE 51 +#define CB_PAPERORIENTATION 52 +#define CB_TRANSPARENCY 53 + +#define FI_PRINTTRANSWARN 60 +#define FT_PRINTTRANSWARN 61 +#define BTN_PRINTTRANS_YES 62 +#define BTN_PRINTTRANS_NO 63 +#define BTN_PRINTTRANS_CANCEL 64 +#define CBX_NOPRINTTRANSWARN 65 diff --git a/sfx2/source/dialog/printopt.src b/sfx2/source/dialog/printopt.src new file mode 100644 index 000000000000..4217539a3af8 --- /dev/null +++ b/sfx2/source/dialog/printopt.src @@ -0,0 +1,355 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// include --------------------------------------------------------------- + +#include <sfx2/sfx.hrc> +#include "printopt.hrc" +#include "dialog.hrc" +#include "helpid.hrc" + +//**************************************************************************** +// +// TabPage +// +//**************************************************************************** + +TabPage TP_COMMONPRINTOPTIONS +{ + HelpID = HID_TP_COMMONPRINTOPTIONS; + SVLook = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + Hide = TRUE ; + + FixedLine GB_REDUCE + { + Pos = MAP_APPFONT ( 6, 3 ) ; + Size = MAP_APPFONT ( 248 , 8 ) ; + Text [ en-US ] = "Reduce print data"; + }; + FixedText FT_OUTPUTTYPE + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 12, 14 ) ; + Size = MAP_APPFONT ( 60, 10 ) ; + Text [ en-US ] = "Settings for"; + }; + RadioButton RB_PRINTEROUTPUT + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 81, 14 ) ; + Size = MAP_APPFONT ( 60, 10 ) ; + Text [ en-US ] = "~Printer"; + }; + RadioButton RB_PRINTFILEOUTPUT + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 142, 14 ) ; + Size = MAP_APPFONT ( 100, 10 ) ; + Text [ en-US ] = "Print to ~file"; + }; + + // ----------- + + FixedLine GB_OUTPUT + { + Pos = MAP_APPFONT ( 12, 27 ) ; + Size = MAP_APPFONT ( 242 , 8 ) ; + }; + + CheckBox CB_REDUCETRANSPARENCY + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 18, 38 ) ; + Size = MAP_APPFONT ( 115, 10 ) ; + Text [ en-US ] = "~Reduce transparency"; + }; + RadioButton RB_REDUCETRANSPARENCY_AUTO + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 28, 51 ) ; + Size = MAP_APPFONT ( 105, 10 ) ; + Text [ en-US ] = "Auto~matically"; + }; + RadioButton RB_REDUCETRANSPARENCY_NONE + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 28, 64 ) ; + Size = MAP_APPFONT ( 105, 10 ) ; + Text [ en-US ] = "~No transparency"; + }; + + // ----------- + + CheckBox CB_REDUCEGRADIENTS + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 136, 38 ) ; + Size = MAP_APPFONT ( 121, 10 ) ; + Text [ en-US ] = "Reduce ~gradients"; + }; + RadioButton RB_REDUCEGRADIENTS_STRIPES + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 146, 51 ) ; + Size = MAP_APPFONT ( 77, 10 ) ; + Text [ en-US ] = "Gradient ~stripes"; + }; + NumericField NF_REDUCEGRADIENTS_STEPCOUNT + { + TabStop = TRUE; + Border = TRUE ; + Pos = MAP_APPFONT ( 224, 49 ) ; + Size = MAP_APPFONT ( 24, 12 ) ; + Minimum = 2; + Maximum = 256; + Spin = TRUE ; + Repeat = TRUE ; + }; + RadioButton RB_REDUCEGRADIENTS_COLOR + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 146, 64 ) ; + Size = MAP_APPFONT ( 108, 10 ) ; + Text [ en-US ] = "Intermediate ~color"; + }; + + // ----------- + + CheckBox CB_REDUCEBITMAPS + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 18, 80 ) ; + Size = MAP_APPFONT ( 115, 10 ) ; + Text [ en-US ] = "Reduce ~bitmaps"; + }; + RadioButton RB_REDUCEBITMAPS_OPTIMAL + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 28, 93 ) ; + Size = MAP_APPFONT ( 226, 10 ) ; + Text [ en-US ] = "~High print quality"; + }; + RadioButton RB_REDUCEBITMAPS_NORMAL + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 28, 106 ) ; + Size = MAP_APPFONT ( 226, 10 ) ; + Text [ en-US ] = "N~ormal print quality"; + }; + RadioButton RB_REDUCEBITMAPS_RESOLUTION + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 28, 119 ) ; + Size = MAP_APPFONT ( 52, 10 ) ; + Text [ en-US ] = "Reso~lution"; + }; + ListBox LB_REDUCEBITMAPS_RESOLUTION + { + TabStop = TRUE; + Border = TRUE ; + Pos = MAP_APPFONT ( 81, 117 ) ; + Size = MAP_APPFONT ( 60, 100 ) ; + DropDown = TRUE; + + StringList [ en-US ] = + { + < "72 DPI"; 0; > ; + < "96 DPI"; 0; > ; + < "150 DPI (Fax)"; 0; > ; + < "200 DPI (default)"; 0; > ; + < "300 DPI"; 0; > ; + < "600 DPI"; 0; > ; + }; + }; + CheckBox CB_REDUCEBITMAPS_TRANSPARENCY + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 28, 132 ) ; + Size = MAP_APPFONT ( 226, 10 ) ; + Text [ en-US ] = "Include transparent ob~jects"; + }; + + // ----------- + + CheckBox CB_CONVERTTOGREYSCALES + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 136, 80 ) ; + Size = MAP_APPFONT ( 123, 10 ) ; + Text [ en-US ] = "Con~vert colors to grayscale"; + }; + + // ----------- + + FixedLine GB_PRINT_WARN + { + Pos = MAP_APPFONT ( 6, 148 ) ; + Size = MAP_APPFONT ( 248 , 8 ) ; + Text [ en-US ] = "Printer warnings" ; + }; + CheckBox CB_PAPERSIZE + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 12, 159 ) ; + Size = MAP_APPFONT ( 123, 10 ) ; + Text [ en-US ] = "P~aper size" ; + }; + CheckBox CB_PAPERORIENTATION + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 12, 172 ) ; + Size = MAP_APPFONT ( 123 , 10 ) ; + Text [ en-US ] = "Pap~er orientation" ; + }; + CheckBox CB_TRANSPARENCY + { + TabStop = TRUE; + Pos = MAP_APPFONT ( 136, 159 ) ; + Size = MAP_APPFONT ( 123, 10 ) ; + Text [ en-US ] = "~Transparency"; + }; +}; + +// -------------- +// - WarningBox - +// -------------- + +ModalDialog RID_WARN_PRINTTRANSPARENCY +{ + OutputSize = TRUE ; + Size = MAP_APPFONT ( 195 , 85 ) ; + Text [ en-US ] = "Warning" ; + Moveable = TRUE ; + FixedImage FI_PRINTTRANSWARN + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 20 , 20 ) ; + }; + FixedText FT_PRINTTRANSWARN + { + Pos = MAP_APPFONT ( 29 , 6 ) ; + Size = MAP_APPFONT ( 163 , 36 ) ; + WordBreak = TRUE ; + Text [ en-US ] = "Your document contains transparent objects.\nThis may lead to longer printing time on certain\nprinters. Should the aspect of transparency\nbe reduced?"; + }; + OKButton BTN_PRINTTRANS_YES + { + Pos = MAP_APPFONT ( 12 , 48 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + DefButton = TRUE; + Text [ en-US ] = "~Yes" ; + }; + PushButton BTN_PRINTTRANS_NO + { + Pos = MAP_APPFONT ( 68 , 48 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~No" ; + }; + CancelButton BTN_PRINTTRANS_CANCEL + { + Pos = MAP_APPFONT ( 124 , 48 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Cancel" ; + }; + CheckBox CBX_NOPRINTTRANSWARN + { + Pos = MAP_APPFONT ( 6 , 68 ) ; + Size = MAP_APPFONT ( 183 , 10 ) ; + Text [ en-US ] = "~Do not show warning again" ; + }; +}; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/recfloat.cxx b/sfx2/source/dialog/recfloat.cxx new file mode 100644 index 000000000000..c678cfdffb6e --- /dev/null +++ b/sfx2/source/dialog/recfloat.cxx @@ -0,0 +1,280 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// includes ******************************************************************* +#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include <svl/eitem.hxx> +#include <svtools/generictoolboxcontroller.hxx> +#include <vcl/msgbox.hxx> +#include <comphelper/processfactory.hxx> + +#include "recfloat.hxx" +#include "dialog.hrc" +#include "sfxresid.hxx" +#include <sfx2/app.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/viewsh.hxx> +#include "imagemgr.hxx" + +using namespace ::com::sun::star; + +static rtl::OUString GetLabelFromCommandURL( const rtl::OUString& rCommandURL, const uno::Reference< frame::XFrame >& xFrame ) +{ + rtl::OUString aLabel; + rtl::OUString aModuleIdentifier; + uno::Reference< container::XNameAccess > xUICommandLabels; + uno::Reference< lang::XMultiServiceFactory > xServiceManager; + uno::Reference< container::XNameAccess > xUICommandDescription; + uno::Reference< ::com::sun::star::frame::XModuleManager > xModuleManager; + + static uno::WeakReference< lang::XMultiServiceFactory > xTmpServiceManager; + static uno::WeakReference< container::XNameAccess > xTmpNameAccess; + static uno::WeakReference< ::com::sun::star::frame::XModuleManager > xTmpModuleMgr; + + xServiceManager = xTmpServiceManager; + if ( !xServiceManager.is() ) + { + xServiceManager = ::comphelper::getProcessServiceFactory(); + xTmpServiceManager = xServiceManager; + } + + xUICommandDescription = xTmpNameAccess; + if ( !xUICommandDescription.is() ) + { + xUICommandDescription = uno::Reference< container::XNameAccess >( + xServiceManager->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.UICommandDescription" ))), + uno::UNO_QUERY ); + xTmpNameAccess = xUICommandDescription; + } + + xModuleManager = xTmpModuleMgr; + if ( !xModuleManager.is() ) + { + xModuleManager = uno::Reference< ::com::sun::star::frame::XModuleManager >( + xServiceManager->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.ModuleManager" ))), + uno::UNO_QUERY_THROW ); + xTmpModuleMgr = xModuleManager; + } + + // Retrieve label from UI command description service + try + { + try + { + aModuleIdentifier = xModuleManager->identify( xFrame ); + } + catch( uno::Exception& ) + { + } + + if ( xUICommandDescription.is() ) + { + uno::Any a = xUICommandDescription->getByName( aModuleIdentifier ); + uno::Reference< container::XNameAccess > xUICommands; + a >>= xUICommandLabels; + } + } + catch ( uno::Exception& ) + { + } + + if ( xUICommandLabels.is() ) + { + try + { + if ( rCommandURL.getLength() > 0 ) + { + uno::Sequence< beans::PropertyValue > aPropSeq; + uno::Any a( xUICommandLabels->getByName( rCommandURL )); + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( "Label" )) + { + aPropSeq[i].Value >>= aLabel; + break; + } + } + } + } + } + catch (uno::Exception& ) + { + } + } + + return aLabel; +} + +SFX_IMPL_FLOATINGWINDOW( SfxRecordingFloatWrapper_Impl, SID_RECORDING_FLOATWINDOW ); + +SfxRecordingFloatWrapper_Impl::SfxRecordingFloatWrapper_Impl( Window* pParentWnd , + USHORT nId , + SfxBindings* pBind , + SfxChildWinInfo* pInfo ) + : SfxChildWindow( pParentWnd, nId ) + , pBindings( pBind ) +{ + pWindow = new SfxRecordingFloat_Impl( pBindings, this, pParentWnd ); + SetWantsFocus( FALSE ); + eChildAlignment = SFX_ALIGN_NOALIGNMENT; + ( ( SfxFloatingWindow* ) pWindow )->Initialize( pInfo ); +} + +SfxRecordingFloatWrapper_Impl::~SfxRecordingFloatWrapper_Impl() +{ + SfxBoolItem aItem( FN_PARAM_1, TRUE ); + com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder = pBindings->GetRecorder(); + if ( xRecorder.is() ) + pBindings->GetDispatcher()->Execute( SID_STOP_RECORDING, SFX_CALLMODE_SYNCHRON, &aItem, 0L ); +} + +sal_Bool SfxRecordingFloatWrapper_Impl::QueryClose() +{ + // asking for recorded macro should be replaced if index access is available! + BOOL bRet = TRUE; + com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder = pBindings->GetRecorder(); + if ( xRecorder.is() && xRecorder->getRecordedMacro().getLength() ) + { + QueryBox aBox( GetWindow(), WB_YES_NO | WB_DEF_NO , String( SfxResId( STR_MACRO_LOSS ) ) ); + aBox.SetText( String( SfxResId(STR_CANCEL_RECORDING) ) ); + bRet = ( aBox.Execute() == RET_YES ); + } + + return bRet; +} + +SfxRecordingFloat_Impl::SfxRecordingFloat_Impl( + SfxBindings* pBind , + SfxChildWindow* pChildWin , + Window* pParent ) + : SfxFloatingWindow( pBind, + pChildWin, + pParent, + SfxResId( SID_RECORDING_FLOATWINDOW ) ) + , pWrapper( pChildWin ) + , aTbx( this, SfxResId(SID_RECORDING_FLOATWINDOW) ) +{ + // Retrieve label from helper function + uno::Reference< frame::XFrame > xFrame = GetBindings().GetActiveFrame(); + rtl::OUString aCommandStr( RTL_CONSTASCII_USTRINGPARAM( ".uno:StopRecording" )); + aTbx.SetItemText( SID_STOP_RECORDING, GetLabelFromCommandURL( aCommandStr, xFrame )); + + // Determine size of toolbar + Size aTbxSize = aTbx.CalcWindowSizePixel(); + aTbx.SetPosSizePixel( Point(), aTbxSize ); + SetOutputSizePixel( aTbxSize ); + + // create a generic toolbox controller for our internal toolbox + svt::GenericToolboxController* pController = new svt::GenericToolboxController( + ::comphelper::getProcessServiceFactory(), + xFrame, + &aTbx, + SID_STOP_RECORDING, + aCommandStr ); + xStopRecTbxCtrl = uno::Reference< frame::XToolbarController >( + static_cast< cppu::OWeakObject* >( pController ), + uno::UNO_QUERY ); + uno::Reference< util::XUpdatable > xUpdate( xStopRecTbxCtrl, uno::UNO_QUERY ); + if ( xUpdate.is() ) + xUpdate->update(); + + aTbx.SetSelectHdl( LINK( this, SfxRecordingFloat_Impl, Select ) ); + + // start recording + SfxBoolItem aItem( SID_RECORDMACRO, TRUE ); + GetBindings().GetDispatcher()->Execute( SID_RECORDMACRO, SFX_CALLMODE_SYNCHRON, &aItem, 0L ); +} + +SfxRecordingFloat_Impl::~SfxRecordingFloat_Impl() +{ + try + { + if ( xStopRecTbxCtrl.is() ) + { + uno::Reference< lang::XComponent > xComp( xStopRecTbxCtrl, uno::UNO_QUERY ); + xComp->dispose(); + } + } + catch ( uno::Exception& ) + { + } +} + +BOOL SfxRecordingFloat_Impl::Close() +{ + BOOL bRet = SfxFloatingWindow::Close(); + return bRet; +} + +void SfxRecordingFloat_Impl::FillInfo( SfxChildWinInfo& rInfo ) const +{ + SfxFloatingWindow::FillInfo( rInfo ); + rInfo.bVisible = sal_False; +} + +void SfxRecordingFloat_Impl::StateChanged( StateChangedType nStateChange ) +{ + if ( nStateChange == STATE_CHANGE_INITSHOW ) + { + SfxViewFrame *pFrame = GetBindings().GetDispatcher_Impl()->GetFrame(); + Window* pEditWin = pFrame->GetViewShell()->GetWindow(); + + Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() ); + aPoint = GetParent()->ScreenToOutputPixel( aPoint ); + aPoint.X() += 20; + aPoint.Y() += 10; + SetPosPixel( aPoint ); + } + + SfxFloatingWindow::StateChanged( nStateChange ); +} + +IMPL_LINK( SfxRecordingFloat_Impl, Select, ToolBox*, pToolBar ) +{ + (void)pToolBar; + sal_Int16 nKeyModifier( (sal_Int16)aTbx.GetModifier() ); + if ( xStopRecTbxCtrl.is() ) + xStopRecTbxCtrl->execute( nKeyModifier ); + + return 1; +} diff --git a/sfx2/source/dialog/recfloat.src b/sfx2/source/dialog/recfloat.src new file mode 100644 index 000000000000..5bdde1f57ab6 --- /dev/null +++ b/sfx2/source/dialog/recfloat.src @@ -0,0 +1,86 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + // include --------------------------------------------------------------- +#include "helpid.hrc" +#include "dialog.hrc" + + // ----------------------------------------------------------------------- +#define STD_MASKCOLOR Color { Red = 0xC000; Green = 0xC000; Blue = 0xC000; } +#define STD_HC_MASKCOLOR Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; } + +FloatingWindow SID_RECORDING_FLOATWINDOW +{ + Moveable = TRUE ; + Closeable = TRUE ; + Hide = TRUE ; + SVLook = TRUE ; + Text [ en-US ] = "Record Macro"; +}; + +ToolBox SID_RECORDING_FLOATWINDOW +{ + SVLook = TRUE ; + ButtonType = BUTTON_TEXT; + ItemList = + { + ToolBoxItem + { + Identifier = SID_STOP_RECORDING; + Command = ".uno:StopRecording"; + }; + }; +}; + +String STR_MACRO_LOSS +{ + Text [ en-US ] = "Do you really want to cancel the recording? Any steps recorded up to this point will be lost."; +}; + +String STR_CANCEL_RECORDING +{ + Text [ en-US ] = "Cancel Recording"; +}; + + + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/securitypage.cxx b/sfx2/source/dialog/securitypage.cxx new file mode 100644 index 000000000000..2ac8f6a43fee --- /dev/null +++ b/sfx2/source/dialog/securitypage.cxx @@ -0,0 +1,553 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include "sfx2/securitypage.hxx" + +#include "securitypage.hrc" +#include "sfxresid.hxx" + +#include <sfx2/sfx.hrc> +#include <sfx2/sfxsids.hrc> +#include <sfx2/objsh.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/passwd.hxx> + +#include <vcl/button.hxx> +#include <vcl/edit.hxx> +#include <vcl/fixed.hxx> +#include <vcl/msgbox.hxx> +#include <svl/eitem.hxx> +#include <svl/poolitem.hxx> +#include <svl/intitem.hxx> +#include <svl/PasswordHelper.hxx> +#include <svtools/xwindowitem.hxx> + + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////// + + +namespace +{ + enum RedliningMode { RL_NONE, RL_WRITER, RL_CALC }; + enum RedlineFunc { RF_ON, RF_PROTECT }; + +/* + bool QueryIsEnabled( USHORT _nSlot ) + { + bool bRes = false; + SfxViewShell* pViewSh = SfxViewShell::Current(); + if (pViewSh) + { + const SfxPoolItem* pItem; + SfxDispatcher* pDisp = pViewSh->GetDispatcher(); + SfxItemState eState = pDisp->QueryState( _nSlot, pItem ); + bRes = (eState & SFX_ITEM_DISABLED) == 0; + } + return bRes; + } +*/ + + bool QueryState( USHORT _nSlot, bool& _rValue ) + { + bool bRet = false; + SfxViewShell* pViewSh = SfxViewShell::Current(); + if (pViewSh) + { + const SfxPoolItem* pItem; + SfxDispatcher* pDisp = pViewSh->GetDispatcher(); + SfxItemState nState = pDisp->QueryState( _nSlot, pItem ); + bRet = SFX_ITEM_AVAILABLE <= nState; + if (bRet) + _rValue = ( static_cast< const SfxBoolItem* >( pItem ) )->GetValue(); + } + return bRet; + } + + + bool QueryRecordChangesProtectionState( RedliningMode _eMode, bool& _rValue ) + { + bool bRet = false; + if (_eMode != RL_NONE) + { + USHORT nSlot = _eMode == RL_WRITER ? FN_REDLINE_PROTECT : SID_CHG_PROTECT; + bRet = QueryState( nSlot, _rValue ); + } + return bRet; + } + + + bool QueryRecordChangesState( RedliningMode _eMode, bool& _rValue ) + { + bool bRet = false; + if (_eMode != RL_NONE) + { + USHORT nSlot = _eMode == RL_WRITER ? FN_REDLINE_ON : FID_CHG_RECORD; + bRet = QueryState( nSlot, _rValue ); + } + return bRet; + } +} + + +////////////////////////////////////////////////////////////////////// + + +static short lcl_GetPassword( + Window *pParent, + bool bProtect, + /*out*/String &rPassword ) +{ + bool bRes = false; + SfxPasswordDialog aPasswdDlg( pParent ); + const String aTitle( SfxResId( bProtect ? RID_SFX_PROTECT_RECORDS : RID_SFX_UNPROTECT_RECORDS ) ); + aPasswdDlg.SetText( aTitle ); + aPasswdDlg.SetMinLen( 1 ); + if (bProtect) + aPasswdDlg.ShowExtras( SHOWEXTRAS_CONFIRM ); + if (RET_OK == aPasswdDlg.Execute() && aPasswdDlg.GetPassword().Len() > 0) + { + rPassword = aPasswdDlg.GetPassword(); + bRes = true; + } + return bRes; +} + + +static bool lcl_IsPasswordCorrect( const String &rPassword ) +{ + bool bRes = false; + + SfxObjectShell* pCurDocShell = SfxObjectShell::Current(); + uno::Sequence< sal_Int8 > aPasswordHash; + pCurDocShell->GetProtectionHash( aPasswordHash ); + + // check if supplied password was correct + uno::Sequence< sal_Int8 > aNewPasswd( aPasswordHash ); + SvPasswordHelper::GetHashPassword( aNewPasswd, rPassword ); + if (SvPasswordHelper::CompareHashPassword( aPasswordHash, rPassword )) + bRes = true; // password was correct + else + InfoBox( NULL, String( SfxResId( RID_SFX_INCORRECT_PASSWORD ) ) ).Execute(); + + return bRes; +} + + +////////////////////////////////////////////////////////////////////// + + +struct SfxSecurityPage_Impl +{ + SfxSecurityPage & m_rMyTabPage; + + FixedLine m_aNewPasswordToOpenFL; + FixedText m_aNewPasswordToOpenFT; + Edit m_aNewPasswordToOpenED; + FixedText m_aConfirmPasswordToOpenFT; + Edit m_aConfirmPasswordToOpenED; + FixedText m_aNewPasswordInfoFT; + + FixedLine m_aNewPasswordToModifyFL; + FixedText m_aNewPasswordToModifyFT; + Edit m_aNewPasswordToModifyED; + FixedText m_aConfirmPasswordToModifyFT; + Edit m_aConfirmPasswordToModifyED; + + FixedLine m_aOptionsFL; + CheckBox m_aOpenReadonlyCB; + CheckBox m_aRecordChangesCB; // for record changes + PushButton m_aChangeProtectionPB; // for record changes + String m_aProtectSTR; // for record changes + String m_aUnProtectSTR; // for record changes + RedliningMode m_eRedlingMode; // for record changes + + bool m_bOrigPasswordIsConfirmed; + bool m_bNewPasswordIsValid; + String m_aNewPassword; + + String m_aEndRedliningWarning; + bool m_bEndRedliningWarningDone; + + DECL_LINK( RecordChangesCBToggleHdl, void* ); + DECL_LINK( ChangeProtectionPBHdl, void* ); + + SfxSecurityPage_Impl( SfxSecurityPage &rDlg, const SfxItemSet &rItemSet ); + ~SfxSecurityPage_Impl(); + + BOOL FillItemSet_Impl( SfxItemSet & ); + void Reset_Impl( const SfxItemSet & ); +}; + + +SfxSecurityPage_Impl::SfxSecurityPage_Impl( SfxSecurityPage &rTabPage, const SfxItemSet & ) : + m_rMyTabPage (rTabPage), + m_aNewPasswordToOpenFL (&rTabPage, SfxResId( PASSWORD_TO_OPEN_FL ) ), + m_aNewPasswordToOpenFT (&rTabPage, SfxResId( PASSWORD_TO_OPEN_FT ) ), + m_aNewPasswordToOpenED (&rTabPage, SfxResId( PASSWORD_TO_OPEN_ED ) ), + m_aConfirmPasswordToOpenFT (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_OPEN_FT ) ), + m_aConfirmPasswordToOpenED (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_OPEN_ED ) ), + m_aNewPasswordInfoFT (&rTabPage, SfxResId( PASSWORD_INFO_FT ) ), + m_aNewPasswordToModifyFL (&rTabPage, SfxResId( PASSWORD_TO_MODIFY_FL ) ), + m_aNewPasswordToModifyFT (&rTabPage, SfxResId( PASSWORD_TO_MODIFY_FT ) ), + m_aNewPasswordToModifyED (&rTabPage, SfxResId( PASSWORD_TO_MODIFY_ED ) ), + m_aConfirmPasswordToModifyFT (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_MODIFY_FT ) ), + m_aConfirmPasswordToModifyED (&rTabPage, SfxResId( CONFIRM_PASSWORD_TO_MODIFY_ED ) ), + m_aOptionsFL (&rTabPage, SfxResId( OPTIONS_FL ) ), + m_aOpenReadonlyCB (&rTabPage, SfxResId( OPEN_READONLY_CB ) ), + m_aRecordChangesCB (&rTabPage, SfxResId( RECORD_CHANGES_CB ) ), + m_aChangeProtectionPB (&rTabPage, SfxResId( CHANGE_PROTECTION_PB ) ), + m_aProtectSTR ( SfxResId( STR_PROTECT ) ), + m_aUnProtectSTR ( SfxResId( STR_UNPROTECT ) ), + m_eRedlingMode ( RL_NONE ), + m_bOrigPasswordIsConfirmed ( false ), + m_bNewPasswordIsValid ( false ), + m_aEndRedliningWarning ( SfxResId( STR_END_REDLINING_WARNING ) ), + m_bEndRedliningWarningDone ( false ) +{ + m_aChangeProtectionPB.SetText( m_aProtectSTR ); + // adjust button width if necessary + long nBtnTextWidth = 0; + long nTemp = m_aChangeProtectionPB.GetCtrlTextWidth( m_aChangeProtectionPB.GetText() ); + if (nTemp > nBtnTextWidth) + nBtnTextWidth = nTemp; + + // force toggle hdl called before visual change of checkbox + m_aRecordChangesCB.SetStyle( m_aRecordChangesCB.GetStyle() | WB_EARLYTOGGLE ); + m_aRecordChangesCB.SetToggleHdl( LINK( this, SfxSecurityPage_Impl, RecordChangesCBToggleHdl ) ); + m_aChangeProtectionPB.SetClickHdl( LINK( this, SfxSecurityPage_Impl, ChangeProtectionPBHdl ) ); + + + // #i112277: for the time being (OOO 3.3) the following options should not + // be available. In the long run however it is planned to implement the yet + // missing functionality. Thus now we hide them and move the remaining ones up. + m_aNewPasswordToOpenFL.Hide(); + m_aNewPasswordToOpenFT.Hide(); + m_aNewPasswordToOpenED.Hide(); + m_aConfirmPasswordToOpenFT.Hide(); + m_aConfirmPasswordToOpenED.Hide(); + m_aNewPasswordInfoFT.Hide(); + m_aNewPasswordToModifyFL.Hide(); + m_aNewPasswordToModifyFT.Hide(); + m_aNewPasswordToModifyED.Hide(); + m_aConfirmPasswordToModifyFT.Hide(); + m_aConfirmPasswordToModifyED.Hide(); + const long nDelta = m_aOptionsFL.GetPosPixel().Y() - m_aNewPasswordToOpenFL.GetPosPixel().Y(); + Point aPos; + aPos = m_aOptionsFL.GetPosPixel(); + aPos.Y() -= nDelta; + m_aOptionsFL.SetPosPixel( aPos ); + aPos = m_aOpenReadonlyCB.GetPosPixel(); + aPos.Y() -= nDelta; + m_aOpenReadonlyCB.SetPosPixel( aPos ); + aPos = m_aRecordChangesCB.GetPosPixel(); + aPos.Y() -= nDelta; + m_aRecordChangesCB.SetPosPixel( aPos ); + aPos = m_aChangeProtectionPB.GetPosPixel(); + aPos.Y() -= nDelta; + m_aChangeProtectionPB.SetPosPixel( aPos ); +} + + +SfxSecurityPage_Impl::~SfxSecurityPage_Impl() +{ +} + + +BOOL SfxSecurityPage_Impl::FillItemSet_Impl( SfxItemSet & ) +{ + bool bModified = false; + + SfxObjectShell* pCurDocShell = SfxObjectShell::Current(); + if (pCurDocShell&& !pCurDocShell->IsReadOnly()) + { + if (m_eRedlingMode != RL_NONE ) + { + const bool bDoRecordChanges = m_aRecordChangesCB.IsChecked(); + const bool bDoChangeProtection = m_aChangeProtectionPB.GetText() != m_aProtectSTR; + + // sanity checks + DBG_ASSERT( bDoRecordChanges || !bDoChangeProtection, "no change recording should imply no change protection" ); + DBG_ASSERT( bDoChangeProtection || !bDoRecordChanges, "no change protection should imply no change recording" ); + DBG_ASSERT( !bDoChangeProtection || m_aNewPassword.Len() > 0, "change protection should imply password length is > 0" ); + DBG_ASSERT( bDoChangeProtection || m_aNewPassword.Len() == 0, "no change protection should imply password length is 0" ); + + // change recording + if (bDoRecordChanges != pCurDocShell->IsChangeRecording()) + { + pCurDocShell->SetChangeRecording( bDoRecordChanges ); + bModified = true; + } + + // change record protection + if (m_bNewPasswordIsValid && + bDoChangeProtection != pCurDocShell->HasChangeRecordProtection()) + { + DBG_ASSERT( !bDoChangeProtection || bDoRecordChanges, + "change protection requires record changes to be active!" ); + pCurDocShell->SetProtectionPassword( m_aNewPassword ); + bModified = true; + } + } + + // open read-only? + const sal_Bool bDoOpenReadonly = m_aOpenReadonlyCB.IsChecked(); + if (pCurDocShell->HasSecurityOptOpenReadOnly() && + bDoOpenReadonly != pCurDocShell->IsSecurityOptOpenReadOnly()) + { + pCurDocShell->SetSecurityOptOpenReadOnly( bDoOpenReadonly ); + bModified = true; + } + } + + return bModified; +} + + +void SfxSecurityPage_Impl::Reset_Impl( const SfxItemSet & ) +{ + SfxObjectShell* pCurDocShell = SfxObjectShell::Current(); + + String sNewText = m_aProtectSTR; + if (!pCurDocShell) + { + // no doc -> hide document settings + m_aOpenReadonlyCB.Disable(); + m_aRecordChangesCB.Disable(); + m_aChangeProtectionPB.Disable(); + } + else + { + bool bIsHTMLDoc = false; + SfxViewShell* pViewSh = SfxViewShell::Current(); + if (pViewSh) + { + const SfxPoolItem* pItem; + SfxDispatcher* pDisp = pViewSh->GetDispatcher(); + if (SFX_ITEM_AVAILABLE <= pDisp->QueryState( SID_HTML_MODE, pItem )) + { + USHORT nMode = static_cast< const SfxUInt16Item* >( pItem )->GetValue(); + bIsHTMLDoc = ( ( nMode & HTMLMODE_ON ) != 0 ); + } + } + + sal_Bool bIsReadonly = pCurDocShell->IsReadOnly(); + if (pCurDocShell->HasSecurityOptOpenReadOnly() && !bIsHTMLDoc) + { + m_aOpenReadonlyCB.Check( pCurDocShell->IsSecurityOptOpenReadOnly() ); + m_aOpenReadonlyCB.Enable( !bIsReadonly ); + } + else + m_aOpenReadonlyCB.Disable(); + + bool bRecordChanges; + if (QueryRecordChangesState( RL_WRITER, bRecordChanges ) && !bIsHTMLDoc) + m_eRedlingMode = RL_WRITER; + else if (QueryRecordChangesState( RL_CALC, bRecordChanges )) + m_eRedlingMode = RL_CALC; + else + m_eRedlingMode = RL_NONE; + + if (m_eRedlingMode != RL_NONE) + { + bool bProtection; + QueryRecordChangesProtectionState( m_eRedlingMode, bProtection ); + + m_aChangeProtectionPB.Enable( !bIsReadonly ); + // set the right text + if (bProtection) + sNewText = m_aUnProtectSTR; + + m_aRecordChangesCB.Check( bRecordChanges ); + m_aRecordChangesCB.Enable( /*!bProtection && */!bIsReadonly ); + + m_bOrigPasswordIsConfirmed = true; // default case if no password is set + uno::Sequence< sal_Int8 > aPasswordHash; + // check if password is available + if (pCurDocShell->GetProtectionHash( aPasswordHash ) && + aPasswordHash.getLength() > 0) + m_bOrigPasswordIsConfirmed = false; // password found, needs to be confirmed later on + } + else + { + // A Calc document that is shared will have 'm_eRedlingMode == RL_NONE' + // In shared documents change recording and protection must be disabled, + // similar to documents that do not support change recording at all. + m_aRecordChangesCB.Check( FALSE ); + m_aRecordChangesCB.Disable(); + m_aChangeProtectionPB.Check( FALSE ); + m_aChangeProtectionPB.Disable(); + } + } + + m_aChangeProtectionPB.SetText( sNewText ); +} + + +IMPL_LINK( SfxSecurityPage_Impl, RecordChangesCBToggleHdl, void*, EMPTYARG ) +{ + // when change recording gets disabled protection must be disabled as well + if (!m_aRecordChangesCB.IsChecked()) // the new check state is already present, thus the '!' + { + bool bAlreadyDone = false; + if (!m_bEndRedliningWarningDone) + { + WarningBox aBox( m_rMyTabPage.GetParent(), WinBits(WB_YES_NO | WB_DEF_NO), + m_aEndRedliningWarning ); + if (aBox.Execute() != RET_YES) + bAlreadyDone = true; + else + m_bEndRedliningWarningDone = true; + } + + const bool bNeedPasssword = !m_bOrigPasswordIsConfirmed + && m_aChangeProtectionPB.GetText() != m_aProtectSTR; + if (!bAlreadyDone && bNeedPasssword) + { + String aPasswordText; + + // dialog canceled or no password provided + if (!lcl_GetPassword( m_rMyTabPage.GetParent(), false, aPasswordText )) + bAlreadyDone = true; + + // ask for password and if dialog is canceled or no password provided return + if (lcl_IsPasswordCorrect( aPasswordText )) + m_bOrigPasswordIsConfirmed = true; + else + bAlreadyDone = true; + } + + if (bAlreadyDone) + m_aRecordChangesCB.Check( true ); // restore original state + else + { + // remember required values to change protection and change recording in + // FillItemSet_Impl later on if password was correct. + m_bNewPasswordIsValid = true; + m_aNewPassword = String(); + + m_aChangeProtectionPB.SetText( m_aProtectSTR ); + } + } + + return 0; +} + + +IMPL_LINK( SfxSecurityPage_Impl, ChangeProtectionPBHdl, void*, EMPTYARG ) +{ + if (m_eRedlingMode == RL_NONE) + return 0; + + // the push button text is always the opposite of the current state. Thus: + const bool bCurrentProtection = m_aChangeProtectionPB.GetText() != m_aProtectSTR; + + // ask user for password (if still necessary) + String aPasswordText; + bool bNewProtection = !bCurrentProtection; + const bool bNeedPassword = bNewProtection || !m_bOrigPasswordIsConfirmed; + if (bNeedPassword) + { + // ask for password and if dialog is canceled or no password provided return + if (!lcl_GetPassword( m_rMyTabPage.GetParent(), bNewProtection, aPasswordText )) + return 0; + + // provided password still needs to be checked? + if (!bNewProtection && !m_bOrigPasswordIsConfirmed) + { + if (lcl_IsPasswordCorrect( aPasswordText )) + m_bOrigPasswordIsConfirmed = true; + else + return 0; + } + } + DBG_ASSERT( m_bOrigPasswordIsConfirmed, "ooops... this should not have happened!" ); + + // remember required values to change protection and change recording in + // FillItemSet_Impl later on if password was correct. + m_bNewPasswordIsValid = true; + m_aNewPassword = bNewProtection? aPasswordText : String(); + +// // RecordChangesCB is enabled if protection is off +// m_aRecordChangesCB.Enable( !bNewProtection ); + m_aRecordChangesCB.Check( bNewProtection ); + // toggle text of button "Protect" <-> "Unprotect" + m_aChangeProtectionPB.SetText( bNewProtection ? m_aUnProtectSTR : m_aProtectSTR ); + + return 0; +} + + +////////////////////////////////////////////////////////////////////// + + +SfxTabPage* SfxSecurityPage::Create( Window * pParent, const SfxItemSet & rItemSet ) +{ + return new SfxSecurityPage( pParent, rItemSet ); +} + + +SfxSecurityPage::SfxSecurityPage( Window* pParent, const SfxItemSet& rItemSet ) : + SfxTabPage( pParent, SfxResId( TP_DOCINFOSECURITY ), rItemSet ) +{ + m_pImpl = std::auto_ptr< SfxSecurityPage_Impl >(new SfxSecurityPage_Impl( *this, rItemSet )); + + FreeResource(); +} + + +SfxSecurityPage::~SfxSecurityPage() +{ +} + + +BOOL SfxSecurityPage::FillItemSet( SfxItemSet & rItemSet ) +{ + bool bModified = false; + DBG_ASSERT( m_pImpl.get(), "implementation pointer is 0. Still in c-tor?" ); + if (m_pImpl.get() != 0) + bModified = m_pImpl->FillItemSet_Impl( rItemSet ); + return bModified; +} + + +void SfxSecurityPage::Reset( const SfxItemSet & rItemSet ) +{ + DBG_ASSERT( m_pImpl.get(), "implementation pointer is 0. Still in c-tor?" ); + if (m_pImpl.get() != 0) + m_pImpl->Reset_Impl( rItemSet ); +} + + +////////////////////////////////////////////////////////////////////// + + diff --git a/sfx2/source/dialog/securitypage.hrc b/sfx2/source/dialog/securitypage.hrc new file mode 100755 index 000000000000..d425131b4772 --- /dev/null +++ b/sfx2/source/dialog/securitypage.hrc @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SECURITYPAGE_HRC_ +#define _SECURITYPAGE_HRC_ + + +#define PASSWORD_TO_OPEN_FL 1 +#define PASSWORD_TO_OPEN_FT 2 +#define PASSWORD_TO_OPEN_ED 3 +#define CONFIRM_PASSWORD_TO_OPEN_FT 4 +#define CONFIRM_PASSWORD_TO_OPEN_ED 5 +#define PASSWORD_INFO_FT 6 +#define PASSWORD_TO_MODIFY_FL 7 +#define PASSWORD_TO_MODIFY_FT 8 +#define PASSWORD_TO_MODIFY_ED 9 +#define CONFIRM_PASSWORD_TO_MODIFY_FT 10 +#define CONFIRM_PASSWORD_TO_MODIFY_ED 11 +#define OPTIONS_FL 12 +#define OPEN_READONLY_CB 13 +#define RECORD_CHANGES_CB 14 +#define CHANGE_PROTECTION_PB 15 + +#define STR_PROTECT 101 +#define STR_UNPROTECT 102 +#define STR_END_REDLINING_WARNING 103 + +#endif + diff --git a/sfx2/source/dialog/securitypage.src b/sfx2/source/dialog/securitypage.src new file mode 100644 index 000000000000..fee60404d01c --- /dev/null +++ b/sfx2/source/dialog/securitypage.src @@ -0,0 +1,174 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sfx2/sfx.hrc" +#include "securitypage.hrc" +#include "helpid.hrc" +#include "dialog.hrc" +#include "sfxlocal.hrc" + +#include <svtools/controldims.hrc> + + +TabPage TP_DOCINFOSECURITY +{ + HelpId = HID_DOCINFOSECURITY ; + Hide = TRUE ; + Size = MAP_APPFONT ( 260 , 185 ) ; + + FixedLine PASSWORD_TO_OPEN_FL + { + Pos = MAP_APPFONT( 6, 6 ); + Size = MAP_APPFONT( 248, RSC_CD_FIXEDLINE_HEIGHT ); + Text [ en-US ] = "File encryption password"; + }; + FixedText PASSWORD_TO_OPEN_FT + { + Pos = MAP_APPFONT( 12, 20 ); + Size = MAP_APPFONT( 82, RSC_CD_FIXEDTEXT_HEIGHT ); + Text [ en-US ] = "~Enter password to open"; + }; + Edit PASSWORD_TO_OPEN_ED + { + HelpId = HID_SECURITYTAB_PASSWORD_TO_OPEN; + Pos = MAP_APPFONT( 100, 18 ); + Size = MAP_APPFONT( 88, RSC_CD_TEXTBOX_HEIGHT ); + Border = TRUE; + PassWord = TRUE; + }; + FixedText CONFIRM_PASSWORD_TO_OPEN_FT + { + Pos = MAP_APPFONT( 12, 34 ); + Size = MAP_APPFONT( 82, RSC_CD_FIXEDTEXT_HEIGHT ); + Text [ en-US ] = "~Reenter password to open"; + }; + Edit CONFIRM_PASSWORD_TO_OPEN_ED + { + HelpId = HID_SECURITYTAB_CONFIRM_PASSWORD_TO_OPEN; + Pos = MAP_APPFONT( 100, 32 ); + Size = MAP_APPFONT( 88, RSC_CD_TEXTBOX_HEIGHT ); + Border = TRUE; + PassWord = TRUE; + }; + FixedText PASSWORD_INFO_FT + { + Pos = MAP_APPFONT( 12, 48 ); + Size = MAP_APPFONT( 236, 3 * RSC_CD_FIXEDTEXT_HEIGHT ); + Text [ en-US ] = + "Note: After a password has been set, the document will only open "\ + "with the password. Should you lose the password, there will be "\ + "no way to recover the document. Please also note that this password "\ + "is case-sensitive."; + WordBreak = TRUE; + }; + FixedLine PASSWORD_TO_MODIFY_FL + { + Pos = MAP_APPFONT( 6, 78 ); + Size = MAP_APPFONT( 248, RSC_CD_FIXEDLINE_HEIGHT ); + Text [ en-US ] = "File sharing password"; + }; + FixedText PASSWORD_TO_MODIFY_FT + { + Pos = MAP_APPFONT( 12, 92 ); + Size = MAP_APPFONT( 82, RSC_CD_FIXEDTEXT_HEIGHT ); + Text [ en-US ] = "Enter password to modify"; + }; + Edit PASSWORD_TO_MODIFY_ED + { + HelpId = HID_SECURITYTAB_PASSWORD_TO_MODIFY; + Pos = MAP_APPFONT( 100, 90 ); + Size = MAP_APPFONT( 88, RSC_CD_TEXTBOX_HEIGHT ); + Border = TRUE; + PassWord = TRUE; + }; + FixedText CONFIRM_PASSWORD_TO_MODIFY_FT + { + Pos = MAP_APPFONT( 12, 106 ); + Size = MAP_APPFONT( 82, RSC_CD_FIXEDTEXT_HEIGHT ); + Text [ en-US ] = "Reenter password to modify"; + }; + Edit CONFIRM_PASSWORD_TO_MODIFY_ED + { + HelpId = HID_SECURITYTAB_CONFIRM_PASSWORD_TO_MODIFY; + Pos = MAP_APPFONT( 100, 104 ); + Size = MAP_APPFONT( 88, RSC_CD_TEXTBOX_HEIGHT ); + Border = TRUE; + PassWord = TRUE; + }; + FixedLine OPTIONS_FL + { + Pos = MAP_APPFONT( 6, 120 ); + Size = MAP_APPFONT( 248, RSC_CD_FIXEDLINE_HEIGHT ); + Text [ en-US ] = "File sharing options"; + }; + CheckBox OPEN_READONLY_CB + { + HelpId = HID_SECURITYTAB_OPEN_FILE_READONLY; + Pos = MAP_APPFONT( 12, 133 ); + Size = MAP_APPFONT( 176, RSC_CD_CHECKBOX_HEIGHT ); + Text [ en-US ] = "~Open file read-only"; + }; + CheckBox RECORD_CHANGES_CB + { + HelpId = HID_SECURITYTAB_RECORD_CHANGES; + Pos = MAP_APPFONT( 12, 147 ); + Size = MAP_APPFONT( 176, RSC_CD_CHECKBOX_HEIGHT ); + Text [ en-US ] = "Record ~changes"; + }; + PushButton CHANGE_PROTECTION_PB + { + HelpId = HID_SECURITYTAB_PROTECTION; + Pos = MAP_APPFONT( 194, 145 ); + Size = MAP_APPFONT( 60, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + String STR_PROTECT + { + Text [ en-US ] = "~Protect..."; + }; + String STR_UNPROTECT + { + Text [ en-US ] = "~Unprotect..."; + }; + String STR_END_REDLINING_WARNING + { + Text [ en-US ] = "This action will exit the change recording mode.\nAny information about changes will be lost.\n\nExit change recording mode?\n\n" ; + }; +}; + +String RID_SFX_PROTECT_RECORDS +{ + Text [ en-US ] = "Protect Records" ; +}; +String RID_SFX_UNPROTECT_RECORDS +{ + Text [ en-US ] = "Unprotect Records" ; +}; +String RID_SFX_INCORRECT_PASSWORD +{ + Text [ en-US ] = "Incorrect password" ; +}; + diff --git a/sfx2/source/dialog/sfxdlg.cxx b/sfx2/source/dialog/sfxdlg.cxx new file mode 100755 index 000000000000..d62ed70b8490 --- /dev/null +++ b/sfx2/source/dialog/sfxdlg.cxx @@ -0,0 +1,44 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <sfx2/sfxdlg.hxx> +#include "cuilib.hxx" + +#include <osl/module.hxx> +#include <tools/string.hxx> + +SfxAbstractDialogFactory* SfxAbstractDialogFactory::Create() +{ + return dynamic_cast <SfxAbstractDialogFactory*>( VclAbstractDialogFactory::Create() ); +} + +SfxAbstractDialogFactory::~SfxAbstractDialogFactory() +{ +} diff --git a/sfx2/source/dialog/splitwin.cxx b/sfx2/source/dialog/splitwin.cxx new file mode 100644 index 000000000000..f6e5f96cf0bd --- /dev/null +++ b/sfx2/source/dialog/splitwin.cxx @@ -0,0 +1,1304 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#ifdef SOLARIS +// HACK: prevent conflict between STLPORT and Workshop headers on Solaris 8 +#include <ctime> +#endif + +#include <string> // HACK: prevent conflict between STLPORT and Workshop headers + +#ifndef _WRKWIN_HXX //autogen +#include <vcl/wrkwin.hxx> +#endif +#include <unotools/viewoptions.hxx> +#ifndef GCC +#endif + +#include <vcl/timer.hxx> + +#include "splitwin.hxx" +#include "workwin.hxx" +#include <sfx2/dockwin.hxx> +#include <sfx2/app.hxx> +#include "dialog.hrc" +#include "sfxresid.hxx" +#include <sfx2/mnumgr.hxx> +#include "virtmenu.hxx" +#include <sfx2/msgpool.hxx> +#include <sfx2/viewfrm.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::rtl; + +#define VERSION 1 +#define nPixel 30L +#define USERITEM_NAME OUString::createFromAscii( "UserItem" ) + +struct SfxDock_Impl +{ + USHORT nType; + SfxDockingWindow* pWin; // SplitWindow hat dieses Fenster + BOOL bNewLine; + BOOL bHide; // SplitWindow hatte dieses Fenster + long nSize; +}; + +typedef SfxDock_Impl* SfxDockPtr; +SV_DECL_PTRARR_DEL( SfxDockArr_Impl, SfxDockPtr, 4, 4) +SV_IMPL_PTRARR( SfxDockArr_Impl, SfxDockPtr); + +class SfxEmptySplitWin_Impl : public SplitWindow +{ +/* [Beschreibung] + + Das SfxEmptySplitWin_Impldow ist ein leeres SplitWindow, das das SfxSplitWindow + im AutoHide-Modus ersetzt. Es dient nur als Platzhalter, um MouseMoves + zu empfangen und ggf. das eigentlichte SplitWindow einzublenden +*/ +friend class SfxSplitWindow; + + SfxSplitWindow* pOwner; + BOOL bFadeIn; + BOOL bAutoHide; + BOOL bSplit; + BOOL bEndAutoHide; + Timer aTimer; + Point aLastPos; + USHORT nState; + + SfxEmptySplitWin_Impl( SfxSplitWindow *pParent ) + : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) ) + , pOwner( pParent ) + , bFadeIn( FALSE ) + , bAutoHide( FALSE ) + , bSplit( FALSE ) + , bEndAutoHide( FALSE ) + , nState( 1 ) + { + aTimer.SetTimeoutHdl( + LINK(pOwner, SfxSplitWindow, TimerHdl ) ); + aTimer.SetTimeout( 200 ); +// EnableDrop( TRUE ); + SetAlign( pOwner->GetAlign() ); + Actualize(); + ShowAutoHideButton( pOwner->IsAutoHideButtonVisible() ); + ShowFadeInHideButton( TRUE ); + } + + ~SfxEmptySplitWin_Impl() + { + aTimer.Stop(); + } + + virtual void MouseMove( const MouseEvent& ); + virtual void AutoHide(); + virtual void FadeIn(); + void Actualize(); +}; + +void SfxEmptySplitWin_Impl::Actualize() +{ + Size aSize( pOwner->GetSizePixel() ); + switch ( pOwner->GetAlign() ) + { + case WINDOWALIGN_LEFT: + case WINDOWALIGN_RIGHT: + aSize.Width() = GetFadeInSize(); + break; + case WINDOWALIGN_TOP: + case WINDOWALIGN_BOTTOM: + aSize.Height() = GetFadeInSize(); + break; + } + + SetSizePixel( aSize ); +} + +void SfxEmptySplitWin_Impl::AutoHide() +{ + pOwner->SetPinned_Impl( !pOwner->bPinned ); + pOwner->SaveConfig_Impl(); + bAutoHide = TRUE; + FadeIn(); +} + +void SfxEmptySplitWin_Impl::FadeIn() +{ + if (!bAutoHide ) + bAutoHide = IsFadeNoButtonMode(); + pOwner->SetFadeIn_Impl( TRUE ); + pOwner->Show_Impl(); + if ( bAutoHide ) + { + // Timer zum Schlie\sen aufsetzen; der Aufrufer mu\s selbst sicherstellen, + // da\s das Window nicht gleich wieder zu geht ( z.B. durch Setzen des + // Focus oder einen modal mode ) + aLastPos = GetPointerPosPixel(); + aTimer.Start(); + } + else + pOwner->SaveConfig_Impl(); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.GetClicks() != 2 ) + SplitWindow::MouseButtonDown( rMEvt ); +} + +void SfxEmptySplitWin_Impl::MouseMove( const MouseEvent& rMEvt ) +{ + SplitWindow::MouseMove( rMEvt ); +} + +//------------------------------------------------------------------------- + +SfxSplitWindow::SfxSplitWindow( Window* pParent, SfxChildAlignment eAl, + SfxWorkWindow *pW, BOOL bWithButtons, WinBits nBits ) + +/* [Beschreibung] + + Ein SfxSplitWindow verbirgt die rekursive Struktur des SV-Splitwindows + nach au\sen, indem es einen tabellenartigen Aufbau mit Zeilen und Spalten + ( also maximale Rekursionstiefe 2 ) simuliert. + Au\erdem sichert es die Persistenz der Anordnung der SfxDockingWindows. +*/ + +: SplitWindow ( pParent, nBits | WB_HIDE ), + eAlign(eAl), + pWorkWin(pW), + pDockArr( new SfxDockArr_Impl ), + bLocked(FALSE), + bPinned(TRUE), + pEmptyWin(NULL), + pActive(NULL) +{ + if ( bWithButtons ) + { + ShowAutoHideButton( FALSE ); // no autohide button (pin) anymore + ShowFadeOutButton( TRUE ); + } + + // SV-Alignment setzen + WindowAlign eTbxAlign; + switch ( eAlign ) + { + case SFX_ALIGN_LEFT: + eTbxAlign = WINDOWALIGN_LEFT; + break; + case SFX_ALIGN_RIGHT: + eTbxAlign = WINDOWALIGN_RIGHT; + break; + case SFX_ALIGN_TOP: + eTbxAlign = WINDOWALIGN_TOP; + break; + case SFX_ALIGN_BOTTOM: + eTbxAlign = WINDOWALIGN_BOTTOM; + bPinned = TRUE; + break; + default: + eTbxAlign = WINDOWALIGN_TOP; // some sort of default... + break; // -Wall lots not handled.. + } + + SetAlign (eTbxAlign); + pEmptyWin = new SfxEmptySplitWin_Impl( this ); + if ( bPinned ) + { + pEmptyWin->bFadeIn = TRUE; + pEmptyWin->nState = 2; + } + + if ( bWithButtons ) + { + // Konfiguration einlesen + String aWindowId = String::CreateFromAscii("SplitWindow"); + aWindowId += String::CreateFromInt32( (sal_Int32) eTbxAlign ); + SvtViewOptions aWinOpt( E_WINDOW, aWindowId ); + String aWinData; + Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + aWinData = String( aTemp ); + if ( aWinData.Len() && aWinData.GetChar( (USHORT) 0 ) == 'V' ) + { + pEmptyWin->nState = (USHORT) aWinData.GetToken( 1, ',' ).ToInt32(); + if ( pEmptyWin->nState & 2 ) + pEmptyWin->bFadeIn = TRUE; + //bPinned = !( pEmptyWin->nState & 1 ); + bPinned = TRUE; // always assume pinned - floating mode not used anymore + + USHORT i=2; + USHORT nCount = (USHORT) aWinData.GetToken(i++, ',').ToInt32(); + for ( USHORT n=0; n<nCount; n++ ) + { + SfxDock_Impl *pDock = new SfxDock_Impl; + pDock->pWin = 0; + pDock->bNewLine = FALSE; + pDock->bHide = TRUE; + pDock->nType = (USHORT) aWinData.GetToken(i++, ',').ToInt32(); + if ( !pDock->nType ) + { + // K"onnte NewLine bedeuten + pDock->nType = (USHORT) aWinData.GetToken(i++, ',').ToInt32(); + if ( !pDock->nType ) + { + // Lesefehler + delete pDock; + break; + } + else + pDock->bNewLine = TRUE; + } + + pDockArr->Insert(pDock,n); + } + } + } + else + { + bPinned = TRUE; + pEmptyWin->bFadeIn = TRUE; + pEmptyWin->nState = 2; + } + + SetAutoHideState( !bPinned ); + pEmptyWin->SetAutoHideState( !bPinned ); +} + +//------------------------------------------------------------------------- + +SfxSplitWindow::~SfxSplitWindow() +{ + if ( !pWorkWin->GetParent_Impl() ) + SaveConfig_Impl(); + + if ( pEmptyWin ) + { + // pOwner auf NULL setzen, sonst versucht pEmptyWin, nochmal zu + // l"oschen; es wird n"amlich von au\sen immer das Fenster deleted, + // das gerade angedockt ist + pEmptyWin->pOwner = NULL; + delete pEmptyWin; + } + + delete pDockArr; +} + +void SfxSplitWindow::SaveConfig_Impl() +{ + // Konfiguration abspeichern + String aWinData('V'); + aWinData += String::CreateFromInt32( VERSION ); + aWinData += ','; + aWinData += String::CreateFromInt32( pEmptyWin->nState ); + aWinData += ','; + + USHORT nCount = 0; + USHORT n; + for ( n=0; n<pDockArr->Count(); n++ ) + { + SfxDock_Impl *pDock = (*pDockArr)[n]; + if ( pDock->bHide || pDock->pWin ) + nCount++; + } + + aWinData += String::CreateFromInt32( nCount ); + + for ( n=0; n<pDockArr->Count(); n++ ) + { + SfxDock_Impl *pDock = (*pDockArr)[n]; + if ( !pDock->bHide && !pDock->pWin ) + continue; + if ( pDock->bNewLine ) + aWinData += DEFINE_CONST_UNICODE(",0"); + aWinData += ','; + aWinData += String::CreateFromInt32( pDock->nType); + } + + String aWindowId = String::CreateFromAscii("SplitWindow"); + aWindowId += String::CreateFromInt32( (sal_Int32) GetAlign() ); + SvtViewOptions aWinOpt( E_WINDOW, aWindowId ); + aWinOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aWinData ) ) ); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::StartSplit() +{ + long nSize = 0; + Size aSize = GetSizePixel(); + + if ( pEmptyWin ) + { + pEmptyWin->bFadeIn = TRUE; + pEmptyWin->bSplit = TRUE; + } + + Rectangle aRect = pWorkWin->GetFreeArea( !bPinned ); + switch ( GetAlign() ) + { + case WINDOWALIGN_LEFT: + case WINDOWALIGN_RIGHT: + nSize = aSize.Width() + aRect.GetWidth(); + break; + case WINDOWALIGN_TOP: + case WINDOWALIGN_BOTTOM: + nSize = aSize.Height() + aRect.GetHeight(); + break; + } + + SetMaxSizePixel( nSize ); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::SplitResize() +{ + if ( bPinned ) + { + pWorkWin->ArrangeChilds_Impl(); + pWorkWin->ShowChilds_Impl(); + } + else + pWorkWin->ArrangeAutoHideWindows( this ); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::Split() +{ + if ( pEmptyWin ) + pEmptyWin->bSplit = FALSE; + + SplitWindow::Split(); + + USHORT nCount = pDockArr->Count(); + for ( USHORT n=0; n<nCount; n++ ) + { + SfxDock_Impl *pD = (*pDockArr)[n]; + if ( pD->pWin ) + { + USHORT nId = pD->nType; + long nSize = GetItemSize( nId, SWIB_FIXED ); + long nSetSize = GetItemSize( GetSet( nId ) ); + Size aSize; + + if ( IsHorizontal() ) + { + aSize.Width() = nSize; + aSize.Height() = nSetSize; + } + else + { + aSize.Width() = nSetSize; + aSize.Height() = nSize; + } + + pD->pWin->SetItemSize_Impl( aSize ); + } + } + + SaveConfig_Impl(); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize) + +/* [Beschreibung] + + Zum Einf"ugen von SfxDockingWindows kann auch keine Position "ubergeben + werden. Das SfxSplitWindow sucht dann die zuletzt gemerkte zu dem + "ubergebenen SfxDockingWindow heraus oder h"angt es als letztes neu an. + +*/ +{ + short nLine = -1; // damit erstes Fenster nLine auf 0 hochsetzen kann + USHORT nL; + USHORT nPos = 0; + BOOL bNewLine = TRUE; + BOOL bSaveConfig = FALSE; + SfxDock_Impl *pFoundDock=0; + USHORT nCount = pDockArr->Count(); + for ( USHORT n=0; n<nCount; n++ ) + { + SfxDock_Impl *pDock = (*pDockArr)[n]; + if ( pDock->bNewLine ) + { + // Das Fenster er"offnet eine neue Zeile + if ( pFoundDock ) + // Aber hinter dem gerade eingef"ugten Fenster + break; + + // Neue Zeile + nPos = 0; + bNewLine = TRUE; + } + + if ( pDock->pWin ) + { + // Es gibt an dieser Stelle gerade ein Fenster + if ( bNewLine && !pFoundDock ) + { + // Bisher ist nicht bekannt, in welcher realen Zeile es liegt + GetWindowPos( pDock->pWin, nL, nPos ); + nLine = (short) nL; + } + + if ( !pFoundDock ) + { + // Fenster liegt vor dem eingef"ugten + nPos++; + } + + // Zeile ist schon er"offnet + bNewLine = FALSE; + if ( pFoundDock ) + break; + } + + if ( pDock->nType == pDockWin->GetType() ) + { + DBG_ASSERT( !pFoundDock && !pDock->pWin, "Fenster ist schon vorhanden!"); + pFoundDock = pDock; + if ( !bNewLine ) + break; + else + { + // Es wurde zuletzt eine neue Reihe gestartet, aber noch kein + // darin liegendes Fenster gefunden; daher weitersuchen, ob noch + // ein Fenster in dieser Zeile folgt, um bNewLine korrekt zu setzen. + // Dabei darf aber nLine oder nPos nicht mehr ver"andert werden! + nLine++; + } + } + } + + if ( !pFoundDock ) + { + // Nicht gefunden, am Ende einf"ugen + pFoundDock = new SfxDock_Impl; + pFoundDock->bHide = TRUE; + pDockArr->Insert( pFoundDock, nCount ); + pFoundDock->nType = pDockWin->GetType(); + nLine++; + nPos = 0; + bNewLine = TRUE; + pFoundDock->bNewLine = bNewLine; + bSaveConfig = TRUE; + } + + pFoundDock->pWin = pDockWin; + pFoundDock->bHide = FALSE; + InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine ); + if ( bSaveConfig ) + SaveConfig_Impl(); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow *pDockWin, BOOL bSave) + +/* [Beschreibung] + + Das DockingWindow wird nicht mehr in den internen Daten gespeichert. +*/ + +{ + SfxDock_Impl *pDock=0; + USHORT nCount = pDockArr->Count(); + BOOL bFound = FALSE; + for ( USHORT n=0; n<nCount; n++ ) + { + pDock = (*pDockArr)[n]; + if ( pDock->nType == pDockWin->GetType() ) + { + if ( pDock->bNewLine && n<nCount-1 ) + (*pDockArr)[n+1]->bNewLine = TRUE; + + // Fenster hat schon eine Position, die vergessen wir + bFound = TRUE; + pDockArr->Remove(n); + break; + } + } + + if ( bFound ) + delete pDock; + + if ( bSave ) + SaveConfig_Impl(); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::MoveWindow( SfxDockingWindow* pDockWin, const Size& rSize, + USHORT nLine, USHORT nPos, BOOL bNewLine) + +/* [Beschreibung] + + Das DockingWindow wird innerhalb des Splitwindows verschoben. + +*/ + +{ + USHORT nL, nP; + GetWindowPos( pDockWin, nL, nP ); + + if ( nLine > nL && GetItemCount( GetItemId( nL, 0 ) ) == 1 ) + { + // Wenn das letzte Fenster aus seiner Zeile entfernt wird, rutscht + // alles eine Zeile nach vorne! + nLine--; + } +/* + else if ( nLine == nL && nPos > nP ) + { + nPos--; + } +*/ + RemoveWindow( pDockWin ); + InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine ); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize, + USHORT nLine, USHORT nPos, BOOL bNewLine) + +/* [Beschreibung] + + Das DockingWindow wird in dieses Splitwindow geschoben und soll die + "ubergebene Position und Gr"o\se haben. + +*/ +{ + ReleaseWindow_Impl( pDockWin, FALSE ); + SfxDock_Impl *pDock = new SfxDock_Impl; + pDock->bHide = FALSE; + pDock->nType = pDockWin->GetType(); + pDock->bNewLine = bNewLine; + pDock->pWin = pDockWin; + + DBG_ASSERT( nPos==0 || !bNewLine, "Falsche Paramenter!"); + if ( bNewLine ) + nPos = 0; + + // Das Fenster mu\s vor dem ersten Fenster eingef"ugt werden, das die + // gleiche oder eine gr"o\sere Position hat als pDockWin. + USHORT nCount = pDockArr->Count(); + + // Wenn gar kein Fenster gefunden wird, wird als erstes eingef"ugt + USHORT nInsertPos = 0; + for ( USHORT n=0; n<nCount; n++ ) + { + SfxDock_Impl *pD = (*pDockArr)[n]; + + if (pD->pWin) + { + // Ein angedocktes Fenster wurde gefunden + // Wenn kein geeignetes Fenster hinter der gew"unschten Einf"ugeposition + // gefunden wird, wird am Ende eingef"ugt + nInsertPos = nCount; + USHORT nL=0, nP=0; + GetWindowPos( pD->pWin, nL, nP ); + + if ( (nL == nLine && nP == nPos) || nL > nLine ) + { + DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Falsche Parameter!" ); + if ( nL == nLine && nPos == 0 && !bNewLine ) + { + DBG_ASSERT(pD->bNewLine, "Keine neue Zeile?"); + + // Das Fenster wird auf nPos==0 eingeschoben + pD->bNewLine = FALSE; + pDock->bNewLine = TRUE; + } + + nInsertPos = n; + break; + } + } + } + + pDockArr->Insert(pDock, nInsertPos); + InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine ); + SaveConfig_Impl(); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl* pDock, + const Size& rSize, + USHORT nLine, USHORT nPos, BOOL bNewLine) + +/* [Beschreibung] + + F"ugt ein DockingWindow ein und veranla\st die Neuberechnung der Gr"o\se + des Splitwindows. +*/ + +{ + SfxDockingWindow* pDockWin = pDock->pWin; + + USHORT nItemBits = pDockWin->GetWinBits_Impl(); + + long nWinSize, nSetSize; + if ( IsHorizontal() ) + { + nWinSize = rSize.Width(); + nSetSize = rSize.Height(); + } + else + { + nSetSize = rSize.Width(); + nWinSize = rSize.Height(); + } + + pDock->nSize = nWinSize; + + BOOL bUpdateMode = IsUpdateMode(); + if ( bUpdateMode ) + SetUpdateMode( FALSE ); + + if ( bNewLine || nLine == GetItemCount( 0 ) ) + { + // Es soll nicht in eine vorhandene Zeile eingef"ugt werden, sondern + // eine neue erzeugt werden + + USHORT nId = 1; + for ( USHORT n=0; n<GetItemCount(0); n++ ) + { + if ( GetItemId(n) >= nId ) + nId = GetItemId(n)+1; + } + + // Eine neue nLine-te Zeile erzeugen + USHORT nBits = nItemBits; + if ( GetAlign() == WINDOWALIGN_TOP || GetAlign() == WINDOWALIGN_BOTTOM ) + nBits |= SWIB_COLSET; + InsertItem( nId, nSetSize, nLine, 0, nBits ); + } + + // In Zeile mit Position nLine das Fenster einf"ugen + // ItemWindowSize auf "Prozentual" setzen, da SV dann das Umgr"o\sern + // so macht, wie man erwartet; "Pixel" macht eigentlich nur Sinn, wenn + // auch Items mit prozentualen oder relativen Gr"o\sen dabei sind. + nItemBits |= SWIB_PERCENTSIZE; + bLocked = TRUE; + USHORT nSet = GetItemId( nLine ); + InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits ); + + // Splitwindows werden im SFX einmal angelegt und beim Einf"ugen des ersten + // DockingWindows sichtbar gemacht. + if ( GetItemCount( 0 ) == 1 && GetItemCount( 1 ) == 1 ) + { + // Das Neuarrangieren am WorkWindow und ein Show() auf das SplitWindow + // wird vom SfxDockingwindow veranla\st (->SfxWorkWindow::ConfigChild_Impl) + if ( !bPinned && !IsFloatingMode() ) + { + bPinned = TRUE; + BOOL bFadeIn = ( pEmptyWin->nState & 2 ) != 0; + pEmptyWin->bFadeIn = FALSE; + SetPinned_Impl( FALSE ); + pEmptyWin->Actualize(); + DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" ); + pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, TRUE )->nVisible = CHILD_VISIBLE; + pWorkWin->ArrangeChilds_Impl(); + if ( bFadeIn ) + FadeIn(); + } + else + { + BOOL bFadeIn = ( pEmptyWin->nState & 2 ) != 0; + pEmptyWin->bFadeIn = FALSE; + pEmptyWin->Actualize(); +#ifdef DBG_UTIL + if ( !bPinned || !pEmptyWin->bFadeIn ) + { + DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" ); + } + else + { + DBG_TRACE( "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" ); + } +#endif + pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign, TRUE )->nVisible = CHILD_VISIBLE; + pWorkWin->ArrangeChilds_Impl(); + if ( bFadeIn ) + FadeIn(); + } + + pWorkWin->ShowChilds_Impl(); + } + + if ( bUpdateMode ) + SetUpdateMode( TRUE ); + bLocked = FALSE; +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::RemoveWindow( SfxDockingWindow* pDockWin, BOOL bHide ) + +/* [Beschreibung] + + Entfernt ein DockingWindow. Wenn es das letzte war, wird das SplitWindow + gehidet. +*/ +{ + USHORT nSet = GetSet( pDockWin->GetType() ); + + // Splitwindows werden im SFX einmal angelegt und nach dem Entfernen + // des letzten DockingWindows unsichtbar gemacht. + if ( GetItemCount( nSet ) == 1 && GetItemCount( 0 ) == 1 ) + { + // Das Neuarrangieren am WorkWindow wird vom SfxDockingwindow + // veranla\st! + Hide(); + pEmptyWin->aTimer.Stop(); + USHORT nRealState = pEmptyWin->nState; + FadeOut_Impl(); + pEmptyWin->Hide(); +#ifdef DBG_UTIL + if ( !bPinned || !pEmptyWin->bFadeIn ) + { + DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" ); + } + else + { + DBG_TRACE( "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" ); + } +#endif + pWorkWin->ReleaseChild_Impl( *GetSplitWindow() ); + pEmptyWin->nState = nRealState; + pWorkWin->ArrangeAutoHideWindows( this ); + } + + SfxDock_Impl *pDock=0; + USHORT nCount = pDockArr->Count(); + for ( USHORT n=0; n<nCount; n++ ) + { + pDock = (*pDockArr)[n]; + if ( pDock->nType == pDockWin->GetType() ) + { + pDock->pWin = 0; + pDock->bHide = bHide; + break; + } + } + + // Fenster removen, und wenn es das letzte der Zeile war, auch die Zeile + // ( Zeile = ItemSet ) + BOOL bUpdateMode = IsUpdateMode(); + if ( bUpdateMode ) + SetUpdateMode( FALSE ); + bLocked = TRUE; + + RemoveItem( pDockWin->GetType() ); + + if ( nSet && !GetItemCount( nSet ) ) + RemoveItem( nSet ); + + if ( bUpdateMode ) + SetUpdateMode( TRUE ); + bLocked = FALSE; +}; + +//------------------------------------------------------------------------- + +BOOL SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow, + USHORT& rLine, USHORT& rPos ) const +/* [Beschreibung] + + Liefert die Id des Itemsets und die des Items f"ur das "ubergebene + DockingWindow in der alten Zeilen/Spalten-Bezeichnung zur"uck. +*/ + +{ + USHORT nSet = GetSet ( pWindow->GetType() ); + if ( nSet == SPLITWINDOW_ITEM_NOTFOUND ) + return FALSE; + + rPos = GetItemPos( pWindow->GetType(), nSet ); + rLine = GetItemPos( nSet ); + return TRUE; +} + +//------------------------------------------------------------------------- + +BOOL SfxSplitWindow::GetWindowPos( const Point& rTestPos, + USHORT& rLine, USHORT& rPos ) const +/* [Beschreibung] + + Liefert die Id des Itemsets und die des Items f"ur das DockingWindow + an der "ubergebenen Position in der alten Zeilen/Spalten-Bezeichnung + zur"uck. +*/ + +{ + USHORT nId = GetItemId( rTestPos ); + if ( nId == 0 ) + return FALSE; + + USHORT nSet = GetSet ( nId ); + rPos = GetItemPos( nId, nSet ); + rLine = GetItemPos( nSet ); + return TRUE; +} + +//------------------------------------------------------------------------- + +USHORT SfxSplitWindow::GetLineCount() const + +/* [Beschreibung] + + Liefert die Zeilenzahl = Zahl der Sub-Itemsets im Root-Set. +*/ +{ + return GetItemCount( 0 ); +} + +//------------------------------------------------------------------------- + +long SfxSplitWindow::GetLineSize( USHORT nLine ) const + +/* [Beschreibung] + + Liefert die "Zeilenh"ohe" des nLine-ten Itemsets. +*/ +{ + USHORT nId = GetItemId( nLine ); + return GetItemSize( nId ); +} + +//------------------------------------------------------------------------- + +USHORT SfxSplitWindow::GetWindowCount( USHORT nLine ) const + +/* [Beschreibung] + + Liefert die +*/ +{ + USHORT nId = GetItemId( nLine ); + return GetItemCount( nId ); +} + +//------------------------------------------------------------------------- + +USHORT SfxSplitWindow::GetWindowCount() const + +/* [Beschreibung] + + Liefert die Gesamtzahl aller Fenstert +*/ +{ + return GetItemCount( 0 ); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::Command( const CommandEvent& rCEvt ) +{ + SplitWindow::Command( rCEvt ); +} + +//------------------------------------------------------------------------- + +IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer) +{ + if ( pTimer ) + pTimer->Stop(); + + if ( CursorIsOverRect( FALSE ) || !pTimer ) + { + // Wenn der Mauszeiger innerhalb des Fensters liegt, SplitWindow anzeigen + // und Timer zum Schlie\sen aufsetzen + pEmptyWin->bAutoHide = TRUE; + if ( !IsVisible() ) + pEmptyWin->FadeIn(); + + pEmptyWin->aLastPos = GetPointerPosPixel(); + pEmptyWin->aTimer.Start(); + } + else if ( pEmptyWin->bAutoHide ) + { + if ( GetPointerPosPixel() != pEmptyWin->aLastPos ) + { + // Die Maus wurd innerhalb der Timerlaugzeit bewegt, also erst einmal + // nichts tun + pEmptyWin->aLastPos = GetPointerPosPixel(); + pEmptyWin->aTimer.Start(); + return 0L; + } + + // Speziell f"ur TF_AUTOSHOW_ON_MOUSEMOVE : + // Wenn das Fenster nicht sichtbar ist, gibt es nichts zu tun + // (Benutzer ist einfach mit der Maus "uber pEmptyWin gefahren) + if ( IsVisible() ) + { + pEmptyWin->bEndAutoHide = FALSE; + if ( !Application::IsInModalMode() && + !PopupMenu::IsInExecute() && + !pEmptyWin->bSplit && !HasChildPathFocus( TRUE ) ) + { + // W"ahrend ein modaler Dialog oder ein Popupmenu offen sind + // oder w"ahrend des Splittens auf keinen Fall zumachen; auch + // solange eines der Children den Focus hat, bleibt das + // das Fenster offen + pEmptyWin->bEndAutoHide = TRUE; + } + + if ( pEmptyWin->bEndAutoHide ) + { + // Von mir aus kann Schlu\s sein mit AutoShow + // Aber vielleicht will noch ein anderes SfxSplitWindow offen bleiben, + // dann bleiben auch alle anderen offen + if ( !pWorkWin->IsAutoHideMode( this ) ) + { + FadeOut_Impl(); + pWorkWin->ArrangeAutoHideWindows( this ); + } + else + { + pEmptyWin->aLastPos = GetPointerPosPixel(); + pEmptyWin->aTimer.Start(); + } + } + else + { + pEmptyWin->aLastPos = GetPointerPosPixel(); + pEmptyWin->aTimer.Start(); + } + } + } + + return 0L; +} + +//------------------------------------------------------------------------- + +BOOL SfxSplitWindow::CursorIsOverRect( BOOL bForceAdding ) const +{ + BOOL bVisible = IsVisible(); + + // Auch das kollabierte SplitWindow ber"ucksichtigen + Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() ); + Size aSize = pEmptyWin->GetSizePixel(); + + if ( bForceAdding ) + { + // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os + aPos.X() -= nPixel; + aPos.Y() -= nPixel; + aSize.Width() += 2 * nPixel; + aSize.Height() += 2 * nPixel; + } + + Rectangle aRect( aPos, aSize ); + + if ( bVisible ) + { + Point aVisPos = GetPosPixel(); + Size aVisSize = GetSizePixel(); + + // Um +/- ein paar Pixel erweitern, sonst ist es zu nerv"os + aVisPos.X() -= nPixel; + aVisPos.Y() -= nPixel; + aVisSize.Width() += 2 * nPixel; + aVisSize.Height() += 2 * nPixel; + + Rectangle aVisRect( aVisPos, aVisSize ); + aRect = aRect.GetUnion( aVisRect ); + } + + if ( aRect.IsInside( OutputToScreenPixel( ((Window*)this)->GetPointerPosPixel() ) ) ) + return TRUE; + return FALSE; +} + +//------------------------------------------------------------------------- + +SplitWindow* SfxSplitWindow::GetSplitWindow() +{ + if ( !bPinned || !pEmptyWin->bFadeIn ) + return pEmptyWin; + return this; +} + +//------------------------------------------------------------------------- +BOOL SfxSplitWindow::IsFadeIn() const +{ + return pEmptyWin->bFadeIn; +} + +BOOL SfxSplitWindow::IsAutoHide( BOOL bSelf ) const +{ + return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide; +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::SetPinned_Impl( BOOL bOn ) +{ + if ( bPinned == bOn ) + return; + + bPinned = bOn; + if ( GetItemCount( 0 ) == 0 ) + return; + + if ( !bOn ) + { + pEmptyWin->nState |= 1; + if ( pEmptyWin->bFadeIn ) + { + // Ersatzfenster anmelden + DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" ); + pWorkWin->ReleaseChild_Impl( *this ); + Hide(); + pEmptyWin->Actualize(); + DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" ); + pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, TRUE )->nVisible = CHILD_VISIBLE; + } + + Point aPos( GetPosPixel() ); + aPos = GetParent()->OutputToScreenPixel( aPos ); + SetFloatingPos( aPos ); + SetFloatingMode( TRUE ); + GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() ); + + if ( pEmptyWin->bFadeIn ) + Show(); + } + else + { + pEmptyWin->nState &= ~1; + SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() ); + SetFloatingMode( FALSE ); + + if ( pEmptyWin->bFadeIn ) + { + // Ersatzfenster abmelden + DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" ); + pWorkWin->ReleaseChild_Impl( *pEmptyWin ); + pEmptyWin->Hide(); + DBG_TRACE( "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" ); + pWorkWin->RegisterChild_Impl( *this, eAlign, TRUE )->nVisible = CHILD_VISIBLE; + } + } + + SetAutoHideState( !bPinned ); + pEmptyWin->SetAutoHideState( !bPinned ); +} + +//------------------------------------------------------------------------- + +void SfxSplitWindow::SetFadeIn_Impl( BOOL bOn ) +{ + if ( bOn == pEmptyWin->bFadeIn ) + return; + + if ( GetItemCount( 0 ) == 0 ) + return; + + pEmptyWin->bFadeIn = bOn; + if ( bOn ) + { + pEmptyWin->nState |= 2; + if ( IsFloatingMode() ) + { + // FloatingWindow ist nicht sichtbar, also anzeigen + pWorkWin->ArrangeAutoHideWindows( this ); + Show(); + } + else + { + DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" ); + pWorkWin->ReleaseChild_Impl( *pEmptyWin ); + pEmptyWin->Hide(); + DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" ); + pWorkWin->RegisterChild_Impl( *this, eAlign, TRUE )->nVisible = CHILD_VISIBLE; + pWorkWin->ArrangeChilds_Impl(); + pWorkWin->ShowChilds_Impl(); + } + } + else + { + pEmptyWin->bAutoHide = FALSE; + pEmptyWin->nState &= ~2; + if ( !IsFloatingMode() ) + { + // Das Fenster "schwebt" nicht, soll aber ausgeblendet werden, + DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" ); + pWorkWin->ReleaseChild_Impl( *this ); + Hide(); + pEmptyWin->Actualize(); + DBG_TRACE( "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" ); + pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign, TRUE )->nVisible = CHILD_VISIBLE; + pWorkWin->ArrangeChilds_Impl(); + pWorkWin->ShowChilds_Impl(); + pWorkWin->ArrangeAutoHideWindows( this ); + } + else + { + Hide(); + pWorkWin->ArrangeAutoHideWindows( this ); + } + } +} + +void SfxSplitWindow::AutoHide() +{ + // Wenn dieser Handler am "echten" SplitWindow aufgerufen wird, ist es + // entweder angedockt und soll "schwebend" angezeigt werden oder umgekehrt + if ( !bPinned ) + { + // Es "schwebt", also wieder andocken + SetPinned_Impl( TRUE ); + pWorkWin->ArrangeChilds_Impl(); + } + else + { + // In den "Schwebezustand" bringen + SetPinned_Impl( FALSE ); + pWorkWin->ArrangeChilds_Impl(); + pWorkWin->ArrangeAutoHideWindows( this ); + } + + pWorkWin->ShowChilds_Impl(); + SaveConfig_Impl(); +} + +void SfxSplitWindow::FadeOut_Impl() +{ + if ( pEmptyWin->aTimer.IsActive() ) + { + pEmptyWin->bAutoHide = FALSE; + pEmptyWin->aTimer.Stop(); + } + + SetFadeIn_Impl( FALSE ); + Show_Impl(); +} + +void SfxSplitWindow::FadeOut() +{ + FadeOut_Impl(); + SaveConfig_Impl(); +} + +void SfxSplitWindow::FadeIn() +{ + SetFadeIn_Impl( TRUE ); + Show_Impl(); +} + +void SfxSplitWindow::Show_Impl() +{ + USHORT nCount = pDockArr->Count(); + for ( USHORT n=0; n<nCount; n++ ) + { + SfxDock_Impl *pDock = (*pDockArr)[n]; + if ( pDock->pWin ) + pDock->pWin->FadeIn( pEmptyWin->bFadeIn ); + } +} +/* +void SfxSplitWindow::Pin_Impl( BOOL bPin ) +{ + if ( bPinned != bPin ) + AutoHide(); +} +*/ +BOOL SfxSplitWindow::ActivateNextChild_Impl( BOOL bForward ) +{ + // Wenn kein pActive, auf erstes bzw. letztes Fenster gehen ( bei !bForward wird erst in der loop dekrementiert ) + USHORT nCount = pDockArr->Count(); + USHORT n = bForward ? 0 : nCount; + + // Wenn Focus innerhalb, dann ein Fenster vor oder zur"uck, wenn m"oglich + if ( pActive ) + { + // Aktives Fenster ermitteln + for ( n=0; n<nCount; n++ ) + { + SfxDock_Impl *pD = (*pDockArr)[n]; + if ( pD->pWin && pD->pWin->HasChildPathFocus() ) + break; + } + + if ( bForward ) + // ein Fenster weiter ( wenn dann n>nCount, wird die Schleife unten gar nicht durchlaufen ) + n++; + } + + if ( bForward ) + { + // N"achstes Fenster suchen + for ( USHORT nNext=n; nNext<nCount; nNext++ ) + { + SfxDock_Impl *pD = (*pDockArr)[nNext]; + if ( pD->pWin ) + { + pD->pWin->GrabFocus(); + return TRUE; + } + } + } + else + { + // Vorheriges Fenster suchen + for ( USHORT nNext=n; nNext--; ) + { + SfxDock_Impl *pD = (*pDockArr)[nNext]; + if ( pD->pWin ) + { + pD->pWin->GrabFocus(); + return TRUE; + } + } + } + + return FALSE; +} + +void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin ) +{ + pActive = pWin; + pWorkWin->SetActiveChild_Impl( this ); +} + + diff --git a/sfx2/source/dialog/srchdlg.cxx b/sfx2/source/dialog/srchdlg.cxx new file mode 100644 index 000000000000..0134b8d58bfa --- /dev/null +++ b/sfx2/source/dialog/srchdlg.cxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include "srchdlg.hxx" +#include "sfxresid.hxx" +#include <sfx2/sfxuno.hxx> + +#include "srchdlg.hrc" +#include "dialog.hrc" +#include <tools/debug.hxx> +#include <unotools/viewoptions.hxx> + +using namespace ::com::sun::star::uno; + +// ============================================================================ + +namespace sfx2 { + +#define USERITEM_NAME DEFINE_CONST_OUSTRING("UserItem") +#define MAX_SAVE_COUNT (USHORT)10 + +// ============================================================================ +// SearchDialog +// ============================================================================ + +SearchDialog::SearchDialog( Window* pWindow, const ::rtl::OUString& rConfigName ) : + + ModelessDialog( pWindow, SfxResId( RID_DLG_SEARCH ) ), + + m_aSearchLabel ( this, SfxResId( FT_SEARCH ) ), + m_aSearchEdit ( this, SfxResId( ED_SEARCH ) ), + m_aWholeWordsBox ( this, SfxResId( CB_WHOLEWORDS ) ), + m_aMatchCaseBox ( this, SfxResId( CB_MATCHCASE ) ), + m_aWrapAroundBox ( this, SfxResId( CB_WRAPAROUND ) ), + m_aBackwardsBox ( this, SfxResId( CB_BACKWARDS ) ), + m_aFindBtn ( this, SfxResId( PB_FIND ) ), + m_aCancelBtn ( this, SfxResId( PB_CANCELFIND ) ), + m_sToggleText ( SfxResId( STR_TOGGLE ) ), + m_sConfigName ( rConfigName ), + m_bIsConstructed ( false ) + +{ + FreeResource(); + + // set handler + m_aFindBtn.SetClickHdl( LINK( this, SearchDialog, FindHdl ) ); + m_aBackwardsBox.SetClickHdl( LINK( this, SearchDialog, ToggleHdl ) ); + // load config: old search strings and the status of the check boxes + LoadConfig(); + // we need to change the text of the WrapAround box, depends on the status of the Backwards box + if ( m_aBackwardsBox.IsChecked() ) + ToggleHdl( &m_aBackwardsBox ); + // the search edit should have the focus + m_aSearchEdit.GrabFocus(); +} + +SearchDialog::~SearchDialog() +{ + SaveConfig(); + m_aCloseHdl.Call( NULL ); +} + +void SearchDialog::LoadConfig() +{ + SvtViewOptions aViewOpt( E_DIALOG, m_sConfigName ); + if ( aViewOpt.Exists() ) + { + m_sWinState = ByteString( aViewOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US ); + Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME ); + ::rtl::OUString aTemp; + if ( aUserItem >>= aTemp ) + { + String sUserData( aTemp ); + DBG_ASSERT( sUserData.GetTokenCount() == 5, "invalid config data" ); + xub_StrLen nIdx = 0; + String sSearchText = sUserData.GetToken( 0, ';', nIdx ); + m_aWholeWordsBox.Check( sUserData.GetToken( 0, ';', nIdx ).ToInt32() == 1 ); + m_aMatchCaseBox.Check( sUserData.GetToken( 0, ';', nIdx ).ToInt32() == 1 ); + m_aWrapAroundBox.Check( sUserData.GetToken( 0, ';', nIdx ).ToInt32() == 1 ); + m_aBackwardsBox.Check( sUserData.GetToken( 0, ';', nIdx ).ToInt32() == 1 ); + + nIdx = 0; + while ( nIdx != STRING_NOTFOUND ) + m_aSearchEdit.InsertEntry( sSearchText.GetToken( 0, '\t', nIdx ) ); + m_aSearchEdit.SelectEntryPos(0); + } + } + else + m_aWrapAroundBox.Check( TRUE ); +} + +void SearchDialog::SaveConfig() +{ + SvtViewOptions aViewOpt( E_DIALOG, m_sConfigName ); + aViewOpt.SetWindowState( rtl::OUString::createFromAscii( m_sWinState.GetBuffer() ) ); + String sUserData; + USHORT i = 0, nCount = Min( m_aSearchEdit.GetEntryCount(), MAX_SAVE_COUNT ); + for ( ; i < nCount; ++i ) + { + sUserData += m_aSearchEdit.GetEntry(i); + sUserData += '\t'; + } + sUserData.EraseTrailingChars( '\t' ); + sUserData += ';'; + sUserData += String::CreateFromInt32( m_aWholeWordsBox.IsChecked() ? 1 : 0 ); + sUserData += ';'; + sUserData += String::CreateFromInt32( m_aMatchCaseBox.IsChecked() ? 1 : 0 ); + sUserData += ';'; + sUserData += String::CreateFromInt32( m_aWrapAroundBox.IsChecked() ? 1 : 0 ); + sUserData += ';'; + sUserData += String::CreateFromInt32( m_aBackwardsBox.IsChecked() ? 1 : 0 ); + + Any aUserItem = makeAny( ::rtl::OUString( sUserData ) ); + aViewOpt.SetUserItem( USERITEM_NAME, aUserItem ); +} + +IMPL_LINK( SearchDialog, FindHdl, PushButton*, EMPTYARG ) +{ + String sSrchTxt = m_aSearchEdit.GetText(); + USHORT nPos = m_aSearchEdit.GetEntryPos( sSrchTxt ); + if ( nPos > 0 && nPos != COMBOBOX_ENTRY_NOTFOUND ) + m_aSearchEdit.RemoveEntry( nPos ); + if ( nPos > 0 ) + m_aSearchEdit.InsertEntry( sSrchTxt, 0 ); + m_aFindHdl.Call( this ); + return 0; +} + +IMPL_LINK( SearchDialog, ToggleHdl, CheckBox*, EMPTYARG ) +{ + String sTemp = m_aWrapAroundBox.GetText(); + m_aWrapAroundBox.SetText( m_sToggleText ); + m_sToggleText = sTemp; + return 0; +} + +void SearchDialog::SetFocusOnEdit() +{ + Selection aSelection( 0, m_aSearchEdit.GetText().Len() ); + m_aSearchEdit.SetSelection( aSelection ); + m_aSearchEdit.GrabFocus(); +} + +BOOL SearchDialog::Close() +{ + BOOL bRet = ModelessDialog::Close(); + m_aCloseHdl.Call( this ); + return bRet; +} + +void SearchDialog::StateChanged( StateChangedType nStateChange ) +{ + if ( nStateChange == STATE_CHANGE_INITSHOW ) + { + if ( m_sWinState.Len() ) + SetWindowState( m_sWinState ); + m_bIsConstructed = TRUE; + } + + ModelessDialog::StateChanged( nStateChange ); +} + +void SearchDialog::Move() +{ + ModelessDialog::Move(); + if ( m_bIsConstructed && IsReallyVisible() ) + m_sWinState = GetWindowState( WINDOWSTATE_MASK_POS | WINDOWSTATE_MASK_STATE ); +} + +// ============================================================================ + +} // namespace sfx2 + +// ============================================================================ + diff --git a/sfx2/source/dialog/srchdlg.hrc b/sfx2/source/dialog/srchdlg.hrc new file mode 100644 index 000000000000..55fe9ce47d26 --- /dev/null +++ b/sfx2/source/dialog/srchdlg.hrc @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SFX_SRCHDLG_HRC_ +#define _SFX_SRCHDLG_HRC_ + +#define FT_SEARCH 10 +#define ED_SEARCH 11 +#define FL_OPTIONS 12 +#define CB_WHOLEWORDS 13 +#define CB_MATCHCASE 14 +#define CB_WRAPAROUND 15 +#define CB_BACKWARDS 16 +#define PB_FIND 17 +#define PB_CANCELFIND 18 + +#define STR_TOGGLE 50 + +#endif // _SFX_SRCHDLG_HRC_ + diff --git a/sfx2/source/dialog/srchdlg.src b/sfx2/source/dialog/srchdlg.src new file mode 100644 index 000000000000..0947f3932981 --- /dev/null +++ b/sfx2/source/dialog/srchdlg.src @@ -0,0 +1,110 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SFX_SRCHDLG_HRC_ +#include "srchdlg.hrc" +#endif +#ifndef _SFX_DIALOG_HRC +#include "dialog.hrc" +#endif +#ifndef _SFX_HELPID_HRC +#include "helpid.hrc" +#endif + +ModelessDialog RID_DLG_SEARCH +{ + HelpId = HID_SEARCHDIALOG; + OutputSize = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Hide = TRUE; + Size = MAP_APPFONT( 218, 84 ); + Text [ en-US ] = "Find on this Page"; + FixedText FT_SEARCH + { + Pos = MAP_APPFONT( 6, 3 ); + Size = MAP_APPFONT( 150, 8 ); + Text [ en-US ] = "~Search for"; + }; + ComboBox ED_SEARCH + { + Border = TRUE; + Pos = MAP_APPFONT( 6, 14 ); + Size = MAP_APPFONT( 150, 50 ); + DropDown = TRUE ; + TabStop = TRUE; + }; + CheckBox CB_WHOLEWORDS + { + Pos = MAP_APPFONT( 6, 29 ); + Size = MAP_APPFONT( 150, 10 ); + Text [ en-US ] = "~Whole words only" ; + TabStop = TRUE; + }; + CheckBox CB_MATCHCASE + { + Pos = MAP_APPFONT( 6, 42 ); + Size = MAP_APPFONT( 150, 10 ); + Text[ en-US ] = "~Match case"; + TabStop = TRUE; + }; + CheckBox CB_WRAPAROUND + { + Pos = MAP_APPFONT( 6, 55 ); + Size = MAP_APPFONT( 150, 10 ); + Text [ en-US ] = "Wrap ~around" ; + TabStop = TRUE; + }; + CheckBox CB_BACKWARDS + { + Pos = MAP_APPFONT( 6, 68 ); + Size = MAP_APPFONT( 150, 10 ); + Text [ en-US ] = "~Backwards" ; + TabStop = TRUE; + }; + PushButton PB_FIND + { + Pos = MAP_APPFONT( 162, 6 ); + Size = MAP_APPFONT( 50, 14 ); + Text [ en-US ] = "~Find" ; + TabStop = TRUE; + DefButton = TRUE ; + }; + CancelButton PB_CANCELFIND + { + Pos = MAP_APPFONT( 162, 23 ); + Size = MAP_APPFONT( 50, 14 ); + Text [ en-US ] = "~Close" ; + TabStop = TRUE; + }; + + String STR_TOGGLE + { + Text [ en-US ] = "Wrap ~around" ; + }; +}; + diff --git a/sfx2/source/dialog/styfitem.cxx b/sfx2/source/dialog/styfitem.cxx new file mode 100644 index 000000000000..a33677c6b2ae --- /dev/null +++ b/sfx2/source/dialog/styfitem.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// INCLUDE --------------------------------------------------------------- + +#ifndef GCC +#endif + +#include <sfx2/styfitem.hxx> +#include <svtools/localresaccess.hxx> +#include <tools/debug.hxx> + +// ----------------------------------------------------------------------- + +class SfxStyleFamilyItem_Impl +{ + Bitmap aBitmap; + Image aImage; +}; + +// ----------------------------------------------------------------------- + +// Implementierung des Resource-Konstruktors + +SfxStyleFamilyItem::SfxStyleFamilyItem( const ResId &rResId ) : + + Resource( rResId.SetRT( RSC_SFX_STYLE_FAMILY_ITEM ) ) + +{ + ULONG nMask = ReadLongRes(); + + if(nMask & RSC_SFX_STYLE_ITEM_LIST) + { + ULONG nCount = ReadLongRes(); + for( ULONG i = 0; i < nCount; i++ ) + { + SfxFilterTupel *pTupel = new SfxFilterTupel; + pTupel->aName = ReadStringRes(); + long lFlags = ReadLongRes(); + pTupel->nFlags = (USHORT)lFlags; + aFilterList.Insert(pTupel, LIST_APPEND); + } + } + if(nMask & RSC_SFX_STYLE_ITEM_BITMAP) + { + aBitmap = Bitmap(ResId((RSHEADER_TYPE *)GetClassRes(),*rResId.GetResMgr())); + IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) ); + } + if(nMask & RSC_SFX_STYLE_ITEM_TEXT) + { + aText = ReadStringRes(); + } + if(nMask & RSC_SFX_STYLE_ITEM_HELPTEXT) + { + aHelpText = ReadStringRes(); + } + if(nMask & RSC_SFX_STYLE_ITEM_STYLEFAMILY) + { + nFamily = (USHORT)ReadLongRes(); + } + else + nFamily = SFX_STYLE_FAMILY_PARA; + if(nMask & RSC_SFX_STYLE_ITEM_IMAGE) + { + aImage = Image(ResId((RSHEADER_TYPE *)GetClassRes(),*rResId.GetResMgr())); + IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) ); + } + else + aImage = Image(aBitmap); +} + +// ----------------------------------------------------------------------- + +// Destruktor; gibt interne Daten frei + +SfxStyleFamilyItem::~SfxStyleFamilyItem() +{ + SfxFilterTupel *pTupel = aFilterList.First(); + while(pTupel) + { + delete pTupel; + pTupel = aFilterList.Next(); + } +} + +// ----------------------------------------------------------------------- + +// Implementierung des Resource-Konstruktors + +SfxStyleFamilies::SfxStyleFamilies( const ResId& rResId ) : + + Resource( rResId.SetRT( RSC_SFX_STYLE_FAMILIES ).SetAutoRelease( FALSE ) ), + aEntryList( 4, 1 ) +{ + ULONG nCount = ReadLongRes(); + for( ULONG i = 0; i < nCount; i++ ) + { + const ResId aResId((RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr()); + SfxStyleFamilyItem *pItem = new SfxStyleFamilyItem(aResId); + IncrementRes( GetObjSizeRes( (RSHEADER_TYPE *)GetClassRes() ) ); + aEntryList.Insert(pItem, LIST_APPEND); + } + + FreeResource(); + + updateImages( rResId, BMP_COLOR_NORMAL ); +} + +// ----------------------------------------------------------------------- + +// Destruktor; gibt interne Daten frei + +SfxStyleFamilies::~SfxStyleFamilies() +{ + SfxStyleFamilyItem *pItem = aEntryList.First(); + + while(pItem) + { + delete pItem; + pItem = aEntryList.Next(); + } +} + + +// ----------------------------------------------------------------------- + +sal_Bool SfxStyleFamilies::updateImages( const ResId& _rId, const BmpColorMode _eMode ) +{ + sal_Bool bSuccess = sal_False; + + { + ::svt::OLocalResourceAccess aLocalRes( _rId ); + + // check if the image list is present + ResId aImageListId( (sal_uInt16)_eMode + 1, *_rId.GetResMgr() ); + aImageListId.SetRT( RSC_IMAGELIST ); + + if ( aLocalRes.IsAvailableRes( aImageListId ) ) + { // there is such a list + ImageList aImages( aImageListId ); + + // number of styles items/images + sal_uInt16 nCount = aImages.GetImageCount( ); + DBG_ASSERT( Count() == nCount, "SfxStyleFamilies::updateImages: found the image list, but missing some bitmaps!" ); + if ( nCount > Count() ) + nCount = Count(); + + // set the images on the items + for ( sal_uInt16 i = 0; i < nCount; ++i ) + { + SfxStyleFamilyItem* pItem = static_cast< SfxStyleFamilyItem* >( aEntryList.GetObject( i ) ); + pItem->SetImage( aImages.GetImage( aImages.GetImageId( i ) ) ); + } + + bSuccess = sal_True; + } + } + + return bSuccess; +} diff --git a/sfx2/source/dialog/styledlg.cxx b/sfx2/source/dialog/styledlg.cxx new file mode 100644 index 000000000000..ff6406f0d5d3 --- /dev/null +++ b/sfx2/source/dialog/styledlg.cxx @@ -0,0 +1,176 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// include --------------------------------------------------------------- +#include <svl/whiter.hxx> +#include <svl/style.hxx> +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#ifndef GCC +#endif + +#include <sfx2/styledlg.hxx> +#include <sfx2/mgetempl.hxx> +#include "sfxresid.hxx" +#include <sfx2/sfxuno.hxx> + +#include "dialog.hrc" + +// class SfxStyleDialog -------------------------------------------------- + +SfxStyleDialog::SfxStyleDialog +( + Window* pParent, // Parent + const ResId& rResId, // ResId + SfxStyleSheetBase& rStyle, // zu bearbeitendes StyleSheet + BOOL bFreeRes, // Flag Resourcen freigeben + const String* pUserBtnTxt +) : + +/* [Beschreibung] + + Konstruktor: Verwalten-TabPage zuf"ugen, ExampleSet vom Style setzen. +*/ + + SfxTabDialog( pParent, rResId, + rStyle.GetItemSet().Clone(), + // auch ohne ParentSupport TRUE "ubergeben, aber erweitert + // um den StandardButton zu unterdr"ucken + rStyle.HasParentSupport() ? TRUE : 2, + pUserBtnTxt ), + + pStyle( &rStyle ) + +{ + AddTabPage( ID_TABPAGE_MANAGESTYLES, + String( SfxResId( STR_TABPAGE_MANAGESTYLES ) ), + SfxManageStyleSheetPage::Create, 0, FALSE, 0 ); + + // bei neuer Vorlage immer die Verwaltungsseite als aktuelle + // Seite setzen + + if( !rStyle.GetName().Len() ) + SetCurPageId( ID_TABPAGE_MANAGESTYLES ); + else + { + String sTxt( GetText() ); + sTxt += DEFINE_CONST_UNICODE(": ") ; + sTxt += rStyle.GetName(); + SetText( sTxt ); + } + delete pExampleSet; // im SfxTabDialog::Ctor() schon angelegt + pExampleSet = &pStyle->GetItemSet(); + + if ( bFreeRes ) + FreeResource(); + GetCancelButton().SetClickHdl( LINK(this, SfxStyleDialog, CancelHdl) ); +} + +// ----------------------------------------------------------------------- + +SfxStyleDialog::~SfxStyleDialog() + +/* [Beschreibung] + + Destruktor: ExampleSet auf NULL setzen, damit der SfxTabDialog nicht den + Set vom Style l"oscht. +*/ + +{ + pExampleSet = 0; + pStyle = 0; + delete GetInputSetImpl(); +} + +// ----------------------------------------------------------------------- + +const SfxItemSet* SfxStyleDialog::GetRefreshedSet() + +/* [Beschreibung] + + Diese wird gerufen, wenn <SfxTabPage::DeactivatePage(SfxItemSet *)> + <SfxTabPage::REFRESH_SET> liefert. +*/ + +{ + return GetInputSetImpl(); +} + +// ----------------------------------------------------------------------- + +short SfxStyleDialog::Ok() + +/* [Beschreibung] + + "Uberladen, damit immer RET_OK zur"uckgegeben wird. +*/ + +{ + SfxTabDialog::Ok(); + return RET_OK; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxStyleDialog, CancelHdl, Button *, pButton ) + +/* [Beschreibung] + + Wenn der Dialog abgebrochen wurde, m"ussen alle schon eingestellten + Attribute wieder zur"uckgesetzt werden. +*/ + +{ + (void)pButton; //unused + SfxTabPage* pPage = GetTabPage( ID_TABPAGE_MANAGESTYLES ); + + const SfxItemSet* pInSet = GetInputSetImpl(); + SfxWhichIter aIter( *pInSet ); + USHORT nWhich = aIter.FirstWhich(); + + while ( nWhich ) + { + SfxItemState eState = pInSet->GetItemState( nWhich, FALSE ); + + if ( SFX_ITEM_DEFAULT == eState ) + pExampleSet->ClearItem( nWhich ); + else + pExampleSet->Put( pInSet->Get( nWhich ) ); + nWhich = aIter.NextWhich(); + } + + if ( pPage ) + pPage->Reset( *GetInputSetImpl() ); + EndDialog( RET_CANCEL ); + return 0; +} + + diff --git a/sfx2/source/dialog/tabdlg.cxx b/sfx2/source/dialog/tabdlg.cxx new file mode 100644 index 000000000000..93c2e0e09595 --- /dev/null +++ b/sfx2/source/dialog/tabdlg.cxx @@ -0,0 +1,1798 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <limits.h> +#include <stdlib.h> +#include <vcl/msgbox.hxx> +#include <unotools/viewoptions.hxx> + +#define _SVSTDARR_USHORTS +#include <svl/svstdarr.hxx> + +#include "appdata.hxx" +#include "sfxtypes.hxx" +#include <sfx2/minarray.hxx> +#include <sfx2/tabdlg.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/app.hxx> +#include "sfxresid.hxx" +#include "sfxhelp.hxx" +#include <sfx2/ctrlitem.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/itemconnect.hxx> + +#include "dialog.hrc" +#include "helpid.hrc" + +#if ENABLE_LAYOUT_SFX_TABDIALOG +#undef TabPage +#undef SfxTabPage +#define SfxTabPage ::SfxTabPage +#undef SfxTabDialog +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + +using namespace ::com::sun::star::uno; +using namespace ::rtl; + +#define USERITEM_NAME OUString::createFromAscii( "UserItem" ) + +TYPEINIT1(LAYOUT_NS_SFX_TABDIALOG SfxTabDialogItem,SfxSetItem); + +struct TabPageImpl +{ + BOOL mbStandard; + sfx::ItemConnectionArray maItemConn; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame; + + TabPageImpl() : mbStandard( FALSE ) {} +}; + +NAMESPACE_LAYOUT_SFX_TABDIALOG + +struct Data_Impl +{ + USHORT nId; // Die ID + CreateTabPage fnCreatePage; // Pointer auf die Factory + GetTabPageRanges fnGetRanges;// Pointer auf die Ranges-Funktion + SfxTabPage* pTabPage; // die TabPage selber + BOOL bOnDemand; // Flag: ItemSet onDemand + BOOL bRefresh; // Flag: Seite mu\s neu initialisiert werden + + // Konstruktor + Data_Impl( USHORT Id, CreateTabPage fnPage, + GetTabPageRanges fnRanges, BOOL bDemand ) : + + nId ( Id ), + fnCreatePage( fnPage ), + fnGetRanges ( fnRanges ), + pTabPage ( 0 ), + bOnDemand ( bDemand ), + bRefresh ( FALSE ) + { + if ( !fnCreatePage ) + { + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + if ( pFact ) + { + fnCreatePage = pFact->GetTabPageCreatorFunc( nId ); + fnGetRanges = pFact->GetTabPageRangesFunc( nId ); + } + } + } +}; + +SfxTabDialogItem::SfxTabDialogItem( const SfxTabDialogItem& rAttr, SfxItemPool* pItemPool ) + : SfxSetItem( rAttr, pItemPool ) +{ +} + +SfxTabDialogItem::SfxTabDialogItem( USHORT nId, const SfxItemSet& rItemSet ) + : SfxSetItem( nId, rItemSet ) +{ +} + +SfxPoolItem* __EXPORT SfxTabDialogItem::Clone(SfxItemPool* pToPool) const +{ + return new SfxTabDialogItem( *this, pToPool ); +} + +SfxPoolItem* __EXPORT SfxTabDialogItem::Create(SvStream& /*rStream*/, USHORT /*nVersion*/) const +{ + DBG_ERROR( "Use it only in UI!" ); + return NULL; +} + +class SfxTabDialogController : public SfxControllerItem +{ + SfxTabDialog* pDialog; + const SfxItemSet* pSet; +public: + SfxTabDialogController( USHORT nSlotId, SfxBindings& rBindings, SfxTabDialog* pDlg ) + : SfxControllerItem( nSlotId, rBindings ) + , pDialog( pDlg ) + , pSet( NULL ) + {} + + ~SfxTabDialogController(); + + DECL_LINK( Execute_Impl, void* ); + virtual void StateChanged( USHORT nSID, SfxItemState eState, const SfxPoolItem* pState ); +}; + +SfxTabDialogController::~SfxTabDialogController() +{ + delete pSet; +} + +IMPL_LINK( SfxTabDialogController, Execute_Impl, void*, pVoid ) +{ + (void)pVoid; //unused + if ( pDialog->OK_Impl() && pDialog->Ok() ) + { + const SfxPoolItem* aItems[2]; + SfxTabDialogItem aItem( GetId(), *pDialog->GetOutputItemSet() ); + aItems[0] = &aItem; + aItems[1] = NULL; + GetBindings().Execute( GetId(), aItems ); + } + + return 0; +} + +void SfxTabDialogController::StateChanged( USHORT /*nSID*/, SfxItemState /*eState*/, const SfxPoolItem* pState ) +{ + const SfxSetItem* pSetItem = PTR_CAST( SfxSetItem, pState ); + if ( pSetItem ) + { + pSet = pDialog->pSet = pSetItem->GetItemSet().Clone(); + BOOL bDialogStarted = FALSE; + for ( USHORT n=0; n<pDialog->aTabCtrl.GetPageCount(); n++ ) + { + USHORT nPageId = pDialog->aTabCtrl.GetPageId( n ); + SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pDialog->aTabCtrl.GetTabPage( nPageId )); + if ( pTabPage ) + { + pTabPage->Reset( pSetItem->GetItemSet() ); + bDialogStarted = TRUE; + } + } + + if ( bDialogStarted ) + pDialog->Show(); + } + else + pDialog->Hide(); +} + +DECL_PTRARRAY(SfxTabDlgData_Impl, Data_Impl *, 4,4) + +struct TabDlg_Impl +{ + BOOL bModified : 1, + bModal : 1, + bInOK : 1, + bHideResetBtn : 1; + SfxTabDlgData_Impl* pData; + + PushButton* pApplyButton; + SfxTabDialogController* pController; + + TabDlg_Impl( BYTE nCnt ) : + + bModified ( FALSE ), + bModal ( TRUE ), + bInOK ( FALSE ), + bHideResetBtn ( FALSE ), + pData ( new SfxTabDlgData_Impl( nCnt ) ), + pApplyButton ( NULL ), + pController ( NULL ) + {} +}; + +Data_Impl* Find( SfxTabDlgData_Impl& rArr, USHORT nId, USHORT* pPos = 0 ); + +Data_Impl* Find( SfxTabDlgData_Impl& rArr, USHORT nId, USHORT* pPos ) +{ + const USHORT nCount = rArr.Count(); + + for ( USHORT i = 0; i < nCount; ++i ) + { + Data_Impl* pObj = rArr[i]; + + if ( pObj->nId == nId ) + { + if ( pPos ) + *pPos = i; + return pObj; + } + } + return 0; +} + +#if !ENABLE_LAYOUT_SFX_TABDIALOG + +void SfxTabPage::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame) +{ + if (pImpl) + pImpl->mxFrame = xFrame; +} + +::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxTabPage::GetFrame() +{ + if (pImpl) + return pImpl->mxFrame; + return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >(); +} + +SfxTabPage::SfxTabPage( Window *pParent, + const ResId &rResId, const SfxItemSet &rAttrSet ) : + +/* [Beschreibung] + + Konstruktor +*/ + + TabPage( pParent, rResId ), + + pSet ( &rAttrSet ), + bHasExchangeSupport ( FALSE ), + pTabDlg ( NULL ), + pImpl ( new TabPageImpl ) + +{ +} +// ----------------------------------------------------------------------- +SfxTabPage:: SfxTabPage( Window *pParent, WinBits nStyle, const SfxItemSet &rAttrSet ) : + TabPage(pParent, nStyle), + pSet ( &rAttrSet ), + bHasExchangeSupport ( FALSE ), + pTabDlg ( NULL ), + pImpl ( new TabPageImpl ) +{ +} +// ----------------------------------------------------------------------- + +SfxTabPage::~SfxTabPage() + +/* [Beschreibung] + + Destruktor +*/ + +{ +#if !ENABLE_LAYOUT + delete pImpl; +#endif /* ENABLE_LAYOUT */ +} + +// ----------------------------------------------------------------------- + +BOOL SfxTabPage::FillItemSet( SfxItemSet& rSet ) +{ + return pImpl->maItemConn.DoFillItemSet( rSet, GetItemSet() ); +} + +// ----------------------------------------------------------------------- + +void SfxTabPage::Reset( const SfxItemSet& rSet ) +{ + pImpl->maItemConn.DoApplyFlags( rSet ); + pImpl->maItemConn.DoReset( rSet ); +} + +// ----------------------------------------------------------------------- + +void SfxTabPage::ActivatePage( const SfxItemSet& ) + +/* [Beschreibung] + + Defaultimplementierung der virtuellen ActivatePage-Methode + Diese wird gerufen, wenn eine Seite des Dialogs den Datenaustausch + zwischen Pages unterst"utzt. + + <SfxTabPage::DeactivatePage(SfxItemSet *)> +*/ + +{ +} + +// ----------------------------------------------------------------------- + +int SfxTabPage::DeactivatePage( SfxItemSet* ) + +/* [Beschreibung] + + Defaultimplementierung der virtuellen DeactivatePage-Methode + Diese wird vor dem Verlassen einer Seite durch den Sfx gerufen; + die Anwendung kann "uber den Returnwert steuern, + ob die Seite verlassen werden soll. + Falls die Seite "uber bHasExchangeSupport + anzeigt, da\s sie einen Datenaustausch zwischen Seiten + unterst"utzt, wird ein Pointer auf das Austausch-Set als + Parameter "ubergeben. Dieser nimmt die Daten f"ur den Austausch + entgegen; das Set steht anschlie\send als Parameter in + <SfxTabPage::ActivatePage(const SfxItemSet &)> zur Verf"ugung. + + [R"uckgabewert] + + LEAVE_PAGE; Verlassen der Seite erlauben +*/ + +{ + return LEAVE_PAGE; +} + +// ----------------------------------------------------------------------- + +void SfxTabPage::FillUserData() + +/* [Beschreibung] + + virtuelle Methode, wird von der Basisklasse im Destruktor gerufen + um spezielle Informationen der TabPage in der Ini-Datei zu speichern. + Beim "Uberladen muss ein String zusammengestellt werden, der mit + <SetUserData()> dann weggeschrieben wird. +*/ + +{ +} + +// ----------------------------------------------------------------------- + +BOOL SfxTabPage::IsReadOnly() const + +/* [Description] + +*/ + +{ + return FALSE; +} + +// ----------------------------------------------------------------------- + +const SfxPoolItem* SfxTabPage::GetItem( const SfxItemSet& rSet, USHORT nSlot, sal_Bool bDeep ) + +/* [Beschreibung] + + static Methode: hiermit wird der Code der TabPage-Implementierungen + vereinfacht. + +*/ + +{ + const SfxItemPool* pPool = rSet.GetPool(); + USHORT nWh = pPool->GetWhich( nSlot, bDeep ); + const SfxPoolItem* pItem = 0; +#ifdef DEBUG + SfxItemState eState; + eState = +#endif + rSet.GetItemState( nWh, TRUE, &pItem ); // -Wall required?? + + if ( !pItem && nWh != nSlot ) + pItem = &pPool->GetDefaultItem( nWh ); + return pItem; +} + +// ----------------------------------------------------------------------- + +const SfxPoolItem* SfxTabPage::GetOldItem( const SfxItemSet& rSet, + USHORT nSlot, sal_Bool bDeep ) + +/* [Beschreibung] + + Diese Methode gibt f"ur Vergleiche den alten Wert eines + Attributs zur"uck. +*/ + +{ + const SfxItemSet& rOldSet = GetItemSet(); + USHORT nWh = GetWhich( nSlot, bDeep ); + const SfxPoolItem* pItem = 0; + + if ( pImpl->mbStandard && rOldSet.GetParent() ) + pItem = GetItem( *rOldSet.GetParent(), nSlot ); + else if ( rSet.GetParent() && + SFX_ITEM_DONTCARE == rSet.GetItemState( nWh ) ) + pItem = GetItem( *rSet.GetParent(), nSlot ); + else + pItem = GetItem( rOldSet, nSlot ); + return pItem; +} + +// ----------------------------------------------------------------------- + +const SfxPoolItem* SfxTabPage::GetExchangeItem( const SfxItemSet& rSet, + USHORT nSlot ) + +/* [Beschreibung] + + Diese Methode gibt f"ur Vergleiche den alten Wert eines + Attributs zur"uck. Dabei wird ber"ucksichtigt, ob der Dialog + gerade mit OK beendet wurde. +*/ + +{ + if ( pTabDlg && !pTabDlg->IsInOK() && pTabDlg->GetExampleSet() ) + return GetItem( *pTabDlg->GetExampleSet(), nSlot ); + else + return GetOldItem( rSet, nSlot ); +} + +// add CHINA001 begin +void SfxTabPage::PageCreated( SfxAllItemSet /*aSet*/ ) +{ + DBG_ASSERT(0, "SfxTabPage::PageCreated should not be called"); +}//CHINA001 +// add CHINA001 end + +// ----------------------------------------------------------------------- + +void SfxTabPage::AddItemConnection( sfx::ItemConnectionBase* pConnection ) +{ + pImpl->maItemConn.AddConnection( pConnection ); +} + +#endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */ + +#if ENABLE_LAYOUT_SFX_TABDIALOG +#undef ResId +#define ResId(id, foo) #id +#undef TabDialog +#define TabDialog(parent, res_id) Dialog (parent, "tab-dialog.xml", "tab-dialog") + +#define aOKBtn(this) aOKBtn (this, "BTN_OK") +#undef PushButton +#define PushButton(this) layout::PushButton (this, "BTN_USER") +#define aCancelBtn(this) aCancelBtn (this, "BTN_CANCEL") +#define aHelpBtn(this) aHelpBtn (this, "BTN_HELP") +#define aResetBtn(this) aResetBtn (this, "BTN_RESET") +#define aBaseFmtBtn(this) aBaseFmtBtn (this, "BTN_BASEFMT") +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + +#define INI_LIST(ItemSetPtr) \ + aTabCtrl ( this, ResId(ID_TABCONTROL,*rResId.GetResMgr() ) ),\ + aOKBtn ( this ),\ + pUserBtn ( pUserButtonText? new PushButton(this): 0 ),\ + aCancelBtn ( this ),\ + aHelpBtn ( this ),\ + aResetBtn ( this ),\ + aBaseFmtBtn ( this ),\ + pSet ( ItemSetPtr ),\ + pOutSet ( 0 ),\ + pImpl ( new TabDlg_Impl( (BYTE)aTabCtrl.GetPageCount() ) ), \ + pRanges ( 0 ), \ + nResId ( rResId.GetId() ), \ + nAppPageId ( USHRT_MAX ), \ + bItemsReset ( FALSE ),\ + bFmt ( bEditFmt ),\ + pExampleSet ( 0 ) + +// ----------------------------------------------------------------------- + +SfxTabDialog::SfxTabDialog + +/* [Beschreibung] + + Konstruktor +*/ + +( + SfxViewFrame* pViewFrame, // Frame, zu dem der Dialog geh"ort + Window* pParent, // Parent-Fenster + const ResId& rResId, // ResourceId + const SfxItemSet* pItemSet, // Itemset mit den Daten; + // kann NULL sein, wenn Pages onDemand + BOOL bEditFmt, // Flag: es werden Vorlagen bearbeitet + // wenn ja -> zus"atzlicher Button f"ur Standard + const String* pUserButtonText // Text fuer BenutzerButton; + // wenn != 0, wird der UserButton erzeugt +) : + TabDialog( pParent, rResId ), + pFrame( pViewFrame ), + INI_LIST(pItemSet) +{ + Init_Impl( bFmt, pUserButtonText ); +} + +// ----------------------------------------------------------------------- + +SfxTabDialog::SfxTabDialog + +/* [Beschreibung] + + Konstruktor, tempor"ar ohne Frame +*/ + +( + Window* pParent, // Parent-Fenster + const ResId& rResId, // ResourceId + const SfxItemSet* pItemSet, // Itemset mit den Daten; kann NULL sein, + // wenn Pages onDemand + BOOL bEditFmt, // Flag: es werden Vorlagen bearbeitet + // wenn ja -> zus"atzlicher Button f"ur Standard + const String* pUserButtonText // Text f"ur BenutzerButton; + // wenn != 0, wird der UserButton erzeugt +) : + TabDialog( pParent, rResId ), + pFrame( 0 ), + INI_LIST(pItemSet) +{ + Init_Impl( bFmt, pUserButtonText ); + DBG_WARNING( "bitte den Ctor mit ViewFrame verwenden" ); +} + +SfxTabDialog::SfxTabDialog + +/* [Beschreibung] + + Konstruktor, tempor"ar ohne Frame +*/ + +( + Window* pParent, // Parent-Fenster + const ResId& rResId, // ResourceId + USHORT nSetId, + SfxBindings& rBindings, + BOOL bEditFmt, // Flag: es werden Vorlagen bearbeitet + // wenn ja -> zus"atzlicher Button f"ur Standard + const String* pUserButtonText // Text f"ur BenutzerButton; + // wenn != 0, wird der UserButton erzeugt +) : + TabDialog( pParent, rResId ), + pFrame( 0 ), + INI_LIST(NULL) +{ + rBindings.ENTERREGISTRATIONS(); + pImpl->pController = new SfxTabDialogController( nSetId, rBindings, this ); + rBindings.LEAVEREGISTRATIONS(); + + EnableApplyButton( TRUE ); + SetApplyHandler( LINK( pImpl->pController, SfxTabDialogController, Execute_Impl ) ); + + rBindings.Invalidate( nSetId ); + rBindings.Update( nSetId ); + DBG_ASSERT( pSet, "No ItemSet!" ); + + Init_Impl( bFmt, pUserButtonText ); +} + +// ----------------------------------------------------------------------- + +#if ENABLE_LAYOUT_SFX_TABDIALOG +#undef ResId +#undef TabDialog +#undef aOKBtn +#undef PushButton +#undef aCancelBtn +#undef aHelpBtn +#undef aResetBtn +#undef aBaseFmtBtn +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + +SfxTabDialog::~SfxTabDialog() +{ + // save settings (screen position and current page) + SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) ); +#if !ENABLE_LAYOUT_SFX_TABDIALOG + aDlgOpt.SetWindowState( OUString::createFromAscii( GetWindowState( WINDOWSTATE_MASK_POS ).GetBuffer() ) ); +#endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */ + aDlgOpt.SetPageID( aTabCtrl.GetCurPageId() ); + + const USHORT nCount = pImpl->pData->Count(); + for ( USHORT i = 0; i < nCount; ++i ) + { + Data_Impl* pDataObject = pImpl->pData->GetObject(i); + + if ( pDataObject->pTabPage ) + { + // save settings of all pages (user data) + pDataObject->pTabPage->FillUserData(); + String aPageData( pDataObject->pTabPage->GetUserData() ); + if ( aPageData.Len() ) + { + // save settings of all pages (user data) + SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) ); + aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) ); + } + + if ( pDataObject->bOnDemand ) + delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet(); + delete pDataObject->pTabPage; + } + delete pDataObject; + } + + delete pImpl->pController; + delete pImpl->pApplyButton; + delete pImpl->pData; + delete pImpl; + delete pUserBtn; + delete pOutSet; + delete pExampleSet; + delete [] pRanges; +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::Init_Impl( BOOL bFmtFlag, const String* pUserButtonText ) + +/* [Beschreibung] + + interne Initialisierung des Dialogs +*/ + +{ + aOKBtn.SetClickHdl( LINK( this, SfxTabDialog, OkHdl ) ); + aResetBtn.SetClickHdl( LINK( this, SfxTabDialog, ResetHdl ) ); + aResetBtn.SetText( String( SfxResId( STR_RESET ) ) ); + aTabCtrl.SetActivatePageHdl( + LINK( this, SfxTabDialog, ActivatePageHdl ) ); + aTabCtrl.SetDeactivatePageHdl( + LINK( this, SfxTabDialog, DeactivatePageHdl ) ); + aTabCtrl.Show(); + aOKBtn.Show(); + aCancelBtn.Show(); + aHelpBtn.Show(); + aResetBtn.Show(); + aResetBtn.SetHelpId( HID_TABDLG_RESET_BTN ); + + if ( pUserBtn ) + { + pUserBtn->SetText( *pUserButtonText ); + pUserBtn->SetClickHdl( LINK( this, SfxTabDialog, UserHdl ) ); + pUserBtn->Show(); + } + + /* TODO: Check what is up with bFmt/bFmtFlag. Comment below suggests a + different behavior than implemented!! */ + if ( bFmtFlag ) + { + String aStd( SfxResId( STR_STANDARD_SHORTCUT ) ); + aBaseFmtBtn.SetText( aStd ); + aBaseFmtBtn.SetClickHdl( LINK( this, SfxTabDialog, BaseFmtHdl ) ); + aBaseFmtBtn.SetHelpId( HID_TABDLG_STANDARD_BTN ); + + // bFmt = tempor"ares Flag im Ctor() "ubergeben, + // wenn bFmt == 2, dann auch TRUE, + // zus"atzlich Ausblendung vom StandardButton, + // nach der Initialisierung wieder auf TRUE setzen + if ( bFmtFlag != 2 ) + aBaseFmtBtn.Show(); + else + bFmtFlag = TRUE; + } + + if ( pSet ) + { + pExampleSet = new SfxItemSet( *pSet ); + pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() ); + } +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::RemoveResetButton() +{ + aResetBtn.Hide(); + pImpl->bHideResetBtn = TRUE; +} + +// ----------------------------------------------------------------------- + +#if ENABLE_LAYOUT_SFX_TABDIALOG +#undef TabDialog +#define TabDialog Dialog +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + +short SfxTabDialog::Execute() +{ + if ( !aTabCtrl.GetPageCount() ) + return RET_CANCEL; + Start_Impl(); + return TabDialog::Execute(); +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::StartExecuteModal( const Link& rEndDialogHdl ) +{ +#if !ENABLE_LAYOUT_SFX_TABDIALOG + if ( !aTabCtrl.GetPageCount() ) + return; + Start_Impl(); + TabDialog::StartExecuteModal( rEndDialogHdl ); +#else + rEndDialogHdl.IsSet(); +#endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */ +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::Start( BOOL bShow ) +{ + aCancelBtn.SetClickHdl( LINK( this, SfxTabDialog, CancelHdl ) ); + pImpl->bModal = FALSE; + Start_Impl(); + + if ( bShow ) + Show(); +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::SetApplyHandler(const Link& _rHdl) +{ + DBG_ASSERT( pImpl->pApplyButton, "SfxTabDialog::GetApplyHandler: no apply button enabled!" ); + if ( pImpl->pApplyButton ) + pImpl->pApplyButton->SetClickHdl( _rHdl ); +} + +// ----------------------------------------------------------------------- + +Link SfxTabDialog::GetApplyHandler() const +{ + DBG_ASSERT( pImpl->pApplyButton, "SfxTabDialog::GetApplyHandler: no button enabled!" ); + if ( !pImpl->pApplyButton ) + return Link(); + + return pImpl->pApplyButton->GetClickHdl(); +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::EnableApplyButton(BOOL bEnable) +{ + if ( IsApplyButtonEnabled() == bEnable ) + // nothing to do + return; + + // create or remove the apply button + if ( bEnable ) + { + pImpl->pApplyButton = new PushButton( this ); +#if !ENABLE_LAYOUT_SFX_TABDIALOG + // in the z-order, the apply button should be behind the ok button, thus appearing at the right side of it + pImpl->pApplyButton->SetZOrder(&aOKBtn, WINDOW_ZORDER_BEHIND); +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + pImpl->pApplyButton->SetText( String( SfxResId( STR_APPLY ) ) ); + pImpl->pApplyButton->Show(); + + pImpl->pApplyButton->SetHelpId( HID_TABDLG_APPLY_BTN ); + } + else + { + delete pImpl->pApplyButton; + pImpl->pApplyButton = NULL; + } + +#if !ENABLE_LAYOUT_SFX_TABDIALOG + // adjust the layout + if (IsReallyShown()) + AdjustLayout(); +#endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */ +} + +// ----------------------------------------------------------------------- + +BOOL SfxTabDialog::IsApplyButtonEnabled() const +{ + return ( NULL != pImpl->pApplyButton ); +} + +// ----------------------------------------------------------------------- + +const PushButton* SfxTabDialog::GetApplyButton() const +{ + return pImpl->pApplyButton; +} + +// ----------------------------------------------------------------------- + +PushButton* SfxTabDialog::GetApplyButton() +{ + return pImpl->pApplyButton; +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::Start_Impl() +{ + DBG_ASSERT( pImpl->pData->Count() == aTabCtrl.GetPageCount(), "not all pages registered" ); + USHORT nActPage = aTabCtrl.GetPageId( 0 ); + + // load old settings, when exists + SvtViewOptions aDlgOpt( E_TABDIALOG, String::CreateFromInt32( nResId ) ); + if ( aDlgOpt.Exists() ) + { +#if !ENABLE_LAYOUT_SFX_TABDIALOG + SetWindowState( ByteString( aDlgOpt.GetWindowState().getStr(), RTL_TEXTENCODING_ASCII_US ) ); +#endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */ + + // initiale TabPage aus Programm/Hilfe/Konfig + nActPage = (USHORT)aDlgOpt.GetPageID(); + + if ( USHRT_MAX != nAppPageId ) + nActPage = nAppPageId; + else + { + USHORT nAutoTabPageId = SFX_APP()->Get_Impl()->nAutoTabPageId; + if ( nAutoTabPageId ) + nActPage = nAutoTabPageId; + } + + if ( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nActPage ) ) + nActPage = aTabCtrl.GetPageId( 0 ); + } + else if ( USHRT_MAX != nAppPageId && TAB_PAGE_NOTFOUND != aTabCtrl.GetPagePos( nAppPageId ) ) + nActPage = nAppPageId; + + aTabCtrl.SetCurPageId( nActPage ); + ActivatePageHdl( &aTabCtrl ); +} + +void SfxTabDialog::AddTabPage( USHORT nId, BOOL bItemsOnDemand ) +{ + AddTabPage( nId, 0, 0, bItemsOnDemand ); +} + +void SfxTabDialog::AddTabPage( USHORT nId, const String &rRiderText, BOOL bItemsOnDemand, USHORT nPos ) +{ + AddTabPage( nId, rRiderText, 0, 0, bItemsOnDemand, nPos ); +} + +#ifdef SV_HAS_RIDERBITMAPS + +void SfxTabDialog::AddTabPage( USHORT nId, const Bitmap &rRiderBitmap, BOOL bItemsOnDemand, USHORT nPos ) +{ + AddTabPage( nId, rRiderBitmap, 0, 0, bItemsOnDemand, nPos ); +} + +#endif + +// ----------------------------------------------------------------------- + +void SfxTabDialog::AddTabPage + +/* [Beschreibung] + + Hinzuf"ugen einer Seite zu dem Dialog. + Mu\s korrespondieren zu einem entsprechende Eintrag im + TabControl in der Resource des Dialogs. +*/ + +( + USHORT nId, // ID der Seite + CreateTabPage pCreateFunc, // Pointer auf die Factory-Methode + GetTabPageRanges pRangesFunc, // Pointer auf die Methode f"ur das + // Erfragen der Ranges onDemand + BOOL bItemsOnDemand // gibt an, ob das Set dieser Seite beim + // Erzeugen der Seite erfragt wird +) +{ + pImpl->pData->Append( + new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) ); +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::AddTabPage + +/* [Beschreibung] + + Hinzuf"ugen einer Seite zu dem Dialog. + Der Ridertext wird "ubergeben, die Seite hat keine Entsprechung im + TabControl in der Resource des Dialogs. +*/ + +( + USHORT nId, + const String& rRiderText, + CreateTabPage pCreateFunc, + GetTabPageRanges pRangesFunc, + BOOL bItemsOnDemand, + USHORT nPos +) +{ + DBG_ASSERT( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ), + "Doppelte Page-Ids in der Tabpage" ); + aTabCtrl.InsertPage( nId, rRiderText, nPos ); + pImpl->pData->Append( + new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) ); +} + +// ----------------------------------------------------------------------- +#ifdef SV_HAS_RIDERBITMAPS + +void SfxTabDialog::AddTabPage + +/* [Beschreibung] + + Hinzuf"ugen einer Seite zu dem Dialog. + Die Riderbitmap wird "ubergeben, die Seite hat keine Entsprechung im + TabControl in der Resource des Dialogs. +*/ + +( + USHORT nId, + const Bitmap &rRiderBitmap, + CreateTabPage pCreateFunc, + GetTabPageRanges pRangesFunc, + BOOL bItemsOnDemand, + USHORT nPos +) +{ + DBG_ASSERT( TAB_PAGE_NOTFOUND == aTabCtrl.GetPagePos( nId ), + "Doppelte Page-Ids in der Tabpage" ); + aTabCtrl.InsertPage( nId, rRiderBitmap, nPos ); + pImpl->pData->Append( + new Data_Impl( nId, pCreateFunc, pRangesFunc, bItemsOnDemand ) ); +} +#endif + +// ----------------------------------------------------------------------- + +void SfxTabDialog::RemoveTabPage( USHORT nId ) + +/* [Beschreibung] + + L"oschen der TabPage mit der ID nId +*/ + +{ + USHORT nPos = 0; + aTabCtrl.RemovePage( nId ); + Data_Impl* pDataObject = Find( *pImpl->pData, nId, &nPos ); + + if ( pDataObject ) + { + if ( pDataObject->pTabPage ) + { + pDataObject->pTabPage->FillUserData(); + String aPageData( pDataObject->pTabPage->GetUserData() ); + if ( aPageData.Len() ) + { + // save settings of this page (user data) + SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) ); + aPageOpt.SetUserItem( USERITEM_NAME, makeAny( OUString( aPageData ) ) ); + } + + if ( pDataObject->bOnDemand ) + delete (SfxItemSet*)&pDataObject->pTabPage->GetItemSet(); + delete pDataObject->pTabPage; + } + + delete pDataObject; + pImpl->pData->Remove( nPos ); + } + else + { + DBG_WARNINGFILE( "TabPage-Id nicht bekannt" ); + } +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::PageCreated + +/* [Beschreibung] + + Defaultimplemetierung der virtuellen Methode. + Diese wird unmittelbar nach dem Erzeugen einer Seite gerufen. + Hier kann der Dialog direkt an der TabPage Methoden rufen. +*/ + +( + USHORT, // Id der erzeugten Seite + SfxTabPage& // Referenz auf die erzeugte Seite +) +{ +} + +// ----------------------------------------------------------------------- + +SfxItemSet* SfxTabDialog::GetInputSetImpl() + +/* [Beschreibung] + + Abgeleitete Klassen legen ggf. fuer den InputSet neuen Speicher an. + Dieser mu\s im Destruktor auch wieder freigegeben werden. Dazu mu\s + diese Methode gerufen werden. +*/ + +{ + return (SfxItemSet*)pSet; +} + +// ----------------------------------------------------------------------- + +SfxTabPage* SfxTabDialog::GetTabPage( USHORT nPageId ) const + +/* [Beschreibung] + + TabPage mit der "Ubergebenen Id zur"uckgeben. +*/ + +{ + USHORT nPos = 0; + Data_Impl* pDataObject = Find( *pImpl->pData, nPageId, &nPos ); + + if ( pDataObject ) + return pDataObject->pTabPage; + return NULL; +} + +// ----------------------------------------------------------------------- + +BOOL SfxTabDialog::IsInOK() const + +/* [Beschreibung] + +*/ + +{ + return pImpl->bInOK; +} + +// ----------------------------------------------------------------------- + +short SfxTabDialog::Ok() + +/* [Beschreibung] + + Ok-Handler des Dialogs + Das OutputSet wird erstellt und jede Seite wird mit + dem bzw. ihrem speziellen OutputSet durch Aufruf der Methode + <SfxTabPage::FillItemSet(SfxItemSet &)> dazu aufgefordert, + die vom Benuzter eingestellten Daten in das Set zu tun. + + [R"uckgabewert] + + RET_OK: wenn mindestens eine Seite TRUE als Returnwert von + FillItemSet geliefert hat, sonst RET_CANCEL. +*/ + +{ + pImpl->bInOK = TRUE; + + if ( !pOutSet ) + { + if ( !pExampleSet && pSet ) + pOutSet = pSet->Clone( FALSE ); // ohne Items + else if ( pExampleSet ) + pOutSet = new SfxItemSet( *pExampleSet ); + } + BOOL bModified = FALSE; + + const USHORT nCount = pImpl->pData->Count(); + + for ( USHORT i = 0; i < nCount; ++i ) + { + Data_Impl* pDataObject = pImpl->pData->GetObject(i); + SfxTabPage* pTabPage = pDataObject->pTabPage; + + if ( pTabPage ) + { + if ( pDataObject->bOnDemand ) + { + SfxItemSet& rSet = (SfxItemSet&)pTabPage->GetItemSet(); + rSet.ClearItem(); + bModified |= pTabPage->FillItemSet( rSet ); + } + else if ( pSet && !pTabPage->HasExchangeSupport() ) + { + SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() ); + + if ( pTabPage->FillItemSet( aTmp ) ) + { + bModified |= TRUE; + pExampleSet->Put( aTmp ); + pOutSet->Put( aTmp ); + } + } + } + } + + if ( pImpl->bModified || ( pOutSet && pOutSet->Count() > 0 ) ) + bModified |= TRUE; + + if ( bFmt == 2 ) + bModified |= TRUE; + return bModified ? RET_OK : RET_CANCEL; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxTabDialog, CancelHdl, Button*, pButton ) +{ + (void)pButton; //unused + Close(); + return 0; +} + +// ----------------------------------------------------------------------- + +SfxItemSet* SfxTabDialog::CreateInputItemSet( USHORT ) + +/* [Beschreibung] + + Defaultimplemetierung der virtuellen Methode. + Diese wird gerufen, wenn Pages ihre Sets onDenamd anlegen +*/ + +{ + DBG_WARNINGFILE( "CreateInputItemSet nicht implementiert" ); + return new SfxAllItemSet( SFX_APP()->GetPool() ); +} + +// ----------------------------------------------------------------------- + +const SfxItemSet* SfxTabDialog::GetRefreshedSet() + +/* [Beschreibung] + + Defaultimplemetierung der virtuellen Methode. + Diese wird gerufen, wenn <SfxTabPage::DeactivatePage(SfxItemSet *)> + <SfxTabPage::REFRESH_SET> liefert. +*/ + +{ + DBG_ERRORFILE( "GetRefreshedSet nicht implementiert" ); + return 0; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxTabDialog, OkHdl, Button *, EMPTYARG ) + +/* [Beschreibung] + + Handler des Ok-Buttons + Dieser ruft f"ur die aktuelle Seite + <SfxTabPage::DeactivatePage(SfxItemSet *)>. + Liefert diese <SfxTabPage::LEAVE_PAGE>, wird <SfxTabDialog::Ok()> gerufen + und so der Dialog beendet. +*/ + +{ + pImpl->bInOK = TRUE; + + if ( OK_Impl() ) + { + if ( pImpl->bModal ) + EndDialog( Ok() ); + else + { + Ok(); + Close(); + } + } + return 0; +} + +// ----------------------------------------------------------------------- + +bool SfxTabDialog::PrepareLeaveCurrentPage() +{ + USHORT const nId = aTabCtrl.GetCurPageId(); + SfxTabPage* pPage = dynamic_cast<SfxTabPage*> (aTabCtrl.GetTabPage( nId )); + bool bEnd = !pPage; + + if ( pPage ) + { + int nRet = SfxTabPage::LEAVE_PAGE; + if ( pSet ) + { + SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() ); + + if ( pPage->HasExchangeSupport() ) + nRet = pPage->DeactivatePage( &aTmp ); + else + nRet = pPage->DeactivatePage( NULL ); + + if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE + && aTmp.Count() ) + { + pExampleSet->Put( aTmp ); + pOutSet->Put( aTmp ); + } + } + else + nRet = pPage->DeactivatePage( NULL ); + bEnd = nRet; + } + + return bEnd; +} + + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxTabDialog, UserHdl, Button *, EMPTYARG ) + +/* [Beschreibung] + + Handler des User-Buttons + Dieser ruft f"ur die aktuelle Seite + <SfxTabPage::DeactivatePage(SfxItemSet *)>. + Liefert diese <SfxTabPage::LEAVE_PAGE>, wird <SfxTabDialog::Ok()> gerufen. + Mit dem Return-Wert von <SfxTabDialog::Ok()> wird dann der Dialog beendet. +*/ + +{ + if ( PrepareLeaveCurrentPage () ) + { + short nRet = Ok(); + + if ( RET_OK == nRet ) + nRet = RET_USER; + else + nRet = RET_USER_CANCEL; + EndDialog( nRet ); + } + return 0; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxTabDialog, ResetHdl, Button *, EMPTYARG ) + +/* [Beschreibung] + + Handler hinter dem Zur"ucksetzen-Button. + Die aktuelle Page wird mit ihren initialen Daten + neu initialisiert; alle Einstellungen, die der Benutzer + auf dieser Seite get"atigt hat, werden aufgehoben. +*/ + +{ + const USHORT nId = aTabCtrl.GetCurPageId(); + Data_Impl* pDataObject = Find( *pImpl->pData, nId ); + DBG_ASSERT( pDataObject, "Id nicht bekannt" ); + + if ( pDataObject->bOnDemand ) + { + // CSet auf AIS hat hier Probleme, daher getrennt + const SfxItemSet* pItemSet = &pDataObject->pTabPage->GetItemSet(); + pDataObject->pTabPage->Reset( *(SfxItemSet*)pItemSet ); + } + else + pDataObject->pTabPage->Reset( *pSet ); + return 0; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxTabDialog, BaseFmtHdl, Button *, EMPTYARG ) + +/* [Beschreibung] + + Handler hinter dem Standard-Button. + Dieser Button steht beim Bearbeiten von StyleSheets zur Verf"ugung. + Alle in dem bearbeiteten StyleSheet eingestellten Attribute + werden gel"oscht. +*/ + +{ + const USHORT nId = aTabCtrl.GetCurPageId(); + Data_Impl* pDataObject = Find( *pImpl->pData, nId ); + DBG_ASSERT( pDataObject, "Id nicht bekannt" ); + bFmt = 2; + + if ( pDataObject->fnGetRanges ) + { + if ( !pExampleSet ) + pExampleSet = new SfxItemSet( *pSet ); + + const SfxItemPool* pPool = pSet->GetPool(); + const USHORT* pTmpRanges = (pDataObject->fnGetRanges)(); + SfxItemSet aTmpSet( *pExampleSet ); + + while ( *pTmpRanges ) + { + const USHORT* pU = pTmpRanges + 1; + + if ( *pTmpRanges == *pU ) + { + // Range mit zwei gleichen Werten -> nur ein Item setzen + USHORT nWh = pPool->GetWhich( *pTmpRanges ); + pExampleSet->ClearItem( nWh ); + aTmpSet.ClearItem( nWh ); + // am OutSet mit InvalidateItem, + // damit die "Anderung wirksam wird + pOutSet->InvalidateItem( nWh ); + } + else + { + // richtiger Range mit mehreren Werten + USHORT nTmp = *pTmpRanges, nTmpEnd = *pU; + DBG_ASSERT( nTmp <= nTmpEnd, "Range ist falsch sortiert" ); + + if ( nTmp > nTmpEnd ) + { + // wenn wirklich falsch sortiert, dann neu setzen + USHORT nTmp1 = nTmp; + nTmp = nTmpEnd; + nTmpEnd = nTmp1; + } + + while ( nTmp <= nTmpEnd ) + { + // "uber den Range iterieren, und die Items setzen + USHORT nWh = pPool->GetWhich( nTmp ); + pExampleSet->ClearItem( nWh ); + aTmpSet.ClearItem( nWh ); + // am OutSet mit InvalidateItem, + // damit die "Anderung wirksam wird + pOutSet->InvalidateItem( nWh ); + nTmp++; + } + } + // zum n"achsten Paar gehen + pTmpRanges += 2; + } + // alle Items neu gesetzt -> dann an der aktuellen Page Reset() rufen + DBG_ASSERT( pDataObject->pTabPage, "die Page ist weg" ); + pDataObject->pTabPage->Reset( aTmpSet ); + pDataObject->pTabPage->pImpl->mbStandard = TRUE; + } + return 1; +} + +// ----------------------------------------------------------------------- + +#if ENABLE_LAYOUT_SFX_TABDIALOG +#define tabControlWindow pTabCtrl->GetWindow () +#else /* !ENABLE_LAYOUT_SFX_TABDIALOG */ +#define tabControlWindow pTabCtrl +#endif /* !ENABLE_LAYOUT_SFX_TABDIALOG */ + +IMPL_LINK( SfxTabDialog, ActivatePageHdl, TabControl *, pTabCtrl ) + +/* [Beschreibung] + + Handler, der vor dem Umschalten auf eine andere Seite + durch Starview gerufen wird. + Existiert die Seite noch nicht, so wird sie erzeugt und + die virtuelle Methode <SfxTabDialog::PageCreated( USHORT, SfxTabPage &)> + gerufen. Existiert die Seite bereits, so wird ggf. + <SfxTabPage::Reset(const SfxItemSet &)> oder + <SfxTabPage::ActivatePage(const SfxItemSet &)> gerufen. +*/ + +{ + USHORT const nId = pTabCtrl->GetCurPageId(); + + DBG_ASSERT( pImpl->pData->Count(), "keine Pages angemeldet" ); + SFX_APP(); + + // Tab Page schon da? + SfxTabPage* pTabPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId )); + Data_Impl* pDataObject = Find( *pImpl->pData, nId ); + DBG_ASSERT( pDataObject, "Id nicht bekannt" ); + + // ggf. TabPage erzeugen: + if ( !pTabPage ) + { +#if ENABLE_LAYOUT_SFX_TABDIALOG + if (dynamic_cast<layout SfxTabPage*> (pTabPage)) + layout::TabPage::global_parent = pTabCtrl->GetWindow (); +#endif + const SfxItemSet* pTmpSet = 0; + + if ( pSet ) + { + if ( bItemsReset && pSet->GetParent() ) + pTmpSet = pSet->GetParent(); + else + pTmpSet = pSet; + } + + if ( pTmpSet && !pDataObject->bOnDemand ) + pTabPage = (pDataObject->fnCreatePage)( tabControlWindow, *pTmpSet ); + else + pTabPage = (pDataObject->fnCreatePage) + ( tabControlWindow, *CreateInputItemSet( nId ) ); + DBG_ASSERT( NULL == pDataObject->pTabPage, "create TabPage more than once" ); + pDataObject->pTabPage = pTabPage; + +#if !ENABLE_LAYOUT_SFX_TABDIALOG + pDataObject->pTabPage->SetTabDialog( this ); +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + SvtViewOptions aPageOpt( E_TABPAGE, String::CreateFromInt32( pDataObject->nId ) ); + String sUserData; + Any aUserItem = aPageOpt.GetUserItem( USERITEM_NAME ); + OUString aTemp; + if ( aUserItem >>= aTemp ) + sUserData = String( aTemp ); + pTabPage->SetUserData( sUserData ); + Size aSiz = pTabPage->GetSizePixel(); + +#if ENABLE_LAYOUT + Size optimalSize = pTabPage->GetOptimalSize (WINDOWSIZE_MINIMUM); +#if ENABLE_LAYOUT_SFX_TABDIALOG + if (dynamic_cast<layout SfxTabPage*> (pTabPage)) + { + if (optimalSize.Height () && optimalSize.Width ()) + { + optimalSize.Width () = optimalSize.Width (); + optimalSize.Height () = optimalSize.Height () + 40; + } + } +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + if (optimalSize.Height () > 0 && optimalSize.Width () > 0 ) + aSiz = optimalSize; +#endif /* ENABLE_LAYOUT */ + + Size aCtrlSiz = pTabCtrl->GetTabPageSizePixel(); + // Gr"o/se am TabControl nur dann setzen, wenn < als TabPage + if ( aCtrlSiz.Width() < aSiz.Width() || + aCtrlSiz.Height() < aSiz.Height() ) + { + pTabCtrl->SetTabPageSizePixel( aSiz ); + } + + PageCreated( nId, *pTabPage ); + + if ( pDataObject->bOnDemand ) + pTabPage->Reset( (SfxItemSet &)pTabPage->GetItemSet() ); + else + pTabPage->Reset( *pSet ); + + pTabCtrl->SetTabPage( nId, pTabPage ); + } + else if ( pDataObject->bRefresh ) + pTabPage->Reset( *pSet ); + pDataObject->bRefresh = FALSE; + +#if ENABLE_LAYOUT_SFX_TABDIALOG + pTabCtrl->GetPagePos (nId); +#endif /* ENABLE_LAYOUT_SFX_TABDIALOG */ + + if ( pExampleSet ) + pTabPage->ActivatePage( *pExampleSet ); + BOOL bReadOnly = pTabPage->IsReadOnly(); + ( bReadOnly || pImpl->bHideResetBtn ) ? aResetBtn.Hide() : aResetBtn.Show(); + return 0; +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( SfxTabDialog, DeactivatePageHdl, TabControl *, pTabCtrl ) + +/* [Beschreibung] + + Handler, der vor dem Verlassen einer Seite durch Starview gerufen wird. + + [Querverweise] + + <SfxTabPage::DeactivatePage(SfxItemSet *)> +*/ + +{ + USHORT nId = pTabCtrl->GetCurPageId(); + SFX_APP(); + SfxTabPage *pPage = dynamic_cast<SfxTabPage*> (pTabCtrl->GetTabPage( nId )); + DBG_ASSERT( pPage, "keine aktive Page" ); +#ifdef DBG_UTIL + Data_Impl* pDataObject = Find( *pImpl->pData, pTabCtrl->GetCurPageId() ); + DBG_ASSERT( pDataObject, "keine Datenstruktur zur aktuellen Seite" ); + if ( pPage->HasExchangeSupport() && pDataObject->bOnDemand ) + { + DBG_WARNING( "Datenaustausch bei ItemsOnDemand ist nicht gewuenscht!" ); + } +#endif + + int nRet = SfxTabPage::LEAVE_PAGE; + + if ( !pExampleSet && pPage->HasExchangeSupport() && pSet ) + pExampleSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() ); + + if ( pSet ) + { + SfxItemSet aTmp( *pSet->GetPool(), pSet->GetRanges() ); + + if ( pPage->HasExchangeSupport() ) + nRet = pPage->DeactivatePage( &aTmp ); + else + nRet = pPage->DeactivatePage( NULL ); +//! else +//! pPage->FillItemSet( aTmp ); + + if ( ( SfxTabPage::LEAVE_PAGE & nRet ) == SfxTabPage::LEAVE_PAGE && + aTmp.Count() ) + { + pExampleSet->Put( aTmp ); + pOutSet->Put( aTmp ); + } + } + else + { + if ( pPage->HasExchangeSupport() ) //!!! + { + if ( !pExampleSet ) + { + SfxItemPool* pPool = pPage->GetItemSet().GetPool(); + pExampleSet = + new SfxItemSet( *pPool, GetInputRanges( *pPool ) ); + } + nRet = pPage->DeactivatePage( pExampleSet ); + } + else + nRet = pPage->DeactivatePage( NULL ); + } + + if ( nRet & SfxTabPage::REFRESH_SET ) + { + pSet = GetRefreshedSet(); + DBG_ASSERT( pSet, "GetRefreshedSet() liefert NULL" ); + // alle Pages als neu zu initialsieren flaggen + const USHORT nCount = pImpl->pData->Count(); + + for ( USHORT i = 0; i < nCount; ++i ) + { + Data_Impl* pObj = (*pImpl->pData)[i]; + + if ( pObj->pTabPage != pPage ) // eigene Page nicht mehr refreshen + pObj->bRefresh = TRUE; + else + pObj->bRefresh = FALSE; + } + } + if ( nRet & SfxTabPage::LEAVE_PAGE ) + return TRUE; + else + return FALSE; +} + +// ----------------------------------------------------------------------- + +const SfxItemSet* SfxTabDialog::GetOutputItemSet + +/* [Beschreibung] + + Liefert die Pages, die ihre Sets onDemand liefern, das OutputItemSet. + + [Querverweise] + + <SfxTabDialog::AddTabPage(USHORT, CreateTabPage, GetTabPageRanges, BOOL)> + <SfxTabDialog::AddTabPage(USHORT, const String &, CreateTabPage, GetTabPageRanges, BOOL, USHORT)> + <SfxTabDialog::AddTabPage(USHORT, const Bitmap &, CreateTabPage, GetTabPageRanges, BOOL, USHORT)> +*/ + +( + USHORT nId // die Id, unter der die Seite bei AddTabPage() + // hinzugef"ugt wurde. +) const +{ + Data_Impl* pDataObject = Find( *pImpl->pData, nId ); + DBG_ASSERT( pDataObject, "TabPage nicht gefunden" ); + + if ( pDataObject ) + { + if ( !pDataObject->pTabPage ) + return NULL; + + if ( pDataObject->bOnDemand ) + return &pDataObject->pTabPage->GetItemSet(); + // else + return pOutSet; + } + return NULL; +} + +// ----------------------------------------------------------------------- + +int SfxTabDialog::FillOutputItemSet() +{ + int nRet = SfxTabPage::LEAVE_PAGE; + if ( OK_Impl() ) + Ok(); + else + nRet = SfxTabPage::KEEP_PAGE; + return nRet; +} + +// ----------------------------------------------------------------------- + +#ifdef WNT +int __cdecl TabDlgCmpUS_Impl( const void* p1, const void* p2 ) +#else +#if defined(OS2) && defined(ICC) +int _Optlink TabDlgCmpUS_Impl( const void* p1, const void* p2 ) +#else +extern "C" int TabDlgCmpUS_Impl( const void* p1, const void* p2 ) +#endif +#endif + +/* [Beschreibung] + + Vergleichsfunktion f"ur qsort +*/ + +{ + return *(USHORT*)p1 - *(USHORT*)p2; +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::ShowPage( USHORT nId ) + +/* [Beschreibung] + + Es wird die TabPage mit der "ubergebenen Id aktiviert. +*/ + +{ + aTabCtrl.SetCurPageId( nId ); + ActivatePageHdl( &aTabCtrl ); +} + +// ----------------------------------------------------------------------- + +const USHORT* SfxTabDialog::GetInputRanges( const SfxItemPool& rPool ) + +/* [Beschreibung] + + Bildet das Set "uber die Ranges aller Seiten des Dialogs. + Die Pages m"ussen die statische Methode f"ur das Erfragen ihrer + Ranges bei AddTabPage angegeben haben, liefern also ihre Sets onDemand. + + [Querverweise] + + <SfxTabDialog::AddTabPage(USHORT, CreateTabPage, GetTabPageRanges, BOOL)> + <SfxTabDialog::AddTabPage(USHORT, const String &, CreateTabPage, GetTabPageRanges, BOOL, USHORT)> + <SfxTabDialog::AddTabPage(USHORT, const Bitmap &, CreateTabPage, GetTabPageRanges, BOOL, USHORT)> + + [R"uckgabewert] + + Pointer auf nullterminiertes Array von USHORTs + Dieses Array geh"ort dem Dialog und wird beim + Zerst"oren des Dialogs gel"oscht. +*/ + +{ + if ( pSet ) + { + DBG_ERRORFILE( "Set bereits vorhanden!" ); + return pSet->GetRanges(); + } + + if ( pRanges ) + return pRanges; + SvUShorts aUS( 16, 16 ); + USHORT nCount = pImpl->pData->Count(); + + USHORT i; + for ( i = 0; i < nCount; ++i ) + { + Data_Impl* pDataObject = pImpl->pData->GetObject(i); + + if ( pDataObject->fnGetRanges ) + { + const USHORT* pTmpRanges = (pDataObject->fnGetRanges)(); + const USHORT* pIter = pTmpRanges; + + USHORT nLen; + for( nLen = 0; *pIter; ++nLen, ++pIter ) + ; + aUS.Insert( pTmpRanges, nLen, aUS.Count() ); + } + } + + //! Doppelte Ids entfernen? +#ifndef TF_POOLABLE + if ( rPool.HasMap() ) +#endif + { + nCount = aUS.Count(); + + for ( i = 0; i < nCount; ++i ) + aUS[i] = rPool.GetWhich( aUS[i] ); + } + + // sortieren + if ( aUS.Count() > 1 ) + qsort( (void*)aUS.GetData(), + aUS.Count(), sizeof(USHORT), TabDlgCmpUS_Impl ); + + // Ranges erzeugen + //!! Auskommentiert, da fehlerhaft + /* + pRanges = new USHORT[aUS.Count() * 2 + 1]; + int j = 0; + i = 0; + + while ( i < aUS.Count() ) + { + pRanges[j++] = aUS[i]; + // aufeinanderfolgende Zahlen + for( ; i < aUS.Count()-1; ++i ) + if ( aUS[i] + 1 != aUS[i+1] ) + break; + pRanges[j++] = aUS[i++]; + } + pRanges[j] = 0; // terminierende NULL + */ + + pRanges = new USHORT[aUS.Count() + 1]; + memcpy(pRanges, aUS.GetData(), sizeof(USHORT) * aUS.Count()); + pRanges[aUS.Count()] = 0; + return pRanges; +} + +// ----------------------------------------------------------------------- + +void SfxTabDialog::SetInputSet( const SfxItemSet* pInSet ) + +/* [Beschreibung] + + Mit dieser Methode kann nachtr"aglich der Input-Set initial oder + neu gesetzt werden. +*/ + +{ + FASTBOOL bSet = ( pSet != NULL ); + + pSet = pInSet; + + if ( !bSet && !pExampleSet && !pOutSet ) + { + pExampleSet = new SfxItemSet( *pSet ); + pOutSet = new SfxItemSet( *pSet->GetPool(), pSet->GetRanges() ); + } +} + +long SfxTabDialog::Notify( NotifyEvent& rNEvt ) +{ + if ( rNEvt.GetType() == EVENT_GETFOCUS ) + { + SfxViewFrame* pViewFrame = GetViewFrame() ? GetViewFrame() : SfxViewFrame::Current(); + if ( pViewFrame ) + { + Window* pWindow = rNEvt.GetWindow(); + ULONG nHelpId = 0; + while ( !nHelpId && pWindow ) + { + nHelpId = pWindow->GetHelpId(); + pWindow = pWindow->GetParent(); + } + + if ( nHelpId ) + SfxHelp::OpenHelpAgent( &pViewFrame->GetFrame(), nHelpId ); + } + } + + return TabDialog::Notify( rNEvt ); +} + +END_NAMESPACE_LAYOUT_SFX_TABDIALOG diff --git a/sfx2/source/dialog/taskpane.cxx b/sfx2/source/dialog/taskpane.cxx new file mode 100644 index 000000000000..30fe2460d512 --- /dev/null +++ b/sfx2/source/dialog/taskpane.cxx @@ -0,0 +1,1290 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_sfx2.hxx" + +#include "sfx2/taskpane.hxx" +#include "imagemgr.hxx" +#include "sfx2/sfxsids.hrc" +#include "sfx2/bindings.hxx" +#include "sfx2/dispatch.hxx" +#include "sfxresid.hxx" +#include "sfxlocal.hrc" +#include "helpid.hrc" + +/** === begin UNO includes === **/ +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/ui/XToolPanel.hpp> +#include <com/sun/star/ui/XUIElementFactory.hpp> +#include <com/sun/star/awt/XWindowPeer.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/awt/XControl.hpp> +/** === end UNO includes === **/ + +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/types.hxx> +#include <comphelper/processfactory.hxx> +#include <tools/diagnose_ex.h> +#include <svtools/toolpanel/toolpaneldeck.hxx> +#include <svtools/toolpanel/tablayouter.hxx> +#include <svtools/toolpanel/drawerlayouter.hxx> +#include <unotools/confignode.hxx> +#include <vcl/menu.hxx> +#include <vcl/svapp.hxx> +#include <toolkit/helper/vclunohelper.hxx> + +#include <boost/noncopyable.hpp> + +//...................................................................................................................... +namespace sfx2 +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::frame::XModuleManager; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::ui::XToolPanel; + using ::com::sun::star::ui::XUIElementFactory; + using ::com::sun::star::ui::XUIElement; + using ::com::sun::star::awt::XWindow; + using ::com::sun::star::frame::XModuleManager; + using ::com::sun::star::frame::XFrame; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::graphic::XGraphicProvider; + using ::com::sun::star::graphic::XGraphic; + using ::com::sun::star::accessibility::XAccessible; + using ::com::sun::star::awt::XControl; + /** === end UNO using === **/ + namespace PosSize = ::com::sun::star::awt::PosSize; + + //================================================================================================================== + //= helpers + //================================================================================================================== + namespace + { + //-------------------------------------------------------------------------------------------------------------- + ::utl::OConfigurationTreeRoot lcl_getModuleUIElementStatesConfig( const ::rtl::OUString& i_rModuleIdentifier, + const ::rtl::OUString& i_rResourceURL = ::rtl::OUString() ) + { + const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + ::rtl::OUStringBuffer aPathComposer; + try + { + const Reference< XNameAccess > xModuleAccess( aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); + const ::comphelper::NamedValueCollection aModuleProps( xModuleAccess->getByName( i_rModuleIdentifier ) ); + + const ::rtl::OUString sWindowStateRef( aModuleProps.getOrDefault( "ooSetupFactoryWindowStateConfigRef", ::rtl::OUString() ) ); + + aPathComposer.appendAscii( "org.openoffice.Office.UI." ); + aPathComposer.append( sWindowStateRef ); + aPathComposer.appendAscii( "/UIElements/States" ); + if ( i_rResourceURL.getLength() ) + { + aPathComposer.appendAscii( "/" ); + aPathComposer.append( i_rResourceURL ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return ::utl::OConfigurationTreeRoot( aContext, aPathComposer.makeStringAndClear(), false ); + } + + //-------------------------------------------------------------------------------------------------------------- + ::rtl::OUString lcl_identifyModule( const Reference< XFrame >& i_rDocumentFrame ) + { + ::rtl::OUString sModuleName; + try + { + const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + const Reference< XModuleManager > xModuleManager( aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); + sModuleName = xModuleManager->identify( i_rDocumentFrame ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return sModuleName; + } + + //-------------------------------------------------------------------------------------------------------------- + Reference< XFrame > lcl_getFrame( const SfxBindings* i_pBindings ) + { + const SfxViewFrame* pViewFrame = i_pBindings->GetDispatcher()->GetFrame(); + const SfxFrame& rFrame = pViewFrame->GetFrame(); + const Reference< XFrame > xFrame( rFrame.GetFrameInterface() ); + return xFrame; + } + + //-------------------------------------------------------------------------------------------------------------- + ::rtl::OUString lcl_getPanelHelpURL( const ::utl::OConfigurationNode& i_rPanelConfigNode ) + { + const ::rtl::OUString sHelpURL( ::comphelper::getString( i_rPanelConfigNode.getNodeValue( "HelpURL" ) ) ); + return sHelpURL; + } + + //-------------------------------------------------------------------------------------------------------------- + Image lcl_getPanelImage( const Reference< XFrame >& i_rDocFrame, const ::utl::OConfigurationNode& i_rPanelConfigNode ) + { + const ::rtl::OUString sImageURL( ::comphelper::getString( i_rPanelConfigNode.getNodeValue( "ImageURL" ) ) ); + if ( sImageURL.getLength() ) + { + try + { + ::comphelper::NamedValueCollection aMediaProperties; + aMediaProperties.put( "URL", sImageURL ); + + // special handling: if the ImageURL denotes a CommandName, then retrieve the image for that command + const sal_Char* pCommandImagePrefix = "private:commandimage/"; + const sal_Int32 nCommandImagePrefixLen = strlen( pCommandImagePrefix ); + if ( sImageURL.compareToAscii( pCommandImagePrefix, nCommandImagePrefixLen ) == 0 ) + { + ::rtl::OUStringBuffer aCommandName; + aCommandName.appendAscii( ".uno:" ); + aCommandName.append( sImageURL.copy( nCommandImagePrefixLen ) ); + const ::rtl::OUString sCommandName( aCommandName.makeStringAndClear() ); + + const BOOL bHiContrast( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ); + const Image aPanelImage( GetImage( i_rDocFrame, sCommandName, FALSE, bHiContrast ) ); + return aPanelImage.GetXGraphic(); + } + + // otherwise, delegate to the GraphicProvider + const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + const Reference< XGraphicProvider > xGraphicProvider( aContext.createComponent( "com.sun.star.graphic.GraphicProvider" ), UNO_QUERY_THROW ); + + const Reference< XGraphic > xGraphic( xGraphicProvider->queryGraphic( aMediaProperties.getPropertyValues() ), UNO_SET_THROW ); + return Image( xGraphic ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return Image(); + } + } + + //================================================================================================================== + //= TaskPaneDockingWindow + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + TaskPaneDockingWindow::TaskPaneDockingWindow( SfxBindings* i_pBindings, TaskPaneWrapper& i_rWrapper, Window* i_pParent, WinBits i_nBits ) + :TitledDockingWindow( i_pBindings, &i_rWrapper, i_pParent, i_nBits ) + ,m_aTaskPane( GetContentWindow(), lcl_getFrame( i_pBindings ) ) + ,m_aPaneController( m_aTaskPane, *this ) + { + m_aTaskPane.Show(); + SetText( String( SfxResId( SID_TASKPANE ) ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + void TaskPaneDockingWindow::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL ) + { + m_aPaneController.ActivateToolPanel( i_rPanelURL ); + } + + //------------------------------------------------------------------------------------------------------------------ + void TaskPaneDockingWindow::GetFocus() + { + TitledDockingWindow::GetFocus(); + m_aTaskPane.GrabFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TaskPaneDockingWindow::onLayoutDone() + { + m_aTaskPane.SetPosSizePixel( Point(), GetContentWindow().GetOutputSizePixel() ); + } + + //================================================================================================================== + //= TaskPaneWrapper + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + SFX_IMPL_DOCKINGWINDOW( TaskPaneWrapper, SID_TASKPANE ); + + //------------------------------------------------------------------------------------------------------------------ + TaskPaneWrapper::TaskPaneWrapper( Window* i_pParent, USHORT i_nId, SfxBindings* i_pBindings, SfxChildWinInfo* i_pInfo ) + :SfxChildWindow( i_pParent, i_nId ) + { + pWindow = new TaskPaneDockingWindow( i_pBindings, *this, i_pParent, + WB_STDDOCKWIN | WB_CLIPCHILDREN | WB_SIZEABLE | WB_3DLOOK | WB_ROLLABLE); + eChildAlignment = SFX_ALIGN_RIGHT; + + pWindow->SetHelpId( HID_TASKPANE_WINDOW ); + pWindow->SetOutputSizePixel( Size( 300, 450 ) ); + + dynamic_cast< SfxDockingWindow* >( pWindow )->Initialize( i_pInfo ); + SetHideNotDelete( TRUE ); + + pWindow->Show(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TaskPaneWrapper::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL ) + { + TaskPaneDockingWindow* pDockingWindow = dynamic_cast< TaskPaneDockingWindow* >( GetWindow() ); + ENSURE_OR_RETURN_VOID( pDockingWindow, "TaskPaneWrapper::ActivateToolPanel: invalid docking window implementation!" ); + pDockingWindow->ActivateToolPanel( i_rPanelURL ); + } + + //================================================================================================================== + //= CustomPanelUIElement + //================================================================================================================== + class CustomPanelUIElement + { + public: + CustomPanelUIElement() + :m_xUIElement() + ,m_xToolPanel() + ,m_xPanelWindow() + { + } + + CustomPanelUIElement( const Reference< XUIElement >& i_rUIElement ) + :m_xUIElement( i_rUIElement, UNO_SET_THROW ) + ,m_xToolPanel( i_rUIElement->getRealInterface(), UNO_QUERY_THROW ) + ,m_xPanelWindow( m_xToolPanel->getWindow(), UNO_SET_THROW ) + { + } + + bool is() const { return m_xPanelWindow.is(); } + + const Reference< XUIElement >& getUIElement() const { return m_xUIElement; } + const Reference< XToolPanel >& getToolPanel() const { return m_xToolPanel; } + const Reference< XWindow >& getPanelWindow() const { return m_xPanelWindow; } + + private: + Reference< XUIElement > m_xUIElement; + Reference< XToolPanel > m_xToolPanel; + Reference< XWindow > m_xPanelWindow; + }; + + //================================================================================================================== + //= CustomToolPanel + //================================================================================================================== + class CustomToolPanel : public ::svt::ToolPanelBase + { + public: + CustomToolPanel( const ::utl::OConfigurationNode& i_rPanelWindowState, const Reference< XFrame >& i_rFrame ); + + virtual ::rtl::OUString GetDisplayName() const; + virtual Image GetImage() const; + virtual SmartId GetHelpID() const; + virtual void Activate( Window& i_rParentWindow ); + virtual void Deactivate(); + virtual void SetSizePixel( const Size& i_rPanelWindowSize ); + virtual void GrabFocus(); + virtual void Dispose(); + virtual Reference< XAccessible > + CreatePanelAccessible( const Reference< XAccessible >& i_rParentAccessible ); + + const ::rtl::OUString& + GetResourceURL() const { return m_sResourceURL; } + + protected: + ~CustomToolPanel(); + + private: + bool impl_ensureToolPanelWindow( Window& i_rPanelParentWindow ); + void impl_updatePanelConfig( const bool i_bVisible ) const; + + private: + const ::rtl::OUString m_sUIName; + const Image m_aPanelImage; + const ::rtl::OUString m_aPanelHelpURL; + const ::rtl::OUString m_sResourceURL; + const ::rtl::OUString m_sPanelConfigPath; + Reference< XFrame > m_xFrame; + CustomPanelUIElement m_aCustomPanel; + bool m_bAttemptedCreation; + }; + + //------------------------------------------------------------------------------------------------------------------ + CustomToolPanel::CustomToolPanel( const ::utl::OConfigurationNode& i_rPanelWindowState, const Reference< XFrame >& i_rFrame ) + :m_sUIName( ::comphelper::getString( i_rPanelWindowState.getNodeValue( "UIName" ) ) ) + ,m_aPanelImage( lcl_getPanelImage( i_rFrame, i_rPanelWindowState ) ) + ,m_aPanelHelpURL( lcl_getPanelHelpURL( i_rPanelWindowState ) ) + ,m_sResourceURL( i_rPanelWindowState.getLocalName() ) + ,m_sPanelConfigPath( i_rPanelWindowState.getNodePath() ) + ,m_xFrame( i_rFrame ) + ,m_aCustomPanel() + ,m_bAttemptedCreation( false ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + CustomToolPanel::~CustomToolPanel() + { + } + + //------------------------------------------------------------------------------------------------------------------ + bool CustomToolPanel::impl_ensureToolPanelWindow( Window& i_rPanelParentWindow ) + { + if ( m_bAttemptedCreation ) + return m_aCustomPanel.is(); + + m_bAttemptedCreation = true; + try + { + const ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + const Reference< XUIElementFactory > xFactory( aContext.createComponent( "com.sun.star.ui.UIElementFactoryManager" ), UNO_QUERY_THROW ); + + ::comphelper::NamedValueCollection aCreationArgs; + aCreationArgs.put( "Frame", makeAny( m_xFrame ) ); + aCreationArgs.put( "ParentWindow", makeAny( i_rPanelParentWindow.GetComponentInterface() ) ); + + const Reference< XUIElement > xElement( + xFactory->createUIElement( m_sResourceURL, aCreationArgs.getPropertyValues() ), + UNO_SET_THROW ); + + m_aCustomPanel = CustomPanelUIElement( xElement ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return m_aCustomPanel.is(); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::impl_updatePanelConfig( const bool i_bVisible ) const + { + ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + ::utl::OConfigurationTreeRoot aConfig( aContext, m_sPanelConfigPath, true ); + + aConfig.setNodeValue( "Visible", makeAny( i_bVisible ) ); + aConfig.commit(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString CustomToolPanel::GetDisplayName() const + { + return m_sUIName; + } + + //------------------------------------------------------------------------------------------------------------------ + Image CustomToolPanel::GetImage() const + { + return m_aPanelImage; + } + + //------------------------------------------------------------------------------------------------------------------ + SmartId CustomToolPanel::GetHelpID() const + { + return SmartId( m_aPanelHelpURL ); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::Activate( Window& i_rParentWindow ) + { + ENSURE_OR_RETURN_VOID( impl_ensureToolPanelWindow( i_rParentWindow ), "no panel to activate!" ); + + // TODO: we might need a mechanism to decide whether the panel should be destroyed/re-created, or (as it is + // done now) hidden/shown + m_aCustomPanel.getPanelWindow()->setVisible( sal_True ); + + // update the panel's configuration + impl_updatePanelConfig( true ); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::Deactivate() + { + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel to deactivate!" ); + + m_aCustomPanel.getPanelWindow()->setVisible( sal_False ); + + // update the panel's configuration + impl_updatePanelConfig( false ); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::SetSizePixel( const Size& i_rPanelWindowSize ) + { + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel/window to position!" ); + + try + { + m_aCustomPanel.getPanelWindow()->setPosSize( 0, 0, i_rPanelWindowSize.Width(), i_rPanelWindowSize.Height(), + PosSize::POSSIZE ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::GrabFocus() + { + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel/window to focus!" ); + + m_aCustomPanel.getPanelWindow()->setFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + void CustomToolPanel::Dispose() + { + if ( !m_bAttemptedCreation ) + // nothing to dispose + return; + + ENSURE_OR_RETURN_VOID( m_aCustomPanel.is(), "no panel to destroy!" ); + try + { + Reference< XComponent > xUIElementComponent( m_aCustomPanel.getUIElement(), UNO_QUERY_THROW ); + xUIElementComponent->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XAccessible > CustomToolPanel::CreatePanelAccessible( const Reference< XAccessible >& i_rParentAccessible ) + { + ENSURE_OR_RETURN( m_aCustomPanel.is(), "no panel to ask!", NULL ); + + Reference< XAccessible > xPanelAccessible; + try + { + xPanelAccessible.set( m_aCustomPanel.getToolPanel()->createAccessible( i_rParentAccessible ), UNO_SET_THROW ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return xPanelAccessible; + } + + //================================================================================================================== + //= ModuleTaskPane_Impl + //================================================================================================================== + class ModuleTaskPane_Impl : public ::boost::noncopyable + { + public: + ModuleTaskPane_Impl( ModuleTaskPane& i_rAntiImpl, const Reference< XFrame >& i_rDocumentFrame, + const IToolPanelCompare* i_pPanelCompare ) + :m_rAntiImpl( i_rAntiImpl ) + ,m_sModuleIdentifier( lcl_identifyModule( i_rDocumentFrame ) ) + ,m_xFrame( i_rDocumentFrame ) + ,m_aPanelDeck( i_rAntiImpl ) + { + m_aPanelDeck.Show(); + OnResize(); + impl_initFromConfiguration( i_pPanelCompare ); + } + + ~ModuleTaskPane_Impl() + { + } + + void OnResize(); + void OnGetFocus(); + + static bool ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier ); + + ::svt::ToolPanelDeck& GetPanelDeck() { return m_aPanelDeck; } + const ::svt::ToolPanelDeck& GetPanelDeck() const { return m_aPanelDeck; } + + ::boost::optional< size_t > + GetPanelPos( const ::rtl::OUString& i_rResourceURL ); + ::rtl::OUString + GetPanelResourceURL( const size_t i_nPanelPos ) const; + + void SetDrawersLayout(); + void SetTabsLayout( const ::svt::TabAlignment i_eTabAlignment, const ::svt::TabItemContent i_eTabContent ); + + private: + void impl_initFromConfiguration( const IToolPanelCompare* i_pPanelCompare ); + + static bool + impl_isToolPanelResource( const ::rtl::OUString& i_rResourceURL ); + + DECL_LINK( OnActivatePanel, void* ); + + private: + ModuleTaskPane& m_rAntiImpl; + const ::rtl::OUString m_sModuleIdentifier; + const Reference< XFrame > m_xFrame; + ::svt::ToolPanelDeck m_aPanelDeck; + }; + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::OnResize() + { + m_aPanelDeck.SetPosSizePixel( Point(), m_rAntiImpl.GetOutputSizePixel() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::OnGetFocus() + { + m_aPanelDeck.GrabFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + IMPL_LINK( ModuleTaskPane_Impl, OnActivatePanel, void*, i_pArg ) + { + m_aPanelDeck.ActivatePanel( reinterpret_cast< size_t >( i_pArg ) ); + return 1L; + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane_Impl::impl_isToolPanelResource( const ::rtl::OUString& i_rResourceURL ) + { + return i_rResourceURL.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:resource/toolpanel/" ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::impl_initFromConfiguration( const IToolPanelCompare* i_pPanelCompare ) + { + const ::utl::OConfigurationTreeRoot aWindowStateConfig( lcl_getModuleUIElementStatesConfig( m_sModuleIdentifier ) ); + if ( !aWindowStateConfig.isValid() ) + return; + + ::rtl::OUString sFirstVisiblePanelResource; + ::rtl::OUString sFirstPanelResource; + + const Sequence< ::rtl::OUString > aUIElements( aWindowStateConfig.getNodeNames() ); + for ( const ::rtl::OUString* resource = aUIElements.getConstArray(); + resource != aUIElements.getConstArray() + aUIElements.getLength(); + ++resource + ) + { + if ( !impl_isToolPanelResource( *resource ) ) + continue; + + sFirstPanelResource = *resource; + + ::utl::OConfigurationNode aResourceNode( aWindowStateConfig.openNode( *resource ) ); + ::svt::PToolPanel pCustomPanel( new CustomToolPanel( aResourceNode, m_xFrame ) ); + + size_t nPanelPos = m_aPanelDeck.GetPanelCount(); + if ( i_pPanelCompare ) + { + // assuming that nobody will insert hundreths of panels, a simple O(n) search should suffice here ... + while ( nPanelPos > 0 ) + { + const short nCompare = i_pPanelCompare->compareToolPanelsURLs( + *resource, + GetPanelResourceURL( --nPanelPos ) + ); + if ( nCompare >= 0 ) + { + ++nPanelPos; + break; + } + } + } + nPanelPos = m_aPanelDeck.InsertPanel( pCustomPanel, nPanelPos ); + + if ( ::comphelper::getBOOL( aResourceNode.getNodeValue( "Visible" ) ) ) + sFirstVisiblePanelResource = *resource; + } + + if ( sFirstVisiblePanelResource.getLength() == 0 ) + sFirstVisiblePanelResource = sFirstPanelResource; + + if ( sFirstVisiblePanelResource.getLength() ) + { + ::boost::optional< size_t > aPanelPos( GetPanelPos( sFirstVisiblePanelResource ) ); + OSL_ENSURE( !!aPanelPos, "ModuleTaskPane_Impl::impl_isToolPanelResource: just inserted it, and it's not there?!" ); + if ( !!aPanelPos ) + m_rAntiImpl.PostUserEvent( LINK( this, ModuleTaskPane_Impl, OnActivatePanel ), reinterpret_cast< void* >( *aPanelPos ) ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane_Impl::ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier ) + { + const ::utl::OConfigurationTreeRoot aWindowStateConfig( lcl_getModuleUIElementStatesConfig( i_rModuleIdentifier ) ); + if ( !aWindowStateConfig.isValid() ) + return false; + + const Sequence< ::rtl::OUString > aUIElements( aWindowStateConfig.getNodeNames() ); + for ( const ::rtl::OUString* resource = aUIElements.getConstArray(); + resource != aUIElements.getConstArray() + aUIElements.getLength(); + ++resource + ) + { + if ( impl_isToolPanelResource( *resource ) ) + return true; + } + return false; + } + + //------------------------------------------------------------------------------------------------------------------ + ::boost::optional< size_t > ModuleTaskPane_Impl::GetPanelPos( const ::rtl::OUString& i_rResourceURL ) + { + ::boost::optional< size_t > aPanelPos; + for ( size_t i = 0; i < m_aPanelDeck.GetPanelCount(); ++i ) + { + const ::svt::PToolPanel pPanel( m_aPanelDeck.GetPanel( i ) ); + const CustomToolPanel* pCustomPanel = dynamic_cast< const CustomToolPanel* >( pPanel.get() ); + ENSURE_OR_CONTINUE( pCustomPanel != NULL, "ModuleTaskPane_Impl::GetPanelPos: illegal panel implementation!" ); + if ( pCustomPanel->GetResourceURL() == i_rResourceURL ) + { + aPanelPos = i; + break; + } + } + return aPanelPos; + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString ModuleTaskPane_Impl::GetPanelResourceURL( const size_t i_nPanelPos ) const + { + ENSURE_OR_RETURN( i_nPanelPos < m_aPanelDeck.GetPanelCount(), "ModuleTaskPane_Impl::GetPanelResourceURL: illegal panel position!", ::rtl::OUString() ); + const ::svt::PToolPanel pPanel( m_aPanelDeck.GetPanel( i_nPanelPos ) ); + const CustomToolPanel* pCustomPanel = dynamic_cast< const CustomToolPanel* >( pPanel.get() ); + ENSURE_OR_RETURN( pCustomPanel != NULL, "ModuleTaskPane_Impl::GetPanelPos: illegal panel implementation!", ::rtl::OUString() ); + return pCustomPanel->GetResourceURL(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::SetDrawersLayout() + { + const ::svt::PDeckLayouter pLayouter( m_aPanelDeck.GetLayouter() ); + const ::svt::DrawerDeckLayouter* pDrawerLayouter = dynamic_cast< const ::svt::DrawerDeckLayouter* >( pLayouter.get() ); + if ( pDrawerLayouter != NULL ) + // already have the proper layout + return; + m_aPanelDeck.SetLayouter( new ::svt::DrawerDeckLayouter( m_aPanelDeck, m_aPanelDeck ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane_Impl::SetTabsLayout( const ::svt::TabAlignment i_eTabAlignment, const ::svt::TabItemContent i_eTabContent ) + { + ::svt::PDeckLayouter pLayouter( m_aPanelDeck.GetLayouter() ); + ::svt::TabDeckLayouter* pTabLayouter = dynamic_cast< ::svt::TabDeckLayouter* >( pLayouter.get() ); + if ( ( pTabLayouter != NULL ) + && ( pTabLayouter->GetTabAlignment() == i_eTabAlignment ) + && ( pTabLayouter->GetTabItemContent() == i_eTabContent ) + ) + // already have the requested layout + return; + + if ( pTabLayouter && ( pTabLayouter->GetTabAlignment() == i_eTabAlignment ) ) + { + // changing only the item content does not require a new layouter instance + pTabLayouter->SetTabItemContent( i_eTabContent ); + return; + } + + m_aPanelDeck.SetLayouter( new ::svt::TabDeckLayouter( m_aPanelDeck, m_aPanelDeck, i_eTabAlignment, i_eTabContent ) ); + } + + //================================================================================================================== + //= ModuleTaskPane + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ModuleTaskPane::ModuleTaskPane( Window& i_rParentWindow, const Reference< XFrame >& i_rDocumentFrame ) + :Window( &i_rParentWindow, WB_DIALOGCONTROL ) + ,m_pImpl( new ModuleTaskPane_Impl( *this, i_rDocumentFrame, NULL ) ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ModuleTaskPane::ModuleTaskPane( Window& i_rParentWindow, const Reference< XFrame >& i_rDocumentFrame, + const IToolPanelCompare& i_rCompare ) + :Window( &i_rParentWindow, WB_DIALOGCONTROL ) + ,m_pImpl( new ModuleTaskPane_Impl( *this, i_rDocumentFrame, &i_rCompare ) ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ModuleTaskPane::~ModuleTaskPane() + { + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane::ModuleHasToolPanels( const ::rtl::OUString& i_rModuleIdentifier ) + { + return ModuleTaskPane_Impl::ModuleHasToolPanels( i_rModuleIdentifier ); + } + + //------------------------------------------------------------------------------------------------------------------ + bool ModuleTaskPane::ModuleHasToolPanels( const Reference< XFrame >& i_rDocumentFrame ) + { + return ModuleTaskPane_Impl::ModuleHasToolPanels( lcl_identifyModule( i_rDocumentFrame ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane::Resize() + { + Window::Resize(); + m_pImpl->OnResize(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane::GetFocus() + { + Window::GetFocus(); + m_pImpl->OnGetFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::svt::ToolPanelDeck& ModuleTaskPane::GetPanelDeck() + { + return m_pImpl->GetPanelDeck(); + } + + //------------------------------------------------------------------------------------------------------------------ + const ::svt::ToolPanelDeck& ModuleTaskPane::GetPanelDeck() const + { + return m_pImpl->GetPanelDeck(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::boost::optional< size_t > ModuleTaskPane::GetPanelPos( const ::rtl::OUString& i_rResourceURL ) + { + return m_pImpl->GetPanelPos( i_rResourceURL ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString ModuleTaskPane::GetPanelResourceURL( const size_t i_nPanelPos ) const + { + return m_pImpl->GetPanelResourceURL( i_nPanelPos ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane::SetDrawersLayout() + { + m_pImpl->SetDrawersLayout(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ModuleTaskPane::SetTabsLayout( const ::svt::TabAlignment i_eTabAlignment, const ::svt::TabItemContent i_eTabContent ) + { + m_pImpl->SetTabsLayout( i_eTabAlignment, i_eTabContent ); + } + + // ===================================================================================================================== + // = PanelSelectorLayout + // ===================================================================================================================== + enum PanelSelectorLayout + { + LAYOUT_DRAWERS, + LAYOUT_TABS_RIGHT, + LAYOUT_TABS_LEFT, + LAYOUT_TABS_TOP, + LAYOUT_TABS_BOTTOM + }; + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + PanelSelectorLayout lcl_getTabLayoutFromAlignment( const SfxChildAlignment i_eAlignment ) + { + switch ( i_eAlignment ) + { + case SFX_ALIGN_LEFT: + return LAYOUT_TABS_LEFT; + case SFX_ALIGN_TOP: + return LAYOUT_TABS_TOP; + case SFX_ALIGN_BOTTOM: + return LAYOUT_TABS_BOTTOM; + default: + return LAYOUT_TABS_RIGHT; + } + } + } + + // ===================================================================================================================== + // = PanelDescriptor + // ===================================================================================================================== + /** is a helper class for TaskPaneController_Impl, holding the details about a single panel which is not + contained in the IToolPanel implementation itself. + */ + struct PanelDescriptor + { + ::svt::PToolPanel pPanel; + bool bHidden; + + PanelDescriptor() + :pPanel() + ,bHidden( false ) + { + } + + PanelDescriptor( const ::svt::PToolPanel& i_rPanel ) + :pPanel( i_rPanel ) + ,bHidden( false ) + { + } + }; + + //================================================================================================================== + //= TaskPaneController_Impl + //================================================================================================================== + class TaskPaneController_Impl :public ::boost::noncopyable + ,public ::svt::IToolPanelDeckListener + { + public: + TaskPaneController_Impl( + ModuleTaskPane& i_rTaskPane, + TitledDockingWindow& i_rDockingWindow + ); + ~TaskPaneController_Impl(); + + void SetDefaultTitle( const String& i_rTitle ); + void ActivateToolPanel( const ::rtl::OUString& i_rPanelURL ); + + protected: + // IToolPanelDeckListener overridables + virtual void PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition ); + virtual void PanelRemoved( const size_t i_nPosition ); + virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ); + virtual void LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter ); + virtual void Dying(); + + private: + DECL_LINK( OnToolboxClicked, ToolBox* ); + DECL_LINK( OnMenuItemSelected, Menu* ); + DECL_LINK( DockingChanged, TitledDockingWindow* ); + ::std::auto_ptr< PopupMenu > impl_createPopupMenu() const; + + /// sets the given layout for the panel selector + void impl_setLayout( const PanelSelectorLayout i_eLayout, const bool i_bForce = false ); + + /// returns the current layout of the panel selector + PanelSelectorLayout + impl_getLayout() const { return m_eCurrentLayout; } + + void impl_updateDockingWindowTitle(); + void impl_togglePanelVisibility( const size_t i_nLogicalPanelIndex ); + size_t impl_getLogicalPanelIndex( const size_t i_nVisibleIndex ); + + private: + enum MenuId + { + MID_UNLOCK_TASK_PANEL = 1, + MID_LOCK_TASK_PANEL = 2, + MID_LAYOUT_TABS = 3, + MID_LAYOUT_DRAWERS = 4, + MID_FIRST_PANEL = 5 + }; + + private: + typedef ::std::vector< PanelDescriptor > PanelDescriptors; + + ModuleTaskPane& m_rTaskPane; + TitledDockingWindow& m_rDockingWindow; + USHORT m_nViewMenuID; + PanelSelectorLayout m_eCurrentLayout; + PanelDescriptors m_aPanelRepository; + bool m_bTogglingPanelVisibility; + ::rtl::OUString m_sDefaultTitle; + }; + + //------------------------------------------------------------------------------------------------------------------ + TaskPaneController_Impl::TaskPaneController_Impl( ModuleTaskPane& i_rTaskPane, TitledDockingWindow& i_rDockingWindow ) + :m_rTaskPane( i_rTaskPane ) + ,m_rDockingWindow( i_rDockingWindow ) + ,m_nViewMenuID( 0 ) + ,m_eCurrentLayout( LAYOUT_DRAWERS ) + ,m_aPanelRepository() + ,m_bTogglingPanelVisibility( false ) + ,m_sDefaultTitle() + { + m_rDockingWindow.ResetToolBox(); + m_nViewMenuID = m_rDockingWindow.AddDropDownToolBoxItem( + String( SfxResId( STR_SFX_TASK_PANE_VIEW ) ), + HID_TASKPANE_VIEW_MENU, + LINK( this, TaskPaneController_Impl, OnToolboxClicked ) + ); + m_rDockingWindow.SetEndDockingHdl( LINK( this, TaskPaneController_Impl, DockingChanged ) ); + impl_setLayout( LAYOUT_DRAWERS, true ); + + m_rTaskPane.GetPanelDeck().AddListener( *this ); + + // initialize the panel repository + for ( size_t i = 0; i < m_rTaskPane.GetPanelDeck().GetPanelCount(); ++i ) + { + ::svt::PToolPanel pPanel( m_rTaskPane.GetPanelDeck().GetPanel( i ) ); + m_aPanelRepository.push_back( PanelDescriptor( pPanel ) ); + } + + SetDefaultTitle( String( SfxResId( STR_SFX_TASKS ) ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + TaskPaneController_Impl::~TaskPaneController_Impl() + { + m_rTaskPane.GetPanelDeck().RemoveListener( *this ); + + // remove the panels which are not under the control of the panel deck currently + for ( PanelDescriptors::iterator panelPos = m_aPanelRepository.begin(); + panelPos != m_aPanelRepository.end(); + ++panelPos + ) + { + if ( panelPos->bHidden ) + panelPos->pPanel->Dispose(); + } + m_aPanelRepository.clear(); + } + + // ----------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::SetDefaultTitle( const String& i_rTitle ) + { + m_sDefaultTitle = i_rTitle; + impl_updateDockingWindowTitle(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TaskPaneController_Impl::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL ) + { + ::boost::optional< size_t > aPanelPos( m_rTaskPane.GetPanelPos( i_rPanelURL ) ); + ENSURE_OR_RETURN_VOID( !!aPanelPos, "TaskPaneController_Impl::ActivateToolPanel: no such panel!" ); + + if ( aPanelPos == m_rTaskPane.GetPanelDeck().GetActivePanel() ) + { + ::svt::PToolPanel pPanel( m_rTaskPane.GetPanelDeck().GetPanel( *aPanelPos ) ); + pPanel->GrabFocus(); + } + else + { + m_rTaskPane.GetPanelDeck().ActivatePanel( aPanelPos ); + } + } + + // ----------------------------------------------------------------------------------------------------------------- + IMPL_LINK( TaskPaneController_Impl, DockingChanged, TitledDockingWindow*, i_pDockingWindow ) + { + ENSURE_OR_RETURN( i_pDockingWindow && &m_rDockingWindow, "TaskPaneController_Impl::DockingChanged: where does this come from?", 0L ); + + if ( impl_getLayout() == LAYOUT_DRAWERS ) + return 0L; + + impl_setLayout( lcl_getTabLayoutFromAlignment( i_pDockingWindow->GetAlignment() ) ); + return 1L; + } + + // ----------------------------------------------------------------------------------------------------------------- + IMPL_LINK( TaskPaneController_Impl, OnToolboxClicked, ToolBox*, i_pToolBox ) + { + if ( i_pToolBox->GetCurItemId() == m_nViewMenuID ) + { + i_pToolBox->EndSelection(); + + ::std::auto_ptr< PopupMenu > pMenu = impl_createPopupMenu(); + pMenu->SetSelectHdl( LINK( this, TaskPaneController_Impl, OnMenuItemSelected ) ); + + // pass toolbox button rect so the menu can stay open on button up + Rectangle aMenuRect( i_pToolBox->GetItemRect( m_nViewMenuID ) ); + aMenuRect.SetPos( i_pToolBox->GetPosPixel() ); + pMenu->Execute( &m_rDockingWindow, aMenuRect, POPUPMENU_EXECUTE_DOWN ); + } + + return 0; + } + + // --------------------------------------------------------------------------------------------------------------------- + IMPL_LINK( TaskPaneController_Impl, OnMenuItemSelected, Menu*, i_pMenu ) + { + ENSURE_OR_RETURN( i_pMenu, "TaskPaneController_Impl::OnMenuItemSelected: illegal menu!", 0L ); + + i_pMenu->Deactivate(); + switch ( i_pMenu->GetCurItemId() ) + { + case MID_UNLOCK_TASK_PANEL: + m_rDockingWindow.SetFloatingMode( TRUE ); + break; + + case MID_LOCK_TASK_PANEL: + m_rDockingWindow.SetFloatingMode( FALSE ); + break; + + case MID_LAYOUT_DRAWERS: + impl_setLayout( LAYOUT_DRAWERS ); + break; + + case MID_LAYOUT_TABS: + impl_setLayout( lcl_getTabLayoutFromAlignment( m_rDockingWindow.GetAlignment() ) ); + break; + + default: + { + size_t nPanelIndex = size_t( i_pMenu->GetCurItemId() - MID_FIRST_PANEL ); + impl_togglePanelVisibility( nPanelIndex ); + } + break; + } + + return 1L; + } + + // --------------------------------------------------------------------------------------------------------------------- + size_t TaskPaneController_Impl::impl_getLogicalPanelIndex( const size_t i_nVisibleIndex ) + { + size_t nLogicalIndex = 0; + size_t nVisibleIndex( i_nVisibleIndex ); + for ( size_t i=0; i < m_aPanelRepository.size(); ++i ) + { + if ( !m_aPanelRepository[i].bHidden ) + { + if ( !nVisibleIndex ) + break; + --nVisibleIndex; + } + ++nLogicalIndex; + } + return nLogicalIndex; + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition ) + { + if ( m_bTogglingPanelVisibility ) + return; + + const size_t nLogicalIndex( impl_getLogicalPanelIndex( i_nPosition ) ); + m_aPanelRepository.insert( m_aPanelRepository.begin() + nLogicalIndex, PanelDescriptor( i_pPanel ) ); + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::PanelRemoved( const size_t i_nPosition ) + { + if ( m_bTogglingPanelVisibility ) + return; + + const size_t nLogicalIndex( impl_getLogicalPanelIndex( i_nPosition ) ); + m_aPanelRepository.erase( m_aPanelRepository.begin() + nLogicalIndex ); + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ) + { + if ( impl_getLayout() == LAYOUT_DRAWERS ) + // no adjustment of the title when we use the classical "drawers" layout + return; + + impl_updateDockingWindowTitle( ); + (void)i_rOldActive; + (void)i_rNewActive; + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter ) + { + // not interested in + (void)i_rNewLayouter; + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::Dying() + { + OSL_ENSURE( false, "TaskPaneController_Impl::Dying: unexpected call!" ); + // We are expected to live longer than the ToolPanelDeck we work with. Since we remove ourself, in our dtor, + // as listener from the panel deck, this method here should never be called. + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::impl_togglePanelVisibility( const size_t i_nLogicalPanelIndex ) + { + ENSURE_OR_RETURN_VOID( i_nLogicalPanelIndex < m_aPanelRepository.size(), "illegal index" ); + + // get the actual panel index, within the deck + size_t nActualPanelIndex(0); + for ( size_t i=0; i < i_nLogicalPanelIndex; ++i ) + { + if ( !m_aPanelRepository[i].bHidden ) + ++nActualPanelIndex; + } + + ::boost::optional< size_t > aActivatePanel; + + m_bTogglingPanelVisibility = true; + if ( m_aPanelRepository[ i_nLogicalPanelIndex ].bHidden ) + { + OSL_VERIFY( m_rTaskPane.GetPanelDeck().InsertPanel( m_aPanelRepository[ i_nLogicalPanelIndex ].pPanel, nActualPanelIndex ) == nActualPanelIndex ); + // if there has not been an active panel before, activate the newly inserted one + ::boost::optional< size_t > aActivePanel( m_rTaskPane.GetPanelDeck().GetActivePanel() ); + if ( !aActivePanel ) + aActivatePanel = nActualPanelIndex; + } + else + { + OSL_VERIFY( m_rTaskPane.GetPanelDeck().RemovePanel( nActualPanelIndex ).get() == m_aPanelRepository[ i_nLogicalPanelIndex ].pPanel.get() ); + } + m_bTogglingPanelVisibility = false; + m_aPanelRepository[ i_nLogicalPanelIndex ].bHidden = !m_aPanelRepository[ i_nLogicalPanelIndex ].bHidden; + + if ( !!aActivatePanel ) + m_rTaskPane.GetPanelDeck().ActivatePanel( *aActivatePanel ); + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::impl_setLayout( const PanelSelectorLayout i_eLayout, const bool i_bForce ) + { + if ( !i_bForce && ( m_eCurrentLayout == i_eLayout ) ) + return; + + switch ( i_eLayout ) + { + case LAYOUT_DRAWERS: + m_rTaskPane.SetDrawersLayout(); + break; + case LAYOUT_TABS_TOP: + m_rTaskPane.SetTabsLayout( ::svt::TABS_TOP, ::svt::TABITEM_IMAGE_ONLY ); + break; + case LAYOUT_TABS_BOTTOM: + m_rTaskPane.SetTabsLayout( ::svt::TABS_BOTTOM, ::svt::TABITEM_IMAGE_ONLY ); + break; + case LAYOUT_TABS_LEFT: + m_rTaskPane.SetTabsLayout( ::svt::TABS_LEFT, ::svt::TABITEM_IMAGE_ONLY ); + break; + case LAYOUT_TABS_RIGHT: + m_rTaskPane.SetTabsLayout( ::svt::TABS_RIGHT, ::svt::TABITEM_IMAGE_ONLY ); + break; + } + m_eCurrentLayout = i_eLayout; + + impl_updateDockingWindowTitle(); + } + + // --------------------------------------------------------------------------------------------------------------------- + void TaskPaneController_Impl::impl_updateDockingWindowTitle() + { + ::boost::optional< size_t > aActivePanel( m_rTaskPane.GetPanelDeck().GetActivePanel() ); + if ( !aActivePanel || ( impl_getLayout() == LAYOUT_DRAWERS ) ) + m_rDockingWindow.SetTitle( m_sDefaultTitle ); + else + { + size_t nNewActive( *aActivePanel ); + for ( size_t i=0; i < m_aPanelRepository.size(); ++i ) + { + if ( m_aPanelRepository[i].bHidden ) + continue; + + if ( !nNewActive ) + { + m_rDockingWindow.SetTitle( m_aPanelRepository[i].pPanel->GetDisplayName() ); + break; + } + --nNewActive; + } + } + } + + // --------------------------------------------------------------------------------------------------------------------- + ::std::auto_ptr< PopupMenu > TaskPaneController_Impl::impl_createPopupMenu() const + { + ::std::auto_ptr<PopupMenu> pMenu( new PopupMenu ); + FloatingWindow* pMenuWindow = static_cast< FloatingWindow* >( pMenu->GetWindow() ); + if ( pMenuWindow != NULL ) + { + pMenuWindow->SetPopupModeFlags ( pMenuWindow->GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE ); + } + + // Add one entry for every tool panel element to individually make + // them visible or hide them. + USHORT nIndex = MID_FIRST_PANEL; + for ( size_t i=0; i<m_aPanelRepository.size(); ++i, ++nIndex ) + { + const PanelDescriptor& rPanelDesc( m_aPanelRepository[i] ); + pMenu->InsertItem( nIndex, rPanelDesc.pPanel->GetDisplayName(), MIB_CHECKABLE ); + pMenu->CheckItem( nIndex, !rPanelDesc.bHidden ); + } + pMenu->InsertSeparator(); + + #if OSL_DEBUG_LEVEL > 0 + pMenu->InsertItem( MID_LAYOUT_TABS, String::CreateFromAscii( "Tab-Layout (exp.)" ), MIB_CHECKABLE ); + pMenu->CheckItem( MID_LAYOUT_TABS, impl_getLayout() != LAYOUT_DRAWERS ); + pMenu->InsertItem( MID_LAYOUT_DRAWERS, String::CreateFromAscii( "Drawer-Layout" ), MIB_CHECKABLE ); + pMenu->CheckItem( MID_LAYOUT_DRAWERS, impl_getLayout() == LAYOUT_DRAWERS ); + + pMenu->InsertSeparator(); + #endif + + // Add entry for docking or un-docking the tool panel. + if ( m_rDockingWindow.IsFloatingMode() ) + pMenu->InsertItem( + MID_LOCK_TASK_PANEL, + String( SfxResId( STR_SFX_DOCK ) ) + ); + else + pMenu->InsertItem( + MID_UNLOCK_TASK_PANEL, + String( SfxResId( STR_SFX_UNDOCK ) ) + ); + + pMenu->RemoveDisabledEntries( FALSE, FALSE ); + + return pMenu; + } + + //================================================================================================================== + //= TaskPaneController + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + TaskPaneController::TaskPaneController( ModuleTaskPane& i_rTaskPane, TitledDockingWindow& i_rDockingWindow ) + :m_pImpl( new TaskPaneController_Impl( i_rTaskPane, i_rDockingWindow ) ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + TaskPaneController::~TaskPaneController() + { + } + + //------------------------------------------------------------------------------------------------------------------ + void TaskPaneController::SetDefaultTitle( const String& i_rTitle ) + { + m_pImpl->SetDefaultTitle( i_rTitle ); + } + + //------------------------------------------------------------------------------------------------------------------ + void TaskPaneController::ActivateToolPanel( const ::rtl::OUString& i_rPanelURL ) + { + m_pImpl->ActivateToolPanel( i_rPanelURL ); + } + +//...................................................................................................................... +} // namespace sfx2 +//...................................................................................................................... diff --git a/sfx2/source/dialog/taskpane.src b/sfx2/source/dialog/taskpane.src new file mode 100644 index 000000000000..5a955e8587d1 --- /dev/null +++ b/sfx2/source/dialog/taskpane.src @@ -0,0 +1,47 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <sfx2/sfx.hrc> +#include "sfxlocal.hrc" + +String STR_SFX_DOCK +{ + Text [ en-US ] = "Dock"; +}; + +String STR_SFX_UNDOCK +{ + Text [ en-US ] = "Undock"; +}; + +String STR_SFX_TASK_PANE_VIEW +{ + Text [ en-US ] = "View"; +}; +String STR_SFX_TASKS +{ + Text [ en-US ] = "Tasks"; +}; diff --git a/sfx2/source/dialog/templdlg.cxx b/sfx2/source/dialog/templdlg.cxx new file mode 100644 index 000000000000..9edeb05b43ac --- /dev/null +++ b/sfx2/source/dialog/templdlg.cxx @@ -0,0 +1,3065 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#ifndef _MENU_HXX //autogen +#include <vcl/menu.hxx> +#endif +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svl/style.hxx> +#ifndef GCC +#endif + +#define _SVSTDARR_STRINGSDTOR +#include <svl/svstdarr.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <unotools/intlwrapper.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> + +#include "sfxhelp.hxx" +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/templdlg.hxx> +#include "templdgi.hxx" +#include "tplcitem.hxx" +#include "sfxtypes.hxx" +#include <sfx2/styfitem.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/newstyle.hxx> +#include "tplpitem.hxx" +#include "sfxresid.hxx" + +#include "templdlg.hrc" +#include <sfx2/sfx.hrc> +#include "dialog.hrc" +#include "arrdecl.hxx" +#include "fltfnc.hxx" +#include <sfx2/docfilt.hxx> +#include <sfx2/docfac.hxx> +#include "docvor.hxx" +#include <sfx2/doctempl.hxx> +#include <sfx2/module.hxx> +#include "imgmgr.hxx" +#include "helpid.hrc" +#include "appdata.hxx" +#include <sfx2/viewfrm.hxx> + +#include <comphelper/configurationhelper.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::uno; + +//========================================================================= + +// Fenster wird ab jetzt dynamisch erstellt. Daher hier R"ander usw. + +#define SFX_TEMPLDLG_HFRAME 3 +#define SFX_TEMPLDLG_VTOPFRAME 3 + +#define SFX_TEMPLDLG_VBOTFRAME 3 +#define SFX_TEMPLDLG_MIDHSPACE 3 +#define SFX_TEMPLDLG_MIDVSPACE 3 +#define SFX_TEMPLDLG_FILTERHEIGHT 100 + +static USHORT nLastItemId = USHRT_MAX; + +// filter box has maximum 12 entries visible +#define MAX_FILTER_ENTRIES 12 + +//========================================================================= + +TYPEINIT0(SfxCommonTemplateDialog_Impl); +TYPEINIT1(SfxTemplateDialog_Impl,SfxCommonTemplateDialog_Impl); +TYPEINIT1(SfxTemplateCatalog_Impl,SfxCommonTemplateDialog_Impl); + +SFX_IMPL_DOCKINGWINDOW(SfxTemplateDialogWrapper, SID_STYLE_DESIGNER) + +//------------------------------------------------------------------------- + +// Redirektionsfunktionen + +SfxTemplateDialog::SfxTemplateDialog +( + SfxBindings *pBind, + SfxChildWindow *pCW, + Window *pParent +) + +/* [Beschreibung] + Gestalterklasse. +*/ + : SfxDockingWindow( pBind, pCW, pParent, SfxResId(DLG_STYLE_DESIGNER) ), + + pImpl( new SfxTemplateDialog_Impl( pParent, pBind, this ) ) + +{ + pImpl->updateNonFamilyImages(); +} + +//------------------------------------------------------------------------- + +SfxTemplateDialog::~SfxTemplateDialog() +{ + delete pImpl; +} + +ISfxTemplateCommon* SfxTemplateDialog::GetISfxTemplateCommon() +{ + return pImpl->GetISfxTemplateCommon(); +} + +void SfxTemplateDialog::SetParagraphFamily() +{ + // first select the paragraph family + pImpl->FamilySelect( SFX_STYLE_FAMILY_PARA ); + // then select the automatic filter + pImpl->SetAutomaticFilter(); +} + +// ------------------------------------------------------------------------ + +void SfxTemplateDialog::DataChanged( const DataChangedEvent& _rDCEvt ) +{ + if ( ( DATACHANGED_SETTINGS == _rDCEvt.GetType() ) && + ( 0 != ( SETTINGS_STYLE & _rDCEvt.GetFlags() ) ) ) + { + pImpl->updateFamilyImages(); + pImpl->updateNonFamilyImages(); + } + + SfxDockingWindow::DataChanged( _rDCEvt ); +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog::Update() +{ + pImpl->Update(); +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog::Resize() +{ + if(pImpl) + pImpl->Resize(); + SfxDockingWindow::Resize(); +} + + +//------------------------------------------------------------------------- + +SfxChildAlignment SfxTemplateDialog::CheckAlignment(SfxChildAlignment eActAlign,SfxChildAlignment eAlign) +{ + switch (eAlign) + { + case SFX_ALIGN_TOP: + case SFX_ALIGN_HIGHESTTOP: + case SFX_ALIGN_LOWESTTOP: + case SFX_ALIGN_BOTTOM: + case SFX_ALIGN_LOWESTBOTTOM: + case SFX_ALIGN_HIGHESTBOTTOM: + return eActAlign; + + case SFX_ALIGN_LEFT: + case SFX_ALIGN_RIGHT: + case SFX_ALIGN_FIRSTLEFT: + case SFX_ALIGN_LASTLEFT: + case SFX_ALIGN_FIRSTRIGHT: + case SFX_ALIGN_LASTRIGHT: + return eAlign; + + default: + return eAlign; + } +} + +//------------------------------------------------------------------------- + +SfxTemplateCatalog::SfxTemplateCatalog(Window *pParent, SfxBindings *pBindings) + : SfxModalDialog(pParent,SfxResId(RID_STYLECATALOG)) +{ + pImpl = new SfxTemplateCatalog_Impl(pParent, pBindings, this); +} + +//------------------------------------------------------------------------- + +SfxTemplateCatalog::~SfxTemplateCatalog() +{ + delete pImpl; +} + +//------------------------------------------------------------------------- + +void DropListBox_Impl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + nModifier = rMEvt.GetModifier(); + + BOOL bHitEmptySpace = ( NULL == GetEntry( rMEvt.GetPosPixel(), TRUE ) ); + if( bHitEmptySpace && ( rMEvt.GetClicks() == 2 ) && rMEvt.IsMod1() ) + Control::MouseButtonDown( rMEvt ); + else + SvTreeListBox::MouseButtonDown( rMEvt ); +} + +sal_Int8 DropListBox_Impl::AcceptDrop( const AcceptDropEvent& rEvt ) + +/* [Description: ] + Drop is enabled as long as it is allowed to create a new style by example, i.e. to + create a style out of the current selection. +*/ + +{ + if ( IsDropFormatSupported( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) ) + { + // special case: page styles are allowed to create new styles by example + // but not allowed to be created by drag and drop + if( pDialog->nActFamily == SfxCommonTemplateDialog_Impl::SfxFamilyIdToNId( SFX_STYLE_FAMILY_PAGE ) || + pDialog->bNewByExampleDisabled ) + return DND_ACTION_NONE; + else + return DND_ACTION_COPY; + } + return SvTreeListBox::AcceptDrop( rEvt ); +} + +//------------------------------------------------------------------------- + +sal_Int8 DropListBox_Impl::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ +// rEvt.maDropEvent.Context->acceptDrop( DND_ACTION_NONE ); +// rEvt.maDropEvent.Context->dropComplete( TRUE ); + + sal_Int8 nRet = DND_ACTION_NONE; + SfxObjectShell* pDocShell = pDialog->GetObjectShell(); + TransferableDataHelper aHelper( rEvt.maDropEvent.Transferable ); + sal_uInt32 nFormatCount = aHelper.GetFormatCount(); + if ( pDocShell ) + { + sal_Bool bFormatFound = sal_False; + + for ( sal_uInt32 i = 0; i < nFormatCount; ++i ) + { + SotFormatStringId nId = aHelper.GetFormat(i); + TransferableObjectDescriptor aDesc; + + if ( aHelper.GetTransferableObjectDescriptor( nId, aDesc ) ) + { + if ( aDesc.maClassName == pDocShell->GetFactory().GetClassId() ) + { + PostUserEvent( LINK( this, DropListBox_Impl, OnAsyncExecuteDrop ), 0 ); + + bFormatFound = sal_True; + nRet = rEvt.mnAction; + break; + } + } + } + + if ( !bFormatFound ) + return SvTreeListBox::ExecuteDrop( rEvt ); + } + + return nRet; +} + + +IMPL_LINK( DropListBox_Impl, OnAsyncExecuteDrop, SvLBoxEntry*, EMPTYARG ) +{ + pDialog->ActionSelect( SID_STYLE_NEW_BY_EXAMPLE ); + return 0; +} + + +IMPL_LINK( DropListBox_Impl, OnAsyncExecuteError, void*, NOTINTERESTEDIN ) +{ + (void)NOTINTERESTEDIN; // unused + ErrorHandler::HandleError( ERRCODE_IO_WRONGFORMAT ); + + return 0; +} + + +long DropListBox_Impl::Notify( NotifyEvent& rNEvt ) +{ + long nRet = 0; + if( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode(); + if(!rKeyCode.GetModifier()) + { + if( pDialog->bCanDel && KEY_DELETE == rKeyCode.GetCode()) + { + pDialog->DeleteHdl( NULL ); + nRet = 1; + } + else if( KEY_RETURN == rKeyCode.GetCode()) + { + GetDoubleClickHdl().Call(this); + nRet = 1; + } + } + } + if(!nRet) + nRet = SvTreeListBox::Notify( rNEvt ); + return nRet; +} + + +//------------------------------------------------------------------------- + + +SfxActionListBox::SfxActionListBox +( + SfxCommonTemplateDialog_Impl* pParent, + WinBits nWinBits +) + +/* [Beschreibung] + + ListBox- Klasse, die im Command-Handler ein PopupMenu (Gestalter + spezifisch) startet. + +*/ + +: DropListBox_Impl(pParent->GetWindow(), nWinBits, pParent) + +{ + EnableContextMenuHandling(); +} + +//------------------------------------------------------------------------- + +SfxActionListBox::SfxActionListBox( SfxCommonTemplateDialog_Impl* pParent, + const ResId &rResId) : + DropListBox_Impl(pParent->GetWindow(), rResId, pParent) +{ + EnableContextMenuHandling(); +} + +//------------------------------------------------------------------------- + +PopupMenu* SfxActionListBox::CreateContextMenu( void ) +{ + //added by BerryJia for fixing Bug102739 2002-9-9 17:00(Beijing Time) + if( !( GetSelectionCount() > 0 ) ) + { + pDialog->EnableEdit( FALSE ); + pDialog->EnableDel( FALSE ); + } + return pDialog->CreateContextMenu(); +} + +//------------------------------------------------------------------------- + +SfxTemplateDialogWrapper::SfxTemplateDialogWrapper(Window *pParentWnd, + USHORT nId, SfxBindings *p, SfxChildWinInfo *pInfo) : + SfxChildWindow(pParentWnd, nId) +{ + SfxTemplateDialog *pWin = new SfxTemplateDialog(p, this, pParentWnd); + pWindow = pWin; + eChildAlignment = SFX_ALIGN_NOALIGNMENT; + + pWin->Initialize( pInfo ); + pWin->SetMinOutputSizePixel(pWin->pImpl->GetMinOutputSizePixel()); +} + +void SfxTemplateDialogWrapper::SetParagraphFamily() +{ + // forward to SfxTemplateDialog, because SfxTemplateDialog isn't exported + static_cast< SfxTemplateDialog* >( GetWindow() )->SetParagraphFamily(); +} + +//========================================================================= +SV_DECL_PTRARR_DEL(ExpandedEntries, StringPtr,16,8) +SV_IMPL_PTRARR(ExpandedEntries, StringPtr) + +/* [Beschreibung] + + TreeListBox- Klasse f"ur die Anzeige der hierarchischen View + der Vorlagen + +*/ + +class StyleTreeListBox_Impl : public DropListBox_Impl +{ +private: + SvLBoxEntry* pCurEntry; + SfxCommonTemplateDialog_Impl* pCommon; + Link aDoubleClickLink; + Link aDropLink; + String aParent; + String aStyle; + +protected: + virtual void Command( const CommandEvent& rMEvt ); + virtual long Notify( NotifyEvent& rNEvt ); + virtual BOOL DoubleClickHdl(); + virtual long ExpandingHdl(); + virtual void ExpandedHdl(); + virtual BOOL NotifyMoving(SvLBoxEntry* pTarget, + SvLBoxEntry* pEntry, + SvLBoxEntry*& rpNewParent, + ULONG& rNewChildPos); +public: + StyleTreeListBox_Impl( SfxCommonTemplateDialog_Impl* pParent, WinBits nWinStyle = 0); + + void SetDoubleClickHdl(const Link &rLink) { aDoubleClickLink = rLink; } + void SetDropHdl(const Link &rLink) { aDropLink = rLink; } + using SvLBox::GetParent; + const String& GetParent() const { return aParent; } + const String& GetStyle() const { return aStyle; } + void MakeExpanded_Impl(ExpandedEntries& rEntries) const; + + virtual PopupMenu* CreateContextMenu( void ); +}; + +//------------------------------------------------------------------------- + + +void StyleTreeListBox_Impl::MakeExpanded_Impl(ExpandedEntries& rEntries) const +{ + SvLBoxEntry *pEntry; + USHORT nCount=0; + for(pEntry=(SvLBoxEntry*)FirstVisible();pEntry;pEntry=(SvLBoxEntry*)NextVisible(pEntry)) + { + if(IsExpanded(pEntry)) + { + StringPtr pString=new String(GetEntryText(pEntry)); + rEntries.Insert(pString,nCount++); + } + } +} + +PopupMenu* StyleTreeListBox_Impl::CreateContextMenu() +{ + return pDialog->CreateContextMenu(); +} + +BOOL StyleTreeListBox_Impl::DoubleClickHdl() + +/* [Beschreibung] + + + DoubleClick-Handler; ruft entsprechenden Link. + Virtuelle Methode aus SV. + +*/ +{ + aDoubleClickLink.Call(this); + return FALSE; +} + +//------------------------------------------------------------------------- + +void StyleTreeListBox_Impl::Command( const CommandEvent& rCEvt ) + +/* [Beschreibung] + + Command Handler; dieser executed ein PopupMenu (Gestalter + spezifisch). + Virtuelle Methode aus SV. + +*/ +{ + SvTreeListBox::Command(rCEvt); +} + +//------------------------------------------------------------------------- + +long StyleTreeListBox_Impl::Notify( NotifyEvent& rNEvt ) +{ + // handle <RETURN> as double click + + long nRet = 0; + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode(); + if ( !rKeyCode.GetModifier() && KEY_RETURN == rKeyCode.GetCode() ) + { + aDoubleClickLink.Call( this ); + nRet = 1; + } + } + + if ( !nRet ) + nRet = DropListBox_Impl::Notify( rNEvt ); + + return nRet; +} + +//------------------------------------------------------------------------- + +BOOL StyleTreeListBox_Impl::NotifyMoving(SvLBoxEntry* pTarget, + SvLBoxEntry* pEntry, + SvLBoxEntry*& rpNewParent, + ULONG& lPos) +/* [Beschreibung] + + NotifyMoving Handler; dieser leitet per Link das Event an den Dialog + weiter. + Virtuelle Methode aus SV. + +*/ +{ + if(!pTarget || !pEntry) + return FALSE; + aParent = GetEntryText(pTarget); + aStyle = GetEntryText(pEntry); + const BOOL bRet = (BOOL)aDropLink.Call(this); + rpNewParent = pTarget; + lPos=0; + IntlWrapper aIntlWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + const CollatorWrapper* pCollator = aIntlWrapper.getCaseCollator(); + for(SvLBoxEntry *pTmpEntry=FirstChild(pTarget); + pTmpEntry && COMPARE_LESS==pCollator->compareString( + GetEntryText(pTmpEntry),GetEntryText(pEntry)); + pTmpEntry=NextSibling(pTmpEntry),lPos++) ; + + return bRet? (BOOL)2: FALSE; +} + +//------------------------------------------------------------------------- + +long StyleTreeListBox_Impl::ExpandingHdl() + +/* [Beschreibung] + + ExpandingHdl Handler; der aktuelle Eintrag wird gemerkt. + Virtuelle Methode aus SV. + + [Querverweise] + <StyleTreeListBox_Impl::ExpandedHdl()> + +*/ +{ + pCurEntry = GetCurEntry(); + return TRUE; +} + +//------------------------------------------------------------------------- + +void StyleTreeListBox_Impl::ExpandedHdl() + +/* [Beschreibung] + + ExpandedHdl Handler; + Virtuelle Methode aus SV. + + [Querverweise] + <StyleTreeListBox_Impl::ExpandingHdl()> + +*/ + +{ + SvLBoxEntry *pEntry = GetHdlEntry(); + if(!IsExpanded(pEntry) && pCurEntry != GetCurEntry()) + SelectAll( FALSE ); + pCurEntry = 0; +} + +//------------------------------------------------------------------------- + +StyleTreeListBox_Impl::StyleTreeListBox_Impl( + SfxCommonTemplateDialog_Impl* pParent, WinBits nWinStyle) : + DropListBox_Impl(pParent->GetWindow(), nWinStyle, pParent), + pCurEntry(0), + pCommon(pParent) + +/* [Beschreibung] + + Konstruktor StyleTreeListBox_Impl + +*/ +{ + EnableContextMenuHandling(); +} + +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +class StyleTreeArr_Impl; + + +/* [Beschreibung] + + Interne Struktur f"ur den Aufbau der hierarchischen View + +*/ + +struct StyleTree_Impl +{ + String aName; + String aParent; + StyleTreeArr_Impl *pChilds; + BOOL bIsExpanded; + BOOL HasParent() const { return aParent.Len() != 0; } + + StyleTree_Impl(const String &rName, const String &rParent): + aName(rName), aParent(rParent), pChilds(0), bIsExpanded(0) {} + ~StyleTree_Impl(); + void Put(StyleTree_Impl* pIns, ULONG lPos=ULONG_MAX); + ULONG Count(); +}; + +typedef StyleTree_Impl* StyleTree_ImplPtr; +SV_DECL_PTRARR_DEL(StyleTreeArr_Impl, StyleTree_ImplPtr, 16, 8) +SV_IMPL_PTRARR(StyleTreeArr_Impl, StyleTree_ImplPtr) + + +ULONG StyleTree_Impl::Count() +{ + return pChilds ? pChilds->Count() : 0L; +} + +//------------------------------------------------------------------------- + +StyleTree_Impl::~StyleTree_Impl() +{ + delete pChilds; +} + +//------------------------------------------------------------------------- + +void StyleTree_Impl::Put(StyleTree_Impl* pIns, ULONG lPos) +{ + if ( !pChilds ) + pChilds = new StyleTreeArr_Impl; + + if ( ULONG_MAX == lPos ) + lPos = pChilds->Count(); + pChilds->Insert( pIns, (USHORT)lPos ); +} + +//------------------------------------------------------------------------- + +StyleTreeArr_Impl &MakeTree_Impl(StyleTreeArr_Impl &rArr) +{ + const USHORT nCount = rArr.Count(); + // Alle unter ihren Parents einordnen + USHORT i; + for(i = 0; i < nCount; ++i) + { + StyleTree_ImplPtr pEntry = rArr[i]; + if(pEntry->HasParent()) + { + for(USHORT j = 0; j < nCount; ++j) + { + StyleTree_ImplPtr pCmp = rArr[j]; + if(pCmp->aName == pEntry->aParent) + { + // initial sortiert einfuegen + USHORT ii; + IntlWrapper aIntlWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + const CollatorWrapper* pCollator = aIntlWrapper.getCaseCollator(); + for ( ii = 0; + ii < pCmp->Count() && COMPARE_LESS == + pCollator->compareString( (*pCmp->pChilds)[ii]->aName, + pEntry->aName);++ii) ; + pCmp->Put(pEntry,ii); + break; + } + } + } + } + // alle, die schon unter ihrem Parent eingeordnet wurden + // entfernen + for(i = 0; i < rArr.Count(); ) + { + if(rArr[i]->HasParent()) + rArr.Remove(i); + else + ++i; + } + return rArr; +} + +//------------------------------------------------------------------------- + + +inline BOOL IsExpanded_Impl( const ExpandedEntries& rEntries, + const String &rStr) +{ + USHORT nCount=rEntries.Count(); + for(USHORT n=0;n<nCount;n++) + if(*rEntries[n]==rStr) + return TRUE; + return FALSE; +} + + + +SvLBoxEntry* FillBox_Impl(SvTreeListBox *pBox, + StyleTree_ImplPtr pEntry, + const ExpandedEntries& rEntries, + SvLBoxEntry* pParent = 0) +{ + SvLBoxEntry* pNewEntry = pBox->InsertEntry(pEntry->aName, pParent); + const USHORT nCount = pEntry->pChilds? pEntry->pChilds->Count(): 0; + for(USHORT i = 0; i < nCount; ++i) + FillBox_Impl(pBox, (*pEntry->pChilds)[i], rEntries, pNewEntry); + return pNewEntry; +} + +//------------------------------------------------------------------------- + +// Konstruktor + +SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl( SfxBindings* pB, SfxDockingWindow* pW ) : + + aISfxTemplateCommon ( this ), + pBindings ( pB ), + pWindow ( pW ), + pModule ( NULL ), + pTimer ( NULL ), + m_pStyleFamiliesId ( NULL ), + pStyleSheetPool ( NULL ), + pTreeBox ( NULL ), + pCurObjShell ( NULL ), + xModuleManager ( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.frame.ModuleManager") ), UNO_QUERY ), + pbDeleted ( NULL ), + + aFmtLb ( this, WB_BORDER | WB_TABSTOP | WB_SORT ), + aFilterLb ( pW, WB_BORDER | WB_DROPDOWN | WB_TABSTOP ), + + nActFamily ( 0xffff ), + nActFilter ( 0 ), + nAppFilter ( 0 ), + + bDontUpdate ( FALSE ), + bIsWater ( FALSE ), + bEnabled ( TRUE ), + bUpdate ( FALSE ), + bUpdateFamily ( FALSE ), + bCanEdit ( FALSE ), + bCanDel ( FALSE ), + bCanNew ( TRUE ), + bWaterDisabled ( FALSE ), + bNewByExampleDisabled ( FALSE ), + bUpdateByExampleDisabled( FALSE ), + bTreeDrag ( TRUE ), + bHierarchical ( FALSE ), + bBindingUpdate ( TRUE ) +{ + aFmtLb.SetHelpId( HID_TEMPLATE_FMT ); + aFilterLb.SetHelpId( HID_TEMPLATE_FILTER ); + aFmtLb.SetWindowBits( WB_SORT | WB_HIDESELECTION ); + Font aFont = aFmtLb.GetFont(); + aFont.SetWeight( WEIGHT_NORMAL ); + aFmtLb.SetFont( aFont ); +} + +//------------------------------------------------------------------------- + +SfxCommonTemplateDialog_Impl::SfxCommonTemplateDialog_Impl( SfxBindings* pB, ModalDialog* pW ) : + + aISfxTemplateCommon ( this ), + pBindings ( pB ), + pWindow ( pW ), + pModule ( NULL ), + pTimer ( NULL ), + pStyleSheetPool ( NULL ), + pTreeBox ( NULL ), + pCurObjShell ( NULL ), + pbDeleted ( NULL ), + + aFmtLb ( this, SfxResId( BT_VLIST ) ), + aFilterLb ( pW, SfxResId( BT_FLIST ) ), + + nActFamily ( 0xffff ), + nActFilter ( 0 ), + nAppFilter ( 0 ), + + bDontUpdate ( FALSE ), + bIsWater ( FALSE ), + bEnabled ( TRUE ), + bUpdate ( FALSE ), + bUpdateFamily ( FALSE ), + bCanEdit ( FALSE ), + bCanDel ( FALSE ), + bCanNew ( TRUE ), + bWaterDisabled ( FALSE ), + bNewByExampleDisabled ( FALSE ), + bUpdateByExampleDisabled( FALSE ), + bTreeDrag ( TRUE ), + bHierarchical ( FALSE ), + bBindingUpdate ( TRUE ) + +{ + aFmtLb.SetWindowBits( WB_SORT ); +} + +//------------------------------------------------------------------------- + +USHORT SfxCommonTemplateDialog_Impl::StyleNrToInfoOffset(USHORT nId) +{ + const SfxStyleFamilyItem *pItem=pStyleFamilies->GetObject(nId); + return SfxFamilyIdToNId(pItem->GetFamily())-1; +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog_Impl::EnableEdit(BOOL bEnable) +{ + SfxCommonTemplateDialog_Impl::EnableEdit( bEnable ); + if( !bEnable || !bUpdateByExampleDisabled ) + EnableItem( SID_STYLE_UPDATE_BY_EXAMPLE, bEnable); +} + +//------------------------------------------------------------------------- + + +USHORT SfxCommonTemplateDialog_Impl::InfoOffsetToStyleNr(USHORT nId) +{ + for ( USHORT i=0;i<pStyleFamilies->Count();i++ ) + if ( SfxFamilyIdToNId(pStyleFamilies->GetObject(i)->GetFamily()) == nId+1 ) + return i; + DBG_ERROR("Style Nummer nicht gefunden"); + return 0; +} + + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::ReadResource() +{ + // globale Benutzer-Resource auslesen + USHORT i; + for(i = 0; i < MAX_FAMILIES; ++i) + pFamilyState[i] = 0; + + SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); + pCurObjShell = pViewFrame->GetObjectShell(); + ResMgr* pMgr = pCurObjShell ? pCurObjShell->GetResMgr() : NULL; + ResId aFamId( DLG_STYLE_DESIGNER, *pMgr ); + aFamId.SetRT(RSC_SFX_STYLE_FAMILIES); + m_pStyleFamiliesId = new ResId( aFamId.GetId(), *pMgr ); + m_pStyleFamiliesId->SetRT(RSC_SFX_STYLE_FAMILIES); + if( !pMgr || !pMgr->IsAvailable( aFamId ) ) + pStyleFamilies = new SfxStyleFamilies; + else + pStyleFamilies = new SfxStyleFamilies( aFamId ); + + nActFilter = pCurObjShell ? static_cast< USHORT >( LoadFactoryStyleFilter( pCurObjShell ) ) : 0xFFFF; + if ( pCurObjShell && 0xFFFF == nActFilter ) + nActFilter = pCurObjShell->GetAutoStyleFilterIndex(); + + // Einfuegen in die Toolbox + // umgekehrte Reihenfolge, da immer vorne eingefuegt wird. + USHORT nCount = pStyleFamilies->Count(); + + pBindings->ENTERREGISTRATIONS(); + + for(i = 0; i < nCount; ++i) + { + USHORT nSlot = 0; + switch((USHORT)pStyleFamilies->GetObject(i)->GetFamily()) + { + case SFX_STYLE_FAMILY_CHAR: nSlot = SID_STYLE_FAMILY1; break; + case SFX_STYLE_FAMILY_PARA: nSlot = SID_STYLE_FAMILY2; break; + case SFX_STYLE_FAMILY_FRAME:nSlot = SID_STYLE_FAMILY3; break; + case SFX_STYLE_FAMILY_PAGE: nSlot = SID_STYLE_FAMILY4; break; + case SFX_STYLE_FAMILY_PSEUDO: nSlot = SID_STYLE_FAMILY5; break; + default: DBG_ERROR("unbekannte StyleFamily"); break; + } + pBoundItems[i] = + new SfxTemplateControllerItem(nSlot, *this, *pBindings); + } + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_WATERCAN, *this, *pBindings); + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_NEW_BY_EXAMPLE, *this, *pBindings); + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_UPDATE_BY_EXAMPLE, *this, *pBindings); + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_NEW, *this, *pBindings); + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_DRAGHIERARCHIE, *this, *pBindings); + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_EDIT, *this, *pBindings); + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_DELETE, *this, *pBindings); + pBoundItems[i++] = new SfxTemplateControllerItem( + SID_STYLE_FAMILY, *this, *pBindings); + pBindings->LEAVEREGISTRATIONS(); + + for(; i < COUNT_BOUND_FUNC; ++i) + pBoundItems[i] = 0; + + StartListening(*pBindings); + +//In umgekehrter Reihenfolge des Auftretens in den Stylefamilies einfuegen. +//Das ist fuer den Toolbar des Gestalters. Die Listbox des Kataloges achtet +//selbst auf korrekte Reihenfolge. + +//Reihenfolgen: Reihenfolge in der Resource = Reihenfolge in Toolbar bzw. +//Listbox. +//Reihenfolge aufsteigender SIDs: Niedrige SIDs werden als erstes angezeigt, +//wenn Vorlagen mehrerer Familien aktiv sind. + + // in the Writer the UpdateStyleByExample Toolbox button is removed and + // the NewStyle button gets a PopupMenu + if(nCount > 4) + ReplaceUpdateButtonByMenu(); + + for( ; nCount--; ) + { + const SfxStyleFamilyItem *pItem = pStyleFamilies->GetObject( nCount ); + USHORT nId = SfxFamilyIdToNId( pItem->GetFamily() ); + InsertFamilyItem( nId, pItem ); + } + + LoadedFamilies(); + + USHORT nStart = SID_STYLE_FAMILY1; + USHORT nEnd = SID_STYLE_FAMILY4; + + for ( i = nStart; i <= nEnd; i++ ) + pBindings->Update(i); + + pModule = pCurObjShell ? pCurObjShell->GetModule() : NULL; +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::ClearResource() +{ + ClearFamilyList(); + DELETEX(pStyleFamilies); + USHORT i; + for ( i = 0; i < MAX_FAMILIES; ++i ) + DELETEX(pFamilyState[i]); + for ( i = 0; i < COUNT_BOUND_FUNC; ++i ) + delete pBoundItems[i]; + pCurObjShell = NULL; + + DELETEZ( m_pStyleFamiliesId ); +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::Initialize() +{ + // globale Benutzer-Resource auslesen + ReadResource(); + pBindings->Invalidate( SID_STYLE_FAMILY ); + pBindings->Update( SID_STYLE_FAMILY ); + Update_Impl(); + + aFilterLb.SetSelectHdl( LINK( this, SfxCommonTemplateDialog_Impl, FilterSelectHdl ) ); + aFmtLb.SetDoubleClickHdl( LINK( this, SfxCommonTemplateDialog_Impl, ApplyHdl ) ); + aFmtLb.SetSelectHdl( LINK( this, SfxCommonTemplateDialog_Impl, FmtSelectHdl ) ); + + aFilterLb.Show(); + aFmtLb.Show(); +} + +//------------------------------------------------------------------------- + +SfxCommonTemplateDialog_Impl::~SfxCommonTemplateDialog_Impl() +{ + String aEmpty; + if ( bIsWater ) + Execute_Impl(SID_STYLE_WATERCAN, aEmpty, aEmpty, 0); + GetWindow()->Hide(); + DELETEX(pStyleFamilies); + DELETEZ( m_pStyleFamiliesId ); + USHORT i; + for ( i = 0; i < MAX_FAMILIES; ++i ) + DELETEX(pFamilyState[i]); + for ( i = 0; i < COUNT_BOUND_FUNC; ++i ) + delete pBoundItems[i]; + if ( pStyleSheetPool ) + EndListening(*pStyleSheetPool); + pStyleSheetPool = NULL; + delete pTreeBox; + delete pTimer; + if ( pbDeleted ) + { + pbDeleted->bDead = true; + pbDeleted = NULL; + } +} + +//------------------------------------------------------------------------- + +USHORT SfxCommonTemplateDialog_Impl::SfxFamilyIdToNId( SfxStyleFamily nFamily ) +{ + switch ( nFamily ) + { + case SFX_STYLE_FAMILY_CHAR: return 1; + case SFX_STYLE_FAMILY_PARA: return 2; + case SFX_STYLE_FAMILY_FRAME: return 3; + case SFX_STYLE_FAMILY_PAGE: return 4; + case SFX_STYLE_FAMILY_PSEUDO: return 5; + default: return 0; + } +} + +void SfxCommonTemplateDialog_Impl::SetAutomaticFilter() +{ + USHORT nCount = aFilterLb.GetEntryCount(); + for ( USHORT i = 0; i < nCount; ++i ) + { + ULONG nFlags = (ULONG)aFilterLb.GetEntryData(i); + if ( SFXSTYLEBIT_AUTO == nFlags ) + { + // automatic entry found -> select it + aFilterLb.SelectEntryPos(i); + // then call the handler to filter the styles + FilterSelect( i - 1 ); + break; + } + } +} + +//------------------------------------------------------------------------- + +// Hilfsfunktion: Zugriff auf aktuelles Family-Item +const SfxStyleFamilyItem *SfxCommonTemplateDialog_Impl::GetFamilyItem_Impl() const +{ + const USHORT nCount = pStyleFamilies->Count(); + for(USHORT i = 0; i < nCount; ++i) + { + const SfxStyleFamilyItem *pItem = pStyleFamilies->GetObject(i); +// if(!pItem)continue; + USHORT nId = SfxFamilyIdToNId(pItem->GetFamily()); + if(nId == nActFamily) + return pItem; + } + return 0; +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::SelectStyle(const String &rStr) +{ + const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); + if ( !pItem ) + return; + const SfxStyleFamily eFam = pItem->GetFamily(); + SfxStyleSheetBase* pStyle = pStyleSheetPool->Find( rStr, eFam, SFXSTYLEBIT_ALL ); + if( pStyle ) + EnableEdit( !(pStyle->GetMask() & SFXSTYLEBIT_READONLY) ); + else + EnableEdit(FALSE); + + if ( pTreeBox ) + { + if ( rStr.Len() ) + { + SvLBoxEntry* pEntry = pTreeBox->First(); + while ( pEntry ) + { + if ( pTreeBox->GetEntryText( pEntry ) == rStr ) + { + pTreeBox->MakeVisible( pEntry ); + pTreeBox->Select( pEntry ); + return; + } + pEntry = pTreeBox->Next( pEntry ); + } + } + else + pTreeBox->SelectAll( FALSE ); + } + else + { + BOOL bSelect = ( rStr.Len() > 0 ); + if ( bSelect ) + { + SvLBoxEntry* pEntry = (SvLBoxEntry*)aFmtLb.FirstVisible(); + while ( pEntry && aFmtLb.GetEntryText( pEntry ) != rStr ) + pEntry = (SvLBoxEntry*)aFmtLb.NextVisible( pEntry ); + if ( !pEntry ) + bSelect = FALSE; + else + { + aFmtLb.MakeVisible( pEntry ); + aFmtLb.Select( pEntry ); + bWaterDisabled = !HasSelectedStyle(); //added by BerryJia for fixing Bug76391 2003-1-22 + FmtSelectHdl( NULL ); + } + } + + if ( !bSelect ) + { + aFmtLb.SelectAll( FALSE ); + EnableEdit(FALSE); + } + } +} + +//------------------------------------------------------------------------- + +String SfxCommonTemplateDialog_Impl::GetSelectedEntry() const +{ + String aRet; + if ( pTreeBox ) + { + SvLBoxEntry* pEntry = pTreeBox->FirstSelected(); + if ( pEntry ) + aRet = pTreeBox->GetEntryText( pEntry ); + } + else + { + SvLBoxEntry* pEntry = aFmtLb.FirstSelected(); + if ( pEntry ) + aRet = aFmtLb.GetEntryText( pEntry ); + } + return aRet; +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::EnableTreeDrag( BOOL bEnable ) +{ + if ( pStyleSheetPool ) + { + SfxStyleSheetBase* pStyle = pStyleSheetPool->First(); + if ( pTreeBox ) + { + if ( pStyle && pStyle->HasParentSupport() && bEnable ) + pTreeBox->SetDragDropMode(SV_DRAGDROP_CTRL_MOVE); + else + pTreeBox->SetDragDropMode(SV_DRAGDROP_NONE); + } + } + bTreeDrag = bEnable; +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::FillTreeBox() +{ + DBG_ASSERT( pTreeBox, "FillTreeBox() without treebox"); + if(pStyleSheetPool && nActFamily != 0xffff) + { + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + pStyleSheetPool->SetSearchMask(pItem->GetFamily(), SFXSTYLEBIT_ALL); + StyleTreeArr_Impl aArr; + SfxStyleSheetBase *pStyle = pStyleSheetPool->First(); + if(pStyle && pStyle->HasParentSupport() && bTreeDrag ) + pTreeBox->SetDragDropMode(SV_DRAGDROP_CTRL_MOVE); + else + pTreeBox->SetDragDropMode(SV_DRAGDROP_NONE); + while(pStyle) + { + StyleTree_ImplPtr pNew = + new StyleTree_Impl(pStyle->GetName(), pStyle->GetParent()); + aArr.Insert(pNew, aArr.Count()); + pStyle = pStyleSheetPool->Next(); + } + MakeTree_Impl(aArr); + ExpandedEntries aEntries; + if(pTreeBox) + ((const StyleTreeListBox_Impl *)pTreeBox)-> + MakeExpanded_Impl( aEntries); + pTreeBox->SetUpdateMode( FALSE ); + pTreeBox->Clear(); + const USHORT nCount = aArr.Count(); + for(USHORT i = 0; i < nCount; ++i) + FillBox_Impl(pTreeBox, aArr[i], aEntries); + +// EnableEdit(FALSE); + EnableItem(SID_STYLE_WATERCAN,FALSE); + + SfxTemplateItem* pState = pFamilyState[nActFamily-1]; + + if ( nCount ) + pTreeBox->Expand( pTreeBox->First() ); + + for ( SvLBoxEntry* pEntry = pTreeBox->First(); pEntry; pEntry = pTreeBox->Next( pEntry ) ) + { + if ( IsExpanded_Impl( aEntries, pTreeBox->GetEntryText( pEntry ) ) ) + pTreeBox->Expand( pEntry ); + } + + pTreeBox->SetUpdateMode( TRUE ); + + String aStyle; + if(pState) //Aktuellen Eintrag selektieren + aStyle = pState->GetStyleName(); + SelectStyle(aStyle); + EnableDelete(); + } +} + +//------------------------------------------------------------------------- +BOOL SfxCommonTemplateDialog_Impl::HasSelectedStyle() const +{ + return pTreeBox? pTreeBox->FirstSelected() != 0: + aFmtLb.GetSelectionCount() != 0; +} + + +//------------------------------------------------------------------------- + +// intern: Aktualisierung der Anzeige +void SfxCommonTemplateDialog_Impl::UpdateStyles_Impl(USHORT nFlags) // Flags, was aktualisiert werden soll (s.o.) +{ + DBG_ASSERT(nFlags, "nichts zu tun"); + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + if (!pItem) + { + // Ist beim Vorlagenkatalog der Fall + SfxTemplateItem **ppItem = pFamilyState; + const USHORT nFamilyCount = pStyleFamilies->Count(); + USHORT n; + for(n=0;n<nFamilyCount;n++) + if(ppItem[StyleNrToInfoOffset(n)])break; + if ( n == nFamilyCount ) + // passiert gelegentlich bei Beichten, Formularen etc.; weiss der Teufel warum + return; + ppItem+=StyleNrToInfoOffset(n); + nAppFilter = (*ppItem)->GetValue(); + FamilySelect( StyleNrToInfoOffset(n)+1 ); + pItem = GetFamilyItem_Impl(); + } + + const SfxStyleFamily eFam = pItem->GetFamily(); + + SfxFilterTupel *pT = pItem->GetFilterList().GetObject(nActFilter); + USHORT nFilter = pT ? pItem->GetFilterList().GetObject(nActFilter)->nFlags : 0; + if(!nFilter) // automatisch + nFilter = nAppFilter; + + DBG_ASSERT(pStyleSheetPool, "kein StyleSheetPool"); + if(pStyleSheetPool) + { + pStyleSheetPool->SetSearchMask(eFam, nFilter); + pItem = GetFamilyItem_Impl(); + if((nFlags & UPDATE_FAMILY) == UPDATE_FAMILY) + { + CheckItem(nActFamily, TRUE); // Button in Toolbox checken + aFilterLb.SetUpdateMode(FALSE); + aFilterLb.Clear(); + //insert hierarchical at the beginning + USHORT nPos = aFilterLb.InsertEntry(String(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)), 0); + aFilterLb.SetEntryData( nPos, (void*)(ULONG)SFXSTYLEBIT_ALL ); + const SfxStyleFilter& rFilter = pItem->GetFilterList(); + for(USHORT i = 0; i < rFilter.Count(); ++i) + { + ULONG nFilterFlags = rFilter.GetObject(i)->nFlags; + nPos = aFilterLb.InsertEntry( rFilter.GetObject(i)->aName ); + aFilterLb.SetEntryData( nPos, (void*)nFilterFlags ); + } + if(nActFilter < aFilterLb.GetEntryCount() - 1) + aFilterLb.SelectEntryPos(nActFilter + 1); + else + { + nActFilter = 0; + aFilterLb.SelectEntryPos(1); + SfxFilterTupel *pActT = rFilter.GetObject(nActFilter); + USHORT nFilterFlags = pActT ? rFilter.GetObject(nActFilter)->nFlags : 0; + pStyleSheetPool->SetSearchMask(eFam, nFilterFlags); + } + + //Falls in Treedarstellung wieder Family Hierarchie selektieren + if(pTreeBox) + aFilterLb.SelectEntry(String(SfxResId(STR_STYLE_FILTER_HIERARCHICAL))); + + // show maximum 12 entries + aFilterLb.SetDropDownLineCount( MAX_FILTER_ENTRIES ); + aFilterLb.SetUpdateMode(TRUE); + } + else + { + if( nActFilter < aFilterLb.GetEntryCount() - 1) + aFilterLb.SelectEntryPos(nActFilter + 1); + else + { + nActFilter = 0; + aFilterLb.SelectEntryPos(1); + } + } + + if(nFlags & UPDATE_FAMILY_LIST) + { +// EnableEdit(FALSE); + EnableItem(SID_STYLE_WATERCAN,FALSE); + + SfxStyleSheetBase *pStyle = pStyleSheetPool->First(); + SvLBoxEntry* pEntry = aFmtLb.First(); + SvStringsDtor aStrings; + + while( pStyle ) + { + //Bubblesort + for( USHORT nPos = aStrings.Count() + 1 ; nPos-- ;) + { + if( !nPos || *aStrings[nPos-1] < pStyle->GetName() ) + { + // Die Namen stehen in den Styles, also nicht kopieren + // Reingefallen!: Writer hat insgesamt nur 1 Style + aStrings.Insert( + new String( pStyle->GetName() ), nPos ); + break; + } + } + pStyle = pStyleSheetPool->Next(); + } + + + USHORT nCount = aStrings.Count(); + USHORT nPos = 0; + while( nPos < nCount && pEntry && + *aStrings[ nPos ] == aFmtLb.GetEntryText( pEntry ) ) + { + nPos++; + pEntry = aFmtLb.Next( pEntry ); + } + + if( nPos < nCount || pEntry ) + { + // Box mit den Vorlagen fuellen + aFmtLb.SetUpdateMode(FALSE); + aFmtLb.Clear(); + + nPos = 0; + while( nPos < nCount ) + aFmtLb.InsertEntry( *aStrings.GetObject( nPos++ )); + aFmtLb.SetUpdateMode(TRUE); + } + // aktuelle Vorlage anzeigen + SfxTemplateItem *pState = pFamilyState[nActFamily-1]; + String aStyle; + if(pState) //Aktuellen Eintrag selektieren + aStyle = pState->GetStyleName(); + SelectStyle(aStyle); + EnableDelete(); + } + } +} + +//------------------------------------------------------------------------- + +// Aktualisierung Anzeige: Gie\skanne an/aus +void SfxCommonTemplateDialog_Impl::SetWaterCanState(const SfxBoolItem *pItem) +{ +// EnableItem(SID_STYLE_WATERCAN, pItem != 0); + bWaterDisabled = pItem == 0; +//added by BerryJia for fixing Bug76391 2003-1-7 + if(!bWaterDisabled) + bWaterDisabled = !HasSelectedStyle(); + + if(pItem && !bWaterDisabled) + { + CheckItem(SID_STYLE_WATERCAN, pItem->GetValue()); + EnableItem( SID_STYLE_WATERCAN, TRUE ); + } + else + if(!bWaterDisabled) + EnableItem(SID_STYLE_WATERCAN, TRUE); + else + EnableItem(SID_STYLE_WATERCAN, FALSE); + +//Waehrend Giesskannenmodus Statusupdates ignorieren. + + USHORT nCount=pStyleFamilies->Count(); + pBindings->EnterRegistrations(); + for(USHORT n=0; n<nCount; n++) + { + SfxControllerItem *pCItem=pBoundItems[n]; + BOOL bChecked = pItem && pItem->GetValue(); + if( pCItem->IsBound() == bChecked ) + { + if( !bChecked ) + pCItem->ReBind(); + else + pCItem->UnBind(); + } + } + pBindings->LeaveRegistrations(); +} + +//------------------------------------------------------------------------- + +// Item mit dem Status einer Family wird kopiert und gemerkt +// (Aktualisierung erfolgt, wenn alle Stati aktualisiert worden sind. +// Siehe auch: <SfxBindings::AddDoneHdl(const Link &)> + +void SfxCommonTemplateDialog_Impl::SetFamilyState( USHORT nSlotId, const SfxTemplateItem* pItem ) +{ + USHORT nIdx = nSlotId - SID_STYLE_FAMILY_START; + DELETEZ(pFamilyState[nIdx]); + if ( pItem ) + pFamilyState[nIdx] = new SfxTemplateItem(*pItem); + bUpdate = TRUE; + + // Wenn verwendete Vorlagen ( wie zum Teufel findet man das heraus ?? ) + bUpdateFamily = TRUE; +} + +//------------------------------------------------------------------------- + +// Benachrichtigung durch SfxBindings, da"s die Aktualisierung +// beendet ist. St"o\st die Aktualisierung der Anzeige an. + +void SfxCommonTemplateDialog_Impl::Update_Impl() +{ + BOOL bDocChanged=FALSE; + SfxStyleSheetBasePool* pNewPool = NULL; + SfxViewFrame* pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); + SfxObjectShell* pDocShell = pViewFrame->GetObjectShell(); + if( pDocShell ) + pNewPool = pDocShell->GetStyleSheetPool(); + + if ( pNewPool != pStyleSheetPool && pDocShell ) + { + SfxModule* pNewModule = pDocShell->GetModule(); + if( pNewModule && pNewModule != pModule ) + { + ClearResource(); + ReadResource(); + } + if ( pStyleSheetPool ) + { + EndListening(*pStyleSheetPool); + pStyleSheetPool = 0; + } + + if ( pNewPool ) + { + StartListening(*pNewPool); + pStyleSheetPool = pNewPool; + bDocChanged=TRUE; + } +// InvalidateBindings(); + } + + if (bUpdateFamily) + UpdateFamily_Impl(); + + USHORT i; + for(i = 0; i < MAX_FAMILIES; ++i) + if(pFamilyState[i]) + break; + if(i == MAX_FAMILIES || !pNewPool) + // nichts erlaubt + return; + + SfxTemplateItem *pItem = 0; + // aktueller Bereich nicht innerhalb der erlaubten Bereiche + // oder Default + if(nActFamily == 0xffff || 0 == (pItem = pFamilyState[nActFamily-1] ) ) + { + CheckItem(nActFamily, FALSE); + SfxTemplateItem **ppItem = pFamilyState; + const USHORT nFamilyCount = pStyleFamilies->Count(); + USHORT n; + for(n=0;n<nFamilyCount;n++) + if(ppItem[StyleNrToInfoOffset(n)])break; + ppItem+=StyleNrToInfoOffset(n); + + nAppFilter = (*ppItem)->GetValue(); + FamilySelect( StyleNrToInfoOffset(n)+1 ); + + pItem = *ppItem; + } + else if( bDocChanged ) + { + // andere DocShell -> alles neu + CheckItem( nActFamily, TRUE ); + nActFilter = static_cast< USHORT >( LoadFactoryStyleFilter( pDocShell ) ); + if ( 0xFFFF == nActFilter ) + nActFilter = pDocShell->GetAutoStyleFilterIndex(); + + nAppFilter = pItem->GetValue(); + if(!pTreeBox) + { + UpdateStyles_Impl(UPDATE_FAMILY_LIST); + } + else + FillTreeBox(); + } + else + { + // anderer Filter fuer automatisch + CheckItem( nActFamily, TRUE ); + const SfxStyleFamilyItem *pStyleItem = GetFamilyItem_Impl(); +#if OSL_DEBUG_LEVEL > 1 + SfxFilterTupel *pT; + pT = pStyleItem->GetFilterList().GetObject(nActFilter); +#endif + if(0 == pStyleItem->GetFilterList().GetObject(nActFilter)->nFlags + && nAppFilter != pItem->GetValue()) + { + nAppFilter = pItem->GetValue(); + if(!pTreeBox) + UpdateStyles_Impl(UPDATE_FAMILY_LIST); + else + FillTreeBox(); + } + else + nAppFilter = pItem->GetValue(); + } + const String aStyle(pItem->GetStyleName()); + SelectStyle(aStyle); + EnableDelete(); + EnableNew( bCanNew ); +} + +//------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonTemplateDialog_Impl, TimeOut, Timer *, pTim ) +{ + (void)pTim; // unused + if(!bDontUpdate) + { + bDontUpdate=TRUE; + if(!pTreeBox) + UpdateStyles_Impl(UPDATE_FAMILY_LIST); + else + { + FillTreeBox(); + SfxTemplateItem *pState = pFamilyState[nActFamily-1]; + if(pState) + { + const String aStyle(pState->GetStyleName()); + SelectStyle(aStyle); + EnableDelete(); + } + } + bDontUpdate=FALSE; + DELETEZ(pTimer); + } + else + pTimer->Start(); + return 0; +} + + +//------------------------------------------------------------------------- +void SfxCommonTemplateDialog_Impl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + // Aktualisierung anstossen + if(rHint.Type() == TYPE(SfxSimpleHint)) + { + switch(((SfxSimpleHint&) rHint ).GetId()) + { + case SFX_HINT_UPDATEDONE: + { + SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); + SfxObjectShell *pDocShell = pViewFrame->GetObjectShell(); + if ( + bUpdate && + ( + !IsCheckedItem(SID_STYLE_WATERCAN) || + (pDocShell && pDocShell->GetStyleSheetPool() != pStyleSheetPool) + ) + ) + { + bUpdate = FALSE; + Update_Impl(); + } + else if ( bUpdateFamily ) + { + UpdateFamily_Impl(); + } + + if( pStyleSheetPool ) + { + String aStr = GetSelectedEntry(); + if( aStr.Len() && pStyleSheetPool ) + { + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + if( !pItem ) break; + const SfxStyleFamily eFam = pItem->GetFamily(); + SfxStyleSheetBase *pStyle = + pStyleSheetPool->Find( + aStr, eFam, SFXSTYLEBIT_ALL ); + if( pStyle ) + EnableEdit( + !(pStyle->GetMask() & SFXSTYLEBIT_READONLY) ); + else + EnableEdit(FALSE); + } + } + break; + } + // noetig, wenn zwichen Dokumenten umgeschaltet wird, + // aber in beiden Dokumenten die gleiche Vorlage gilt. + // Nicht sofort Update_Impl rufen, fuer den Fall da\s eines + // der Dokumente ein internes InPlaceObjekt ist! + case SFX_HINT_DOCCHANGED: + bUpdate = TRUE; + break; + case SFX_HINT_DYING: + { + EndListening(*pStyleSheetPool); + pStyleSheetPool=0; + break; + } + } + } + + // Timer nicht aufsetzen, wenn der StyleSheetPool in die Kiste geht, denn + // es kann sein, da\s sich ein neuer erst anmeldet, nachdem der Timer + // abgelaufen ist - macht sich schlecht in UpdateStyles_Impl() ! + + ULONG nId = rHint.ISA(SfxSimpleHint) ? ( (SfxSimpleHint&)rHint ).GetId() : 0; + + if(!bDontUpdate && nId != SFX_HINT_DYING && + (rHint.Type() == TYPE(SfxStyleSheetPoolHint)|| + rHint.Type() == TYPE(SfxStyleSheetHint) || + rHint.Type() == TYPE( SfxStyleSheetHintExtended ))) + { + if(!pTimer) + { + pTimer=new Timer; + pTimer->SetTimeout(500); + pTimer->SetTimeoutHdl(LINK(this,SfxCommonTemplateDialog_Impl,TimeOut)); + } + pTimer->Start(); + + } +} + + +//------------------------------------------------------------------------- + +// Anderer Filter; kann durch den Benutzer umgeschaltet werden +// oder als Folge von Neu oder Bearbeiten, wenn die aktuelle +// Vorlage einem anderen Filter zugewiesen wurde. +void SfxCommonTemplateDialog_Impl::FilterSelect( + USHORT nEntry, // Idx des neuen Filters + BOOL bForce ) // Aktualisierung erzwingen, auch wenn der neue Filter gleich dem aktuellen ist +{ + if( nEntry != nActFilter || bForce ) + { + nActFilter = nEntry; + SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); + SfxObjectShell *pDocShell = pViewFrame->GetObjectShell(); + if (pDocShell) + { + pDocShell->SetAutoStyleFilterIndex(nActFilter); + SaveFactoryStyleFilter( pDocShell, nActFilter ); + } + + SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool; + pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): 0; + if ( pOldStyleSheetPool != pStyleSheetPool ) + { + if ( pOldStyleSheetPool ) + EndListening(*pOldStyleSheetPool); + if ( pStyleSheetPool ) + StartListening(*pOldStyleSheetPool); + } + + UpdateStyles_Impl(UPDATE_FAMILY_LIST); + } +} + +//------------------------------------------------------------------------- + +// Intern: Ausf"uhren von Funktionen "uber den Dispatcher +BOOL SfxCommonTemplateDialog_Impl::Execute_Impl( + USHORT nId, const String &rStr, const String& rRefStr, USHORT nFamily, + USHORT nMask, USHORT *pIdx, const USHORT* pModifier) +{ + SfxDispatcher &rDispatcher = *SFX_APP()->GetDispatcher_Impl(); + SfxStringItem aItem(nId, rStr); + SfxUInt16Item aFamily(SID_STYLE_FAMILY, nFamily); + SfxUInt16Item aMask( SID_STYLE_MASK, nMask ); + SfxStringItem aUpdName(SID_STYLE_UPD_BY_EX_NAME, rStr); + SfxStringItem aRefName( SID_STYLE_REFERENCE, rRefStr ); + const SfxPoolItem* pItems[ 6 ]; + USHORT nCount = 0; + if( rStr.Len() ) + pItems[ nCount++ ] = &aItem; + pItems[ nCount++ ] = &aFamily; + if( nMask ) + pItems[ nCount++ ] = &aMask; + if(SID_STYLE_UPDATE_BY_EXAMPLE == nId) + { + //Sonderloesung fuer Numerierungsupdate im Writer + const String aTemplName(GetSelectedEntry()); + aUpdName.SetValue(aTemplName); + pItems[ nCount++ ] = &aUpdName; + } + if ( rRefStr.Len() ) + pItems[ nCount++ ] = &aRefName; + + pItems[ nCount++ ] = 0; + + Deleted aDeleted; + pbDeleted = &aDeleted; + USHORT nModi = pModifier ? *pModifier : 0; + const SfxPoolItem* pItem = rDispatcher.Execute( + nId, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD | SFX_CALLMODE_MODAL, + pItems, nModi ); + + // FIXME: Dialog can be destroyed while in Execute() check stack variable for dtor flag! + if ( !pItem || aDeleted() ) + return FALSE; + + if ( nId == SID_STYLE_NEW || SID_STYLE_EDIT == nId ) + { + SfxUInt16Item *pFilterItem = PTR_CAST(SfxUInt16Item, pItem); + DBG_ASSERT(pFilterItem, "SfxUINT16Item erwartet"); + USHORT nFilterFlags = pFilterItem->GetValue() & ~SFXSTYLEBIT_USERDEF; + if(!nFilterFlags) // Benutzervorlage? + nFilterFlags = pFilterItem->GetValue(); + const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl(); + const USHORT nFilterCount = (USHORT) pFamilyItem->GetFilterList().Count(); + + for ( USHORT i = 0; i < nFilterCount; ++i ) + { + const SfxFilterTupel *pTupel = + pFamilyItem->GetFilterList().GetObject(i); + + if ( ( pTupel->nFlags & nFilterFlags ) == nFilterFlags && pIdx ) + *pIdx = i; + } + } + + // Reset destroyed flag otherwise we use the pointer in the dtor + // where the local stack object is already destroyed. This would + // overwrite objects on the stack!! See #i100110 + pbDeleted = NULL; + return TRUE; +} + +//------------------------------------------------------------------------- + +// Handler der Listbox der Filter +IMPL_LINK( SfxCommonTemplateDialog_Impl, FilterSelectHdl, ListBox *, pBox ) +{ + if ( pBox->GetSelectEntry() == String(SfxResId(STR_STYLE_FILTER_HIERARCHICAL)) ) + { + if ( !bHierarchical ) + { + // TreeView einschalten + bHierarchical=TRUE; + const String aSelectEntry( GetSelectedEntry()); + aFmtLb.Hide(); + // aFilterLb.Disable(); + + pTreeBox = new StyleTreeListBox_Impl( + this, WB_HASBUTTONS | WB_HASLINES | + WB_BORDER | WB_TABSTOP | WB_HASLINESATROOT | + WB_HASBUTTONSATROOT | WB_HIDESELECTION ); + pTreeBox->SetFont( aFmtLb.GetFont() ); + + pTreeBox->SetPosSizePixel(aFmtLb.GetPosPixel(), aFmtLb.GetSizePixel()); + pTreeBox->SetNodeDefaultImages(); + pTreeBox->SetSelectHdl( + LINK(this, SfxCommonTemplateDialog_Impl, FmtSelectHdl)); + ((StyleTreeListBox_Impl*)pTreeBox)-> + SetDoubleClickHdl( + LINK(this, SfxCommonTemplateDialog_Impl, ApplyHdl)); + ((StyleTreeListBox_Impl*)pTreeBox)-> + SetDropHdl(LINK(this, SfxCommonTemplateDialog_Impl, DropHdl)); + pTreeBox->SetIndent(10); + + FillTreeBox(); + SelectStyle(aSelectEntry); + pTreeBox->Show(); + } + } + + else + { + DELETEZ(pTreeBox); + aFmtLb.Show(); + // aFilterLb.Enable(); + // Falls bHierarchical, kann sich die Familie geaendert haben + // minus one since hierarchical is inserted at the start + FilterSelect(pBox->GetSelectEntryPos() - 1, bHierarchical ); + bHierarchical=FALSE; +// UpdateStyles_Impl(UPDATE_FAMILY_LIST); // Anzeige aktualisieren + } + + return 0; +} + +//------------------------------------------------------------------------- + +// Select-Handler der Toolbox +void SfxCommonTemplateDialog_Impl::FamilySelect(USHORT nEntry) +{ + if( nEntry != nActFamily ) + { + CheckItem( nActFamily, FALSE ); + nActFamily = nEntry; + SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl(); + SfxUInt16Item aItem( SID_STYLE_FAMILY, nEntry ); + pDispat->Execute( SID_STYLE_FAMILY, SFX_CALLMODE_SYNCHRON, &aItem, 0L ); + pBindings->Invalidate( SID_STYLE_FAMILY ); + pBindings->Update( SID_STYLE_FAMILY ); + UpdateFamily_Impl(); + } +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::ActionSelect(USHORT nEntry) +{ + String aEmpty; + switch(nEntry) + { + case SID_STYLE_WATERCAN: + { + const BOOL bState = IsCheckedItem(nEntry); + BOOL bCheck; + SfxBoolItem aBool; + // wenn eine Vorlage ausgewaehlt ist. + if(!bState && aFmtLb.GetSelectionCount()) + { + const String aTemplName( + GetSelectedEntry()); + Execute_Impl( + SID_STYLE_WATERCAN, aTemplName, aEmpty, + (USHORT)GetFamilyItem_Impl()->GetFamily() ); + bCheck = TRUE; + } + else + { + Execute_Impl(SID_STYLE_WATERCAN, aEmpty, aEmpty, 0); + bCheck = FALSE; + } + CheckItem(nEntry, bCheck); + aBool.SetValue(bCheck); + SetWaterCanState(&aBool); + break; + } + case SID_STYLE_NEW_BY_EXAMPLE: + { + if(pStyleSheetPool && nActFamily != 0xffff) + { + const SfxStyleFamily eFam=GetFamilyItem_Impl()->GetFamily(); +//pStyleSheetPool->GetSearchFamily(); + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + USHORT nFilter; + if(pItem&&nActFilter!=0xffff) + { + nFilter = pItem->GetFilterList().GetObject( + nActFilter)->nFlags; + if(!nFilter) // automatisch + nFilter = nAppFilter; + } + else + nFilter=pStyleSheetPool->GetSearchMask(); + pStyleSheetPool->SetSearchMask( eFam, SFXSTYLEBIT_USERDEF ); + + SfxNewStyleDlg *pDlg = + // why? : FloatingWindow must not be parent of a modal dialog + new SfxNewStyleDlg(pWindow, *pStyleSheetPool); + if(RET_OK == pDlg->Execute()) + { + pStyleSheetPool->SetSearchMask(eFam, nFilter); + const String aTemplName(pDlg->GetName()); + Execute_Impl(SID_STYLE_NEW_BY_EXAMPLE, + aTemplName, aEmpty, + (USHORT)GetFamilyItem_Impl()->GetFamily(), + nFilter); + } + pStyleSheetPool->SetSearchMask( eFam, nFilter ); + delete pDlg; + } + break; + } + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + Execute_Impl(SID_STYLE_UPDATE_BY_EXAMPLE, + aEmpty, aEmpty, + (USHORT)GetFamilyItem_Impl()->GetFamily()); + break; + } + case SID_TEMPLATE_LOAD: + SFX_APP()->GetDispatcher_Impl()->Execute(nEntry); + break; + default: DBG_ERROR("not implemented"); break; + } +} + +//------------------------------------------------------------------------- + +static rtl::OUString getModuleIdentifier( const Reference< XModuleManager >& i_xModMgr, SfxObjectShell* i_pObjSh ) +{ + DBG_ASSERT( i_xModMgr.is(), "getModuleIdentifier(): no XModuleManager" ); + DBG_ASSERT( i_pObjSh, "getModuleIdentifier(): no ObjectShell" ); + + ::rtl::OUString sIdentifier; + + try + { + sIdentifier = i_xModMgr->identify( i_pObjSh->GetModel() ); + } + catch ( ::com::sun::star::frame::UnknownModuleException& ) + { + DBG_WARNING( "getModuleIdentifier(): unknown module" ); + } + catch ( Exception& ) + { + DBG_ERRORFILE( "getModuleIdentifier(): exception of XModuleManager::identify()" ); + } + + return sIdentifier; +} + +//------------------------------------------------------------------------- + +sal_Int32 SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter( SfxObjectShell* i_pObjSh ) +{ + DBG_ASSERT( i_pObjSh, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" ); + sal_Int32 nFilter = -1; + + Sequence< PropertyValue > lProps; + Reference< ::com::sun::star::container::XNameAccess > xContainer( xModuleManager, UNO_QUERY ); + if ( xContainer.is() ) + { + ::comphelper::SequenceAsHashMap aFactoryProps( + xContainer->getByName( getModuleIdentifier( xModuleManager, i_pObjSh ) ) ); + sal_Int32 nDefault = -1; + nFilter = aFactoryProps.getUnpackedValueOrDefault( DEFINE_CONST_UNICODE("ooSetupFactoryStyleFilter"), nDefault ); + } + + return nFilter; +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::SaveFactoryStyleFilter( SfxObjectShell* i_pObjSh, sal_Int32 i_nFilter ) +{ + DBG_ASSERT( i_pObjSh, "SfxCommonTemplateDialog_Impl::LoadFactoryStyleFilter(): no ObjectShell" ); + Reference< ::com::sun::star::container::XNameReplace > xContainer( xModuleManager, UNO_QUERY ); + if ( xContainer.is() ) + { + Sequence< PropertyValue > lProps(1); + lProps[0].Name = DEFINE_CONST_UNICODE("ooSetupFactoryStyleFilter"); + lProps[0].Value = makeAny( i_nFilter );; + xContainer->replaceByName( getModuleIdentifier( xModuleManager, i_pObjSh ), makeAny( lProps ) ); + } +} + +//------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonTemplateDialog_Impl, DropHdl, StyleTreeListBox_Impl *, pBox ) +{ + bDontUpdate=TRUE; + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + const SfxStyleFamily eFam = pItem->GetFamily(); + long ret= pStyleSheetPool->SetParent(eFam,pBox->GetStyle(), pBox->GetParent())? 1L: 0L; + bDontUpdate=FALSE; + return ret; +} + +//------------------------------------------------------------------------- + +// Handler des Neu-Buttons +void SfxCommonTemplateDialog_Impl::NewHdl(void *) +{ + String aEmpty; + if ( nActFamily != 0xffff ) + { + Window* pTmp; + pTmp = Application::GetDefDialogParent(); + if ( ISA(SfxTemplateDialog_Impl) ) + Application::SetDefDialogParent( pWindow->GetParent() ); + else + Application::SetDefDialogParent( pWindow ); + + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + const SfxStyleFamily eFam=pItem->GetFamily(); + USHORT nMask; + if(pItem&&nActFilter!=0xffff) + { + nMask = pItem->GetFilterList().GetObject( + nActFilter)->nFlags; + if(!nMask) // automatisch + nMask = nAppFilter; + } + else + nMask=pStyleSheetPool->GetSearchMask(); + + pStyleSheetPool->SetSearchMask(eFam,nMask); + + Execute_Impl(SID_STYLE_NEW, + aEmpty, GetSelectedEntry(), + ( USHORT )GetFamilyItem_Impl()->GetFamily(), + nMask); + + Application::SetDefDialogParent( pTmp ); + +/* { + DBG_ASSERT(nFilter < aFilterLb.GetEntryCount(), + "Filter ueberindiziert"); + + if(!pTreeBox) + { +// aFilterLb.SelectEntryPos(nFilter); + FilterSelect(nActFilter, TRUE); + } + else + { + FillTreeBox(); + SfxTemplateItem *pState = pFamilyState[nActFamily-1]; + if(pState) + { + const String aStyle(pState->GetStyleName()); + SelectStyle(aStyle); + } + EnableDelete(); + }*/ +// } + } +} + +//------------------------------------------------------------------------- + +// Handler des Bearbeiten-Buttons +void SfxCommonTemplateDialog_Impl::EditHdl(void *) +{ + if(IsInitialized() && HasSelectedStyle()) + { + USHORT nFilter = nActFilter; + String aTemplName(GetSelectedEntry()); + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + const SfxStyleFamily eFam = pItem->GetFamily(); + pStyleSheetPool->Find(aTemplName,eFam,SFXSTYLEBIT_ALL); // -Wall required?? + Window* pTmp; + //DefModalDialogParent setzen fuer + //Modalitaet der nachfolgenden Dialoge + pTmp = Application::GetDefDialogParent(); + if ( ISA(SfxTemplateDialog_Impl) ) + Application::SetDefDialogParent( pWindow->GetParent() ); + else + Application::SetDefDialogParent( pWindow ); + if ( Execute_Impl( SID_STYLE_EDIT, aTemplName, String(), + (USHORT)GetFamilyItem_Impl()->GetFamily(), 0, &nFilter ) ) + { +// DBG_ASSERT(nFilter < aFilterLb.GetEntryCount(), "Filter ueberindiziert"); +// aTemplName = pStyle->GetName(); +// kann durch Bearbeiten umbenannt worden sein +/* if(!pTreeBox) + { + // aFilterLb.SelectEntryPos(nFilter); + // FilterSelect(nFilter, TRUE); + } + else + FillTreeBox();*/ + } + Application::SetDefDialogParent( pTmp ); + } +} + +//------------------------------------------------------------------------- + +// Handler des L"oschen-Buttons +void SfxCommonTemplateDialog_Impl::DeleteHdl(void *) +{ + if ( IsInitialized() && HasSelectedStyle() ) + { + const String aTemplName( GetSelectedEntry() ); + const SfxStyleFamilyItem* pItem = GetFamilyItem_Impl(); + SfxStyleSheetBase* pStyle = + pStyleSheetPool->Find( aTemplName, pItem->GetFamily(), SFXSTYLEBIT_ALL ); + if ( pStyle ) + { + String aMsg; + if ( pStyle->IsUsed() ) + aMsg = String( SfxResId( STR_DELETE_STYLE_USED ) ); + aMsg += String ( SfxResId( STR_DELETE_STYLE ) ); + aMsg.SearchAndReplaceAscii( "$1", aTemplName ); +#if defined UNX + QueryBox aBox( SFX_APP()->GetTopWindow(), WB_YES_NO | WB_DEF_NO, aMsg ); +#else + QueryBox aBox( GetWindow(), WB_YES_NO | WB_DEF_NO , aMsg ); +#endif + if ( RET_YES == aBox.Execute() ) + { + PrepareDeleteAction(); + + if ( pTreeBox ) // Damit die Treelistbox beim L"oschen nicht zuklappt + { + bDontUpdate = TRUE; + } + Execute_Impl( SID_STYLE_DELETE, aTemplName, + String(), (USHORT)GetFamilyItem_Impl()->GetFamily() ); + + if ( pTreeBox ) + { + pTreeBox->RemoveParentKeepChilds( pTreeBox->FirstSelected() ); + bDontUpdate = FALSE; + } + } + } + } +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::EnableDelete() +{ + if(IsInitialized() && HasSelectedStyle()) + { + DBG_ASSERT(pStyleSheetPool, "Kein StyleSheetPool"); + const String aTemplName(GetSelectedEntry()); + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + const SfxStyleFamily eFam = pItem->GetFamily(); + USHORT nFilter = 0; + if(pItem->GetFilterList().Count() > nActFilter) + nFilter = pItem->GetFilterList().GetObject(nActFilter)->nFlags; + if(!nFilter) // automatisch + nFilter = nAppFilter; + const SfxStyleSheetBase *pStyle = + pStyleSheetPool->Find(aTemplName,eFam, + pTreeBox? SFXSTYLEBIT_ALL: nFilter); + DBG_ASSERT(pStyle, "Style nicht gefunden"); + if(pStyle && pStyle->IsUserDefined()) + { + EnableDel(TRUE); + } + else + { + EnableDel(FALSE); + } + } + else + { + EnableDel(FALSE); + } +// rBindings.Invalidate( SID_STYLE_DELETE ); +// rBindings.Update( SID_STYLE_DELETE ); +} + +//------------------------------------------------------------------------- + +// nach Selektion eines Eintrags den Focus gfs. wieder auf das App-Fenster +// setzen +void SfxCommonTemplateDialog_Impl::ResetFocus() +{ + if(ISA(SfxTemplateDialog_Impl)) + { + SfxViewFrame *pViewFrame = pBindings->GetDispatcher_Impl()->GetFrame(); + SfxViewShell *pVu = pViewFrame->GetViewShell(); + Window *pAppWin = pVu ? pVu->GetWindow(): 0; + if(pAppWin) + pAppWin->GrabFocus(); + } +} + +//------------------------------------------------------------------------- + +// Doppelclick auf ein StyleSheet in der ListBox, wird angewendet. +IMPL_LINK( SfxCommonTemplateDialog_Impl, ApplyHdl, Control *, pControl ) +{ + (void)pControl; //unused + // nur, wenn dieser Bereich erlaubt ist + if ( IsInitialized() && 0 != pFamilyState[nActFamily-1] && + GetSelectedEntry().Len() ) + { + USHORT nModifier = aFmtLb.GetModifier(); + Execute_Impl(SID_STYLE_APPLY, + GetSelectedEntry(), String(), + ( USHORT )GetFamilyItem_Impl()->GetFamily(), + 0, 0, &nModifier ); + if(ISA(SfxTemplateCatalog_Impl)) + ((SfxTemplateCatalog_Impl*) this)->pReal->EndDialog(RET_OK); + } + ResetFocus(); + return 0; +} + +//------------------------------------------------------------------------- + +// Selektion einer Vorlage w"ahrend des Watercan-Status +IMPL_LINK( SfxCommonTemplateDialog_Impl, FmtSelectHdl, SvTreeListBox *, pListBox ) +{ + // HilfePI antriggern, wenn von Call als Handler und Bereich erlaubt ist + if( !pListBox || pListBox->IsSelected( pListBox->GetHdlEntry() ) ) + { +#ifdef WIR_KOENNEN_WIEDER_HILFE_FUER_STYLESHEETS + SfxHelpPI* pHelpPI = SFX_APP()->GetHelpPI(); + if ( pHelpPI && pListBox && IsInitialized() && + GetSelectedEntry().Len() ) + { + const SfxStyleFamilyItem *pItem = GetFamilyItem_Impl(); + const SfxStyleFamily eFam = pItem->GetFamily(); + DBG_ASSERT(pStyleSheetPool, "Kein Pool"); + // SfxStyleSheetBase* pStyle = pStyleSheetPool + // ? pStyleSheetPool->Find( GetSelectedEntry(), eFam ) : 0; + SfxStyleSheetBase *pStyle; + if ( pStyleSheetPool ) + pStyle = pStyleSheetPool->Find ( GetSelectedEntry(), eFam ); + else + pStyle = 0; + + if ( pStyle ) + { + String aHelpFile; + ULONG nHelpId=pStyle->GetHelpId(aHelpFile); + if ( nHelpId ) + pHelpPI->LoadTopic( nHelpId ); + } + } +#endif + + // nur, wenn Giesskanne an ist + if ( IsInitialized() && + IsCheckedItem(SID_STYLE_WATERCAN) && + // nur, wenn dieser Bereich erlaubt ist + 0 != pFamilyState[nActFamily-1] ) + { + String aEmpty; + Execute_Impl(SID_STYLE_WATERCAN, + aEmpty, aEmpty, 0); + Execute_Impl(SID_STYLE_WATERCAN, + GetSelectedEntry(), aEmpty, + ( USHORT )GetFamilyItem_Impl()->GetFamily()); + } +// EnableEdit(TRUE); + EnableItem(SID_STYLE_WATERCAN, !bWaterDisabled); + EnableDelete(); + } + if( pListBox ) + SelectStyle( pListBox->GetEntryText( pListBox->GetHdlEntry() )); + + return 0; +} + +//------------------------------------------------------------------------- + +IMPL_LINK( SfxCommonTemplateDialog_Impl, MenuSelectHdl, Menu *, pMenu ) +{ + if( pMenu ) + { + nLastItemId = pMenu->GetCurItemId(); + Application::PostUserEvent( + LINK( this, SfxCommonTemplateDialog_Impl, MenuSelectHdl ), 0 ); + return TRUE; + } + + switch(nLastItemId) { + case ID_NEW: NewHdl(0); break; + case ID_EDIT: EditHdl(0); break; + case ID_DELETE: DeleteHdl(0); break; + default: return FALSE; + } + return TRUE; +} + +// ----------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::ExecuteContextMenu_Impl( const Point& rPos, Window* pWin ) +{ + // Bug# 94152: This part should never be called, because before this happens, the TreeListBox should captured this! + DBG_ASSERT( FALSE, "+SfxCommonTemplateDialog_Impl::ExecuteContextMenu_Impl(): How could this happen? Please infirm developer ASAP!" ); + + PopupMenu* pMenu = CreateContextMenu(); + pMenu->Execute( pWin, rPos ); + delete pMenu; +} + +// ----------------------------------------------------------------------- + +SfxStyleFamily SfxCommonTemplateDialog_Impl::GetActualFamily() const +{ + const SfxStyleFamilyItem *pFamilyItem = GetFamilyItem_Impl(); + if( !pFamilyItem || nActFamily == 0xffff ) + return SFX_STYLE_FAMILY_PARA; + else + return pFamilyItem->GetFamily(); +} + +// ----------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::EnableExample_Impl(USHORT nId, BOOL bEnable) +{ + if( nId == SID_STYLE_NEW_BY_EXAMPLE ) + bNewByExampleDisabled = !bEnable; + else if( nId == SID_STYLE_UPDATE_BY_EXAMPLE ) + bUpdateByExampleDisabled = !bEnable; + EnableItem(nId, bEnable); +} + +void SfxCommonTemplateDialog_Impl::PrepareDeleteAction() +{ +} + +// ----------------------------------------------------------------------- + +PopupMenu* SfxCommonTemplateDialog_Impl::CreateContextMenu( void ) +{ + if ( bBindingUpdate ) + { + pBindings->Invalidate( SID_STYLE_NEW, TRUE, FALSE ); + pBindings->Update( SID_STYLE_NEW ); + bBindingUpdate = FALSE; + } + PopupMenu* pMenu = new PopupMenu( SfxResId( MN_CONTEXT_TEMPLDLG ) ); + pMenu->SetSelectHdl( LINK( this, SfxCommonTemplateDialog_Impl, MenuSelectHdl ) ); + pMenu->EnableItem( ID_EDIT, bCanEdit ); + pMenu->EnableItem( ID_DELETE, bCanDel ); + pMenu->EnableItem( ID_NEW, bCanNew ); + + return pMenu; +} + +// ------------------------------------------------------------------------ + +SfxTemplateDialog_Impl::SfxTemplateDialog_Impl( + Window* /*pParent*/, SfxBindings* pB, SfxTemplateDialog* pDlgWindow ) : + + SfxCommonTemplateDialog_Impl( pB, pDlgWindow ), + + m_pFloat ( pDlgWindow ), + m_bZoomIn ( FALSE ), + m_aActionTbL ( pDlgWindow, this ), + m_aActionTbR ( pDlgWindow, SfxResId( TB_ACTION ) ) + +{ + pDlgWindow->FreeResource(); + Initialize(); + + m_aActionTbL.SetSelectHdl(LINK(this, SfxTemplateDialog_Impl, ToolBoxLSelect)); + m_aActionTbR.SetSelectHdl(LINK(this, SfxTemplateDialog_Impl, ToolBoxRSelect)); + m_aActionTbR.SetDropdownClickHdl(LINK(this, SfxTemplateDialog_Impl, ToolBoxRClick)); + m_aActionTbL.Show(); + m_aActionTbR.Show(); + Font aFont=aFilterLb.GetFont(); + aFont.SetWeight( WEIGHT_NORMAL ); + aFilterLb.SetFont( aFont ); + m_aActionTbL.SetHelpId( HID_TEMPLDLG_TOOLBOX_LEFT ); +} + +// ------------------------------------------------------------------------ + +void SfxTemplateDialog_Impl::EnableFamilyItem( USHORT nId, BOOL bEnable ) +{ + m_aActionTbL.EnableItem( nId, bEnable ); +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog_Impl::InsertFamilyItem(USHORT nId,const SfxStyleFamilyItem *pItem) +{ + USHORT nHelpId = 0; + switch( (USHORT) pItem->GetFamily() ) + { + case SFX_STYLE_FAMILY_CHAR: nHelpId = SID_STYLE_FAMILY1; break; + case SFX_STYLE_FAMILY_PARA: nHelpId = SID_STYLE_FAMILY2; break; + case SFX_STYLE_FAMILY_FRAME:nHelpId = SID_STYLE_FAMILY3; break; + case SFX_STYLE_FAMILY_PAGE: nHelpId = SID_STYLE_FAMILY4; break; + case SFX_STYLE_FAMILY_PSEUDO: nHelpId = SID_STYLE_FAMILY5; break; + default: DBG_ERROR("unbekannte StyleFamily"); break; + } + m_aActionTbL.InsertItem( nId, pItem->GetImage(), pItem->GetText(), 0, 0); + m_aActionTbL.SetHelpId( nId, nHelpId ); +} + +// ------------------------------------------------------------------------ + +void SfxTemplateDialog_Impl::ReplaceUpdateButtonByMenu() +{ + m_aActionTbR.HideItem(SID_STYLE_UPDATE_BY_EXAMPLE); + m_aActionTbR.SetItemBits( SID_STYLE_NEW_BY_EXAMPLE, + TIB_DROPDOWNONLY|m_aActionTbR.GetItemBits( SID_STYLE_NEW_BY_EXAMPLE )); +} + +// ------------------------------------------------------------------------ +void SfxTemplateDialog_Impl::updateFamilyImages() +{ + if ( !m_pStyleFamiliesId ) + // we do not have a resource id to load the new images from + return; + + // let the families collection update the images + sal_Bool bIsHighContrast = m_pFloat->GetSettings().GetStyleSettings().GetHighContrastMode(); + pStyleFamilies->updateImages( *m_pStyleFamiliesId, bIsHighContrast ? BMP_COLOR_HIGHCONTRAST : BMP_COLOR_NORMAL ); + + // and set the new images on our toolbox + USHORT nLoop = pStyleFamilies->Count(); + for( ; nLoop--; ) + { + const SfxStyleFamilyItem *pItem = pStyleFamilies->GetObject( nLoop ); + USHORT nId = SfxFamilyIdToNId( pItem->GetFamily() ); + m_aActionTbL.SetItemImage( nId, pItem->GetImage() ); + } +} + +// ------------------------------------------------------------------------ +void SfxTemplateDialog_Impl::updateNonFamilyImages() +{ + m_aActionTbR.SetImageList( ImageList( SfxResId( + m_pFloat->GetSettings().GetStyleSettings().GetHighContrastMode() ? IMG_LST_STYLE_DESIGNER_HC + : DLG_STYLE_DESIGNER ) ) ); +} + +// ------------------------------------------------------------------------ + +void SfxTemplateDialog_Impl::ClearFamilyList() +{ + m_aActionTbL.Clear(); +} + +//------------------------------------------------------------------------- + +void SfxCommonTemplateDialog_Impl::InvalidateBindings() +{ + pBindings->Invalidate(SID_STYLE_NEW_BY_EXAMPLE, TRUE, FALSE); + pBindings->Update( SID_STYLE_NEW_BY_EXAMPLE ); + pBindings->Invalidate(SID_STYLE_UPDATE_BY_EXAMPLE, TRUE, FALSE); + pBindings->Update( SID_STYLE_UPDATE_BY_EXAMPLE ); + pBindings->Invalidate( SID_STYLE_WATERCAN, TRUE, FALSE); + pBindings->Update( SID_STYLE_WATERCAN ); + pBindings->Invalidate( SID_STYLE_NEW, TRUE, FALSE ); + pBindings->Update( SID_STYLE_NEW ); + pBindings->Invalidate( SID_STYLE_DRAGHIERARCHIE, TRUE, FALSE ); + pBindings->Update( SID_STYLE_DRAGHIERARCHIE ); +} + +//------------------------------------------------------------------------- + +SfxTemplateDialog_Impl::~SfxTemplateDialog_Impl() +{ +/* + SfxImageManager* pImgMgr = pBindings->GetImageManager(); + if ( pImgMgr ) + { + pImgMgr->ReleaseToolBox( &m_aActionTbL ); + pImgMgr->ReleaseToolBox( &m_aActionTbR ); + } +*/ +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog_Impl::LoadedFamilies() +{ + updateFamilyImages(); + Resize(); +} + +//------------------------------------------------------------------------- + +// "Uberladener Resize-Handler ( StarView ) +// Die Groesse der Listboxen wird angepasst +void SfxTemplateDialog_Impl::Resize() +{ + FloatingWindow *pF = m_pFloat->GetFloatingWindow(); + if ( pF ) + { +// if(pF->IsZoomedIn() && m_bZoomIn==FALSE) +// pF->SetText(String(SfxResId( DLG_STYLE_DESIGNER ))); +// if(!pF->IsZoomedIn() && m_bZoomIn==TRUE && GetFamilyItem_Impl()) +// UpdateStyles_Impl(UPDATE_FAMILY); //Bereich wieder in Titel schreiben + m_bZoomIn = pF->IsRollUp(); + if ( m_bZoomIn ) + return; + } + + Size aDlgSize=m_pFloat->PixelToLogic(m_pFloat->GetOutputSizePixel()); + Size aSizeATL=m_pFloat->PixelToLogic(m_aActionTbL.CalcWindowSizePixel()); + Size aSizeATR=m_pFloat->PixelToLogic(m_aActionTbR.CalcWindowSizePixel()); + Size aMinSize = GetMinOutputSizePixel(); + + long nListHeight = m_pFloat->PixelToLogic( aFilterLb.GetSizePixel() ).Height(); + long nWidth = aDlgSize.Width()- 2 * SFX_TEMPLDLG_HFRAME; + + m_aActionTbL.SetPosSizePixel(m_pFloat->LogicToPixel(Point(SFX_TEMPLDLG_HFRAME,SFX_TEMPLDLG_VTOPFRAME)), + m_pFloat->LogicToPixel(aSizeATL)); + + // Die Position der rechten Toolbox nur ver"andern, wenn das Fenster + // breit genug ist + Point aPosATR(aDlgSize.Width()-SFX_TEMPLDLG_HFRAME-aSizeATR.Width(),SFX_TEMPLDLG_VTOPFRAME); + if(aDlgSize.Width() >= aMinSize.Width()) + m_aActionTbR.SetPosPixel(m_pFloat->LogicToPixel(aPosATR)); + else + m_aActionTbR.SetPosPixel( m_pFloat->LogicToPixel( + Point( SFX_TEMPLDLG_HFRAME + aSizeATL.Width() + SFX_TEMPLDLG_MIDHSPACE, + SFX_TEMPLDLG_VTOPFRAME ) ) ); + + m_aActionTbR.SetSizePixel(m_pFloat->LogicToPixel(aSizeATR)); + + Point aFilterPos( + m_pFloat->LogicToPixel(Point(SFX_TEMPLDLG_HFRAME, + aDlgSize.Height()-SFX_TEMPLDLG_VBOTFRAME-nListHeight)) ); + + Size aFilterSize( + m_pFloat->LogicToPixel(Size(nWidth,SFX_TEMPLDLG_FILTERHEIGHT)) ); + + Point aFmtPos( + m_pFloat->LogicToPixel(Point(SFX_TEMPLDLG_HFRAME, SFX_TEMPLDLG_VTOPFRAME + + SFX_TEMPLDLG_MIDVSPACE+aSizeATL.Height())) ); + Size aFmtSize( + m_pFloat->LogicToPixel(Size(nWidth, + aDlgSize.Height() - SFX_TEMPLDLG_VBOTFRAME - + SFX_TEMPLDLG_VTOPFRAME - 2*SFX_TEMPLDLG_MIDVSPACE- + nListHeight-aSizeATL.Height())) ); + + // Die Position der Listboxen nur ver"andern, wenn das Fenster + // hoch genug ist + if(aDlgSize.Height() >= aMinSize.Height()) + { + aFilterLb.SetPosPixel(aFilterPos); + aFmtLb.SetPosPixel( aFmtPos ); + if(pTreeBox) + pTreeBox->SetPosPixel(aFmtPos); + } + else + aFmtSize.Height() += aFilterSize.Height(); + + aFilterLb.SetSizePixel(aFilterSize); + aFmtLb.SetSizePixel( aFmtSize ); + if(pTreeBox) + pTreeBox->SetSizePixel(aFmtSize); +} + +// ----------------------------------------------------------------------- + + +Size SfxTemplateDialog_Impl::GetMinOutputSizePixel() +{ + Size aSizeATL=m_pFloat->PixelToLogic(m_aActionTbL.CalcWindowSizePixel()); + Size aSizeATR=m_pFloat->PixelToLogic(m_aActionTbR.CalcWindowSizePixel()); + Size aMinSize=Size( + aSizeATL.Width()+aSizeATR.Width()+ + 2*SFX_TEMPLDLG_HFRAME + SFX_TEMPLDLG_MIDHSPACE, + 4*aSizeATL.Height()+2*SFX_TEMPLDLG_MIDVSPACE); + return aMinSize; +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog_Impl::Command( const CommandEvent& rCEvt ) +{ + if(COMMAND_CONTEXTMENU == rCEvt.GetCommand()) + ExecuteContextMenu_Impl( rCEvt.GetMousePosPixel(), m_pFloat ); + else + m_pFloat->Command(rCEvt); +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog_Impl::EnableItem(USHORT nMesId, BOOL bCheck) +{ + String aEmpty; + switch(nMesId) + { + case SID_STYLE_WATERCAN : + if(!bCheck && IsCheckedItem(SID_STYLE_WATERCAN)) + Execute_Impl(SID_STYLE_WATERCAN, aEmpty, aEmpty, 0); + case SID_STYLE_NEW_BY_EXAMPLE: + case SID_STYLE_UPDATE_BY_EXAMPLE: + m_aActionTbR.EnableItem(nMesId,bCheck); + break; + } +} + +//------------------------------------------------------------------------- + +void SfxTemplateDialog_Impl::CheckItem(USHORT nMesId, BOOL bCheck) +{ + switch(nMesId) + { + case SID_STYLE_WATERCAN : + bIsWater=bCheck; + m_aActionTbR.CheckItem(SID_STYLE_WATERCAN,bCheck); + break; + default: + m_aActionTbL.CheckItem(nMesId,bCheck); break; + } +} + +//------------------------------------------------------------------------- + +BOOL SfxTemplateDialog_Impl::IsCheckedItem(USHORT nMesId) +{ + switch(nMesId) + { + case SID_STYLE_WATERCAN : + return m_aActionTbR.GetItemState(SID_STYLE_WATERCAN)==STATE_CHECK; + default: + return m_aActionTbL.GetItemState(nMesId)==STATE_CHECK; + } +} + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxTemplateDialog_Impl, ToolBoxLSelect, ToolBox *, pBox ) +{ + const USHORT nEntry = pBox->GetCurItemId(); + FamilySelect(nEntry); + return 0; +} +IMPL_LINK_INLINE_END( SfxTemplateDialog_Impl, ToolBoxLSelect, ToolBox *, pBox ) + +//------------------------------------------------------------------------- +::rtl::OUString lcl_GetLabel(uno::Any& rAny) +{ + ::rtl::OUString sRet; + uno::Sequence< beans::PropertyValue >aPropSeq; + if ( rAny >>= aPropSeq ) + { + for( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( "Label" )) + { + aPropSeq[i].Value >>= sRet; + break; + } + } + } + return sRet; +} +//------------------------------------------------------------------------- + +IMPL_LINK( SfxTemplateDialog_Impl, ToolBoxRSelect, ToolBox *, pBox ) +{ + const USHORT nEntry = pBox->GetCurItemId(); + if(nEntry != SID_STYLE_NEW_BY_EXAMPLE || + TIB_DROPDOWN != (pBox->GetItemBits(nEntry)&TIB_DROPDOWN)) + ActionSelect(nEntry); + return 0; +} +//------------------------------------------------------------------------- +IMPL_LINK( SfxTemplateDialog_Impl, ToolBoxRClick, ToolBox *, pBox ) +{ + const USHORT nEntry = pBox->GetCurItemId(); + if(nEntry == SID_STYLE_NEW_BY_EXAMPLE && + TIB_DROPDOWN == (pBox->GetItemBits(nEntry)&TIB_DROPDOWN)) + { + //create a popup menu in Writer + PopupMenu *pMenu = new PopupMenu; + uno::Reference< container::XNameAccess > xNameAccess( + ::comphelper::getProcessServiceFactory()-> + createInstance( ::rtl::OUString::createFromAscii( + "com.sun.star.frame.UICommandDescription") ), uno::UNO_QUERY ); + uno::Reference< container::XNameAccess > xUICommands; + if ( xNameAccess.is() ) + { + rtl::OUString sTextDoc = ::rtl::OUString::createFromAscii("com.sun.star.text.TextDocument"); + if(xNameAccess->hasByName(sTextDoc)) + { + uno::Any a = xNameAccess->getByName( sTextDoc ); + a >>= xUICommands; + } + } + if(!xUICommands.is()) + return 0; + try + { + uno::Sequence< beans::PropertyValue > aPropSeq; + uno::Any aCommand = xUICommands->getByName(::rtl::OUString::createFromAscii(".uno:StyleNewByExample")); + ::rtl::OUString sLabel = lcl_GetLabel( aCommand ); + pMenu->InsertItem( SID_STYLE_NEW_BY_EXAMPLE, sLabel ); + pMenu->SetHelpId(SID_STYLE_NEW_BY_EXAMPLE, HID_TEMPLDLG_NEWBYEXAMPLE); + + aCommand = xUICommands->getByName(::rtl::OUString::createFromAscii(".uno:StyleUpdateByExample")); + sLabel = lcl_GetLabel( aCommand ); + + pMenu->InsertItem( SID_STYLE_UPDATE_BY_EXAMPLE, sLabel ); + pMenu->SetHelpId(SID_STYLE_UPDATE_BY_EXAMPLE, HID_TEMPLDLG_UPDATEBYEXAMPLE); + + aCommand = xUICommands->getByName(::rtl::OUString::createFromAscii(".uno:LoadStyles")); + sLabel = lcl_GetLabel( aCommand ); + pMenu->InsertItem( SID_TEMPLATE_LOAD, sLabel ); + pMenu->SetHelpId(SID_TEMPLATE_LOAD, SID_TEMPLATE_LOAD); + + pMenu->SetSelectHdl(LINK(this, SfxTemplateDialog_Impl, MenuSelectHdl)); + pMenu->Execute( pBox, + pBox->GetItemRect(nEntry), + POPUPMENU_EXECUTE_DOWN ); + pBox->EndSelection(); + } + catch(uno::Exception&) + { + } + delete pMenu; + pBox->Invalidate(); + } + return 0; +} +//------------------------------------------------------------------------- +IMPL_LINK( SfxTemplateDialog_Impl, MenuSelectHdl, Menu*, pMenu) +{ + USHORT nMenuId = pMenu->GetCurItemId(); + ActionSelect(nMenuId); + return 0; +} +//------------------------------------------------------------------------- + +SfxTemplateCatalog_Impl::SfxTemplateCatalog_Impl( Window* /*pParent*/, SfxBindings* pB, + SfxTemplateCatalog* pTmpWindow ) : + + SfxCommonTemplateDialog_Impl( pB, pTmpWindow ), + + aFamList ( pTmpWindow, SfxResId( BT_TOOL ) ), + aOkBtn ( pTmpWindow, SfxResId( BT_OK ) ), + aCancelBtn ( pTmpWindow, SfxResId( BT_CANCEL ) ), + aNewBtn ( pTmpWindow, SfxResId( BT_NEW ) ), + aChangeBtn ( pTmpWindow, SfxResId( BT_EDIT ) ), + aDelBtn ( pTmpWindow, SfxResId( BT_DEL ) ), + aOrgBtn ( pTmpWindow, SfxResId( BT_ORG ) ), + aHelpBtn ( pTmpWindow, SfxResId( BT_HELP ) ), + pReal ( pTmpWindow ), + aHelper ( pTmpWindow ) + +{ + aNewBtn.Disable(); + aDelBtn.Disable(); + aChangeBtn.Disable(); + + SFX_APP()->Get_Impl()->pTemplateCommon = GetISfxTemplateCommon(); + pTmpWindow->FreeResource(); + + Initialize(); + + aFamList.SetSelectHdl( LINK( this, SfxTemplateCatalog_Impl, FamListSelect ) ); + aOkBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, OkHdl ) ); + aCancelBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, CancelHdl ) ); + aNewBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, NewHdl ) ); + aDelBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, DelHdl ) ); + aChangeBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, ChangeHdl ) ); + aOrgBtn.SetClickHdl( LINK( this, SfxTemplateCatalog_Impl, OrgHdl ) ); +} + +//------------------------------------------------------------------------- + +SfxTemplateCatalog_Impl::~SfxTemplateCatalog_Impl() +{ + SFX_APP()->Get_Impl()->pTemplateCommon = 0; +} + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, OkHdl, Button *, pButton ) +{ + (void)pButton; //unused + ApplyHdl( NULL ); + pReal->EndDialog( RET_OK ); + return 0; +} +IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, OkHdl, Button *, pButton ) + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, CancelHdl, Button *, pButton ) +{ + (void)pButton; //unused + pReal->EndDialog( RET_CANCEL ); + return 0; +} +IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, CancelHdl, Button *, pButton ) + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, NewHdl, Button *, pButton ) +{ + (void)pButton; //unused + aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) ); + SfxCommonTemplateDialog_Impl::NewHdl( NULL ); + return 0; +} +IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, NewHdl, Button *, pButton ) + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, ChangeHdl, Button *, pButton ) +{ + (void)pButton; //unused + aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) ); + SfxCommonTemplateDialog_Impl::EditHdl( NULL ); + return 0; +} +IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, ChangeHdl, Button *, pButton ) + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, DelHdl, Button *, pButton ) +{ + (void)pButton; //unused + SfxCommonTemplateDialog_Impl::DeleteHdl( NULL ); + return 0; +} +IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, DelHdl, Button *, pButton ) + +//------------------------------------------------------------------------- + +IMPL_LINK( SfxTemplateCatalog_Impl, OrgHdl, Button *, pButton ) +{ + (void)pButton; //unused + aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) ); + SfxDocumentTemplates aTemplates; + aTemplates.Construct(); + SfxTemplateOrganizeDlg* pDlg = new SfxTemplateOrganizeDlg( pReal, &aTemplates ); + const short nRet = pDlg->Execute(); + delete pDlg; + if ( RET_OK == nRet ) + Update_Impl(); + else if ( RET_EDIT_STYLE == nRet ) + pReal->EndDialog( RET_CANCEL ); + return 0; +} + +//------------------------------------------------------------------------- + +void SfxTemplateCatalog_Impl::EnableEdit( BOOL bEnable ) +{ + SfxCommonTemplateDialog_Impl::EnableEdit( bEnable ); + aChangeBtn.Enable( bEnable ); +} + +//------------------------------------------------------------------------- + +void SfxTemplateCatalog_Impl::EnableDel( BOOL bEnable ) +{ + SfxCommonTemplateDialog_Impl::EnableDel( bEnable ); + aDelBtn.Enable( bEnable ); +} + +void SfxTemplateCatalog_Impl::EnableNew(BOOL bEnable) +{ + SfxCommonTemplateDialog_Impl::EnableNew( bEnable ); + aNewBtn.Enable( bEnable ); +} + +//------------------------------------------------------------------------- + +IMPL_LINK_INLINE_START( SfxTemplateCatalog_Impl, FamListSelect, ListBox *, pList ) +{ + const USHORT nEntry = aFamIds[pList->GetSelectEntryPos()]; + FamilySelect(nEntry); + return 0; +} +IMPL_LINK_INLINE_END( SfxTemplateCatalog_Impl, FamListSelect, ListBox *, pList ) + +//------------------------------------------------------------------------- + +void SfxTemplateCatalog_Impl::EnableItem( USHORT nMesId, BOOL bCheck ) +{ + if ( nMesId == SID_STYLE_WATERCAN ) + aOkBtn.Enable( bCheck ); + if ( nMesId > SFX_STYLE_FAMILY_PSEUDO || nMesId < SFX_STYLE_FAMILY_CHAR ) + return; + +/* for(USHORT i=0;i<aFamIds.Count&&aFamIds[i]!=nMesId;i++); + if(i!=aFamIds.Count()) + aFamList.SelectEntry(aFamIds[i]); + else + DBG_ERROR("Entry nicht gefunden");*/ + +} + +//------------------------------------------------------------------------- + +void SfxTemplateCatalog_Impl::CheckItem(USHORT nMesId, BOOL /*bCheck*/) +{ + if ( nMesId > SFX_STYLE_FAMILY_PSEUDO || nMesId < SFX_STYLE_FAMILY_CHAR ) + return; + USHORT i; + for ( i = 0; i < aFamIds.Count() && aFamIds[i] != nMesId; i++ ) ; + aFamList.SelectEntryPos(i); +} + +//------------------------------------------------------------------------- + +BOOL SfxTemplateCatalog_Impl::IsCheckedItem(USHORT nMesId) +{ + if ( nMesId > SFX_STYLE_FAMILY_PSEUDO || nMesId < SFX_STYLE_FAMILY_CHAR ) + return FALSE; + USHORT i; + for ( i = 0; i < aFamIds.Count() && aFamIds[i] != nMesId; i++ ) + ; + return aFamList.IsEntrySelected( String::CreateFromInt32(i) ); +} + +//------------------------------------------------------------------------- + +// Der Katalog muss nur das Disablen beherrschen, da waehrend seiner +// Lebenszeit keine Selektionsaenderungen vorgenommen werden koennen +void SfxTemplateCatalog_Impl::EnableFamilyItem( USHORT nId, BOOL bEnable ) +{ + if ( !bEnable ) + for ( USHORT nPos = aFamIds.Count(); nPos--; ) + if ( aFamIds[ nPos ] == nId ) + { + aFamIds.Remove( nPos ); + aFamList.RemoveEntry( nPos ); + } +} + +void SfxTemplateCatalog_Impl::InsertFamilyItem( USHORT nId, const SfxStyleFamilyItem* pItem ) +{ + if ( nId > SFX_STYLE_FAMILY_PSEUDO || nId < SFX_STYLE_FAMILY_CHAR ) + return; + aFamList.InsertEntry( pItem->GetText(), 0 ); + aFamIds.Insert( nId, 0 ); +} + +void SfxTemplateCatalog_Impl::ClearFamilyList() +{ + aFamList.Clear(); + aFamIds.Remove( 0, aFamIds.Count() ); +} + +void SfxTemplateCatalog_Impl::PrepareDeleteAction() +{ + aDelBtn.Disable(); + aCancelBtn.SetText( String( SfxResId( STR_CLOSE ) ) ); +} + + +void SfxCommonTemplateDialog_Impl::SetFamily( USHORT nId ) +{ + if ( nId != nActFamily ) + { + if ( nActFamily != 0xFFFF ) + CheckItem( nActFamily, FALSE ); + nActFamily = nId; + if ( nId != 0xFFFF ) + bUpdateFamily = TRUE; + } +} + +void SfxCommonTemplateDialog_Impl::UpdateFamily_Impl() +{ + bUpdateFamily = FALSE; + + SfxDispatcher* pDispat = pBindings->GetDispatcher_Impl(); + SfxViewFrame *pViewFrame = pDispat->GetFrame(); + SfxObjectShell *pDocShell = pViewFrame->GetObjectShell(); + + SfxStyleSheetBasePool *pOldStyleSheetPool = pStyleSheetPool; + pStyleSheetPool = pDocShell? pDocShell->GetStyleSheetPool(): 0; + if ( pOldStyleSheetPool != pStyleSheetPool ) + { + if ( pOldStyleSheetPool ) + EndListening(*pOldStyleSheetPool); + if ( pStyleSheetPool ) + StartListening(*pOldStyleSheetPool); + } + + bWaterDisabled = FALSE; + bCanNew = TRUE; + bTreeDrag = TRUE; + bUpdateByExampleDisabled = FALSE; + + if ( pStyleSheetPool ) + { + if(!pTreeBox) + UpdateStyles_Impl(UPDATE_FAMILY | UPDATE_FAMILY_LIST); + else + { + UpdateStyles_Impl(UPDATE_FAMILY); + FillTreeBox(); + } + } + + InvalidateBindings(); + + if ( IsCheckedItem( SID_STYLE_WATERCAN ) && + // nur, wenn dieser Bereich erlaubt ist + 0 != pFamilyState[ nActFamily - 1 ] ) + Execute_Impl( SID_STYLE_APPLY, GetSelectedEntry(), + String(), (USHORT)GetFamilyItem_Impl()->GetFamily() ); +} +void SfxCommonTemplateDialog_Impl::ReplaceUpdateButtonByMenu() +{ + //does nothing +} + +void SfxTemplateDialog::StateChanged( StateChangedType nStateChange ) +{ + if ( nStateChange == STATE_CHANGE_INITSHOW ) + { + SfxViewFrame *pFrame = GetBindings().GetDispatcher_Impl()->GetFrame(); + Window* pEditWin = pFrame->GetViewShell()->GetWindow(); + + Size aSize = pEditWin->GetSizePixel(); + Point aPoint = pEditWin->OutputToScreenPixel( pEditWin->GetPosPixel() ); + aPoint = GetParent()->ScreenToOutputPixel( aPoint ); + Size aWinSize = GetSizePixel(); + aPoint.X() += aSize.Width() - aWinSize.Width() - 20; + aPoint.Y() += aSize.Height() / 2 - aWinSize.Height() / 2; + SetFloatingPos( aPoint ); + } + + SfxDockingWindow::StateChanged( nStateChange ); +} + +/*-- 10.12.2003 11:44:35--------------------------------------------------- + + -----------------------------------------------------------------------*/ +DropToolBox_Impl::DropToolBox_Impl(Window* pParent, SfxTemplateDialog_Impl* pTemplateDialog) : + ToolBox(pParent), + DropTargetHelper(this), + rParent(*pTemplateDialog) +{ +} +/*-- 10.12.2003 11:44:35--------------------------------------------------- + + -----------------------------------------------------------------------*/ +DropToolBox_Impl::~DropToolBox_Impl() +{ +} +/*-- 10.12.2003 11:44:35--------------------------------------------------- + + -----------------------------------------------------------------------*/ +sal_Int8 DropToolBox_Impl::AcceptDrop( const AcceptDropEvent& rEvt ) +{ + sal_Int8 nReturn = DND_ACTION_NONE; + USHORT nItemId = GetItemId( rEvt.maPosPixel ); + if(USHRT_MAX != nItemId && !IsItemChecked( nItemId )) + { + SetCurItemId(nItemId); + GetSelectHdl().Call(this); + } + // special case: page styles are allowed to create new styles by example + // but not allowed to be created by drag and drop + if ( nItemId != SfxCommonTemplateDialog_Impl::SfxFamilyIdToNId( SFX_STYLE_FAMILY_PAGE )&& + IsDropFormatSupported( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) && + !rParent.bNewByExampleDisabled ) + { + nReturn = DND_ACTION_COPY; + } + return nReturn; +} +/*-- 10.12.2003 11:44:35--------------------------------------------------- + + -----------------------------------------------------------------------*/ +sal_Int8 DropToolBox_Impl::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ + return rParent.aFmtLb.ExecuteDrop(rEvt); +} + diff --git a/sfx2/source/dialog/templdlg.hrc b/sfx2/source/dialog/templdlg.hrc new file mode 100644 index 000000000000..58563fb9c160 --- /dev/null +++ b/sfx2/source/dialog/templdlg.hrc @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#define TB_FMT 1 +#define LB_FMT 3 +#define BTN_EDIT 11 +#define BTN_DELETE 12 +#define TB_ACTION 15 +#define BTN_NEW 10 +#define LB_FILTER 4 + +#define ID_APPLY_TEMPLATE 10 + +#define ID_NEW_STYLE_BY_EXAMPLE 20 +#define ID_UPDATE_STYLE_BY_EXAMPLE 21 +#define ID_TREEVIEW 22 + +#define BT_OK 1 +#define BT_CANCEL 2 +#define BT_ORG 3 +#define BT_DEL 4 +#define BT_EDIT 5 +#define BT_NEW 6 +#define BT_HELP 7 +#define BT_FLIST 8 +#define BT_VLIST 9 +#define BT_TOOL 10 + + diff --git a/sfx2/source/dialog/templdlg.src b/sfx2/source/dialog/templdlg.src new file mode 100644 index 000000000000..a4adcd77b6d3 --- /dev/null +++ b/sfx2/source/dialog/templdlg.src @@ -0,0 +1,210 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + // include --------------------------------------------------------------- +#include <sfx2/sfx.hrc> +#include "dialog.hrc" +#include "templdlg.hrc" +#include "helpid.hrc" + +ImageList DLG_STYLE_DESIGNER +{ + Prefix = "sc"; + MaskColor = Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; }; + IdList = + { + SID_STYLE_WATERCAN ; + SID_STYLE_NEW_BY_EXAMPLE ; + SID_STYLE_UPDATE_BY_EXAMPLE ; + }; + IdCount = { 3 ; }; +}; +ImageList IMG_LST_STYLE_DESIGNER_HC +{ + Prefix = "sch"; + MaskColor = Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; }; + IdList = + { + SID_STYLE_WATERCAN ; + SID_STYLE_NEW_BY_EXAMPLE ; + SID_STYLE_UPDATE_BY_EXAMPLE ; + }; + IdCount = { 3 ; }; +}; + // RID_STYLECATALOG ------------------------------------------------------ +ModalDialog RID_STYLECATALOG +{ + HelpId = SID_STYLE_CATALOG ; + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 181 , 134 ) ; + Text [ en-US ] = "Style Catalog" ; + Moveable = TRUE ; + OKButton BT_OK + { + DefButton = TRUE ; + Pos = MAP_APPFONT ( 123 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + CancelButton BT_CANCEL + { + Pos = MAP_APPFONT ( 123 , 23 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + PushButton BT_ORG + { + Pos = MAP_APPFONT ( 123 , 97 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Organizer..." ; + TabStop = TRUE ; + }; + PushButton BT_DEL + { + Pos = MAP_APPFONT ( 123 , 78 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Delete..." ; + TabStop = TRUE ; + }; + PushButton BT_EDIT + { + Pos = MAP_APPFONT ( 123 , 60 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~Modify..." ; + TabStop = TRUE ; + }; + PushButton BT_NEW + { + Pos = MAP_APPFONT ( 123 , 43 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + Text [ en-US ] = "~New..." ; + TabStop = TRUE ; + }; + HelpButton BT_HELP + { + Pos = MAP_APPFONT ( 123 , 114 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + ListBox BT_TOOL + { + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 110 , 55 ) ; + TabStop = TRUE ; + DropDown = TRUE ; + }; + Control BT_VLIST + { + HelpId = HID_TEMPLATE_FMT ; + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 23 ) ; + Size = MAP_APPFONT ( 110 , 89 ) ; + TabStop = TRUE ; + }; + ListBox BT_FLIST + { + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 114 ) ; + Size = MAP_APPFONT ( 110 , 77 ) ; + TabStop = TRUE ; + Hide = TRUE ; + DropDown = TRUE ; + }; +}; + // Strings --------------------------------------------------------------- +String STR_STYLE_FILTER_HIERARCHICAL +{ + Text [ en-US ] = "Hierarchical" ; +}; + // DLG_STYLE_DESIGNER ---------------------------------------------------- +DockingWindow DLG_STYLE_DESIGNER +{ + Text [ en-US ] = "Styles and Formatting" ; + + HelpId = SID_STYLE_DESIGNER ; + OutputSize = TRUE ; + Hide = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 116 , 215 ) ; + Pos = MAP_APPFONT ( 0 , 0 ) ; + Closeable = TRUE ; + Zoomable = TRUE ; + Sizeable = TRUE ; + Dockable = TRUE ; + EnableResizing = TRUE ; + // HideWhenDeactivate = TRUE; + Border = TRUE ; + Moveable = TRUE ; + ToolBox TB_ACTION + { + Pos = MAP_APPFONT ( 3 , 3 ) ; + Size = MAP_APPFONT ( 57 , 42 ) ; + LineCount = 1 ; + ItemImageList = DLG_STYLE_DESIGNER ; + HelpId = HID_TEMPLDLG_TOOLBOX_RIGHT ; + ItemList = + { + ToolBoxItem + { + HelpId = HID_TEMPLDLG_WATERCAN ; + Identifier = SID_STYLE_WATERCAN ; + Text [ en-US ] = "Fill Format Mode" ; + }; + ToolBoxItem + { + HelpId = HID_TEMPLDLG_NEWBYEXAMPLE ; + Identifier = SID_STYLE_NEW_BY_EXAMPLE ; + Text [ en-US ] = "New Style from Selection" ; + }; + ToolBoxItem + { + HelpId = HID_TEMPLDLG_UPDATEBYEXAMPLE ; + Identifier = SID_STYLE_UPDATE_BY_EXAMPLE ; + Text [ en-US ] = "Update Style" ; + }; + }; + }; +}; + + + + + + + + + + + + + + + + + + diff --git a/sfx2/source/dialog/titledockwin.cxx b/sfx2/source/dialog/titledockwin.cxx new file mode 100644 index 000000000000..4be0948d8047 --- /dev/null +++ b/sfx2/source/dialog/titledockwin.cxx @@ -0,0 +1,360 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_sfx2.hxx" + +#include "sfx2/titledockwin.hxx" +#include "sfx2/bindings.hxx" +#include "sfx2/dispatch.hxx" +#include "sfxlocal.hrc" +#include "sfxresid.hxx" + +#include <svl/eitem.hxx> + +//...................................................................................................................... +namespace sfx2 +{ +//...................................................................................................................... + + //================================================================================================================== + //= TitledDockingWindow + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + TitledDockingWindow::TitledDockingWindow( SfxBindings* i_pBindings, SfxChildWindow* i_pChildWindow, Window* i_pParent, + WinBits i_nStyle ) + :SfxDockingWindow( i_pBindings, i_pChildWindow, i_pParent, i_nStyle ) + ,m_sTitle() + ,m_aToolbox( this ) + ,m_aContentWindow( this, WB_DIALOGCONTROL ) + ,m_aBorder( 3, 1, 3, 3 ) + ,m_bLayoutPending( false ) + ,m_nTitleBarHeight(0) + { + impl_construct(); + } + + //------------------------------------------------------------------------------------------------------------------ + TitledDockingWindow::TitledDockingWindow( SfxBindings* i_pBindings, SfxChildWindow* i_pChildWindow, Window* i_pParent, + const ResId& i_rResId ) + :SfxDockingWindow( i_pBindings, i_pChildWindow, i_pParent, i_rResId ) + ,m_sTitle() + ,m_aToolbox( this ) + ,m_aContentWindow( this ) + ,m_aBorder( 3, 1, 3, 3 ) + ,m_bLayoutPending( false ) + { + impl_construct(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::impl_construct() + { + SetBackground( Wallpaper() ); + + m_aToolbox.SetSelectHdl( LINK( this, TitledDockingWindow, OnToolboxItemSelected ) ); + m_aToolbox.SetOutStyle( TOOLBOX_STYLE_FLAT ); + m_aToolbox.SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetDialogColor() ) ); + m_aToolbox.Show(); + impl_resetToolBox(); + + m_aContentWindow.Show(); + } + + //------------------------------------------------------------------------------------------------------------------ + TitledDockingWindow::~TitledDockingWindow() + { + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::SetTitle( const String& i_rTitle ) + { + m_sTitle = i_rTitle; + Invalidate(); + } + + //------------------------------------------------------------------------------------------------------------------ + String TitledDockingWindow::GetTitle() const + { + return impl_getTitle(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::SetText( const String& i_rText ) + { + SfxDockingWindow::SetText( i_rText ); + if ( m_sTitle.Len() == 0 ) + // our text is used as title, too => repaint + Invalidate(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::Resize() + { + SfxDockingWindow::Resize(); + impl_scheduleLayout(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::onLayoutDone() + { + // not interested in + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::impl_scheduleLayout() + { + m_bLayoutPending = true; + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::impl_layout() + { + m_bLayoutPending = false; + + m_aToolbox.ShowItem( 1, !IsFloatingMode() ); + + const Size aToolBoxSize( m_aToolbox.CalcWindowSizePixel() ); + Size aWindowSize( GetOutputSizePixel() ); + + // position the tool box + m_nTitleBarHeight = GetSettings().GetStyleSettings().GetTitleHeight(); + if ( aToolBoxSize.Height() > m_nTitleBarHeight ) + m_nTitleBarHeight = aToolBoxSize.Height(); + m_aToolbox.SetPosSizePixel( + Point( + aWindowSize.Width() - aToolBoxSize.Width(), + ( m_nTitleBarHeight - aToolBoxSize.Height() ) / 2 + ), + aToolBoxSize + ); + + // Place the content window. + if ( m_nTitleBarHeight < aToolBoxSize.Height() ) + m_nTitleBarHeight = aToolBoxSize.Height(); + aWindowSize.Height() -= m_nTitleBarHeight; + m_aContentWindow.SetPosSizePixel( + Point( m_aBorder.Left(), m_nTitleBarHeight + m_aBorder.Top() ), + Size( + aWindowSize.Width() - m_aBorder.Left() - m_aBorder.Right(), + aWindowSize.Height() - m_aBorder.Top() - m_aBorder.Bottom() + ) + ); + + onLayoutDone(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::Paint( const Rectangle& i_rArea ) + { + if ( m_bLayoutPending ) + impl_layout(); + + SfxDockingWindow::Paint( i_rArea ); + + Push( PUSH_FONT | PUSH_FILLCOLOR | PUSH_LINECOLOR ); + + SetFillColor( GetSettings().GetStyleSettings().GetDialogColor() ); + SetLineColor(); + + // bold font + Font aFont( GetFont() ); + aFont.SetWeight( WEIGHT_BOLD ); + SetFont( aFont ); + + // Set border values. + Size aWindowSize( GetOutputSizePixel() ); + int nOuterLeft = 0; + int nInnerLeft = nOuterLeft + m_aBorder.Left() - 1; + int nOuterRight = aWindowSize.Width() - 1; + int nInnerRight = nOuterRight - m_aBorder.Right() + 1; + int nInnerTop = m_nTitleBarHeight + m_aBorder.Top() - 1; + int nOuterBottom = aWindowSize.Height() - 1; + int nInnerBottom = nOuterBottom - m_aBorder.Bottom() + 1; + + // Paint title bar background. + Rectangle aTitleBarBox( Rectangle( + nOuterLeft, + 0, + nOuterRight, + nInnerTop-1 + ) ); + DrawRect( aTitleBarBox ); + + if ( nInnerLeft > nOuterLeft ) + DrawRect( Rectangle( nOuterLeft, nInnerTop, nInnerLeft, nInnerBottom ) ); + if ( nOuterRight > nInnerRight ) + DrawRect( Rectangle( nInnerRight, nInnerTop, nOuterRight, nInnerBottom ) ); + if ( nInnerBottom < nOuterBottom ) + DrawRect( Rectangle( nOuterLeft, nInnerBottom, nOuterRight, nOuterBottom ) ); + + // Paint bevel border. + SetFillColor(); + SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() ); + if ( m_aBorder.Top() > 0 ) + DrawLine( Point( nInnerLeft, nInnerTop ), Point( nInnerLeft, nInnerBottom ) ); + if ( m_aBorder.Left() > 0 ) + DrawLine( Point( nInnerLeft, nInnerTop ), Point( nInnerRight, nInnerTop ) ); + + SetLineColor( GetSettings().GetStyleSettings().GetLightColor() ); + if ( m_aBorder.Bottom() > 0 ) + DrawLine( Point( nInnerRight, nInnerBottom ), Point( nInnerLeft, nInnerBottom ) ); + if ( m_aBorder.Right() > 0 ) + DrawLine( Point( nInnerRight, nInnerBottom ), Point( nInnerRight, nInnerTop ) ); + + // Paint title bar text. + SetLineColor( GetSettings().GetStyleSettings().GetActiveTextColor() ); + aTitleBarBox.Left() += 3; + DrawText( aTitleBarBox, impl_getTitle(), TEXT_DRAW_LEFT | TEXT_DRAW_VCENTER | TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); + + // Restore original values of the output device. + Pop(); + } + + //------------------------------------------------------------------------------------------------------------------ + String TitledDockingWindow::impl_getTitle() const + { + return m_sTitle.Len() ? m_sTitle : GetText(); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::impl_resetToolBox() + { + m_aToolbox.Clear(); + + // Get the closer bitmap and set it as right most button. + Image aImage( SfxResId( SFX_IMG_CLOSE_DOC ) ); + Image aImageHC( SfxResId( SFX_IMG_CLOSE_DOC_HC ) ); + m_aToolbox.InsertItem( 1, + GetSettings().GetStyleSettings().GetHighContrastMode() + ? aImageHC + : aImage + ); + m_aToolbox.ShowItem( 1 ); + } + + //------------------------------------------------------------------------------------------------------------------ + USHORT TitledDockingWindow::impl_addDropDownToolBoxItem( const String& i_rItemText, ULONG i_nHelpId, const Link& i_rCallback ) + { + // Add the menu before the closer button. + const USHORT nItemCount( m_aToolbox.GetItemCount() ); + const USHORT nItemId( nItemCount + 1 ); + m_aToolbox.InsertItem( nItemId, i_rItemText, TIB_DROPDOWNONLY, nItemCount > 0 ? nItemCount - 1 : TOOLBOX_APPEND ); + m_aToolbox.SetHelpId( nItemId, i_nHelpId ); + m_aToolbox.SetClickHdl( i_rCallback ); + m_aToolbox.SetDropdownClickHdl( i_rCallback ); + + // The tool box has likely changed its size. The title bar has to be + // resized. + impl_scheduleLayout(); + Invalidate(); + + return nItemId; + } + + //------------------------------------------------------------------------------------------------------------------ + IMPL_LINK( TitledDockingWindow, OnToolboxItemSelected, ToolBox*, pToolBox ) + { + const USHORT nId = pToolBox->GetCurItemId(); + + if ( nId == 1 ) + { + // the closer + EndTracking(); + const sal_uInt16 nChildWindowId( GetChildWindow_Impl()->GetType() ); + const SfxBoolItem aVisibility( nChildWindowId, FALSE ); + GetBindings().GetDispatcher()->Execute( + nChildWindowId, + SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, + &aVisibility, + NULL + ); + } + + return 0; + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::StateChanged( StateChangedType i_nType ) + { + switch ( i_nType ) + { + case STATE_CHANGE_INITSHOW: + impl_scheduleLayout(); + break; + } + SfxDockingWindow::StateChanged( i_nType ); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::EndDocking( const Rectangle& i_rRect, BOOL i_bFloatMode ) + { + SfxDockingWindow::EndDocking( i_rRect, i_bFloatMode ); + + if ( m_aEndDockingHdl.IsSet() ) + m_aEndDockingHdl.Call( this ); + } + + //------------------------------------------------------------------------------------------------------------------ + void TitledDockingWindow::DataChanged( const DataChangedEvent& i_rDataChangedEvent ) + { + SfxDockingWindow::DataChanged( i_rDataChangedEvent ); + + switch ( i_rDataChangedEvent.GetType() ) + { + case DATACHANGED_SETTINGS: + if ( ( i_rDataChangedEvent.GetFlags() & SETTINGS_STYLE ) == 0) + break; + // else fall through. + case DATACHANGED_FONTS: + case DATACHANGED_FONTSUBSTITUTION: + { + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + // Font. + Font aFont = rStyleSettings.GetAppFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + SetZoomedPointFont( aFont ); + + // Color. + Color aColor; + if ( IsControlForeground() ) + aColor = GetControlForeground(); + else + aColor = rStyleSettings.GetButtonTextColor(); + SetTextColor( aColor ); + SetTextFillColor(); + + impl_scheduleLayout(); + Invalidate(); + } + break; + } + } + +//...................................................................................................................... +} // namespace sfx2 +//...................................................................................................................... diff --git a/sfx2/source/dialog/titledockwin.src b/sfx2/source/dialog/titledockwin.src new file mode 100644 index 000000000000..3f52e84ab75d --- /dev/null +++ b/sfx2/source/dialog/titledockwin.src @@ -0,0 +1,39 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <sfx2/sfx.hrc> +#include "sfxlocal.hrc" + +Image SFX_IMG_CLOSE_DOC +{ + ImageBitmap = Bitmap { File = "closedoc.png" ; }; +}; + +Image SFX_IMG_CLOSE_DOC_HC +{ + ImageBitmap = Bitmap { File = "closedochc.png" ; }; +}; + diff --git a/sfx2/source/dialog/tplcitem.cxx b/sfx2/source/dialog/tplcitem.cxx new file mode 100644 index 000000000000..5d7569300cf8 --- /dev/null +++ b/sfx2/source/dialog/tplcitem.cxx @@ -0,0 +1,188 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include <svl/intitem.hxx> +#include <vcl/svapp.hxx> + +#ifndef GCC +#endif + +#include <sfx2/templdlg.hxx> +#include <sfx2/bindings.hxx> +#include "tplpitem.hxx" +#include "tplcitem.hxx" +#include "templdgi.hxx" + +#include <sfx2/sfx.hrc> +#include "dialog.hrc" + +// STATIC DATA ----------------------------------------------------------- + +// Konstruktor + +SfxTemplateControllerItem::SfxTemplateControllerItem( + USHORT nSlotId, // ID + SfxCommonTemplateDialog_Impl &rDlg, // Controller-Instanz, dem dieses Item zugeordnet ist. + SfxBindings &rBindings): + SfxControllerItem(nSlotId, rBindings), + rTemplateDlg(rDlg), + nWaterCanState(0xff), + nUserEventId(0) +{ +} +// ----------------------------------------------------------------------- +SfxTemplateControllerItem::~SfxTemplateControllerItem() +{ + if(nUserEventId) + Application::RemoveUserEvent(nUserEventId); +} + +// ----------------------------------------------------------------------- + +// Benachrichtigung "uber Status"anderung; wird an den +// im Konstruktor "ubergebenen Controller propagiert + +void SfxTemplateControllerItem::StateChanged( USHORT nSID, SfxItemState eState, + const SfxPoolItem* pItem ) +{ + switch(nSID) + { + case SID_STYLE_FAMILY1: + case SID_STYLE_FAMILY2: + case SID_STYLE_FAMILY3: + case SID_STYLE_FAMILY4: + case SID_STYLE_FAMILY5: + { + FASTBOOL bAvailable = SFX_ITEM_AVAILABLE == eState; + if ( !bAvailable ) + rTemplateDlg.SetFamilyState(GetId(), 0); + else { + const SfxTemplateItem *pStateItem = PTR_CAST( + SfxTemplateItem, pItem); + DBG_ASSERT(pStateItem != 0, "SfxTemplateItem erwartet"); + rTemplateDlg.SetFamilyState( GetId(), pStateItem ); + } + BOOL bDisable = eState == SFX_ITEM_DISABLED; + // Familie Disablen + USHORT nFamily = 0; + switch( GetId()) + { + case SID_STYLE_FAMILY1: + nFamily = 1; break; + case SID_STYLE_FAMILY2: + nFamily = 2; break; + case SID_STYLE_FAMILY3: + nFamily = 3; break; + case SID_STYLE_FAMILY4: + nFamily = 4; break; + case SID_STYLE_FAMILY5: + nFamily = 5; break; + default: DBG_ERROR("unbekannte StyleFamily"); break; + } + rTemplateDlg.EnableFamilyItem( nFamily, !bDisable ); + break; + } + case SID_STYLE_WATERCAN: + { + if ( eState == SFX_ITEM_DISABLED ) + nWaterCanState = 0xff; + else if( eState == SFX_ITEM_AVAILABLE ) + { + const SfxBoolItem *pStateItem = PTR_CAST(SfxBoolItem, pItem); + DBG_ASSERT(pStateItem != 0, "BoolItem erwartet"); + nWaterCanState = pStateItem->GetValue() ? 1 : 0; + } + //not necessary if the last event is still on the way + if(!nUserEventId) + nUserEventId = Application::PostUserEvent( STATIC_LINK( + this, SfxTemplateControllerItem, SetWaterCanStateHdl_Impl ) ); + break; + } + case SID_STYLE_EDIT: + rTemplateDlg.EnableEdit( SFX_ITEM_DISABLED != eState ); + break; + case SID_STYLE_DELETE: + rTemplateDlg.EnableDel( SFX_ITEM_DISABLED != eState ); + break; + case SID_STYLE_NEW_BY_EXAMPLE: + + rTemplateDlg.EnableExample_Impl( + GetId(), SFX_ITEM_DISABLED != eState ); + break; + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + rTemplateDlg.EnableExample_Impl( + GetId(), eState != SFX_ITEM_DISABLED ); + // Das Select Disabled dann, falls enabled und Style Readonly +/* String aStr = rTemplateDlg.GetSelectedEntry(); + if( aStr.Len() ) rTemplateDlg.SelectStyle( aStr ); */ + break; + } + case SID_STYLE_NEW: + { + rTemplateDlg.EnableNew( SFX_ITEM_DISABLED != eState ); + break; + } + case SID_STYLE_DRAGHIERARCHIE: + { + rTemplateDlg.EnableTreeDrag( SFX_ITEM_DISABLED != eState ); + break; + } + case SID_STYLE_FAMILY : + { + const SfxUInt16Item *pStateItem = PTR_CAST( SfxUInt16Item, pItem); + if (pStateItem) + rTemplateDlg.SetFamily( pStateItem->GetValue() ); + break; + } + } +} +/* -----------------------------05.09.2001 10:48------------------------------ + + ---------------------------------------------------------------------------*/ +IMPL_STATIC_LINK(SfxTemplateControllerItem, SetWaterCanStateHdl_Impl, + SfxTemplateControllerItem*, EMPTYARG) +{ + pThis->nUserEventId = 0; + SfxBoolItem* pState = 0; + switch(pThis->nWaterCanState) + { + case 0 : + case 1 : + pState = new SfxBoolItem(SID_STYLE_WATERCAN, pThis->nWaterCanState ? TRUE : FALSE); + break; + } + pThis->rTemplateDlg.SetWaterCanState(pState); + delete pState; + return 0; +} + diff --git a/sfx2/source/dialog/tplpitem.cxx b/sfx2/source/dialog/tplpitem.cxx new file mode 100644 index 000000000000..7b81fb54cdbd --- /dev/null +++ b/sfx2/source/dialog/tplpitem.cxx @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +// INCLUDE --------------------------------------------------------------- + +#ifndef GCC +#endif + +#include "tplpitem.hxx" +#include <com/sun/star/frame/status/Template.hpp> + + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1_AUTOFACTORY(SfxTemplateItem, SfxFlagItem); + +//========================================================================= + +SfxTemplateItem::SfxTemplateItem() : + SfxFlagItem() +{ +} + +SfxTemplateItem::SfxTemplateItem +( + USHORT nWhichId, // Slot-ID + const String& rStyle, // Name des aktuellen Styles + USHORT nValue // Flags f"ur das Filtern bei automatischer Anzeige +) : SfxFlagItem( nWhichId, nValue ), + aStyle( rStyle ) +{ +} + +//------------------------------------------------------------------------- + +// copy ctor +SfxTemplateItem::SfxTemplateItem( const SfxTemplateItem& rCopy ) : + + SfxFlagItem( rCopy ), + + aStyle( rCopy.aStyle ) +{ +} + +//------------------------------------------------------------------------- + +// op == + +int SfxTemplateItem::operator==( const SfxPoolItem& rCmp ) const +{ + return ( SfxFlagItem::operator==( rCmp ) && + aStyle == ( (const SfxTemplateItem&)rCmp ).aStyle ); +} + +//------------------------------------------------------------------------- + +SfxPoolItem* SfxTemplateItem::Clone( SfxItemPool *) const +{ + return new SfxTemplateItem(*this); +} + +//------------------------------------------------------------------------- +sal_Bool SfxTemplateItem::QueryValue( com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ ) const +{ + ::com::sun::star::frame::status::Template aTemplate; + + aTemplate.Value = GetValue(); + aTemplate.StyleName = aStyle; + rVal <<= aTemplate; + + return sal_True; +} + +//------------------------------------------------------------------------- +sal_Bool SfxTemplateItem::PutValue( const com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ ) +{ + ::com::sun::star::frame::status::Template aTemplate; + + if ( rVal >>= aTemplate ) + { + SetValue( sal::static_int_cast< USHORT >( aTemplate.Value ) ); + aStyle = aTemplate.StyleName; + return sal_True; + } + + return sal_False; +} + +//------------------------------------------------------------------------- + +BYTE SfxTemplateItem::GetFlagCount() const +{ + return sizeof(USHORT) * 8; +} + + diff --git a/sfx2/source/dialog/versdlg.cxx b/sfx2/source/dialog/versdlg.cxx new file mode 100644 index 000000000000..beb43c192810 --- /dev/null +++ b/sfx2/source/dialog/versdlg.cxx @@ -0,0 +1,519 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <unotools/localedatawrapper.hxx> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svl/itemset.hxx> +#include <unotools/useroptions.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <tools/datetime.hxx> + +#define _SVSTDARR_STRINGSDTOR +#include <svl/svstdarr.hxx> + +#include "versdlg.hrc" +#include "versdlg.hxx" +#include <sfx2/viewfrm.hxx> +#include "sfxresid.hxx" +#include <sfx2/docfile.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/dispatch.hxx> +#include <sfx2/request.hxx> + +#include <sfx2/sfxuno.hxx> + +using namespace com::sun::star; + +// ************************************************************************** +struct SfxVersionInfo +{ + String aName; + String aComment; + String aAuthor; + DateTime aCreationDate; + + SfxVersionInfo(); + SfxVersionInfo( const SfxVersionInfo& rInfo ) + { *this = rInfo; } + + SfxVersionInfo& operator=( const SfxVersionInfo &rInfo ) + { + aName = rInfo.aName; + aComment = rInfo.aComment; + aAuthor = rInfo.aAuthor; + aCreationDate = rInfo.aCreationDate; + return *this; + } +}; +DECLARE_LIST( _SfxVersionTable, SfxVersionInfo* ) +class SfxVersionTableDtor : public _SfxVersionTable +{ +public: + SfxVersionTableDtor( const sal_uInt16 nInitSz=0, const sal_uInt16 nReSz=1 ) + : _SfxVersionTable( nInitSz, nReSz ) + {} + + SfxVersionTableDtor( const SfxVersionTableDtor &rCpy ) : + _SfxVersionTable( rCpy ) + { *this = rCpy; } + + SfxVersionTableDtor( const uno::Sequence < util::RevisionTag >& rInfo ); + + ~SfxVersionTableDtor() + { DelDtor(); } + + SfxVersionTableDtor& operator=( const SfxVersionTableDtor &rCpy ); + void DelDtor(); + SvStream& Read( SvStream & ); + SvStream& Write( SvStream & ) const; + SvStringsDtor* GetVersions() const; +}; + +SfxVersionTableDtor::SfxVersionTableDtor( const uno::Sequence < util::RevisionTag >& rInfo ) +{ + for ( sal_Int32 n=0; n<(sal_Int32)rInfo.getLength(); n++ ) + { + SfxVersionInfo* pInfo = new SfxVersionInfo; + pInfo->aName = rInfo[n].Identifier; + pInfo->aComment = rInfo[n].Comment; + pInfo->aAuthor = rInfo[n].Author; + + Date aDate ( rInfo[n].TimeStamp.Day, rInfo[n].TimeStamp.Month, rInfo[n].TimeStamp.Year ); + Time aTime ( rInfo[n].TimeStamp.Hours, rInfo[n].TimeStamp.Minutes, rInfo[n].TimeStamp.Seconds, rInfo[n].TimeStamp.HundredthSeconds ); + + pInfo->aCreationDate = DateTime( aDate, aTime ); + Insert( pInfo, Count() ); + } +} + +void SfxVersionTableDtor::DelDtor() +{ + SfxVersionInfo* pTmp = First(); + while( pTmp ) + { + delete pTmp; + pTmp = Next(); + } + Clear(); +} + +SfxVersionTableDtor& SfxVersionTableDtor::operator=( const SfxVersionTableDtor& rTbl ) +{ + DelDtor(); + SfxVersionInfo* pTmp = ((SfxVersionTableDtor&)rTbl).First(); + while( pTmp ) + { + SfxVersionInfo *pNew = new SfxVersionInfo( *pTmp ); + Insert( pNew, LIST_APPEND ); + pTmp = ((SfxVersionTableDtor&)rTbl).Next(); + } + return *this; +} + +//---------------------------------------------------------------- +//---------------------------------------------------------------- +//---------------------------------------------------------------- +SfxVersionInfo::SfxVersionInfo() +{ +} + +static String ConvertDateTime_Impl(const DateTime& rTime, const LocaleDataWrapper& rWrapper) +{ + const String pDelim ( DEFINE_CONST_UNICODE( ", ")); + String aStr(rWrapper.getDate(rTime)); + aStr += pDelim; + aStr += rWrapper.getTime(rTime, TRUE, FALSE); + return aStr; +} + +SvStringsDtor* SfxVersionTableDtor::GetVersions() const +{ + SvStringsDtor *pList = new SvStringsDtor; + SfxVersionInfo* pInfo = ((SfxVersionTableDtor*) this)->First(); + LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + while ( pInfo ) + { + String *pString = new String( pInfo->aComment ); + (*pString) += DEFINE_CONST_UNICODE( "; " ); + (*pString) += ConvertDateTime_Impl( pInfo->aCreationDate, aLocaleWrapper ); + pList->Insert( pString, pList->Count() ); + pInfo = ((SfxVersionTableDtor*) this)->Next(); + } + + return pList; +} + +// Achtung im Code wird dieses Array direkt (0, 1, ...) indiziert +static long nTabs_Impl[] = +{ + 3, // Number of Tabs + 0, 62, 124 +}; + +void SfxVersionsTabListBox_Impl::KeyInput( const KeyEvent& rKeyEvent ) +{ + const KeyCode& rCode = rKeyEvent.GetKeyCode(); + switch ( rCode.GetCode() ) + { + case KEY_RETURN : + case KEY_ESCAPE : + case KEY_TAB : + Window::GetParent()->KeyInput( rKeyEvent ); + break; + default: + SvTabListBox::KeyInput( rKeyEvent ); + break; + } +} + +SfxVersionsTabListBox_Impl::SfxVersionsTabListBox_Impl( Window* pParent, const ResId& rResId ) + : SvTabListBox( pParent, rResId ) +{ +} + +SfxVersionDialog::SfxVersionDialog ( SfxViewFrame* pVwFrame, BOOL bIsSaveVersionOnClose ) + : SfxModalDialog( NULL, SfxResId( DLG_VERSIONS ) ) + , aNewGroup( this, SfxResId( GB_NEWVERSIONS ) ) + , aSaveButton( this, SfxResId( PB_SAVE ) ) + , aSaveCheckBox( this, SfxResId( CB_SAVEONCLOSE ) ) + , aExistingGroup( this, SfxResId( GB_OLDVERSIONS ) ) + , aDateTimeText( this, SfxResId( FT_DATETIME ) ) + , aSavedByText( this, SfxResId( FT_SAVEDBY ) ) + , aCommentText( this, SfxResId( FT_COMMENTS ) ) + , aVersionBox( this, SfxResId( TLB_VERSIONS ) ) + , aCloseButton( this, SfxResId( PB_CLOSE ) ) + , aOpenButton( this, SfxResId( PB_OPEN ) ) + , aViewButton( this, SfxResId( PB_VIEW ) ) + , aDeleteButton( this, SfxResId( PB_DELETE ) ) + , aCompareButton( this, SfxResId( PB_COMPARE ) ) + , aHelpButton( this, SfxResId( PB_HELP ) ) + , pViewFrame( pVwFrame ) + , mpTable( NULL ) + , mpLocaleWrapper( NULL ) + , mbIsSaveVersionOnClose( bIsSaveVersionOnClose ) +{ + FreeResource(); + + Link aClickLink = LINK( this, SfxVersionDialog, ButtonHdl_Impl ); + aViewButton.SetClickHdl ( aClickLink ); + aSaveButton.SetClickHdl ( aClickLink ); + aDeleteButton.SetClickHdl ( aClickLink ); + aCompareButton.SetClickHdl ( aClickLink ); + aOpenButton.SetClickHdl ( aClickLink ); + aSaveCheckBox.SetClickHdl ( aClickLink ); + + aVersionBox.SetSelectHdl( LINK( this, SfxVersionDialog, SelectHdl_Impl ) ); + aVersionBox.SetDoubleClickHdl( LINK( this, SfxVersionDialog, DClickHdl_Impl ) ); + + aVersionBox.GrabFocus(); + aVersionBox.SetWindowBits( WB_HSCROLL | WB_CLIPCHILDREN ); + aVersionBox.SetSelectionMode( SINGLE_SELECTION ); + aVersionBox.SetTabs( &nTabs_Impl[0], MAP_APPFONT ); + aVersionBox.Resize(); // OS: Hack fuer richtige Selektion + RecalcDateColumn(); + + // set dialog title (filename or docinfo title) + String sText = GetText(); + ( sText += ' ' ) += pViewFrame->GetObjectShell()->GetTitle(); + SetText( sText ); + + Init_Impl(); +} + +String ConvertWhiteSpaces_Impl( const String& rText ) +{ + // converted linebreaks and tabs to blanks; it's necessary for the display + String sConverted; + const sal_Unicode* pChars = rText.GetBuffer(); + while ( *pChars ) + { + switch ( *pChars ) + { + case '\n' : + case '\t' : + sConverted += ' '; + break; + + default: + sConverted += *pChars; + } + + ++pChars; + } + + return sConverted; +} + +void SfxVersionDialog::Init_Impl() +{ + SfxObjectShell *pObjShell = pViewFrame->GetObjectShell(); + SfxMedium* pMedium = pObjShell->GetMedium(); + uno::Sequence < util::RevisionTag > aVersions = pMedium->GetVersionList( true ); + delete mpTable; + mpTable = new SfxVersionTableDtor( aVersions ); + { + for ( USHORT n = 0; n < mpTable->Count(); ++n ) + { + SfxVersionInfo *pInfo = mpTable->GetObject(n); + String aEntry = ConvertDateTime_Impl( pInfo->aCreationDate, *mpLocaleWrapper ); + aEntry += '\t'; + aEntry += pInfo->aAuthor; + aEntry += '\t'; + aEntry += ConvertWhiteSpaces_Impl( pInfo->aComment ); + SvLBoxEntry *pEntry = aVersionBox.InsertEntry( aEntry ); + pEntry->SetUserData( pInfo ); + } + } + + aSaveCheckBox.Check( mbIsSaveVersionOnClose ); + + BOOL bEnable = !pObjShell->IsReadOnly(); + aSaveButton.Enable( bEnable ); + aSaveCheckBox.Enable( bEnable ); + + aOpenButton.Disable(); + aViewButton.Disable(); + aDeleteButton.Disable(); + aCompareButton.Disable(); + + SelectHdl_Impl( &aVersionBox ); +} + +SfxVersionDialog::~SfxVersionDialog () +{ + delete mpTable; + delete mpLocaleWrapper; +} + +void SfxVersionDialog::Open_Impl() +{ + SfxObjectShell *pObjShell = pViewFrame->GetObjectShell(); + + SvLBoxEntry *pEntry = aVersionBox.FirstSelected(); + ULONG nPos = aVersionBox.GetModel()->GetRelPos( pEntry ); + SfxInt16Item aItem( SID_VERSION, (short)nPos+1 ); + SfxStringItem aTarget( SID_TARGETNAME, DEFINE_CONST_UNICODE("_blank") ); + SfxStringItem aReferer( SID_REFERER, DEFINE_CONST_UNICODE("private:user") ); + SfxStringItem aFile( SID_FILE_NAME, pObjShell->GetMedium()->GetName() ); + + ::rtl::OUString aPassString; + if ( GetPasswd_Impl( pObjShell->GetMedium()->GetItemSet(), aPassString ) ) + { + // there is a password, it should be used during the opening + SfxStringItem aPassItem( SID_PASSWORD, aPassString ); + pViewFrame->GetDispatcher()->Execute( + SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, &aFile, &aItem, &aTarget, &aReferer, &aPassItem, 0L ); + } + else + pViewFrame->GetDispatcher()->Execute( + SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, &aFile, &aItem, &aTarget, &aReferer, 0L ); + + Close(); +} + +void SfxVersionDialog::RecalcDateColumn() +{ + // recalculate the datetime column width + DateTime aNow; + mpLocaleWrapper = new LocaleDataWrapper( + ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + String sDateTime = ConvertDateTime_Impl( aNow, *mpLocaleWrapper ); + long nWidth = aVersionBox.GetTextWidth( sDateTime ); + nWidth += 15; // a little offset + long nTab = aVersionBox.GetTab(1); + if ( nWidth > nTab ) + { + // resize columns + long nDelta = nWidth - nTab; + aVersionBox.SetTab( 1, nTab + nDelta, MAP_PIXEL ); + nTab = aVersionBox.GetTab(2); + aVersionBox.SetTab( 2, nTab + nDelta, MAP_PIXEL ); + + // resize and move header + Size aSize = aDateTimeText.GetSizePixel(); + aSize.Width() += nDelta; + aDateTimeText.SetSizePixel( aSize ); + Point aPos = aSavedByText.GetPosPixel(); + aPos.X() += nDelta; + aSavedByText.SetPosPixel( aPos ); + aPos = aCommentText.GetPosPixel(); + aPos.X() += nDelta; + aCommentText.SetPosPixel( aPos ); + } +} + +IMPL_LINK( SfxVersionDialog, DClickHdl_Impl, Control*, EMPTYARG ) +{ + Open_Impl(); + return 0L; +} + +IMPL_LINK( SfxVersionDialog, SelectHdl_Impl, Control*, EMPTYARG ) +{ + bool bEnable = ( aVersionBox.FirstSelected() != NULL ); + SfxObjectShell* pObjShell = pViewFrame->GetObjectShell(); + aDeleteButton.Enable( bEnable!= false && !pObjShell->IsReadOnly() ); + aOpenButton.Enable( bEnable!= false ); + aViewButton.Enable( bEnable!= false ); + + const SfxPoolItem *pDummy=NULL; + SfxItemState eState = pViewFrame->GetDispatcher()->QueryState( SID_DOCUMENT_MERGE, pDummy ); + eState = pViewFrame->GetDispatcher()->QueryState( SID_DOCUMENT_COMPARE, pDummy ); + aCompareButton.Enable( bEnable!= false && eState >= SFX_ITEM_AVAILABLE ); + + return 0L; +} + +IMPL_LINK( SfxVersionDialog, ButtonHdl_Impl, Button*, pButton ) +{ + SfxObjectShell *pObjShell = pViewFrame->GetObjectShell(); + SvLBoxEntry *pEntry = aVersionBox.FirstSelected(); + + if ( pButton == &aSaveCheckBox ) + { + mbIsSaveVersionOnClose = aSaveCheckBox.IsChecked(); + } + else if ( pButton == &aSaveButton ) + { + SfxVersionInfo aInfo; + aInfo.aAuthor = SvtUserOptions().GetFullName(); + SfxViewVersionDialog_Impl* pDlg = new SfxViewVersionDialog_Impl( this, aInfo, TRUE ); + short nRet = pDlg->Execute(); + if ( nRet == RET_OK ) + { + SfxStringItem aComment( SID_DOCINFO_COMMENTS, aInfo.aComment ); + pObjShell->SetModified( TRUE ); + const SfxPoolItem* aItems[2]; + aItems[0] = &aComment; + aItems[1] = NULL; + pViewFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, aItems, 0 ); + aVersionBox.SetUpdateMode( FALSE ); + aVersionBox.Clear(); + Init_Impl(); + aVersionBox.SetUpdateMode( TRUE ); + } + + delete pDlg; + } + if ( pButton == &aDeleteButton && pEntry ) + { + pObjShell->GetMedium()->RemoveVersion_Impl( ((SfxVersionInfo*) pEntry->GetUserData())->aName ); + pObjShell->SetModified( TRUE ); + aVersionBox.SetUpdateMode( FALSE ); + aVersionBox.Clear(); + Init_Impl(); + aVersionBox.SetUpdateMode( TRUE ); + } + else if ( pButton == &aOpenButton && pEntry ) + { + Open_Impl(); + } + else if ( pButton == &aViewButton && pEntry ) + { + SfxVersionInfo* pInfo = (SfxVersionInfo*) pEntry->GetUserData(); + SfxViewVersionDialog_Impl* pDlg = new SfxViewVersionDialog_Impl( this, *pInfo, FALSE ); + pDlg->Execute(); + delete pDlg; + } + else if ( pEntry && pButton == &aCompareButton ) + { + SfxAllItemSet aSet( pObjShell->GetPool() ); + ULONG nPos = aVersionBox.GetModel()->GetRelPos( pEntry ); + aSet.Put( SfxInt16Item( SID_VERSION, (short)nPos+1 ) ); + aSet.Put( SfxStringItem( SID_FILE_NAME, pObjShell->GetMedium()->GetName() ) ); + + SfxItemSet* pSet = pObjShell->GetMedium()->GetItemSet(); + SFX_ITEMSET_ARG( pSet, pFilterItem, SfxStringItem, SID_FILTER_NAME, FALSE ); + SFX_ITEMSET_ARG( pSet, pFilterOptItem, SfxStringItem, SID_FILE_FILTEROPTIONS, FALSE ); + if ( pFilterItem ) + aSet.Put( *pFilterItem ); + if ( pFilterOptItem ) + aSet.Put( *pFilterOptItem ); + + pViewFrame->GetDispatcher()->Execute( SID_DOCUMENT_COMPARE, SFX_CALLMODE_ASYNCHRON, aSet ); + Close(); + } + + return 0L; +} + +SfxViewVersionDialog_Impl::SfxViewVersionDialog_Impl ( Window *pParent, SfxVersionInfo& rInfo, BOOL bEdit ) + : SfxModalDialog( pParent, SfxResId( DLG_COMMENTS ) ) + , aDateTimeText( this, SfxResId( FT_DATETIME ) ) + , aSavedByText( this, SfxResId( FT_SAVEDBY ) ) + , aEdit( this, SfxResId( ME_VERSIONS ) ) + , aOKButton( this, SfxResId( PB_OK ) ) + , aCancelButton( this, SfxResId( PB_CANCEL ) ) + , aCloseButton( this, SfxResId( PB_CLOSE ) ) + , aHelpButton( this, SfxResId( PB_HELP ) ) + , pInfo( &rInfo ) +{ + FreeResource(); + + LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + aDateTimeText.SetText( aDateTimeText.GetText().Append(ConvertDateTime_Impl( pInfo->aCreationDate, aLocaleWrapper )) ); + aSavedByText.SetText( aSavedByText.GetText().Append(pInfo->aAuthor) ); + aEdit.SetText( rInfo.aComment ); + + aCloseButton.SetClickHdl ( LINK( this, SfxViewVersionDialog_Impl, ButtonHdl ) ); + aOKButton.SetClickHdl ( LINK( this, SfxViewVersionDialog_Impl, ButtonHdl ) ); + + aEdit.GrabFocus(); + if ( !bEdit ) + { + aOKButton.Hide(); + aCancelButton.Hide(); + aEdit.SetReadOnly( TRUE ); + } + else + aCloseButton.Hide(); +} + +IMPL_LINK( SfxViewVersionDialog_Impl, ButtonHdl, Button*, pButton ) +{ + if ( pButton == &aCloseButton ) + { + EndDialog( RET_CANCEL ); + } + else if ( pButton == &aOKButton ) + { + pInfo->aComment = aEdit.GetText(); + EndDialog( RET_OK ); + } + + return 0L; +} + diff --git a/sfx2/source/dialog/versdlg.hrc b/sfx2/source/dialog/versdlg.hrc new file mode 100644 index 000000000000..2de7596221e1 --- /dev/null +++ b/sfx2/source/dialog/versdlg.hrc @@ -0,0 +1,48 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <dialog.hrc> + +#define GB_NEWVERSIONS 1 +#define PB_SAVE 2 +#define CB_SAVEONCLOSE 3 +#define TLB_VERSIONS 4 +#define PB_DELETE 5 +#define PB_OPEN 6 +#define PB_HELP 7 +#define PB_CLOSE 8 +#define GB_OLDVERSIONS 9 +#define FT_DATETIME 10 +#define FT_SAVEDBY 11 +#define FT_COMMENTS 12 +#define PB_VIEW 13 +#define ME_VERSIONS 14 +#define PB_OK 15 +#define PB_CANCEL 16 +#define PB_COMPARE 17 +#define PB_MERGE 18 + diff --git a/sfx2/source/dialog/versdlg.src b/sfx2/source/dialog/versdlg.src new file mode 100644 index 000000000000..60aeb2777542 --- /dev/null +++ b/sfx2/source/dialog/versdlg.src @@ -0,0 +1,212 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "versdlg.hrc" +ModalDialog DLG_VERSIONS +{ + OutputSize = TRUE ; + Size = MAP_APPFONT ( 340 , 184 ) ; + SvLook = TRUE ; + Moveable = TRUE ; +//! Closeable = TRUE ; + FixedLine GB_NEWVERSIONS + { + Pos = MAP_APPFONT ( 6 , 3 ) ; + Size = MAP_APPFONT ( 272 , 8 ) ; + Text [ en-US ] = "New versions" ; + }; + PushButton PB_SAVE + { + Pos = MAP_APPFONT ( 12 , 14 ) ; + Size = MAP_APPFONT ( 90 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "Save ~New Version" ; + }; + CheckBox CB_SAVEONCLOSE + { + Pos = MAP_APPFONT ( 108 , 16 ) ; + Size = MAP_APPFONT ( 164 , 10 ) ; + TabStop = TRUE ; + Text [ en-US ] = "~Always save a version on closing" ; + }; + FixedLine GB_OLDVERSIONS + { + Pos = MAP_APPFONT ( 6 , 34 ) ; + Size = MAP_APPFONT ( 272 , 8 ) ; + Text [ en-US ] = "Existing versions" ; + }; + FixedText FT_DATETIME + { + Pos = MAP_APPFONT ( 15 , 45 ) ; + Size = MAP_APPFONT ( 60 , 10 ) ; + Text [ en-US ] = "Date and time" ; + }; + FixedText FT_SAVEDBY + { + Pos = MAP_APPFONT ( 76 , 45 ) ; + Size = MAP_APPFONT ( 60 , 10 ) ; + Text [ en-US ] = "Saved by" ; + }; + FixedText FT_COMMENTS + { + Pos = MAP_APPFONT ( 138 , 45 ) ; + Size = MAP_APPFONT ( 60 , 10 ) ; + Text [ en-US ] = "Comments" ; + }; + Control TLB_VERSIONS + { + Border = TRUE ; + Pos = MAP_APPFONT ( 12 , 58 ) ; + Size = MAP_APPFONT ( 260 , 114 ) ; + TabStop = TRUE ; + }; + CancelButton PB_CLOSE + { + Pos = MAP_APPFONT ( 284 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "Close" ; + }; + PushButton PB_OPEN + { + Pos = MAP_APPFONT ( 284 , 26 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "Open" ; + }; + PushButton PB_VIEW + { + Pos = MAP_APPFONT ( 284 , 43 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + Text [ en-US ] = "~Show..." ; + }; + PushButton PB_DELETE + { + Pos = MAP_APPFONT ( 284 , 60 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "~Delete" ; + }; + PushButton PB_COMPARE + { + Pos = MAP_APPFONT ( 284 , 77 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "Compare" ; + }; + HelpButton PB_HELP + { + Pos = MAP_APPFONT ( 284 , 97 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + Text [ en-US ] = "Versions of" ; +}; +ModalDialog DLG_COMMENTS +{ + OutputSize = TRUE ; + Size = MAP_APPFONT ( 180 , 118 ) ; + SvLook = TRUE ; + Moveable = TRUE ; + FixedText FT_DATETIME + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 168 , 10 ) ; + Text [ en-US ] = "Date and time : " ; + }; + FixedText FT_SAVEDBY + { + Pos = MAP_APPFONT ( 6 , 19 ) ; + Size = MAP_APPFONT ( 168 , 10 ) ; + Text [ en-US ] = "Saved by " ; + }; + MultiLineEdit ME_VERSIONS + { + Border = TRUE ; + Pos = MAP_APPFONT ( 6 , 32 ) ; + Size = MAP_APPFONT ( 168 , 60 ) ; + TabStop = TRUE ; + }; + OKButton PB_OK + { + Pos = MAP_APPFONT ( 15 , 98 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + }; + CancelButton PB_CANCEL + { + Pos = MAP_APPFONT ( 68 , 98 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + PushButton PB_CLOSE + { + Pos = MAP_APPFONT ( 68 , 98 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "~Close" ; + }; + HelpButton PB_HELP + { + Pos = MAP_APPFONT ( 124 , 98 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + TabStop = TRUE ; + }; + Text [ en-US ] = "Insert Version Comment" ; +}; +String DLG_COMMENTS +{ + Text [ en-US ] = "Version comment" ; +}; + + + + + + + + + + + + + + + + + + + + + + + + + |