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