1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: eventcfg.cxx,v $
10 * $Revision: 1.8.24.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include "eventcfg.hxx"
35 #include <unotools/configmgr.hxx>
36 #include <unotools/configitem.hxx>
37 #include <tools/debug.hxx>
38 #include <com/sun/star/uno/Any.hxx>
39 #include <com/sun/star/uno/Sequence.hxx>
40 #include <com/sun/star/beans/PropertyValue.hpp>
41 #include <cppuhelper/weakref.hxx>
43 #ifndef __SGI_STL_HASH_MAP
46 #include <tools/urlobj.hxx>
47 #include <rtl/ustrbuf.hxx>
49 #include <itemholder1.hxx>
53 using namespace ::std
;
54 using namespace ::utl
;
55 using namespace ::rtl
;
56 using namespace ::osl
;
57 using namespace ::com::sun::star::uno
;
58 using namespace ::com::sun::star
;
60 #define ROOTNODE_EVENTS OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Events/ApplicationEvents" ))
61 #define PATHDELIMITER OUString(RTL_CONSTASCII_USTRINGPARAM("/"))
62 #define SETNODE_BINDINGS OUString(RTL_CONSTASCII_USTRINGPARAM("Bindings" ))
63 #define PROPERTYNAME_BINDINGURL OUString(RTL_CONSTASCII_USTRINGPARAM("BindingURL"))
65 const char* pEventAsciiNames
[] =
88 "OnPrepareViewClosing",
97 GlobalEventConfig_Impl::GlobalEventConfig_Impl()
98 : ConfigItem( ROOTNODE_EVENTS
, CONFIG_MODE_IMMEDIATE_UPDATE
)
100 // the supported event names
101 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_STARTAPP
] ) );
102 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_CLOSEAPP
] ) );
103 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_DOCCREATED
] ) );
104 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_CREATEDOC
] ) );
105 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_LOADFINISHED
] ) );
106 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_OPENDOC
] ) );
107 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_PREPARECLOSEDOC
] ) );
108 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_CLOSEDOC
] ) );
109 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVEDOC
] ) );
110 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVEDOCDONE
] ) );
111 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVEDOCFAILED
] ) );
112 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVEASDOC
] ) );
113 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVEASDOCDONE
] ) );
114 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVEASDOCFAILED
] ) );
115 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVETODOC
] ) );
116 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVETODOCDONE
] ) );
117 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_SAVETODOCFAILED
] ) );
118 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_ACTIVATEDOC
] ) );
119 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_DEACTIVATEDOC
] ) );
120 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_PRINTDOC
] ) );
121 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_VIEWCREATED
] ) );
122 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_PREPARECLOSEVIEW
] ) );
123 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_CLOSEVIEW
] ) );
124 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_MODIFYCHANGED
] ) );
125 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_TITLECHANGED
] ) );
126 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_VISAREACHANGED
] ) );
127 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_MODECHANGED
] ) );
128 m_supportedEvents
.push_back(::rtl::OUString::createFromAscii( pEventAsciiNames
[STR_EVENT_STORAGECHANGED
] ) );
132 /*TODO: Not used in the moment! see Notify() ...
133 // Enable notification mechanism of our baseclass.
134 // We need it to get information about changes outside these class on our used configuration keys! */
135 Sequence
< OUString
> aNotifySeq( 1 );
136 aNotifySeq
[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "Events" ));
137 EnableNotification( aNotifySeq
, sal_True
);
140 //*****************************************************************************************************************
142 //*****************************************************************************************************************
143 GlobalEventConfig_Impl::~GlobalEventConfig_Impl()
145 // We must save our current values .. if user forget it!
146 if( IsModified() == sal_True
)
152 ::rtl::OUString
GlobalEventConfig_Impl::GetEventName( sal_Int32 nIndex
)
154 if ( nIndex
< (sal_Int32
) m_supportedEvents
.size() )
155 return m_supportedEvents
[nIndex
];
157 return rtl::OUString();
160 //*****************************************************************************************************************
162 //*****************************************************************************************************************
163 void GlobalEventConfig_Impl::Notify( const Sequence
< OUString
>& )
165 MutexGuard
aGuard( GlobalEventConfig::GetOwnStaticMutex() );
169 // dont forget to update all existing frames and her might cached dispatch objects!
170 // But look for already killed frames. We hold weak references instead of hard ones ...
171 for (FrameVector::const_iterator pIt
= m_lFrames
.begin();
172 pIt
!= m_lFrames
.end() ;
175 ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
> xFrame(pIt
->get(), ::com::sun::star::uno::UNO_QUERY
);
177 xFrame
->contextChanged();
181 //*****************************************************************************************************************
183 //*****************************************************************************************************************
184 void GlobalEventConfig_Impl::Commit()
186 //DF need to check it this is correct??
187 OSL_TRACE("In GlobalEventConfig_Impl::Commit");
188 EventBindingHash::const_iterator it
= m_eventBindingHash
.begin();
189 EventBindingHash::const_iterator it_end
= m_eventBindingHash
.end();
190 // clear the existing nodes
191 ClearNodeSet( SETNODE_BINDINGS
);
192 Sequence
< beans::PropertyValue
> seqValues( 1 );
194 static const OUString
sPrefix(SETNODE_BINDINGS
+ PATHDELIMITER
+ OUString::createFromAscii("BindingType['"));
195 static const OUString
sPostfix(OUString::createFromAscii("']") + PATHDELIMITER
+ PROPERTYNAME_BINDINGURL
);
196 //step through the list of events
197 for(int i
=0;it
!=it_end
;++it
,++i
)
199 //no point in writing out empty bindings!
200 if(it
->second
.getLength() == 0 )
202 sNode
= sPrefix
+ it
->first
+ sPostfix
;
203 OSL_TRACE("writing binding for: %s",::rtl::OUStringToOString(sNode
, RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
204 seqValues
[ 0 ].Name
= sNode
;
205 seqValues
[ 0 ].Value
<<= it
->second
;
206 //write the data to the registry
207 SetSetProperties(SETNODE_BINDINGS
,seqValues
);
211 //*****************************************************************************************************************
213 //*****************************************************************************************************************
214 void GlobalEventConfig_Impl::EstablishFrameCallback(const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
>& xFrame
)
216 // check if frame already exists inside list
217 // ignore double registrations
218 // every frame must be notified one times only!
219 ::com::sun::star::uno::WeakReference
< ::com::sun::star::frame::XFrame
> xWeak(xFrame
);
220 FrameVector::const_iterator pIt
= ::std::find(m_lFrames
.begin(), m_lFrames
.end(), xWeak
);
221 if (pIt
== m_lFrames
.end())
222 m_lFrames
.push_back(xWeak
);
225 //*****************************************************************************************************************
227 //*****************************************************************************************************************
228 void GlobalEventConfig_Impl::initBindingInfo()
230 // Get ALL names of current existing list items in configuration!
231 Sequence
< OUString
> lEventNames
= GetNodeNames( SETNODE_BINDINGS
, utl::CONFIG_NAME_LOCAL_PATH
);
233 OUString
aSetNode( SETNODE_BINDINGS
);
234 aSetNode
+= PATHDELIMITER
;
236 OUString
aCommandKey( PATHDELIMITER
);
237 aCommandKey
+= PROPERTYNAME_BINDINGURL
;
240 Sequence
< OUString
> lMacros(1);
241 for (sal_Int32 i
=0; i
<lEventNames
.getLength(); ++i
)
243 OUStringBuffer
aBuffer( 32 );
244 aBuffer
.append( aSetNode
);
245 aBuffer
.append( lEventNames
[i
] );
246 aBuffer
.append( aCommandKey
);
247 lMacros
[0] = aBuffer
.makeStringAndClear();
248 OSL_TRACE("reading binding for: %s",::rtl::OUStringToOString(lMacros
[0] , RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
249 Sequence
< Any
> lValues
= GetProperties( lMacros
);
251 if( lValues
.getLength() > 0 )
253 lValues
[0] >>= sMacroURL
;
254 sal_Int32 startIndex
= lEventNames
[i
].indexOf('\'');
255 sal_Int32 endIndex
= lEventNames
[i
].lastIndexOf('\'');
256 if( startIndex
>=0 && endIndex
> 0 )
259 OUString eventName
= lEventNames
[i
].copy(startIndex
,endIndex
-startIndex
);
260 m_eventBindingHash
[ eventName
] = sMacroURL
;
266 Reference
< container::XNameReplace
> SAL_CALL
GlobalEventConfig_Impl::getEvents() throw (::com::sun::star::uno::RuntimeException
)
268 //how to return this object as an XNameReplace?
269 Reference
< container::XNameReplace
> ret
;
273 void SAL_CALL
GlobalEventConfig_Impl::replaceByName( const OUString
& aName
, const Any
& aElement
) throw (lang::IllegalArgumentException
, container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
275 Sequence
< beans::PropertyValue
> props
;
276 //DF should we prepopulate the hash with a list of valid event Names?
277 if( sal_False
== ( aElement
>>= props
) )
279 throw lang::IllegalArgumentException( OUString(),
280 Reference
< XInterface
> (), 2);
283 sal_Int32 nPropCount
= props
.getLength();
284 for( sal_Int32 index
= 0 ; index
< nPropCount
; ++index
)
286 if ( props
[ index
].Name
.compareToAscii( "Script" ) == 0 )
287 props
[ index
].Value
>>= macroURL
;
289 m_eventBindingHash
[ aName
] = macroURL
;
293 Any SAL_CALL
GlobalEventConfig_Impl::getByName( const OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
296 Sequence
< beans::PropertyValue
> props(2);
297 props
[0].Name
= OUString::createFromAscii("EventType");
298 props
[0].Value
<<= OUString::createFromAscii("Script");
299 props
[1].Name
= OUString::createFromAscii("Script");
300 EventBindingHash::const_iterator it
= m_eventBindingHash
.find( aName
);
301 if( it
!= m_eventBindingHash
.end() )
303 props
[1].Value
<<= it
->second
;
307 // not yet accessed - is it a supported name?
308 SupportedEventsVector::const_iterator pos
= ::std::find(
309 m_supportedEvents
.begin(), m_supportedEvents
.end(), aName
);
310 if ( pos
== m_supportedEvents
.end() )
311 throw container::NoSuchElementException( aName
, NULL
);
313 props
[1].Value
<<= OUString();
319 Sequence
< OUString
> SAL_CALL
GlobalEventConfig_Impl::getElementNames( ) throw (RuntimeException
)
321 const ::rtl::OUString
* pRet
= m_supportedEvents
.empty() ? NULL
: &m_supportedEvents
[0];
322 return uno::Sequence
< ::rtl::OUString
>(pRet
, m_supportedEvents
.size());
325 sal_Bool SAL_CALL
GlobalEventConfig_Impl::hasByName( const OUString
& aName
) throw (RuntimeException
)
327 if ( m_eventBindingHash
.find( aName
) != m_eventBindingHash
.end() )
330 // never accessed before - is it supported in general?
331 SupportedEventsVector::const_iterator pos
= ::std::find(
332 m_supportedEvents
.begin(), m_supportedEvents
.end(), aName
);
333 if ( pos
!= m_supportedEvents
.end() )
339 Type SAL_CALL
GlobalEventConfig_Impl::getElementType( ) throw (RuntimeException
)
341 //DF definitly not sure about this??
342 return ::getCppuType((const Sequence
<beans::PropertyValue
>*)0);
345 sal_Bool SAL_CALL
GlobalEventConfig_Impl::hasElements( ) throw (RuntimeException
)
347 return ( m_eventBindingHash
.empty() );
350 // and now the wrapper
353 //initialize static member
354 GlobalEventConfig_Impl
* GlobalEventConfig::m_pImpl
= NULL
;
355 sal_Int32
GlobalEventConfig::m_nRefCount
= 0 ;
357 GlobalEventConfig::GlobalEventConfig()
359 // Global access, must be guarded (multithreading!).
360 MutexGuard
aGuard( GetOwnStaticMutex() );
361 // Increase our refcount ...
363 // ... and initialize our data container only if it not already exist!
364 if( m_pImpl
== NULL
)
366 m_pImpl
= new GlobalEventConfig_Impl
;
367 ItemHolder1::holdConfigItem(E_EVENTCFG
);
371 GlobalEventConfig::~GlobalEventConfig()
373 // Global access, must be guarded (multithreading!)
374 MutexGuard
aGuard( GetOwnStaticMutex() );
375 // Decrease our refcount.
377 // If last instance was deleted ...
378 // we must destroy our static data container!
379 if( m_nRefCount
<= 0 )
386 void GlobalEventConfig::EstablishFrameCallback(const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XFrame
>& xFrame
)
388 MutexGuard
aGuard( GetOwnStaticMutex() );
389 m_pImpl
->EstablishFrameCallback( xFrame
);
392 Reference
< container::XNameReplace
> SAL_CALL
GlobalEventConfig::getEvents() throw (::com::sun::star::uno::RuntimeException
)
394 MutexGuard
aGuard( GetOwnStaticMutex() );
395 Reference
< container::XNameReplace
> ret(this);
399 void SAL_CALL
GlobalEventConfig::replaceByName( const OUString
& aName
, const Any
& aElement
) throw (lang::IllegalArgumentException
, container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
401 MutexGuard
aGuard( GetOwnStaticMutex() );
402 m_pImpl
->replaceByName( aName
, aElement
);
404 Any SAL_CALL
GlobalEventConfig::getByName( const OUString
& aName
) throw (container::NoSuchElementException
, lang::WrappedTargetException
, RuntimeException
)
406 MutexGuard
aGuard( GetOwnStaticMutex() );
407 return m_pImpl
->getByName( aName
);
409 Sequence
< OUString
> SAL_CALL
GlobalEventConfig::getElementNames( ) throw (RuntimeException
)
411 MutexGuard
aGuard( GetOwnStaticMutex() );
412 return m_pImpl
->getElementNames( );
414 sal_Bool SAL_CALL
GlobalEventConfig::hasByName( const OUString
& aName
) throw (RuntimeException
)
416 MutexGuard
aGuard( GetOwnStaticMutex() );
417 return m_pImpl
->hasByName( aName
);
419 Type SAL_CALL
GlobalEventConfig::getElementType( ) throw (RuntimeException
)
421 MutexGuard
aGuard( GetOwnStaticMutex() );
422 return m_pImpl
->getElementType( );
424 sal_Bool SAL_CALL
GlobalEventConfig::hasElements( ) throw (RuntimeException
)
426 MutexGuard
aGuard( GetOwnStaticMutex() );
427 return m_pImpl
->hasElements( );
430 Mutex
& GlobalEventConfig::GetOwnStaticMutex()
432 // Initialize static mutex only for one time!
433 static Mutex
* pMutex
= NULL
;
434 // If these method first called (Mutex not already exist!) ...
437 // ... we must create a new one. Protect following code with
438 // the global mutex -
439 // It must be - we create a static variable!
440 MutexGuard
aGuard( Mutex::getGlobalMutex() );
441 // We must check our pointer again - because it can be that
442 // another instance of our class will be faster then these!
445 // Create the new mutex and set it for return on static variable.
450 // Return new created or already existing mutex object.
454 ::rtl::OUString
GlobalEventConfig::GetEventName( sal_Int32 nIndex
)
456 return GlobalEventConfig().m_pImpl
->GetEventName( nIndex
);