LibreOffice Module forms (master) 1
FormComponent.cxx
Go to the documentation of this file.
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#include <componenttools.hxx>
20#include <FormComponent.hxx>
21#include <strings.hrc>
22#include <frm_resource.hxx>
23#include <property.hxx>
24#include <services.hxx>
25
26#include <com/sun/star/awt/XTextComponent.hpp>
27#include <com/sun/star/awt/XWindow.hpp>
28#include <com/sun/star/beans/PropertyAttribute.hpp>
29#include <com/sun/star/form/FormComponentType.hpp>
30#include <com/sun/star/form/XForm.hpp>
31#include <com/sun/star/form/XLoadable.hpp>
32#include <com/sun/star/form/binding/IncompatibleTypesException.hpp>
33#include <com/sun/star/io/IOException.hpp>
34#include <com/sun/star/io/XMarkableStream.hpp>
35#include <com/sun/star/lang/DisposedException.hpp>
36#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37#include <com/sun/star/sdb/XRowSetChangeBroadcaster.hpp>
38#include <com/sun/star/sdb/XRowSetSupplier.hpp>
39#include <com/sun/star/sdbc/ColumnValue.hpp>
40#include <com/sun/star/sdbc/DataType.hpp>
41#include <com/sun/star/sdbc/SQLException.hpp>
42#include <com/sun/star/util/VetoException.hpp>
43#include <com/sun/star/util/XModifyBroadcaster.hpp>
44
51#include <tools/debug.hxx>
53#include <sal/log.hxx>
54
55#include <algorithm>
56
57namespace frm
58{
59using namespace ::com::sun::star::uno;
60using namespace ::com::sun::star::sdb;
61using namespace ::com::sun::star::sdbc;
62using namespace ::com::sun::star::sdbcx;
63using namespace ::com::sun::star::beans;
64using namespace ::com::sun::star::container;
65using namespace ::com::sun::star::form;
66using namespace ::com::sun::star::awt;
67using namespace ::com::sun::star::io;
68using namespace ::com::sun::star::lang;
69using namespace ::com::sun::star::util;
70using namespace ::com::sun::star::form::binding;
71using namespace ::com::sun::star::form::validation;
72using namespace ::dbtools;
73using namespace ::comphelper;
74
75// FieldChangeNotifier
77{
79}
80
81void ControlModelLock::addPropertyNotification( const sal_Int32 _nHandle, const Any& _rOldValue, const Any& _rNewValue )
82{
83 assert( m_aHandles.size() == m_aOldValues.size() && m_aOldValues.size() == m_aNewValues.size() );
84
85 m_aHandles.push_back( _nHandle );
86 m_aOldValues.push_back( _rOldValue );
87 m_aNewValues.push_back( _rNewValue );
88}
89
90namespace {
91
92class FieldChangeNotifier
93{
94public:
95 explicit FieldChangeNotifier(ControlModelLock& _rLock)
96 : m_rLock( _rLock )
97 , m_rModel( dynamic_cast< OBoundControlModel& >( _rLock.getModel() ) )
98 {
99 m_xOldField = m_rModel.getField();
100 }
101
102 ~FieldChangeNotifier()
103 {
104 Reference< XPropertySet > xNewField( m_rModel.getField() );
105 if ( m_xOldField != xNewField )
106 m_rLock.addPropertyNotification( PROPERTY_ID_BOUNDFIELD, Any( m_xOldField ), Any( xNewField ) );
107 }
108
109private:
110 ControlModelLock& m_rLock;
111 OBoundControlModel& m_rModel;
112 Reference< XPropertySet > m_xOldField;
113};
114
115}
116
117// base class for form layer controls
118OControl::OControl( const Reference< XComponentContext >& _rxContext, const OUString& _rAggregateService, const bool _bSetDelegator )
119 :OComponentHelper(m_aMutex)
120 ,m_xContext( _rxContext )
121{
122 // Aggregate VCL Control
123 // Increment the RefCount for aggregates, because the aggregate by itself increments the RefCount in the setDelegator
124 osl_atomic_increment( &m_refCount );
125 {
126 m_xAggregate.set(_rxContext->getServiceManager()->createInstanceWithContext(_rAggregateService, _rxContext), css::uno::UNO_QUERY);
127 m_xControl.set(m_xAggregate, css::uno::UNO_QUERY);
128 }
129 osl_atomic_decrement( &m_refCount );
130
131 if ( _bSetDelegator )
133}
134
136{
138}
139
141{
142 if ( m_xAggregate.is() )
143 m_xAggregate->setDelegator( nullptr );
144}
145
147{
148 osl_atomic_increment( &m_refCount );
149 if ( m_xAggregate.is() )
150 { // those brackets are important for some compilers, don't remove!
151 // (they ensure that the temporary object created in the line below
152 // is destroyed *before* the refcount-decrement)
153 m_xAggregate->setDelegator( static_cast< XWeak* >( this ) );
154 }
155 osl_atomic_decrement( &m_refCount );
156}
157
158// UNO Binding
159Any SAL_CALL OControl::queryAggregation( const Type& _rType )
160{
161 // ask the base class
162 Any aReturn( OComponentHelper::queryAggregation(_rType) );
163 // ask our own interfaces
164 if (!aReturn.hasValue())
165 {
166 aReturn = OControl_BASE::queryInterface(_rType);
167 // ask our aggregate
168 if (!aReturn.hasValue() && m_xAggregate.is())
169 aReturn = m_xAggregate->queryAggregation(_rType);
170 }
171
172 return aReturn;
173}
174
175Sequence<sal_Int8> SAL_CALL OControl::getImplementationId()
176{
177 return css::uno::Sequence<sal_Int8>();
178}
179
180Sequence<Type> SAL_CALL OControl::getTypes()
181{
183
184 Reference< XTypeProvider > xProv;
185 if ( query_aggregation( m_xAggregate, xProv ) )
186 aTypes.addTypes( xProv->getTypes() );
187
188 return aTypes.getTypes();
189}
190
191Sequence<Type> OControl::_getTypes()
192{
193 return TypeBag( OComponentHelper::getTypes(), OControl_BASE::getTypes() ).getTypes();
194}
195
196// OComponentHelper
198{
199 OComponentHelper::disposing();
200
201 m_aWindowStateGuard.attach( nullptr, nullptr );
202
203 Reference< XComponent > xComp;
205 xComp->dispose();
206}
207
208// XServiceInfo
209sal_Bool SAL_CALL OControl::supportsService(const OUString& _rsServiceName)
211 return cppu::supportsService(this, _rsServiceName);
212}
213
214Sequence< OUString > OControl::getAggregateServiceNames() const
215{
216 Sequence< OUString > aAggServices;
217 Reference< XServiceInfo > xInfo;
218 if ( query_aggregation( m_xAggregate, xInfo ) )
219 aAggServices = xInfo->getSupportedServiceNames();
220
221 return aAggServices;
222}
223
224Sequence<OUString> SAL_CALL OControl::getSupportedServiceNames()
225{
226 // no own supported service names
228}
229
230// XEventListener
231void SAL_CALL OControl::disposing(const css::lang::EventObject& _rEvent)
232{
233 Reference< XInterface > xAggAsIface;
234 query_aggregation(m_xAggregate, xAggAsIface);
235
236 // does the disposing come from the aggregate?
237 if (xAggAsIface != Reference< XInterface >(_rEvent.Source, UNO_QUERY))
238 { // no -> forward it
239 Reference<css::lang::XEventListener> xListener;
240 if (query_aggregation(m_xAggregate, xListener))
241 xListener->disposing(_rEvent);
242 }
243}
244
245// XControl
246void SAL_CALL OControl::setContext(const Reference< XInterface >& Context)
247{
248 if (m_xControl.is())
249 m_xControl->setContext(Context);
250}
251
252Reference< XInterface > SAL_CALL OControl::getContext()
253{
254 return m_xControl.is() ? m_xControl->getContext() : Reference< XInterface >();
255}
256
258{
259 Reference< XWindow2 > xWindow;
260 Reference< XControlModel > xModel;
261 try
262 {
263 xWindow.set( getPeer(), UNO_QUERY );
264 xModel = getModel();
265 }
266 catch( const Exception& )
267 {
268 DBG_UNHANDLED_EXCEPTION("forms.component");
269 }
271}
272
273void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const Reference<XWindowPeer>& _rxParent)
274{
275 if ( m_xControl.is() )
276 {
277 m_xControl->createPeer( _rxToolkit, _rxParent );
279 }
280}
281
282Reference<XWindowPeer> SAL_CALL OControl::getPeer()
283{
284 return m_xControl.is() ? m_xControl->getPeer() : Reference<XWindowPeer>();
285}
286
287sal_Bool SAL_CALL OControl::setModel(const Reference<XControlModel>& Model)
288{
289 if ( !m_xControl.is() )
290 return false;
291
292 bool bSuccess = m_xControl->setModel( Model );
294 return bSuccess;
295}
296
297Reference<XControlModel> SAL_CALL OControl::getModel()
298{
299 return m_xControl.is() ? m_xControl->getModel() : Reference<XControlModel>();
300}
301
302Reference<XView> SAL_CALL OControl::getView()
303{
304 return m_xControl.is() ? m_xControl->getView() : Reference<XView>();
305}
306
308{
309 if (m_xControl.is())
310 m_xControl->setDesignMode(bOn);
311}
312
314{
315 return !m_xControl.is() || m_xControl->isDesignMode();
316}
317
319{
320 return !m_xControl.is() || m_xControl->isTransparent();
321}
322
323OBoundControl::OBoundControl( const Reference< XComponentContext >& _rxContext,
324 const OUString& _rAggregateService, const bool _bSetDelegator )
325 :OControl( _rxContext, _rAggregateService, _bSetDelegator )
326 ,m_bLocked(false)
327{
328}
329
331{
332}
333
335{
337}
338
340{
341 Any aReturn;
342
343 // XTypeProvider first - don't ask the OBoundControl_BASE, it would deliver incomplete types
344 if ( _rType.equals( cppu::UnoType<XTypeProvider>::get() ) )
345 aReturn = OControl::queryAggregation( _rType );
346
347 // ask our own interfaces
348 // (do this first (except XTypeProvider ) - we want to "overwrite" XPropertiesChangeListener)
349 if ( !aReturn.hasValue() )
350 aReturn = OBoundControl_BASE::queryInterface( _rType );
351
352 // ask the base class
353 if ( !aReturn.hasValue() )
354 aReturn = OControl::queryAggregation( _rType );
355
356 return aReturn;
357}
358
360{
361 return m_bLocked;
362}
363
364void SAL_CALL OBoundControl::setLock(sal_Bool _bLock)
365{
366 if (m_bLocked == bool(_bLock))
367 return;
368
369 osl::MutexGuard aGuard(m_aMutex);
370 _setLock(_bLock);
371 m_bLocked = _bLock;
372}
373
374void OBoundControl::_setLock(bool _bLock)
375{
376 // try to set the text component to readonly
377 Reference< XWindowPeer > xPeer = getPeer();
378 Reference< XTextComponent > xText( xPeer, UNO_QUERY );
379
380 if ( xText.is() )
381 xText->setEditable( !_bLock );
382 else
383 {
384 // disable the window
385 Reference< XWindow > xComp( xPeer, UNO_QUERY );
386 if ( xComp.is() )
387 xComp->setEnable( !_bLock );
388 }
389}
390
391sal_Bool SAL_CALL OBoundControl::setModel( const Reference< XControlModel >& _rxModel )
392{
393 return OControl::setModel( _rxModel );
394}
395
396void SAL_CALL OBoundControl::disposing(const EventObject& Source)
397{
398 // just disambiguate
399 OControl::disposing(Source);
400}
401
405}
407// OControlModel
408Sequence<sal_Int8> SAL_CALL OControlModel::getImplementationId()
409{
410 return css::uno::Sequence<sal_Int8>();
411}
412
413Sequence<Type> SAL_CALL OControlModel::getTypes()
414{
416
417 Reference< XTypeProvider > xProv;
418
419 if ( query_aggregation( m_xAggregate, xProv ) )
420 aTypes.addTypes( xProv->getTypes() );
421
422 return aTypes.getTypes();
423}
424
426{
427 return TypeBag( OComponentHelper::getTypes(),
428 OPropertySetAggregationHelper::getTypes(),
430 ).getTypes();
431}
432
434{
435 // base class 1
436 Any aReturn(OComponentHelper::queryAggregation(_rType));
437
438 // base class 2
439 if (!aReturn.hasValue())
440 {
441 aReturn = OControlModel_BASE::queryInterface(_rType);
442
443 // our own interfaces
444 if (!aReturn.hasValue())
445 {
446 aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
447 // our aggregate
448 if (!aReturn.hasValue() && m_xAggregate.is() && !_rType.equals(cppu::UnoType<XCloneable>::get()))
449 aReturn = m_xAggregate->queryAggregation(_rType);
450 }
451 }
452 return aReturn;
453}
454
455void OControlModel::readHelpTextCompatibly(const css::uno::Reference< css::io::XObjectInputStream >& _rxInStream)
456{
457 OUString sHelpText;
458 ::comphelper::operator>>( _rxInStream, sHelpText);
459 try
460 {
461 if (m_xAggregateSet.is())
462 m_xAggregateSet->setPropertyValue(PROPERTY_HELPTEXT, Any(sHelpText));
463 }
464 catch(const Exception&)
465 {
466 DBG_UNHANDLED_EXCEPTION("forms.component");
467 SAL_WARN("forms.component", "OControlModel::readHelpTextCompatibly: could not forward the property value to the aggregate!");
468 }
469}
470
471void OControlModel::writeHelpTextCompatibly(const css::uno::Reference< css::io::XObjectOutputStream >& _rxOutStream)
472{
473 OUString sHelpText;
474 try
475 {
476 if (m_xAggregateSet.is())
477 m_xAggregateSet->getPropertyValue(PROPERTY_HELPTEXT) >>= sHelpText;
478 }
479 catch(const Exception&)
480 {
481 DBG_UNHANDLED_EXCEPTION("forms.component");
482 SAL_WARN("forms.component", "OControlModel::writeHelpTextCompatibly: could not retrieve the property value from the aggregate!");
483 }
484 ::comphelper::operator<<( _rxOutStream, sHelpText);
485}
486
488 const Reference<XComponentContext>& _rxContext,
489 const OUString& _rUnoControlModelTypeName,
490 const OUString& rDefault, const bool _bSetDelegator)
491 :OComponentHelper(m_aMutex)
492 ,OPropertySetAggregationHelper(OComponentHelper::rBHelper)
493 ,m_xContext( _rxContext )
494 ,m_lockCount( 0 )
495 ,m_aPropertyBagHelper( *this )
496 ,m_nTabIndex(FRM_DEFAULT_TABINDEX)
497 ,m_nClassId(FormComponentType::CONTROL)
498 ,m_bNativeLook( false )
499 ,m_bStandardTheme( false )
500 ,m_bGenerateVbEvents( false )
501 ,m_nControlTypeinMSO(0) // 0 : default value is create from AOO
502 ,m_nObjIDinMSO(INVALID_OBJ_ID_IN_MSO)
503 // form controls are usually embedded into documents, not dialogs, and in documents
504 // the native look is ugly...
505 // #i37342#
506{
507 if (_rUnoControlModelTypeName.isEmpty()) // the is a model we have to aggregate
508 return;
509
510 osl_atomic_increment(&m_refCount);
511 {
512 m_xAggregate.set(m_xContext->getServiceManager()->createInstanceWithContext(_rUnoControlModelTypeName, m_xContext), UNO_QUERY);
513 setAggregation(m_xAggregate);
514
515 if ( m_xAggregateSet.is() )
516 {
517 try
518 {
519 if ( !rDefault.isEmpty() )
520 m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, Any( rDefault ) );
521 }
522 catch( const Exception& )
523 {
524 TOOLS_WARN_EXCEPTION("forms.component", "OControlModel::OControlModel");
525 }
526 }
527 }
528 if (_bSetDelegator)
530
531 // Refcount is at NULL again
532 osl_atomic_decrement(&m_refCount);
533}
534
535OControlModel::OControlModel( const OControlModel* _pOriginal, const Reference< XComponentContext>& _rxFactory, const bool _bCloneAggregate, const bool _bSetDelegator )
536 :OComponentHelper( m_aMutex )
537 ,OPropertySetAggregationHelper( OComponentHelper::rBHelper )
538 ,m_xContext( _rxFactory )
539 ,m_lockCount( 0 )
540 ,m_aPropertyBagHelper( *this )
541 ,m_nTabIndex( FRM_DEFAULT_TABINDEX )
542 ,m_nClassId( FormComponentType::CONTROL )
543{
544 DBG_ASSERT( _pOriginal, "OControlModel::OControlModel: invalid original!" );
545
546 // copy members
547 m_aName = _pOriginal->m_aName;
548 m_aTag = _pOriginal->m_aTag;
549 m_nTabIndex = _pOriginal->m_nTabIndex;
550 m_nClassId = _pOriginal->m_nClassId;
551 m_bNativeLook = _pOriginal->m_bNativeLook;
552 m_bStandardTheme = _pOriginal->m_bStandardTheme;
553 m_bGenerateVbEvents = _pOriginal->m_bGenerateVbEvents;
554 m_nControlTypeinMSO = _pOriginal->m_nControlTypeinMSO;
555 m_nObjIDinMSO = _pOriginal->m_nObjIDinMSO;
556
557 if ( !_bCloneAggregate )
558 return;
559
560 // temporarily increment refcount because of temporary references to ourself in the following
561 osl_atomic_increment( &m_refCount );
562 {
563 // transfer the (only, at the very moment!) ref count
564 m_xAggregate = createAggregateClone( _pOriginal );
565
566 // set aggregation (retrieve other direct interfaces of the aggregate)
567 setAggregation( m_xAggregate );
568 }
569
570 // set the delegator, if allowed by our derived class
571 if ( _bSetDelegator )
573
574 // decrement ref count
575 osl_atomic_decrement( &m_refCount );
576}
577
579{
580 // release the aggregate
582}
583
584void OControlModel::clonedFrom( const OControlModel* /*_pOriginal*/ )
585{
586 // nothing to do in this base class
587}
588
590{
591 if (m_xAggregate.is())
592 m_xAggregate->setDelegator(nullptr);
593}
594
596{
597 osl_atomic_increment(&m_refCount);
598 if (m_xAggregate.is())
599 {
600 m_xAggregate->setDelegator(static_cast<XWeak*>(this));
601 }
602 osl_atomic_decrement(&m_refCount);
603}
604
605// XChild
606Reference< XInterface > SAL_CALL OControlModel::getParent()
607{
608 return m_xParent;
609}
610
611void SAL_CALL OControlModel::setParent(const Reference< XInterface >& _rxParent)
612{
613 osl::MutexGuard aGuard(m_aMutex);
614
615 Reference<XComponent> xComp(m_xParent, UNO_QUERY);
616 if (xComp.is())
617 xComp->removeEventListener(static_cast<XPropertiesChangeListener*>(this));
618
619 m_xParent = _rxParent;
620 xComp.set(m_xParent, css::uno::UNO_QUERY);
621
622 if ( xComp.is() )
623 xComp->addEventListener(static_cast<XPropertiesChangeListener*>(this));
624}
625
626// XNamed
627OUString SAL_CALL OControlModel::getName()
628{
629 OUString aReturn;
630 try
631 {
633 }
634 catch (const css::beans::UnknownPropertyException&)
635 {
636 css::uno::Any a(cppu::getCaughtException());
637 throw WrappedTargetRuntimeException(
638 "OControlModel::getName",
639 *this,
640 a
641 );
642 }
643 return aReturn;
644}
645
646void SAL_CALL OControlModel::setName(const OUString& _rName)
647{
648 try
649 {
650 setFastPropertyValue(PROPERTY_ID_NAME, Any(_rName));
651 }
652 catch (const css::beans::UnknownPropertyException&)
653 {
654 css::uno::Any a(cppu::getCaughtException());
655 throw WrappedTargetRuntimeException(
656 "OControlModel::setName",
657 *this,
658 a
659 );
660 }
661}
662
663// XServiceInfo
664sal_Bool SAL_CALL OControlModel::supportsService(const OUString& _rServiceName)
665{
666 return cppu::supportsService(this, _rServiceName);
667}
668
669Sequence< OUString > OControlModel::getAggregateServiceNames() const
670{
671 Sequence< OUString > aAggServices;
672 Reference< XServiceInfo > xInfo;
673 if ( query_aggregation( m_xAggregate, xInfo ) )
674 aAggServices = xInfo->getSupportedServiceNames();
675 return aAggServices;
676}
677
678Sequence<OUString> SAL_CALL OControlModel::getSupportedServiceNames()
679{
680 return ::comphelper::concatSequences(
683 );
684}
685
687{
688 return { FRM_SUN_FORMCOMPONENT, "com.sun.star.form.FormControlModel" };
689}
690
691// XEventListener
692void SAL_CALL OControlModel::disposing(const css::lang::EventObject& _rSource)
693{
694 // release the parent
695 if (_rSource.Source == m_xParent)
696 {
697 osl::MutexGuard aGuard(m_aMutex);
698 m_xParent = nullptr;
699 }
700 else
701 {
702 Reference<css::lang::XEventListener> xEvtLst;
703 if (query_aggregation(m_xAggregate, xEvtLst))
704 {
705 osl::MutexGuard aGuard(m_aMutex);
706 xEvtLst->disposing(_rSource);
707 }
708 }
709}
710
711// OComponentHelper
713{
714 OPropertySetAggregationHelper::disposing();
715
716 Reference<css::lang::XComponent> xComp;
718 xComp->dispose();
719
720 setParent(Reference<XFormComponent>());
721
723}
724
725void OControlModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
726{
727 Reference< XPersistObject > xPersist;
728 if ( query_aggregation( m_xAggregate, xPersist ) )
729 xPersist->write( _rxOutStream );
730}
731
732void OControlModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
733{
734 Reference< XPersistObject > xPersist;
735 if ( query_aggregation( m_xAggregate, xPersist ) )
736 xPersist->read( _rxInStream );
737}
738
739void SAL_CALL OControlModel::write(const Reference<css::io::XObjectOutputStream>& _rxOutStream)
740{
741 osl::MutexGuard aGuard(m_aMutex);
742
743 // 1. writing the UnoControls
744 Reference<css::io::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
745 if ( !xMark.is() )
746 {
747 throw IOException(
748 ResourceManager::loadString(RID_STR_INVALIDSTREAM),
749 static_cast< ::cppu::OWeakObject* >( this )
750 );
751 }
752
753 sal_Int32 nMark = xMark->createMark();
754 sal_Int32 nLen = 0;
755
756 _rxOutStream->writeLong(nLen);
757
758 writeAggregate( _rxOutStream );
759
760 // determining the length
761 nLen = xMark->offsetToMark(nMark) - 4;
762 xMark->jumpToMark(nMark);
763 _rxOutStream->writeLong(nLen);
764 xMark->jumpToFurthest();
765 xMark->deleteMark(nMark);
766
767 // 2. writing a version number
768 _rxOutStream->writeShort(0x0003);
769
770 // 3. writing the general properties
771 ::comphelper::operator<<( _rxOutStream, m_aName);
772 _rxOutStream->writeShort(m_nTabIndex);
773 ::comphelper::operator<<( _rxOutStream, m_aTag); // 3rd version
774
775 // IMPORTANT NOTE!
776 // don't write any new members here: this wouldn't be compatible with older versions, as OControlModel
777 // is a base class which is called in derived classes "read" method. So if you increment the version
778 // and write new stuff, older office versions will read this in the _derived_ classes, which may result
779 // in anything from data loss to crash.
780 // EOIN!
781}
782
783void OControlModel::read(const Reference<css::io::XObjectInputStream>& InStream)
784{
785 osl::MutexGuard aGuard(m_aMutex);
786
787 Reference<css::io::XMarkableStream> xMark(InStream, UNO_QUERY);
788 if ( !xMark.is() )
789 {
790 throw IOException(
791 ResourceManager::loadString(RID_STR_INVALIDSTREAM),
792 static_cast< ::cppu::OWeakObject* >( this )
793 );
794 }
795
796 // 1. reading the UnoControls
797 sal_Int32 nLen = InStream->readLong();
798 if (nLen)
799 {
800 sal_Int32 nMark = xMark->createMark();
801
802 try
803 {
804 readAggregate( InStream );
805 }
806
807 catch( const Exception& )
808 {
809 DBG_UNHANDLED_EXCEPTION("forms.component");
810 }
811
812 xMark->jumpToMark(nMark);
813 InStream->skipBytes(nLen);
814 xMark->deleteMark(nMark);
815 }
816
817 // 2. reading the version number
818 sal_uInt16 nVersion = InStream->readShort();
819
820 // 3. reading the general properties
821 ::comphelper::operator>>( InStream, m_aName);
822 m_nTabIndex = InStream->readShort();
823
824 if (nVersion > 0x0002)
825 ::comphelper::operator>>( InStream, m_aTag);
826
827 // we had a version where we wrote the help text
828 if (nVersion == 0x0004)
829 readHelpTextCompatibly(InStream);
830
831 DBG_ASSERT(nVersion < 5, "OControlModel::read : suspicious version number !");
832 // 4 was the version where we wrote the help text
833 // later versions shouldn't exist (see write for a detailed comment)
834}
835
836PropertyState OControlModel::getPropertyStateByHandle( sal_Int32 _nHandle )
837{
838 // simply compare the current and the default value
839 Any aCurrentValue = getPropertyDefaultByHandle( _nHandle );
840 Any aDefaultValue; getFastPropertyValue( aDefaultValue, _nHandle );
841
842 bool bEqual = aCurrentValue == aDefaultValue;
843 return bEqual ? PropertyState_DEFAULT_VALUE : PropertyState_DIRECT_VALUE;
844}
845
847{
848 Any aDefault = getPropertyDefaultByHandle( _nHandle );
849
850 Any aConvertedValue, aOldValue;
851 if ( convertFastPropertyValue( aConvertedValue, aOldValue, _nHandle, aDefault ) )
852 {
853 setFastPropertyValue_NoBroadcast( _nHandle, aConvertedValue );
854 // TODO: fire the property change
855 }
856}
857
859{
860 Any aReturn;
861 switch ( _nHandle )
862 {
863 case PROPERTY_ID_NAME:
864 case PROPERTY_ID_TAG:
865 aReturn <<= OUString();
866 break;
868 aReturn <<= sal_Int16(FormComponentType::CONTROL);
869 break;
871 aReturn <<= sal_Int16(FRM_DEFAULT_TABINDEX);
872 break;
874 aReturn <<= true;
875 break;
877 aReturn <<= false;
878 break;
880 aReturn <<= false;
881 break;
882 // added for exporting OCX control
884 aReturn <<= sal_Int16(0);
885 break;
887 aReturn <<= sal_uInt16(INVALID_OBJ_ID_IN_MSO);
888 break;
889 default:
892 else
893 SAL_WARN("forms.component", "OControlModel::convertFastPropertyValue: unknown handle " << _nHandle);
894 }
895 return aReturn;
896}
897
898void OControlModel::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
899{
900 switch ( _nHandle )
901 {
902 case PROPERTY_ID_NAME:
903 _rValue <<= m_aName;
904 break;
905 case PROPERTY_ID_TAG:
906 _rValue <<= m_aTag;
907 break;
909 _rValue <<= m_nClassId;
910 break;
912 _rValue <<= m_nTabIndex;
913 break;
915 _rValue <<= m_bNativeLook;
916 break;
918 _rValue <<= m_bStandardTheme;
919 break;
921 _rValue <<= m_bGenerateVbEvents;
922 break;
923 // added for exporting OCX control
925 _rValue <<= m_nControlTypeinMSO;
926 break;
928 _rValue <<= m_nObjIDinMSO;
929 break;
930 default:
933 else
934 OPropertySetAggregationHelper::getFastPropertyValue( _rValue, _nHandle );
935 break;
936 }
937}
938
940 Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
941{
942 bool bModified(false);
943 switch (_nHandle)
944 {
945 case PROPERTY_ID_NAME:
946 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aName);
947 break;
948 case PROPERTY_ID_TAG:
949 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aTag);
950 break;
952 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nTabIndex);
953 break;
955 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bNativeLook);
956 break;
958 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bStandardTheme);
959 break;
961 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_bGenerateVbEvents);
962 break;
963 // added for exporting OCX control
965 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nControlTypeinMSO);
966 break;
968 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_nObjIDinMSO);
969 break;
970 default:
972 bModified = m_aPropertyBagHelper.convertDynamicFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
973 else
974 SAL_WARN("forms.component", "OControlModel::convertFastPropertyValue: unknown handle " << _nHandle);
975 break;
976 }
977 return bModified;
978}
979
980void OControlModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
981{
982 switch (_nHandle)
983 {
984 case PROPERTY_ID_NAME:
985 DBG_ASSERT(_rValue.getValueType() == cppu::UnoType<OUString>::get(),
986 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
987 _rValue >>= m_aName;
988 break;
989 case PROPERTY_ID_TAG:
990 DBG_ASSERT(_rValue.getValueType() == cppu::UnoType<OUString>::get(),
991 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
992 _rValue >>= m_aTag;
993 break;
995 DBG_ASSERT(_rValue.getValueType() == cppu::UnoType<sal_Int16>::get(),
996 "OControlModel::setFastPropertyValue_NoBroadcast : invalid type" );
997 _rValue >>= m_nTabIndex;
998 break;
1000 OSL_VERIFY( _rValue >>= m_bNativeLook );
1001 break;
1003 OSL_VERIFY( _rValue >>= m_bStandardTheme );
1004 break;
1006 OSL_VERIFY( _rValue >>= m_bGenerateVbEvents );
1007 break;
1008 // added for exporting OCX control
1010 OSL_VERIFY( _rValue >>= m_nControlTypeinMSO );
1011 break;
1013 OSL_VERIFY( _rValue >>= m_nObjIDinMSO );
1014 break;
1015 default:
1018 else
1019 SAL_WARN("forms.component", "OControlModel::setFastPropertyValue_NoBroadcast: unknown handle " << _nHandle );
1020 break;
1021 }
1022}
1023
1024void OControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
1025{
1026 _rProps.realloc(8);
1027 css::beans::Property* pProperties = _rProps.getArray();
1028 *pProperties++ = css::beans::Property(PROPERTY_CLASSID, PROPERTY_ID_CLASSID, cppu::UnoType<sal_Int16>::get(), css::beans::PropertyAttribute::READONLY | css::beans::PropertyAttribute::TRANSIENT);
1029 *pProperties++ = css::beans::Property(PROPERTY_NAME, PROPERTY_ID_NAME, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND);
1030 *pProperties++ = css::beans::Property(PROPERTY_NATIVE_LOOK, PROPERTY_ID_NATIVE_LOOK, cppu::UnoType<bool>::get(),
1031 css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::TRANSIENT);
1032 *pProperties++ = css::beans::Property(PROPERTY_STANDARD_THEME, PROPERTY_ID_STANDARD_THEME, cppu::UnoType<bool>::get(),
1033 css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::TRANSIENT);
1034 *pProperties++ = css::beans::Property(PROPERTY_TAG, PROPERTY_ID_TAG, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND);
1035 *pProperties++ = css::beans::Property(PROPERTY_GENERATEVBAEVENTS, PROPERTY_ID_GENERATEVBAEVENTS, cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::TRANSIENT);
1036 *pProperties++ = css::beans::Property(PROPERTY_CONTROL_TYPE_IN_MSO, PROPERTY_ID_CONTROL_TYPE_IN_MSO, cppu::UnoType<sal_Int16>::get(), css::beans::PropertyAttribute::BOUND);
1037 *pProperties++ = css::beans::Property(PROPERTY_OBJ_ID_IN_MSO, PROPERTY_ID_OBJ_ID_IN_MSO, cppu::UnoType<cppu::UnoUnsignedShortType>::get(), css::beans::PropertyAttribute::BOUND);
1038 DBG_ASSERT( pProperties == _rProps.getArray() + _rProps.getLength(), "<...>::describeFixedProperties/getInfoHelper: forgot to adjust the count ?");
1039}
1040
1041void OControlModel::describeAggregateProperties( Sequence< Property >& /* [out] */ _rAggregateProps ) const
1042{
1043 if ( m_xAggregateSet.is() )
1044 {
1045 Reference< XPropertySetInfo > xPSI( m_xAggregateSet->getPropertySetInfo() );
1046 if ( xPSI.is() )
1047 _rAggregateProps = xPSI->getProperties();
1048 }
1049}
1050
1052{
1053 return m_aMutex;
1054}
1055
1056void OControlModel::describeFixedAndAggregateProperties( Sequence< Property >& _out_rFixedProperties, Sequence< Property >& _out_rAggregateProperties ) const
1057{
1058 describeFixedProperties( _out_rFixedProperties );
1059 describeAggregateProperties( _out_rAggregateProperties );
1060}
1061
1062Reference< XMultiPropertySet > OControlModel::getPropertiesInterface()
1063{
1064 return this;
1065}
1066
1067Reference< XPropertySetInfo> SAL_CALL OControlModel::getPropertySetInfo()
1068{
1069 return createPropertySetInfo( getInfoHelper() );
1070}
1071
1073{
1075}
1076
1077void SAL_CALL OControlModel::addProperty( const OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue )
1078{
1079 m_aPropertyBagHelper.addProperty( _rName, _nAttributes, _rInitialValue );
1080}
1081
1082void SAL_CALL OControlModel::removeProperty( const OUString& _rName )
1083{
1085}
1086
1087Sequence< PropertyValue > SAL_CALL OControlModel::getPropertyValues()
1088{
1090}
1091
1092void SAL_CALL OControlModel::setPropertyValues( const Sequence< PropertyValue >& _rProps )
1093{
1095}
1096
1098{
1099 m_aMutex.acquire();
1100 osl_atomic_increment( &m_lockCount );
1101}
1102
1104{
1105 OSL_ENSURE( m_lockCount > 0, "OControlModel::unlockInstance: not locked!" );
1106 oslInterlockedCount lockCount = osl_atomic_decrement( &m_lockCount );
1107 m_aMutex.release();
1108 return lockCount;
1109}
1110
1111void OControlModel::firePropertyChanges( const std::vector< sal_Int32 >& _rHandles, const std::vector< Any >& _rOldValues,
1112 const std::vector< Any >& _rNewValues, LockAccess )
1113{
1115 const_cast< std::vector< sal_Int32 >& >( _rHandles ).data(),
1116 _rNewValues.data(),
1117 _rOldValues.data(),
1118 _rHandles.size(),
1119 false
1120 );
1121}
1122
1123// OBoundControlModel
1125{
1126 Any aReturn( OControlModel::queryAggregation(_rType) );
1127 if (!aReturn.hasValue())
1128 {
1130
1131 if ( !aReturn.hasValue() && m_bCommitable )
1133
1134 if ( !aReturn.hasValue() && m_bSupportsExternalBinding )
1136
1137 if ( !aReturn.hasValue() && m_bSupportsValidation )
1139 }
1140 return aReturn;
1141}
1142
1144 const Reference< XComponentContext>& _rxFactory,
1145 const OUString& _rUnoControlModelTypeName, const OUString& _rDefault,
1146 const bool _bCommitable, const bool _bSupportExternalBinding, const bool _bSupportsValidation )
1147 :OControlModel( _rxFactory, _rUnoControlModelTypeName, _rDefault, false )
1149 ,m_nValuePropertyAggregateHandle( -1 )
1150 ,m_nFieldType( DataType::OTHER )
1151 ,m_bValuePropertyMayBeVoid( false )
1152 ,m_aResetHelper( *this, m_aMutex )
1153 ,m_aUpdateListeners(m_aMutex)
1154 ,m_aFormComponentListeners( m_aMutex )
1155 ,m_bInputRequired( false )
1156 ,m_bFormListening( false )
1157 ,m_bLoaded(false)
1158 ,m_bRequired(false)
1159 ,m_bCommitable(_bCommitable)
1160 ,m_bSupportsExternalBinding( _bSupportExternalBinding )
1161 ,m_bSupportsValidation( _bSupportsValidation )
1162 ,m_bForwardValueChanges(true)
1163 ,m_bTransferringValue( false )
1164 ,m_bIsCurrentValueValid( true )
1165 ,m_bBindingControlsRO( false )
1166 ,m_bBindingControlsEnable( false )
1167 ,m_eControlValueChangeInstigator( eOther )
1168 ,m_aLabelServiceName(FRM_SUN_COMPONENT_FIXEDTEXT)
1169{
1170 // start property listening at the aggregate
1172}
1173
1175 const OBoundControlModel* _pOriginal, const Reference< XComponentContext>& _rxFactory )
1176 :OControlModel( _pOriginal, _rxFactory, true, false )
1177 ,OPropertyChangeListener( m_aMutex )
1178 ,m_nValuePropertyAggregateHandle( _pOriginal->m_nValuePropertyAggregateHandle )
1179 ,m_nFieldType( DataType::OTHER )
1180 ,m_bValuePropertyMayBeVoid( _pOriginal->m_bValuePropertyMayBeVoid )
1181 ,m_aResetHelper( *this, m_aMutex )
1182 ,m_aUpdateListeners( m_aMutex )
1183 ,m_aFormComponentListeners( m_aMutex )
1184 ,m_xValidator( _pOriginal->m_xValidator )
1185 ,m_bInputRequired( false )
1186 ,m_bFormListening( false )
1187 ,m_bLoaded( false )
1188 ,m_bRequired( false )
1189 ,m_bCommitable( _pOriginal->m_bCommitable )
1190 ,m_bSupportsExternalBinding( _pOriginal->m_bSupportsExternalBinding )
1191 ,m_bSupportsValidation( _pOriginal->m_bSupportsValidation )
1192 ,m_bForwardValueChanges( true )
1193 ,m_bTransferringValue( false )
1194 ,m_bIsCurrentValueValid( _pOriginal->m_bIsCurrentValueValid )
1195 ,m_bBindingControlsRO( false )
1196 ,m_bBindingControlsEnable( false )
1197 ,m_eControlValueChangeInstigator( eOther )
1198{
1199 // start property listening at the aggregate
1201 m_aLabelServiceName = _pOriginal->m_aLabelServiceName;
1202 m_sValuePropertyName = _pOriginal->m_sValuePropertyName;
1203 m_nValuePropertyAggregateHandle = _pOriginal->m_nValuePropertyAggregateHandle;
1204 m_bValuePropertyMayBeVoid = _pOriginal->m_bValuePropertyMayBeVoid;
1205 m_aValuePropertyType = _pOriginal->m_aValuePropertyType;
1206 m_aControlSource = _pOriginal->m_aControlSource;
1207 m_bInputRequired = _pOriginal->m_bInputRequired;
1208 // m_xLabelControl, though being a property, is not to be cloned, not even the reference will be transferred.
1209 // (the former should be clear - a clone of the object we're only referencing does not make sense)
1210 // (the second would violate the restriction for label controls that they're part of the
1211 // same form component hierarchy - we ourself are no part, yet, so we can't have a label control)
1212 // start listening for changes at the value property
1214}
1215
1217{
1218 if ( !OComponentHelper::rBHelper.bDisposed )
1219 {
1220 acquire();
1221 dispose();
1222 }
1223
1225 OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::~OBoundControlModel: what about my property multiplexer?" );
1227 {
1228 m_pAggPropMultiplexer->dispose();
1229 m_pAggPropMultiplexer = nullptr;
1230 }
1231}
1232
1234{
1235 const OBoundControlModel* pBoundOriginal = static_cast< const OBoundControlModel* >( _pOriginal );
1236 // the value binding can be handled as if somebody called setValueBinding here
1237 // By definition, bindings can be share between bindables
1238 if ( !(pBoundOriginal && pBoundOriginal->m_xExternalBinding.is()) )
1239 return;
1240
1241 try
1242 {
1243 setValueBinding( pBoundOriginal->m_xExternalBinding );
1244 }
1245
1246 catch( const Exception& )
1247 {
1248 DBG_UNHANDLED_EXCEPTION("forms.component");
1249 }
1250}
1251
1253{
1254 osl_atomic_increment( &m_refCount );
1255 if ( m_xAggregateSet.is() )
1256 {
1257 m_pAggPropMultiplexer = new OPropertyChangeMultiplexer( this, m_xAggregateSet, false );
1258 }
1259
1260 osl_atomic_decrement( &m_refCount );
1262}
1263
1265{
1266 // start listening for changes at the value property
1267 // There are three pre-requisites for this to be done:
1268 // 1. We support external value bindings. In this case, the changes in the control value need to
1269 // be propagated to the external binding immediately when they happen
1270 // 2. We support external validation. In this case, we need to listen for changes in the value
1271 // property, since we need to revalidate then.
1272 // 3. We are not committable. In this case, changes in the control value need to be propagated
1273 // to the database column immediately when they happen.
1275 {
1276 OSL_ENSURE( m_pAggPropMultiplexer, "OBoundControlModel::implInitValuePropertyListening: no multiplexer!" );
1277 if ( m_pAggPropMultiplexer && !m_sValuePropertyName.isEmpty() )
1279 }
1280}
1281
1282void OBoundControlModel::initOwnValueProperty( const OUString& i_rValuePropertyName )
1283{
1284 OSL_PRECOND( m_sValuePropertyName.isEmpty() && -1 == m_nValuePropertyAggregateHandle,
1285 "OBoundControlModel::initOwnValueProperty: value property is already initialized!" );
1286 OSL_ENSURE( !i_rValuePropertyName.isEmpty(), "OBoundControlModel::initOwnValueProperty: invalid property name!" );
1287 m_sValuePropertyName = i_rValuePropertyName;
1288}
1289
1290void OBoundControlModel::initValueProperty( const OUString& _rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle )
1291{
1292 OSL_PRECOND( m_sValuePropertyName.isEmpty() && -1 == m_nValuePropertyAggregateHandle,
1293 "OBoundControlModel::initValueProperty: value property is already initialized!" );
1294 OSL_ENSURE( !_rValuePropertyName.isEmpty(), "OBoundControlModel::initValueProperty: invalid property name!" );
1295 OSL_ENSURE( _nValuePropertyExternalHandle != -1, "OBoundControlModel::initValueProperty: invalid property handle!" );
1296
1297 m_sValuePropertyName = _rValuePropertyName;
1298 m_nValuePropertyAggregateHandle = getOriginalHandle( _nValuePropertyExternalHandle );
1299 OSL_ENSURE( m_nValuePropertyAggregateHandle != -1, "OBoundControlModel::initValueProperty: unable to find the original handle!" );
1300
1302 {
1303 Reference< XPropertySetInfo > xPropInfo( m_xAggregateSet->getPropertySetInfo(), UNO_SET_THROW );
1304 Property aValuePropDesc = xPropInfo->getPropertyByName( m_sValuePropertyName );
1305 m_aValuePropertyType = aValuePropDesc.Type;
1306 m_bValuePropertyMayBeVoid = ( aValuePropDesc.Attributes & PropertyAttribute::MAYBEVOID ) != 0;
1307 }
1308
1309 // start listening for changes at the value property
1311}
1312
1314{
1315 OSL_PRECOND( !m_sValuePropertyName.isEmpty(), "OBoundControlModel::suspendValueListening: don't have a value property!" );
1316 OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::suspendValueListening: I *am* not listening!" );
1317
1319 m_pAggPropMultiplexer->lock();
1320}
1321
1323{
1324 OSL_PRECOND( !m_sValuePropertyName.isEmpty(), "OBoundControlModel::resumeValueListening: don't have a value property!" );
1325 OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::resumeValueListening: I *am* not listening at all!" );
1326 OSL_PRECOND( !m_pAggPropMultiplexer || m_pAggPropMultiplexer->locked(), "OBoundControlModel::resumeValueListening: listening not suspended currently!" );
1328 m_pAggPropMultiplexer->unlock();
1329}
1330
1332{
1336 );
1337
1338 if ( m_bCommitable )
1340
1343
1346 return aTypes.getTypes();
1347}
1348
1349// OComponentHelper
1351{
1353
1354 osl::MutexGuard aGuard(m_aMutex);
1355
1357 m_pAggPropMultiplexer->dispose();
1358
1359 // notify all our listeners
1360 css::lang::EventObject aEvt( static_cast< XWeak* >( this ) );
1363
1364 // disconnect from our database column
1365 // TODO: could we replace the following 5 lines with a call to impl_disconnectDatabaseColumn_noNotify?
1366 // The only more thing which it does is calling onDisconnectedDbColumn - could this
1367 // cause trouble? At least when we continue to call OControlModel::disposing before, it *may*.
1368 if ( hasField() )
1369 {
1370 getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
1371 resetField();
1372 }
1373
1374 m_xCursor = nullptr;
1375 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1376 if ( xComp.is() )
1377 xComp->removeEventListener(static_cast< XEventListener* >( static_cast< XPropertyChangeListener* >( this ) ) );
1378 // disconnect from our external value binding
1381 // ditto for the validator
1382 if ( hasValidator() )
1384}
1385
1387{
1389 {
1390 // the control value changed, while we have an external value binding
1391 // -> forward the value to it
1393 transferControlValueToExternal( i_rControLock );
1394 }
1395
1396 else if ( !m_bCommitable && m_xColumnUpdate.is() )
1397 {
1398 // the control value changed, while we are bound to a database column,
1399 // but not committable (which means changes in the control have to be reflected to
1400 // the underlying database column immediately)
1401 // -> forward the value to the database column
1404 }
1405
1406 // validate the new value
1408 recheckValidity( true );
1409}
1410
1411void OBoundControlModel::_propertyChanged( const PropertyChangeEvent& _rEvt )
1412{
1413 ControlModelLock aLock( *this );
1414 OSL_ENSURE( _rEvt.PropertyName == m_sValuePropertyName,
1415 "OBoundControlModel::_propertyChanged: where did this come from (1)?" );
1416 OSL_ENSURE( m_pAggPropMultiplexer && !m_pAggPropMultiplexer->locked(),
1417 "OBoundControlModel::_propertyChanged: where did this come from (2)?" );
1418 if ( _rEvt.PropertyName == m_sValuePropertyName )
1419 {
1420 onValuePropertyChange( aLock );
1421 }
1422}
1423
1424void OBoundControlModel::startAggregatePropertyListening( const OUString& _rPropertyName )
1425{
1426 OSL_PRECOND( m_pAggPropMultiplexer, "OBoundControlModel::startAggregatePropertyListening: no multiplexer!" );
1427 OSL_ENSURE( !_rPropertyName.isEmpty(), "OBoundControlModel::startAggregatePropertyListening: invalid property name!" );
1428 if ( m_pAggPropMultiplexer && !_rPropertyName.isEmpty() )
1429 {
1430 m_pAggPropMultiplexer->addProperty( _rPropertyName );
1431 }
1432}
1433
1434void OBoundControlModel::doFormListening( const bool _bStart )
1435{
1436 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::doFormListening: external value binding should overrule the database binding!" );
1437 if ( isFormListening() == _bStart )
1438 return;
1439 if ( m_xAmbientForm.is() )
1440 _bStart ? m_xAmbientForm->addLoadListener( this ) : m_xAmbientForm->removeLoadListener( this );
1441 Reference< XLoadable > xParentLoadable( getParent(), UNO_QUERY );
1442 if ( getParent().is() && !xParentLoadable.is() )
1443 {
1444 // if our parent does not directly support the XLoadable interface, then it might support the
1445 // XRowSetSupplier/XRowSetChangeBroadcaster interfaces. In this case we have to listen for changes
1446 // broadcasted by the latter.
1447 Reference< XRowSetChangeBroadcaster > xRowSetBroadcaster( getParent(), UNO_QUERY );
1448 if ( xRowSetBroadcaster.is() )
1449 _bStart ? xRowSetBroadcaster->addRowSetChangeListener( this ) : xRowSetBroadcaster->removeRowSetChangeListener( this );
1450 }
1451
1452 m_bFormListening = _bStart && m_xAmbientForm.is();
1453}
1454
1455// XChild
1456void SAL_CALL OBoundControlModel::setParent(const Reference<XInterface>& _rxParent)
1457{
1458 ControlModelLock aLock( *this );
1459 FieldChangeNotifier aBoundFieldNotifier( aLock );
1460 if ( getParent() == _rxParent )
1461 return;
1462 // disconnect from database column (which is controlled by parent, directly or indirectly)
1463 if ( hasField() )
1465 // log off old listeners
1466 if ( isFormListening() )
1467 doFormListening( false );
1468 // actually set the new parent
1469 OControlModel::setParent( _rxParent );
1470 // a new parent means a new ambient form
1472 if ( !hasExternalValueBinding() )
1473 {
1474 // log on new listeners
1475 doFormListening( true );
1476 // re-connect to database column of the new parent
1477 if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
1479 }
1480}
1481
1482// XEventListener
1483void SAL_CALL OBoundControlModel::disposing(const css::lang::EventObject& _rEvent)
1484{
1485 ControlModelLock aLock( *this );
1486 if ( _rEvent.Source == getField() )
1487 {
1488 resetField();
1489 }
1490
1491 else if ( _rEvent.Source == m_xLabelControl )
1492 {
1493 Reference<XPropertySet> xOldValue = m_xLabelControl;
1494 m_xLabelControl = nullptr;
1495 // fire a propertyChanged (when we leave aLock's scope)
1497 }
1498
1499 else if ( _rEvent.Source == m_xExternalBinding )
1500 { // *first* check for the external binding
1502 }
1503
1504 else if ( _rEvent.Source == m_xValidator )
1505 { // *then* check for the validator. Reason is that bindings may also act as validator at the same
1506 // time, in this case, the validator is automatically revoked when the binding is revoked
1508 }
1509
1510 else
1511 OControlModel::disposing(_rEvent);
1512}
1513
1514// XServiceInfo
1515css::uno::Sequence<OUString> SAL_CALL OBoundControlModel::getSupportedServiceNames()
1516{
1517 return ::comphelper::combineSequences(
1520 );
1521}
1522
1524{
1525 Sequence<OUString> aOwnServiceNames { "com.sun.star.form.DataAwareControlModel" };
1526 return ::comphelper::concatSequences(
1528 aOwnServiceNames
1529 );
1530}
1531
1532// XPersist
1533void SAL_CALL OBoundControlModel::write( const Reference<css::io::XObjectOutputStream>& _rxOutStream )
1534{
1535 OControlModel::write(_rxOutStream);
1536 osl::MutexGuard aGuard(m_aMutex);
1537 // Version
1538 _rxOutStream->writeShort(0x0002);
1539 // Controlsource
1540 ::comphelper::operator<<( _rxOutStream, m_aControlSource);
1541 // !!! IMPORTANT NOTE !!!
1542 // don't write any new members here: this wouldn't be compatible with older versions, as OBoundControlModel
1543 // is a base class which is called in derived classes "read" method. So if you increment the version
1544 // and write new stuff, older office versions will read this in the _derived_ classes, which may result
1545 // in anything from data loss to crash.
1546 // (use writeCommonProperties instead, this is called in derived classes write-method)
1547 // !!! EOIN !!!
1548}
1549
1551{
1552 Reference<css::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1553 if (xComp.is())
1554 xComp->removeEventListener(static_cast<css::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1555 m_xLabelControl = nullptr;
1556}
1557
1558void OBoundControlModel::readCommonProperties(const Reference<css::io::XObjectInputStream>& _rxInStream)
1559{
1560 sal_Int32 nLen = _rxInStream->readLong();
1561 Reference<css::io::XMarkableStream> xMark(_rxInStream, UNO_QUERY);
1562 DBG_ASSERT(xMark.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
1563 sal_Int32 nMark = xMark->createMark();
1564 // read the reference to the label control
1565 Reference<css::io::XPersistObject> xPersist;
1566 sal_Int32 nUsedFlag;
1567 nUsedFlag = _rxInStream->readLong();
1568 if (nUsedFlag)
1569 xPersist = _rxInStream->readObject();
1570 m_xLabelControl.set(xPersist, css::uno::UNO_QUERY);
1571 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1572 if (xComp.is())
1573 xComp->addEventListener(static_cast<css::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1574 // read any other new common properties here
1575 // skip the remaining bytes
1576 xMark->jumpToMark(nMark);
1577 _rxInStream->skipBytes(nLen);
1578 xMark->deleteMark(nMark);
1579}
1580
1581void OBoundControlModel::writeCommonProperties(const Reference<css::io::XObjectOutputStream>& _rxOutStream)
1582{
1583 Reference<css::io::XMarkableStream> xMark(_rxOutStream, UNO_QUERY);
1584 DBG_ASSERT(xMark.is(), "OBoundControlModel::writeCommonProperties : can only work with markable streams !");
1585 sal_Int32 nMark = xMark->createMark();
1586 // a placeholder where we will write the overall length (later in this method)
1587 sal_Int32 nLen = 0;
1588 _rxOutStream->writeLong(nLen);
1589 // write the reference to the label control
1590 Reference<css::io::XPersistObject> xPersist(m_xLabelControl, UNO_QUERY);
1591 sal_Int32 nUsedFlag = 0;
1592 if (xPersist.is())
1593 nUsedFlag = 1;
1594 _rxOutStream->writeLong(nUsedFlag);
1595 if (xPersist.is())
1596 _rxOutStream->writeObject(xPersist);
1597 // write any other new common properties here
1598 // write the correct length at the beginning of the block
1599 nLen = xMark->offsetToMark(nMark) - sizeof(nLen);
1600 xMark->jumpToMark(nMark);
1601 _rxOutStream->writeLong(nLen);
1602 xMark->jumpToFurthest();
1603 xMark->deleteMark(nMark);
1604}
1605
1606void SAL_CALL OBoundControlModel::read( const Reference< css::io::XObjectInputStream >& _rxInStream )
1607{
1608 OControlModel::read(_rxInStream);
1609 osl::MutexGuard aGuard(m_aMutex);
1610 _rxInStream->readShort(); // version;
1611 ::comphelper::operator>>( _rxInStream, m_aControlSource);
1612}
1613
1614void OBoundControlModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
1615{
1616 switch (nHandle)
1617 {
1619 rValue <<= m_bInputRequired;
1620 break;
1622 rValue <<= m_sValuePropertyName;
1623 break;
1625 rValue <<= m_aControlSource;
1626 break;
1628 rValue <<= getField();
1629 break;
1631 if (!m_xLabelControl.is())
1632 rValue.clear();
1633 else
1634 rValue <<= m_xLabelControl;
1635 break;
1636 default:
1638 }
1639}
1640
1642 Any& _rConvertedValue, Any& _rOldValue,
1643 sal_Int32 _nHandle,
1644 const Any& _rValue)
1645{
1646 bool bModified(false);
1647 switch (_nHandle)
1648 {
1650 bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_bInputRequired );
1651 break;
1653 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aControlSource);
1654 break;
1656 SAL_WARN("forms.component", "OBoundControlModel::convertFastPropertyValue: BoundField should be a read-only property !" );
1657 throw css::lang::IllegalArgumentException();
1659 if (!_rValue.hasValue())
1660 { // property set to void
1661 _rConvertedValue = Any();
1662 getFastPropertyValue(_rOldValue, _nHandle);
1663 bModified = m_xLabelControl.is();
1664 }
1665
1666 else
1667 {
1668 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_xLabelControl);
1669 if (!m_xLabelControl.is())
1670 // an empty interface is interpreted as VOID
1671 _rOldValue.clear();
1672 }
1673
1674 break;
1675 default:
1676 bModified = OControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
1677 }
1678 return bModified;
1679}
1680
1682{
1683 Any aDefault;
1684 switch ( _nHandle )
1685 {
1687 aDefault <<= false;
1688 break;
1690 aDefault <<= OUString();
1691 break;
1693 aDefault <<= Reference< XPropertySet >();
1694 break;
1695 }
1696 return aDefault;
1697}
1698
1699void OBoundControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
1700{
1701 switch (nHandle)
1702 {
1704 OSL_VERIFY( rValue >>= m_bInputRequired );
1705 break;
1707 OSL_VERIFY( rValue >>= m_aControlSource );
1708 break;
1710 SAL_WARN("forms.component", "OBoundControlModel::setFastPropertyValue_NoBroadcast : BoundField should be a read-only property !");
1711 throw css::lang::IllegalArgumentException();
1713 {
1714 if ( rValue.hasValue() && ( rValue.getValueTypeClass() != TypeClass_INTERFACE ) )
1715 throw css::lang::IllegalArgumentException();
1716 Reference< XInterface > xNewValue( rValue, UNO_QUERY );
1717 if ( !xNewValue.is() )
1718 { // set property to "void"
1719 Reference< XComponent > xComp( m_xLabelControl, UNO_QUERY );
1720 if ( xComp.is() )
1721 xComp->removeEventListener( static_cast< XPropertyChangeListener* >( this ) );
1722 m_xLabelControl = nullptr;
1723 break;
1724 }
1725
1726 Reference< XControlModel > xAsModel ( xNewValue, UNO_QUERY );
1727 Reference< XServiceInfo > xAsServiceInfo ( xAsModel, UNO_QUERY );
1728 Reference< XPropertySet > xAsPropSet ( xAsServiceInfo, UNO_QUERY );
1729 Reference< XChild > xAsChild ( xAsPropSet, UNO_QUERY );
1730 if ( !xAsChild.is() || !xAsServiceInfo->supportsService( m_aLabelServiceName ) )
1731 {
1732 throw css::lang::IllegalArgumentException();
1733 }
1734
1735 // Check if we and the given model have a common ancestor (up to the forms collection)
1736 Reference<XChild> xCont(this);
1737 Reference< XInterface > xMyTopLevel = xCont->getParent();
1738 while (xMyTopLevel.is())
1739 {
1740 Reference<XForm> xAsForm(xMyTopLevel, UNO_QUERY);
1741 if (!xAsForm.is())
1742 // found my root
1743 break;
1744 Reference<XChild> xLoopAsChild(xMyTopLevel, UNO_QUERY);
1745 xMyTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
1746 }
1747
1748 Reference< XInterface > xNewTopLevel = xAsChild->getParent();
1749 while (xNewTopLevel.is())
1750 {
1751 Reference<XForm> xAsForm(xNewTopLevel, UNO_QUERY);
1752 if (!xAsForm.is())
1753 break;
1754 Reference<XChild> xLoopAsChild(xNewTopLevel, UNO_QUERY);
1755 xNewTopLevel = xLoopAsChild.is() ? xLoopAsChild->getParent() : Reference< XInterface >();
1756 }
1757
1758 if (xNewTopLevel != xMyTopLevel)
1759 {
1760 // the both objects don't belong to the same forms collection -> not acceptable
1761 throw css::lang::IllegalArgumentException();
1762 }
1763
1764 m_xLabelControl = xAsPropSet;
1765 Reference<css::lang::XComponent> xComp(m_xLabelControl, UNO_QUERY);
1766 if (xComp.is())
1767 xComp->addEventListener(static_cast<css::lang::XEventListener*>(static_cast<XPropertyChangeListener*>(this)));
1768 }
1769
1770 break;
1771 default:
1773 }
1774}
1775
1776// XPropertyChangeListener
1777void SAL_CALL OBoundControlModel::propertyChange( const PropertyChangeEvent& evt )
1778{
1779 // if the DBColumn value changed, transfer it to the control
1780 if ( evt.PropertyName == PROPERTY_VALUE )
1781 {
1782 OSL_ENSURE( evt.Source == getField(), "OBoundControlModel::propertyChange: value changes from components other than our database column?" );
1783 osl::MutexGuard aGuard(m_aMutex);
1784 if ( m_bForwardValueChanges && m_xColumn.is() )
1786 }
1787
1788 else
1789 {
1790 OSL_ENSURE( evt.Source == m_xExternalBinding, "OBoundControlModel::propertyChange: where did this come from?" );
1791 // our binding has properties which can control properties of ourself
1792 OUString sBindingControlledProperty;
1793 bool bForwardToLabelControl = false;
1794 if ( evt.PropertyName == PROPERTY_READONLY )
1795 {
1796 sBindingControlledProperty = PROPERTY_READONLY;
1797 }
1798
1799 else if ( evt.PropertyName == PROPERTY_RELEVANT )
1800 {
1801 sBindingControlledProperty = PROPERTY_ENABLED;
1802 bForwardToLabelControl = true;
1803 }
1804
1805 else
1806 return;
1807 try
1808 {
1809 setPropertyValue( sBindingControlledProperty, evt.NewValue );
1810 if ( bForwardToLabelControl && m_xLabelControl.is() )
1811 m_xLabelControl->setPropertyValue( sBindingControlledProperty, evt.NewValue );
1812 }
1813
1814 catch( const Exception& )
1815 {
1816 DBG_UNHANDLED_EXCEPTION("forms.component");
1817 SAL_WARN("forms.component", "OBoundControlModel::propertyChange: could not adjust my binding-controlled property!");
1818 }
1819
1820 }
1821}
1822
1823void SAL_CALL OBoundControlModel::onRowSetChanged( const EventObject& /*i_Event*/ )
1824{
1825 ControlModelLock aLock( *this );
1826 FieldChangeNotifier aBoundFieldNotifier( aLock );
1827 // disconnect from database column (which is controlled by parent, directly or indirectly)
1828 if ( hasField() )
1830 // log off old listeners
1831 if ( isFormListening() )
1832 doFormListening( false );
1833 // determine the new ambient form
1835 // log on new listeners
1836 doFormListening( true );
1837 // re-connect to database column if needed and possible
1838 if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
1840}
1841
1842// XBoundComponent
1843void SAL_CALL OBoundControlModel::addUpdateListener(const Reference<XUpdateListener>& _rxListener)
1844{
1845 m_aUpdateListeners.addInterface(_rxListener);
1846}
1847
1848void SAL_CALL OBoundControlModel::removeUpdateListener(const Reference< XUpdateListener>& _rxListener)
1849{
1851}
1852
1854{
1855 ControlModelLock aLock( *this );
1856 OSL_PRECOND( m_bCommitable, "OBoundControlModel::commit: invalid call (I'm not committable!) " );
1858 {
1859 // in most cases, no action is required: For most derivees, we know the value property of
1860 // our control (see initValueProperty), and when an external binding is active, we
1861 // instantly forward all changes in this property to the external binding.
1862 if ( m_sValuePropertyName.isEmpty() )
1863 // but for those derivees which did not use this feature, we need an
1864 // explicit transfer
1866 return true;
1867 }
1868
1869 OSL_ENSURE( !hasExternalValueBinding(), "OBoundControlModel::commit: control flow broken!" );
1870 // we reach this only if we're not working with an external binding
1871 if ( !hasField() )
1872 return true;
1874 EventObject aEvent;
1875 aEvent.Source = static_cast< XWeak* >( this );
1876 bool bSuccess = true;
1877 aLock.release();
1878 // UNSAFE >
1879 while (aIter.hasMoreElements() && bSuccess)
1880 bSuccess = aIter.next()->approveUpdate( aEvent );
1881 // < UNSAFE
1882 aLock.acquire();
1883 if ( bSuccess )
1884 {
1885 try
1886 {
1887 if ( m_xColumnUpdate.is() )
1888 bSuccess = commitControlValueToDbColumn( false );
1889 }
1890
1891 catch(const Exception&)
1892 {
1893 bSuccess = false;
1894 }
1895
1896 }
1897
1898 if ( bSuccess )
1899 {
1900 aLock.release();
1901 m_aUpdateListeners.notifyEach( &XUpdateListener::updated, aEvent );
1902 }
1903 return bSuccess;
1904}
1905
1907{
1908 m_xColumnUpdate.clear();
1909 m_xColumn.clear();
1910 m_xField.clear();
1911 m_nFieldType = DataType::OTHER;
1912}
1913
1914void OBoundControlModel::connectToField(const Reference<XRowSet>& rForm)
1915{
1916 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::connectToField: invalid call (have an external binding)!" );
1917 // if there's a connection to the database
1918 if (!(rForm.is() && getConnection(rForm).is()))
1919 return;
1920
1921 // determine field and PropertyChangeListener
1922 m_xCursor = rForm;
1923 Reference<XPropertySet> xFieldCandidate;
1924 if (m_xCursor.is())
1925 {
1926 Reference<XColumnsSupplier> xColumnsSupplier(m_xCursor, UNO_QUERY);
1927 DBG_ASSERT(xColumnsSupplier.is(), "OBoundControlModel::connectToField : the row set should support the css::sdb::ResultSet service !");
1928 if (xColumnsSupplier.is())
1929 {
1930 Reference<XNameAccess> xColumns = xColumnsSupplier->getColumns();
1931 if (xColumns.is() && xColumns->hasByName(m_aControlSource))
1932 {
1933 OSL_VERIFY( xColumns->getByName(m_aControlSource) >>= xFieldCandidate );
1934 }
1935
1936 }
1937
1938 }
1939
1940 try
1941 {
1942 sal_Int32 nFieldType = DataType::OTHER;
1943 if ( xFieldCandidate.is() )
1944 {
1945 xFieldCandidate->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
1946 if ( approveDbColumnType( nFieldType ) )
1947 impl_setField_noNotify( xFieldCandidate );
1948 }
1949
1950 else
1951 impl_setField_noNotify( nullptr );
1952 if ( m_xField.is() )
1953 {
1954 if ( m_xField->getPropertySetInfo()->hasPropertyByName( PROPERTY_VALUE ) )
1955 {
1956 m_nFieldType = nFieldType;
1957 // listen to changing values
1958 m_xField->addPropertyChangeListener( PROPERTY_VALUE, this );
1959 m_xColumnUpdate.set( m_xField, UNO_QUERY );
1960 m_xColumn.set( m_xField, UNO_QUERY );
1961 sal_Int32 nNullableFlag = ColumnValue::NO_NULLS;
1962 m_xField->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullableFlag;
1963 // tdf#122319 - don't allow nullable form components if input is required
1964 m_bRequired = (ColumnValue::NO_NULLS == nNullableFlag || m_bInputRequired);
1965 // we're optimistic: in case of ColumnValue_NULLABLE_UNKNOWN we assume nullability...
1966 }
1967 else
1968 {
1969 SAL_WARN("forms.component", "OBoundControlModel::connectToField: property " << PROPERTY_VALUE << " not supported!");
1970 impl_setField_noNotify( nullptr );
1971 }
1972
1973 }
1974
1975 }
1976
1977 catch( const Exception& )
1978 {
1979 DBG_UNHANDLED_EXCEPTION("forms.component");
1980 resetField();
1981 }
1982}
1983
1984void OBoundControlModel::initFromField( const Reference< XRowSet >& _rxRowSet )
1985{
1986 // but only if the rowset is positioned on a valid record
1987 if ( !(hasField() && _rxRowSet.is()) )
1988 return;
1989
1990 bool shouldTransfer(!_rxRowSet->isBeforeFirst() && !_rxRowSet->isAfterLast());
1991 if (!shouldTransfer)
1992 {
1993 const Reference< XPropertySet > xPS(_rxRowSet, UNO_QUERY);
1994 if (xPS.is())
1995 {
1996 assert(!shouldTransfer);
1997 xPS->getPropertyValue("IsNew") >>= shouldTransfer;
1998 }
1999 }
2000 if ( shouldTransfer )
2002 else
2003 // reset the field if the row set is empty
2004 // #i30661#
2006}
2007
2009{
2010 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::approveDbColumnType: invalid call (have an external binding)!" );
2011 if ((_nColumnType == DataType::BINARY) || (_nColumnType == DataType::VARBINARY)
2012 || (_nColumnType == DataType::LONGVARBINARY) || (_nColumnType == DataType::OTHER)
2013 || (_nColumnType == DataType::OBJECT) || (_nColumnType == DataType::DISTINCT)
2014 || (_nColumnType == DataType::STRUCT) || (_nColumnType == DataType::ARRAY)
2015 || (_nColumnType == DataType::BLOB) /*|| (_nColumnType == DataType::CLOB)*/
2016 || (_nColumnType == DataType::REF) || (_nColumnType == DataType::SQLNULL))
2017 return false;
2018 return true;
2019}
2020
2022{
2023 Reference< XInterface > xParent( getParent() );
2024 m_xAmbientForm.set( xParent, UNO_QUERY );
2025 if ( !m_xAmbientForm.is() )
2026 {
2027 Reference< XRowSetSupplier > xSupRowSet( xParent, UNO_QUERY );
2028 if ( xSupRowSet.is() )
2029 m_xAmbientForm.set( xSupRowSet->getRowSet(), UNO_QUERY );
2030 }
2031}
2032
2034{
2035 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2036 // consistency checks
2037 DBG_ASSERT( !( hasField() && !_bFromReload ),
2038 "OBoundControlModel::impl_connectDatabaseColumn_noNotify: the form is just *loaded*, but we already have a field!" );
2039
2040 Reference< XRowSet > xRowSet( m_xAmbientForm, UNO_QUERY );
2041 OSL_ENSURE( xRowSet.is(), "OBoundControlModel::impl_connectDatabaseColumn_noNotify: no row set!" );
2042 if ( !xRowSet.is() )
2043 return;
2044 if ( !hasField() || _bFromReload )
2045 {
2046 // connect to the column
2047 connectToField( xRowSet );
2048 }
2049
2050 // now that we're connected (more or less, even if we did not find a column),
2051 // we definitely want to forward any potentially occurring value changes
2053 // let derived classes react on this new connection
2054 m_bLoaded = true;
2055 onConnectedDbColumn( xRowSet );
2056 // initially transfer the db column value to the control, if we successfully connected to a database column
2057 if ( hasField() )
2058 initFromField( xRowSet );
2059}
2060
2062{
2063 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::impl_disconnectDatabaseColumn_noNotify: not to be called with an external value binding!" );
2064 // let derived classes react on this
2066 if ( hasField() )
2067 {
2068 getField()->removePropertyChangeListener( PROPERTY_VALUE, this );
2069 resetField();
2070 }
2071
2072 m_xCursor = nullptr;
2073 m_bLoaded = false;
2074}
2075
2076// XLoadListener
2077void SAL_CALL OBoundControlModel::loaded( const EventObject& _rEvent )
2078{
2079 ControlModelLock aLock( *this );
2080 FieldChangeNotifier aBoundFieldNotifier( aLock );
2081 OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::loaded: where does this come from?" );
2082 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::loaded: we should never reach this with an external value binding!" );
2084 return;
2086}
2087
2088void SAL_CALL OBoundControlModel::unloaded( const css::lang::EventObject& /*aEvent*/ )
2089{
2090 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloaded: we should never reach this with an external value binding!" );
2091}
2092
2093void SAL_CALL OBoundControlModel::reloading( const css::lang::EventObject& /*aEvent*/ )
2094{
2095 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloading: we should never reach this with an external value binding!" );
2097 return;
2098 osl::MutexGuard aGuard(m_aMutex);
2099 m_bForwardValueChanges = false;
2100}
2101
2102void SAL_CALL OBoundControlModel::unloading(const css::lang::EventObject& /*aEvent*/)
2103{
2104 ControlModelLock aLock( *this );
2105 FieldChangeNotifier aBoundFieldNotifier( aLock );
2106 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::unloading: we should never reach this with an external value binding!" );
2108 return;
2110}
2111
2112void SAL_CALL OBoundControlModel::reloaded( const EventObject& _rEvent )
2113{
2114 ControlModelLock aLock( *this );
2115 FieldChangeNotifier aBoundFieldNotifier( aLock );
2116 OSL_ENSURE( _rEvent.Source == m_xAmbientForm, "OBoundControlModel::reloaded: where does this come from?" );
2117 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::reloaded: we should never reach this with an external value binding!" );
2119 return;
2121}
2122
2123void OBoundControlModel::setControlValue( const Any& _rValue, ValueChangeInstigator _eInstigator )
2124{
2125 m_eControlValueChangeInstigator = _eInstigator;
2126 doSetControlValue( _rValue );
2128}
2129
2131{
2132 OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2133 "OBoundControlModel::doSetControlValue: invalid aggregate !" );
2134 OSL_PRECOND( !m_sValuePropertyName.isEmpty() || ( m_nValuePropertyAggregateHandle != -1 ),
2135 "OBoundControlModel::doSetControlValue: please override if you have own value property handling!" );
2136 try
2137 {
2138 // release our mutex once (it's acquired in one of the calling methods), as setting aggregate properties
2139 // may cause any uno controls belonging to us to lock the solar mutex, which is potentially dangerous with
2140 // our own mutex locked
2141 MutexRelease aRelease( m_aMutex );
2142 if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2143 {
2144 m_xAggregateFastSet->setFastPropertyValue( m_nValuePropertyAggregateHandle, _rValue );
2145 }
2146
2147 else if ( !m_sValuePropertyName.isEmpty() && m_xAggregateSet.is() )
2148 {
2149 m_xAggregateSet->setPropertyValue( m_sValuePropertyName, _rValue );
2150 }
2151
2152 }
2153
2154 catch( const Exception& )
2155 {
2156 TOOLS_WARN_EXCEPTION("forms.component", "OBoundControlModel::doSetControlValue");
2157 }
2158}
2159
2161{
2162 try
2163 {
2164 // if we have an external validator, we do not want the control to force invalid
2165 // inputs to the default value. Instead, invalid inputs should be translated
2166 // to NaN (not a number)
2167 Reference< XPropertySetInfo > xAggregatePropertyInfo;
2168 if ( m_xAggregateSet.is() )
2169 xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
2170 if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
2171 m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, Any( false ) );
2172 }
2173
2174 catch( const Exception& )
2175 {
2176 TOOLS_WARN_EXCEPTION("forms.component", "OBoundControlModel::onConnectedValidator");
2177 }
2178
2179 recheckValidity( false );
2180}
2181
2183{
2184 try
2185 {
2186 Reference< XPropertySetInfo > xAggregatePropertyInfo;
2187 if ( m_xAggregateSet.is() )
2188 xAggregatePropertyInfo = m_xAggregateSet->getPropertySetInfo();
2189 if ( xAggregatePropertyInfo.is() && xAggregatePropertyInfo->hasPropertyByName( PROPERTY_ENFORCE_FORMAT ) )
2190 m_xAggregateSet->setPropertyValue( PROPERTY_ENFORCE_FORMAT, Any( true ) );
2191 }
2192
2193 catch( const Exception& )
2194 {
2195 TOOLS_WARN_EXCEPTION("forms.component", "OBoundControlModel::onDisconnectedValidator");
2196 }
2197
2198 recheckValidity( false );
2199}
2200
2202{
2204}
2205
2206void OBoundControlModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
2207{
2208 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onConnectedDbColumn: how this? There's an external value binding!" );
2209}
2210
2212{
2213 OSL_PRECOND( !hasExternalValueBinding(), "OBoundControlModel::onDisconnectedDbColumn: how this? There's an external value binding!" );
2214}
2215
2216// XReset
2218{
2219 return Any();
2220}
2221
2223{
2225}
2226
2227void OBoundControlModel::addResetListener(const Reference<XResetListener>& l)
2228{
2230}
2231
2232void OBoundControlModel::removeResetListener(const Reference<XResetListener>& l)
2233{
2235}
2236
2238{
2240 return;
2241 ControlModelLock aLock( *this );
2242 // on a new record?
2243 bool bIsNewRecord = false;
2244 Reference<XPropertySet> xSet( m_xCursor, UNO_QUERY );
2245 if ( xSet.is() )
2246 {
2247 try
2248 {
2249 xSet->getPropertyValue( PROPERTY_ISNEW ) >>= bIsNewRecord;
2250 }
2251
2252 catch( const Exception& )
2253 {
2254 DBG_UNHANDLED_EXCEPTION("forms.component");
2255 }
2256
2257 }
2258
2259 // cursor on an invalid row?
2260 bool bInvalidCursorPosition = true;
2261 try
2262 {
2263 bInvalidCursorPosition = m_xCursor.is()
2264 && ( m_xCursor->isAfterLast()
2265 || m_xCursor->isBeforeFirst()
2266 )
2267 && !bIsNewRecord;
2268 }
2269
2270 catch( const SQLException& )
2271 {
2272 TOOLS_WARN_EXCEPTION("forms.component", "OBoundControlModel::reset: caught an SQL exception!" );
2273 }
2274
2275 // #i24495# - don't count the insert row as "invalid"
2276 bool bSimpleReset =
2277 ( !m_xColumn.is() // no connection to a database column
2278 || ( m_xCursor.is() // OR we have an improperly positioned cursor
2279 && bInvalidCursorPosition
2280 )
2281 || hasExternalValueBinding() // OR we have an external value binding
2282 );
2283 if ( !bSimpleReset )
2284 {
2285 // The default values will be set if and only if the current value of the field which we're bound
2286 // to is NULL.
2287 // Else, the current field value should be refreshed
2288 // This behaviour is not completely ... "matured": What should happen if the field as well as the
2289 // control have a default value?
2290 bool bIsNull = true;
2291 // we have to access the field content at least once to get a reliable result by XColumn::wasNull
2292 try
2293 {
2294 // normally, we'd do a getString here. However, this is extremely expensive in the case
2295 // of binary fields. Unfortunately, getString is the only method which is guaranteed
2296 // to *always* succeed, all other getXXX methods may fail if the column is asked for a
2297 // non-convertible type
2298 sal_Int32 nFieldType = DataType::OBJECT;
2299 getField()->getPropertyValue( PROPERTY_FIELDTYPE ) >>= nFieldType;
2300 if ( ( nFieldType == DataType::BINARY )
2301 || ( nFieldType == DataType::VARBINARY )
2302 || ( nFieldType == DataType::LONGVARBINARY )
2303 || ( nFieldType == DataType::OBJECT )
2304 /*|| ( nFieldType == DataType::CLOB )*/
2305 )
2306 m_xColumn->getBinaryStream();
2307 else if ( nFieldType == DataType::BLOB )
2308 m_xColumn->getBlob();
2309 else
2310 m_xColumn->getString();
2311 bIsNull = m_xColumn->wasNull();
2312 }
2313
2314 catch(const Exception&)
2315 {
2316 DBG_UNHANDLED_EXCEPTION("forms.component");
2317 SAL_WARN("forms.component", "OBoundControlModel::reset: this should have succeeded in all cases!");
2318 }
2319
2320 bool bNeedValueTransfer = true;
2321 if ( bIsNull )
2322 {
2323 if ( bIsNewRecord )
2324 {
2325 // reset the control to its default
2327 // and immediately commit the changes to the DB column, to keep consistency
2329 bNeedValueTransfer = false;
2330 }
2331
2332 }
2333
2334 if ( bNeedValueTransfer )
2336 }
2337
2338 else
2339 {
2341 // transfer to the external binding, if necessary
2344 }
2345
2346 // revalidate, if necessary
2347 if ( hasValidator() )
2348 recheckValidity( true );
2349 aLock.release();
2351}
2352
2353void OBoundControlModel::impl_setField_noNotify( const Reference< XPropertySet>& _rxField )
2354{
2355 DBG_ASSERT( !hasExternalValueBinding(), "OBoundControlModel::impl_setField_noNotify: We have an external value binding!" );
2356 m_xField = _rxField;
2357}
2358
2359bool OBoundControlModel::impl_approveValueBinding_nolock( const Reference< XValueBinding >& _rxBinding )
2360{
2361 if ( !_rxBinding.is() )
2362 return false;
2363 Sequence< Type > aTypeCandidates;
2364 {
2365 // SYNCHRONIZED >
2366 ::osl::MutexGuard aGuard( m_aMutex );
2367 aTypeCandidates = getSupportedBindingTypes();
2368 // < SYNCHRONIZED
2369 }
2370
2371 for ( auto const & type : std::as_const(aTypeCandidates) )
2372 {
2373 if ( _rxBinding->supportsType( type ) )
2374 return true;
2375 }
2376 return false;
2377}
2378
2380 const Reference< XValueBinding >& _rxBinding, ControlModelLock& _rInstanceLock )
2381{
2382 OSL_PRECOND( _rxBinding.is(), "OBoundControlModel::connectExternalValueBinding: invalid binding instance!" );
2383 OSL_PRECOND( !hasExternalValueBinding( ), "OBoundControlModel::connectExternalValueBinding: precond not met (currently have a binding)!" );
2384 // if we're connected to a database column, suspend this
2385 if ( hasField() )
2387 // suspend listening for load-related events at out ambient form.
2388 // This is because an external value binding overrules a possible database binding.
2389 if ( isFormListening() )
2390 doFormListening( false );
2391 // remember this new binding
2392 m_xExternalBinding = _rxBinding;
2393 // tell the derivee
2395 try
2396 {
2397 // add as value listener so we get notified when the value changes
2398 Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2399 if ( xModifiable.is() )
2400 xModifiable->addModifyListener( this );
2401 // add as property change listener for some (possibly present) properties we're
2402 // interested in
2403 Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2404 Reference< XPropertySetInfo > xBindingPropsInfo( xBindingProps.is() ? xBindingProps->getPropertySetInfo() : Reference< XPropertySetInfo >() );
2405 if ( xBindingPropsInfo.is() )
2406 {
2407 if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_READONLY ) )
2408 {
2409 xBindingProps->addPropertyChangeListener( PROPERTY_READONLY, this );
2410 m_bBindingControlsRO = true;
2411 }
2412
2413 if ( xBindingPropsInfo->hasPropertyByName( PROPERTY_RELEVANT ) )
2414 {
2415 xBindingProps->addPropertyChangeListener( PROPERTY_RELEVANT, this );
2417 }
2418
2419 }
2420
2421 }
2422
2423 catch( const Exception& )
2424 {
2425 DBG_UNHANDLED_EXCEPTION("forms.component");
2426 }
2427
2428 // propagate our new value
2429 transferExternalValueToControl( _rInstanceLock );
2430 // if the binding is also a validator, use it, too. This is a constraint of the
2431 // com.sun.star.form.binding.ValidatableBindableFormComponent service
2432 if ( !m_bSupportsValidation )
2433 return;
2434
2435 try
2436 {
2437 Reference< XValidator > xAsValidator( _rxBinding, UNO_QUERY );
2438 if ( xAsValidator.is() )
2439 setValidator( xAsValidator );
2440 }
2441
2442 catch( const Exception& )
2443 {
2444 DBG_UNHANDLED_EXCEPTION("forms.component");
2445 }
2446}
2447
2449{
2450 try
2451 {
2452 // not listening at the binding anymore
2453 Reference< XModifyBroadcaster > xModifiable( m_xExternalBinding, UNO_QUERY );
2454 if ( xModifiable.is() )
2455 xModifiable->removeModifyListener( this );
2456 // remove as property change listener
2457 Reference< XPropertySet > xBindingProps( m_xExternalBinding, UNO_QUERY );
2459 xBindingProps->removePropertyChangeListener( PROPERTY_READONLY, this );
2461 xBindingProps->removePropertyChangeListener( PROPERTY_RELEVANT, this );
2462 }
2463
2464 catch( const Exception& )
2465 {
2466 TOOLS_WARN_EXCEPTION("forms.component", "OBoundControlModel::disconnectExternalValueBinding");
2467 }
2468
2469 // if the binding also acts as our validator, disconnect the validator, too
2470 if ( ( m_xExternalBinding == m_xValidator ) && m_xValidator.is() )
2472 // no binding anymore
2473 m_xExternalBinding.clear();
2474 // be a load listener at our form, again. This was suspended while we had
2475 // an external value binding in place.
2476 doFormListening( true );
2477 // re-connect to database column of the new parent
2478 if ( m_xAmbientForm.is() && m_xAmbientForm->isLoaded() )
2480}
2481
2482void SAL_CALL OBoundControlModel::setValueBinding( const Reference< XValueBinding >& _rxBinding )
2483{
2484 OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::setValueBinding: How did you reach this method?" );
2485 // the interface for this method should not have been exposed if we do not
2486 // support binding to external data
2487 // allow reset
2488 if ( _rxBinding.is() && !impl_approveValueBinding_nolock( _rxBinding ) )
2489 {
2490 throw IncompatibleTypesException(
2491 ResourceManager::loadString(RID_STR_INCOMPATIBLE_TYPES),
2492 *this
2493 );
2494 }
2495
2496 ControlModelLock aLock( *this );
2497 // since a ValueBinding overrules any potentially active database binding, the change in a ValueBinding
2498 // might trigger a change in our BoundField.
2499 FieldChangeNotifier aBoundFieldNotifier( aLock );
2500 // disconnect from the old binding
2503 // connect to the new binding
2504 if ( _rxBinding.is() )
2505 connectExternalValueBinding( _rxBinding, aLock );
2506}
2507
2508Reference< XValueBinding > SAL_CALL OBoundControlModel::getValueBinding( )
2509{
2510 ::osl::MutexGuard aGuard( m_aMutex );
2511 OSL_PRECOND( m_bSupportsExternalBinding, "OBoundControlModel::getValueBinding: How did you reach this method?" );
2512 // the interface for this method should not have been exposed if we do not
2513 // support binding to external data
2514 return m_xExternalBinding;
2515}
2516
2517void SAL_CALL OBoundControlModel::modified( const EventObject& _rEvent )
2518{
2519 ControlModelLock aLock( *this );
2520 OSL_PRECOND( hasExternalValueBinding(), "OBoundControlModel::modified: Where did this come from?" );
2521 if ( !m_bTransferringValue && ( m_xExternalBinding == _rEvent.Source ) && m_xExternalBinding.is() )
2522 {
2524 }
2525}
2526
2528{
2529 try
2530 {
2532 }
2533
2534 catch( const Exception& )
2535 {
2536 DBG_UNHANDLED_EXCEPTION("forms.component");
2537 }
2538}
2539
2541{
2542 Reference< XValueBinding > xExternalBinding( m_xExternalBinding );
2543 Type aValueExchangeType( getExternalValueType() );
2544 _rInstanceLock.release();
2545 // UNSAFE >
2546 Any aExternalValue;
2547 try
2548 {
2549 aExternalValue = xExternalBinding->getValue( aValueExchangeType );
2550 }
2551
2552 catch( const Exception& )
2553 {
2554 DBG_UNHANDLED_EXCEPTION("forms.component");
2555 }
2556 // < UNSAFE
2557 _rInstanceLock.acquire();
2559}
2560
2562{
2564 "OBoundControlModel::transferControlValueToExternal: precondition not met!" );
2565 if ( !m_xExternalBinding.is() )
2566 return;
2567
2568 Any aExternalValue( translateControlValueToExternalValue() );
2569 m_bTransferringValue = true;
2570 _rInstanceLock.release();
2571 // UNSAFE >
2572 try
2573 {
2574 m_xExternalBinding->setValue( aExternalValue );
2575 }
2576
2577 catch( const Exception& )
2578 {
2579 DBG_UNHANDLED_EXCEPTION("forms.component");
2580 }
2581
2582 // < UNSAFE
2583 _rInstanceLock.acquire();
2584 m_bTransferringValue = false;
2585}
2586
2588{
2589 return Sequence< Type >( &m_aValuePropertyType, 1 );
2590}
2591
2593{
2595 if ( !m_xExternalBinding.is() )
2596 return;
2597 const Sequence< Type > aTypeCandidates( getSupportedBindingTypes() );
2598 for ( auto const & typeCandidate : aTypeCandidates )
2599 {
2600 if ( m_xExternalBinding->supportsType( typeCandidate ) )
2601 {
2602 m_aExternalValueType = typeCandidate;
2603 break;
2604 }
2605 }
2606}
2607
2609{
2611 "OBoundControlModel::translateExternalValueToControlValue: precondition not met!" );
2612 Any aControlValue( _rExternalValue );
2613 // if the external value is VOID, and our value property is not allowed to be VOID,
2614 // then default-construct a value
2615 if ( !aControlValue.hasValue() && !m_bValuePropertyMayBeVoid )
2616 aControlValue.setValue( nullptr, m_aValuePropertyType );
2617 // out of here
2618 return aControlValue;
2619}
2620
2622{
2623 return getControlValue( );
2624}
2625
2627{
2628 OSL_PRECOND( m_xValidator.is(), "OBoundControlModel::translateControlValueToValidatableValue: no validator, so why should I?" );
2629 if ( ( m_xValidator == m_xExternalBinding ) && m_xValidator.is() )
2631 return getControlValue();
2632}
2633
2635{
2636 OSL_PRECOND( m_xAggregateFastSet.is() && m_xAggregateSet.is(),
2637 "OBoundControlModel::getControlValue: invalid aggregate !" );
2638 OSL_PRECOND( !m_sValuePropertyName.isEmpty() || ( m_nValuePropertyAggregateHandle != -1 ),
2639 "OBoundControlModel::getControlValue: please override if you have own value property handling!" );
2640 // determine the current control value
2641 Any aControlValue;
2642 if ( ( m_nValuePropertyAggregateHandle != -1 ) && m_xAggregateFastSet.is() )
2643 {
2644 aControlValue = m_xAggregateFastSet->getFastPropertyValue( m_nValuePropertyAggregateHandle );
2645 }
2646
2647 else if ( !m_sValuePropertyName.isEmpty() && m_xAggregateSet.is() )
2648 {
2649 aControlValue = m_xAggregateSet->getPropertyValue( m_sValuePropertyName );
2650 }
2651 return aControlValue;
2652}
2653
2654void OBoundControlModel::connectValidator( const Reference< XValidator >& _rxValidator )
2655{
2656 OSL_PRECOND( _rxValidator.is(), "OBoundControlModel::connectValidator: invalid validator instance!" );
2657 OSL_PRECOND( !hasValidator( ), "OBoundControlModel::connectValidator: precond not met (have a validator currently)!" );
2658 m_xValidator = _rxValidator;
2659
2660 // add as value listener so we get notified when the value changes
2661 if ( m_xValidator.is() )
2662 {
2663 try
2664 {
2665 m_xValidator->addValidityConstraintListener( this );
2666 }
2667
2668 catch( const RuntimeException& )
2669 {
2670 }
2671 }
2673}
2674
2676{
2677 OSL_PRECOND( hasValidator( ), "OBoundControlModel::connectValidator: precond not met (don't have a validator currently)!" );
2678
2679 // add as value listener so we get notified when the value changes
2680 if ( m_xValidator.is() )
2681 {
2682 try
2683 {
2684 m_xValidator->removeValidityConstraintListener( this );
2685 }
2686
2687 catch( const RuntimeException& )
2688 {
2689 }
2690 }
2691
2692 m_xValidator.clear();
2693
2695}
2696
2697void SAL_CALL OBoundControlModel::setValidator( const Reference< XValidator >& _rxValidator )
2698{
2699 osl::MutexGuard aGuard( m_aMutex );
2700 OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::setValidator: How did you reach this method?" );
2701 // the interface for this method should not have been exposed if we do not
2702 // support validation
2703
2704 // early out if the validator does not change
2705 if ( _rxValidator == m_xValidator )
2706 return;
2707
2708 if ( m_xValidator.is() && ( m_xValidator == m_xExternalBinding ) )
2709 throw VetoException(
2710 ResourceManager::loadString(RID_STR_INVALID_VALIDATOR),
2711 *this
2712 );
2713
2714 // disconnect from the old validator
2715 if ( hasValidator() )
2717
2718 // connect to the new validator
2719 if ( _rxValidator.is() )
2720 connectValidator( _rxValidator );
2721}
2722
2723Reference< XValidator > SAL_CALL OBoundControlModel::getValidator( )
2724{
2725 ::osl::MutexGuard aGuard( m_aMutex );
2726 OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::getValidator: How did you reach this method?" );
2727 // the interface for this method should not have been exposed if we do not
2728 // support validation
2729
2730 return m_xValidator;
2731}
2732
2733void SAL_CALL OBoundControlModel::validityConstraintChanged( const EventObject& /*Source*/ )
2734{
2735 osl::MutexGuard aGuard( m_aMutex );
2736 OSL_PRECOND( m_bSupportsValidation, "OBoundControlModel::validityConstraintChanged: How did you reach this method?" );
2737 // the interface for this method should not have been exposed if we do not
2738 // support validation
2739
2740 recheckValidity( false );
2741}
2742
2744{
2746}
2747
2749{
2750 if ( hasValidator() )
2752 return getControlValue();
2753}
2754
2756{
2757 ::osl::MutexGuard aGuard( m_aMutex );
2759}
2760
2761void SAL_CALL OBoundControlModel::addFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener )
2762{
2763 if ( Listener.is() )
2765}
2766
2767void SAL_CALL OBoundControlModel::removeFormComponentValidityListener( const Reference< validation::XFormComponentValidityListener >& Listener )
2768{
2769 if ( Listener.is() )
2771}
2772
2773void OBoundControlModel::recheckValidity( bool _bForceNotification )
2774{
2775 try
2776 {
2777 bool bIsCurrentlyValid = true;
2778 if ( hasValidator() )
2779 bIsCurrentlyValid = m_xValidator->isValid( translateControlValueToValidatableValue() );
2780
2781 if ( ( bIsCurrentlyValid != m_bIsCurrentValueValid ) || _bForceNotification )
2782 {
2783 m_bIsCurrentValueValid = bIsCurrentlyValid;
2784
2785 // release our mutex for the notifications
2786 MutexRelease aRelease( m_aMutex );
2787 m_aFormComponentListeners.notifyEach( &validation::XFormComponentValidityListener::componentValidityChanged, EventObject( *this ) );
2788 }
2789
2790 }
2791
2792 catch( const Exception& )
2793 {
2794 TOOLS_WARN_EXCEPTION("forms.component", "OBoundControlModel::recheckValidity");
2795 }
2796}
2797
2798void OBoundControlModel::describeFixedProperties( Sequence< Property >& _rProps ) const
2799{
2801 sal_Int32 nOldCount = _rProps.getLength();
2802 _rProps.realloc( nOldCount + 5);
2803 css::beans::Property* pProperties = _rProps.getArray() + nOldCount;
2804 *pProperties++ = css::beans::Property(PROPERTY_CONTROLSOURCE, PROPERTY_ID_CONTROLSOURCE, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND);
2805 *pProperties++ = css::beans::Property(PROPERTY_BOUNDFIELD, PROPERTY_ID_BOUNDFIELD, cppu::UnoType<XPropertySet>::get(),
2806 css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY | css::beans::PropertyAttribute::TRANSIENT);
2808 css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::MAYBEVOID);
2809 *pProperties++ = css::beans::Property(PROPERTY_CONTROLSOURCEPROPERTY, PROPERTY_ID_CONTROLSOURCEPROPERTY, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY | css::beans::PropertyAttribute::TRANSIENT);
2810 *pProperties++ = css::beans::Property(PROPERTY_INPUT_REQUIRED, PROPERTY_ID_INPUT_REQUIRED, cppu::UnoType<bool>::get(),
2811 css::beans::PropertyAttribute::BOUND);
2812 DBG_ASSERT( pProperties == _rProps.getArray() + _rProps.getLength(), "<...>::describeFixedProperties/getInfoHelper: forgot to adjust the count ?");
2813}
2814}
2815
2816/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XPropertySet > m_xOldField
OBoundControlModel & m_rModel
ControlModelLock & m_rLock
#define INVALID_OBJ_ID_IN_MSO
Reference< XComponentContext > m_xContext
AnyEventRef aEvent
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
css::uno::Reference< ListenerT > const & next()
friend friend class OPropertyChangeMultiplexer
virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override final
void fire(std::unique_lock< std::mutex > &rGuard, sal_Int32 *pnHandles, const css::uno::Any *pNewValues, const css::uno::Any *pOldValues, sal_Int32 nCount, bool bVetoable)
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
virtual void SAL_CALL dispose() SAL_OVERRIDE
oslInterlockedCount m_refCount
class whose instances lock an OControlModel
std::vector< sal_Int32 > m_aHandles
void addPropertyNotification(const sal_Int32 _nHandle, const css::uno::Any &_rOldValue, const css::uno::Any &_rNewValue)
adds a property change notification, which is to be fired when the last lock on the model (in the cur...
std::vector< css::uno::Any > m_aNewValues
OControlModel & m_rModel
std::vector< css::uno::Any > m_aOldValues
void impl_disconnectDatabaseColumn_noNotify()
disconnects from a value supplier which is a database column
virtual css::uno::Any getDefaultForReset() const
returns the default which should be used when resetting the control
void transferControlValueToExternal(ControlModelLock &_rInstanceLock)
transfers the control value to the external binding @precond our own mutex is locked,...
void writeCommonProperties(const css::uno::Reference< css::io::XObjectOutputStream > &_rxOutStream)
We can't write (new) common properties in this base class, as the file format doesn't allow this (unf...
virtual css::uno::Any translateControlValueToValidatableValue() const
retrieves the current value of the control, in a shape which can be used with our external validator.
sal_Int32 m_nValuePropertyAggregateHandle
virtual css::uno::Any translateDbColumnToControlValue()=0
translates a db column value into a control value.
OBoundControlModel(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const OUString &_rUnoControlModelTypeName, const OUString &_rDefault, const bool _bCommitable, const bool _bSupportExternalBinding, const bool _bSupportsValidation)
virtual void SAL_CALL unloading(const css::lang::EventObject &aEvent) override
bool hasExternalValueBinding() const
checks whether we currently have an external value binding in place
const bool m_bSupportsExternalBinding
virtual void SAL_CALL reloading(const css::lang::EventObject &aEvent) override
virtual void onConnectedDbColumn(const css::uno::Reference< css::uno::XInterface > &_rxForm)
called whenever a connection to a database column has been established
const css::uno::Type & getExternalValueType() const
returns the type which should be used to exchange data with our external value binding
void onValuePropertyChange(ControlModelLock &i_rControLock)
(to be) called when the value property changed
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
css::uno::Reference< css::form::binding::XValueBinding > m_xExternalBinding
virtual css::uno::Reference< css::form::validation::XValidator > SAL_CALL getValidator() override
virtual void doSetControlValue(const css::uno::Any &_rValue)
css::uno::Type m_aExternalValueType
virtual void onConnectedExternalValue()
called whenever a connection to an external supplier of values (XValueBinding) has been established
rtl::Reference<::comphelper::OPropertyChangeMultiplexer > m_pAggPropMultiplexer
bool impl_approveValueBinding_nolock(const css::uno::Reference< css::form::binding::XValueBinding > &_rxBinding)
called from within <member scope="css:::form::binding">XBindableValue::setValueBinding</member> to ap...
css::uno::Type m_aValuePropertyType
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL removeFormComponentValidityListener(const css::uno::Reference< css::form::validation::XFormComponentValidityListener > &Listener) override
void setControlValue(const css::uno::Any &_rValue, ValueChangeInstigator _eInstigator)
sets the given value as new current value for the control
void disconnectExternalValueBinding()
disconnects from an external value binding
void initFromField(const css::uno::Reference< css::sdbc::XRowSet > &_rxForm)
initializes the control from m_xField
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
void connectToField(const css::uno::Reference< css::sdbc::XRowSet > &_rxForm)
virtual void SAL_CALL unloaded(const css::lang::EventObject &aEvent) override
void implInitAggMultiplexer()
initializes m_pAggPropMultiplexer
virtual void SAL_CALL disposing() override
virtual css::uno::Any translateControlValueToExternalValue() const
commits the current control value to our external value binding
css::uno::Reference< css::form::XLoadable > m_xAmbientForm
void initValueProperty(const OUString &_rValuePropertyName, sal_Int32 _nValuePropertyExternalHandle)
initializes the part of the class which is related to the control value.
void implInitValuePropertyListening() const
initializes listening at the value property
css::uno::Reference< css::sdb::XColumn > m_xColumn
virtual void describeFixedProperties(css::uno::Sequence< css::beans::Property > &_rProps) const override
describes the properties provided by this class, or its respective derived class
virtual void resetNoBroadcast()
called to reset the control to some kind of default.
css::uno::Reference< css::beans::XPropertySet > m_xField
virtual css::uno::Any translateExternalValueToControlValue(const css::uno::Any &_rExternalValue) const
translates the given value, which was obtained from the current external value binding,...
virtual css::uno::Sequence< css::uno::Type > _getTypes() override
css::uno::Reference< css::beans::XPropertySet > m_xLabelControl
virtual void SAL_CALL onRowSetChanged(const css::lang::EventObject &i_Event) override
virtual void SAL_CALL write(const css::uno::Reference< css::io::XObjectOutputStream > &OutStream) override
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &rValue, sal_Int32 nHandle) const override
virtual void SAL_CALL removeUpdateListener(const css::uno::Reference< css::form::XUpdateListener > &aListener) override
virtual sal_Bool SAL_CALL convertFastPropertyValue(css::uno::Any &_rConvertedValue, css::uno::Any &_rOldValue, sal_Int32 _nHandle, const css::uno::Any &_rValue) override
virtual void clonedFrom(const OControlModel *_pOriginal) override
late ctor after cloning
virtual void SAL_CALL read(const css::uno::Reference< css::io::XObjectInputStream > &InStream) override
::comphelper::OInterfaceContainerHelper3< css::form::XUpdateListener > m_aUpdateListeners
virtual void SAL_CALL setParent(const css::uno::Reference< css::uno::XInterface > &Parent) override
void readCommonProperties(const css::uno::Reference< css::io::XObjectInputStream > &_rxInStream)
void connectExternalValueBinding(const css::uno::Reference< css::form::binding::XValueBinding > &_rxBinding, ControlModelLock &_rInstanceLock)
connects to an external value binding
virtual css::uno::Any getCurrentFormComponentValue() const
retrieves the current value of the form component
void connectValidator(const css::uno::Reference< css::form::validation::XValidator > &_rxValidator)
connects the component to an external validator
void calculateExternalValueType()
calculates the type which is to be used to communicate with the current external binding,...
virtual void SAL_CALL loaded(const css::lang::EventObject &aEvent) override
void resumeValueListening()
resumes listening at the value property
virtual void SAL_CALL addFormComponentValidityListener(const css::uno::Reference< css::form::validation::XFormComponentValidityListener > &Listener) override
void impl_setField_noNotify(const css::uno::Reference< css::beans::XPropertySet > &_rxField)
sets m_xField to the given new value, without notifying our listeners
virtual void SAL_CALL addResetListener(const css::uno::Reference< css::form::XResetListener > &aListener) override
virtual bool commitControlValueToDbColumn(bool _bPostReset)=0
commits the current control value to the database column we're bound to @precond we're properly bound...
css::uno::Reference< css::sdbc::XRowSet > m_xCursor
void impl_connectDatabaseColumn_noNotify(bool _bFromReload)
connects to a value supplier which is a database column.
void transferExternalValueToControl(ControlModelLock &_rInstanceLock)
transfers the current value of the active external binding to the control @precond we do have an acti...
virtual void SAL_CALL validityConstraintChanged(const css::lang::EventObject &Source) override
void suspendValueListening()
suspends listening at the value property
virtual css::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const override
const css::uno::Reference< css::beans::XPropertySet > & getField() const
virtual void SAL_CALL reset() override
css::uno::Reference< css::sdb::XColumnUpdate > m_xColumnUpdate
virtual void SAL_CALL setValidator(const css::uno::Reference< css::form::validation::XValidator > &Validator) override
void impl_determineAmbientForm_nothrow()
determines the new value of m_xAmbientForm
void onDisconnectedValidator()
called whenever an external validator has been revoked
virtual sal_Bool SAL_CALL isValid() override
static css::uno::Sequence< OUString > getSupportedServiceNames_Static()
void startAggregatePropertyListening(const OUString &_rPropertyName)
starts listening at the aggregate, for changes in the given property
void recheckValidity(bool _bForceNotification)
does a new validation of the control value
ValueChangeInstigator m_eControlValueChangeInstigator
virtual void onDisconnectedDbColumn()
called whenever a connection to a database column has been suspended
css::uno::Reference< css::form::validation::XValidator > m_xValidator
virtual css::uno::Reference< css::form::binding::XValueBinding > SAL_CALL getValueBinding() override
void doFormListening(const bool _bStart)
adds or removes the component as load listener to/from our form, and (if necessary) as RowSetChange l...
void onConnectedValidator()
called whenever an external validator has been registered
void disconnectValidator()
disconnects the component from its current an external validator
virtual void SAL_CALL setValueBinding(const css::uno::Reference< css::form::binding::XValueBinding > &_rxBinding) override
virtual css::uno::Any getControlValue() const
retrieves the current value of the control
::comphelper::OInterfaceContainerHelper3< css::form::validation::XFormComponentValidityListener > m_aFormComponentListeners
virtual css::uno::Any SAL_CALL getCurrentValue() override
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &evt) override
virtual void SAL_CALL addUpdateListener(const css::uno::Reference< css::form::XUpdateListener > &aListener) override
virtual void _propertyChanged(const css::beans::PropertyChangeEvent &_rEvt) override
virtual sal_Bool SAL_CALL commit() override
virtual bool approveDbColumnType(sal_Int32 _nColumnType)
nFieldType is the type of the field, on which the model will be linked.
virtual css::uno::Sequence< css::uno::Type > getSupportedBindingTypes()
returns the data types which the control could use to exchange data with an external value binding
virtual ~OBoundControlModel() override
virtual void SAL_CALL reloaded(const css::lang::EventObject &aEvent) override
void transferDbValueToControl()
transfers the very current value of the db column we're bound to the control @precond our own mutex i...
virtual void SAL_CALL removeResetListener(const css::uno::Reference< css::form::XResetListener > &aListener) override
void initOwnValueProperty(const OUString &i_rValuePropertyName)
initializes the part of the class which is related to the control value.
virtual void SAL_CALL modified(const css::lang::EventObject &_rEvent) override
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
virtual sal_Bool SAL_CALL setModel(const css::uno::Reference< css::awt::XControlModel > &Model) override
virtual ~OBoundControl() override
void _setLock(bool _bLock)
virtual void SAL_CALL disposing() override
virtual css::uno::Sequence< css::uno::Type > _getTypes() override
OBoundControl(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const OUString &_rAggregateService, const bool _bSetDelegator=true)
virtual sal_Bool SAL_CALL getLock() override
virtual void SAL_CALL setLock(sal_Bool _bLock) override
static css::uno::Reference< css::uno::XAggregation > createAggregateClone(const OCloneableAggregation *_pOriginal)
Definition: cloneable.cxx:38
css::uno::Reference< css::uno::XAggregation > m_xAggregate
Definition: cloneable.hxx:31
css::uno::Sequence< OUString > getAggregateServiceNames() const
virtual void describeFixedProperties(css::uno::Sequence< css::beans::Property > &_rProps) const
describes the properties provided by this class, or its respective derived class
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual ::osl::Mutex & getMutex() override
virtual void SAL_CALL read(const css::uno::Reference< css::io::XObjectInputStream > &_rxInStream) override
virtual css::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle) override
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent() override
virtual void SAL_CALL removeProperty(const OUString &Name) override
css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual void SAL_CALL setParent(const css::uno::Reference< css::uno::XInterface > &Parent) override
PropertyBagHelper m_aPropertyBagHelper
virtual void readAggregate(const css::uno::Reference< css::io::XObjectInputStream > &_rxInStream)
virtual void writeAggregate(const css::uno::Reference< css::io::XObjectOutputStream > &_rxOutStream) const
virtual css::uno::Reference< css::beans::XMultiPropertySet > getPropertiesInterface() override
virtual css::uno::Sequence< css::uno::Type > _getTypes()
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &rValue, sal_Int32 nHandle) const override
::osl::Mutex m_aMutex
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
virtual void SAL_CALL addProperty(const OUString &Name, ::sal_Int16 Attributes, const css::uno::Any &DefaultValue) override
virtual void SAL_CALL disposing() override
virtual void describeFixedAndAggregateProperties(css::uno::Sequence< css::beans::Property > &_out_rFixedProperties, css::uno::Sequence< css::beans::Property > &_out_rAggregateProperties) const override
oslInterlockedCount m_lockCount
sal_uInt16 m_nObjIDinMSO
void firePropertyChanges(const std::vector< sal_Int32 > &_rHandles, const std::vector< css::uno::Any > &_rOldValues, const std::vector< css::uno::Any > &_rNewValues, LockAccess)
virtual css::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const override
virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle) override
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
virtual void describeAggregateProperties(css::uno::Sequence< css::beans::Property > &_rAggregateProps) const
describes the properties of our aggregate
void writeHelpTextCompatibly(const css::uno::Reference< css::io::XObjectOutputStream > &_rxOutStream)
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
oslInterlockedCount unlockInstance(LockAccess)
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getPropertyValues() override
virtual void SAL_CALL setPropertyValues(const css::uno::Sequence< css::beans::PropertyValue > &aProps) override
css::uno::Reference< css::uno::XInterface > m_xParent
void lockInstance(LockAccess)
static css::uno::Sequence< OUString > getSupportedServiceNames_Static()
virtual ~OControlModel() override
virtual OUString SAL_CALL getName() override
virtual void SAL_CALL write(const css::uno::Reference< css::io::XObjectOutputStream > &_rxOutStream) override
virtual sal_Bool SAL_CALL convertFastPropertyValue(css::uno::Any &_rConvertedValue, css::uno::Any &_rOldValue, sal_Int32 _nHandle, const css::uno::Any &_rValue) override
virtual void clonedFrom(const OControlModel *_pOriginal)
to be called after an OBoundControlModel (a derivee, respectively) has been cloned
virtual void SAL_CALL setName(const OUString &aName) override
void readHelpTextCompatibly(const css::uno::Reference< css::io::XObjectInputStream > &_rxInStream)
virtual cppu::IPropertyArrayHelper &SAL_CALL getInfoHelper() override
sal_Int16 m_nControlTypeinMSO
OControlModel(const css::uno::Reference< css::uno::XComponentContext > &_rFactory, const OUString &_rUnoControlModelTypeName, const OUString &rDefault=OUString(), const bool _bSetDelegator=true)
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
css::uno::Reference< css::uno::XAggregation > m_xAggregate
virtual css::uno::Reference< css::awt::XView > SAL_CALL getView() override
void impl_resetStateGuard_nothrow()
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getContext() override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual void SAL_CALL setContext(const css::uno::Reference< css::uno::XInterface > &Context) override
virtual css::uno::Any SAL_CALL queryAggregation(const css::uno::Type &_rType) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void doSetDelegator()
sets the control as delegator at the aggregate
virtual sal_Bool SAL_CALL isDesignMode() override
virtual ~OControl() override
virtual void SAL_CALL createPeer(const css::uno::Reference< css::awt::XToolkit > &Toolkit, const css::uno::Reference< css::awt::XWindowPeer > &Parent) override
virtual css::uno::Reference< css::awt::XWindowPeer > SAL_CALL getPeer() override
void doResetDelegator()
virtual css::uno::Reference< css::awt::XControlModel > SAL_CALL getModel() override
virtual sal_Bool SAL_CALL isTransparent() override
OControl(const css::uno::Reference< css::uno::XComponentContext > &_rFactory, const OUString &_rAggregateService, const bool _bSetDelegator=true)
constructs a control
virtual sal_Bool SAL_CALL setModel(const css::uno::Reference< css::awt::XControlModel > &Model) override
virtual void SAL_CALL disposing() override
css::uno::Reference< css::awt::XControl > m_xControl
virtual void SAL_CALL setDesignMode(sal_Bool bOn) override
virtual css::uno::Sequence< css::uno::Type > _getTypes()
::osl::Mutex m_aMutex
WindowStateGuard m_aWindowStateGuard
css::uno::Sequence< OUString > getAggregateServiceNames() const
css::uno::Sequence< css::beans::PropertyValue > getPropertyValues()
bool convertDynamicFastPropertyValue(sal_Int32 _nHandle, const css::uno::Any &_rNewValue, css::uno::Any &_out_rConvertedValue, css::uno::Any &_out_rCurrentValue) const
void getDynamicPropertyDefaultByHandle(sal_Int32 _nHandle, css::uno::Any &_out_rValue) const
void getDynamicFastPropertyValue(sal_Int32 _nHandle, css::uno::Any &_out_rValue) const
void removeProperty(const OUString &_rName)
void addProperty(const OUString &_rName, ::sal_Int16 _nAttributes, const css::uno::Any &_rInitialValue)
void setPropertyValues(const css::uno::Sequence< css::beans::PropertyValue > &_rProps)
bool hasDynamicPropertyByHandle(sal_Int32 _nHandle) const
inline ::comphelper::OPropertyArrayAggregationHelper & getInfoHelper() const
void setDynamicFastPropertyValue(sal_Int32 _nHandle, const css::uno::Any &_rValue)
void addResetListener(const css::uno::Reference< css::form::XResetListener > &_listener)
Definition: resettable.cxx:37
void notifyResetted()
Definition: resettable.cxx:62
void removeResetListener(const css::uno::Reference< css::form::XResetListener > &_listener)
Definition: resettable.cxx:43
a helper class which merges sequences of <type scope="css::uno">Type</type>s, so that the resulting s...
TypeSequence getTypes() const
returns the types represented by this bag
void attach(const css::uno::Reference< css::awt::XWindow2 > &_rxWindow, const css::uno::Reference< css::awt::XControlModel > &_rxModel)
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
sal_Int16 nVersion
constexpr OUStringLiteral PROPERTY_ENFORCE_FORMAT
constexpr OUStringLiteral PROPERTY_DEFAULTCONTROL
Definition: frm_strings.hxx:51
constexpr OUStringLiteral PROPERTY_CONTROL_TYPE_IN_MSO
constexpr OUStringLiteral PROPERTY_NAME
Definition: frm_strings.hxx:28
constexpr OUStringLiteral PROPERTY_ISNULLABLE
constexpr OUStringLiteral PROPERTY_OBJ_ID_IN_MSO
constexpr OUStringLiteral PROPERTY_BOUNDFIELD
constexpr OUStringLiteral PROPERTY_NATIVE_LOOK
constexpr OUStringLiteral PROPERTY_CONTROLSOURCE
Definition: frm_strings.hxx:38
constexpr OUStringLiteral PROPERTY_READONLY
Definition: frm_strings.hxx:41
constexpr OUStringLiteral PROPERTY_STANDARD_THEME
constexpr OUStringLiteral PROPERTY_CONTROLLABEL
constexpr OUStringLiteral PROPERTY_RELEVANT
Definition: frm_strings.hxx:42
constexpr OUStringLiteral PROPERTY_GENERATEVBAEVENTS
constexpr OUStringLiteral PROPERTY_HELPTEXT
constexpr OUStringLiteral PROPERTY_CLASSID
Definition: frm_strings.hxx:30
constexpr OUStringLiteral PROPERTY_FIELDTYPE
Definition: frm_strings.hxx:90
constexpr OUStringLiteral PROPERTY_TAG
Definition: frm_strings.hxx:27
constexpr OUStringLiteral PROPERTY_ISNEW
constexpr OUStringLiteral PROPERTY_INPUT_REQUIRED
constexpr OUStringLiteral PROPERTY_CONTROLSOURCEPROPERTY
constexpr OUStringLiteral PROPERTY_VALUE
Definition: frm_strings.hxx:32
constexpr OUStringLiteral PROPERTY_ENABLED
Definition: frm_strings.hxx:39
std::mutex m_aMutex
uno_Any a
#define SAL_WARN(area, stream)
@ Exception
bool query_aggregation(const css::uno::Reference< css::uno::XAggregation > &_rxAggregate, css::uno::Reference< iface > &_rxOut)
bool tryPropertyValue(Any &_rConvertedValue, Any &_rOldValue, const Any &_rValueToSet, const Any &_rCurrentValue, const Type &_rExpectedType)
Type
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
Reference< XConnection > getConnection(const Reference< XRowSet > &_rxRowSet)
OUString loadString(TranslateId aResId)
loads the string with the specified resource id from the FormLayer mo file
ListBox is a bit confusing / different from other form components, so here are a few notes:
Definition: BaseListBox.hxx:25
const sal_Int16 FRM_DEFAULT_TABINDEX
VBAHELPER_DLLPUBLIC bool setPropertyValue(css::uno::Sequence< css::beans::PropertyValue > &aProp, const OUString &aName, const css::uno::Any &aValue)
DataType
#define PROPERTY_ID_CONTROLSOURCEPROPERTY
Definition: property.hxx:241
#define PROPERTY_ID_NAME
Definition: property.hxx:40
#define PROPERTY_ID_BOUNDFIELD
Definition: property.hxx:189
#define PROPERTY_ID_GENERATEVBAEVENTS
Definition: property.hxx:300
#define PROPERTY_ID_CONTROL_TYPE_IN_MSO
Definition: property.hxx:301
#define PROPERTY_ID_INPUT_REQUIRED
Definition: property.hxx:54
#define PROPERTY_ID_CONTROLLABEL
Definition: property.hxx:205
#define PROPERTY_ID_TAG
Definition: property.hxx:155
#define PROPERTY_ID_STANDARD_THEME
Definition: property.hxx:60
#define PROPERTY_ID_NATIVE_LOOK
Definition: property.hxx:53
#define PROPERTY_ID_CLASSID
Definition: property.hxx:45
#define PROPERTY_ID_CONTROLSOURCE
Definition: property.hxx:42
#define PROPERTY_ID_OBJ_ID_IN_MSO
Definition: property.hxx:302
#define PROPERTY_ID_TABINDEX
Definition: property.hxx:41
sal_Int32 nHandle
constexpr OUStringLiteral FRM_SUN_FORMCOMPONENT
Definition: services.hxx:188
constexpr OUStringLiteral FRM_SUN_COMPONENT_FIXEDTEXT
Definition: services.hxx:118
Reference< XModel > xModel
unsigned char sal_Bool
ResultType type
const SvXMLTokenMapEntry aTypes[]