1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #include "vbacommandbarhelper.hxx"
28 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
29 #include <com/sun/star/ui/XUIConfigurationStorage.hpp>
30 #include <com/sun/star/ui/XModuleUIConfigurationManager.hpp>
31 #include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
32 #include <com/sun/star/ui/XUIElement.hpp>
33 #include <com/sun/star/ui/UIElementType.hpp>
34 #include <comphelper/processfactory.hxx>
35 #include <vbahelper/vbahelper.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <time.h>
38 #include <map>
39 
40 using namespace com::sun::star;
41 using namespace ooo::vba;
42 
43 #define CREATEOUSTRING(asciistr) rtl::OUString::createFromAscii(asciistr)
44 
45 typedef std::map< rtl::OUString, rtl::OUString > MSO2OOCommandbarMap;
46 
47 class MSO2OOCommandbarHelper
48 {
49 private:
50     static MSO2OOCommandbarHelper* pMSO2OOCommandbarHelper;
51     MSO2OOCommandbarMap maBuildinToolbarMap;
52 
53     MSO2OOCommandbarHelper()
54     {
55         // Buildin toolbars
56         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Standard"),CREATEOUSTRING("private:resource/toolbar/standardbar") ) );
57         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Formatting"),CREATEOUSTRING("private:resource/toolbar/formatobjectbar") ) );
58         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Drawing"),CREATEOUSTRING("private:resource/toolbar/drawbar") ) );
59         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Toolbar List"),CREATEOUSTRING("private:resource/toolbar/toolbar") ) );
60         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Forms"),CREATEOUSTRING("private:resource/toolbar/formcontrols") ) );
61         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Form Controls"),CREATEOUSTRING("private:resource/toolbar/formcontrols") ) );
62         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Full Screen"),CREATEOUSTRING("private:resource/toolbar/fullscreenbar") ) );
63         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Chart"),CREATEOUSTRING("private:resource/toolbar/flowchartshapes") ) );
64         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("Picture"),CREATEOUSTRING("private:resource/toolbar/graphicobjectbar") ) );
65         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("WordArt"),CREATEOUSTRING("private:resource/toolbar/fontworkobjectbar") ) );
66         maBuildinToolbarMap.insert( std::make_pair( CREATEOUSTRING("3-D Settings"),CREATEOUSTRING("private:resource/toolbar/extrusionobjectbar") ) );
67     }
68 
69 public:
70     virtual ~MSO2OOCommandbarHelper() {};
71     static MSO2OOCommandbarHelper* getMSO2OOCommandbarHelper()
72     {
73         if( pMSO2OOCommandbarHelper == NULL )
74         {
75             pMSO2OOCommandbarHelper = new MSO2OOCommandbarHelper();
76         }
77         return pMSO2OOCommandbarHelper;
78     }
79 
80     rtl::OUString findBuildinToolbar( const rtl::OUString& sToolbarName )
81     {
82         MSO2OOCommandbarMap::iterator it = maBuildinToolbarMap.begin();
83         for(; it != maBuildinToolbarMap.end(); it++ )
84         {
85             rtl::OUString sName = it->first;
86             if( sName.equalsIgnoreAsciiCase( sToolbarName ) )
87                 return it->second;
88         }
89         return rtl::OUString();
90     }
91 };
92 
93 MSO2OOCommandbarHelper* MSO2OOCommandbarHelper::pMSO2OOCommandbarHelper = NULL;
94 
95 
96 VbaCommandBarHelper::VbaCommandBarHelper( const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::frame::XModel >& xModel ) throw (css::uno::RuntimeException) : mxContext( xContext ), mxModel( xModel )
97 {
98     Init();
99 }
100 
101 void VbaCommandBarHelper::Init( ) throw (css::uno::RuntimeException)
102 {
103     uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUICfgSupplier( mxModel, uno::UNO_QUERY_THROW );
104     m_xDocCfgMgr = xUICfgSupplier->getUIConfigurationManager();
105 
106     uno::Reference< lang::XServiceInfo > xServiceInfo( mxModel, uno::UNO_QUERY_THROW );
107     if( xServiceInfo->supportsService( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetDocument") ) ) )
108     {
109         maModuleId = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetDocument") );
110     }
111     else if( xServiceInfo->supportsService( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextDocument" ) ) ) )
112     {
113         maModuleId = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextDocument") );
114     }
115 
116     if( maModuleId.getLength() == 0 )
117     {
118         throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() );
119     }
120 
121 	uno::Reference< lang::XMultiServiceFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_QUERY_THROW );
122 
123 	css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUICfgMgrSupp( xServiceManager->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ModuleUIConfigurationManagerSupplier" ))), uno::UNO_QUERY_THROW );
124 
125     m_xAppCfgMgr.set( xUICfgMgrSupp->getUIConfigurationManager( maModuleId ), uno::UNO_QUERY_THROW );
126 
127 	css::uno::Reference< css::container::XNameAccess > xNameAccess( xServiceManager->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.WindowStateConfiguration" ))), uno::UNO_QUERY_THROW );
128 
129     m_xWindowState.set( xNameAccess->getByName( maModuleId ), uno::UNO_QUERY_THROW );
130 }
131 
132 css::uno::Reference< css::container::XIndexAccess > VbaCommandBarHelper::getSettings( const rtl::OUString& sResourceUrl ) throw (css::uno::RuntimeException)
133 {
134     if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
135         return m_xDocCfgMgr->getSettings( sResourceUrl, sal_True );
136     else if( m_xAppCfgMgr->hasSettings( sResourceUrl ) )
137         return m_xAppCfgMgr->getSettings( sResourceUrl, sal_True );
138     else
139     {
140         css::uno::Reference< css::container::XIndexAccess > xSettings( m_xAppCfgMgr->createSettings( ), uno::UNO_QUERY_THROW );
141         return xSettings;
142     }
143 }
144 
145 void VbaCommandBarHelper::removeSettings( const rtl::OUString& sResourceUrl ) throw (css::uno::RuntimeException)
146 {
147     if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
148         m_xDocCfgMgr->removeSettings( sResourceUrl );
149     else if( m_xAppCfgMgr->hasSettings( sResourceUrl ) )
150         m_xAppCfgMgr->removeSettings( sResourceUrl );
151 
152     // persistChanges();
153 }
154 
155 void VbaCommandBarHelper::ApplyChange( const rtl::OUString& sResourceUrl, const css::uno::Reference< css::container::XIndexAccess >& xSettings, sal_Bool bTemporary ) throw (css::uno::RuntimeException)
156 {
157     if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
158     {
159         m_xDocCfgMgr->replaceSettings( sResourceUrl, xSettings );
160     }
161     else
162     {
163         m_xDocCfgMgr->insertSettings( sResourceUrl, xSettings );
164     }
165     if( !bTemporary )
166     {
167         persistChanges();
168     }
169 }
170 
171 sal_Bool VbaCommandBarHelper::persistChanges() throw (css::uno::RuntimeException)
172 {
173     uno::Reference< css::ui::XUIConfigurationPersistence > xConfigPersistence( m_xDocCfgMgr, uno::UNO_QUERY_THROW );
174     sal_Bool result = sal_False;
175     if( xConfigPersistence->isModified() )
176     {
177         xConfigPersistence->store();
178         result = sal_True;
179     }
180     return result;
181 }
182 
183 uno::Reference< frame::XLayoutManager > VbaCommandBarHelper::getLayoutManager() throw (uno::RuntimeException)
184 {
185     uno::Reference< frame::XFrame > xFrame( getModel()->getCurrentController()->getFrame(), uno::UNO_QUERY_THROW );
186     uno::Reference< beans::XPropertySet > xPropertySet( xFrame, uno::UNO_QUERY_THROW );
187     uno::Reference< frame::XLayoutManager > xLayoutManager( xPropertySet->getPropertyValue( rtl::OUString::createFromAscii("LayoutManager") ), uno::UNO_QUERY_THROW );
188     return xLayoutManager;
189 }
190 
191 sal_Bool VbaCommandBarHelper::hasToolbar( const rtl::OUString& sResourceUrl, const rtl::OUString& sName ) throw (css::uno::RuntimeException)
192 {
193     if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
194     {
195         rtl::OUString sUIName;
196         uno::Reference< beans::XPropertySet > xPropertySet( m_xDocCfgMgr->getSettings( sResourceUrl, sal_False ), uno::UNO_QUERY_THROW );
197         xPropertySet->getPropertyValue( rtl::OUString::createFromAscii(ITEM_DESCRIPTOR_UINAME) ) >>= sUIName;
198         if( sName.equalsIgnoreAsciiCase( sUIName ) )
199             return sal_True;
200     }
201     return sal_False;
202 }
203 
204 // return the resource url if found
205 rtl::OUString VbaCommandBarHelper::findToolbarByName( const css::uno::Reference< css::container::XNameAccess >& xNameAccess, const rtl::OUString& sName ) throw (css::uno::RuntimeException)
206 {
207     rtl::OUString sResourceUrl;
208 
209     // check if it is an buildin toolbar
210     sResourceUrl = MSO2OOCommandbarHelper::getMSO2OOCommandbarHelper()->findBuildinToolbar( sName );
211     if( sResourceUrl.getLength() > 0 )
212         return sResourceUrl;
213 
214     uno::Sequence< ::rtl::OUString > allNames = xNameAccess->getElementNames();
215     for( sal_Int32 i = 0; i < allNames.getLength(); i++ )
216     {
217         sResourceUrl = allNames[i];
218         if(sResourceUrl.indexOf( rtl::OUString::createFromAscii( ITEM_TOOLBAR_URL ) ) == 0 )
219         {
220             if( hasToolbar( sResourceUrl, sName ) )
221                 return sResourceUrl;
222         }
223     }
224 
225     // the customize toolbars creating during importing, shoud found there.
226     static rtl::OUString sToolbarPrefix( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/custom_" ) );
227     sResourceUrl = sToolbarPrefix.concat( sName );
228     if( hasToolbar( sResourceUrl, sName ) )
229         return sResourceUrl;
230 
231     return rtl::OUString();
232 }
233 
234 // if found, return the position of the control. if not found, return -1
235 sal_Int32 VbaCommandBarHelper::findControlByName( const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, const rtl::OUString& sName, bool bMenu ) throw (css::uno::RuntimeException)
236 {
237     sal_Int32 nCount = xIndexAccess->getCount();
238     css::uno::Sequence< css::beans::PropertyValue > aProps;
239     for( sal_Int32 i = 0; i < nCount; i++ )
240     {
241         rtl::OUString sLabel;
242         xIndexAccess->getByIndex( i ) >>= aProps;
243         getPropertyValue( aProps, rtl::OUString::createFromAscii(ITEM_DESCRIPTOR_LABEL) ) >>= sLabel;
244         // handle the hotkey marker '~' (remove in toolbars (?), replace by '&' in menus)
245         ::rtl::OUStringBuffer aBuffer;
246         sal_Int32 index = sLabel.indexOf( sal_Unicode('~') );
247         if( index < 0 )
248         {
249             aBuffer = sLabel;
250         }
251         else
252         {
253             aBuffer.append( sLabel.copy( 0, index ) );
254             if( bMenu )
255                 aBuffer.append( sal_Unicode( '&' ) );
256             aBuffer.append( sLabel.copy( index + 1 ) );
257         }
258         rtl::OUString sNewLabel = aBuffer.makeStringAndClear();
259         OSL_TRACE("VbaCommandBarHelper::findControlByName, control name: %s", rtl::OUStringToOString( sNewLabel, RTL_TEXTENCODING_UTF8 ).getStr() );
260         if( sName.equalsIgnoreAsciiCase( sNewLabel ) )
261             return i;
262     }
263 
264     // not found
265     return -1;
266 }
267 
268 rtl::OUString VbaCommandBarHelper::generateCustomURL()
269 {
270     rtl::OUString url = rtl::OUString::createFromAscii( ITEM_TOOLBAR_URL );
271     url += rtl::OUString::createFromAscii( CUSTOM_TOOLBAR_STR );
272 
273     // use a random number to minimize possible clash with existing custom toolbars
274     srand( unsigned( time( NULL ) ));
275     url += rtl::OUString::valueOf( sal_Int64( rand() ), 16 );
276     return url;
277 }
278