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
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_toolkit.hxx"
26
27 #include <vcl/svapp.hxx>
28 #include <vcl/window.hxx>
29 #include <vcl/wall.hxx>
30 #include <vos/mutex.hxx>
31 #include <toolkit/controls/dialogcontrol.hxx>
32 #include <toolkit/helper/property.hxx>
33 #include <toolkit/helper/unopropertyarrayhelper.hxx>
34 #include <toolkit/controls/stdtabcontroller.hxx>
35 #include <com/sun/star/awt/PosSize.hpp>
36 #include <com/sun/star/awt/WindowAttribute.hpp>
37 #include <com/sun/star/resource/XStringResourceResolver.hpp>
38 #include <com/sun/star/graphic/XGraphicProvider.hpp>
39 #include <tools/list.hxx>
40 #include <cppuhelper/typeprovider.hxx>
41 #include <tools/debug.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <comphelper/sequence.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/outdev.hxx>
46
47 #include <toolkit/helper/vclunohelper.hxx>
48 #include <unotools/ucbstreamhelper.hxx>
49 #include <vcl/graph.hxx>
50 #include <vcl/image.hxx>
51 #include <map>
52 #include <algorithm>
53 #include <functional>
54 #include "tools/urlobj.hxx"
55 #include "osl/file.hxx"
56
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::awt;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::container;
62 using namespace ::com::sun::star::beans;
63 using namespace ::com::sun::star::util;
64
65 #define PROPERTY_DIALOGSOURCEURL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogSourceURL" ))
66 #define PROPERTY_IMAGEURL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ImageURL" ))
67 #define PROPERTY_GRAPHIC ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" ))
68 //
69 ////HELPER
70 ::rtl::OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl );
71
72 // ----------------------------------------------------
73 // class UnoControlDialogModel
74 // ----------------------------------------------------
UnoControlDialogModel(const Reference<XMultiServiceFactory> & i_factory)75 UnoControlDialogModel::UnoControlDialogModel( const Reference< XMultiServiceFactory >& i_factory )
76 :ControlModelContainerBase( i_factory )
77 {
78 ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
79 // ImplRegisterProperty( BASEPROPERTY_BORDER );
80 ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
81 ImplRegisterProperty( BASEPROPERTY_ENABLED );
82 ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
83 // ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
84 ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
85 ImplRegisterProperty( BASEPROPERTY_HELPURL );
86 ImplRegisterProperty( BASEPROPERTY_TITLE );
87 ImplRegisterProperty( BASEPROPERTY_SIZEABLE );
88 ImplRegisterProperty( BASEPROPERTY_DESKTOP_AS_PARENT );
89 ImplRegisterProperty( BASEPROPERTY_DECORATION );
90 ImplRegisterProperty( BASEPROPERTY_DIALOGSOURCEURL );
91 ImplRegisterProperty( BASEPROPERTY_GRAPHIC );
92 ImplRegisterProperty( BASEPROPERTY_IMAGEURL );
93
94 Any aBool;
95 aBool <<= (sal_Bool) sal_True;
96 ImplRegisterProperty( BASEPROPERTY_MOVEABLE, aBool );
97 ImplRegisterProperty( BASEPROPERTY_CLOSEABLE, aBool );
98 }
99
UnoControlDialogModel(const UnoControlDialogModel & rModel)100 UnoControlDialogModel::UnoControlDialogModel( const UnoControlDialogModel& rModel )
101 : ControlModelContainerBase( rModel )
102 {
103 }
104
~UnoControlDialogModel()105 UnoControlDialogModel::~UnoControlDialogModel()
106 {
107 }
108
Clone() const109 UnoControlModel* UnoControlDialogModel::Clone() const
110 {
111 // clone the container itself
112 UnoControlDialogModel* pClone = new UnoControlDialogModel( *this );
113
114 Clone_Impl(*pClone);
115
116 return pClone;
117 }
118
119
getServiceName()120 ::rtl::OUString UnoControlDialogModel::getServiceName( ) throw(RuntimeException)
121 {
122 return ::rtl::OUString::createFromAscii( szServiceName_UnoControlDialogModel );
123 }
124
ImplGetDefaultValue(sal_uInt16 nPropId) const125 Any UnoControlDialogModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
126 {
127 Any aAny;
128
129 switch ( nPropId )
130 {
131 case BASEPROPERTY_DEFAULTCONTROL:
132 aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlDialog );
133 break;
134 default:
135 aAny = UnoControlModel::ImplGetDefaultValue( nPropId );
136 }
137
138 return aAny;
139 }
140
getInfoHelper()141 ::cppu::IPropertyArrayHelper& UnoControlDialogModel::getInfoHelper()
142 {
143 static UnoPropertyArrayHelper* pHelper = NULL;
144 if ( !pHelper )
145 {
146 Sequence<sal_Int32> aIDs = ImplGetPropertyIds();
147 pHelper = new UnoPropertyArrayHelper( aIDs );
148 }
149 return *pHelper;
150 }
151
152 // XMultiPropertySet
getPropertySetInfo()153 Reference< XPropertySetInfo > UnoControlDialogModel::getPropertySetInfo( ) throw(RuntimeException)
154 {
155 static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
156 return xInfo;
157 }
158
159 // ============================================================================
160 // = class UnoDialogControl
161 // ============================================================================
162
UnoDialogControl(const uno::Reference<lang::XMultiServiceFactory> & i_factory)163 UnoDialogControl::UnoDialogControl( const uno::Reference< lang::XMultiServiceFactory >& i_factory )
164 :UnoDialogControl_Base( i_factory )
165 ,maTopWindowListeners( *this )
166 ,mbWindowListener(false)
167 {
168 maComponentInfos.nWidth = 300;
169 maComponentInfos.nHeight = 450;
170 }
171
~UnoDialogControl()172 UnoDialogControl::~UnoDialogControl()
173 {
174 }
175
GetComponentServiceName()176 ::rtl::OUString UnoDialogControl::GetComponentServiceName()
177 {
178
179 sal_Bool bDecoration( sal_True );
180 ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DECORATION )) >>= bDecoration;
181 if ( bDecoration )
182 return ::rtl::OUString::createFromAscii( "Dialog" );
183 else
184 return ::rtl::OUString::createFromAscii( "TabPage" );
185 }
186
dispose()187 void UnoDialogControl::dispose() throw(RuntimeException)
188 {
189 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
190
191 EventObject aEvt;
192 aEvt.Source = static_cast< ::cppu::OWeakObject* >( this );
193 maTopWindowListeners.disposeAndClear( aEvt );
194 ControlContainerBase::dispose();
195 }
196
disposing(const EventObject & Source)197 void SAL_CALL UnoDialogControl::disposing(
198 const EventObject& Source )
199 throw(RuntimeException)
200 {
201 ControlContainerBase::disposing( Source );
202 }
203
setModel(const Reference<XControlModel> & rxModel)204 sal_Bool UnoDialogControl::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException)
205 {
206 // #Can we move all the Resource stuff to the ControlContainerBase ?
207 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
208 sal_Bool bRet = ControlContainerBase::setModel( rxModel );
209 ImplStartListingForResourceEvents();
210 return bRet;
211 }
212
createPeer(const Reference<XToolkit> & rxToolkit,const Reference<XWindowPeer> & rParentPeer)213 void UnoDialogControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException)
214 {
215 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
216
217 UnoControlContainer::createPeer( rxToolkit, rParentPeer );
218
219 Reference < XTopWindow > xTW( getPeer(), UNO_QUERY );
220 if ( xTW.is() )
221 {
222 xTW->setMenuBar( mxMenuBar );
223
224 if ( !mbWindowListener )
225 {
226 Reference< XWindowListener > xWL( static_cast< cppu::OWeakObject*>( this ), UNO_QUERY );
227 addWindowListener( xWL );
228 mbWindowListener = true;
229 }
230
231 if ( maTopWindowListeners.getLength() )
232 xTW->addTopWindowListener( &maTopWindowListeners );
233 }
234 }
235
PrepareWindowDescriptor(::com::sun::star::awt::WindowDescriptor & rDesc)236 void UnoDialogControl::PrepareWindowDescriptor( ::com::sun::star::awt::WindowDescriptor& rDesc )
237 {
238 sal_Bool bDecoration( sal_True );
239 ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DECORATION )) >>= bDecoration;
240 if ( !bDecoration )
241 {
242 // Now we have to manipulate the WindowDescriptor
243 rDesc.WindowAttributes = rDesc.WindowAttributes | ::com::sun::star::awt::WindowAttribute::NODECORATION;
244 }
245
246 // We have to set the graphic property before the peer
247 // will be created. Otherwise the properties will be copied
248 // into the peer via propertiesChangeEvents. As the order of
249 // can lead to overwrites we have to set the graphic property
250 // before the propertiesChangeEvents are sent!
251 ::rtl::OUString aImageURL;
252 Reference< graphic::XGraphic > xGraphic;
253 if (( ImplGetPropertyValue( PROPERTY_IMAGEURL ) >>= aImageURL ) &&
254 ( aImageURL.getLength() > 0 ))
255 {
256 ::rtl::OUString absoluteUrl =
257 getPhysicalLocation( ImplGetPropertyValue( PROPERTY_DIALOGSOURCEURL ),
258 ImplGetPropertyValue( PROPERTY_IMAGEURL ));
259
260 xGraphic = ControlContainerBase::Impl_getGraphicFromURL_nothrow( absoluteUrl );
261 ImplSetPropertyValue( PROPERTY_GRAPHIC, uno::makeAny( xGraphic ), sal_True );
262 }
263 }
264
addTopWindowListener(const Reference<XTopWindowListener> & rxListener)265 void UnoDialogControl::addTopWindowListener( const Reference< XTopWindowListener >& rxListener ) throw (RuntimeException)
266 {
267 maTopWindowListeners.addInterface( rxListener );
268 if( getPeer().is() && maTopWindowListeners.getLength() == 1 )
269 {
270 Reference < XTopWindow > xTW( getPeer(), UNO_QUERY );
271 xTW->addTopWindowListener( &maTopWindowListeners );
272 }
273 }
274
removeTopWindowListener(const Reference<XTopWindowListener> & rxListener)275 void UnoDialogControl::removeTopWindowListener( const Reference< XTopWindowListener >& rxListener ) throw (RuntimeException)
276 {
277 if( getPeer().is() && maTopWindowListeners.getLength() == 1 )
278 {
279 Reference < XTopWindow > xTW( getPeer(), UNO_QUERY );
280 xTW->removeTopWindowListener( &maTopWindowListeners );
281 }
282 maTopWindowListeners.removeInterface( rxListener );
283 }
284
toFront()285 void UnoDialogControl::toFront( ) throw (RuntimeException)
286 {
287 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
288 if ( getPeer().is() )
289 {
290 Reference< XTopWindow > xTW( getPeer(), UNO_QUERY );
291 if( xTW.is() )
292 xTW->toFront();
293 }
294 }
295
toBack()296 void UnoDialogControl::toBack( ) throw (RuntimeException)
297 {
298 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
299 if ( getPeer().is() )
300 {
301 Reference< XTopWindow > xTW( getPeer(), UNO_QUERY );
302 if( xTW.is() )
303 xTW->toBack();
304 }
305 }
306
setMenuBar(const Reference<XMenuBar> & rxMenuBar)307 void UnoDialogControl::setMenuBar( const Reference< XMenuBar >& rxMenuBar ) throw (RuntimeException)
308 {
309 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
310 mxMenuBar = rxMenuBar;
311 if ( getPeer().is() )
312 {
313 Reference< XTopWindow > xTW( getPeer(), UNO_QUERY );
314 if( xTW.is() )
315 xTW->setMenuBar( mxMenuBar );
316 }
317 }
ImplMapPixelToAppFont(OutputDevice * pOutDev,const::Size & aSize)318 static ::Size ImplMapPixelToAppFont( OutputDevice* pOutDev, const ::Size& aSize )
319 {
320 ::Size aTmp = pOutDev->PixelToLogic( aSize, MAP_APPFONT );
321 return aTmp;
322 }
323 // ::com::sun::star::awt::XWindowListener
windowResized(const::com::sun::star::awt::WindowEvent & e)324 void SAL_CALL UnoDialogControl::windowResized( const ::com::sun::star::awt::WindowEvent& e )
325 throw (::com::sun::star::uno::RuntimeException)
326 {
327 OutputDevice*pOutDev = Application::GetDefaultDevice();
328 DBG_ASSERT( pOutDev, "Missing Default Device!" );
329 if ( pOutDev && !mbSizeModified )
330 {
331 // Currentley we are simply using MAP_APPFONT
332 ::Size aAppFontSize( e.Width, e.Height );
333
334 Reference< XControl > xDialogControl( *this, UNO_QUERY_THROW );
335 Reference< XDevice > xDialogDevice( xDialogControl->getPeer(), UNO_QUERY );
336 OSL_ENSURE( xDialogDevice.is(), "UnoDialogControl::windowResized: no peer, but a windowResized event?" );
337
338 // #i87592 In design mode the drawing layer works with sizes with decoration.
339 // Therefore we have to subtract them before writing back to the properties (model).
340 if ( xDialogDevice.is() && mbDesignMode )
341 {
342 DeviceInfo aDeviceInfo( xDialogDevice->getInfo() );
343 aAppFontSize.Width() -= aDeviceInfo.LeftInset + aDeviceInfo.RightInset;
344 aAppFontSize.Height() -= aDeviceInfo.TopInset + aDeviceInfo.BottomInset;
345 }
346
347 aAppFontSize = ImplMapPixelToAppFont( pOutDev, aAppFontSize );
348
349 // Remember that changes have been done by listener. No need to
350 // update the position because of property change event.
351 mbSizeModified = true;
352 Sequence< rtl::OUString > aProps( 2 );
353 Sequence< Any > aValues( 2 );
354 // Properties in a sequence must be sorted!
355 aProps[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Height" ));
356 aProps[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Width" ));
357 aValues[0] <<= aAppFontSize.Height();
358 aValues[1] <<= aAppFontSize.Width();
359
360 ImplSetPropertyValues( aProps, aValues, true );
361 mbSizeModified = false;
362 }
363 }
364
windowMoved(const::com::sun::star::awt::WindowEvent & e)365 void SAL_CALL UnoDialogControl::windowMoved( const ::com::sun::star::awt::WindowEvent& e )
366 throw (::com::sun::star::uno::RuntimeException)
367 {
368 OutputDevice*pOutDev = Application::GetDefaultDevice();
369 DBG_ASSERT( pOutDev, "Missing Default Device!" );
370 if ( pOutDev && !mbPosModified )
371 {
372 // Currentley we are simply using MAP_APPFONT
373 Any aAny;
374 ::Size aTmp( e.X, e.Y );
375 aTmp = ImplMapPixelToAppFont( pOutDev, aTmp );
376
377 // Remember that changes have been done by listener. No need to
378 // update the position because of property change event.
379 mbPosModified = true;
380 Sequence< rtl::OUString > aProps( 2 );
381 Sequence< Any > aValues( 2 );
382 aProps[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PositionX" ));
383 aProps[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PositionY" ));
384 aValues[0] <<= aTmp.Width();
385 aValues[1] <<= aTmp.Height();
386
387 ImplSetPropertyValues( aProps, aValues, true );
388 mbPosModified = false;
389 }
390 }
391
windowShown(const EventObject & e)392 void SAL_CALL UnoDialogControl::windowShown( const EventObject& e ) throw (RuntimeException)
393 {
394 (void)e;
395 }
396
windowHidden(const EventObject & e)397 void SAL_CALL UnoDialogControl::windowHidden( const EventObject& e ) throw (RuntimeException)
398 {
399 (void)e;
400 }
401
endDialog(::sal_Int32 i_result)402 void SAL_CALL UnoDialogControl::endDialog( ::sal_Int32 i_result ) throw (RuntimeException)
403 {
404 Reference< XDialog2 > xPeerDialog( getPeer(), UNO_QUERY );
405 if ( xPeerDialog.is() )
406 xPeerDialog->endDialog( i_result );
407 }
408
setHelpId(const rtl::OUString & i_id)409 void SAL_CALL UnoDialogControl::setHelpId( const rtl::OUString& i_id ) throw (RuntimeException)
410 {
411 Reference< XDialog2 > xPeerDialog( getPeer(), UNO_QUERY );
412 if ( xPeerDialog.is() )
413 xPeerDialog->setHelpId( i_id );
414 }
415
setTitle(const::rtl::OUString & Title)416 void UnoDialogControl::setTitle( const ::rtl::OUString& Title ) throw(RuntimeException)
417 {
418 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
419 Any aAny;
420 aAny <<= Title;
421 ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TITLE ), aAny, sal_True );
422 }
423
getTitle()424 ::rtl::OUString UnoDialogControl::getTitle() throw(RuntimeException)
425 {
426 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
427 return ImplGetPropertyValue_UString( BASEPROPERTY_TITLE );
428 }
429
execute()430 sal_Int16 UnoDialogControl::execute() throw(RuntimeException)
431 {
432 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
433 sal_Int16 nDone = -1;
434 if ( getPeer().is() )
435 {
436 Reference< XDialog > xDlg( getPeer(), UNO_QUERY );
437 if( xDlg.is() )
438 {
439 GetComponentInfos().bVisible = sal_True;
440 nDone = xDlg->execute();
441 GetComponentInfos().bVisible = sal_False;
442 }
443 }
444 return nDone;
445 }
446
endExecute()447 void UnoDialogControl::endExecute() throw(RuntimeException)
448 {
449 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
450 if ( getPeer().is() )
451 {
452 Reference< XDialog > xDlg( getPeer(), UNO_QUERY );
453 if( xDlg.is() )
454 {
455 xDlg->endExecute();
456 GetComponentInfos().bVisible = sal_False;
457 }
458 }
459 }
460
461 // XModifyListener
modified(const lang::EventObject &)462 void SAL_CALL UnoDialogControl::modified(
463 const lang::EventObject& /*rEvent*/ )
464 throw (RuntimeException)
465 {
466 ImplUpdateResourceResolver();
467 }
468
ImplModelPropertiesChanged(const Sequence<PropertyChangeEvent> & rEvents)469 void UnoDialogControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException)
470 {
471 sal_Int32 nLen = rEvents.getLength();
472 for( sal_Int32 i = 0; i < nLen; i++ )
473 {
474 const PropertyChangeEvent& rEvt = rEvents.getConstArray()[i];
475 Reference< XControlModel > xModel( rEvt.Source, UNO_QUERY );
476 sal_Bool bOwnModel = (XControlModel*)xModel.get() == (XControlModel*)getModel().get();
477 if ( bOwnModel && rEvt.PropertyName.equalsAsciiL( "ImageURL", 8 ))
478 {
479 ::rtl::OUString aImageURL;
480 Reference< graphic::XGraphic > xGraphic;
481 if (( ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_IMAGEURL ) ) >>= aImageURL ) &&
482 ( aImageURL.getLength() > 0 ))
483 {
484 ::rtl::OUString absoluteUrl =
485 getPhysicalLocation( ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DIALOGSOURCEURL )),
486 uno::makeAny(aImageURL));
487
488 xGraphic = Impl_getGraphicFromURL_nothrow( absoluteUrl );
489 }
490 ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_GRAPHIC), uno::makeAny( xGraphic ), sal_True );
491 break;
492 }
493 }
494 ControlContainerBase::ImplModelPropertiesChanged(rEvents);
495 }
496