diff options
Diffstat (limited to 'cui/source/customize/cfg.cxx')
-rw-r--r-- | cui/source/customize/cfg.cxx | 6060 |
1 files changed, 6060 insertions, 0 deletions
diff --git a/cui/source/customize/cfg.cxx b/cui/source/customize/cfg.cxx new file mode 100644 index 000000000000..022cc1cfb72c --- /dev/null +++ b/cui/source/customize/cfg.cxx @@ -0,0 +1,6060 @@ +/************************************************************************* + * + * 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_cui.hxx" + +#include <stdlib.h> +#include <time.h> + +#ifndef _HELP_HXX //autogen +#include <vcl/help.hxx> +#endif +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <vcl/decoview.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/scrbar.hxx> + +//added for issue73355 +//#ifndef _SV_SVDATA_HXX +//#include <vcl/svdata.hxx> +//#endif +//issue73355 ends + +#include <sfx2/app.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/msgpool.hxx> +#include <sfx2/mnumgr.hxx> +#include <sfx2/macrconf.hxx> +#include <sfx2/minfitem.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/request.hxx> +#include <sfx2/filedlghelper.hxx> +#include <svl/stritem.hxx> +#include <svtools/miscopt.hxx> +#include <tools/diagnose_ex.h> +#include <toolkit/unohlp.hxx> + +#include <algorithm> +//add +#include <cuires.hrc> +#include "cfg.hrc" +#include "helpid.hrc" + +#include "acccfg.hxx" +#include "cfg.hxx" +#include "eventdlg.hxx" +#include <dialmgr.hxx> + +#include <comphelper/documentinfo.hxx> +#include <comphelper/processfactory.hxx> +#ifndef _UNOTOOLS_CONFIGMGR_HXX_ +#include <unotools/configmgr.hxx> +#endif +#include <com/sun/star/ui/ItemType.hpp> +#include <com/sun/star/ui/ItemStyle.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/ui/XUIConfiguration.hpp> +#include <com/sun/star/ui/XUIConfigurationListener.hpp> +#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> +#include <com/sun/star/ui/XUIConfigurationStorage.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManager.hpp> +#include <com/sun/star/ui/XUIElement.hpp> +#ifndef _COM_SUN_STAR_UI_UIElementType_HPP_ +#include <com/sun/star/ui/UIElementType.hpp> +#endif +#include <com/sun/star/ui/ImageType.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include "com/sun/star/ui/dialogs/TemplateDescription.hpp" +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/frame/XFrames.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/embed/ElementModes.hpp> + +#include "dlgname.hxx" + +#define PRTSTR(x) rtl::OUStringToOString(x, RTL_TEXTENCODING_ASCII_US).pData->buffer + +#define ENTRY_HEIGHT 16 + +static const char ITEM_DESCRIPTOR_COMMANDURL[] = "CommandURL"; +static const char ITEM_DESCRIPTOR_HELPURL[] = "HelpURL"; +static const char ITEM_DESCRIPTOR_CONTAINER[] = "ItemDescriptorContainer"; +static const char ITEM_DESCRIPTOR_LABEL[] = "Label"; +static const char ITEM_DESCRIPTOR_TYPE[] = "Type"; +static const char ITEM_DESCRIPTOR_STYLE[] = "Style"; +static const char ITEM_DESCRIPTOR_ISVISIBLE[] = "IsVisible"; +static const char ITEM_DESCRIPTOR_RESOURCEURL[] = "ResourceURL"; +static const char ITEM_DESCRIPTOR_UINAME[] = "UIName"; + +static const char ITEM_MENUBAR_URL[] = "private:resource/menubar/menubar"; +static const char ITEM_TOOLBAR_URL[] = "private:resource/toolbar/"; + +static const char CUSTOM_TOOLBAR_STR[] = "custom_toolbar_"; +static const char CUSTOM_MENU_STR[] = "vnd.openoffice.org:CustomMenu"; + +static const char __FAR_DATA pSeparatorStr[] = + "----------------------------------"; +static const char __FAR_DATA pMenuSeparatorStr[] = " | "; + +#ifdef _MSC_VER +#pragma warning (disable:4355) +#endif + +using rtl::OUString; +namespace css = com::sun::star; +namespace uno = com::sun::star::uno; +namespace frame = com::sun::star::frame; +namespace lang = com::sun::star::lang; +namespace container = com::sun::star::container; +namespace beans = com::sun::star::beans; +namespace graphic = com::sun::star::graphic; + +void printPropertySet( + const OUString& prefix, + const uno::Reference< beans::XPropertySet >& xPropSet ) +{ + uno::Reference< beans::XPropertySetInfo > xPropSetInfo = + xPropSet->getPropertySetInfo(); + + uno::Sequence< beans::Property > aPropDetails = + xPropSetInfo->getProperties(); + + OSL_TRACE("printPropertySet: %d properties", aPropDetails.getLength()); + + for ( sal_Int32 i = 0; i < aPropDetails.getLength(); i++ ) + { + OUString tmp; + sal_Int32 ival; + + uno::Any a = xPropSet->getPropertyValue( aPropDetails[i].Name ); + + if ( ( a >>= tmp ) /* && tmp.getLength() != 0 */ ) + { + OSL_TRACE("%s: Got property: %s = %s", + PRTSTR(prefix), PRTSTR(aPropDetails[i].Name), PRTSTR(tmp)); + } + else if ( ( a >>= ival ) ) + { + OSL_TRACE("%s: Got property: %s = %d", + PRTSTR(prefix), PRTSTR(aPropDetails[i].Name), PRTSTR(tmp)); + } + else + { + OSL_TRACE("%s: Got property: %s of type %s", + PRTSTR(prefix), PRTSTR(aPropDetails[i].Name), PRTSTR(a.getValueTypeName())); + } + } +} + +void printProperties( + const OUString& prefix, + const uno::Sequence< beans::PropertyValue >& aProp ) +{ + for ( sal_Int32 i = 0; i < aProp.getLength(); i++ ) + { + OUString tmp; + + aProp[i].Value >>= tmp; + + OSL_TRACE("%s: Got property: %s = %s", + PRTSTR(prefix), PRTSTR(aProp[i].Name), PRTSTR(tmp)); + } +} + +void printEntries(SvxEntries* entries) +{ + SvxEntries::const_iterator iter = entries->begin(); + + for ( ; iter != entries->end(); iter++ ) + { + SvxConfigEntry* entry = *iter; + + OSL_TRACE("printEntries: %s", PRTSTR(entry->GetName())); + } +} + +OUString +stripHotKey( const OUString& str ) +{ + sal_Int32 index = str.indexOf( '~' ); + if ( index == -1 ) + { + return str; + } + else + { + return str.replaceAt( index, 1, OUString() ); + } +} + +OUString replaceSaveInName( + const OUString& rMessage, + const OUString& rSaveInName ) +{ + OUString name; + OUString placeholder = OUString::createFromAscii( "%SAVE IN SELECTION%" ); + + sal_Int32 pos = rMessage.indexOf( placeholder ); + + if ( pos != -1 ) + { + name = rMessage.replaceAt( + pos, placeholder.getLength(), rSaveInName ); + } + else + { + // don't change the message + } + + return name; +} + +OUString +replaceSixteen( const OUString& str, sal_Int32 nReplacement ) +{ + OUString result( str ); + OUString sixteen = OUString::valueOf( (sal_Int32)16 ); + OUString expected = OUString::valueOf( nReplacement ); + + sal_Int32 len = sixteen.getLength(); + sal_Int32 index = result.indexOf( sixteen ); + + while ( index != -1 ) + { + result = result.replaceAt( index, len, expected ); + index = result.indexOf( sixteen, index ); + } + + return result; +} + +OUString +generateCustomName( + const OUString& prefix, + SvxEntries* entries, + sal_Int32 suffix = 1 ) +{ + // find and replace the %n placeholder in the prefix string + OUString name; + OUString placeholder = OUString::createFromAscii( "%n" ); + + sal_Int32 pos = prefix.indexOf( + OUString::createFromAscii( "%n" ) ); + + if ( pos != -1 ) + { + name = prefix.replaceAt( + pos, placeholder.getLength(), OUString::valueOf( suffix ) ); + } + else + { + // no placeholder found so just append the suffix + name = prefix + OUString::valueOf( suffix ); + } + + // now check is there is an already existing entry with this name + SvxEntries::const_iterator iter = entries->begin(); + + SvxConfigEntry* pEntry; + while ( iter != entries->end() ) + { + pEntry = *iter; + + if ( name.equals( pEntry->GetName() ) ) + { + break; + } + iter++; + } + + if ( iter != entries->end() ) + { + // name already exists so try the next number up + return generateCustomName( prefix, entries, ++suffix ); + } + + return name; +} + +sal_uInt32 generateRandomValue() +{ + srand( unsigned( time( NULL ) )); + return sal_uInt32( rand() ); +} + +OUString +generateCustomURL( + SvxEntries* entries ) +{ + OUString url = OUString::createFromAscii( ITEM_TOOLBAR_URL ); + url += OUString::createFromAscii( CUSTOM_TOOLBAR_STR ); + + // use a random number to minimize possible clash with existing custom toolbars + url += OUString::valueOf( sal_Int64( generateRandomValue() ), 16 ); + + // now check is there is an already existing entry with this url + SvxEntries::const_iterator iter = entries->begin(); + + SvxConfigEntry* pEntry; + while ( iter != entries->end() ) + { + pEntry = *iter; + + if ( url.equals( pEntry->GetCommand() ) ) + { + break; + } + iter++; + } + + if ( iter != entries->end() ) + { + // url already exists so try the next number up + return generateCustomURL( entries ); + } + + return url; +} + +OUString +generateCustomMenuURL( + SvxEntries* entries, + sal_Int32 suffix = 1 ) +{ + OUString url = OUString::createFromAscii( CUSTOM_MENU_STR ); + url += OUString::valueOf( suffix ); + + // now check is there is an already existing entry with this url + SvxEntries::const_iterator iter = entries->begin(); + + SvxConfigEntry* pEntry; + while ( iter != entries->end() ) + { + pEntry = *iter; + + if ( url.equals( pEntry->GetCommand() ) ) + { + break; + } + iter++; + } + + if ( iter != entries->end() ) + { + // url already exists so try the next number up + return generateCustomMenuURL( entries, ++suffix ); + } + + return url; +} + +static sal_Int16 theImageType = + css::ui::ImageType::COLOR_NORMAL | + css::ui::ImageType::SIZE_DEFAULT; + +void InitImageType() +{ + theImageType = + css::ui::ImageType::COLOR_NORMAL | + css::ui::ImageType::SIZE_DEFAULT; + + if ( SvtMiscOptions().AreCurrentSymbolsLarge() ) + { + theImageType |= css::ui::ImageType::SIZE_LARGE; + } + + Window* topwin = Application::GetActiveTopWindow(); + if ( topwin != NULL && + topwin->GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + theImageType |= css::ui::ImageType::COLOR_HIGHCONTRAST; + } +} + +sal_Int16 GetImageType() +{ + return theImageType; +} + +void RemoveEntry( SvxEntries* pEntries, SvxConfigEntry* pChildEntry ) +{ + SvxEntries::iterator iter = pEntries->begin(); + + while ( iter != pEntries->end() ) + { + if ( pChildEntry == *iter ) + { + pEntries->erase( iter ); + break; + } + iter++; + } +} + +bool +SvxConfigPage::CanConfig( const OUString& aModuleId ) +{ + OSL_TRACE("SupportsDocumentConfig: %s", PRTSTR(aModuleId)); + + if ( aModuleId.equalsAscii( "com.sun.star.script.BasicIDE" ) + || aModuleId.equalsAscii( "com.sun.star.frame.Bibliography" ) + ) + { + return FALSE; + } + return TRUE; +} + +OUString GetModuleName( const OUString& aModuleId ) +{ + if ( aModuleId.equalsAscii( "com.sun.star.text.TextDocument" ) || + aModuleId.equalsAscii( "com.sun.star.text.GlobalDocument" ) ) + return OUString::createFromAscii("Writer"); + else if ( aModuleId.equalsAscii( "com.sun.star.text.WebDocument" ) ) + return OUString::createFromAscii("Writer/Web"); + else if ( aModuleId.equalsAscii( "com.sun.star.drawing.DrawingDocument" ) ) + return OUString::createFromAscii("Draw"); + else if ( aModuleId.equalsAscii( "com.sun.star.presentation.PresentationDocument" ) ) + return OUString::createFromAscii("Impress"); + else if ( aModuleId.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" ) ) + return OUString::createFromAscii("Calc"); + else if ( aModuleId.equalsAscii( "com.sun.star.script.BasicIDE" ) ) + return OUString::createFromAscii("Basic"); + else if ( aModuleId.equalsAscii( "com.sun.star.formula.FormulaProperties" ) ) + return OUString::createFromAscii("Math"); + else if ( aModuleId.equalsAscii( "com.sun.star.sdb.RelationDesign" ) ) + return OUString::createFromAscii("Relation Design"); + else if ( aModuleId.equalsAscii( "com.sun.star.sdb.QueryDesign" ) ) + return OUString::createFromAscii("Query Design"); + else if ( aModuleId.equalsAscii( "com.sun.star.sdb.TableDesign" ) ) + return OUString::createFromAscii("Table Design"); + else if ( aModuleId.equalsAscii( "com.sun.star.sdb.DataSourceBrowser" ) ) + return OUString::createFromAscii("Data Source Browser" ); + else if ( aModuleId.equalsAscii( "com.sun.star.sdb.DatabaseDocument" ) ) + return OUString::createFromAscii("Database" ); + + return ::rtl::OUString(); +} + +OUString GetUIModuleName( const OUString& aModuleId, const uno::Reference< css::frame::XModuleManager >& rModuleManager ) +{ + OUString aModuleUIName; + + if ( rModuleManager.is() ) + { + uno::Reference< css::container::XNameAccess > xNameAccess( rModuleManager, uno::UNO_QUERY ); + if ( xNameAccess.is() ) + { + try + { + uno::Any a = xNameAccess->getByName( aModuleId ); + uno::Sequence< beans::PropertyValue > aSeq; + + if ( a >>= aSeq ) + { + OUString aUIName; + for ( sal_Int32 i = 0; i < aSeq.getLength(); i++ ) + { + if ( aSeq[i].Name.equalsAscii( "ooSetupFactoryUIName" )) + { + aSeq[i].Value >>= aModuleUIName; + break; + } + } + } + } + catch ( uno::RuntimeException& e ) + { + throw e; + } + catch ( uno::Exception& ) + { + } + } + } + + if ( aModuleUIName.getLength() == 0 ) + aModuleUIName = GetModuleName( aModuleId ); + + return aModuleUIName; +} + +bool GetMenuItemData( + const uno::Reference< container::XIndexAccess >& rItemContainer, + sal_Int32 nIndex, + OUString& rCommandURL, + OUString& rHelpURL, + OUString& rLabel, + sal_uInt16& rType, + uno::Reference< container::XIndexAccess >& rSubMenu ) +{ + try + { + uno::Sequence< beans::PropertyValue > aProp; + if ( rItemContainer->getByIndex( nIndex ) >>= aProp ) + { + for ( sal_Int32 i = 0; i < aProp.getLength(); i++ ) + { + if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + aProp[i].Value >>= rCommandURL; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL )) + { + aProp[i].Value >>= rHelpURL; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_CONTAINER )) + { + aProp[i].Value >>= rSubMenu; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL )) + { + aProp[i].Value >>= rLabel; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_TYPE )) + { + aProp[i].Value >>= rType; + } + } + + return TRUE; + } + } + catch ( ::com::sun::star::lang::IndexOutOfBoundsException& ) + { + } + + return FALSE; +} + +bool GetToolbarItemData( + const uno::Reference< container::XIndexAccess >& rItemContainer, + sal_Int32 nIndex, + OUString& rCommandURL, + OUString& rHelpURL, + OUString& rLabel, + sal_uInt16& rType, + sal_Bool& rIsVisible, + sal_Int32& rStyle, + uno::Reference< container::XIndexAccess >& rSubMenu ) +{ + try + { + uno::Sequence< beans::PropertyValue > aProp; + if ( rItemContainer->getByIndex( nIndex ) >>= aProp ) + { + for ( sal_Int32 i = 0; i < aProp.getLength(); i++ ) + { + if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + aProp[i].Value >>= rCommandURL; + } + if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE )) + { + aProp[i].Value >>= rStyle; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL )) + { + aProp[i].Value >>= rHelpURL; + } + else if (aProp[i].Name.equalsAscii(ITEM_DESCRIPTOR_CONTAINER)) + { + aProp[i].Value >>= rSubMenu; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL )) + { + aProp[i].Value >>= rLabel; + } + else if ( aProp[i].Name.equalsAscii( ITEM_DESCRIPTOR_TYPE )) + { + aProp[i].Value >>= rType; + } + else if (aProp[i].Name.equalsAscii(ITEM_DESCRIPTOR_ISVISIBLE)) + { + aProp[i].Value >>= rIsVisible; + } + } + + return sal_True; + } + } + catch ( ::com::sun::star::lang::IndexOutOfBoundsException& ) + { + } + + return sal_False; +} + +uno::Sequence< beans::PropertyValue > +ConvertSvxConfigEntry( + const uno::Reference< container::XNameAccess >& xCommandToLabelMap, + const SvxConfigEntry* pEntry ) +{ + static const OUString aDescriptorCommandURL ( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_COMMANDURL ) ); + + static const OUString aDescriptorType( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE ) ); + + static const OUString aDescriptorLabel( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_LABEL ) ); + + static const OUString aDescriptorHelpURL( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_HELPURL ) ); + + static const OUString aDescriptorContainer( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_CONTAINER ) ); + + uno::Sequence< beans::PropertyValue > aPropSeq( 4 ); + + aPropSeq[0].Name = aDescriptorCommandURL; + aPropSeq[0].Value <<= rtl::OUString( pEntry->GetCommand() ); + + aPropSeq[1].Name = aDescriptorType; + aPropSeq[1].Value <<= css::ui::ItemType::DEFAULT; + + // If the name has not been changed and the name is the same as + // in the default command to label map then the label can be stored + // as an empty string. + // It will be initialised again later using the command to label map. + aPropSeq[2].Name = aDescriptorLabel; + if ( pEntry->HasChangedName() == FALSE && pEntry->GetCommand().getLength() ) + { + BOOL isDefaultName = FALSE; + try + { + uno::Any a( xCommandToLabelMap->getByName( pEntry->GetCommand() ) ); + uno::Sequence< beans::PropertyValue > tmpPropSeq; + if ( a >>= tmpPropSeq ) + { + for ( sal_Int32 i = 0; i < tmpPropSeq.getLength(); i++ ) + { + if ( tmpPropSeq[i].Name.equals( aDescriptorLabel ) ) + { + OUString tmpLabel; + tmpPropSeq[i].Value >>= tmpLabel; + + if ( tmpLabel.equals( pEntry->GetName() ) ) + { + isDefaultName = TRUE; + } + + break; + } + } + } + } + catch ( container::NoSuchElementException& ) + { + // isDefaultName is left as FALSE + } + + if ( isDefaultName ) + { + aPropSeq[2].Value <<= rtl::OUString(); + } + else + { + aPropSeq[2].Value <<= rtl::OUString( pEntry->GetName() ); + } + } + else + { + aPropSeq[2].Value <<= rtl::OUString( pEntry->GetName() ); + } + + aPropSeq[3].Name = aDescriptorHelpURL; + aPropSeq[3].Value <<= rtl::OUString( pEntry->GetHelpURL() ); + + return aPropSeq; +} + +uno::Sequence< beans::PropertyValue > +ConvertToolbarEntry( + const uno::Reference< container::XNameAccess >& xCommandToLabelMap, + const SvxConfigEntry* pEntry ) +{ + static const OUString aDescriptorCommandURL ( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_COMMANDURL ) ); + + static const OUString aDescriptorType( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE ) ); + + static const OUString aDescriptorLabel( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_LABEL ) ); + + static const OUString aDescriptorHelpURL( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_HELPURL ) ); + + static const OUString aDescriptorContainer( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_CONTAINER ) ); + + static const OUString aIsVisible( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_ISVISIBLE ) ); + + uno::Sequence< beans::PropertyValue > aPropSeq( 5 ); + + aPropSeq[0].Name = aDescriptorCommandURL; + aPropSeq[0].Value <<= rtl::OUString( pEntry->GetCommand() ); + + aPropSeq[1].Name = aDescriptorType; + aPropSeq[1].Value <<= css::ui::ItemType::DEFAULT; + + // If the name has not been changed and the name is the same as + // in the default command to label map then the label can be stored + // as an empty string. + // It will be initialised again later using the command to label map. + aPropSeq[2].Name = aDescriptorLabel; + if ( pEntry->HasChangedName() == FALSE && pEntry->GetCommand().getLength() ) + { + BOOL isDefaultName = FALSE; + try + { + uno::Any a( xCommandToLabelMap->getByName( pEntry->GetCommand() ) ); + uno::Sequence< beans::PropertyValue > tmpPropSeq; + if ( a >>= tmpPropSeq ) + { + for ( sal_Int32 i = 0; i < tmpPropSeq.getLength(); i++ ) + { + if ( tmpPropSeq[i].Name.equals( aDescriptorLabel ) ) + { + OUString tmpLabel; + tmpPropSeq[i].Value >>= tmpLabel; + + if ( tmpLabel.equals( pEntry->GetName() ) ) + { + isDefaultName = TRUE; + } + + break; + } + } + } + } + catch ( container::NoSuchElementException& ) + { + // isDefaultName is left as FALSE + } + + if ( isDefaultName ) + { + aPropSeq[2].Value <<= rtl::OUString(); + } + else + { + aPropSeq[2].Value <<= rtl::OUString( pEntry->GetName() ); + } + } + else + { + aPropSeq[2].Value <<= rtl::OUString( pEntry->GetName() ); + } + + aPropSeq[3].Name = aDescriptorHelpURL; + aPropSeq[3].Value <<= rtl::OUString( pEntry->GetHelpURL() ); + + aPropSeq[4].Name = aIsVisible; + aPropSeq[4].Value <<= pEntry->IsVisible(); + + return aPropSeq; +} + +SfxTabPage *CreateSvxMenuConfigPage( Window *pParent, const SfxItemSet& rSet ) +{ + return new SvxMenuConfigPage( pParent, rSet ); +} + +SfxTabPage *CreateKeyboardConfigPage( Window *pParent, const SfxItemSet& rSet ) +{ + return new SfxAcceleratorConfigPage( pParent, rSet ); +} + +SfxTabPage *CreateSvxToolbarConfigPage( Window *pParent, const SfxItemSet& rSet ) +{ + return new SvxToolbarConfigPage( pParent, rSet ); +} + +SfxTabPage *CreateSvxEventConfigPage( Window *pParent, const SfxItemSet& rSet ) +{ + return new SvxEventConfigPage( pParent, rSet, SvxEventConfigPage::EarlyInit() ); +} + +sal_Bool impl_showKeyConfigTabPage( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + static ::rtl::OUString SERVICENAME_MODULEMANAGER = ::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager"); + static ::rtl::OUString SERVICENAME_DESKTOP = ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop" ); + static ::rtl::OUString MODULEID_STARTMODULE = ::rtl::OUString::createFromAscii("com.sun.star.frame.StartModule" ); + + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::frame::XModuleManager > xMM (xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY_THROW); + + if (xMM.is() && xFrame.is()) + { + ::rtl::OUString sModuleId = xMM->identify(xFrame); + if ( + ( sModuleId.getLength() ) && + (!sModuleId.equals(MODULEID_STARTMODULE)) + ) + return sal_True; + } + } + catch(const css::uno::Exception&) + {} + + return sal_False; +} + +/****************************************************************************** + * + * SvxConfigDialog is the configuration dialog which is brought up from the + * Tools menu. It includes tabs for customizing menus, toolbars, events and + * key bindings. + * + *****************************************************************************/ +SvxConfigDialog::SvxConfigDialog( + Window * pParent, const SfxItemSet* pSet_ ) + : + SfxTabDialog( pParent, + CUI_RES( RID_SVXDLG_CUSTOMIZE ), pSet_ ) +{ + FreeResource(); + + InitImageType(); + + AddTabPage( RID_SVXPAGE_MENUS, CreateSvxMenuConfigPage, NULL ); + AddTabPage( RID_SVXPAGE_KEYBOARD, CreateKeyboardConfigPage, NULL ); + AddTabPage( RID_SVXPAGE_TOOLBARS, CreateSvxToolbarConfigPage, NULL ); + AddTabPage( RID_SVXPAGE_EVENTS, CreateSvxEventConfigPage, NULL ); + + const SfxPoolItem* pItem = + pSet_->GetItem( pSet_->GetPool()->GetWhich( SID_CONFIG ) ); + + if ( pItem ) + { + OUString text = ((const SfxStringItem*)pItem)->GetValue(); + + if (text.indexOf(OUString::createFromAscii(ITEM_TOOLBAR_URL)) == 0) + { + SetCurPageId( RID_SVXPAGE_TOOLBARS ); + } + } +} + +void SvxConfigDialog::SetFrame(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame) +{ + m_xFrame = xFrame; + + if (!impl_showKeyConfigTabPage( xFrame )) + RemoveTabPage( RID_SVXPAGE_KEYBOARD ); +} + +SvxConfigDialog::~SvxConfigDialog() +{ +} + +short SvxConfigDialog::Ok() +{ + return SfxTabDialog::Ok(); +} + +void SvxConfigDialog::PageCreated( USHORT nId, SfxTabPage& rPage ) +{ + (void)rPage; + + switch ( nId ) + { + case RID_SVXPAGE_MENUS: + case RID_SVXPAGE_TOOLBARS: + case RID_SVXPAGE_KEYBOARD: + { + rPage.SetFrame(m_xFrame); + } + break; + case RID_SVXPAGE_EVENTS: + { + dynamic_cast< SvxEventConfigPage& >( rPage ).LateInit( m_xFrame ); + }; + break; + default: + break; + } +} + +void SvxConfigDialog::ActivateTabPage( USHORT nSlotId ) +{ + (void)nSlotId; +} + +/****************************************************************************** + * + * The SaveInData class is used to hold data for entries in the Save In + * ListBox controls in the menu and toolbar tabs + * + ******************************************************************************/ + +// Initialize static variable which holds default XImageManager +uno::Reference< css::ui::XImageManager>* SaveInData::xDefaultImgMgr = NULL; + +SaveInData::SaveInData( + const uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool isDocConfig ) + : + bModified( FALSE ), + bDocConfig( isDocConfig ), + bReadOnly( FALSE ), + m_xCfgMgr( xCfgMgr ), + m_xParentCfgMgr( xParentCfgMgr ) +{ + uno::Reference< beans::XPropertySet > xProps( + ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY ); + + xProps->getPropertyValue( + OUString::createFromAscii( "DefaultContext" )) + >>= m_xComponentContext; + + m_aSeparatorSeq.realloc( 1 ); + m_aSeparatorSeq[0].Name = OUString( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE ) ); + m_aSeparatorSeq[0].Value <<= css::ui::ItemType::SEPARATOR_LINE; + + if ( bDocConfig ) + { + uno::Reference< css::ui::XUIConfigurationPersistence > + xDocPersistence( GetConfigManager(), uno::UNO_QUERY ); + + bReadOnly = xDocPersistence->isReadOnly(); + } + + m_xServiceManager = uno::Reference< lang::XMultiServiceFactory >( + ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + + uno::Reference< container::XNameAccess > xNameAccess( + m_xServiceManager->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.UICommandDescription" ) ) ), + uno::UNO_QUERY ); + + if ( xNameAccess.is() ) + xNameAccess->getByName( aModuleId ) >>= m_xCommandToLabelMap; + + if ( !m_xImgMgr.is() ) + { + m_xImgMgr = uno::Reference< css::ui::XImageManager >( + GetConfigManager()->getImageManager(), uno::UNO_QUERY ); + } + + if ( !IsDocConfig() ) + { + // If this is not a document configuration then it is the settings + // for the module (writer, calc, impress etc.) Use this as the default + // XImageManager instance + xDefaultImgMgr = &m_xImgMgr; + } + else + { + // If this is a document configuration then use the module image manager + // as default. + if ( m_xParentCfgMgr.is() ) + { + m_xParentImgMgr = uno::Reference< css::ui::XImageManager >( + m_xParentCfgMgr->getImageManager(), uno::UNO_QUERY ); + xDefaultImgMgr = &m_xParentImgMgr; + } + } +} + +uno::Reference< graphic::XGraphic > GetGraphic( + const uno::Reference< css::ui::XImageManager >& xImageManager, + const OUString& rCommandURL ) +{ + uno::Reference< graphic::XGraphic > result; + + if ( xImageManager.is() ) + { + // TODO handle large and high contrast graphics + uno::Sequence< uno::Reference< graphic::XGraphic > > aGraphicSeq; + + uno::Sequence< OUString > aImageCmdSeq( 1 ); + aImageCmdSeq[0] = rCommandURL; + + try + { + aGraphicSeq = + xImageManager->getImages( GetImageType(), aImageCmdSeq ); + + if ( aGraphicSeq.getLength() > 0 ) + { + result = aGraphicSeq[0]; + } + } + catch ( uno::Exception& ) + { + // will return empty XGraphic + } + } + + return result; +} + +Image SaveInData::GetImage( const OUString& rCommandURL ) +{ + Image aImage; + + uno::Reference< graphic::XGraphic > xGraphic = + GetGraphic( m_xImgMgr, rCommandURL ); + + if ( xGraphic.is() ) + { + aImage = Image( xGraphic ); + } + else if ( xDefaultImgMgr != NULL && (*xDefaultImgMgr).is() ) + { + xGraphic = GetGraphic( (*xDefaultImgMgr), rCommandURL ); + + if ( xGraphic.is() ) + { + aImage = Image( xGraphic ); + } + } + + return aImage; +} + +bool SaveInData::PersistChanges( + const uno::Reference< uno::XInterface >& xManager ) +{ + bool result = TRUE; + + try + { + if ( xManager.is() && !IsReadOnly() ) + { + uno::Reference< css::ui::XUIConfigurationPersistence > + xConfigPersistence( xManager, uno::UNO_QUERY ); + + if ( xConfigPersistence->isModified() ) + { + xConfigPersistence->store(); + } + } + } + catch ( com::sun::star::io::IOException& ) + { + result = FALSE; + } + + return result; +} + +/****************************************************************************** + * + * The MenuSaveInData class extends SaveInData and provides menu specific + * load and store functionality. + * + ******************************************************************************/ + +// Initialize static variable which holds default Menu data +MenuSaveInData* MenuSaveInData::pDefaultData = NULL; + +MenuSaveInData::MenuSaveInData( + const uno::Reference< css::ui::XUIConfigurationManager >& cfgmgr, + const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool isDocConfig ) + : + SaveInData( cfgmgr, xParentCfgMgr, aModuleId, isDocConfig ), + m_aMenuResourceURL( + RTL_CONSTASCII_USTRINGPARAM( ITEM_MENUBAR_URL ) ), + m_aDescriptorContainer( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_CONTAINER ) ), + pRootEntry( 0 ) +{ + try + { + OUString url( RTL_CONSTASCII_USTRINGPARAM( ITEM_MENUBAR_URL ) ); + m_xMenuSettings = GetConfigManager()->getSettings( url, sal_False ); + } + catch ( container::NoSuchElementException& ) + { + // will use menu settings for the module + } + + // If this is not a document configuration then it is the settings + // for the module (writer, calc, impress etc.). These settings should + // be set as the default to be used for SaveIn locations that do not + // have custom settings + if ( !IsDocConfig() ) + { + SetDefaultData( this ); + } +} + +MenuSaveInData::~MenuSaveInData() +{ + if ( pRootEntry != NULL ) + { + delete pRootEntry; + } +} + +SvxEntries* +MenuSaveInData::GetEntries() +{ + if ( pRootEntry == NULL ) + { + pRootEntry = new SvxConfigEntry( + String::CreateFromAscii("MainMenus"), String(), TRUE ); + + if ( m_xMenuSettings.is() ) + { + LoadSubMenus( m_xMenuSettings, String(), pRootEntry ); + } + else if ( GetDefaultData() != NULL ) + { + // If the doc has no config settings use module config settings + LoadSubMenus( GetDefaultData()->m_xMenuSettings, String(), pRootEntry ); + } + } + + return pRootEntry->GetEntries(); +} + +void +MenuSaveInData::SetEntries( SvxEntries* pNewEntries ) +{ + // delete old menu hierarchy first + if ( pRootEntry != NULL ) + { + delete pRootEntry->GetEntries(); + } + + // now set new menu hierarchy + pRootEntry->SetEntries( pNewEntries ); +} + +bool MenuSaveInData::LoadSubMenus( + const uno::Reference< container::XIndexAccess >& xMenuSettings, + const OUString& rBaseTitle, + SvxConfigEntry* pParentData ) +{ + SvxEntries* pEntries = pParentData->GetEntries(); + + // Don't access non existing menu configuration! + if ( !xMenuSettings.is() ) + return true; + + for ( sal_Int32 nIndex = 0; nIndex < xMenuSettings->getCount(); nIndex++ ) + { + uno::Reference< container::XIndexAccess > xSubMenu; + OUString aCommandURL; + OUString aHelpURL; + OUString aLabel; + bool bIsUserDefined = TRUE; + + sal_uInt16 nType( css::ui::ItemType::DEFAULT ); + + bool bItem = GetMenuItemData( xMenuSettings, nIndex, + aCommandURL, aHelpURL, aLabel, nType, xSubMenu ); + + if ( bItem ) + { + if ( nType == css::ui::ItemType::DEFAULT ) + { + uno::Any a; + try + { + a = m_xCommandToLabelMap->getByName( aCommandURL ); + bIsUserDefined = FALSE; + } + catch ( container::NoSuchElementException& ) + { + bIsUserDefined = TRUE; + } + + // If custom label not set retrieve it from the command + // to info service + if ( aLabel.equals( OUString() ) ) + { + uno::Sequence< beans::PropertyValue > aPropSeq; + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL ) ) + { + aPropSeq[i].Value >>= aLabel; + break; + } + } + } + } + + if ( xSubMenu.is() ) + { + // popup menu + SvxConfigEntry* pEntry = new SvxConfigEntry( + aLabel, aCommandURL, TRUE ); + + pEntry->SetUserDefined( bIsUserDefined ); + pEntry->SetHelpURL( aHelpURL ); + + pEntries->push_back( pEntry ); + + OUString subMenuTitle( rBaseTitle ); + + if ( subMenuTitle.getLength() != 0 ) + { + subMenuTitle += + OUString::createFromAscii(pMenuSeparatorStr); + } + else + { + pEntry->SetMain( TRUE ); + } + + subMenuTitle += stripHotKey( aLabel ); + + LoadSubMenus( xSubMenu, subMenuTitle, pEntry ); + } + else + { + SvxConfigEntry* pEntry = new SvxConfigEntry( + aLabel, aCommandURL, FALSE ); + pEntry->SetUserDefined( bIsUserDefined ); + pEntry->SetHelpURL( aHelpURL ); + pEntries->push_back( pEntry ); + } + } + else + { + SvxConfigEntry* pEntry = new SvxConfigEntry; + pEntry->SetUserDefined( bIsUserDefined ); + pEntries->push_back( pEntry ); + } + } + } + return true; +} + +bool MenuSaveInData::Apply() +{ + bool result = FALSE; + + if ( IsModified() ) + { + // Apply new menu bar structure to our settings container + m_xMenuSettings = uno::Reference< container::XIndexAccess >( + GetConfigManager()->createSettings(), uno::UNO_QUERY ); + + uno::Reference< container::XIndexContainer > xIndexContainer ( + m_xMenuSettings, uno::UNO_QUERY ); + + uno::Reference< lang::XSingleComponentFactory > xFactory ( + m_xMenuSettings, uno::UNO_QUERY ); + + Apply( pRootEntry, xIndexContainer, xFactory, NULL ); + + try + { + if ( GetConfigManager()->hasSettings( m_aMenuResourceURL ) ) + { + GetConfigManager()->replaceSettings( + m_aMenuResourceURL, m_xMenuSettings ); + } + else + { + GetConfigManager()->insertSettings( + m_aMenuResourceURL, m_xMenuSettings ); + } + } + catch ( container::NoSuchElementException& ) + { + OSL_TRACE("caught container::NoSuchElementException saving settings"); + } + catch ( com::sun::star::io::IOException& ) + { + OSL_TRACE("caught IOException saving settings"); + } + catch ( com::sun::star::uno::Exception& ) + { + OSL_TRACE("caught some other exception saving settings"); + } + + SetModified( FALSE ); + + result = PersistChanges( GetConfigManager() ); + } + + return result; +} + +void MenuSaveInData::Apply( + SvxConfigEntry* pRootEntry_, + uno::Reference< container::XIndexContainer >& rMenuBar, + uno::Reference< lang::XSingleComponentFactory >& rFactory, + SvLBoxEntry *pParentEntry ) +{ + (void)pRootEntry_; + (void)pParentEntry; + + SvxEntries::const_iterator iter = GetEntries()->begin(); + SvxEntries::const_iterator end = GetEntries()->end(); + + for ( ; iter != end; iter++ ) + { + SvxConfigEntry* pEntryData = *iter; + + uno::Sequence< beans::PropertyValue > aPropValueSeq = + ConvertSvxConfigEntry( m_xCommandToLabelMap, pEntryData ); + + uno::Reference< container::XIndexContainer > xSubMenuBar( + rFactory->createInstanceWithContext( m_xComponentContext ), + uno::UNO_QUERY ); + + sal_Int32 nIndex = aPropValueSeq.getLength(); + aPropValueSeq.realloc( nIndex + 1 ); + aPropValueSeq[nIndex].Name = m_aDescriptorContainer; + aPropValueSeq[nIndex].Value <<= xSubMenuBar; + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::makeAny( aPropValueSeq )); + ApplyMenu( xSubMenuBar, rFactory, pEntryData ); + } +} + +void MenuSaveInData::ApplyMenu( + uno::Reference< container::XIndexContainer >& rMenuBar, + uno::Reference< lang::XSingleComponentFactory >& rFactory, + SvxConfigEntry* pMenuData ) +{ + SvxEntries::const_iterator iter = pMenuData->GetEntries()->begin(); + SvxEntries::const_iterator end = pMenuData->GetEntries()->end(); + + for ( ; iter != end; iter++ ) + { + SvxConfigEntry* pEntry = *iter; + + if ( pEntry->IsPopup() ) + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + ConvertSvxConfigEntry( m_xCommandToLabelMap, pEntry ); + + uno::Reference< container::XIndexContainer > xSubMenuBar( + rFactory->createInstanceWithContext( m_xComponentContext ), + uno::UNO_QUERY ); + + sal_Int32 nIndex = aPropValueSeq.getLength(); + aPropValueSeq.realloc( nIndex + 1 ); + aPropValueSeq[nIndex].Name = m_aDescriptorContainer; + aPropValueSeq[nIndex].Value <<= xSubMenuBar; + + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::makeAny( aPropValueSeq )); + + ApplyMenu( xSubMenuBar, rFactory, pEntry ); + } + else if ( pEntry->IsSeparator() ) + { + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::makeAny( m_aSeparatorSeq )); + } + else + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + ConvertSvxConfigEntry( m_xCommandToLabelMap, pEntry ); + rMenuBar->insertByIndex( + rMenuBar->getCount(), uno::makeAny( aPropValueSeq )); + } + } +} + +void +MenuSaveInData::Reset() +{ + GetConfigManager()->reset(); + + delete pRootEntry; + pRootEntry = NULL; + + try + { + m_xMenuSettings = GetConfigManager()->getSettings( + m_aMenuResourceURL, sal_False ); + } + catch ( container::NoSuchElementException& ) + { + // will use default settings + } +} + +class PopupPainter : public SvLBoxString +{ +public: + PopupPainter( SvLBoxEntry* pEntry, const String& rStr ) + : SvLBoxString( pEntry, 0, rStr ) + { } + + ~PopupPainter() { } + + void Paint( const Point& rPos, SvLBox& rOutDev, + USHORT nViewDataEntryFlags, SvLBoxEntry* pEntry ) + { + SvLBoxString::Paint( rPos, rOutDev, nViewDataEntryFlags, pEntry ); + + Color aOldFillColor = rOutDev.GetFillColor(); + + SvTreeListBox* pTreeBox = static_cast< SvTreeListBox* >( &rOutDev ); + long nX = pTreeBox->GetSizePixel().Width(); + + ScrollBar* pVScroll = pTreeBox->GetVScroll(); + if ( pVScroll->IsVisible() ) + { + nX -= pVScroll->GetSizePixel().Width(); + } + + SvViewDataItem* pItem = rOutDev.GetViewDataItem( pEntry, this ); + nX -= pItem->aSize.Height(); + + long nSize = pItem->aSize.Height() / 2; + long nHalfSize = nSize / 2; + long nY = rPos.Y() + nHalfSize; + + if ( aOldFillColor == COL_WHITE ) + { + rOutDev.SetFillColor( Color( COL_BLACK ) ); + } + else + { + rOutDev.SetFillColor( Color( COL_WHITE ) ); + } + + long n = 0; + while ( n <= nHalfSize ) + { + rOutDev.DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) ); + n++; + } + + rOutDev.SetFillColor( aOldFillColor ); + } +}; + +/****************************************************************************** + * + * SvxMenuEntriesListBox is the listbox in which the menu items for a + * particular menu are shown. We have a custom listbox because we need + * to add drag'n'drop support from the Macro Selector and within the + * listbox + * + *****************************************************************************/ +SvxMenuEntriesListBox::SvxMenuEntriesListBox( + Window* pParent, const ResId& rResId) + : SvTreeListBox( pParent, rResId ) + , pPage( (SvxMenuConfigPage*) pParent ) + , m_bIsInternalDrag( FALSE ) +{ + SetWindowBits( + GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_HIDESELECTION ); + + SetSpaceBetweenEntries( 3 ); + SetEntryHeight( ENTRY_HEIGHT ); + + SetHighlightRange(); + SetSelectionMode(SINGLE_SELECTION); + + SetDragDropMode( SV_DRAGDROP_CTRL_MOVE | + SV_DRAGDROP_APP_COPY | + SV_DRAGDROP_ENABLE_TOP | + SV_DRAGDROP_APP_DROP); +} + +SvxMenuEntriesListBox::~SvxMenuEntriesListBox() +{ + // do nothing +} + +// drag and drop support +DragDropMode SvxMenuEntriesListBox::NotifyStartDrag( + TransferDataContainer& aTransferDataContainer, SvLBoxEntry* pEntry ) +{ + (void)aTransferDataContainer; + (void)pEntry; + + m_bIsInternalDrag = TRUE; + return GetDragDropMode(); +} + +void SvxMenuEntriesListBox::DragFinished( sal_Int8 nDropAction ) +{ + (void)nDropAction; + m_bIsInternalDrag = FALSE; +} + +sal_Int8 SvxMenuEntriesListBox::AcceptDrop( const AcceptDropEvent& rEvt ) +{ + if ( m_bIsInternalDrag ) + { + // internal copy isn't allowed! + if ( rEvt.mnAction == DND_ACTION_COPY ) + return DND_ACTION_NONE; + else + return SvTreeListBox::AcceptDrop( rEvt ); + } + + // Always do COPY instead of MOVE if D&D comes from outside! + AcceptDropEvent aNewAcceptDropEvent( rEvt ); + aNewAcceptDropEvent.mnAction = DND_ACTION_COPY; + return SvTreeListBox::AcceptDrop( aNewAcceptDropEvent ); +} + +BOOL SvxMenuEntriesListBox::NotifyAcceptDrop( SvLBoxEntry* ) +{ + return TRUE; +} + +BOOL SvxMenuEntriesListBox::NotifyMoving( + SvLBoxEntry* pTarget, SvLBoxEntry* pSource, + SvLBoxEntry*& rpNewParent, ULONG& rNewChildPos) +{ + // only try to do a move if we are dragging within the list box + if ( m_bIsInternalDrag ) + { + if ( pPage->MoveEntryData( pSource, pTarget ) == TRUE ) + { + SvTreeListBox::NotifyMoving( + pTarget, pSource, rpNewParent, rNewChildPos ); + return TRUE; + } + else + { + return FALSE; + } + } + else + { + return NotifyCopying( pTarget, pSource, rpNewParent, rNewChildPos ); + } +} + +BOOL SvxMenuEntriesListBox::NotifyCopying( + SvLBoxEntry* pTarget, SvLBoxEntry* pSource, + SvLBoxEntry*& rpNewParent, ULONG& rNewChildPos) +{ + (void)pSource; + (void)rpNewParent; + (void)rNewChildPos; + + if ( !m_bIsInternalDrag ) + { + // if the target is NULL then add function to the start of the list + pPage->AddFunction( pTarget, pTarget == NULL ); + + // AddFunction already adds the listbox entry so return FALSE + // to stop another listbox entry being added + return FALSE; + } + + // Copying is only allowed from external controls, not within the listbox + return FALSE; +} + +void SvxMenuEntriesListBox::KeyInput( const KeyEvent& rKeyEvent ) +{ + KeyCode keycode = rKeyEvent.GetKeyCode(); + + // support DELETE for removing the current entry + if ( keycode == KEY_DELETE ) + { + pPage->DeleteSelectedContent(); + } + // support CTRL+UP and CTRL+DOWN for moving selected entries + else if ( keycode.GetCode() == KEY_UP && keycode.IsMod1() ) + { + pPage->MoveEntry( TRUE ); + } + else if ( keycode.GetCode() == KEY_DOWN && keycode.IsMod1() ) + { + pPage->MoveEntry( FALSE ); + } + else + { + // pass on to superclass + SvTreeListBox::KeyInput( rKeyEvent ); + } +} + +// class SvxDescriptionEdit ---------------------------------------------- + +SvxDescriptionEdit::SvxDescriptionEdit( Window* pParent, const ResId& _rId ) : + + ExtMultiLineEdit( pParent, _rId ) + +{ + // calculate the available space for help text + m_aRealRect = Rectangle( Point(), GetSizePixel() ); + if ( GetVScrollBar() ) + m_aRealRect.Right() -= ( GetVScrollBar()->GetSizePixel().Width() + 4 ); + + SetLeftMargin(2); + SetBorderStyle( WINDOW_BORDER_MONO ); +} + +// ----------------------------------------------------------------------- + +void SvxDescriptionEdit::SetNewText( const String& _rText ) +{ + String sTemp( _rText ); + sal_Bool bShow = sal_False; + if ( sTemp.Len() > 0 ) + { + // detect if a scrollbar is necessary + Rectangle aRect = GetTextRect( m_aRealRect, sTemp, TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE ); + bShow = ( aRect.Bottom() > m_aRealRect.Bottom() ); + } + + if ( GetVScrollBar() ) + GetVScrollBar()->Show( bShow ); + + if ( bShow ) + sTemp += '\n'; + + SetText( sTemp ); +} + +/****************************************************************************** + * + * SvxConfigPage is the abstract base class on which the Menu and Toolbar + * configuration tabpages are based. It includes methods which are common to + * both tabpages to add, delete, move and rename items etc. + * + *****************************************************************************/ +SvxConfigPage::SvxConfigPage( + Window *pParent, const SfxItemSet& rSet ) + : + SfxTabPage( pParent, CUI_RES( RID_SVXPAGE_MENUS ), rSet ), + bInitialised( FALSE ), + pCurrentSaveInData( 0 ), + aTopLevelSeparator( this, CUI_RES( GRP_MENUS ) ), + aTopLevelLabel( this, CUI_RES( FT_MENUS ) ), + aTopLevelListBox( this, CUI_RES( LB_MENUS ) ), + aNewTopLevelButton( this, CUI_RES( BTN_NEW ) ), + aModifyTopLevelButton( this, CUI_RES( BTN_CHANGE ) ), + aContentsSeparator( this, CUI_RES( GRP_MENU_SEPARATOR ) ), + aContentsLabel( this, CUI_RES( GRP_MENU_ENTRIES ) ), + aContentsListBox( 0 ), + aAddCommandsButton( this, CUI_RES( BTN_ADD_COMMANDS ) ), + aModifyCommandButton( this, CUI_RES( BTN_CHANGE_ENTRY ) ), + aMoveUpButton( this, CUI_RES( BTN_UP ) ), + aMoveDownButton( this, CUI_RES( BTN_DOWN ) ), + aSaveInText( this, CUI_RES( TXT_SAVEIN ) ), + aSaveInListBox( this, CUI_RES( LB_SAVEIN ) ), + aDescriptionLabel( this, CUI_RES( FT_DESCRIPTION ) ), + aDescriptionField( this, CUI_RES( ED_DESCRIPTION ) ), + pSelectorDlg( 0 ) +{ + aDescriptionField.SetControlBackground( GetSettings().GetStyleSettings().GetDialogColor() ); + aDescriptionField.SetAutoScroll( TRUE ); + aDescriptionField.EnableCursor( FALSE ); +} + +SvxConfigPage::~SvxConfigPage() +{ +} + +void SvxConfigPage::Reset( const SfxItemSet& ) +{ + // If we haven't initialised our XMultiServiceFactory reference + // then Reset is being called at the opening of the dialog. + // + // Load menu configuration data for the module of the currently + // selected document, for the currently selected document, and for + // all other open documents of the same module type + if ( !bInitialised ) + { + USHORT nPos = 0; + uno::Reference < css::ui::XUIConfigurationManager > xCfgMgr; + uno::Reference < css::ui::XUIConfigurationManager > xDocCfgMgr; + + uno::Reference< lang::XMultiServiceFactory > xServiceManager( + ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + + m_xFrame = GetFrame(); + OUString aModuleId = GetFrameWithDefaultAndIdentify( m_xFrame ); + + // replace %MODULENAME in the label with the correct module name + uno::Reference< css::frame::XModuleManager > xModuleManager( + xServiceManager->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.ModuleManager" ) ) ), + uno::UNO_QUERY_THROW ); + OUString aModuleName = GetUIModuleName( aModuleId, xModuleManager ); + + OUString title = aTopLevelSeparator.GetText(); + OUString aSearchString = OUString::createFromAscii( "%MODULENAME" ); + sal_Int32 index = title.indexOf( aSearchString ); + + if ( index != -1 ) + { + title = title.replaceAt( + index, aSearchString.getLength(), aModuleName ); + aTopLevelSeparator.SetText( title ); + } + + uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > + xModuleCfgSupplier( xServiceManager->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ui.ModuleUIConfigurationManagerSupplier" ))), + uno::UNO_QUERY ); + + // Set up data for module specific menus + SaveInData* pModuleData = NULL; + + try + { + xCfgMgr = + xModuleCfgSupplier->getUIConfigurationManager( aModuleId ); + + pModuleData = CreateSaveInData( xCfgMgr, + uno::Reference< css::ui::XUIConfigurationManager >(), + aModuleId, + FALSE ); + } + catch ( container::NoSuchElementException& ) + { + } + + if ( pModuleData != NULL ) + { + OUString label; + utl::ConfigManager::GetDirectConfigProperty( + utl::ConfigManager::PRODUCTNAME ) >>= label; + label += OUString::createFromAscii( " " ); + label += aModuleName; + + nPos = aSaveInListBox.InsertEntry( label ); + aSaveInListBox.SetEntryData( nPos, pModuleData ); + } + + // try to retrieve the document based ui configuration manager + OUString aTitle; + uno::Reference< frame::XController > xController = + m_xFrame->getController(); + if ( CanConfig( aModuleId ) && xController.is() ) + { + uno::Reference< frame::XModel > xModel( xController->getModel() ); + if ( xModel.is() ) + { + uno::Reference< css::ui::XUIConfigurationManagerSupplier > + xCfgSupplier( xModel, uno::UNO_QUERY ); + + if ( xCfgSupplier.is() ) + { + xDocCfgMgr = xCfgSupplier->getUIConfigurationManager(); + } + aTitle = ::comphelper::DocumentInfo::getDocumentTitle( xModel ); + } + } + + SaveInData* pDocData = NULL; + if ( xDocCfgMgr.is() ) + { + pDocData = CreateSaveInData( xDocCfgMgr, xCfgMgr, aModuleId, TRUE ); + + if ( !pDocData->IsReadOnly() ) + { + nPos = aSaveInListBox.InsertEntry( aTitle ); + aSaveInListBox.SetEntryData( nPos, pDocData ); + } + } + + // if an item to select has been passed in (eg. the ResourceURL for a + // toolbar) then try to select the SaveInData entry that has that item + bool bURLToSelectFound = FALSE; + if ( m_aURLToSelect.getLength() != 0 ) + { + if ( pDocData != NULL && pDocData->HasURL( m_aURLToSelect ) ) + { + aSaveInListBox.SelectEntryPos( nPos, TRUE ); + pCurrentSaveInData = pDocData; + bURLToSelectFound = TRUE; + } + else if ( pModuleData->HasURL( m_aURLToSelect ) ) + { + aSaveInListBox.SelectEntryPos( 0, TRUE ); + pCurrentSaveInData = pModuleData; + bURLToSelectFound = TRUE; + } + } + + if ( bURLToSelectFound == FALSE ) + { + // if the document has menu configuration settings select it + // it the SaveIn listbox, otherwise select the module data + if ( pDocData != NULL && pDocData->HasSettings() ) + { + aSaveInListBox.SelectEntryPos( nPos, TRUE ); + pCurrentSaveInData = pDocData; + } + else + { + aSaveInListBox.SelectEntryPos( 0, TRUE ); + pCurrentSaveInData = pModuleData; + } + } + +#ifdef DBG_UTIL + DBG_ASSERT( pCurrentSaveInData, "SvxConfigPage::Reset(): no SaveInData" ); +#endif + + if ( CanConfig( aModuleId ) ) + { + // Load configuration for other open documents which have + // same module type + uno::Sequence< uno::Reference< frame::XFrame > > aFrameList; + try + { + uno::Reference< frame::XFramesSupplier > xFramesSupplier( + xServiceManager->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.Desktop" ) ) ), + uno::UNO_QUERY_THROW ); + + uno::Reference< frame::XFrames > xFrames = + xFramesSupplier->getFrames(); + + aFrameList = xFrames->queryFrames( + frame::FrameSearchFlag::ALL & ~frame::FrameSearchFlag::SELF ); + + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + for ( sal_Int32 i = 0; i < aFrameList.getLength(); i++ ) + { + SaveInData* pData = NULL; + uno::Reference < frame::XFrame > xf = aFrameList[i]; + + if ( xf.is() && xf != m_xFrame ) + { + OUString aCheckId; + try{ + aCheckId = xModuleManager->identify( xf ); + } catch(const uno::Exception&) + { aCheckId = ::rtl::OUString(); } + + if ( aModuleId.equals( aCheckId ) ) + { + // try to get the document based ui configuration manager + OUString aTitle2; + uno::Reference< frame::XController > xController_ = + xf->getController(); + + if ( xController_.is() ) + { + uno::Reference< frame::XModel > xModel( + xController_->getModel() ); + + if ( xModel.is() ) + { + uno::Reference< + css::ui::XUIConfigurationManagerSupplier > + xCfgSupplier( xModel, uno::UNO_QUERY ); + + if ( xCfgSupplier.is() ) + { + xDocCfgMgr = + xCfgSupplier->getUIConfigurationManager(); + } + aTitle2 = ::comphelper::DocumentInfo::getDocumentTitle( xModel ); + } + } + + if ( xDocCfgMgr.is() ) + { + pData = CreateSaveInData( xDocCfgMgr, xCfgMgr, aModuleId, TRUE ); + + if ( pData && !pData->IsReadOnly() ) + { + nPos = aSaveInListBox.InsertEntry( aTitle2 ); + aSaveInListBox.SetEntryData( nPos, pData ); + } + } + } + } + } + } + + aSaveInListBox.SetSelectHdl( + LINK( this, SvxConfigPage, SelectSaveInLocation ) ); + + bInitialised = TRUE; + + Init(); + } + else + { + if ( QueryReset() == RET_YES ) + { + // Reset menu configuration for currently selected SaveInData + GetSaveInData()->Reset(); + + Init(); + } + } +} + +::rtl::OUString SvxConfigPage::GetFrameWithDefaultAndIdentify( uno::Reference< frame::XFrame >& _inout_rxFrame ) +{ + ::rtl::OUString sModuleID; + try + { + uno::Reference< lang::XMultiServiceFactory > xServiceManager( + ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + + uno::Reference< frame::XFramesSupplier > xFramesSupplier( + xServiceManager->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.Desktop" ) ) ), + uno::UNO_QUERY_THROW ); + + if ( !_inout_rxFrame.is() ) + _inout_rxFrame = xFramesSupplier->getActiveFrame(); + + if ( !_inout_rxFrame.is() ) + { + uno::Reference< frame::XDesktop > xDesktop( xFramesSupplier, uno::UNO_QUERY_THROW ); + _inout_rxFrame = xDesktop->getCurrentFrame(); + } + + if ( !_inout_rxFrame.is() && SfxViewFrame::Current() ) + _inout_rxFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + + if ( !_inout_rxFrame.is() ) + { + DBG_ERRORFILE( "SvxConfigPage::GetFrameWithDefaultAndIdentify(): no frame found!" ); + return sModuleID; + } + + uno::Reference< css::frame::XModuleManager > xModuleManager( + xServiceManager->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.frame.ModuleManager" ) ) ), + uno::UNO_QUERY_THROW ); + + try + { + sModuleID = xModuleManager->identify( _inout_rxFrame ); + } + catch ( const frame::UnknownModuleException& ) + { + } + + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sModuleID; +} + +BOOL SvxConfigPage::FillItemSet( SfxItemSet& ) +{ + bool result = FALSE; + + for ( USHORT i = 0 ; i < aSaveInListBox.GetEntryCount(); i++ ) + { + SaveInData* pData = + (SaveInData*) aSaveInListBox.GetEntryData( i ); + + result = pData->Apply(); + } + return result; +} + +void SvxConfigPage::PositionContentsListBox() +{ + if ( aContentsListBox == NULL ) + { + return; + } + + Point p, newp; + Size s, news; + long x, y, width, height; + + // x and width is same as aTopLevelListBox + x = aTopLevelListBox.GetPosPixel().X(); + width = aTopLevelListBox.GetSizePixel().Width(); + + // y is same as aAddCommandsButton + y = aAddCommandsButton.GetPosPixel().Y(); + + // get gap between aAddCommandsButton and aContentsSeparator + p = aContentsSeparator.GetPosPixel(); + s = aContentsSeparator.GetSizePixel(); + long gap = y - ( p.Y() + s.Height() ); + + height = aSaveInListBox.GetPosPixel().Y() - y - gap; + + aContentsListBox->SetPosPixel( Point( x, y ) ); + aContentsListBox->SetSizePixel( Size( width, height ) ); +} + +IMPL_LINK( SvxConfigPage, SelectSaveInLocation, ListBox *, pBox ) +{ + (void)pBox; + + pCurrentSaveInData = (SaveInData*) aSaveInListBox.GetEntryData( + aSaveInListBox.GetSelectEntryPos()); + + Init(); + return 1; +} + +void SvxConfigPage::ReloadTopLevelListBox( SvxConfigEntry* pToSelect ) +{ + USHORT nSelectionPos = aTopLevelListBox.GetSelectEntryPos(); + aTopLevelListBox.Clear(); + + if ( GetSaveInData() && GetSaveInData()->GetEntries() ) + { + SvxEntries::const_iterator iter = GetSaveInData()->GetEntries()->begin(); + SvxEntries::const_iterator end = GetSaveInData()->GetEntries()->end(); + + for ( ; iter != end; iter++ ) + { + SvxConfigEntry* pEntryData = *iter; + USHORT nPos = aTopLevelListBox.InsertEntry( stripHotKey( pEntryData->GetName() ) ); + aTopLevelListBox.SetEntryData( nPos, pEntryData ); + + if ( pEntryData == pToSelect ) + nSelectionPos = nPos; + + AddSubMenusToUI( stripHotKey( pEntryData->GetName() ), pEntryData ); + } + } +#ifdef DBG_UTIL + else + { + DBG_ASSERT( GetSaveInData(), "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData" ); + DBG_ASSERT( GetSaveInData()->GetEntries() , + "SvxConfigPage::ReloadTopLevelListBox(): no SaveInData entries" ); + } +#endif + + nSelectionPos = nSelectionPos < aTopLevelListBox.GetEntryCount() ? + nSelectionPos : aTopLevelListBox.GetEntryCount() - 1; + + aTopLevelListBox.SelectEntryPos( nSelectionPos, TRUE ); + aTopLevelListBox.GetSelectHdl().Call( this ); +} + +void SvxConfigPage::AddSubMenusToUI( + const String& rBaseTitle, SvxConfigEntry* pParentData ) +{ + SvxEntries::const_iterator iter = pParentData->GetEntries()->begin(); + SvxEntries::const_iterator end = pParentData->GetEntries()->end(); + + for ( ; iter != end; iter++ ) + { + SvxConfigEntry* pEntryData = *iter; + + if ( pEntryData->IsPopup() ) + { + OUString subMenuTitle( rBaseTitle ); + subMenuTitle += OUString::createFromAscii( pMenuSeparatorStr ); + subMenuTitle += stripHotKey( pEntryData->GetName() ); + + USHORT nPos = aTopLevelListBox.InsertEntry( subMenuTitle ); + aTopLevelListBox.SetEntryData( nPos, pEntryData ); + + AddSubMenusToUI( subMenuTitle, pEntryData ); + } + } +} + +SvxEntries* SvxConfigPage::FindParentForChild( + SvxEntries* pRootEntries, SvxConfigEntry* pChildData ) +{ + SvxEntries::const_iterator iter = pRootEntries->begin(); + SvxEntries::const_iterator end = pRootEntries->end(); + + for ( ; iter != end; iter++ ) + { + SvxConfigEntry* pEntryData = *iter; + + if ( pEntryData == pChildData ) + { + return pRootEntries; + } + else if ( pEntryData->IsPopup() ) + { + SvxEntries* result = + FindParentForChild( pEntryData->GetEntries(), pChildData ); + + if ( result != NULL ) + { + return result; + } + } + } + return NULL; +} + +SvLBoxEntry* SvxConfigPage::AddFunction( + SvLBoxEntry* pTarget, bool bFront, bool bAllowDuplicates ) +{ + String aDisplayName = pSelectorDlg->GetSelectedDisplayName(); + String aHelpText = pSelectorDlg->GetSelectedHelpText(); + String aURL = pSelectorDlg->GetScriptURL(); + + if ( !aURL.Len() ) + { + return NULL; + } + + SvxConfigEntry* pNewEntryData = + new SvxConfigEntry( aDisplayName, aURL, FALSE ); + pNewEntryData->SetUserDefined( TRUE ); + pNewEntryData->SetHelpURL( aURL ); + + // check that this function is not already in the menu + SvxConfigEntry* pParent = GetTopLevelSelection(); + + SvxEntries::const_iterator iter = pParent->GetEntries()->begin(); + SvxEntries::const_iterator end = pParent->GetEntries()->end(); + + if ( !bAllowDuplicates ) + { + while ( iter != end ) + { + SvxConfigEntry *pCurEntry = *iter; + + if ( pCurEntry->GetCommand() == pNewEntryData->GetCommand() ) + { + // asynchronous error message, because of MsgBoxes + PostUserEvent( + LINK( this, SvxConfigPage, AsyncInfoMsg ) ); + return NULL; + } + + iter++; + } + } + + return InsertEntry( pNewEntryData, pTarget, bFront ); +} + +SvLBoxEntry* SvxConfigPage::InsertEntry( + SvxConfigEntry* pNewEntryData, + SvLBoxEntry* pTarget, + bool bFront ) +{ + // Grab the entries list for the currently selected menu + SvxEntries* pEntries = GetTopLevelSelection()->GetEntries(); + + SvLBoxEntry* pNewEntry = NULL; + SvLBoxEntry* pCurEntry = + pTarget != NULL ? pTarget : aContentsListBox->GetCurEntry(); + + if ( bFront ) + { + pEntries->insert( pEntries->begin(), pNewEntryData ); + pNewEntry = InsertEntryIntoUI( pNewEntryData, 0 ); + } + else if ( pCurEntry == NULL || pCurEntry == aContentsListBox->Last() ) + { + pEntries->push_back( pNewEntryData ); + pNewEntry = InsertEntryIntoUI( pNewEntryData ); + } + else + { + SvxConfigEntry* pEntryData = + (SvxConfigEntry*) pCurEntry->GetUserData(); + + SvxEntries::iterator iter = pEntries->begin(); + SvxEntries::const_iterator end = pEntries->end(); + + // Advance the iterator to the data for currently selected entry + USHORT nPos = 0; + while (*iter != pEntryData && ++iter != end) + { + nPos++; + } + + // Now step past it to the entry after the currently selected one + iter++; + nPos++; + + // Now add the new entry to the UI and to the parent's list + if ( iter != end ) + { + pEntries->insert( iter, pNewEntryData ); + pNewEntry = InsertEntryIntoUI( pNewEntryData, nPos ); + } + } + + if ( pNewEntry != NULL ) + { + aContentsListBox->Select( pNewEntry ); + aContentsListBox->MakeVisible( pNewEntry ); + + GetSaveInData()->SetModified( TRUE ); + } + + return pNewEntry; +} + +SvLBoxEntry* SvxConfigPage::InsertEntryIntoUI( + SvxConfigEntry* pNewEntryData, ULONG nPos ) +{ + SvLBoxEntry* pNewEntry = NULL; + + if (pNewEntryData->IsSeparator()) + { + pNewEntry = aContentsListBox->InsertEntry( + String::CreateFromAscii( pSeparatorStr ), + 0, FALSE, nPos, pNewEntryData ); + } + else + { + OUString aName = stripHotKey( pNewEntryData->GetName() ); + + Image aImage = GetSaveInData()->GetImage( + pNewEntryData->GetCommand()); + + if ( !!aImage ) + { + pNewEntry = aContentsListBox->InsertEntry( + aName, aImage, aImage, 0, FALSE, nPos, pNewEntryData ); + } + else + { + pNewEntry = aContentsListBox->InsertEntry( + aName, 0, FALSE, nPos, pNewEntryData ); + } + + if ( pNewEntryData->IsPopup() || + pNewEntryData->GetStyle() & css::ui::ItemStyle::DROP_DOWN ) + { + // add new popup painter, it gets destructed by the entry + pNewEntry->ReplaceItem( + new PopupPainter( pNewEntry, aName ), + pNewEntry->ItemCount() - 1 ); + } + } + + return pNewEntry; +} + +IMPL_LINK( SvxConfigPage, AsyncInfoMsg, String*, pMsg ) +{ + (void)pMsg; + + // Asynchronous msg because of D&D + InfoBox( this, CUI_RES( + IBX_MNUCFG_ALREADY_INCLUDED ) ).Execute(); + + return 0; +} + +IMPL_LINK( SvxConfigPage, MoveHdl, Button *, pButton ) +{ + MoveEntry( pButton == &aMoveUpButton ); + return 0; +} + +void SvxConfigPage::MoveEntry( bool bMoveUp ) +{ + SvLBoxEntry *pSourceEntry = aContentsListBox->FirstSelected(); + SvLBoxEntry *pTargetEntry = NULL; + SvLBoxEntry *pToSelect = NULL; + + if ( !pSourceEntry ) + { + return; + } + + if ( bMoveUp ) + { + // Move Up is just a Move Down with the source and target reversed + pTargetEntry = pSourceEntry; + pSourceEntry = aContentsListBox->PrevSibling( pTargetEntry ); + pToSelect = pTargetEntry; + } + else + { + pTargetEntry = aContentsListBox->NextSibling( pSourceEntry ); + pToSelect = pSourceEntry; + } + + if ( MoveEntryData( pSourceEntry, pTargetEntry ) ) + { + aContentsListBox->GetModel()->Move( pSourceEntry, pTargetEntry ); + aContentsListBox->Select( pToSelect ); + aContentsListBox->MakeVisible( pToSelect ); + + UpdateButtonStates(); + } +} + +bool SvxConfigPage::MoveEntryData( + SvLBoxEntry* pSourceEntry, SvLBoxEntry* pTargetEntry ) +{ + //modified by shizhoubo for issue53677 + if ( NULL == pSourceEntry || NULL == pTargetEntry ) + { + return FALSE; + } + + // Grab the entries list for the currently selected menu + SvxEntries* pEntries = GetTopLevelSelection()->GetEntries(); + + SvxConfigEntry* pSourceData = + (SvxConfigEntry*) pSourceEntry->GetUserData(); + + if ( pTargetEntry == NULL ) + { + RemoveEntry( pEntries, pSourceData ); + pEntries->insert( + pEntries->begin(), pSourceData ); + + GetSaveInData()->SetModified( TRUE ); + + return TRUE; + } + else + { + SvxConfigEntry* pTargetData = + (SvxConfigEntry*) pTargetEntry->GetUserData(); + + if ( pSourceData != NULL && pTargetData != NULL ) + { + // remove the source entry from our list + RemoveEntry( pEntries, pSourceData ); + + SvxEntries::iterator iter = pEntries->begin(); + SvxEntries::const_iterator end = pEntries->end(); + + // advance the iterator to the position of the target entry + while (*iter != pTargetData && ++iter != end) ; + + // insert the source entry at the position after the target + pEntries->insert( ++iter, pSourceData ); + + GetSaveInData()->SetModified( TRUE ); + + return TRUE; + } + } + + return FALSE; +} + +SvxMenuConfigPage::SvxMenuConfigPage( + Window *pParent, const SfxItemSet& rSet ) + : + SvxConfigPage( pParent, rSet ) +{ + aContentsListBox = new SvxMenuEntriesListBox( this, CUI_RES( BOX_ENTRIES ) ); + FreeResource(); + + PositionContentsListBox(); + aContentsListBox->SetZOrder( &aAddCommandsButton, WINDOW_ZORDER_BEFOR ); + + aTopLevelListBox.SetSelectHdl( + LINK( this, SvxMenuConfigPage, SelectMenu ) ); + + aContentsListBox->SetSelectHdl( + LINK( this, SvxMenuConfigPage, SelectMenuEntry ) ); + + aMoveUpButton.SetClickHdl ( LINK( this, SvxConfigPage, MoveHdl) ); + aMoveDownButton.SetClickHdl ( LINK( this, SvxConfigPage, MoveHdl) ); + + aNewTopLevelButton.SetClickHdl ( + LINK( this, SvxMenuConfigPage, NewMenuHdl ) ); + + aAddCommandsButton.SetClickHdl ( + LINK( this, SvxMenuConfigPage, AddCommandsHdl ) ); + + PopupMenu* pMenu = new PopupMenu( CUI_RES( MODIFY_MENU ) ); + pMenu->SetMenuFlags( + pMenu->GetMenuFlags() | MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ); + + aModifyTopLevelButton.SetPopupMenu( pMenu ); + aModifyTopLevelButton.SetSelectHdl( + LINK( this, SvxMenuConfigPage, MenuSelectHdl ) ); + + PopupMenu* pEntry = new PopupMenu( CUI_RES( MODIFY_ENTRY ) ); + pEntry->SetMenuFlags( + pEntry->GetMenuFlags() | MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ); + + aModifyCommandButton.SetPopupMenu( pEntry ); + aModifyCommandButton.SetSelectHdl( + LINK( this, SvxMenuConfigPage, EntrySelectHdl ) ); +} + +// Populates the Menu combo box +void SvxMenuConfigPage::Init() +{ + // ensure that the UI is cleared before populating it + aTopLevelListBox.Clear(); + aContentsListBox->Clear(); + + ReloadTopLevelListBox(); + + aTopLevelListBox.SelectEntryPos(0, TRUE); + aTopLevelListBox.GetSelectHdl().Call(this); +} + +SvxMenuConfigPage::~SvxMenuConfigPage() +{ + for ( USHORT i = 0 ; i < aSaveInListBox.GetEntryCount(); i++ ) + { + MenuSaveInData* pData = + (MenuSaveInData*) aSaveInListBox.GetEntryData( i ); + + delete pData; + } + + if ( pSelectorDlg != NULL ) + { + delete pSelectorDlg; + } + + delete aContentsListBox; +} + +IMPL_LINK( SvxMenuConfigPage, SelectMenuEntry, Control *, pBox ) +{ + (void)pBox; + + UpdateButtonStates(); + + return 1; +} + +void SvxMenuConfigPage::UpdateButtonStates() +{ + PopupMenu* pPopup = aModifyCommandButton.GetPopupMenu(); + + // Disable Up and Down buttons depending on current selection + SvLBoxEntry* selection = aContentsListBox->GetCurEntry(); + + if ( aContentsListBox->GetEntryCount() == 0 || selection == NULL ) + { + aMoveUpButton.Enable( FALSE ); + aMoveDownButton.Enable( FALSE ); + + pPopup->EnableItem( ID_BEGIN_GROUP, TRUE ); + pPopup->EnableItem( ID_RENAME, FALSE ); + pPopup->EnableItem( ID_DELETE, FALSE ); + + aDescriptionField.Clear(); + + return; + } + + SvLBoxEntry* first = aContentsListBox->First(); + SvLBoxEntry* last = aContentsListBox->Last(); + + aMoveUpButton.Enable( selection != first ); + aMoveDownButton.Enable( selection != last ); + + SvxConfigEntry* pEntryData = + (SvxConfigEntry*) selection->GetUserData(); + + if ( pEntryData->IsSeparator() ) + { + pPopup->EnableItem( ID_DELETE, TRUE ); + pPopup->EnableItem( ID_BEGIN_GROUP, FALSE ); + pPopup->EnableItem( ID_RENAME, FALSE ); + + aDescriptionField.Clear(); + } + else + { + pPopup->EnableItem( ID_BEGIN_GROUP, TRUE ); + pPopup->EnableItem( ID_DELETE, TRUE ); + pPopup->EnableItem( ID_RENAME, TRUE ); + + aDescriptionField.SetNewText( pEntryData->GetHelpText() ); + } +} + +void SvxMenuConfigPage::DeleteSelectedTopLevel() +{ + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + SvxEntries* pParentEntries = + FindParentForChild( GetSaveInData()->GetEntries(), pMenuData ); + + RemoveEntry( pParentEntries, pMenuData ); + delete pMenuData; + + ReloadTopLevelListBox(); + + GetSaveInData()->SetModified( TRUE ); +} + +bool SvxMenuConfigPage::DeleteSelectedContent() +{ + SvLBoxEntry *pActEntry = aContentsListBox->FirstSelected(); + + if ( pActEntry != NULL ) + { + // get currently selected menu entry + SvxConfigEntry* pMenuEntry = + (SvxConfigEntry*) pActEntry->GetUserData(); + + // get currently selected menu + SvxConfigEntry* pMenu = GetTopLevelSelection(); + + // remove menu entry from the list for this menu + RemoveEntry( pMenu->GetEntries(), pMenuEntry ); + + // remove menu entry from UI + aContentsListBox->GetModel()->Remove( pActEntry ); + + // if this is a submenu entry, redraw the menus list box + if ( pMenuEntry->IsPopup() ) + { + ReloadTopLevelListBox(); + } + + // delete data for menu entry + delete pMenuEntry; + + GetSaveInData()->SetModified( TRUE ); + + return TRUE; + } + return FALSE; +} + +short SvxMenuConfigPage::QueryReset() +{ + String msg = + String( CUI_RES( RID_SVXSTR_CONFIRM_MENU_RESET ) ); + + String saveInName = aSaveInListBox.GetEntry( + aSaveInListBox.GetSelectEntryPos() ); + + OUString label = replaceSaveInName( msg, saveInName ); + + QueryBox qbox( this, WB_YES_NO, label ); + + return qbox.Execute(); +} + +IMPL_LINK( SvxMenuConfigPage, SelectMenu, ListBox *, pBox ) +{ + (void)pBox; + + aContentsListBox->Clear(); + + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + PopupMenu* pPopup = aModifyTopLevelButton.GetPopupMenu(); + if ( pMenuData ) + { + pPopup->EnableItem( ID_DELETE, pMenuData->IsDeletable() ); + pPopup->EnableItem( ID_RENAME, pMenuData->IsRenamable() ); + pPopup->EnableItem( ID_MOVE, pMenuData->IsMovable() ); + + SvxEntries* pEntries = pMenuData->GetEntries(); + SvxEntries::const_iterator iter = pEntries->begin(); + + for ( ; iter != pEntries->end(); iter++ ) + { + SvxConfigEntry* pEntry = *iter; + InsertEntryIntoUI( pEntry ); + } + } + + UpdateButtonStates(); + + return 0; +} + +IMPL_LINK( SvxMenuConfigPage, MenuSelectHdl, MenuButton *, pButton ) +{ + switch( pButton->GetCurItemId() ) + { + case ID_DELETE: + { + DeleteSelectedTopLevel(); + break; + } + case ID_RENAME: + { + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + String aNewName( stripHotKey( pMenuData->GetName() ) ); + String aDesc = CUI_RESSSTR( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog* pNameDialog = new SvxNameDialog( this, aNewName, aDesc ); + pNameDialog->SetHelpId( HID_SVX_CONFIG_RENAME_MENU ); + pNameDialog->SetText( CUI_RESSTR( RID_SVXSTR_RENAME_MENU ) ); + + bool ret = pNameDialog->Execute(); + + if ( ret == RET_OK ) { + pNameDialog->GetName( aNewName ); + pMenuData->SetName( aNewName ); + + ReloadTopLevelListBox(); + + GetSaveInData()->SetModified( TRUE ); + } + + // #i68101# Moemory leak (!) + delete pNameDialog; + + break; + } + case ID_MOVE: + { + SvxConfigEntry* pMenuData = GetTopLevelSelection(); + + SvxMainMenuOrganizerDialog* pDialog = + new SvxMainMenuOrganizerDialog( this, + GetSaveInData()->GetEntries(), pMenuData ); + + bool ret = pDialog->Execute(); + + if ( ret == RET_OK ) + { + GetSaveInData()->SetEntries( pDialog->GetEntries() ); + + ReloadTopLevelListBox( pDialog->GetSelectedEntry() ); + + GetSaveInData()->SetModified( TRUE ); + } + + delete pDialog; + + break; + } + default: + return FALSE; + } + return TRUE; +} + +IMPL_LINK( SvxMenuConfigPage, EntrySelectHdl, MenuButton *, pButton ) +{ + switch( pButton->GetCurItemId() ) + { + case ID_ADD_SUBMENU: + { + String aNewName; + String aDesc = CUI_RESSSTR( RID_SVXSTR_SUBMENU_NAME ); + + SvxNameDialog* pNameDialog = new SvxNameDialog( this, aNewName, aDesc ); + pNameDialog->SetHelpId( HID_SVX_CONFIG_NAME_SUBMENU ); + pNameDialog->SetText( CUI_RESSTR( RID_SVXSTR_ADD_SUBMENU ) ); + + bool ret = pNameDialog->Execute(); + + if ( ret == RET_OK ) { + pNameDialog->GetName(aNewName); + + SvxConfigEntry* pNewEntryData = + new SvxConfigEntry( aNewName, aNewName, TRUE ); + pNewEntryData->SetUserDefined( TRUE ); + + InsertEntry( pNewEntryData ); + + ReloadTopLevelListBox(); + + GetSaveInData()->SetModified( TRUE ); + } + + delete pNameDialog; + + break; + } + case ID_BEGIN_GROUP: + { + SvxConfigEntry* pNewEntryData = new SvxConfigEntry; + pNewEntryData->SetUserDefined( TRUE ); + InsertEntry( pNewEntryData ); + + break; + } + case ID_DELETE: + { + DeleteSelectedContent(); + break; + } + case ID_RENAME: + { + SvLBoxEntry* pActEntry = aContentsListBox->GetCurEntry(); + SvxConfigEntry* pEntry = + (SvxConfigEntry*) pActEntry->GetUserData(); + + String aNewName( stripHotKey( pEntry->GetName() ) ); + String aDesc = CUI_RESSSTR( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog* pNameDialog = new SvxNameDialog( this, aNewName, aDesc ); + pNameDialog->SetHelpId( HID_SVX_CONFIG_RENAME_MENU_ITEM ); + pNameDialog->SetText( CUI_RESSTR( RID_SVXSTR_RENAME_MENU ) ); + + bool ret = pNameDialog->Execute(); + + if ( ret == RET_OK ) { + pNameDialog->GetName(aNewName); + + pEntry->SetName( aNewName ); + aContentsListBox->SetEntryText( pActEntry, aNewName ); + + GetSaveInData()->SetModified( TRUE ); + } + + delete pNameDialog; + + break; + } + default: + { + return FALSE; + } + } + + if ( GetSaveInData()->IsModified() ) + { + UpdateButtonStates(); + } + + return TRUE; +} + +IMPL_LINK( SvxMenuConfigPage, AddFunctionHdl, + SvxScriptSelectorDialog *, pDialog ) +{ + (void)pDialog; + + AddFunction(); + + return 0; +} + +IMPL_LINK( SvxMenuConfigPage, NewMenuHdl, Button *, pButton ) +{ + (void)pButton; + + SvxMainMenuOrganizerDialog* pDialog = + new SvxMainMenuOrganizerDialog( 0, + GetSaveInData()->GetEntries(), NULL, TRUE ); + + bool ret = pDialog->Execute(); + + if ( ret == RET_OK ) + { + GetSaveInData()->SetEntries( pDialog->GetEntries() ); + ReloadTopLevelListBox( pDialog->GetSelectedEntry() ); + GetSaveInData()->SetModified( TRUE ); + } + + delete pDialog; + + return 0; +} + +IMPL_LINK( SvxMenuConfigPage, AddCommandsHdl, Button *, pButton ) +{ + (void)pButton; + + if ( pSelectorDlg == NULL ) + { + // Create Script Selector which also shows builtin commands + pSelectorDlg = new SvxScriptSelectorDialog( this, TRUE, m_xFrame ); + + pSelectorDlg->SetAddHdl( + LINK( this, SvxMenuConfigPage, AddFunctionHdl ) ); + + pSelectorDlg->SetDialogDescription( String( + CUI_RES( RID_SVXSTR_MENU_ADDCOMMANDS_DESCRIPTION ) ) ); + } + + // Position the Script Selector over the Add button so it is + // beside the menu contents list and does not obscure it + pSelectorDlg->SetPosPixel( aAddCommandsButton.GetPosPixel() ); + + pSelectorDlg->SetImageProvider( + static_cast< ImageProvider* >( GetSaveInData() ) ); + + pSelectorDlg->Show(); + return 1; +} + +SaveInData* SvxMenuConfigPage::CreateSaveInData( + const uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool bDocConfig ) +{ + return static_cast< SaveInData* >( + new MenuSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig )); +} + +SvxMainMenuOrganizerDialog::SvxMainMenuOrganizerDialog( + Window* pParent, SvxEntries* entries, + SvxConfigEntry* selection, bool bCreateMenu ) + : + ModalDialog( pParent, CUI_RES( MD_MENU_ORGANISER ) ), + aMenuNameText( this, CUI_RES( TXT_MENU_NAME ) ), + aMenuNameEdit( this, CUI_RES( EDIT_MENU_NAME ) ), + aMenuListText( this, CUI_RES( TXT_MENU ) ), + aMenuListBox( this, CUI_RES( BOX_MAIN_MENUS ) ), + aMoveUpButton( this, CUI_RES( BTN_MENU_UP ) ), + aMoveDownButton( this, CUI_RES( BTN_MENU_DOWN ) ), + aOKButton( this, CUI_RES( BTN_MENU_ADD ) ), + aCloseButton( this, CUI_RES( BTN_MENU_CLOSE ) ), + aHelpButton( this, CUI_RES( BTN_MENU_HELP ) ), + bModified( FALSE ) +{ + FreeResource(); + + // Copy the entries list passed in + if ( entries != NULL ) + { + SvxConfigEntry* pEntry; + SvLBoxEntry* pLBEntry; + + pEntries = new SvxEntries(); + SvxEntries::const_iterator iter = entries->begin(); + + while ( iter != entries->end() ) + { + pEntry = *iter; + pLBEntry = + aMenuListBox.InsertEntry( stripHotKey( pEntry->GetName() ) ); + pLBEntry->SetUserData( pEntry ); + pEntries->push_back( pEntry ); + + if ( pEntry == selection ) + { + aMenuListBox.Select( pLBEntry ); + } + iter++; + } + } + + if ( bCreateMenu ) + { + // Generate custom name for new menu + String prefix = + String( CUI_RES( RID_SVXSTR_NEW_MENU ) ); + + OUString newname = generateCustomName( prefix, entries ); + OUString newurl = generateCustomMenuURL( pEntries ); + + SvxConfigEntry* pNewEntryData = + new SvxConfigEntry( newname, newurl, TRUE ); + pNewEntryData->SetUserDefined( TRUE ); + pNewEntryData->SetMain( TRUE ); + + pNewMenuEntry = + aMenuListBox.InsertEntry( stripHotKey( pNewEntryData->GetName() ) ); + aMenuListBox.Select( pNewMenuEntry ); + + pNewMenuEntry->SetUserData( pNewEntryData ); + + pEntries->push_back( pNewEntryData ); + + aMenuNameEdit.SetText( newname ); + aMenuNameEdit.SetModifyHdl( + LINK( this, SvxMainMenuOrganizerDialog, ModifyHdl ) ); + } + else + { + Point p, newp; + Size s, news; + + // get offset to bottom of name textfield from top of dialog + p = aMenuNameEdit.GetPosPixel(); + s = aMenuNameEdit.GetSizePixel(); + long offset = p.Y() + s.Height(); + + // reposition menu list and label + aMenuListText.SetPosPixel( aMenuNameText.GetPosPixel() ); + aMenuListBox.SetPosPixel( aMenuNameEdit.GetPosPixel() ); + + // reposition up and down buttons + p = aMoveUpButton.GetPosPixel(); + newp = Point( p.X(), p.Y() - offset ); + aMoveUpButton.SetPosPixel( newp ); + + p = aMoveDownButton.GetPosPixel(); + newp = Point( p.X(), p.Y() - offset ); + aMoveDownButton.SetPosPixel( newp ); + + // change size of dialog + s = GetSizePixel(); + news = Size( s.Width(), s.Height() - offset ); + SetSizePixel( news ); + + // hide name label and textfield + aMenuNameText.Hide(); + aMenuNameEdit.Hide(); + + // change the title + SetText( CUI_RES( RID_SVXSTR_MOVE_MENU ) ); + } + + aMenuListBox.SetSelectHdl( + LINK( this, SvxMainMenuOrganizerDialog, SelectHdl ) ); + + aMoveUpButton.SetClickHdl ( + LINK( this, SvxMainMenuOrganizerDialog, MoveHdl) ); + aMoveDownButton.SetClickHdl ( + LINK( this, SvxMainMenuOrganizerDialog, MoveHdl) ); +} + +IMPL_LINK(SvxMainMenuOrganizerDialog, ModifyHdl, Edit*, pEdit) +{ + (void)pEdit; + + // if the Edit control is empty do not change the name + if ( aMenuNameEdit.GetText().Equals( String() ) ) + { + return 0; + } + + SvxConfigEntry* pNewEntryData = + (SvxConfigEntry*) pNewMenuEntry->GetUserData(); + + pNewEntryData->SetName( aMenuNameEdit.GetText() ); + + aMenuListBox.SetEntryText( pNewMenuEntry, pNewEntryData->GetName() ); + + return 0; +} + +SvxMainMenuOrganizerDialog::~SvxMainMenuOrganizerDialog() +{ +} + +IMPL_LINK( SvxMainMenuOrganizerDialog, SelectHdl, Control*, pCtrl ) +{ + (void)pCtrl; + UpdateButtonStates(); + return 1; +} + +void SvxMainMenuOrganizerDialog::UpdateButtonStates() +{ + // Disable Up and Down buttons depending on current selection + SvLBoxEntry* selection = aMenuListBox.GetCurEntry(); + SvLBoxEntry* first = aMenuListBox.First(); + SvLBoxEntry* last = aMenuListBox.Last(); + + aMoveUpButton.Enable( selection != first ); + aMoveDownButton.Enable( selection != last ); +} + +IMPL_LINK( SvxMainMenuOrganizerDialog, MoveHdl, Button *, pButton ) +{ + SvLBoxEntry *pSourceEntry = aMenuListBox.FirstSelected(); + SvLBoxEntry *pTargetEntry = NULL; + + if ( !pSourceEntry ) + { + return 0; + } + + if ( pButton == &aMoveDownButton ) + { + pTargetEntry = aMenuListBox.NextSibling( pSourceEntry ); + } + else if ( pButton == &aMoveUpButton ) + { + // Move Up is just a Move Down with the source and target reversed + pTargetEntry = pSourceEntry; + pSourceEntry = aMenuListBox.PrevSibling( pTargetEntry ); + } + + if ( pSourceEntry != NULL && pTargetEntry != NULL ) + { + SvxConfigEntry* pSourceData = + (SvxConfigEntry*) pSourceEntry->GetUserData(); + SvxConfigEntry* pTargetData = + (SvxConfigEntry*) pTargetEntry->GetUserData(); + + SvxEntries::iterator iter1 = GetEntries()->begin(); + SvxEntries::iterator iter2 = GetEntries()->begin(); + SvxEntries::const_iterator end = GetEntries()->end(); + + // Advance the iterators to the positions of the source and target + while (*iter1 != pSourceData && ++iter1 != end) ; + while (*iter2 != pTargetData && ++iter2 != end) ; + + // Now swap the entries in the menu list and in the UI + if ( iter1 != end && iter2 != end ) + { + std::swap( *iter1, *iter2 ); + aMenuListBox.GetModel()->Move( pSourceEntry, pTargetEntry ); + aMenuListBox.MakeVisible( pSourceEntry ); + + bModified = TRUE; + } + } + + if ( bModified ) + { + UpdateButtonStates(); + } + + return 0; +} + +SvxEntries* SvxMainMenuOrganizerDialog::GetEntries() +{ + return pEntries; +} + +SvxConfigEntry* SvxMainMenuOrganizerDialog::GetSelectedEntry() +{ + return (SvxConfigEntry*)aMenuListBox.FirstSelected()->GetUserData(); +} + +SvxConfigEntry::SvxConfigEntry( + const uno::Sequence< beans::PropertyValue >& rProperties, + const uno::Reference< container::XNameAccess >& rCommandToLabelMap ) + : + nId( 1 ), + bPopUp( FALSE ), + bStrEdited( FALSE ), + bIsUserDefined( FALSE ), + bIsMain( FALSE ), + bIsParentData( FALSE ), + bIsVisible( TRUE ), + nStyle( 0 ), + pEntries( 0 ) +{ + sal_uInt16 nType( css::ui::ItemType::DEFAULT ); + OUString aHelpURL_; + + for ( sal_Int32 i = 0; i < rProperties.getLength(); i++ ) + { + if ( rProperties[i].Name.equalsAscii( ITEM_DESCRIPTOR_COMMANDURL )) + { + rProperties[i].Value >>= aCommand; + } + else if ( rProperties[i].Name.equalsAscii( ITEM_DESCRIPTOR_HELPURL )) + { + rProperties[i].Value >>= aHelpURL_; + } + else if ( rProperties[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL )) + { + rProperties[i].Value >>= aLabel; + } + else if ( rProperties[i].Name.equalsAscii( ITEM_DESCRIPTOR_TYPE )) + { + rProperties[i].Value >>= nType; + } + } + + if ( nType == css::ui::ItemType::DEFAULT ) + { + uno::Any a; + try + { + a = rCommandToLabelMap->getByName( aCommand ); + bIsUserDefined = FALSE; + } + catch ( container::NoSuchElementException& ) + { + bIsUserDefined = TRUE; + } + + // If custom label not set retrieve it from the command to info service + if ( aLabel.equals( OUString() ) ) + { + uno::Sequence< beans::PropertyValue > aPropSeq; + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL ) ) + { + aPropSeq[i].Value >>= aLabel; + break; + } + } + } + } + } +} + +const OUString& +SvxConfigEntry::GetHelpText() +{ + if ( aHelpText.getLength() == 0 ) + { + OUString helpid = OUString::createFromAscii( "helpid:" ); + if ( aHelpURL.indexOf( helpid ) != -1 ) + { + aHelpURL = aHelpURL.copy( helpid.getLength() ); + } + + Help* pHelp = Application::GetHelp(); + if ( aHelpURL.toInt32() != 0 ) + { + aHelpText = pHelp->GetHelpText( aHelpURL.toInt32(), NULL ); + } + + if ( aHelpText.getLength() == 0 && aCommand.getLength() != 0 ) + { + aHelpText = pHelp->GetHelpText( aCommand, NULL ); + } + } + + return aHelpText; +} + +uno::Sequence< beans::PropertyValue > +SvxConfigEntry::GetProperties( + const uno::Reference< container::XNameAccess >& rCommandToLabelMap ) +{ + if ( IsSeparator() ) + { + uno::Sequence< beans::PropertyValue > aPropSeq( 1 ); + + aPropSeq[0].Name = OUString( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE ) ); + aPropSeq[0].Value <<= css::ui::ItemType::SEPARATOR_LINE; + + return aPropSeq; + } + + static const OUString aDescriptorCommandURL ( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_COMMANDURL ) ); + + static const OUString aDescriptorType( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_TYPE ) ); + + static const OUString aDescriptorLabel( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_LABEL ) ); + + static const OUString aDescriptorHelpURL( + RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_HELPURL ) ); + + uno::Sequence< beans::PropertyValue > aPropSeq( 4 ); + + aPropSeq[0].Name = aDescriptorCommandURL; + aPropSeq[0].Value <<= rtl::OUString( GetCommand() ); + + aPropSeq[1].Name = aDescriptorType; + aPropSeq[1].Value <<= css::ui::ItemType::DEFAULT; + + // If the name has not been changed and the name is the same as + // in the default command to label map then the label can be stored + // as an empty string. + // It will be initialised again later using the command to label map. + aPropSeq[2].Name = aDescriptorLabel; + if ( HasChangedName() == FALSE && GetCommand().getLength() ) + { + BOOL isDefaultName = FALSE; + try + { + uno::Any a( rCommandToLabelMap->getByName( GetCommand() ) ); + uno::Sequence< beans::PropertyValue > tmpPropSeq; + if ( a >>= tmpPropSeq ) + { + for ( sal_Int32 i = 0; i < tmpPropSeq.getLength(); i++ ) + { + if ( tmpPropSeq[i].Name.equals( aDescriptorLabel ) ) + { + OUString tmpLabel; + tmpPropSeq[i].Value >>= tmpLabel; + + if ( tmpLabel.equals( GetName() ) ) + { + isDefaultName = TRUE; + } + + break; + } + } + } + } + catch ( container::NoSuchElementException& ) + { + // isDefaultName is left as FALSE + } + + if ( isDefaultName ) + { + aPropSeq[2].Value <<= rtl::OUString(); + } + else + { + aPropSeq[2].Value <<= rtl::OUString( GetName() ); + } + } + else + { + aPropSeq[2].Value <<= rtl::OUString( GetName() ); + } + + aPropSeq[3].Name = aDescriptorHelpURL; + aPropSeq[3].Value <<= rtl::OUString( GetHelpURL() ); + + return aPropSeq; +} + +/* +SvxMenuConfigEntry::SvxMenuConfigEntry( + const uno::Sequence< beans::PropertyValue >& rProperties, + const uno::Reference< container::XNameAccess >& rCommandToLabelMap ) + : + SvxConfigEntry( rProperties, rCommandToLabelMap ) +{ + uno::Reference< container::XIndexAccess > aChildren; + + for ( sal_Int32 i = 0; i < rProperties.getLength(); i++ ) + { + if ( rProperties[i].Name.equalsAscii( ITEM_DESCRIPTOR_CONTAINER )) + { + rProperties[i].Value >>= aChildren; + } + } + + if ( aChildren.is() ) + { + SetPopup( TRUE ); + SetEntries( new SvxEntries() ); + + uno::Sequence< beans::PropertyValue > aProps; + for ( sal_Int32 i = 0; i < aChildren->getCount(); i++ ) + { + if ( aChildren->getByIndex( i ) >>= aProps ) + { + SvxConfigEntry* pEntry = + new SvxMenuConfigEntry( aProps, rCommandToLabelMap ); + GetEntries()->push_back( pEntry ); + } + } + } +} +*/ + +SvxConfigEntry::SvxConfigEntry( const OUString& rDisplayName, + const OUString& rCommandURL, bool bPopup, bool bParentData ) + : nId( 1 ) + , aLabel(rDisplayName) + , aCommand(rCommandURL) + , bPopUp(bPopup) + , bStrEdited( FALSE ) + , bIsUserDefined( FALSE ) + , bIsMain( FALSE ) + , bIsParentData( bParentData ) + , bIsVisible( TRUE ) + , nStyle( 0 ) + , pEntries( 0 ) +{ + if (bPopUp) + { + pEntries = new SvxEntries(); + } +} + +SvxConfigEntry::~SvxConfigEntry() +{ + if ( pEntries != NULL ) + { + SvxEntries::const_iterator iter = pEntries->begin(); + + for ( ; iter != pEntries->end(); iter++ ) + { + delete *iter; + } + delete pEntries; + } +} + +bool SvxConfigEntry::IsMovable() +{ + if ( IsPopup() && !IsMain() ) + { + return FALSE; + } + return TRUE; +} + +bool SvxConfigEntry::IsDeletable() +{ + if ( IsMain() && !IsUserDefined() ) + { + return FALSE; + } + return TRUE; +} + +bool SvxConfigEntry::IsRenamable() +{ + if ( IsMain() && !IsUserDefined() ) + { + return FALSE; + } + return TRUE; +} + +SvxToolbarConfigPage::SvxToolbarConfigPage( + Window *pParent, const SfxItemSet& rSet ) + : + SvxConfigPage( pParent, rSet ) +{ + SetHelpId( HID_SVX_CONFIG_TOOLBAR ); + + aContentsListBox = new SvxToolbarEntriesListBox(this, CUI_RES(BOX_ENTRIES)); + FreeResource(); + PositionContentsListBox(); + aContentsListBox->SetZOrder( &aAddCommandsButton, WINDOW_ZORDER_BEFOR ); + + aContentsListBox->SetHelpId( HID_SVX_CONFIG_TOOLBAR_CONTENTS ); + aNewTopLevelButton.SetHelpId( HID_SVX_NEW_TOOLBAR ); + aModifyTopLevelButton.SetHelpId( HID_SVX_MODIFY_TOOLBAR ); + aAddCommandsButton.SetHelpId( HID_SVX_NEW_TOOLBAR_ITEM ); + aModifyCommandButton.SetHelpId( HID_SVX_MODIFY_TOOLBAR_ITEM ); + aSaveInListBox.SetHelpId( HID_SVX_SAVE_IN ); + + aTopLevelSeparator.SetText( + CUI_RES ( RID_SVXSTR_PRODUCTNAME_TOOLBARS ) ); + + aTopLevelLabel.SetText( CUI_RES( RID_SVXSTR_TOOLBAR ) ); + aModifyTopLevelButton.SetText( CUI_RES( RID_SVXSTR_TOOLBAR ) ); + aContentsSeparator.SetText( CUI_RES( RID_SVXSTR_TOOLBAR_CONTENT ) ); + aContentsLabel.SetText( CUI_RES( RID_SVXSTR_COMMANDS ) ); + + aTopLevelListBox.SetSelectHdl( + LINK( this, SvxToolbarConfigPage, SelectToolbar ) ); + aContentsListBox->SetSelectHdl( + LINK( this, SvxToolbarConfigPage, SelectToolbarEntry ) ); + + aNewTopLevelButton.SetClickHdl ( + LINK( this, SvxToolbarConfigPage, NewToolbarHdl ) ); + + aAddCommandsButton.SetClickHdl ( + LINK( this, SvxToolbarConfigPage, AddCommandsHdl ) ); + + aMoveUpButton.SetClickHdl ( LINK( this, SvxToolbarConfigPage, MoveHdl) ); + aMoveDownButton.SetClickHdl ( LINK( this, SvxToolbarConfigPage, MoveHdl) ); + // Always enable Up and Down buttons + // added for issue i53677 by shizhoubo + aMoveDownButton.Enable( TRUE ); + aMoveUpButton.Enable( TRUE ); + + PopupMenu* pMenu = new PopupMenu( CUI_RES( MODIFY_TOOLBAR ) ); + pMenu->SetMenuFlags( + pMenu->GetMenuFlags() | MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ); + + aModifyTopLevelButton.SetPopupMenu( pMenu ); + aModifyTopLevelButton.SetSelectHdl( + LINK( this, SvxToolbarConfigPage, ToolbarSelectHdl ) ); + + PopupMenu* pEntry = new PopupMenu( + CUI_RES( MODIFY_TOOLBAR_CONTENT ) ); + pEntry->SetMenuFlags( + pEntry->GetMenuFlags() | MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES ); + + aModifyCommandButton.SetPopupMenu( pEntry ); + aModifyCommandButton.SetSelectHdl( + LINK( this, SvxToolbarConfigPage, EntrySelectHdl ) ); + + // default toolbar to select is standardbar unless a different one + // has been passed in + m_aURLToSelect = OUString::createFromAscii( ITEM_TOOLBAR_URL ); + m_aURLToSelect += OUString::createFromAscii( "standardbar" ); + + const SfxPoolItem* pItem = + rSet.GetItem( rSet.GetPool()->GetWhich( SID_CONFIG ) ); + + if ( pItem ) + { + OUString text = ((const SfxStringItem*)pItem)->GetValue(); + if (text.indexOf(OUString::createFromAscii(ITEM_TOOLBAR_URL)) == 0) + { + m_aURLToSelect = text.copy( 0 ); + } + } + + long nTxtW = aTopLevelLabel.GetCtrlTextWidth( aTopLevelLabel.GetText() ); + long nCtrlW = aTopLevelLabel.GetSizePixel().Width(); + if ( nTxtW >= nCtrlW ) + { + long nDelta = Max( (long)10, nTxtW - nCtrlW ); + Size aNewSz = aTopLevelLabel.GetSizePixel(); + aNewSz.Width() += nDelta; + aTopLevelLabel.SetSizePixel( aNewSz ); + aNewSz = aTopLevelListBox.GetSizePixel(); + aNewSz.Width() -= nDelta; + Point aNewPt = aTopLevelListBox.GetPosPixel(); + aNewPt.X() += nDelta; + aTopLevelListBox.SetPosSizePixel( aNewPt, aNewSz ); + } +} + +SvxToolbarConfigPage::~SvxToolbarConfigPage() +{ + for ( USHORT i = 0 ; i < aSaveInListBox.GetEntryCount(); i++ ) + { + ToolbarSaveInData* pData = + (ToolbarSaveInData*) aSaveInListBox.GetEntryData( i ); + + delete pData; + } + + if ( pSelectorDlg != NULL ) + { + delete pSelectorDlg; + } + + + delete aContentsListBox; +} + +void SvxToolbarConfigPage::DeleteSelectedTopLevel() +{ + USHORT nSelectionPos = aTopLevelListBox.GetSelectEntryPos(); + ToolbarSaveInData* pSaveInData = (ToolbarSaveInData*) GetSaveInData(); + pSaveInData->RemoveToolbar( GetTopLevelSelection() ); + + if ( aTopLevelListBox.GetEntryCount() > 1 ) + { + // select next entry after the one being deleted + // selection position is indexed from 0 so need to + // subtract one from the entry count + if ( nSelectionPos != aTopLevelListBox.GetEntryCount() - 1 ) + { + aTopLevelListBox.SelectEntryPos( nSelectionPos + 1, TRUE ); + } + else + { + aTopLevelListBox.SelectEntryPos( nSelectionPos - 1, TRUE ); + } + aTopLevelListBox.GetSelectHdl().Call( this ); + + // and now remove the entry + aTopLevelListBox.RemoveEntry( nSelectionPos ); + } + else + { + ReloadTopLevelListBox(); + } +} + +bool SvxToolbarConfigPage::DeleteSelectedContent() +{ + SvLBoxEntry *pActEntry = aContentsListBox->FirstSelected(); + + if ( pActEntry != NULL ) + { + // get currently selected entry + SvxConfigEntry* pEntry = + (SvxConfigEntry*) pActEntry->GetUserData(); + + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + + // remove entry from the list for this toolbar + RemoveEntry( pToolbar->GetEntries(), pEntry ); + + // remove toolbar entry from UI + aContentsListBox->GetModel()->Remove( pActEntry ); + + // delete data for toolbar entry + delete pEntry; + + (( ToolbarSaveInData* ) GetSaveInData())->ApplyToolbar( pToolbar ); + UpdateButtonStates(); + + // if this is the last entry in the toolbar and it is a user + // defined toolbar pop up a dialog asking the user if they + // want to delete the toolbar + if ( aContentsListBox->GetEntryCount() == 0 && + GetTopLevelSelection()->IsDeletable() ) + { + QueryBox qbox( this, + CUI_RES( QBX_CONFIRM_DELETE_TOOLBAR ) ); + + if ( qbox.Execute() == RET_YES ) + { + DeleteSelectedTopLevel(); + } + } + + return TRUE; + } + + return FALSE; +} + +IMPL_LINK( SvxToolbarConfigPage, MoveHdl, Button *, pButton ) +{ + MoveEntry( pButton == &aMoveUpButton ); + return 0; +} + +void SvxToolbarConfigPage::MoveEntry( bool bMoveUp ) +{ + SvxConfigPage::MoveEntry( bMoveUp ); + + // Apply change to currently selected toolbar + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + if ( pToolbar ) + ((ToolbarSaveInData*)GetSaveInData())->ApplyToolbar( pToolbar ); + else + { + DBG_ERRORFILE( "SvxToolbarConfigPage::MoveEntry(): no entry" ); + UpdateButtonStates(); + } +} + +IMPL_LINK( SvxToolbarConfigPage, ToolbarSelectHdl, MenuButton *, pButton ) +{ + USHORT nSelectionPos = aTopLevelListBox.GetSelectEntryPos(); + + SvxConfigEntry* pToolbar = + (SvxConfigEntry*)aTopLevelListBox.GetEntryData( nSelectionPos ); + + ToolbarSaveInData* pSaveInData = (ToolbarSaveInData*) GetSaveInData(); + + switch( pButton->GetCurItemId() ) + { + case ID_DELETE: + { + DeleteSelectedTopLevel(); + UpdateButtonStates(); + break; + } + case ID_RENAME: + { + String aNewName( stripHotKey( pToolbar->GetName() ) ); + String aDesc = CUI_RESSSTR( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog* pNameDialog = new SvxNameDialog( this, aNewName, aDesc ); + pNameDialog->SetHelpId( HID_SVX_CONFIG_RENAME_TOOLBAR ); + pNameDialog->SetText( CUI_RESSTR( RID_SVXSTR_RENAME_TOOLBAR ) ); + + bool ret = pNameDialog->Execute(); + + if ( ret == RET_OK ) + { + pNameDialog->GetName(aNewName); + + pToolbar->SetName( aNewName ); + pSaveInData->ApplyToolbar( pToolbar ); + + // have to use remove and insert to change the name + aTopLevelListBox.RemoveEntry( nSelectionPos ); + nSelectionPos = + aTopLevelListBox.InsertEntry( aNewName, nSelectionPos ); + aTopLevelListBox.SetEntryData( nSelectionPos, pToolbar ); + aTopLevelListBox.SelectEntryPos( nSelectionPos ); + } + + delete pNameDialog; + + break; + } + case ID_DEFAULT_STYLE: + { + QueryBox qbox( this, + CUI_RES( QBX_CONFIRM_RESTORE_DEFAULT ) ); + + if ( qbox.Execute() == RET_YES ) + { + ToolbarSaveInData* pSaveInData_ = + (ToolbarSaveInData*) GetSaveInData(); + + pSaveInData_->RestoreToolbar( pToolbar ); + + aTopLevelListBox.GetSelectHdl().Call( this ); + } + + break; + } + case ID_ICONS_ONLY: + { + pToolbar->SetStyle( 0 ); + pSaveInData->SetSystemStyle( m_xFrame, pToolbar->GetCommand(), 0 ); + + aTopLevelListBox.GetSelectHdl().Call( this ); + + break; + } + case ID_TEXT_ONLY: + { + pToolbar->SetStyle( 1 ); + pSaveInData->SetSystemStyle( m_xFrame, pToolbar->GetCommand(), 1 ); + + aTopLevelListBox.GetSelectHdl().Call( this ); + + break; + } + case ID_ICONS_AND_TEXT: + { + pToolbar->SetStyle( 2 ); + pSaveInData->SetSystemStyle( m_xFrame, pToolbar->GetCommand(), 2 ); + + aTopLevelListBox.GetSelectHdl().Call( this ); + + break; + } + } + return 1; +} + +IMPL_LINK( SvxToolbarConfigPage, EntrySelectHdl, MenuButton *, pButton ) +{ + bool bNeedsApply = FALSE; + + // get currently selected toolbar + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + + switch( pButton->GetCurItemId() ) + { + case ID_RENAME: + { + SvLBoxEntry* pActEntry = aContentsListBox->GetCurEntry(); + SvxConfigEntry* pEntry = + (SvxConfigEntry*) pActEntry->GetUserData(); + + String aNewName( stripHotKey( pEntry->GetName() ) ); + String aDesc = CUI_RESSSTR( RID_SVXSTR_LABEL_NEW_NAME ); + + SvxNameDialog* pNameDialog = new SvxNameDialog( this, aNewName, aDesc ); + pNameDialog->SetHelpId( HID_SVX_CONFIG_RENAME_TOOLBAR_ITEM ); + pNameDialog->SetText( CUI_RESSTR( RID_SVXSTR_RENAME_TOOLBAR ) ); + + bool ret = pNameDialog->Execute(); + + if ( ret == RET_OK ) { + pNameDialog->GetName(aNewName); + + pEntry->SetName( aNewName ); + aContentsListBox->SetEntryText( pActEntry, aNewName ); + + bNeedsApply = TRUE; + } + + delete pNameDialog; + break; + } + case ID_DEFAULT_COMMAND: + { + SvLBoxEntry* pActEntry = aContentsListBox->GetCurEntry(); + SvxConfigEntry* pEntry = + (SvxConfigEntry*) pActEntry->GetUserData(); + + USHORT nSelectionPos = 0; + + // find position of entry within the list + for ( USHORT i = 0; i < aContentsListBox->GetEntryCount(); i++ ) + { + if ( aContentsListBox->GetEntry( 0, i ) == pActEntry ) + { + nSelectionPos = i; + break; + } + } + + ToolbarSaveInData* pSaveInData = + (ToolbarSaveInData*) GetSaveInData(); + + OUString aSystemName = + pSaveInData->GetSystemUIName( pEntry->GetCommand() ); + + if ( !pEntry->GetName().equals( aSystemName ) ) + { + pEntry->SetName( aSystemName ); + aContentsListBox->SetEntryText( + pActEntry, stripHotKey( aSystemName ) ); + bNeedsApply = TRUE; + } + + uno::Sequence< OUString > aURLSeq( 1 ); + aURLSeq[ 0 ] = pEntry->GetCommand(); + + try + { + GetSaveInData()->GetImageManager()->removeImages( + GetImageType(), aURLSeq ); + + // reset backup in entry + pEntry->SetBackupGraphic( + uno::Reference< graphic::XGraphic >() ); + + GetSaveInData()->PersistChanges( + GetSaveInData()->GetImageManager() ); + + aContentsListBox->GetModel()->Remove( pActEntry ); + + SvLBoxEntry* pNewLBEntry = + InsertEntryIntoUI( pEntry, nSelectionPos ); + + aContentsListBox->SetCheckButtonState( pNewLBEntry, + pEntry->IsVisible() ? + SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED ); + + aContentsListBox->Select( pNewLBEntry ); + aContentsListBox->MakeVisible( pNewLBEntry ); + + bNeedsApply = TRUE; + } + catch ( uno::Exception& ) + { + OSL_TRACE("Error restoring image"); + } + break; + } + case ID_BEGIN_GROUP: + { + SvxConfigEntry* pNewEntryData = new SvxConfigEntry; + pNewEntryData->SetUserDefined( TRUE ); + + SvLBoxEntry* pNewLBEntry = InsertEntry( pNewEntryData ); + + aContentsListBox->SetCheckButtonState( + pNewLBEntry, SV_BUTTON_TRISTATE ); + + bNeedsApply = TRUE; + break; + } + case ID_DELETE: + { + DeleteSelectedContent(); + break; + } + case ID_ICON_ONLY: + { + break; + } + case ID_TEXT_ONLY: + { + break; + } + case ID_ICON_AND_TEXT: + { + break; + } + case ID_CHANGE_SYMBOL: + { + SvLBoxEntry* pActEntry = aContentsListBox->GetCurEntry(); + SvxConfigEntry* pEntry = + (SvxConfigEntry*) pActEntry->GetUserData(); + + USHORT nSelectionPos = 0; + + // find position of entry within the list + for ( USHORT i = 0; i < aContentsListBox->GetEntryCount(); i++ ) + { + if ( aContentsListBox->GetEntry( 0, i ) == pActEntry ) + { + nSelectionPos = i; + break; + } + } + + SvxIconSelectorDialog* pIconDialog = + new SvxIconSelectorDialog( 0, + GetSaveInData()->GetImageManager(), + GetSaveInData()->GetParentImageManager() ); + + bool ret = pIconDialog->Execute(); + + if ( ret == RET_OK ) + { + uno::Reference< graphic::XGraphic > newgraphic = + pIconDialog->GetSelectedIcon(); + + if ( newgraphic.is() ) + { + uno::Sequence< uno::Reference< graphic::XGraphic > > + aGraphicSeq( 1 ); + + uno::Sequence< OUString > aURLSeq( 1 ); + aURLSeq[ 0 ] = pEntry->GetCommand(); + + if ( !pEntry->GetBackupGraphic().is() ) + { + uno::Reference< graphic::XGraphic > backup; + backup = GetGraphic( + GetSaveInData()->GetImageManager(), aURLSeq[ 0 ] ); + + if ( backup.is() ) + { + pEntry->SetBackupGraphic( backup ); + } + } + + aGraphicSeq[ 0 ] = newgraphic; + try + { + GetSaveInData()->GetImageManager()->replaceImages( + GetImageType(), aURLSeq, aGraphicSeq ); + + Image aImage( newgraphic ); + + aContentsListBox->GetModel()->Remove( pActEntry ); + SvLBoxEntry* pNewLBEntry = + InsertEntryIntoUI( pEntry, nSelectionPos ); + + aContentsListBox->SetCheckButtonState( pNewLBEntry, + pEntry->IsVisible() ? + SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED ); + + aContentsListBox->Select( pNewLBEntry ); + aContentsListBox->MakeVisible( pNewLBEntry ); + + GetSaveInData()->PersistChanges( + GetSaveInData()->GetImageManager() ); + } + catch ( uno::Exception& ) + { + OSL_TRACE("Error replacing image"); + } + } + } + + delete pIconDialog; + + break; + } + case ID_RESET_SYMBOL: + { + SvLBoxEntry* pActEntry = aContentsListBox->GetCurEntry(); + SvxConfigEntry* pEntry = + (SvxConfigEntry*) pActEntry->GetUserData(); + + USHORT nSelectionPos = 0; + + // find position of entry within the list + for ( USHORT i = 0; i < aContentsListBox->GetEntryCount(); i++ ) + { + if ( aContentsListBox->GetEntry( 0, i ) == pActEntry ) + { + nSelectionPos = i; + break; + } + } + + uno::Reference< graphic::XGraphic > backup = + pEntry->GetBackupGraphic(); + + uno::Sequence< uno::Reference< graphic::XGraphic > > + aGraphicSeq( 1 ); + aGraphicSeq[ 0 ] = backup; + + uno::Sequence< OUString > aURLSeq( 1 ); + aURLSeq[ 0 ] = pEntry->GetCommand(); + + try + { + GetSaveInData()->GetImageManager()->replaceImages( + GetImageType(), aURLSeq, aGraphicSeq ); + + Image aImage( backup ); + aContentsListBox->GetModel()->Remove( pActEntry ); + + SvLBoxEntry* pNewLBEntry = + InsertEntryIntoUI( pEntry, nSelectionPos ); + + aContentsListBox->SetCheckButtonState( pNewLBEntry, + pEntry->IsVisible() ? + SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED ); + + aContentsListBox->Select( pNewLBEntry ); + aContentsListBox->MakeVisible( pNewLBEntry ); + + // reset backup in entry + pEntry->SetBackupGraphic( + uno::Reference< graphic::XGraphic >() ); + + GetSaveInData()->PersistChanges( + GetSaveInData()->GetImageManager() ); + } + catch ( uno::Exception& ) + { + OSL_TRACE("Error resetting image"); + } + break; + } + } + + if ( bNeedsApply == TRUE ) + { + (( ToolbarSaveInData* ) GetSaveInData())->ApplyToolbar( pToolbar ); + UpdateButtonStates(); + } + + return 1; +} + +void SvxToolbarConfigPage::Init() +{ + // ensure that the UI is cleared before populating it + aTopLevelListBox.Clear(); + aContentsListBox->Clear(); + + ReloadTopLevelListBox(); + + USHORT nPos = 0; + if ( m_aURLToSelect.getLength() != 0 ) + { + for ( USHORT i = 0 ; i < aTopLevelListBox.GetEntryCount(); i++ ) + { + SvxConfigEntry* pData = + (SvxConfigEntry*) aTopLevelListBox.GetEntryData( i ); + + if ( pData->GetCommand().equals( m_aURLToSelect ) ) + { + nPos = i; + break; + } + } + + // in future select the default toolbar: Standard + m_aURLToSelect = OUString::createFromAscii( ITEM_TOOLBAR_URL ); + m_aURLToSelect += OUString::createFromAscii( "standardbar" ); + } + + aTopLevelListBox.SelectEntryPos(nPos, TRUE); + aTopLevelListBox.GetSelectHdl().Call(this); +} + +SaveInData* SvxToolbarConfigPage::CreateSaveInData( + const uno::Reference< css::ui::XUIConfigurationManager >& xCfgMgr, + const uno::Reference< css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool bDocConfig ) +{ + return static_cast< SaveInData* >( + new ToolbarSaveInData( xCfgMgr, xParentCfgMgr, aModuleId, bDocConfig )); +} + +ToolbarSaveInData::ToolbarSaveInData( + const uno::Reference < css::ui::XUIConfigurationManager >& xCfgMgr, + const uno::Reference < css::ui::XUIConfigurationManager >& xParentCfgMgr, + const OUString& aModuleId, + bool docConfig ) : + + SaveInData ( xCfgMgr, xParentCfgMgr, aModuleId, docConfig ), + pRootEntry ( NULL ), + m_aDescriptorContainer ( RTL_CONSTASCII_USTRINGPARAM( ITEM_DESCRIPTOR_CONTAINER ) ) + +{ + // Initialize the m_xPersistentWindowState variable which is used + // to get the default properties of system toolbars such as name + uno::Reference< container::XNameAccess > xPWSS( + m_xServiceManager->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.ui.WindowStateConfiguration" ) ) ), + uno::UNO_QUERY ); + + if ( xPWSS.is() ) + xPWSS->getByName( aModuleId ) >>= m_xPersistentWindowState; +} + +ToolbarSaveInData::~ToolbarSaveInData() +{ + delete pRootEntry; +} + +void ToolbarSaveInData::SetSystemStyle( + uno::Reference< frame::XFrame > xFrame, + const OUString& rResourceURL, + sal_Int32 nStyle ) +{ + // change the style using the API + SetSystemStyle( rResourceURL, nStyle ); + + // this code is a temporary hack as the UI is not updating after + // changing the toolbar style via the API + uno::Reference< css::frame::XLayoutManager > xLayoutManager; + Window *window = NULL; + + uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + uno::Any a = xPropSet->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ) ) ); + a >>= xLayoutManager; + } + + if ( xLayoutManager.is() ) + { + uno::Reference< css::ui::XUIElement > xUIElement = + xLayoutManager->getElement( rResourceURL ); + + // check reference before we call getRealInterface. The layout manager + // can only provide references for elements that have been created + // before. It's possible that the current element is not available. + uno::Reference< com::sun::star::awt::XWindow > xWindow; + if ( xUIElement.is() ) + xWindow = uno::Reference< com::sun::star::awt::XWindow >( + xUIElement->getRealInterface(), uno::UNO_QUERY ); + + window = VCLUnoHelper::GetWindow( xWindow ); + } + + if ( window != NULL && window->GetType() == WINDOW_TOOLBOX ) + { + ToolBox* toolbox = (ToolBox*)window; + + if ( nStyle == 0 ) + { + toolbox->SetButtonType( BUTTON_SYMBOL ); + } + else if ( nStyle == 1 ) + { + toolbox->SetButtonType( BUTTON_TEXT ); + } + if ( nStyle == 2 ) + { + toolbox->SetButtonType( BUTTON_SYMBOLTEXT ); + } + } +} + +void ToolbarSaveInData::SetSystemStyle( + const OUString& rResourceURL, + sal_Int32 nStyle ) +{ + if ( rResourceURL.indexOf( OUString::createFromAscii( "private" ) ) == 0 && + m_xPersistentWindowState.is() && + m_xPersistentWindowState->hasByName( rResourceURL ) ) + { + try + { + uno::Sequence< beans::PropertyValue > aProps; + + uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) ); + + if ( a >>= aProps ) + { + for ( sal_Int32 i = 0; i < aProps.getLength(); i++ ) + { + if ( aProps[ i ].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE) ) + { + aProps[ i ].Value = uno::makeAny( nStyle ); + break; + } + } + } + + uno::Reference< container::XNameReplace > + xNameReplace( m_xPersistentWindowState, uno::UNO_QUERY ); + + xNameReplace->replaceByName( rResourceURL, uno::makeAny( aProps ) ); + } + catch ( uno::Exception& ) + { + // do nothing, a default value is returned + OSL_TRACE("Exception setting toolbar style"); + } + } +} + +sal_Int32 ToolbarSaveInData::GetSystemStyle( const OUString& rResourceURL ) +{ + sal_Int32 result = 0; + + if ( rResourceURL.indexOf( OUString::createFromAscii( "private" ) ) == 0 && + m_xPersistentWindowState.is() && + m_xPersistentWindowState->hasByName( rResourceURL ) ) + { + try + { + uno::Sequence< beans::PropertyValue > aProps; + uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) ); + + if ( a >>= aProps ) + { + for ( sal_Int32 i = 0; i < aProps.getLength(); i++ ) + { + if ( aProps[ i ].Name.equalsAscii( ITEM_DESCRIPTOR_STYLE) ) + { + aProps[i].Value >>= result; + break; + } + } + } + } + catch ( uno::Exception& ) + { + // do nothing, a default value is returned + } + } + + return result; +} + +OUString ToolbarSaveInData::GetSystemUIName( const OUString& rResourceURL ) +{ + OUString result; + + if ( rResourceURL.indexOf( OUString::createFromAscii( "private" ) ) == 0 && + m_xPersistentWindowState.is() && + m_xPersistentWindowState->hasByName( rResourceURL ) ) + { + try + { + uno::Sequence< beans::PropertyValue > aProps; + uno::Any a( m_xPersistentWindowState->getByName( rResourceURL ) ); + + if ( a >>= aProps ) + { + for ( sal_Int32 i = 0; i < aProps.getLength(); i++ ) + { + if ( aProps[ i ].Name.equalsAscii( ITEM_DESCRIPTOR_UINAME) ) + { + aProps[ i ].Value >>= result; + } + } + } + } + catch ( uno::Exception& ) + { + // do nothing, an empty UIName will be returned + } + } + + if ( rResourceURL.indexOf( OUString::createFromAscii( ".uno" ) ) == 0 && + m_xCommandToLabelMap.is() && + m_xCommandToLabelMap->hasByName( rResourceURL ) ) + { + uno::Any a; + try + { + a = m_xCommandToLabelMap->getByName( rResourceURL ); + + uno::Sequence< beans::PropertyValue > aPropSeq; + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL ) ) + { + aPropSeq[i].Value >>= result; + } + } + } + } + catch ( uno::Exception& ) + { + // not a system command name + } + } + + return result; +} + +bool EntrySort( SvxConfigEntry* a, SvxConfigEntry* b ) +{ + return a->GetName().compareTo( b->GetName() ) < 0; +} + +SvxEntries* ToolbarSaveInData::GetEntries() +{ + typedef ::std::hash_map< ::rtl::OUString, + bool, + ::rtl::OUStringHash, + ::std::equal_to< ::rtl::OUString > > ToolbarInfo; + + ToolbarInfo aToolbarInfo; + + if ( pRootEntry == NULL ) + { + + pRootEntry = new SvxConfigEntry( + String::CreateFromAscii("MainToolbars"), String(), TRUE ); + + uno::Sequence< uno::Sequence < beans::PropertyValue > > info = + GetConfigManager()->getUIElementsInfo( + css::ui::UIElementType::TOOLBAR ); + + for ( sal_Int32 i = 0; i < info.getLength(); i++ ) + { + uno::Sequence< beans::PropertyValue > props = info[ i ]; + + OUString url; + OUString systemname; + OUString uiname; + + for ( sal_Int32 j = 0; j < props.getLength(); j++ ) + { + if ( props[ j ].Name.equalsAscii( ITEM_DESCRIPTOR_RESOURCEURL) ) + { + props[ j ].Value >>= url; + systemname = url.copy( url.lastIndexOf( '/' ) + 1 ); + } + else if ( props[ j ].Name.equalsAscii( ITEM_DESCRIPTOR_UINAME) ) + { + props[ j ].Value >>= uiname; + } + } + + try + { + uno::Reference< container::XIndexAccess > xToolbarSettings = + GetConfigManager()->getSettings( url, sal_False ); + + if ( uiname.getLength() == 0 ) + { + // try to get the name from m_xPersistentWindowState + uiname = GetSystemUIName( url ); + + if ( uiname.getLength() == 0 ) + { + uiname = systemname; + } + } + + SvxConfigEntry* pEntry = new SvxConfigEntry( + uiname, url, TRUE ); + + pEntry->SetMain( TRUE ); + pEntry->SetStyle( GetSystemStyle( url ) ); + + + // insert into hash_map to filter duplicates from the parent + aToolbarInfo.insert( ToolbarInfo::value_type( systemname, true )); + + OUString custom = OUString::createFromAscii(CUSTOM_TOOLBAR_STR); + if ( systemname.indexOf( custom ) == 0 ) + { + pEntry->SetUserDefined( TRUE ); + } + else + { + pEntry->SetUserDefined( FALSE ); + } + + pRootEntry->GetEntries()->push_back( pEntry ); + + LoadToolbar( xToolbarSettings, pEntry ); + } + catch ( container::NoSuchElementException& ) + { + // TODO, handle resourceURL with no settings + } + } + + uno::Reference< css::ui::XUIConfigurationManager > xParentCfgMgr = GetParentConfigManager(); + if ( xParentCfgMgr.is() ) + { + // Retrieve also the parent toolbars to make it possible + // to configure module toolbars and save them into the document + // config manager. + uno::Sequence< uno::Sequence < beans::PropertyValue > > info_ = + xParentCfgMgr->getUIElementsInfo( + css::ui::UIElementType::TOOLBAR ); + + for ( sal_Int32 i = 0; i < info_.getLength(); i++ ) + { + uno::Sequence< beans::PropertyValue > props = info_[ i ]; + + OUString url; + OUString systemname; + OUString uiname; + + for ( sal_Int32 j = 0; j < props.getLength(); j++ ) + { + if ( props[ j ].Name.equalsAscii( ITEM_DESCRIPTOR_RESOURCEURL) ) + { + props[ j ].Value >>= url; + systemname = url.copy( url.lastIndexOf( '/' ) + 1 ); + } + else if ( props[ j ].Name.equalsAscii( ITEM_DESCRIPTOR_UINAME) ) + { + props[ j ].Value >>= uiname; + } + } + + // custom toolbars of the parent are not visible in the document layer + OUString custom = OUString::createFromAscii(CUSTOM_TOOLBAR_STR); + if ( systemname.indexOf( custom ) == 0 ) + continue; + + // check if toolbar is already in the document layer + ToolbarInfo::const_iterator pIter = aToolbarInfo.find( systemname ); + if ( pIter == aToolbarInfo.end() ) + { + aToolbarInfo.insert( ToolbarInfo::value_type( systemname, true )); + + try + { + uno::Reference< container::XIndexAccess > xToolbarSettings = + xParentCfgMgr->getSettings( url, sal_False ); + + if ( uiname.getLength() == 0 ) + { + // try to get the name from m_xPersistentWindowState + uiname = GetSystemUIName( url ); + + if ( uiname.getLength() == 0 ) + { + uiname = systemname; + } + } + + SvxConfigEntry* pEntry = new SvxConfigEntry( + uiname, url, TRUE, TRUE ); + + pEntry->SetMain( TRUE ); + pEntry->SetStyle( GetSystemStyle( url ) ); + + if ( systemname.indexOf( custom ) == 0 ) + { + pEntry->SetUserDefined( TRUE ); + } + else + { + pEntry->SetUserDefined( FALSE ); + } + + pRootEntry->GetEntries()->push_back( pEntry ); + + LoadToolbar( xToolbarSettings, pEntry ); + } + catch ( container::NoSuchElementException& ) + { + // TODO, handle resourceURL with no settings + } + } + } + } + + std::sort( GetEntries()->begin(), GetEntries()->end(), EntrySort ); + } + + return pRootEntry->GetEntries(); +} + +void +ToolbarSaveInData::SetEntries( SvxEntries* pNewEntries ) +{ + // delete old menu hierarchy first + if ( pRootEntry != NULL && pRootEntry->GetEntries() != NULL ) + { + delete pRootEntry->GetEntries(); + } + + // now set new menu hierarchy + pRootEntry->SetEntries( pNewEntries ); +} + +bool +ToolbarSaveInData::HasURL( const OUString& rURL ) +{ + SvxEntries::const_iterator iter = GetEntries()->begin(); + SvxEntries::const_iterator end = GetEntries()->end(); + + while ( iter != end ) + { + SvxConfigEntry* pEntry = *iter; + + if ( pEntry->GetCommand().equals( rURL ) ) + { + if ( pEntry->IsParentData() ) + return FALSE; + else + return TRUE; + } + + iter++; + } + return FALSE; +} + +bool ToolbarSaveInData::HasSettings() +{ + // return true if there is at least one toolbar entry + if ( GetEntries()->size() > 0 ) + { + return TRUE; + } + return FALSE; +} + +void ToolbarSaveInData::Reset() +{ + SvxEntries::const_iterator toolbars = GetEntries()->begin(); + SvxEntries::const_iterator end = GetEntries()->end(); + + // reset each toolbar by calling removeSettings for it's toolbar URL + for ( ; toolbars != end; toolbars++ ) + { + SvxConfigEntry* pToolbar = *toolbars; + + try + { + OUString url = pToolbar->GetCommand(); + GetConfigManager()->removeSettings( url ); + } + catch ( uno::Exception& ) + { + // error occured removing the settings + // TODO - add error dialog in future? + } + } + + // persist changes to toolbar storage + PersistChanges( GetConfigManager() ); + + // now delete the root SvxConfigEntry the next call to GetEntries() + // causes it to be reinitialised + delete pRootEntry; + pRootEntry = NULL; + + // reset all icons to default + try + { + GetImageManager()->reset(); + PersistChanges( GetImageManager() ); + } + catch ( uno::Exception& ) + { + OSL_TRACE("Error resetting all icons when resetting toolbars"); + } +} + +bool ToolbarSaveInData::Apply() +{ + // toolbar changes are instantly applied + return FALSE; +} + +void ToolbarSaveInData::ApplyToolbar( + uno::Reference< container::XIndexContainer >& rToolbarBar, + uno::Reference< lang::XSingleComponentFactory >& rFactory, + SvxConfigEntry* pToolbarData ) +{ + SvxEntries::const_iterator iter = pToolbarData->GetEntries()->begin(); + SvxEntries::const_iterator end = pToolbarData->GetEntries()->end(); + + for ( ; iter != end; iter++ ) + { + SvxConfigEntry* pEntry = *iter; + + if ( pEntry->IsPopup() ) + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + ConvertToolbarEntry( m_xCommandToLabelMap, pEntry ); + + uno::Reference< container::XIndexContainer > xSubMenuBar( + rFactory->createInstanceWithContext( m_xComponentContext ), + uno::UNO_QUERY ); + + sal_Int32 nIndex = aPropValueSeq.getLength(); + aPropValueSeq.realloc( nIndex + 1 ); + aPropValueSeq[nIndex].Name = m_aDescriptorContainer; + aPropValueSeq[nIndex].Value <<= xSubMenuBar; + rToolbarBar->insertByIndex( + rToolbarBar->getCount(), uno::makeAny( aPropValueSeq )); + + ApplyToolbar( xSubMenuBar, rFactory, pEntry ); + } + else if ( pEntry->IsSeparator() ) + { + rToolbarBar->insertByIndex( + rToolbarBar->getCount(), uno::makeAny( m_aSeparatorSeq )); + } + else + { + uno::Sequence< beans::PropertyValue > aPropValueSeq = + ConvertToolbarEntry( m_xCommandToLabelMap, pEntry ); + + rToolbarBar->insertByIndex( + rToolbarBar->getCount(), uno::makeAny( aPropValueSeq )); + } + } +} + +void ToolbarSaveInData::ApplyToolbar( SvxConfigEntry* pToolbar ) +{ + // Apply new toolbar structure to our settings container + uno::Reference< container::XIndexAccess > xSettings( + GetConfigManager()->createSettings(), uno::UNO_QUERY ); + + uno::Reference< container::XIndexContainer > xIndexContainer ( + xSettings, uno::UNO_QUERY ); + + uno::Reference< lang::XSingleComponentFactory > xFactory ( + xSettings, uno::UNO_QUERY ); + + ApplyToolbar( xIndexContainer, xFactory, pToolbar ); + + uno::Reference< beans::XPropertySet > xProps( + xSettings, uno::UNO_QUERY ); + + if ( pToolbar->IsUserDefined() ) + { + xProps->setPropertyValue( + OUString::createFromAscii( ITEM_DESCRIPTOR_UINAME ), + uno::makeAny( OUString( pToolbar->GetName() ) ) ); + } + + try + { + if ( GetConfigManager()->hasSettings( pToolbar->GetCommand() ) ) + { + GetConfigManager()->replaceSettings( + pToolbar->GetCommand(), xSettings ); + } + else + { + GetConfigManager()->insertSettings( + pToolbar->GetCommand(), xSettings ); + if ( pToolbar->IsParentData() ) + pToolbar->SetParentData( false ); + } + } + catch ( container::NoSuchElementException& ) + { + OSL_TRACE("caught container::NoSuchElementException saving settings"); + } + catch ( com::sun::star::io::IOException& ) + { + OSL_TRACE("caught IOException saving settings"); + } + catch ( com::sun::star::uno::Exception& ) + { + OSL_TRACE("caught some other exception saving settings"); + } + + PersistChanges( GetConfigManager() ); +} + +void ToolbarSaveInData::CreateToolbar( SvxConfigEntry* pToolbar ) +{ + // show the new toolbar in the UI also + uno::Reference< container::XIndexAccess > + xSettings( GetConfigManager()->createSettings(), uno::UNO_QUERY ); + + uno::Reference< container::XIndexContainer > + xIndexContainer ( xSettings, uno::UNO_QUERY ); + + uno::Reference< beans::XPropertySet > + xPropertySet( xSettings, uno::UNO_QUERY ); + + xPropertySet->setPropertyValue( + OUString::createFromAscii( ITEM_DESCRIPTOR_UINAME ), + uno::makeAny( pToolbar->GetName() ) ); + + try + { + GetConfigManager()->insertSettings( pToolbar->GetCommand(), xSettings ); + } + catch ( container::ElementExistException& ) + { + OSL_TRACE("caught ElementExistsException saving settings"); + } + catch ( com::sun::star::lang::IllegalArgumentException& ) + { + OSL_TRACE("caught IOException saving settings"); + } + catch ( com::sun::star::lang::IllegalAccessException& ) + { + OSL_TRACE("caught IOException saving settings"); + } + catch ( com::sun::star::uno::Exception& ) + { + OSL_TRACE("caught some other exception saving settings"); + } + + GetEntries()->push_back( pToolbar ); + + PersistChanges( GetConfigManager() ); +} + +void ToolbarSaveInData::RemoveToolbar( SvxConfigEntry* pToolbar ) +{ + try + { + OUString url = pToolbar->GetCommand(); + GetConfigManager()->removeSettings( url ); + RemoveEntry( GetEntries(), pToolbar ); + delete pToolbar; + + PersistChanges( GetConfigManager() ); + + // remove the persistent window state data + css::uno::Reference< css::container::XNameContainer > xNameContainer( + m_xPersistentWindowState, css::uno::UNO_QUERY_THROW ); + + xNameContainer->removeByName( url ); + } + catch ( uno::Exception& ) + { + // error occured removing the settings + } +} + +void ToolbarSaveInData::RestoreToolbar( SvxConfigEntry* pToolbar ) +{ + OUString url = pToolbar->GetCommand(); + + // Restore of toolbar is done by removing it from + // it's configuration manager and then getting it again + bool bParentToolbar = pToolbar->IsParentData(); + + // Cannot restore parent toolbar + if ( bParentToolbar ) + return; + + try + { + GetConfigManager()->removeSettings( url ); + pToolbar->GetEntries()->clear(); + PersistChanges( GetConfigManager() ); + } + catch ( uno::Exception& ) + { + // if an error occurs removing the settings then just return + return; + } + + // Now reload the toolbar settings + try + { + uno::Reference< container::XIndexAccess > xToolbarSettings; + if ( IsDocConfig() ) + { + xToolbarSettings = GetParentConfigManager()->getSettings( url, sal_False ); + pToolbar->SetParentData( true ); + } + else + xToolbarSettings = GetConfigManager()->getSettings( url, sal_False ); + + LoadToolbar( xToolbarSettings, pToolbar ); + + // After reloading, ensure that the icon is reset of each entry + // in the toolbar + SvxEntries::const_iterator iter = pToolbar->GetEntries()->begin(); + uno::Sequence< OUString > aURLSeq( 1 ); + for ( ; iter != pToolbar->GetEntries()->end(); iter++ ) + { + SvxConfigEntry* pEntry = *iter; + aURLSeq[ 0 ] = pEntry->GetCommand(); + + try + { + GetImageManager()->removeImages( GetImageType(), aURLSeq ); + } + catch ( uno::Exception& ) + { + OSL_TRACE("Error restoring icon when resetting toolbar"); + } + } + PersistChanges( GetImageManager() ); + } + catch ( container::NoSuchElementException& ) + { + // cannot find the resource URL after removing it + // so no entry will appear in the toolbar list + } +} + +void ToolbarSaveInData::ReloadToolbar( const OUString& rResourceURL ) +{ + SvxEntries::const_iterator iter = GetEntries()->begin(); + SvxConfigEntry* pToolbar = NULL; + + for ( ; iter != GetEntries()->end(); iter++ ) + { + SvxConfigEntry* pEntry = *iter; + + if ( pEntry->GetCommand().equals( rResourceURL ) ) + { + pToolbar = pEntry; + break; + } + } + + if ( pToolbar != NULL ) + { + delete pToolbar->GetEntries(); + + try + { + uno::Reference< container::XIndexAccess > xToolbarSettings; + + if ( pToolbar->IsParentData() ) + { + xToolbarSettings = GetParentConfigManager()->getSettings( + pToolbar->GetCommand(), sal_False); + } + else + { + xToolbarSettings = GetConfigManager()->getSettings( + pToolbar->GetCommand(), sal_False); + } + + LoadToolbar( xToolbarSettings, pToolbar ); + } + catch ( container::NoSuchElementException& ) + { + // toolbar not found for some reason + // it will not appear in the toolbar list + } + } +} + +bool ToolbarSaveInData::LoadToolbar( + const uno::Reference< container::XIndexAccess >& xToolbarSettings, + SvxConfigEntry* pParentData ) +{ + SvxEntries* pEntries = pParentData->GetEntries(); + + for ( sal_Int32 nIndex = 0; nIndex < xToolbarSettings->getCount(); nIndex++ ) + { + uno::Reference< container::XIndexAccess > xSubMenu; + OUString aCommandURL; + OUString aHelpURL; + OUString aLabel; + bool bIsUserDefined = TRUE; + sal_Bool bIsVisible; + sal_Int32 nStyle; + + sal_uInt16 nType( css::ui::ItemType::DEFAULT ); + + bool bItem = GetToolbarItemData( xToolbarSettings, nIndex, aCommandURL, + aHelpURL, aLabel, nType, bIsVisible, nStyle, xSubMenu ); + + if ( bItem ) + { + if ( nType == css::ui::ItemType::DEFAULT ) + { + uno::Any a; + try + { + a = m_xCommandToLabelMap->getByName( aCommandURL ); + bIsUserDefined = FALSE; + } + catch ( container::NoSuchElementException& ) + { + bIsUserDefined = TRUE; + } + + // If custom label not set retrieve it from the command + // to info service + if ( aLabel.equals( OUString() ) ) + { + uno::Sequence< beans::PropertyValue > aPropSeq; + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( ITEM_DESCRIPTOR_LABEL ) ) + { + aPropSeq[i].Value >>= aLabel; + break; + } + } + } + } + + if ( xSubMenu.is() ) + { + SvxConfigEntry* pEntry = new SvxConfigEntry( + aLabel, aCommandURL, TRUE ); + + pEntry->SetUserDefined( bIsUserDefined ); + pEntry->SetHelpURL( aHelpURL ); + pEntry->SetVisible( bIsVisible ); + + pEntries->push_back( pEntry ); + + LoadToolbar( xSubMenu, pEntry ); + } + else + { + SvxConfigEntry* pEntry = new SvxConfigEntry( + aLabel, aCommandURL, FALSE ); + pEntry->SetUserDefined( bIsUserDefined ); + pEntry->SetHelpURL( aHelpURL ); + pEntry->SetVisible( bIsVisible ); + pEntry->SetStyle( nStyle ); + pEntries->push_back( pEntry ); + } + } + else + { + SvxConfigEntry* pEntry = new SvxConfigEntry; + pEntry->SetUserDefined( bIsUserDefined ); + pEntries->push_back( pEntry ); + } + } + } + + return true; +} + +IMPL_LINK( SvxToolbarConfigPage, SelectToolbarEntry, Control *, pBox ) +{ + (void)pBox; + UpdateButtonStates(); + return 1; +} + +void SvxToolbarConfigPage::UpdateButtonStates() +{ + PopupMenu* pPopup = aModifyCommandButton.GetPopupMenu(); + pPopup->EnableItem( ID_RENAME, FALSE ); + pPopup->EnableItem( ID_DELETE, FALSE ); + pPopup->EnableItem( ID_BEGIN_GROUP, FALSE ); + pPopup->EnableItem( ID_DEFAULT_COMMAND, FALSE ); + pPopup->EnableItem( ID_ICON_ONLY, FALSE ); + pPopup->EnableItem( ID_ICON_AND_TEXT, FALSE ); + pPopup->EnableItem( ID_TEXT_ONLY, FALSE ); + pPopup->EnableItem( ID_CHANGE_SYMBOL, FALSE ); + pPopup->EnableItem( ID_RESET_SYMBOL, FALSE ); + + aDescriptionField.Clear(); + + SvLBoxEntry* selection = aContentsListBox->GetCurEntry(); + if ( aContentsListBox->GetEntryCount() == 0 || selection == NULL ) + { + return; + } + + SvxConfigEntry* pEntryData = (SvxConfigEntry*) selection->GetUserData(); + if ( pEntryData->IsSeparator() ) + pPopup->EnableItem( ID_DELETE, TRUE ); + else + { + pPopup->EnableItem( ID_BEGIN_GROUP, TRUE ); + pPopup->EnableItem( ID_DELETE, TRUE ); + pPopup->EnableItem( ID_RENAME, TRUE ); + pPopup->EnableItem( ID_ICON_ONLY, TRUE ); + pPopup->EnableItem( ID_ICON_AND_TEXT, TRUE ); + pPopup->EnableItem( ID_TEXT_ONLY, TRUE ); + pPopup->EnableItem( ID_CHANGE_SYMBOL, TRUE ); + + if ( !pEntryData->IsUserDefined() ) + pPopup->EnableItem( ID_DEFAULT_COMMAND, TRUE ); + + if ( pEntryData->IsIconModified() ) + pPopup->EnableItem( ID_RESET_SYMBOL, TRUE ); + + aDescriptionField.SetNewText( pEntryData->GetHelpText() ); + } +} + +short SvxToolbarConfigPage::QueryReset() +{ + String msg = + String( CUI_RES( RID_SVXSTR_CONFIRM_TOOLBAR_RESET ) ); + + String saveInName = aSaveInListBox.GetEntry( + aSaveInListBox.GetSelectEntryPos() ); + + OUString label = replaceSaveInName( msg, saveInName ); + + QueryBox qbox( this, WB_YES_NO, label ); + + return qbox.Execute(); +} + +IMPL_LINK( SvxToolbarConfigPage, SelectToolbar, ListBox *, pBox ) +{ + (void)pBox; + + aContentsListBox->Clear(); + + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + if ( pToolbar == NULL ) + { + aModifyTopLevelButton.Enable( FALSE ); + aModifyCommandButton.Enable( FALSE ); + aAddCommandsButton.Enable( FALSE ); + + return 0; + } + + aModifyTopLevelButton.Enable( TRUE ); + aModifyCommandButton.Enable( TRUE ); + aAddCommandsButton.Enable( TRUE ); + + PopupMenu* pPopup = aModifyTopLevelButton.GetPopupMenu(); + + pPopup->EnableItem( ID_DELETE, pToolbar->IsDeletable() ); + pPopup->EnableItem( ID_RENAME, pToolbar->IsRenamable() ); + pPopup->EnableItem( ID_DEFAULT_STYLE, !pToolbar->IsRenamable() ); + + switch( pToolbar->GetStyle() ) + { + case 0: + { + pPopup->CheckItem( ID_ICONS_ONLY ); + break; + } + case 1: + { + pPopup->CheckItem( ID_TEXT_ONLY ); + break; + } + case 2: + { + pPopup->CheckItem( ID_ICONS_AND_TEXT ); + break; + } + } + + SvxEntries* pEntries = pToolbar->GetEntries(); + SvxEntries::const_iterator iter = pEntries->begin(); + + for ( ; iter != pEntries->end(); iter++ ) + { + SvxConfigEntry* pEntry = *iter; + + SvLBoxEntry* pNewLBEntry = InsertEntryIntoUI( pEntry ); + + if (pEntry->IsBinding()) + { + aContentsListBox->SetCheckButtonState( pNewLBEntry, + pEntry->IsVisible() ? SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED ); + } + else + { + aContentsListBox->SetCheckButtonState( + pNewLBEntry, SV_BUTTON_TRISTATE ); + } + } + + UpdateButtonStates(); + + return 0; +} + +IMPL_LINK( SvxToolbarConfigPage, NewToolbarHdl, Button *, pButton ) +{ + (void)pButton; + + String prefix = + String( CUI_RES( RID_SVXSTR_NEW_TOOLBAR ) ); + + OUString aNewName = + generateCustomName( prefix, GetSaveInData()->GetEntries() ); + + OUString aNewURL = + generateCustomURL( GetSaveInData()->GetEntries() ); + + SvxNewToolbarDialog* pNameDialog = new SvxNewToolbarDialog( 0, aNewName ); + + USHORT nInsertPos; + for ( USHORT i = 0 ; i < aSaveInListBox.GetEntryCount(); i++ ) + { + SaveInData* pData = + (SaveInData*) aSaveInListBox.GetEntryData( i ); + + nInsertPos = pNameDialog->aSaveInListBox.InsertEntry( + aSaveInListBox.GetEntry( i ) ); + + pNameDialog->aSaveInListBox.SetEntryData( nInsertPos, pData ); + } + + pNameDialog->aSaveInListBox.SelectEntryPos( + aSaveInListBox.GetSelectEntryPos(), TRUE ); + + bool ret = pNameDialog->Execute(); + if ( ret == RET_OK ) + { + pNameDialog->GetName( aNewName ); + + nInsertPos = pNameDialog->aSaveInListBox.GetSelectEntryPos(); + + ToolbarSaveInData* pData = (ToolbarSaveInData*) + pNameDialog->aSaveInListBox.GetEntryData( nInsertPos ); + + if ( GetSaveInData() != pData ) + { + aSaveInListBox.SelectEntryPos( nInsertPos, TRUE ); + aSaveInListBox.GetSelectHdl().Call(this); + } + + SvxConfigEntry* pToolbar = + new SvxConfigEntry( aNewName, aNewURL, TRUE ); + + pToolbar->SetUserDefined( TRUE ); + pToolbar->SetMain( TRUE ); + + pData->CreateToolbar( pToolbar ); + + nInsertPos = aTopLevelListBox.InsertEntry( pToolbar->GetName() ); + aTopLevelListBox.SetEntryData( nInsertPos, pToolbar ); + aTopLevelListBox.SelectEntryPos( nInsertPos, TRUE ); + aTopLevelListBox.GetSelectHdl().Call(this); + + pData->SetModified( TRUE ); + } + + delete pNameDialog; + + return 0; +} + +IMPL_LINK( SvxToolbarConfigPage, AddCommandsHdl, Button *, pButton ) +{ + (void)pButton; + + if ( pSelectorDlg == NULL ) + { + // Create Script Selector which shows slot commands + pSelectorDlg = new SvxScriptSelectorDialog( this, TRUE, m_xFrame ); + + // Position the Script Selector over the Add button so it is + // beside the menu contents list and does not obscure it + pSelectorDlg->SetPosPixel( aAddCommandsButton.GetPosPixel() ); + + pSelectorDlg->SetAddHdl( + LINK( this, SvxToolbarConfigPage, AddFunctionHdl ) ); + } + + pSelectorDlg->SetImageProvider( + static_cast< ImageProvider* >( GetSaveInData() ) ); + + pSelectorDlg->Show(); + return 1; +} + +IMPL_LINK( SvxToolbarConfigPage, AddFunctionHdl, + SvxScriptSelectorDialog *, pDialog ) +{ + (void)pDialog; + + AddFunction(); + + return 0; +} + +SvLBoxEntry* SvxToolbarConfigPage::AddFunction( + SvLBoxEntry* pTarget, bool bFront, bool bAllowDuplicates ) +{ + SvLBoxEntry* pNewLBEntry = + SvxConfigPage::AddFunction( pTarget, bFront, bAllowDuplicates ); + + SvxConfigEntry* pEntry = (SvxConfigEntry*) pNewLBEntry->GetUserData(); + + if ( pEntry->IsBinding() ) + { + pEntry->SetVisible( TRUE ); + aContentsListBox->SetCheckButtonState( + pNewLBEntry, SV_BUTTON_CHECKED ); + } + else + { + aContentsListBox->SetCheckButtonState( + pNewLBEntry, SV_BUTTON_TRISTATE ); + } + + // get currently selected toolbar and apply change + SvxConfigEntry* pToolbar = GetTopLevelSelection(); + + if ( pToolbar != NULL ) + { + ( ( ToolbarSaveInData* ) GetSaveInData() )->ApplyToolbar( pToolbar ); + } + + return pNewLBEntry; +} + +// ----------------------------------------------------------------------- + +SvxToolbarEntriesListBox::SvxToolbarEntriesListBox( + Window* pParent, const ResId& aResId ) + : + SvxMenuEntriesListBox( pParent, aResId ), + pPage( ( SvxToolbarConfigPage* ) pParent ) +{ + m_pButtonData = new SvLBoxButtonData( this ); + BuildCheckBoxButtonImages( m_pButtonData ); + EnableCheckButton( m_pButtonData ); + + m_bHiContrastMode = GetSettings().GetStyleSettings().GetHighContrastMode(); +} + +// -------------------------------------------------------- + +SvxToolbarEntriesListBox::~SvxToolbarEntriesListBox() +{ + delete m_pButtonData; +} + +// -------------------------------------------------------- + +void SvxToolbarEntriesListBox::BuildCheckBoxButtonImages( SvLBoxButtonData* pData ) +{ + // Build checkbox images according to the current application + // settings. This is necessary to be able to have correct colors + // in all color modes, like high contrast. + const AllSettings& rSettings = Application::GetSettings(); + + VirtualDevice aDev; + Size aSize( 26, 20 ); + + aDev.SetOutputSizePixel( aSize ); + + Image aImage = GetSizedImage( aDev, aSize, + CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_DEFAULT )); + + // Fill button data struct with new images + pData->aBmps[SV_BMP_UNCHECKED] = aImage; + pData->aBmps[SV_BMP_CHECKED] = GetSizedImage( aDev, aSize, CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_CHECKED )); + pData->aBmps[SV_BMP_HICHECKED] = GetSizedImage( aDev, aSize, CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_CHECKED | BUTTON_DRAW_PRESSED )); + pData->aBmps[SV_BMP_HIUNCHECKED] = GetSizedImage( aDev, aSize, CheckBox::GetCheckImage( rSettings, BUTTON_DRAW_DEFAULT | BUTTON_DRAW_PRESSED)); + pData->aBmps[SV_BMP_TRISTATE] = GetSizedImage( aDev, aSize, Image() ); // Use tristate bitmaps to have no checkbox for separator entries + pData->aBmps[SV_BMP_HITRISTATE] = GetSizedImage( aDev, aSize, Image() ); + + // Get image size + m_aCheckBoxImageSizePixel = aImage.GetSizePixel(); +} + +Image SvxToolbarEntriesListBox::GetSizedImage( + VirtualDevice& aDev, const Size& aNewSize, const Image& aImage ) +{ + // Create new checkbox images for treelistbox. They must have a + // decent width to have a clear column for the visibility checkbox. + + // Standard transparent color is light magenta as is won't be + // used for other things + Color aFillColor( COL_LIGHTMAGENTA ); + + // Position image at the center of (width-2),(height) rectangle. + // We need 2 pixels to have a bigger border to the next button image + USHORT nPosX = std::max( (USHORT) (((( aNewSize.Width() - 2 ) - aImage.GetSizePixel().Width() ) / 2 ) - 1), (USHORT) 0 ); + USHORT nPosY = std::max( (USHORT) (((( aNewSize.Height() - 2 ) - aImage.GetSizePixel().Height() ) / 2 ) + 1), (USHORT) 0 ); + Point aPos( nPosX > 0 ? nPosX : 0, nPosY > 0 ? nPosY : 0 ); + aDev.SetFillColor( aFillColor ); + aDev.SetLineColor( aFillColor ); + aDev.DrawRect( Rectangle( Point(), aNewSize )); + aDev.DrawImage( aPos, aImage ); + + // Draw separator line 2 pixels left from the right border + Color aLineColor = GetDisplayBackground().GetColor().IsDark() ? Color( COL_WHITE ) : Color( COL_BLACK ); + aDev.SetLineColor( aLineColor ); + aDev.DrawLine( Point( aNewSize.Width()-3, 0 ), Point( aNewSize.Width()-3, aNewSize.Height()-1 )); + + // Create new image that uses the fillcolor as transparent + return Image( aDev.GetBitmap( Point(), aNewSize ), aFillColor ); +} + +void SvxToolbarEntriesListBox::DataChanged( const DataChangedEvent& rDCEvt ) +{ + SvTreeListBox::DataChanged( rDCEvt ); + + if (( rDCEvt.GetType() == DATACHANGED_SETTINGS ) && + ( rDCEvt.GetFlags() & SETTINGS_STYLE )) + { + // We have to reset all images because we change to/from high contrast mode + m_bHiContrastMode = GetSettings().GetStyleSettings().GetHighContrastMode(); + + BuildCheckBoxButtonImages( m_pButtonData ); + Invalidate(); + } +} + +// -------------------------------------------------------- + +void SvxToolbarEntriesListBox::ChangeVisibility( SvLBoxEntry* pEntry ) +{ + if ( pEntry != NULL ) + { + SvxConfigEntry* pEntryData = + (SvxConfigEntry*) pEntry->GetUserData(); + + if ( pEntryData->IsBinding() ) + { + pEntryData->SetVisible( !pEntryData->IsVisible() ); + + SvxConfigEntry* pToolbar = pPage->GetTopLevelSelection(); + + ToolbarSaveInData* pToolbarSaveInData = ( ToolbarSaveInData* ) + pPage->GetSaveInData(); + + pToolbarSaveInData->ApplyToolbar( pToolbar ); + + SetCheckButtonState( pEntry, pEntryData->IsVisible() ? + SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED ); + } + } +} + +void SvxToolbarEntriesListBox::CheckButtonHdl() +{ + ChangeVisibility( GetHdlEntry() ); +} + +void SvxToolbarEntriesListBox::KeyInput( const KeyEvent& rKeyEvent ) +{ + // space key will change visibility of toolbar items + if ( rKeyEvent.GetKeyCode() == KEY_SPACE ) + { + ChangeVisibility( GetCurEntry() ); + } + else + { + // pass on to superclass + SvxMenuEntriesListBox::KeyInput( rKeyEvent ); + } +} + +BOOL SvxToolbarEntriesListBox::NotifyMoving( + SvLBoxEntry* pTarget, SvLBoxEntry* pSource, + SvLBoxEntry*& rpNewParent, ULONG& rNewChildPos) +{ + bool result = SvxMenuEntriesListBox::NotifyMoving( + pTarget, pSource, rpNewParent, rNewChildPos ); + + if ( result == TRUE ) + { + // Instant Apply changes to UI + SvxConfigEntry* pToolbar = pPage->GetTopLevelSelection(); + if ( pToolbar != NULL ) + { + ToolbarSaveInData* pSaveInData = + ( ToolbarSaveInData*) pPage->GetSaveInData(); + pSaveInData->ApplyToolbar( pToolbar ); + } + } + + return result; +} + +BOOL SvxToolbarEntriesListBox::NotifyCopying( + SvLBoxEntry* pTarget, + SvLBoxEntry* pSource, + SvLBoxEntry*& rpNewParent, + ULONG& rNewChildPos) +{ + (void)pSource; + (void)rpNewParent; + (void)rNewChildPos; + + if ( !m_bIsInternalDrag ) + { + // if the target is NULL then add function to the start of the list + ((SvxToolbarConfigPage*)pPage)->AddFunction( pTarget, pTarget == NULL ); + + // Instant Apply changes to UI + SvxConfigEntry* pToolbar = pPage->GetTopLevelSelection(); + if ( pToolbar != NULL ) + { + ToolbarSaveInData* pSaveInData = + ( ToolbarSaveInData*) pPage->GetSaveInData(); + pSaveInData->ApplyToolbar( pToolbar ); + } + + // AddFunction already adds the listbox entry so return FALSE + // to stop another listbox entry being added + return FALSE; + } + + // Copying is only allowed from external controls, not within the listbox + return FALSE; +} + +SvxNewToolbarDialog::SvxNewToolbarDialog( + Window* pWindow, const String& rName ) + : + ModalDialog ( pWindow, CUI_RES( MD_NEW_TOOLBAR ) ), + aFtDescription ( this, CUI_RES( FT_NAME ) ), + aEdtName ( this, CUI_RES( EDT_STRING ) ), + aSaveInText ( this, CUI_RES( TXT_SAVEIN ) ), + aBtnOK ( this, CUI_RES( BTN_OK ) ), + aBtnCancel ( this, CUI_RES( BTN_CANCEL ) ), + aBtnHelp ( this, CUI_RES( BTN_HELP ) ), + aSaveInListBox ( this, CUI_RES( LB_SAVEIN ) ) +{ + FreeResource(); + + aEdtName.SetText( rName ); + aEdtName.SetSelection(Selection(SELECTION_MIN, SELECTION_MAX)); + ModifyHdl(&aEdtName); + aEdtName.SetModifyHdl(LINK(this, SvxNewToolbarDialog, ModifyHdl)); +} + +IMPL_LINK(SvxNewToolbarDialog, ModifyHdl, Edit*, pEdit) +{ + (void)pEdit; + + if(aCheckNameHdl.IsSet()) + aBtnOK.Enable(aCheckNameHdl.Call(this) > 0); + + return 0; +} + +/******************************************************************************* +* +* The SvxIconSelectorDialog class +* +*******************************************************************************/ +SvxIconSelectorDialog::SvxIconSelectorDialog( Window *pWindow, + const uno::Reference< css::ui::XImageManager >& rXImageManager, + const uno::Reference< css::ui::XImageManager >& rXParentImageManager ) + : + ModalDialog ( pWindow, CUI_RES( MD_ICONSELECTOR ) ), + aFtDescription ( this, CUI_RES( FT_SYMBOLS ) ), + aTbSymbol ( this, CUI_RES( TB_SYMBOLS ) ), + aFtNote ( this, CUI_RES( FT_NOTE ) ), + aBtnOK ( this, CUI_RES( BTN_OK ) ), + aBtnCancel ( this, CUI_RES( BTN_CANCEL ) ), + aBtnHelp ( this, CUI_RES( BTN_HELP ) ), + aBtnImport ( this, CUI_RES( BTN_IMPORT ) ), + aBtnDelete ( this, CUI_RES( BTN_DELETE ) ), + aFlSeparator ( this, CUI_RES( FL_SEPARATOR ) ), + m_nNextId ( 0 ), + m_xImageManager ( rXImageManager ), + m_xParentImageManager( rXParentImageManager ) +{ + FreeResource(); + + typedef ::std::hash_map< ::rtl::OUString, + bool, + ::rtl::OUStringHash, + ::std::equal_to< ::rtl::OUString > > ImageInfo; + + aTbSymbol.SetPageScroll( TRUE ); + + bool bLargeIcons = GetImageType() & css::ui::ImageType::SIZE_LARGE; + m_nExpectedSize = bLargeIcons ? 26 : 16; + + if ( m_nExpectedSize != 16 ) + { + aFtNote.SetText( replaceSixteen( aFtNote.GetText(), m_nExpectedSize ) ); + } + + uno::Reference< lang::XMultiServiceFactory > xServiceManager = + ::comphelper::getProcessServiceFactory(); + + if ( xServiceManager.is() ) + { + m_xGraphProvider = uno::Reference< graphic::XGraphicProvider >( + xServiceManager->createInstance( + ::rtl::OUString::createFromAscii( + "com.sun.star.graphic.GraphicProvider" ) ), + uno::UNO_QUERY ); + } + + if ( !m_xGraphProvider.is() ) + { + aBtnImport.Enable( FALSE ); + } + + uno::Reference< beans::XPropertySet > xPropSet( + xServiceManager->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.util.PathSettings" ) ), + uno::UNO_QUERY ); + + uno::Any aAny = xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfig" ) ) ); + + ::rtl::OUString aDirectory; + + aAny >>= aDirectory; + + sal_Int32 aCount = aDirectory.getLength(); + + if ( aCount > 0 ) + { + sal_Unicode aChar = aDirectory[ aCount-1 ]; + if ( aChar != '/') + { + aDirectory += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + } + } + else + { + aBtnImport.Enable( FALSE ); + } + + aDirectory += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "soffice.cfg/import" ) ); + + uno::Reference< lang::XSingleServiceFactory > xStorageFactory( + xServiceManager->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.embed.FileSystemStorageFactory" )), + uno::UNO_QUERY ); + + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[ 0 ] <<= aDirectory; + aArgs[ 1 ] <<= com::sun::star::embed::ElementModes::READWRITE; + + uno::Reference< com::sun::star::embed::XStorage > xStorage( + xStorageFactory->createInstanceWithArguments( aArgs ), uno::UNO_QUERY ); + + uno::Sequence< uno::Any > aProp( 2 ); + beans::PropertyValue aPropValue; + + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserConfigStorage" ) ); + aPropValue.Value <<= xStorage; + aProp[ 0 ] <<= aPropValue; + + aPropValue.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenMode" ) ); + aPropValue.Value <<= com::sun::star::embed::ElementModes::READWRITE; + aProp[ 1 ] <<= aPropValue; + + m_xImportedImageManager = uno::Reference< com::sun::star::ui::XImageManager >( + xServiceManager->createInstanceWithArguments( + ::rtl::OUString::createFromAscii( "com.sun.star.ui.ImageManager" ), aProp ), + uno::UNO_QUERY ); + + ImageInfo mImageInfo; + uno::Sequence< OUString > names; + if ( m_xImportedImageManager.is() ) + { + names = m_xImportedImageManager->getAllImageNames( GetImageType() ); + for ( sal_Int32 n = 0; n < names.getLength(); n++ ) + mImageInfo.insert( ImageInfo::value_type( names[n], false )); + } + USHORT nId = 1; + ImageInfo::const_iterator pConstIter = mImageInfo.begin(); + uno::Sequence< OUString > name( 1 ); + while ( pConstIter != mImageInfo.end() ) + { + name[ 0 ] = pConstIter->first; + uno::Sequence< uno::Reference< graphic::XGraphic> > graphics = m_xImportedImageManager->getImages( GetImageType(), name ); + if ( graphics.getLength() > 0 ) + { + Image img = Image( graphics[ 0 ] ); + aTbSymbol.InsertItem( nId, img, pConstIter->first ); + + graphics[ 0 ]->acquire(); + + aTbSymbol.SetItemData( + nId, static_cast< void * > ( graphics[ 0 ].get() ) ); + + ++nId; + } + ++pConstIter; + } + + ImageInfo aImageInfo; + + if ( m_xParentImageManager.is() ) + { + names = m_xParentImageManager->getAllImageNames( GetImageType() ); + for ( sal_Int32 n = 0; n < names.getLength(); n++ ) + aImageInfo.insert( ImageInfo::value_type( names[n], false )); + } + + names = m_xImageManager->getAllImageNames( GetImageType() ); + for ( sal_Int32 n = 0; n < names.getLength(); n++ ) + { + ImageInfo::iterator pIter = aImageInfo.find( names[n] ); + if ( pIter != aImageInfo.end() ) + pIter->second = true; + else + aImageInfo.insert( ImageInfo::value_type( names[n], true )); + } + + // large growth factor, expecting many entries + pConstIter = aImageInfo.begin(); + while ( pConstIter != aImageInfo.end() ) + { + name[ 0 ] = pConstIter->first; + + uno::Sequence< uno::Reference< graphic::XGraphic> > graphics; + try + { + if ( pConstIter->second ) + graphics = m_xImageManager->getImages( GetImageType(), name ); + else + graphics = m_xParentImageManager->getImages( GetImageType(), name ); + } + catch ( uno::Exception& ) + { + // can't get sequence for this name so it will not be + // added to the list + } + + if ( graphics.getLength() > 0 ) + { + Image img = Image( graphics[ 0 ] ); + aTbSymbol.InsertItem( nId, img, pConstIter->first ); + + uno::Reference< graphic::XGraphic > xGraphic = graphics[ 0 ]; + + if ( xGraphic.is() ) + xGraphic->acquire(); + + aTbSymbol.SetItemData( + nId, static_cast< void * > ( xGraphic.get() ) ); + + ++nId; + } + + ++pConstIter; + } + + aBtnDelete.Enable( FALSE ); + aTbSymbol.SetSelectHdl( LINK(this, SvxIconSelectorDialog, SelectHdl) ); + aBtnImport.SetClickHdl( LINK(this, SvxIconSelectorDialog, ImportHdl) ); + aBtnDelete.SetClickHdl( LINK(this, SvxIconSelectorDialog, DeleteHdl) ); + + m_nNextId = aTbSymbol.GetItemCount()+1; +} + +SvxIconSelectorDialog::~SvxIconSelectorDialog() +{ + USHORT nCount = aTbSymbol.GetItemCount(); + + for (USHORT n = 0; n < nCount; n++ ) + { + USHORT nId = aTbSymbol.GetItemId(n); + + uno::XInterface* xi = static_cast< uno::XInterface* >( + aTbSymbol.GetItemData( nId ) ); + + if ( xi != NULL ) + { + xi->release(); + } + } +} + +uno::Reference< graphic::XGraphic> SvxIconSelectorDialog::GetSelectedIcon() +{ + uno::Reference< graphic::XGraphic > result; + + USHORT nId; + for ( USHORT n = 0; n < aTbSymbol.GetItemCount(); n++ ) + { + nId = aTbSymbol.GetItemId( n ); + if ( aTbSymbol.IsItemChecked( nId ) ) + { + result = uno::Reference< graphic::XGraphic >( + reinterpret_cast< graphic::XGraphic* >( + aTbSymbol.GetItemData( nId ) ) ); + } + } + + return result; +} + +IMPL_LINK( SvxIconSelectorDialog, SelectHdl, ToolBox *, pToolBox ) +{ + (void)pToolBox; + + USHORT nCount = aTbSymbol.GetItemCount(); + + for (USHORT n = 0; n < nCount; n++ ) + { + USHORT nId = aTbSymbol.GetItemId( n ); + + if ( aTbSymbol.IsItemChecked( nId ) ) + { + aTbSymbol.CheckItem( nId, FALSE ); + } + } + + USHORT nId = aTbSymbol.GetCurItemId(); + aTbSymbol.CheckItem( nId ); + + ::rtl::OUString aSelImageText = aTbSymbol.GetItemText( nId ); + if ( m_xImportedImageManager->hasImage( GetImageType(), aSelImageText ) ) + { + aBtnDelete.Enable( TRUE ); + } + else + { + aBtnDelete.Enable( FALSE ); + } + + return 0; +} + +IMPL_LINK( SvxIconSelectorDialog, ImportHdl, PushButton *, pButton ) +{ + (void)pButton; + + sfx2::FileDialogHelper aImportDialog( + css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW, + SFXWB_GRAPHIC | SFXWB_MULTISELECTION ); + + // disable the link checkbox in the dialog + uno::Reference< css::ui::dialogs::XFilePickerControlAccess > + xController( aImportDialog.GetFilePicker(), uno::UNO_QUERY); + if ( xController.is() ) + { + xController->enableControl( + css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK, + sal_False); + } + + aImportDialog.SetCurrentFilter( + String::CreateFromAscii( "PNG - Portable Network Graphic" ) ); + + if ( ERRCODE_NONE == aImportDialog.Execute() ) + { + uno::Sequence< OUString > paths = aImportDialog.GetMPath(); + ImportGraphics ( paths ); + } + + return 0; +} + +IMPL_LINK( SvxIconSelectorDialog, DeleteHdl, PushButton *, pButton ) +{ + (void)pButton; + + OUString message = String( CUI_RES( RID_SVXSTR_DELETE_ICON_CONFIRM ) ); + bool ret = WarningBox( this, WinBits(WB_OK_CANCEL), message ).Execute(); + + if ( ret == RET_OK ) + { + USHORT nCount = aTbSymbol.GetItemCount(); + + for (USHORT n = 0; n < nCount; n++ ) + { + USHORT nId = aTbSymbol.GetItemId( n ); + + if ( aTbSymbol.IsItemChecked( nId ) ) + { + ::rtl::OUString aSelImageText = aTbSymbol.GetItemText( nId ); + uno::Sequence< OUString > URLs(1); + URLs[0] = aSelImageText; + aTbSymbol.RemoveItem( aTbSymbol.GetItemPos( nId ) ); + m_xImportedImageManager->removeImages( GetImageType(), URLs ); + uno::Reference< css::ui::XUIConfigurationPersistence > + xConfigPersistence( m_xImportedImageManager, uno::UNO_QUERY ); + if ( xConfigPersistence.is() && xConfigPersistence->isModified() ) + { + xConfigPersistence->store(); + } + break; + } + } + } + return 0; +} + +bool SvxIconSelectorDialog::ReplaceGraphicItem( + const ::rtl::OUString& aURL ) +{ + uno::Sequence< OUString > URLs(1); + uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph( 1 ); + uno::Reference< css::ui::XUIConfigurationPersistence > + xConfigPer( m_xImportedImageManager, uno::UNO_QUERY ); + + uno::Reference< graphic::XGraphic > xGraphic; + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = ::rtl::OUString::createFromAscii("URL"); + aMediaProps[0].Value <<= aURL; + + com::sun::star::awt::Size aSize; + bool bOK = FALSE; + try + { + xGraphic = m_xGraphProvider->queryGraphic( aMediaProps ); + + uno::Reference< beans::XPropertySet > props = + m_xGraphProvider->queryGraphicDescriptor( aMediaProps ); + uno::Any a = props->getPropertyValue( + OUString::createFromAscii("SizePixel") ); + a >>= aSize; + if (0 == aSize.Width || 0 == aSize.Height) + return FALSE; + else + bOK = TRUE; + } + catch ( uno::Exception& ) + { + return false; + } + + bool bResult( false ); + USHORT nCount = aTbSymbol.GetItemCount(); + for (USHORT n = 0; n < nCount; n++ ) + { + USHORT nId = aTbSymbol.GetItemId( n ); + + if ( OUString( aTbSymbol.GetItemText( nId ) ) == aURL ) + { + try + { + // replace/insert image with provided URL + aTbSymbol.RemoveItem( aTbSymbol.GetItemPos( nId ) ); + aMediaProps[0].Value <<= aURL; + + Image aImage( xGraphic ); + if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) ) + { + BitmapEx aBitmap = aImage.GetBitmapEx(); + BitmapEx aBitmapex = AutoScaleBitmap(aBitmap, m_nExpectedSize); + aImage = Image( aBitmapex); + } + aTbSymbol.InsertItem( nId,aImage, aURL, 0, 0 ); //modify + + xGraphic = aImage.GetXGraphic(); + + URLs[0] = aURL; + aImportGraph[ 0 ] = xGraphic; + m_xImportedImageManager->replaceImages( GetImageType(), URLs, aImportGraph ); + xConfigPer->store(); + + bResult = true; + break; + } + catch ( ::com::sun::star::uno::Exception& ) + { + break; + } + } + } + + return bResult; +} + +void SvxIconSelectorDialog::ImportGraphics( + const uno::Sequence< OUString >& rPaths ) +{ + uno::Sequence< OUString > rejected( rPaths.getLength() ); + sal_Int32 rejectedCount = 0; + + USHORT ret = 0; + sal_Int32 aIndex; + OUString aIconName; + uno::Sequence< OUString > URLs(1); + uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph( 1 ); + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = ::rtl::OUString::createFromAscii("URL"); + uno::Reference< css::ui::XUIConfigurationPersistence > + xConfigPer( m_xImportedImageManager, uno::UNO_QUERY ); + + if ( rPaths.getLength() == 1 ) + { + if ( m_xImportedImageManager->hasImage( GetImageType(), rPaths[0] ) ) + { + aIndex = rPaths[0].lastIndexOf( '/' ); + aIconName = rPaths[0].copy( aIndex+1 ); + ret = SvxIconReplacementDialog( this, aIconName ).ShowDialog(); + if ( ret == 2 ) + { + ReplaceGraphicItem( rPaths[0] ); + } + } + else + { + if ( ImportGraphic( rPaths[0] ) == FALSE ) + { + rejected[0] = rPaths[0]; + rejectedCount = 1; + } + } + } + else + { + ::rtl::OUString aSourcePath( rPaths[0] ); + if ( rPaths[0].lastIndexOf( '/' ) != rPaths[0].getLength() -1 ) + aSourcePath = rPaths[0] + ::rtl::OUString::createFromAscii( "/" ); + + for ( sal_Int32 i = 1; i < rPaths.getLength(); i++ ) + { + ::rtl::OUString aPath = aSourcePath + rPaths[i]; + if ( m_xImportedImageManager->hasImage( GetImageType(), aPath ) ) + { + aIndex = rPaths[i].lastIndexOf( '/' ); + aIconName = rPaths[i].copy( aIndex+1 ); + ret = SvxIconReplacementDialog( this, aIconName, TRUE ).ShowDialog(); + if ( ret == 2 ) + { + ReplaceGraphicItem( aPath ); + } + else if ( ret == 5 ) + { + for ( sal_Int32 k = i; k < rPaths.getLength(); k++ ) + { + aPath = aSourcePath + rPaths[k]; + bool bHasReplaced = ReplaceGraphicItem( aPath ); + + if ( !bHasReplaced ) + { + bool result = ImportGraphic( aPath ); + if ( result == FALSE ) + { + rejected[ rejectedCount ] = rPaths[i]; + rejectedCount++; + } + } + } + break; + } + } + else + { + bool result = ImportGraphic( aSourcePath + rPaths[i] ); + if ( result == FALSE ) + { + rejected[ rejectedCount ] = rPaths[i]; + rejectedCount++; + } + } + } + } + + if ( rejectedCount != 0 ) + { + OUString message =OUString::createFromAscii(""); + OUString newLine = OUString::createFromAscii("\n"); + rtl::OUString fPath = OUString::createFromAscii(""); + if (rejectedCount > 1) + fPath = rPaths[0].copy(8) + ::rtl::OUString::createFromAscii( "/" ); + for ( sal_Int32 i = 0; i < rejectedCount; i++ ) + { + message += fPath + rejected[i]; + message += newLine; + } + + SvxIconChangeDialog aDialog(this, message); + aDialog.Execute(); + } +} + +bool SvxIconSelectorDialog::ImportGraphic( const OUString& aURL ) +{ + bool result = FALSE; + + USHORT nId = m_nNextId; + ++m_nNextId; + + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = ::rtl::OUString::createFromAscii("URL"); + + uno::Reference< graphic::XGraphic > xGraphic; + com::sun::star::awt::Size aSize; + bool bOK = TRUE; + aMediaProps[0].Value <<= aURL; + try + { + uno::Reference< beans::XPropertySet > props = + m_xGraphProvider->queryGraphicDescriptor( aMediaProps ); + + uno::Any a = props->getPropertyValue( + OUString::createFromAscii("SizePixel") ); + + xGraphic = m_xGraphProvider->queryGraphic( aMediaProps ); + if ( xGraphic.is() ) + { + a >>= aSize; + if ( 0 == aSize.Width || 0 == aSize.Height ) + bOK = FALSE; + + Image aImage( xGraphic ); + + if ( bOK && ((aSize.Width != m_nExpectedSize) || (aSize.Height != m_nExpectedSize)) ) + { + BitmapEx aBitmap = aImage.GetBitmapEx(); + BitmapEx aBitmapex = AutoScaleBitmap(aBitmap, m_nExpectedSize); + aImage = Image( aBitmapex); + } + if ( bOK && !!aImage ) + { + aTbSymbol.InsertItem( nId, aImage, aURL, 0, 0 ); + + xGraphic = aImage.GetXGraphic(); + xGraphic->acquire(); + + aTbSymbol.SetItemData( + nId, static_cast< void * > ( xGraphic.get() ) ); + uno::Sequence< OUString > aImportURL( 1 ); + aImportURL[ 0 ] = aURL; + uno::Sequence< uno::Reference<graphic::XGraphic > > aImportGraph( 1 ); + aImportGraph[ 0 ] = xGraphic; + m_xImportedImageManager->insertImages( GetImageType(), aImportURL, aImportGraph ); + uno::Reference< css::ui::XUIConfigurationPersistence > + xConfigPersistence( m_xImportedImageManager, uno::UNO_QUERY ); + + if ( xConfigPersistence.is() && xConfigPersistence->isModified() ) + { + xConfigPersistence->store(); + } + + result = TRUE; + } + else + { + OSL_TRACE("could not create Image from XGraphic"); + } + } + else + { + OSL_TRACE("could not get query XGraphic"); + } + } + catch( uno::Exception& e ) + { + OSL_TRACE("Caught exception importing XGraphic: %s", PRTSTR(e.Message)); + } + return result; +} + +/******************************************************************************* +* +* The SvxIconReplacementDialog class +* +*******************************************************************************/ +SvxIconReplacementDialog :: SvxIconReplacementDialog( + Window *pWindow, const rtl::OUString& aMessage, bool /*bYestoAll*/ ) + : +MessBox( pWindow, WB_DEF_YES, String( CUI_RES( RID_SVXSTR_REPLACE_ICON_CONFIRM ) ), String( CUI_RES( RID_SVXSTR_REPLACE_ICON_WARNING ) ) ) + +{ + SetImage( WarningBox::GetStandardImage() ); + SetMessText( ReplaceIconName( aMessage ) ); + RemoveButton( 1 ); + AddButton( BUTTON_YES, 2, 0 ); + AddButton( String( CUI_RES( RID_SVXSTR_YESTOALL ) ), 5, 0 ); + AddButton( BUTTON_NO, 3, 0 ); + AddButton( BUTTON_CANCEL, 4, 0 ); +} + +SvxIconReplacementDialog :: SvxIconReplacementDialog( + Window *pWindow, const rtl::OUString& aMessage ) + : +MessBox( pWindow, WB_YES_NO_CANCEL, String( CUI_RES( RID_SVXSTR_REPLACE_ICON_CONFIRM ) ), String( CUI_RES( RID_SVXSTR_REPLACE_ICON_WARNING ) ) ) +{ + SetImage( WarningBox::GetStandardImage() ); + SetMessText( ReplaceIconName( aMessage )); +} + +rtl::OUString SvxIconReplacementDialog :: ReplaceIconName( const OUString& rMessage ) +{ + rtl::OUString name; + rtl::OUString message = String( CUI_RES( RID_SVXSTR_REPLACE_ICON_WARNING ) ); + rtl::OUString placeholder = OUString::createFromAscii( "%ICONNAME" ); + sal_Int32 pos = message.indexOf( placeholder ); + if ( pos != -1 ) + { + name = message.replaceAt( + pos, placeholder.getLength(), rMessage ); + } + return name; +} + +USHORT SvxIconReplacementDialog :: ShowDialog() +{ + this->Execute(); + return ( this->GetCurButtonId() ); +} +/******************************************************************************* +* +* The SvxIconChangeDialog class added for issue83555 +* +*******************************************************************************/ +SvxIconChangeDialog::SvxIconChangeDialog( + Window *pWindow, const rtl::OUString& aMessage) + : + ModalDialog ( pWindow, CUI_RES( MD_ICONCHANGE ) ), + aFImageInfo (this, CUI_RES( FI_INFO ) ), + aBtnOK (this, CUI_RES(MD_BTN_OK)), + aDescriptionLabel (this, CUI_RES(FTCHGE_DESCRIPTION)), + aLineEditDescription (this, CUI_RES(EDT_ADDR)) +{ + FreeResource(); + aFImageInfo.SetImage(InfoBox::GetStandardImage()); + aLineEditDescription.SetControlBackground( GetSettings().GetStyleSettings().GetDialogColor() ); + aLineEditDescription.SetAutoScroll( TRUE ); + aLineEditDescription.EnableCursor( FALSE ); + aLineEditDescription.SetText(aMessage); +} + +BitmapEx SvxIconSelectorDialog::AutoScaleBitmap(BitmapEx & aBitmap, const long aStandardSize) +{ + Point aEmptyPoint(0,0); + sal_Int32 imgNewWidth = 0; + sal_Int32 imgNewHeight = 0; + double imgposX = 0; + double imgposY = 0; + BitmapEx aRet = aBitmap; + double imgOldWidth = aRet.GetSizePixel().Width(); + double imgOldHeight =aRet.GetSizePixel().Height(); + + Size aScaledSize; + if (imgOldWidth >= aStandardSize || imgOldHeight >= aStandardSize) + { + if (imgOldWidth >= imgOldHeight) + { + imgNewWidth = aStandardSize; + imgNewHeight = sal_Int32(imgOldHeight / (imgOldWidth / aStandardSize) + 0.5); + imgposX = 0; + imgposY = (aStandardSize - (imgOldHeight / (imgOldWidth / aStandardSize) + 0.5)) / 2 + 0.5; + } + else + { + imgNewHeight = aStandardSize; + imgNewWidth = sal_Int32(imgOldWidth / (imgOldHeight / aStandardSize) + 0.5); + imgposY = 0; + imgposX = (aStandardSize - (imgOldWidth / (imgOldHeight / aStandardSize) + 0.5)) / 2 + 0.5; + } + + aScaledSize = Size( imgNewWidth, imgNewHeight ); + aRet.Scale( aScaledSize, BMP_SCALE_INTERPOLATE ); + } + else + { + imgposX = (aStandardSize - imgOldWidth) / 2 + 0.5; + imgposY = (aStandardSize - imgOldHeight) / 2 + 0.5; + } + + Size aBmpSize = aRet.GetSizePixel(); + Size aStdSize( aStandardSize, aStandardSize ); + Rectangle aRect(aEmptyPoint, aStdSize ); + + VirtualDevice aVirDevice( *Application::GetDefaultDevice(), 0, 1 ); + aVirDevice.SetOutputSizePixel( aStdSize ); + aVirDevice.SetFillColor( COL_TRANSPARENT ); + aVirDevice.SetLineColor( COL_TRANSPARENT ); + + //draw a rect into virDevice + aVirDevice.DrawRect( aRect ); + Point aPointPixel( (long)imgposX, (long)imgposY ); + aVirDevice.DrawBitmapEx( aPointPixel, aRet ); + aRet = aVirDevice.GetBitmapEx( aEmptyPoint, aStdSize ); + + return aRet; +} |