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_forms.hxx"
26
27 #include "Button.hxx"
28
29 #include <com/sun/star/awt/XVclWindowPeer.hpp>
30
31 #include <comphelper/streamsection.hxx>
32 #include <comphelper/basicio.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <tools/debug.hxx>
35 #include <tools/urlobj.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vos/mutex.hxx>
38
39 //.........................................................................
40 namespace frm
41 {
42 //.........................................................................
43
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::sdb;
46 using namespace ::com::sun::star::sdbc;
47 using namespace ::com::sun::star::sdbcx;
48 using namespace ::com::sun::star::beans;
49 using namespace ::com::sun::star::container;
50 using namespace ::com::sun::star::form;
51 using namespace ::com::sun::star::awt;
52 using namespace ::com::sun::star::io;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::util;
55 using ::com::sun::star::frame::XDispatchProviderInterceptor;
56
57 //==================================================================
58 //= OButtonModel
59 //==================================================================
DBG_NAME(OButtonModel)60 DBG_NAME(OButtonModel)
61 //------------------------------------------------------------------
62 InterfaceRef SAL_CALL OButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
63 {
64 return *(new OButtonModel(_rxFactory));
65 }
66
67 //------------------------------------------------------------------
OButtonModel(const Reference<XMultiServiceFactory> & _rxFactory)68 OButtonModel::OButtonModel(const Reference<XMultiServiceFactory>& _rxFactory)
69 :OClickableImageBaseModel( _rxFactory, VCL_CONTROLMODEL_COMMANDBUTTON, FRM_SUN_CONTROL_COMMANDBUTTON )
70 // use the old control name for compatibility reasons
71 ,m_aResetHelper( *this, m_aMutex )
72 ,m_eDefaultState( STATE_NOCHECK )
73 {
74 DBG_CTOR( OButtonModel, NULL );
75 m_nClassId = FormComponentType::COMMANDBUTTON;
76 }
77
78 //------------------------------------------------------------------
queryAggregation(const Type & _type)79 Any SAL_CALL OButtonModel::queryAggregation( const Type& _type ) throw(RuntimeException)
80 {
81 Any aReturn = OClickableImageBaseModel::queryAggregation( _type );
82 if ( !aReturn.hasValue() )
83 aReturn = OButtonModel_Base::queryInterface( _type );
84 return aReturn;
85 }
86
87 //------------------------------------------------------------------
_getTypes()88 Sequence< Type > OButtonModel::_getTypes()
89 {
90 return ::comphelper::concatSequences(
91 OClickableImageBaseModel::_getTypes(),
92 OButtonModel_Base::getTypes()
93 );
94 }
95
96 //------------------------------------------------------------------
OButtonModel(const OButtonModel * _pOriginal,const Reference<XMultiServiceFactory> & _rxFactory)97 OButtonModel::OButtonModel( const OButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
98 :OClickableImageBaseModel( _pOriginal, _rxFactory )
99 ,m_aResetHelper( *this, m_aMutex )
100 ,m_eDefaultState( _pOriginal->m_eDefaultState )
101 {
102 DBG_CTOR( OButtonModel, NULL );
103 m_nClassId = FormComponentType::COMMANDBUTTON;
104
105 implInitializeImageURL();
106 }
107
108 //------------------------------------------------------------------------------
~OButtonModel()109 OButtonModel::~OButtonModel()
110 {
111 DBG_DTOR(OButtonModel, NULL);
112 }
113
114 //------------------------------------------------------------------------------
describeFixedProperties(Sequence<Property> & _rProps) const115 void OButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const
116 {
117 BEGIN_DESCRIBE_PROPERTIES( 6, OClickableImageBaseModel )
118 DECL_PROP1( BUTTONTYPE, FormButtonType, BOUND );
119 DECL_PROP1( DEFAULT_STATE, sal_Int16, BOUND );
120 DECL_PROP1( DISPATCHURLINTERNAL, sal_Bool, BOUND );
121 DECL_PROP1( TARGET_URL, ::rtl::OUString, BOUND );
122 DECL_PROP1( TARGET_FRAME, ::rtl::OUString, BOUND );
123 DECL_PROP1( TABINDEX, sal_Int16, BOUND );
124 END_DESCRIBE_PROPERTIES();
125 }
126
127 //------------------------------------------------------------------------------
IMPLEMENT_DEFAULT_CLONING(OButtonModel)128 IMPLEMENT_DEFAULT_CLONING( OButtonModel )
129
130 // XServiceInfo
131 //------------------------------------------------------------------------------
132 StringSequence OButtonModel::getSupportedServiceNames() throw()
133 {
134 StringSequence aSupported = OClickableImageBaseModel::getSupportedServiceNames();
135 aSupported.realloc( aSupported.getLength() + 1 );
136
137 ::rtl::OUString* pArray = aSupported.getArray();
138 pArray[ aSupported.getLength() - 1 ] = FRM_SUN_COMPONENT_COMMANDBUTTON;
139
140 return aSupported;
141 }
142
143 //------------------------------------------------------------------------------
getServiceName()144 ::rtl::OUString OButtonModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException)
145 {
146 return FRM_COMPONENT_COMMANDBUTTON; // old (non-sun) name for compatibility !
147 }
148
149 //------------------------------------------------------------------------------
write(const Reference<XObjectOutputStream> & _rxOutStream)150 void OButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
151 {
152 OClickableImageBaseModel::write(_rxOutStream);
153
154 _rxOutStream->writeShort(0x0003); // Version
155
156 {
157 OStreamSection aSection( _rxOutStream.get() );
158 // this will allow readers to skip unknown bytes in their dtor
159
160 _rxOutStream->writeShort( (sal_uInt16)m_eButtonType );
161
162 ::rtl::OUString sTmp = INetURLObject::decode( m_sTargetURL, '%', INetURLObject::DECODE_UNAMBIGUOUS);
163 _rxOutStream << sTmp;
164 _rxOutStream << m_sTargetFrame;
165 writeHelpTextCompatibly(_rxOutStream);
166 _rxOutStream << isDispatchUrlInternal();
167 }
168 }
169
170 //------------------------------------------------------------------------------
read(const Reference<XObjectInputStream> & _rxInStream)171 void OButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
172 {
173 OClickableImageBaseModel::read(_rxInStream);
174
175 sal_uInt16 nVersion = _rxInStream->readShort(); // Version
176 switch (nVersion)
177 {
178 case 0x0001:
179 {
180 m_eButtonType = (FormButtonType)_rxInStream->readShort();
181
182 _rxInStream >> m_sTargetURL;
183 _rxInStream >> m_sTargetFrame;
184 }
185 break;
186
187 case 0x0002:
188 {
189 m_eButtonType = (FormButtonType)_rxInStream->readShort();
190
191 _rxInStream >> m_sTargetURL;
192 _rxInStream >> m_sTargetFrame;
193 readHelpTextCompatibly(_rxInStream);
194 }
195 break;
196
197 case 0x0003:
198 {
199 OStreamSection aSection( _rxInStream.get() );
200 // this will skip any unknown bytes in it's dtor
201
202 // button type
203 m_eButtonType = (FormButtonType)_rxInStream->readShort();
204
205 // URL
206 _rxInStream >> m_sTargetURL;
207
208 // target frame
209 _rxInStream >> m_sTargetFrame;
210
211 // help text
212 readHelpTextCompatibly(_rxInStream);
213
214 // DispatchInternal
215 sal_Bool bDispath;
216 _rxInStream >> bDispath;
217 setDispatchUrlInternal(bDispath);
218 }
219 break;
220
221 default:
222 DBG_ERROR("OButtonModel::read : unknown version !");
223 m_eButtonType = FormButtonType_PUSH;
224 m_sTargetURL = ::rtl::OUString();
225 m_sTargetFrame = ::rtl::OUString();
226 break;
227 }
228 }
229
230 //--------------------------------------------------------------------
disposing()231 void SAL_CALL OButtonModel::disposing()
232 {
233 m_aResetHelper.disposing();
234 OClickableImageBaseModel::disposing();
235 }
236
237 //--------------------------------------------------------------------
reset()238 void SAL_CALL OButtonModel::reset() throw (RuntimeException)
239 {
240 if ( !m_aResetHelper.approveReset() )
241 return;
242
243 impl_resetNoBroadcast_nothrow();
244
245 m_aResetHelper.notifyResetted();
246 }
247
248 //--------------------------------------------------------------------
addResetListener(const Reference<XResetListener> & _listener)249 void SAL_CALL OButtonModel::addResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException)
250 {
251 m_aResetHelper.addResetListener( _listener );
252 }
253
254 //--------------------------------------------------------------------
removeResetListener(const Reference<XResetListener> & _listener)255 void SAL_CALL OButtonModel::removeResetListener( const Reference< XResetListener >& _listener ) throw (RuntimeException)
256 {
257 m_aResetHelper.removeResetListener( _listener );
258 }
259
260 //--------------------------------------------------------------------
getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const261 void SAL_CALL OButtonModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
262 {
263 switch ( _nHandle )
264 {
265 case PROPERTY_ID_DEFAULT_STATE:
266 _rValue <<= (sal_Int16)m_eDefaultState;
267 break;
268
269 default:
270 OClickableImageBaseModel::getFastPropertyValue( _rValue, _nHandle );
271 break;
272 }
273 }
274
275 //--------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle,const Any & _rValue)276 void SAL_CALL OButtonModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception)
277 {
278 switch ( _nHandle )
279 {
280 case PROPERTY_ID_DEFAULT_STATE:
281 {
282 sal_Int16 nDefaultState( (sal_Int16)STATE_NOCHECK );
283 OSL_VERIFY( _rValue >>= nDefaultState );
284 m_eDefaultState = (ToggleState)nDefaultState;
285 impl_resetNoBroadcast_nothrow();
286 }
287 break;
288
289 default:
290 OClickableImageBaseModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
291 break;
292 }
293 }
294
295 //--------------------------------------------------------------------
convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)296 sal_Bool SAL_CALL OButtonModel::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException)
297 {
298 sal_Bool bModified = sal_False;
299 switch ( _nHandle )
300 {
301 case PROPERTY_ID_DEFAULT_STATE:
302 bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, (sal_Int16)m_eDefaultState );
303 break;
304
305 default:
306 bModified = OClickableImageBaseModel::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue );
307 break;
308 }
309 return bModified;
310 }
311
312 //--------------------------------------------------------------------
getPropertyDefaultByHandle(sal_Int32 _nHandle) const313 Any OButtonModel::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
314 {
315 Any aDefault;
316 switch ( _nHandle )
317 {
318 case PROPERTY_ID_DEFAULT_STATE:
319 aDefault <<= (sal_Int16)STATE_NOCHECK;
320 break;
321
322 default:
323 aDefault = OClickableImageBaseModel::getPropertyDefaultByHandle( _nHandle );
324 break;
325 }
326 return aDefault;
327 }
328
329 //--------------------------------------------------------------------
impl_resetNoBroadcast_nothrow()330 void OButtonModel::impl_resetNoBroadcast_nothrow()
331 {
332 try
333 {
334 setPropertyValue( PROPERTY_STATE, getPropertyValue( PROPERTY_DEFAULT_STATE ) );
335 }
336 catch( const Exception& )
337 {
338 DBG_UNHANDLED_EXCEPTION();
339 }
340 }
341
342 //==================================================================
343 // OButtonControl
344 //==================================================================
345 //------------------------------------------------------------------
OButtonControl_CreateInstance(const Reference<XMultiServiceFactory> & _rxFactory)346 InterfaceRef SAL_CALL OButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
347 {
348 return *(new OButtonControl(_rxFactory));
349 }
350
351 //------------------------------------------------------------------------------
_getTypes()352 Sequence<Type> OButtonControl::_getTypes()
353 {
354 return ::comphelper::concatSequences(
355 OButtonControl_BASE::getTypes(),
356 OClickableImageBaseControl::_getTypes(),
357 OFormNavigationHelper::getTypes()
358 );
359 }
360
361 //------------------------------------------------------------------------------
getSupportedServiceNames()362 StringSequence OButtonControl::getSupportedServiceNames() throw()
363 {
364 StringSequence aSupported = OClickableImageBaseControl::getSupportedServiceNames();
365 aSupported.realloc(aSupported.getLength() + 1);
366
367 ::rtl::OUString*pArray = aSupported.getArray();
368 pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_COMMANDBUTTON;
369 return aSupported;
370 }
371
372 //------------------------------------------------------------------------------
OButtonControl(const Reference<XMultiServiceFactory> & _rxFactory)373 OButtonControl::OButtonControl(const Reference<XMultiServiceFactory>& _rxFactory)
374 :OClickableImageBaseControl(_rxFactory, VCL_CONTROL_COMMANDBUTTON)
375 ,OFormNavigationHelper( _rxFactory )
376 ,m_nClickEvent( 0 )
377 ,m_nTargetUrlFeatureId( -1 )
378 ,m_bEnabledByPropertyValue( sal_False )
379 {
380 increment(m_refCount);
381 {
382 // als ActionListener anmelden
383 Reference<XButton> xButton;
384 query_aggregation( m_xAggregate, xButton);
385 if (xButton.is())
386 xButton->addActionListener(this);
387 }
388 // Refcount bei 1 fuer Listener
389 decrement(m_refCount);
390 }
391
392 //------------------------------------------------------------------------------
~OButtonControl()393 OButtonControl::~OButtonControl()
394 {
395 if (m_nClickEvent)
396 Application::RemoveUserEvent(m_nClickEvent);
397 }
398
399 // UNO Anbindung
400 //------------------------------------------------------------------------------
queryAggregation(const Type & _rType)401 Any SAL_CALL OButtonControl::queryAggregation(const Type& _rType) throw (RuntimeException)
402 {
403 // if asked for the XTypeProvider, don't let OButtonControl_BASE do this
404 Any aReturn;
405 if ( !_rType.equals( ::getCppuType( static_cast< Reference< XTypeProvider >* >( NULL ) ) ) )
406 aReturn = OButtonControl_BASE::queryInterface( _rType );
407
408 if ( !aReturn.hasValue() )
409 aReturn = OClickableImageBaseControl::queryAggregation( _rType );
410
411 if ( !aReturn.hasValue() )
412 aReturn = OFormNavigationHelper::queryInterface( _rType );
413
414 return aReturn;
415 }
416
417 //------------------------------------------------------------------------------
disposing()418 void SAL_CALL OButtonControl::disposing()
419 {
420 startOrStopModelPropertyListening( false );
421
422 OClickableImageBaseControl::disposing();
423 OFormNavigationHelper::dispose();
424 }
425
426 //------------------------------------------------------------------------------
disposing(const EventObject & _rSource)427 void SAL_CALL OButtonControl::disposing( const EventObject& _rSource ) throw( RuntimeException )
428 {
429 OControl::disposing( _rSource );
430 OFormNavigationHelper::disposing( _rSource );
431 }
432
433 // ActionListener
434 //------------------------------------------------------------------------------
actionPerformed(const ActionEvent &)435 void OButtonControl::actionPerformed(const ActionEvent& /*rEvent*/) throw ( ::com::sun::star::uno::RuntimeException)
436 {
437 // Asynchron fuer starutil::URL-Button
438 sal_uLong n = Application::PostUserEvent( LINK(this, OButtonControl,OnClick) );
439 {
440 ::osl::MutexGuard aGuard( m_aMutex );
441 m_nClickEvent = n;
442 }
443 }
444
445 //------------------------------------------------------------------------------
IMPL_LINK(OButtonControl,OnClick,void *,EMPTYARG)446 IMPL_LINK( OButtonControl, OnClick, void*, EMPTYARG )
447 {
448 ::osl::ClearableMutexGuard aGuard( m_aMutex );
449 m_nClickEvent = 0;
450
451 if (m_aApproveActionListeners.getLength())
452 {
453 // if there are listeners, start the action in an own thread, to not allow
454 // them to block us here (we're in the application's main thread)
455 getImageProducerThread()->addEvent();
456 }
457 else
458 {
459 // Sonst nicht. Dann darf man aber auf keinen Fal die Listener
460 // benachrichtigen, auch dann nicht, wenn er spaeter hinzukommt.
461 aGuard.clear();
462
463 // recognize the button type
464 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
465 if (!xSet.is())
466 return 0L;
467
468 if (FormButtonType_PUSH == *(FormButtonType*)xSet->getPropertyValue(PROPERTY_BUTTONTYPE).getValue())
469 {
470 // notify the action listeners for a push button
471 ::cppu::OInterfaceIteratorHelper aIter(m_aActionListeners);
472 ActionEvent aEvt(static_cast<XWeak*>(this), m_aActionCommand);
473 while(aIter.hasMoreElements() )
474 {
475 // catch exceptions
476 // and catch them on a per-listener basis - if one listener fails, the others still need
477 // to get notified
478 // 97676 - 21.02.2002 - fs@openoffice.org
479 try
480 {
481 static_cast< XActionListener* >( aIter.next() )->actionPerformed(aEvt);
482 }
483 #ifdef DBG_UTIL
484 catch( const RuntimeException& )
485 {
486 // silent this
487 }
488 #endif
489 catch( const Exception& )
490 {
491 DBG_ERROR( "OButtonControl::OnClick: caught a exception other than RuntimeException!" );
492 }
493 }
494 }
495 else
496 actionPerformed_Impl( sal_False, ::com::sun::star::awt::MouseEvent() );
497 }
498 return 0L;
499 }
500
501 //------------------------------------------------------------------------------
actionPerformed_Impl(sal_Bool _bNotifyListener,const::com::sun::star::awt::MouseEvent & _rEvt)502 void OButtonControl::actionPerformed_Impl( sal_Bool _bNotifyListener, const ::com::sun::star::awt::MouseEvent& _rEvt )
503 {
504 {
505 sal_Int16 nFeatureId = -1;
506 {
507 ::osl::MutexGuard aGuard( m_aMutex );
508 nFeatureId = m_nTargetUrlFeatureId;
509 }
510
511 if ( nFeatureId != -1 )
512 {
513 if ( !approveAction() )
514 return;
515
516 ::vos::OGuard aGuard( Application::GetSolarMutex() );
517 dispatch( nFeatureId );
518 return;
519 }
520 }
521
522 OClickableImageBaseControl::actionPerformed_Impl( _bNotifyListener, _rEvt );
523 }
524
525 // XButton
526 //------------------------------------------------------------------------------
setLabel(const::rtl::OUString & Label)527 void OButtonControl::setLabel(const ::rtl::OUString& Label) throw( RuntimeException )
528 {
529 Reference<XButton> xButton;
530 query_aggregation( m_xAggregate, xButton );
531 if (xButton.is())
532 xButton->setLabel(Label);
533 }
534
535 //------------------------------------------------------------------------------
setActionCommand(const::rtl::OUString & _rCommand)536 void SAL_CALL OButtonControl::setActionCommand(const ::rtl::OUString& _rCommand) throw( RuntimeException )
537 {
538 {
539 ::osl::MutexGuard aGuard( m_aMutex );
540 m_aActionCommand = _rCommand;
541 }
542
543 Reference<XButton> xButton;
544 query_aggregation( m_xAggregate, xButton);
545 if (xButton.is())
546 xButton->setActionCommand(_rCommand);
547 }
548
549 //------------------------------------------------------------------------------
addActionListener(const Reference<XActionListener> & _rxListener)550 void SAL_CALL OButtonControl::addActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException )
551 {
552 m_aActionListeners.addInterface(_rxListener);
553 }
554
555 //------------------------------------------------------------------------------
removeActionListener(const Reference<XActionListener> & _rxListener)556 void SAL_CALL OButtonControl::removeActionListener(const Reference<XActionListener>& _rxListener) throw( RuntimeException )
557 {
558 m_aActionListeners.removeInterface(_rxListener);
559 }
560
561 //------------------------------------------------------------------------------
562 class DoPropertyListening
563 {
564 private:
565 Reference< XPropertySet > m_xProps;
566 Reference< XPropertyChangeListener > m_xListener;
567 bool m_bStartListening;
568
569 public:
570 DoPropertyListening(
571 const Reference< XInterface >& _rxComponent,
572 const Reference< XPropertyChangeListener >& _rxListener,
573 bool _bStart
574 );
575
576 void handleListening( const ::rtl::OUString& _rPropertyName );
577 };
578
579 //..............................................................................
DoPropertyListening(const Reference<XInterface> & _rxComponent,const Reference<XPropertyChangeListener> & _rxListener,bool _bStart)580 DoPropertyListening::DoPropertyListening(
581 const Reference< XInterface >& _rxComponent, const Reference< XPropertyChangeListener >& _rxListener,
582 bool _bStart )
583 :m_xProps( _rxComponent, UNO_QUERY )
584 ,m_xListener( _rxListener )
585 ,m_bStartListening( _bStart )
586 {
587 DBG_ASSERT( m_xProps.is() || !_rxComponent.is(), "DoPropertyListening::DoPropertyListening: valid component, but no property set!" );
588 DBG_ASSERT( m_xListener.is(), "DoPropertyListening::DoPropertyListening: invalid listener!" );
589 }
590
591 //..............................................................................
handleListening(const::rtl::OUString & _rPropertyName)592 void DoPropertyListening::handleListening( const ::rtl::OUString& _rPropertyName )
593 {
594 if ( m_xProps.is() )
595 {
596 if ( m_bStartListening )
597 m_xProps->addPropertyChangeListener( _rPropertyName, m_xListener );
598 else
599 m_xProps->removePropertyChangeListener( _rPropertyName, m_xListener );
600 }
601 }
602
603 //------------------------------------------------------------------------------
startOrStopModelPropertyListening(bool _bStart)604 void OButtonControl::startOrStopModelPropertyListening( bool _bStart )
605 {
606 DoPropertyListening aListeningHandler( getModel(), this, _bStart );
607 aListeningHandler.handleListening( PROPERTY_TARGET_URL );
608 aListeningHandler.handleListening( PROPERTY_BUTTONTYPE );
609 aListeningHandler.handleListening( PROPERTY_ENABLED );
610 }
611
612 //------------------------------------------------------------------------------
setModel(const Reference<XControlModel> & _rxModel)613 sal_Bool SAL_CALL OButtonControl::setModel( const Reference< XControlModel >& _rxModel ) throw ( RuntimeException )
614 {
615 startOrStopModelPropertyListening( false );
616 sal_Bool bResult = OClickableImageBaseControl::setModel( _rxModel );
617 startOrStopModelPropertyListening( true );
618
619 m_bEnabledByPropertyValue = sal_True;
620 Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY );
621 if ( xModelProps.is() )
622 xModelProps->getPropertyValue( PROPERTY_ENABLED ) >>= m_bEnabledByPropertyValue;
623
624 modelFeatureUrlPotentiallyChanged( );
625
626 return bResult;
627 }
628
629 //------------------------------------------------------------------------------
modelFeatureUrlPotentiallyChanged()630 void OButtonControl::modelFeatureUrlPotentiallyChanged( )
631 {
632 sal_Int16 nOldUrlFeatureId = m_nTargetUrlFeatureId;
633
634 // doe we have another TargetURL now? If so, we need to update our dispatches
635 m_nTargetUrlFeatureId = getModelUrlFeatureId( );
636 if ( nOldUrlFeatureId != m_nTargetUrlFeatureId )
637 {
638 invalidateSupportedFeaturesSet();
639 if ( !isDesignMode() )
640 updateDispatches( );
641 }
642 }
643
644 //------------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & _rEvent)645 void SAL_CALL OButtonControl::propertyChange( const PropertyChangeEvent& _rEvent ) throw ( RuntimeException )
646 {
647 if ( _rEvent.PropertyName.equals( PROPERTY_TARGET_URL )
648 || _rEvent.PropertyName.equals( PROPERTY_BUTTONTYPE )
649 )
650 {
651 modelFeatureUrlPotentiallyChanged( );
652 }
653 else if ( _rEvent.PropertyName.equals( PROPERTY_ENABLED ) )
654 {
655 _rEvent.NewValue >>= m_bEnabledByPropertyValue;
656 }
657 }
658
659 //------------------------------------------------------------------------------
660 namespace
661 {
isFormControllerURL(const::rtl::OUString & _rURL)662 bool isFormControllerURL( const ::rtl::OUString& _rURL )
663 {
664 const sal_Int32 nPrefixLen = URL_CONTROLLER_PREFIX.length;
665 return ( _rURL.getLength() > nPrefixLen )
666 && ( _rURL.compareToAscii( URL_CONTROLLER_PREFIX, nPrefixLen ) == 0 );
667 }
668 }
669
670 //------------------------------------------------------------------------------
getModelUrlFeatureId() const671 sal_Int16 OButtonControl::getModelUrlFeatureId( ) const
672 {
673 sal_Int16 nFeatureId = -1;
674
675 // some URL related properties of the model
676 ::rtl::OUString sUrl;
677 FormButtonType eButtonType = FormButtonType_PUSH;
678
679 Reference< XPropertySet > xModelProps( const_cast< OButtonControl* >( this )->getModel(), UNO_QUERY );
680 if ( xModelProps.is() )
681 {
682 xModelProps->getPropertyValue( PROPERTY_TARGET_URL ) >>= sUrl;
683 xModelProps->getPropertyValue( PROPERTY_BUTTONTYPE ) >>= eButtonType;
684 }
685
686 // are we an URL button?
687 if ( eButtonType == FormButtonType_URL )
688 {
689 // is it a feature URL?
690 if ( isFormControllerURL( sUrl ) )
691 {
692 OFormNavigationMapper aMapper( m_aContext.getLegacyServiceFactory() );
693 nFeatureId = aMapper.getFeatureId( sUrl );
694 }
695 }
696
697 return nFeatureId;
698 }
699
700 //------------------------------------------------------------------
setDesignMode(sal_Bool _bOn)701 void SAL_CALL OButtonControl::setDesignMode( sal_Bool _bOn ) throw( RuntimeException )
702 {
703 OClickableImageBaseControl::setDesignMode( _bOn );
704
705 if ( _bOn )
706 disconnectDispatchers();
707 else
708 connectDispatchers();
709 // this will connect if not already connected and just update else
710 }
711
712 //------------------------------------------------------------------------------
getSupportedFeatures(::std::vector<sal_Int16> & _rFeatureIds)713 void OButtonControl::getSupportedFeatures( ::std::vector< sal_Int16 >& /* [out] */ _rFeatureIds )
714 {
715 if ( -1 != m_nTargetUrlFeatureId )
716 _rFeatureIds.push_back( m_nTargetUrlFeatureId );
717 }
718
719 //------------------------------------------------------------------
featureStateChanged(sal_Int16 _nFeatureId,sal_Bool _bEnabled)720 void OButtonControl::featureStateChanged( sal_Int16 _nFeatureId, sal_Bool _bEnabled )
721 {
722 if ( _nFeatureId == m_nTargetUrlFeatureId )
723 {
724 // enable or disable our peer, according to the new state
725 Reference< XVclWindowPeer > xPeer( getPeer(), UNO_QUERY );
726 if ( xPeer.is() )
727 xPeer->setProperty( PROPERTY_ENABLED, makeAny( m_bEnabledByPropertyValue ? _bEnabled : sal_False ) );
728 // if we're disabled according to our model's property, then
729 // we don't care for the feature state, but *are* disabled.
730 // If the model's property states that we're enabled, then we *do*
731 // care for the feature state
732 }
733
734 // base class
735 OFormNavigationHelper::featureStateChanged( _nFeatureId, _bEnabled );
736 }
737
738 //------------------------------------------------------------------
allFeatureStatesChanged()739 void OButtonControl::allFeatureStatesChanged( )
740 {
741 if ( -1 != m_nTargetUrlFeatureId )
742 // we have only one supported feature, so simulate it has changed ...
743 featureStateChanged( m_nTargetUrlFeatureId, isEnabled( m_nTargetUrlFeatureId ) );
744
745 // base class
746 OFormNavigationHelper::allFeatureStatesChanged( );
747 }
748
749 //------------------------------------------------------------------
isEnabled(sal_Int16 _nFeatureId) const750 bool OButtonControl::isEnabled( sal_Int16 _nFeatureId ) const
751 {
752 if ( const_cast< OButtonControl* >( this )->isDesignMode() )
753 // TODO: the model property?
754 return true;
755
756 return OFormNavigationHelper::isEnabled( _nFeatureId );
757 }
758
759 //--------------------------------------------------------------------
registerDispatchProviderInterceptor(const Reference<XDispatchProviderInterceptor> & _rxInterceptor)760 void SAL_CALL OButtonControl::registerDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
761 {
762 OClickableImageBaseControl::registerDispatchProviderInterceptor( _rxInterceptor );
763 OFormNavigationHelper::registerDispatchProviderInterceptor( _rxInterceptor );
764 }
765
766 //--------------------------------------------------------------------
releaseDispatchProviderInterceptor(const Reference<XDispatchProviderInterceptor> & _rxInterceptor)767 void SAL_CALL OButtonControl::releaseDispatchProviderInterceptor( const Reference< XDispatchProviderInterceptor >& _rxInterceptor ) throw (RuntimeException)
768 {
769 OClickableImageBaseControl::releaseDispatchProviderInterceptor( _rxInterceptor );
770 OFormNavigationHelper::releaseDispatchProviderInterceptor( _rxInterceptor );
771 }
772
773 //.........................................................................
774 } // namespace frm
775 //.........................................................................
776
777