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