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