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