1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <sal/macros.h>
22 #include "fmitems.hxx"
24 #include "fmpgeimp.hxx"
25 #include "svx/fmtools.hxx"
27 #include "svx/fmresids.hrc"
28 #include "fmservs.hxx"
29 #include "fmshimp.hxx"
30 #include "fmtextcontrolshell.hxx"
33 #include "fmvwimp.hxx"
34 #include "formtoolbars.hxx"
35 #include "gridcols.hxx"
36 #include "svx/svditer.hxx"
37 #include "svx/dialmgr.hxx"
38 #include "svx/dialogs.hrc"
39 #include "svx/fmglob.hxx"
40 #include "svx/fmmodel.hxx"
41 #include "svx/fmpage.hxx"
42 #include "svx/fmshell.hxx"
43 #include "svx/obj3d.hxx"
44 #include "svx/sdrpagewindow.hxx"
45 #include "svx/svdpagv.hxx"
46 #include "svx/svxdlg.hxx"
47 #include "svx/svxids.hrc"
49 #include <com/sun/star/awt/XWindow2.hpp>
50 #include <com/sun/star/awt/XCheckBox.hpp>
51 #include <com/sun/star/awt/XListBox.hpp>
52 #include <com/sun/star/awt/XTextComponent.hpp>
53 #include <com/sun/star/beans/theIntrospection.hpp>
54 #include <com/sun/star/beans/NamedValue.hpp>
55 #include <com/sun/star/beans/PropertyAttribute.hpp>
56 #include <com/sun/star/beans/XPropertyState.hpp>
57 #include <com/sun/star/container/XContainer.hpp>
58 #include <com/sun/star/container/XEnumeration.hpp>
59 #include <com/sun/star/container/XEnumerationAccess.hpp>
60 #include <com/sun/star/container/XIndexAccess.hpp>
61 #include <com/sun/star/container/XNamed.hpp>
62 #include <com/sun/star/form/ListSourceType.hpp>
63 #include <com/sun/star/form/TabOrderDialog.hpp>
64 #include <com/sun/star/form/XBoundComponent.hpp>
65 #include <com/sun/star/form/XBoundControl.hpp>
66 #include <com/sun/star/form/XGrid.hpp>
67 #include <com/sun/star/form/XGridPeer.hpp>
68 #include <com/sun/star/form/XLoadable.hpp>
69 #include <com/sun/star/form/XReset.hpp>
70 #include <com/sun/star/form/binding/XBindableValue.hpp>
71 #include <com/sun/star/form/binding/XListEntrySink.hpp>
72 #include <com/sun/star/frame/FrameSearchFlag.hpp>
73 #include <com/sun/star/script/XEventAttacherManager.hpp>
74 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
75 #include <com/sun/star/util/XCancellable.hpp>
76 #include <com/sun/star/util/XModeSelector.hpp>
77 #include <com/sun/star/util/XModifyBroadcaster.hpp>
78 #include <com/sun/star/util/XNumberFormatter.hpp>
79 #include <com/sun/star/view/XSelectionSupplier.hpp>
81 #include <comphelper/evtmethodhelper.hxx>
82 #include <comphelper/processfactory.hxx>
83 #include <comphelper/property.hxx>
84 #include <comphelper/solarmutex.hxx>
85 #include <comphelper/string.hxx>
86 #include <connectivity/dbtools.hxx>
87 #include <sfx2/dispatch.hxx>
88 #include <sfx2/docfile.hxx>
89 #include <sfx2/frame.hxx>
90 #include <sfx2/objsh.hxx>
91 #include <sfx2/viewfrm.hxx>
92 #include <sfx2/viewsh.hxx>
93 #include <toolkit/helper/vclunohelper.hxx>
94 #include <tools/diagnose_ex.h>
95 #include <vcl/layout.hxx>
96 #include <vcl/waitobj.hxx>
97 #include <vcl/settings.hxx>
100 #include <functional>
103 #include <boost/scoped_ptr.hpp>
105 // wird fuer Invalidate verwendet -> mitpflegen
106 static const sal_uInt16 DatabaseSlotMap
[] =
113 SID_FM_RECORD_DELETE
,
114 SID_FM_RECORD_ABSOLUTE
,
118 SID_FM_REMOVE_FILTER_SORT
,
123 SID_FM_FORM_FILTERED
,
125 SID_FM_REFRESH_FORM_CONTROL
,
132 // wird fuer Invalidate verwendet -> mitpflegen
133 // aufsteigend sortieren !!!!!!
134 static const sal_Int16 DlgSlotMap
[] = // slots des Controllers
136 SID_FM_CTL_PROPERTIES
,
140 SID_FM_SHOW_FMEXPLORER
,
141 SID_FM_FIELDS_CONTROL
,
142 SID_FM_SHOW_PROPERTIES
,
143 SID_FM_PROPERTY_CONTROL
,
144 SID_FM_FMEXPLORER_CONTROL
,
145 SID_FM_SHOW_DATANAVIGATOR
,
146 SID_FM_DATANAVIGATOR_CONTROL
,
150 static const sal_Int16 SelObjectSlotMap
[] = // vom SelObject abhaengige Slots
152 SID_FM_CONVERTTO_EDIT
,
153 SID_FM_CONVERTTO_BUTTON
,
154 SID_FM_CONVERTTO_FIXEDTEXT
,
155 SID_FM_CONVERTTO_LISTBOX
,
156 SID_FM_CONVERTTO_CHECKBOX
,
157 SID_FM_CONVERTTO_RADIOBUTTON
,
158 SID_FM_CONVERTTO_GROUPBOX
,
159 SID_FM_CONVERTTO_COMBOBOX
,
160 SID_FM_CONVERTTO_IMAGEBUTTON
,
161 SID_FM_CONVERTTO_FILECONTROL
,
162 SID_FM_CONVERTTO_DATE
,
163 SID_FM_CONVERTTO_TIME
,
164 SID_FM_CONVERTTO_NUMERIC
,
165 SID_FM_CONVERTTO_CURRENCY
,
166 SID_FM_CONVERTTO_PATTERN
,
167 SID_FM_CONVERTTO_IMAGECONTROL
,
168 SID_FM_CONVERTTO_FORMATTED
,
169 SID_FM_CONVERTTO_SCROLLBAR
,
170 SID_FM_CONVERTTO_SPINBUTTON
,
171 SID_FM_CONVERTTO_NAVIGATIONBAR
,
173 SID_FM_FMEXPLORER_CONTROL
,
174 SID_FM_DATANAVIGATOR_CONTROL
,
179 // die folgenden Arrays muessen kosistent sein, also einander entsprechende Eintraege an der selben relativen Position
180 // innerhalb ihres jeweiligen Arrays stehen
181 static const sal_Int16 nConvertSlots
[] =
183 SID_FM_CONVERTTO_EDIT
,
184 SID_FM_CONVERTTO_BUTTON
,
185 SID_FM_CONVERTTO_FIXEDTEXT
,
186 SID_FM_CONVERTTO_LISTBOX
,
187 SID_FM_CONVERTTO_CHECKBOX
,
188 SID_FM_CONVERTTO_RADIOBUTTON
,
189 SID_FM_CONVERTTO_GROUPBOX
,
190 SID_FM_CONVERTTO_COMBOBOX
,
191 SID_FM_CONVERTTO_IMAGEBUTTON
,
192 SID_FM_CONVERTTO_FILECONTROL
,
193 SID_FM_CONVERTTO_DATE
,
194 SID_FM_CONVERTTO_TIME
,
195 SID_FM_CONVERTTO_NUMERIC
,
196 SID_FM_CONVERTTO_CURRENCY
,
197 SID_FM_CONVERTTO_PATTERN
,
198 SID_FM_CONVERTTO_IMAGECONTROL
,
199 SID_FM_CONVERTTO_FORMATTED
,
200 SID_FM_CONVERTTO_SCROLLBAR
,
201 SID_FM_CONVERTTO_SPINBUTTON
,
202 SID_FM_CONVERTTO_NAVIGATIONBAR
205 static const sal_Int16 nCreateSlots
[] =
220 SID_FM_CURRENCYFIELD
,
223 SID_FM_FORMATTEDFIELD
,
229 static const sal_Int16 nObjectTypes
[] =
244 OBJ_FM_CURRENCYFIELD
,
247 OBJ_FM_FORMATTEDFIELD
,
253 using namespace ::com::sun::star
;
254 using namespace ::com::sun::star::ui
;
255 using namespace ::com::sun::star::uno
;
256 using namespace ::com::sun::star::sdb
;
257 using namespace ::com::sun::star::sdbc
;
258 using namespace ::com::sun::star::sdbcx
;
259 using namespace ::com::sun::star::beans
;
260 using namespace ::com::sun::star::container
;
261 using namespace ::com::sun::star::form
;
262 using namespace ::com::sun::star::form::binding
;
263 using namespace ::com::sun::star::form::runtime
;
264 using namespace ::com::sun::star::awt
;
265 using namespace ::com::sun::star::view
;
266 using namespace ::com::sun::star::util
;
267 using namespace ::com::sun::star::frame
;
268 using namespace ::com::sun::star::script
;
269 using namespace ::svxform
;
270 using namespace ::svx
;
271 using namespace ::dbtools
;
279 void collectInterfacesFromMarkList( const SdrMarkList
& _rMarkList
, InterfaceBag
& /* [out] */ _rInterfaces
)
281 _rInterfaces
.clear();
283 const size_t nMarkCount
= _rMarkList
.GetMarkCount();
284 for ( size_t i
= 0; i
< nMarkCount
; ++i
)
286 SdrObject
* pCurrent
= _rMarkList
.GetMark( i
)->GetMarkedSdrObj();
288 boost::scoped_ptr
<SdrObjListIter
> pGroupIterator
;
289 if ( pCurrent
->IsGroupObject() )
291 pGroupIterator
.reset(new SdrObjListIter( *pCurrent
->GetSubList() ));
292 pCurrent
= pGroupIterator
->IsMore() ? pGroupIterator
->Next() : NULL
;
297 FmFormObj
* pAsFormObject
= FmFormObj::GetFormObject( pCurrent
);
298 // note this will de-reference virtual objects, if necessary/possible
301 Reference
< XInterface
> xControlModel( pAsFormObject
->GetUnoControlModel(), UNO_QUERY
);
302 // the UNO_QUERY is important for normalization
303 if ( xControlModel
.is() )
304 _rInterfaces
.insert( xControlModel
);
308 pCurrent
= pGroupIterator
&& pGroupIterator
->IsMore() ? pGroupIterator
->Next() : NULL
;
314 sal_Int16
GridView2ModelPos(const Reference
< XIndexAccess
>& rColumns
, sal_Int16 nViewPos
)
320 // loop through all columns
322 Reference
< XPropertySet
> xCur
;
323 for (i
=0; i
<rColumns
->getCount(); ++i
)
325 rColumns
->getByIndex(i
) >>= xCur
;
326 if (!::comphelper::getBOOL(xCur
->getPropertyValue(FM_PROP_HIDDEN
)))
328 // for every visible col : if nViewPos is greater zero, decrement it, else we
329 // have found the model position
336 if (i
<rColumns
->getCount())
340 catch(const Exception
&)
342 DBG_UNHANDLED_EXCEPTION();
344 return (sal_Int16
)-1;
348 void TransferEventScripts(const Reference
< XControlModel
>& xModel
, const Reference
< XControl
>& xControl
,
349 const Sequence
< ScriptEventDescriptor
>& rTransferIfAvailable
)
351 // first check if we have a XEventAttacherManager for the model
352 Reference
< XChild
> xModelChild(xModel
, UNO_QUERY
);
353 if (!xModelChild
.is())
354 return; // nothing to do
356 Reference
< XEventAttacherManager
> xEventManager(xModelChild
->getParent(), UNO_QUERY
);
357 if (!xEventManager
.is())
358 return; // nothing to do
360 if (!rTransferIfAvailable
.getLength())
361 return; // nothing to do
363 // check for the index of the model within its parent
364 Reference
< XIndexAccess
> xParentIndex(xModelChild
->getParent(), UNO_QUERY
);
365 if (!xParentIndex
.is())
366 return; // nothing to do
367 sal_Int32 nIndex
= getElementPos(xParentIndex
, xModel
);
368 if (nIndex
<0 || nIndex
>=xParentIndex
->getCount())
369 return; // nothing to do
371 // then we need information about the listeners supported by the control and the model
372 Sequence
< Type
> aModelListeners
;
373 Sequence
< Type
> aControlListeners
;
375 Reference
< XIntrospection
> xIntrospection
= theIntrospection::get(::comphelper::getProcessComponentContext());
379 Any
aModel(makeAny(xModel
));
380 aModelListeners
= xIntrospection
->inspect(aModel
)->getSupportedListeners();
385 Any
aControl(makeAny(xControl
));
386 aControlListeners
= xIntrospection
->inspect(aControl
)->getSupportedListeners();
389 sal_Int32 nMaxNewLen
= aModelListeners
.getLength() + aControlListeners
.getLength();
391 return; // the model and the listener don't support any listeners (or we were unable to retrieve these infos)
393 Sequence
< ScriptEventDescriptor
> aTransferable(nMaxNewLen
);
394 ScriptEventDescriptor
* pTransferable
= aTransferable
.getArray();
396 const ScriptEventDescriptor
* pCurrent
= rTransferIfAvailable
.getConstArray();
398 for (i
=0; i
<rTransferIfAvailable
.getLength(); ++i
, ++pCurrent
)
400 // search the model/control idl classes for the event described by pCurrent
401 for ( Sequence
< Type
>* pCurrentArray
= &aModelListeners
;
403 pCurrentArray
= (pCurrentArray
== &aModelListeners
) ? &aControlListeners
: NULL
406 const Type
* pCurrentListeners
= pCurrentArray
->getConstArray();
407 for (j
=0; j
<pCurrentArray
->getLength(); ++j
, ++pCurrentListeners
)
409 OUString aListener
= (*pCurrentListeners
).getTypeName();
410 sal_Int32 nTokens
= comphelper::string::getTokenCount(aListener
, '.');
412 aListener
= aListener
.getToken(nTokens
- 1, '.');
414 if (aListener
== pCurrent
->ListenerType
.getStr())
415 // the current ScriptEventDescriptor doesn't match the current listeners class
418 // now check the methods
419 Sequence
< OUString
> aMethodsNames
= ::comphelper::getEventMethodsForType(*pCurrentListeners
);
421 const OUString
* pMethodsNames
= aMethodsNames
.getConstArray();
422 for (k
=0; k
<aMethodsNames
.getLength(); ++k
, ++pMethodsNames
)
424 if ((*pMethodsNames
) != pCurrent
->EventMethod
)
425 // the current ScriptEventDescriptor doesn't match the current listeners current method
428 // we can transfer the script event : the model (control) supports it
429 *pTransferable
= *pCurrent
;
433 if (k
<aMethodsNames
.getLength())
439 sal_Int32 nRealNewLen
= pTransferable
- aTransferable
.getArray();
440 aTransferable
.realloc(nRealNewLen
);
442 xEventManager
->registerScriptEvents(nIndex
, aTransferable
);
446 OUString
getServiceNameByControlType(sal_Int16 nType
)
450 case OBJ_FM_EDIT
: return OUString(FM_COMPONENT_TEXTFIELD
);
451 case OBJ_FM_BUTTON
: return OUString(FM_COMPONENT_COMMANDBUTTON
);
452 case OBJ_FM_FIXEDTEXT
: return OUString(FM_COMPONENT_FIXEDTEXT
);
453 case OBJ_FM_LISTBOX
: return OUString(FM_COMPONENT_LISTBOX
);
454 case OBJ_FM_CHECKBOX
: return OUString(FM_COMPONENT_CHECKBOX
);
455 case OBJ_FM_RADIOBUTTON
: return OUString(FM_COMPONENT_RADIOBUTTON
);
456 case OBJ_FM_GROUPBOX
: return OUString(FM_COMPONENT_GROUPBOX
);
457 case OBJ_FM_COMBOBOX
: return OUString(FM_COMPONENT_COMBOBOX
);
458 case OBJ_FM_GRID
: return OUString(FM_COMPONENT_GRIDCONTROL
);
459 case OBJ_FM_IMAGEBUTTON
: return OUString(FM_COMPONENT_IMAGEBUTTON
);
460 case OBJ_FM_FILECONTROL
: return OUString(FM_COMPONENT_FILECONTROL
);
461 case OBJ_FM_DATEFIELD
: return OUString(FM_COMPONENT_DATEFIELD
);
462 case OBJ_FM_TIMEFIELD
: return OUString(FM_COMPONENT_TIMEFIELD
);
463 case OBJ_FM_NUMERICFIELD
: return OUString(FM_COMPONENT_NUMERICFIELD
);
464 case OBJ_FM_CURRENCYFIELD
: return OUString(FM_COMPONENT_CURRENCYFIELD
);
465 case OBJ_FM_PATTERNFIELD
: return OUString(FM_COMPONENT_PATTERNFIELD
);
466 case OBJ_FM_HIDDEN
: return OUString(FM_COMPONENT_HIDDENCONTROL
);
467 case OBJ_FM_IMAGECONTROL
: return OUString(FM_COMPONENT_IMAGECONTROL
);
468 case OBJ_FM_FORMATTEDFIELD
: return OUString(FM_COMPONENT_FORMATTEDFIELD
);
469 case OBJ_FM_SCROLLBAR
: return OUString(FM_SUN_COMPONENT_SCROLLBAR
);
470 case OBJ_FM_SPINBUTTON
: return OUString(FM_SUN_COMPONENT_SPINBUTTON
);
471 case OBJ_FM_NAVIGATIONBAR
: return OUString(FM_SUN_COMPONENT_NAVIGATIONBAR
);
479 // check if the control has one of the interfaces we can use for searching
480 // *_pCurrentText will be filled with the current text of the control (as used when searching this control)
481 bool IsSearchableControl( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _rxControl
,
482 OUString
* _pCurrentText
)
484 if ( !_rxControl
.is() )
487 Reference
< XTextComponent
> xAsText( _rxControl
, UNO_QUERY
);
491 *_pCurrentText
= xAsText
->getText();
495 Reference
< XListBox
> xListBox( _rxControl
, UNO_QUERY
);
499 *_pCurrentText
= xListBox
->getSelectedItem();
503 Reference
< XCheckBox
> xCheckBox( _rxControl
, UNO_QUERY
);
504 if ( xCheckBox
.is() )
508 switch ( (::TriState
)xCheckBox
->getState() )
510 case TRISTATE_FALSE
: *_pCurrentText
= "0"; break;
511 case TRISTATE_TRUE
: *_pCurrentText
= "1"; break;
512 default: _pCurrentText
->clear(); break;
522 bool FmXBoundFormFieldIterator::ShouldStepInto(const Reference
< XInterface
>& _rContainer
) const
524 if (_rContainer
== m_xStartingPoint
)
525 // would be quite stupid to step over the root ....
528 return Reference
< XControlModel
>(_rContainer
, UNO_QUERY
).is();
532 bool FmXBoundFormFieldIterator::ShouldHandleElement(const Reference
< XInterface
>& _rElement
)
538 if (Reference
< XForm
>(_rElement
, UNO_QUERY
).is() || Reference
< XGrid
>(_rElement
, UNO_QUERY
).is())
542 Reference
< XPropertySet
> xSet(_rElement
, UNO_QUERY
);
543 if (!xSet
.is() || !::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
544 // no "BoundField" property
547 Any
aVal( xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) );
548 if (aVal
.getValueTypeClass() != TypeClass_INTERFACE
)
549 // void or invalid property value
552 return aVal
.hasValue();
556 bool isControlList(const SdrMarkList
& rMarkList
)
558 // enthaelt die liste nur Controls und mindestens ein control
559 const size_t nMarkCount
= rMarkList
.GetMarkCount();
560 bool bControlList
= nMarkCount
!= 0;
562 bool bHadAnyLeafs
= false;
564 for (size_t i
= 0; i
< nMarkCount
&& bControlList
; ++i
)
566 SdrObject
*pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
567 E3dObject
* pAs3DObject
= PTR_CAST(E3dObject
, pObj
);
568 // E3dObject's do not contain any 2D-objects (by definition)
569 // we need this extra check here : an E3dObject->IsGroupObject says "YES", but an SdrObjListIter working
570 // with an E3dObject doesn't give me any Nodes (E3dObject has a sub list, but no members in that list,
571 // cause there implementation differs from the one of "normal" SdrObject's. Unfortunally SdrObject::IsGroupObject
572 // doesn't check the element count of the sub list, which is simply a bug in IsGroupObject we can't fix at the moment).
573 // So at the end of this function bControlList would have the same value it was initialized with above : sal_True
574 // And this would be wrong :)
575 // 03.02.00 - 72529 - FS
578 if (pObj
->IsGroupObject())
580 SdrObjListIter
aIter(*pObj
->GetSubList());
581 while (aIter
.IsMore() && bControlList
)
583 bControlList
= FmFormInventor
== aIter
.Next()->GetObjInventor();
590 bControlList
= FmFormInventor
== pObj
->GetObjInventor();
595 return bControlList
&& bHadAnyLeafs
;
599 Reference
< XForm
> GetForm(const Reference
< XInterface
>& _rxElement
)
601 Reference
< XForm
> xForm( _rxElement
, UNO_QUERY
);
605 Reference
< XChild
> xChild( _rxElement
, UNO_QUERY
);
607 return GetForm( xChild
->getParent() );
609 return Reference
< XForm
>();
612 FmXFormShell_Base_Disambiguation::FmXFormShell_Base_Disambiguation( ::osl::Mutex
& _rMutex
)
613 :FmXFormShell_BD_BASE( _rMutex
)
617 void SAL_CALL
FmXFormShell_Base_Disambiguation::disposing()
619 WeakComponentImplHelperBase::disposing();
622 // Normally it should be sufficient to call the "disposing" of our direct
623 // base class, but SUN PRO 5 does not like this and claims there is a conflict
624 // with the XEventListener::disposing(EventObject) of our various listener
628 FmXFormShell::FmXFormShell( FmFormShell
& _rShell
, SfxViewFrame
* _pViewFrame
)
629 :FmXFormShell_BASE(m_aMutex
)
630 ,FmXFormShell_CFGBASE(OUString("Office.Common/Misc"), ConfigItemMode::DelayedUpdate
)
631 ,m_eNavigate( NavigationBarMode_NONE
)
632 ,m_nInvalidationEvent( 0 )
633 ,m_nActivationEvent( 0 )
634 ,m_pShell( &_rShell
)
635 ,m_pTextShell( new svx::FmTextControlShell( _pViewFrame
) )
636 ,m_aActiveControllerFeatures( this )
637 ,m_aNavControllerFeatures( this )
638 ,m_eDocumentType( eUnknownDocumentType
)
639 ,m_nLockSlotInvalidation( 0 )
640 ,m_bHadPropertyBrowserInDesignMode( false )
641 ,m_bTrackProperties( true )
642 ,m_bUseWizards( true )
643 ,m_bDatabaseBar( false )
644 ,m_bInActivate( false )
645 ,m_bSetFocus( false )
646 ,m_bFilterMode( false )
647 ,m_bChangingDesignMode( false )
648 ,m_bPreparedClose( false )
649 ,m_bFirstActivation( true )
651 m_aMarkTimer
.SetTimeout(100);
652 m_aMarkTimer
.SetTimeoutHdl(LINK(this,FmXFormShell
,OnTimeOut
));
654 m_xAttachedFrame
= _pViewFrame
->GetFrame().GetFrameInterface();
656 // to prevent deletion of this we acquire our refcounter once
657 osl_atomic_increment(&m_refCount
);
659 // correct the refcounter
660 osl_atomic_decrement(&m_refCount
);
662 // cache the current configuration settings we're interested in
663 implAdjustConfigCache();
664 // and register for changes on this settings
665 Sequence
< OUString
> aNames(1);
666 aNames
[0] = "FormControlPilotsEnabled";
667 EnableNotification(aNames
);
671 FmXFormShell::~FmXFormShell()
677 Reference
< XModel
> FmXFormShell::getContextDocument() const
679 Reference
< XModel
> xModel
;
681 // determine the type of document we live in
684 Reference
< XController
> xController
;
685 if ( m_xAttachedFrame
.is() )
686 xController
= m_xAttachedFrame
->getController();
687 if ( xController
.is() )
688 xModel
= xController
->getModel();
690 catch( const Exception
& )
692 DBG_UNHANDLED_EXCEPTION();
698 bool FmXFormShell::isEnhancedForm() const
700 return getDocumentType() == eEnhancedForm
;
704 bool FmXFormShell::impl_checkDisposed() const
708 OSL_FAIL( "FmXFormShell::impl_checkDisposed: already disposed!" );
715 ::svxform::DocumentType
FmXFormShell::getDocumentType() const
717 if ( m_eDocumentType
!= eUnknownDocumentType
)
718 return m_eDocumentType
;
720 // determine the type of document we live in
721 Reference
< XModel
> xModel
= getContextDocument();
723 m_eDocumentType
= DocumentClassification::classifyDocument( xModel
);
726 OSL_FAIL( "FmXFormShell::getDocumentType: can't determine the document type!" );
727 m_eDocumentType
= eTextDocument
;
728 // fallback, just to have a defined state
731 return m_eDocumentType
;
735 bool FmXFormShell::IsReadonlyDoc() const
737 if ( impl_checkDisposed() )
740 FmFormModel
* pModel
= m_pShell
->GetFormModel();
741 if ( pModel
&& pModel
->GetObjectShell() )
742 return pModel
->GetObjectShell()->IsReadOnly() || pModel
->GetObjectShell()->IsReadOnlyUI();
748 void SAL_CALL
FmXFormShell::disposing(const lang::EventObject
& e
) throw( RuntimeException
, std::exception
)
751 if (m_xActiveController
== e
.Source
)
753 // wird der Controller freigeben dann alles loslassen
755 m_xActiveForm
= NULL
;
756 m_xActiveController
= NULL
;
757 m_xNavigationController
= NULL
;
759 m_aActiveControllerFeatures
.dispose();
760 m_aNavControllerFeatures
.dispose();
763 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
766 if (e
.Source
== m_xExternalViewController
)
768 Reference
< runtime::XFormController
> xFormController( m_xExternalViewController
, UNO_QUERY
);
769 OSL_ENSURE( xFormController
.is(), "FmXFormShell::disposing: invalid external view controller!" );
770 if (xFormController
.is())
771 xFormController
->removeActivateListener((XFormControllerListener
*)this);
773 Reference
< ::com::sun::star::lang::XComponent
> xComp(m_xExternalViewController
, UNO_QUERY
);
775 xComp
->removeEventListener((XEventListener
*)(XPropertyChangeListener
*)this);
777 m_xExternalViewController
= NULL
;
778 m_xExternalDisplayedForm
= NULL
;
779 m_xExtViewTriggerController
= NULL
;
781 InvalidateSlot( SID_FM_VIEW_AS_GRID
, false );
786 void SAL_CALL
FmXFormShell::propertyChange(const PropertyChangeEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
788 if ( impl_checkDisposed() )
791 if (evt
.PropertyName
== FM_PROP_ROWCOUNT
)
793 // Das gleich folgenden Update erzwingt ein Neu-Painten der entsprechenden Slots. Wenn ich mich aber hier nicht
794 // in dem HauptThread der Applikation befinde (weil zum Beispiel ein Cursor gerade Datensaetze zaehlt und mir dabei
795 // immer diese PropertyChanges beschert), kann sich das mit en normalen Paints im HauptThread der Applikation beissen.
796 // (Solche Paints passieren zum Beispiel, wenn man einfach nur eine andere Applikation ueber das Office legt und wieder
798 // Deshalb die Benutzung des SolarMutex, der sichert das ab.
799 comphelper::SolarMutex
& rSolarSafety
= Application::GetSolarMutex();
800 if (rSolarSafety
.tryToAcquire())
802 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_RECORD_TOTAL
, true, false);
803 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Update(SID_FM_RECORD_TOTAL
);
804 rSolarSafety
.release();
808 // with the following the slot is invalidated asynchron
809 LockSlotInvalidation(true);
810 InvalidateSlot(SID_FM_RECORD_TOTAL
, false);
811 LockSlotInvalidation(false);
815 // this may be called from a non-main-thread so invalidate the shell asynchronously
816 LockSlotInvalidation(true);
817 InvalidateSlot(0, false); // special meaning : invalidate m_pShell
818 LockSlotInvalidation(false);
822 void FmXFormShell::invalidateFeatures( const ::std::vector
< sal_Int32
>& _rFeatures
)
824 if ( impl_checkDisposed() )
827 OSL_ENSURE( _rFeatures
.size() > 0, "FmXFormShell::invalidateFeatures: invalid arguments!" );
829 if ( m_pShell
->GetViewShell() && m_pShell
->GetViewShell()->GetViewFrame() )
831 // unfortunately, SFX requires sal_uInt16
832 ::std::vector
< sal_uInt16
> aSlotIds
;
833 aSlotIds
.reserve( _rFeatures
.size() );
834 ::std::copy( _rFeatures
.begin(),
836 ::std::insert_iterator
< ::std::vector
< sal_uInt16
> >( aSlotIds
, aSlotIds
.begin() )
839 // furthermore, SFX wants a terminating 0
840 aSlotIds
.push_back( 0 );
842 // and, last but not least, SFX wants the ids to be sorted
843 ::std::sort( aSlotIds
.begin(), aSlotIds
.end() - 1 );
845 sal_uInt16
*pSlotIds
= &(aSlotIds
[0]);
846 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( pSlotIds
);
851 void SAL_CALL
FmXFormShell::formActivated(const lang::EventObject
& rEvent
) throw( RuntimeException
, std::exception
)
853 if ( impl_checkDisposed() )
856 Reference
< runtime::XFormController
> xController( rEvent
.Source
, UNO_QUERY_THROW
);
857 m_pTextShell
->formActivated( xController
);
858 setActiveController( xController
);
862 void SAL_CALL
FmXFormShell::formDeactivated(const lang::EventObject
& rEvent
) throw( RuntimeException
, std::exception
)
864 if ( impl_checkDisposed() )
867 Reference
< runtime::XFormController
> xController( rEvent
.Source
, UNO_QUERY_THROW
);
868 m_pTextShell
->formDeactivated( xController
);
872 void FmXFormShell::disposing()
875 FmXFormShell_BASE::disposing();
877 if ( m_pShell
&& !m_pShell
->IsDesignMode() )
878 setActiveController( NULL
, true );
879 // do NOT save the content of the old form (the second parameter tells this)
880 // if we're here, then we expect that PrepareClose has been called, and thus the user
881 // got a chance to commit or reject any changes. So in case we're here and there
882 // are still uncommitted changes, the user explicitly wanted this.
884 m_pTextShell
->dispose();
886 m_xAttachedFrame
= NULL
;
888 CloseExternalFormViewer();
890 while ( m_aLoadingPages
.size() )
892 Application::RemoveUserEvent( m_aLoadingPages
.front().nEventId
);
893 m_aLoadingPages
.pop();
897 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
898 if (m_nInvalidationEvent
)
900 Application::RemoveUserEvent(m_nInvalidationEvent
);
901 m_nInvalidationEvent
= 0;
903 if ( m_nActivationEvent
)
905 Application::RemoveUserEvent( m_nActivationEvent
);
906 m_nActivationEvent
= 0;
911 ::osl::ClearableMutexGuard
aGuard(m_aAsyncSafety
);
914 DBG_ASSERT(!m_nInvalidationEvent
, "FmXFormShell::~FmXFormShell : still have an invalidation event !");
915 // should have been deleted while being disposed
920 DisableNotification();
922 RemoveElement( m_xForms
);
925 impl_switchActiveControllerListening( false );
926 m_xActiveController
= NULL
;
927 m_xActiveForm
= NULL
;
930 m_xNavigationController
= NULL
;
931 m_xCurrentForm
= NULL
;
932 m_xLastGridFound
= NULL
;
933 m_xAttachedFrame
= NULL
;
934 m_xExternalViewController
= NULL
;
935 m_xExtViewTriggerController
= NULL
;
936 m_xExternalDisplayedForm
= NULL
;
937 m_xLastGridFound
= NULL
;
940 m_aCurrentSelection
.swap( aEmpty
);
942 m_aActiveControllerFeatures
.dispose();
943 m_aNavControllerFeatures
.dispose();
947 void FmXFormShell::UpdateSlot( sal_Int16 _nId
)
949 if ( impl_checkDisposed() )
952 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
954 if ( m_nLockSlotInvalidation
)
956 OSL_FAIL( "FmXFormShell::UpdateSlot: cannot update if invalidation is currently locked!" );
957 InvalidateSlot( _nId
, false );
961 OSL_ENSURE( _nId
, "FmXFormShell::UpdateSlot: can't update the complete shell!" );
962 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( _nId
, true, true );
963 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Update( _nId
);
968 void FmXFormShell::InvalidateSlot( sal_Int16 nId
, bool bWithId
)
970 if ( impl_checkDisposed() )
973 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
974 if (m_nLockSlotInvalidation
)
976 sal_uInt8 nFlags
= ( bWithId
? 0x01 : 0 );
977 m_arrInvalidSlots
.push_back( InvalidSlotInfo(nId
, nFlags
) );
981 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(nId
, true, bWithId
);
983 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
987 void FmXFormShell::LockSlotInvalidation(bool bLock
)
989 if ( impl_checkDisposed() )
992 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
993 DBG_ASSERT(bLock
|| m_nLockSlotInvalidation
>0, "FmXFormShell::LockSlotInvalidation : invalid call !");
996 ++m_nLockSlotInvalidation
;
997 else if (!--m_nLockSlotInvalidation
)
999 // alles, was sich waehrend der gelockten Phase angesammelt hat, (asynchron) invalidieren
1000 if (!m_nInvalidationEvent
)
1001 m_nInvalidationEvent
= Application::PostUserEvent(LINK(this, FmXFormShell
, OnInvalidateSlots
));
1006 IMPL_LINK_NOARG(FmXFormShell
, OnInvalidateSlots
)
1008 if ( impl_checkDisposed() )
1011 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
1012 m_nInvalidationEvent
= 0;
1014 for (std::vector
<InvalidSlotInfo
>::const_iterator i
= m_arrInvalidSlots
.begin(); i
< m_arrInvalidSlots
.end(); ++i
)
1017 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(i
->id
, true, (i
->flags
& 0x01));
1019 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
1021 m_arrInvalidSlots
.clear();
1026 void FmXFormShell::ForceUpdateSelection(bool bAllowInvalidation
)
1028 if ( impl_checkDisposed() )
1031 if (IsSelectionUpdatePending())
1033 m_aMarkTimer
.Stop();
1035 // die Invalidierung der Slots, die implizit von SetSelection besorgt wird, eventuell abschalten
1036 if (!bAllowInvalidation
)
1037 LockSlotInvalidation(true);
1039 SetSelection(m_pShell
->GetFormView()->GetMarkedObjectList());
1041 if (!bAllowInvalidation
)
1042 LockSlotInvalidation(false);
1047 PopupMenu
* FmXFormShell::GetConversionMenu()
1050 PopupMenu
* pNewMenu
= new PopupMenu(SVX_RES( RID_FMSHELL_CONVERSIONMENU
));
1052 ImageList
aImageList( SVX_RES( RID_SVXIMGLIST_FMEXPL
) );
1053 for ( size_t i
= 0; i
< sizeof (nConvertSlots
) / sizeof (nConvertSlots
[0]); ++i
)
1055 // das entsprechende Image dran
1056 pNewMenu
->SetItemImage(nConvertSlots
[i
], aImageList
.GetImage(nCreateSlots
[i
]));
1063 bool FmXFormShell::isControlConversionSlot( sal_uInt16 nSlotId
)
1065 for ( size_t i
= 0; i
< sizeof (nConvertSlots
) / sizeof (nConvertSlots
[0]); ++i
)
1066 if (nConvertSlots
[i
] == nSlotId
)
1072 bool FmXFormShell::executeControlConversionSlot( sal_uInt16 _nSlotId
)
1074 OSL_PRECOND( canConvertCurrentSelectionToControl( _nSlotId
), "FmXFormShell::executeControlConversionSlot: illegal call!" );
1075 InterfaceBag::const_iterator aSelectedElement
= m_aCurrentSelection
.begin();
1076 if ( aSelectedElement
== m_aCurrentSelection
.end() )
1079 return executeControlConversionSlot( Reference
< XFormComponent
>( *aSelectedElement
, UNO_QUERY
), _nSlotId
);
1083 bool FmXFormShell::executeControlConversionSlot( const Reference
< XFormComponent
>& _rxObject
, sal_uInt16 _nSlotId
)
1085 if ( impl_checkDisposed() )
1088 OSL_ENSURE( _rxObject
.is(), "FmXFormShell::executeControlConversionSlot: invalid object!" );
1089 if ( !_rxObject
.is() )
1092 SdrPage
* pPage
= m_pShell
->GetCurPage();
1093 FmFormPage
* pFormPage
= pPage
? dynamic_cast< FmFormPage
* >( pPage
) : NULL
;
1094 OSL_ENSURE( pFormPage
, "FmXFormShell::executeControlConversionSlot: no current (form) page!" );
1098 OSL_ENSURE( isSolelySelected( _rxObject
),
1099 "FmXFormShell::executeControlConversionSlot: hmm ... shouldn't this parameter be redundant?" );
1101 for ( size_t lookupSlot
= 0; lookupSlot
< sizeof( nConvertSlots
) / sizeof( nConvertSlots
[0] ); ++lookupSlot
)
1103 if (nConvertSlots
[lookupSlot
] == _nSlotId
)
1105 Reference
< XInterface
> xNormalizedObject( _rxObject
, UNO_QUERY
);
1107 FmFormObj
* pFormObject
= NULL
;
1108 SdrObjListIter
aPageIter( *pFormPage
);
1109 while ( aPageIter
.IsMore() )
1111 SdrObject
* pCurrent
= aPageIter
.Next();
1112 pFormObject
= FmFormObj::GetFormObject( pCurrent
);
1116 Reference
< XInterface
> xCurrentNormalized( pFormObject
->GetUnoControlModel(), UNO_QUERY
);
1117 if ( xCurrentNormalized
.get() == xNormalizedObject
.get() )
1126 OUString
sNewName( getServiceNameByControlType( nObjectTypes
[ lookupSlot
] ) );
1127 Reference
<XComponentContext
> xContext
= comphelper::getProcessComponentContext();
1128 Reference
< XControlModel
> xNewModel( xContext
->getServiceManager()->createInstanceWithContext(sNewName
, xContext
), UNO_QUERY
);
1129 if (!xNewModel
.is())
1132 Reference
< XControlModel
> xOldModel( pFormObject
->GetUnoControlModel() );
1133 Reference
< lang::XServiceInfo
> xModelInfo(xOldModel
, UNO_QUERY
);
1135 // Properties uebertragen
1136 Reference
< XPropertySet
> xOldSet(xOldModel
, UNO_QUERY
);
1137 Reference
< XPropertySet
> xNewSet(xNewModel
, UNO_QUERY
);
1140 lang::Locale aNewLanguage
= Application::GetSettings().GetUILanguageTag().getLocale();
1141 TransferFormComponentProperties(xOldSet
, xNewSet
, aNewLanguage
);
1143 Sequence
< ::com::sun::star::script::ScriptEventDescriptor
> aOldScripts
;
1144 Reference
< XChild
> xChild(xOldModel
, UNO_QUERY
);
1147 Reference
< XIndexAccess
> xParent(xChild
->getParent(), UNO_QUERY
);
1149 // remember old script events
1150 Reference
< ::com::sun::star::script::XEventAttacherManager
> xEvManager(xChild
->getParent(), UNO_QUERY
);
1151 if (xParent
.is() && xEvManager
.is())
1153 sal_Int32 nIndex
= getElementPos(xParent
, xOldModel
);
1154 if (nIndex
>=0 && nIndex
<xParent
->getCount())
1155 aOldScripts
= xEvManager
->getScriptEvents(nIndex
);
1158 // replace the mdoel within the parent container
1159 Reference
< XIndexContainer
> xIndexParent(xChild
->getParent(), UNO_QUERY
);
1160 if (xIndexParent
.is())
1162 // the form container works with FormComponents
1163 Reference
< XFormComponent
> xComponent(xNewModel
, UNO_QUERY
);
1164 DBG_ASSERT(xComponent
.is(), "FmXFormShell::executeControlConversionSlot: the new model is no form component !");
1165 Any
aNewModel(makeAny(xComponent
));
1169 sal_Int32 nIndex
= getElementPos(xParent
, xOldModel
);
1170 if (nIndex
>=0 && nIndex
<xParent
->getCount())
1171 xIndexParent
->replaceByIndex(nIndex
, aNewModel
);
1174 OSL_FAIL("FmXFormShell::executeControlConversionSlot: could not replace the model !");
1175 Reference
< ::com::sun::star::lang::XComponent
> xNewComponent(xNewModel
, UNO_QUERY
);
1176 if (xNewComponent
.is())
1177 xNewComponent
->dispose();
1183 OSL_FAIL("FmXFormShell::executeControlConversionSlot: could not replace the model !");
1184 Reference
< ::com::sun::star::lang::XComponent
> xNewComponent(xNewModel
, UNO_QUERY
);
1185 if (xNewComponent
.is())
1186 xNewComponent
->dispose();
1193 // special handling for the LabelControl-property : can only be set when the model is placed
1194 // within the forms hierarchy
1195 if (::comphelper::hasProperty(FM_PROP_CONTROLLABEL
, xOldSet
) && ::comphelper::hasProperty(FM_PROP_CONTROLLABEL
, xNewSet
))
1199 xNewSet
->setPropertyValue(FM_PROP_CONTROLLABEL
, xOldSet
->getPropertyValue(FM_PROP_CONTROLLABEL
));
1207 // neues Model setzen
1208 pFormObject
->SetChanged();
1209 pFormObject
->SetUnoControlModel(xNewModel
);
1211 // transfer script events
1212 // (do this _after_ SetUnoControlModel as we need the new (implicitly created) control)
1213 if (aOldScripts
.getLength())
1215 // das Control zum Model suchen
1216 Reference
< XControlContainer
> xControlContainer( getControlContainerForView() );
1218 Sequence
< Reference
< XControl
> > aControls( xControlContainer
->getControls() );
1219 const Reference
< XControl
>* pControls
= aControls
.getConstArray();
1221 sal_uInt32 nLen
= aControls
.getLength();
1222 Reference
< XControl
> xControl
;
1223 for (sal_uInt32 i
=0 ; i
<nLen
; ++i
)
1225 if (pControls
[i
]->getModel() == xNewModel
)
1227 xControl
= pControls
[i
];
1231 TransferEventScripts(xNewModel
, xControl
, aOldScripts
);
1234 // transfer value bindings, if possible
1236 Reference
< XBindableValue
> xOldBindable( xOldModel
, UNO_QUERY
);
1237 Reference
< XBindableValue
> xNewBindable( xNewModel
, UNO_QUERY
);
1238 if ( xOldBindable
.is() )
1242 if ( xNewBindable
.is() )
1243 xNewBindable
->setValueBinding( xOldBindable
->getValueBinding() );
1244 xOldBindable
->setValueBinding( NULL
);
1246 catch(const Exception
&)
1248 DBG_UNHANDLED_EXCEPTION();
1252 // same for list entry sources
1254 Reference
< XListEntrySink
> xOldSink( xOldModel
, UNO_QUERY
);
1255 Reference
< XListEntrySink
> xNewSink( xNewModel
, UNO_QUERY
);
1256 if ( xOldSink
.is() )
1260 if ( xNewSink
.is() )
1261 xNewSink
->setListEntrySource( xOldSink
->getListEntrySource() );
1262 xOldSink
->setListEntrySource( NULL
);
1264 catch(const Exception
&)
1266 DBG_UNHANDLED_EXCEPTION();
1271 // create an undo action
1272 FmFormModel
* pModel
= m_pShell
->GetFormModel();
1273 DBG_ASSERT(pModel
!= NULL
, "FmXFormShell::executeControlConversionSlot: my shell has no model !");
1274 if (pModel
&& pModel
->IsUndoEnabled() )
1276 pModel
->AddUndo(new FmUndoModelReplaceAction(*pModel
, pFormObject
, xOldModel
));
1280 FmUndoModelReplaceAction::DisposeElement( xOldModel
);
1290 bool FmXFormShell::canConvertCurrentSelectionToControl( sal_Int16 nConversionSlot
)
1292 if ( m_aCurrentSelection
.empty() )
1295 InterfaceBag::const_iterator aCheck
= m_aCurrentSelection
.begin();
1296 Reference
< lang::XServiceInfo
> xElementInfo( *aCheck
, UNO_QUERY
);
1297 if ( !xElementInfo
.is() )
1298 // no service info -> cannot determine this
1301 if ( ++aCheck
!= m_aCurrentSelection
.end() )
1302 // more than one element
1305 if ( Reference
< XForm
>::query( xElementInfo
).is() )
1309 sal_Int16 nObjectType
= getControlTypeByObject( xElementInfo
);
1311 if ( ( OBJ_FM_HIDDEN
== nObjectType
)
1312 || ( OBJ_FM_CONTROL
== nObjectType
)
1313 || ( OBJ_FM_GRID
== nObjectType
)
1315 return false; // those types cannot be converted
1317 DBG_ASSERT(sizeof(nConvertSlots
)/sizeof(nConvertSlots
[0]) == sizeof(nObjectTypes
)/sizeof(nObjectTypes
[0]),
1318 "FmXFormShell::canConvertCurrentSelectionToControl: nConvertSlots & nObjectTypes must have the same size !");
1320 for ( size_t i
= 0; i
< sizeof( nConvertSlots
) / sizeof( nConvertSlots
[0] ); ++i
)
1321 if (nConvertSlots
[i
] == nConversionSlot
)
1322 return nObjectTypes
[i
] != nObjectType
;
1324 return true; // all other slots: assume "yes"
1328 void FmXFormShell::checkControlConversionSlotsForCurrentSelection( Menu
& rMenu
)
1330 for (sal_Int16 i
=0; i
<rMenu
.GetItemCount(); ++i
)
1331 // der Context ist schon von einem Typ, der dem Eitnrag entspricht -> disable
1332 rMenu
.EnableItem( rMenu
.GetItemId(i
), canConvertCurrentSelectionToControl( rMenu
.GetItemId( i
) ) );
1336 void FmXFormShell::LoopGrids(sal_Int16 nWhat
)
1338 if ( impl_checkDisposed() )
1341 Reference
< XIndexContainer
> xControlModels(m_xActiveForm
, UNO_QUERY
);
1342 if (xControlModels
.is())
1344 for (sal_Int16 i
=0; i
<xControlModels
->getCount(); ++i
)
1346 Reference
< XPropertySet
> xModelSet
;
1347 xControlModels
->getByIndex(i
) >>= xModelSet
;
1348 if (!xModelSet
.is())
1351 if (!::comphelper::hasProperty(FM_PROP_CLASSID
, xModelSet
))
1353 sal_Int16 nClassId
= ::comphelper::getINT16(xModelSet
->getPropertyValue(FM_PROP_CLASSID
));
1354 if (FormComponentType::GRIDCONTROL
!= nClassId
)
1357 if (!::comphelper::hasProperty(FM_PROP_CURSORCOLOR
, xModelSet
) || !::comphelper::hasProperty(FM_PROP_ALWAYSSHOWCURSOR
, xModelSet
) || !::comphelper::hasProperty(FM_PROP_DISPLAYSYNCHRON
, xModelSet
))
1360 switch (nWhat
& GA_SYNC_MASK
)
1362 case GA_DISABLE_SYNC
:
1364 sal_Bool
bB(sal_False
);
1365 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, Any(&bB
,cppu::UnoType
<bool>::get()));
1370 Any
aOldVal( xModelSet
->getPropertyValue(FM_PROP_DISPLAYSYNCHRON
) );
1371 sal_Bool
bB(sal_True
);
1372 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, Any(&bB
,cppu::UnoType
<bool>::get()));
1373 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, aOldVal
);
1376 case GA_ENABLE_SYNC
:
1378 sal_Bool
bB(sal_True
);
1379 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, Any(&bB
,cppu::UnoType
<bool>::get()));
1384 if (nWhat
& GA_DISABLE_ROCTRLR
)
1386 sal_Bool
bB(sal_False
);
1387 xModelSet
->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR
, Any(&bB
,cppu::UnoType
<bool>::get()));
1388 Reference
< XPropertyState
> xModelPropState(xModelSet
, UNO_QUERY
);
1389 if (xModelPropState
.is())
1390 xModelPropState
->setPropertyToDefault(FM_PROP_CURSORCOLOR
);
1392 xModelSet
->setPropertyValue(FM_PROP_CURSORCOLOR
, Any()); // this should be the default
1394 else if (nWhat
& GA_ENABLE_ROCTRLR
)
1396 sal_Bool
bB(sal_True
);
1397 xModelSet
->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR
, Any(&bB
,cppu::UnoType
<bool>::get()));
1398 xModelSet
->setPropertyValue(FM_PROP_CURSORCOLOR
, makeAny(sal_Int32(COL_LIGHTRED
)));
1405 Reference
< XControlContainer
> FmXFormShell::getControlContainerForView()
1407 if ( impl_checkDisposed() )
1410 SdrPageView
* pPageView
= NULL
;
1411 if ( m_pShell
&& m_pShell
->GetFormView() )
1412 pPageView
= m_pShell
->GetFormView()->GetSdrPageView();
1414 Reference
< XControlContainer
> xControlContainer
;
1416 xControlContainer
= pPageView
->GetPageWindow(0)->GetControlContainer();
1418 return xControlContainer
;
1422 void FmXFormShell::ExecuteTabOrderDialog( const Reference
< XTabControllerModel
>& _rxForForm
)
1424 if ( impl_checkDisposed() )
1427 OSL_PRECOND( _rxForForm
.is(), "FmXFormShell::ExecuteTabOrderDialog: invalid tabbing model!" );
1428 if ( !_rxForForm
.is() )
1433 Reference
< XWindow
> xParentWindow
;
1434 if ( m_pShell
->GetViewShell() && m_pShell
->GetViewShell()->GetViewFrame() )
1435 xParentWindow
= VCLUnoHelper::GetInterface ( &m_pShell
->GetViewShell()->GetViewFrame()->GetWindow() );
1437 Reference
< dialogs::XExecutableDialog
> xDialog
= form::TabOrderDialog::createWithModel(
1438 comphelper::getProcessComponentContext(),
1439 _rxForForm
, getControlContainerForView(), xParentWindow
1444 catch( const Exception
& )
1446 OSL_FAIL( "FmXFormShell::ExecuteTabOrderDialog: caught an exception!" );
1451 void FmXFormShell::ExecuteSearch()
1453 if ( impl_checkDisposed() )
1456 // eine Sammlung aller (logischen) Formulare
1458 m_aSearchForms
.swap( aEmpty
);
1459 ::std::vector
< OUString
> aContextNames
;
1460 impl_collectFormSearchContexts_nothrow( m_pShell
->GetCurPage()->GetForms(), OUString(), m_aSearchForms
, aContextNames
);
1462 if ( m_aSearchForms
.size() != aContextNames
.size() )
1464 SAL_WARN ( "svx.form", "FmXFormShell::ExecuteSearch: nonsense!" );
1468 // filter out the forms which do not contain valid controls at all
1470 FmFormArray aValidForms
;
1471 ::std::vector
< OUString
> aValidContexts
;
1472 FmFormArray::const_iterator form
= m_aSearchForms
.begin();
1473 ::std::vector
< OUString
>::const_iterator contextName
= aContextNames
.begin();
1474 for ( ; form
!= m_aSearchForms
.end(); ++form
, ++contextName
)
1476 FmSearchContext aTestContext
;
1477 aTestContext
.nContext
= static_cast< sal_Int16
>( form
- m_aSearchForms
.begin() );
1478 sal_uInt32 nValidControls
= OnSearchContextRequest( &aTestContext
);
1479 if ( nValidControls
> 0 )
1481 aValidForms
.push_back( *form
);
1482 aValidContexts
.push_back( *contextName
);
1486 m_aSearchForms
.swap( aValidForms
);
1487 aContextNames
.swap( aValidContexts
);
1490 if (m_aSearchForms
.empty() )
1491 { // es gibt keine Controls, die alle Bedingungen fuer eine Suche erfuellen
1492 ScopedVclPtrInstance
<MessageDialog
>::Create(nullptr, SVX_RESSTR(RID_STR_NODATACONTROLS
))->Execute();
1496 // jetzt brauche ich noch einen 'initial context'
1497 sal_Int16 nInitialContext
= 0;
1498 Reference
< XForm
> xActiveForm( getActiveForm());
1499 for ( size_t i
=0; i
<m_aSearchForms
.size(); ++i
)
1501 if (m_aSearchForms
.at(i
) == xActiveForm
)
1503 nInitialContext
= (sal_Int16
)i
;
1508 // wenn der Dialog initial den Text des aktiven Controls anbieten soll, muss dieses ein XTextComponent-Interface habe,
1509 // ausserdem macht das nur Sinn, wenn das aktuelle Feld auch an ein Tabellen- (oder was-auch-immer-)Feld gebunden ist
1510 OUString strActiveField
;
1511 OUString strInitialText
;
1512 // ... das bekomme ich von meinem FormController
1513 DBG_ASSERT(m_xActiveController
.is(), "FmXFormShell::ExecuteSearch : no active controller !");
1514 Reference
< XControl
> xActiveControl( m_xActiveController
->getCurrentControl());
1515 if (xActiveControl
.is())
1517 // das Control kann mir sein Model sagen ...
1518 Reference
< XControlModel
> xActiveModel( xActiveControl
->getModel());
1519 DBG_ASSERT(xActiveModel
.is(), "FmXFormShell::ExecuteSearch : active control has no model !");
1521 // das Model frage ich nach der ControlSource-Eigenschaft ...
1522 Reference
< XPropertySet
> xProperties(xActiveControl
->getModel(), UNO_QUERY
);
1523 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE
, xProperties
) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xProperties
))
1525 Reference
< XPropertySet
> xField
;
1526 xProperties
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
1527 if (xField
.is()) // (nur wenn das Ding wirklich gebunden ist)
1529 // und das Control selber nach einem TextComponent-Interface (damit ich mir dort den Text abholen kann)
1530 Reference
< XTextComponent
> xText(xActiveControl
, UNO_QUERY
);
1533 strActiveField
= getLabelName(xProperties
).getStr();
1534 strInitialText
= xText
->getText().getStr();
1540 // das Control selber hat keine ControlSource, aber vielleicht ist es ein GridControl
1541 Reference
< XGrid
> xGrid(xActiveControl
, UNO_QUERY
);
1544 // fuer strActiveField brauche ich die ControlSource der Column, dafuer den Columns-Container, dafuer die
1546 Reference
< XGridPeer
> xGridPeer(xActiveControl
->getPeer(), UNO_QUERY
);
1547 Reference
< XIndexAccess
> xColumns
;
1549 xColumns
= Reference
< XIndexAccess
>(xGridPeer
->getColumns(),UNO_QUERY
);
1551 sal_Int16 nViewCol
= xGrid
->getCurrentColumnPosition();
1552 sal_Int16 nModelCol
= GridView2ModelPos(xColumns
, nViewCol
);
1553 Reference
< XPropertySet
> xCurrentCol
;
1555 xColumns
->getByIndex(nModelCol
) >>= xCurrentCol
;
1556 if (xCurrentCol
.is())
1557 strActiveField
= ::comphelper::getString(xCurrentCol
->getPropertyValue(FM_PROP_LABEL
)).getStr();
1559 // the text fo the current column
1560 Reference
< XIndexAccess
> xColControls(xGridPeer
, UNO_QUERY
);
1561 Reference
< XInterface
> xCurControl
;
1562 xColControls
->getByIndex(nViewCol
) >>= xCurControl
;
1563 OUString sInitialText
;
1564 if (IsSearchableControl(xCurControl
, &sInitialText
))
1565 strInitialText
= sInitialText
.getStr();
1570 // um eventuelle GridControls, die ich kenne, kuemmern
1571 LoopGrids(GA_DISABLE_SYNC
/*| GA_ENABLE_ROCTRLR*/);
1573 // jetzt bin ich reif fuer den Dialog
1574 // wenn die potentiellen Deadlocks, die durch die Benutzung des Solar-Mutex in MTs VCLX...-Klasen entstehen, irgendwann mal
1575 // ausgeraeumt sind, sollte hier ein SM_USETHREAD rein, denn die Suche in einem eigenen Thread ist doch etwas fluessiger
1576 // sollte allerdings irgendwie von dem unterliegenden Cursor abhaengig gemacht werden, DAO zum Beispiel ist nicht thread-sicher
1577 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1578 boost::scoped_ptr
<AbstractFmSearchDialog
> pDialog
;
1580 pDialog
.reset(pFact
->CreateFmSearchDialog( &m_pShell
->GetViewShell()->GetViewFrame()->GetWindow(), strInitialText
, aContextNames
, nInitialContext
, LINK( this, FmXFormShell
, OnSearchContextRequest
) ));
1581 DBG_ASSERT( pDialog
, "FmXFormShell::ExecuteSearch: could not create the search dialog!" );
1584 pDialog
->SetActiveField( strActiveField
);
1585 pDialog
->SetFoundHandler( LINK( this, FmXFormShell
, OnFoundData
) );
1586 pDialog
->SetCanceledNotFoundHdl( LINK( this, FmXFormShell
, OnCanceledNotFound
) );
1591 // GridControls wieder restaurieren
1592 LoopGrids(GA_ENABLE_SYNC
| GA_DISABLE_ROCTRLR
);
1594 m_pShell
->GetFormView()->UnMarkAll(m_pShell
->GetFormView()->GetSdrPageView());
1595 // da ich in OnFoundData (fals ich dort war) Controls markiert habe
1599 bool FmXFormShell::GetY2KState(sal_uInt16
& n
)
1601 if ( impl_checkDisposed() )
1604 if (m_pShell
->IsDesignMode())
1605 // im Design-Modus (ohne aktive Controls) soll sich das Haupt-Dokument darum kuemmern
1608 Reference
< XForm
> xForm( getActiveForm());
1610 // kein aktuelles Formular (also insbesondere kein aktuelles Control) -> das Haupt-Dokument soll sich kuemmern
1613 Reference
< XRowSet
> xDB(xForm
, UNO_QUERY
);
1614 DBG_ASSERT(xDB
.is(), "FmXFormShell::GetY2KState : current form has no dbform-interface !");
1616 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats(getConnection(xDB
), false));
1619 Reference
< XPropertySet
> xSet(xSupplier
->getNumberFormatSettings());
1624 Any
aVal( xSet
->getPropertyValue("TwoDigitDateStart") );
1638 void FmXFormShell::SetY2KState(sal_uInt16 n
)
1640 if ( impl_checkDisposed() )
1643 Reference
< XForm
> xActiveForm( getActiveForm());
1644 Reference
< XRowSet
> xActiveRowSet( xActiveForm
, UNO_QUERY
);
1645 if ( xActiveRowSet
.is() )
1647 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats( getConnection( xActiveRowSet
), false ) );
1650 Reference
< XPropertySet
> xSet(xSupplier
->getNumberFormatSettings());
1657 xSet
->setPropertyValue("TwoDigitDateStart", aVal
);
1661 OSL_FAIL("FmXFormShell::SetY2KState: Exception occurred!");
1669 // kein aktives Formular gefunden -> alle aktuell vorhandenen Formulare durchiterieren
1670 Reference
< XIndexAccess
> xCurrentForms( m_xForms
);
1671 if (!xCurrentForms
.is())
1672 { // im alive-Modus sind meine Forms nicht gesetzt, wohl aber die an der Page
1673 if (m_pShell
->GetCurPage())
1674 xCurrentForms
= Reference
< XIndexAccess
>( m_pShell
->GetCurPage()->GetForms( false ), UNO_QUERY
);
1676 if (!xCurrentForms
.is())
1679 ::comphelper::IndexAccessIterator
aIter(xCurrentForms
);
1680 Reference
< XInterface
> xCurrentElement( aIter
.Next());
1681 while (xCurrentElement
.is())
1683 // ist das aktuelle Element eine DatabaseForm ?
1684 Reference
< XRowSet
> xElementAsRowSet( xCurrentElement
, UNO_QUERY
);
1685 if ( xElementAsRowSet
.is() )
1687 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats( getConnection( xElementAsRowSet
), false ) );
1688 if (!xSupplier
.is())
1691 Reference
< XPropertySet
> xSet(xSupplier
->getNumberFormatSettings());
1698 xSet
->setPropertyValue("TwoDigitDateStart", aVal
);
1702 OSL_FAIL("FmXFormShell::SetY2KState: Exception occurred!");
1707 xCurrentElement
= aIter
.Next();
1712 void FmXFormShell::CloseExternalFormViewer()
1714 if ( impl_checkDisposed() )
1717 if (!m_xExternalViewController
.is())
1720 Reference
< ::com::sun::star::frame::XFrame
> xExternalViewFrame( m_xExternalViewController
->getFrame());
1721 Reference
< ::com::sun::star::frame::XDispatchProvider
> xCommLink(xExternalViewFrame
, UNO_QUERY
);
1722 if (!xCommLink
.is())
1725 xExternalViewFrame
->setComponent(NULL
,NULL
);
1726 ::comphelper::disposeComponent(xExternalViewFrame
);
1727 m_xExternalViewController
= NULL
;
1728 m_xExtViewTriggerController
= NULL
;
1729 m_xExternalDisplayedForm
= NULL
;
1733 Reference
< XResultSet
> FmXFormShell::getInternalForm(const Reference
< XResultSet
>& _xForm
) const
1735 if ( impl_checkDisposed() )
1738 Reference
< runtime::XFormController
> xExternalCtrlr(m_xExternalViewController
, UNO_QUERY
);
1739 if (xExternalCtrlr
.is() && (_xForm
== xExternalCtrlr
->getModel()))
1741 DBG_ASSERT(m_xExternalDisplayedForm
.is(), "FmXFormShell::getInternalForm : invalid external form !");
1742 return m_xExternalDisplayedForm
;
1748 Reference
< XForm
> FmXFormShell::getInternalForm(const Reference
< XForm
>& _xForm
) const
1750 if ( impl_checkDisposed() )
1753 Reference
< runtime::XFormController
> xExternalCtrlr(m_xExternalViewController
, UNO_QUERY
);
1754 if (xExternalCtrlr
.is() && (_xForm
== xExternalCtrlr
->getModel()))
1756 DBG_ASSERT(m_xExternalDisplayedForm
.is(), "FmXFormShell::getInternalForm : invalid external form !");
1757 return Reference
< XForm
>(m_xExternalDisplayedForm
, UNO_QUERY
);
1765 static bool lcl_isNavigationRelevant( sal_Int32 _nWhich
)
1767 return ( _nWhich
== SID_FM_RECORD_FIRST
)
1768 || ( _nWhich
== SID_FM_RECORD_PREV
)
1769 || ( _nWhich
== SID_FM_RECORD_NEXT
)
1770 || ( _nWhich
== SID_FM_RECORD_LAST
)
1771 || ( _nWhich
== SID_FM_RECORD_NEW
);
1776 bool FmXFormShell::IsFormSlotEnabled( sal_Int32 _nSlot
, FeatureState
* _pCompleteState
)
1778 const svx::ControllerFeatures
& rController
=
1779 lcl_isNavigationRelevant( _nSlot
)
1780 ? getNavControllerFeatures()
1781 : getActiveControllerFeatures();
1783 if ( !_pCompleteState
)
1784 return rController
->isEnabled( _nSlot
);
1786 rController
->getState( _nSlot
, *_pCompleteState
);
1787 return _pCompleteState
->Enabled
;
1791 void FmXFormShell::ExecuteFormSlot( sal_Int32 _nSlot
)
1793 const svx::ControllerFeatures
& rController
=
1794 lcl_isNavigationRelevant( _nSlot
)
1795 ? getNavControllerFeatures()
1796 : getActiveControllerFeatures();
1798 rController
->execute( _nSlot
);
1800 if ( _nSlot
== SID_FM_RECORD_UNDO
)
1802 // if we're doing an UNDO, *and* if the affected form is the form which we also display
1803 // as external view, then we need to reset the controls of the external form, too
1804 if ( getInternalForm( getActiveForm() ) == m_xExternalDisplayedForm
)
1806 Reference
< XIndexAccess
> xContainer( m_xExternalDisplayedForm
, UNO_QUERY
);
1807 if ( xContainer
.is() )
1809 Reference
< XReset
> xReset
;
1810 for ( sal_Int32 i
= 0; i
< xContainer
->getCount(); ++i
)
1812 if ( ( xContainer
->getByIndex( i
) >>= xReset
) && xReset
.is() )
1814 // no resets on sub forms
1815 Reference
< XForm
> xAsForm( xReset
, UNO_QUERY
);
1816 if ( !xAsForm
.is() )
1826 void FmXFormShell::impl_switchActiveControllerListening( const bool _bListen
)
1828 Reference
< XComponent
> xComp( m_xActiveController
, UNO_QUERY
);
1833 xComp
->addEventListener( (XFormControllerListener
*)this );
1835 xComp
->removeEventListener( (XFormControllerListener
*)this );
1839 void FmXFormShell::setActiveController( const Reference
< runtime::XFormController
>& xController
, bool _bNoSaveOldContent
)
1841 if ( impl_checkDisposed() )
1844 if (m_bChangingDesignMode
)
1846 DBG_ASSERT(!m_pShell
->IsDesignMode(), "nur im alive mode verwenden");
1848 // Ist die Routine ein zweites Mal gerufen worden,
1849 // dann sollte der Focus nicht mehr umgesetzt werden
1852 m_bSetFocus
= xController
!= m_xActiveController
;
1856 if (xController
!= m_xActiveController
)
1858 ::osl::ClearableMutexGuard
aGuard(m_aAsyncSafety
);
1859 // switch all nav dispatchers belonging to the form of the current nav controller to 'non active'
1860 Reference
< XResultSet
> xNavigationForm
;
1861 if (m_xNavigationController
.is())
1862 xNavigationForm
= Reference
< XResultSet
>(m_xNavigationController
->getModel(), UNO_QUERY
);
1865 m_bInActivate
= true;
1867 // check if the 2 controllers serve different forms
1868 Reference
< XResultSet
> xOldForm
;
1869 if (m_xActiveController
.is())
1870 xOldForm
= Reference
< XResultSet
>(m_xActiveController
->getModel(), UNO_QUERY
);
1871 Reference
< XResultSet
> xNewForm
;
1872 if (xController
.is())
1873 xNewForm
= Reference
< XResultSet
>(xController
->getModel(), UNO_QUERY
);
1874 xOldForm
= getInternalForm(xOldForm
);
1875 xNewForm
= getInternalForm(xNewForm
);
1877 bool bDifferentForm
= ( xOldForm
.get() != xNewForm
.get() );
1878 bool bNeedSave
= bDifferentForm
&& !_bNoSaveOldContent
;
1879 // we save the content of the old form if we move to a new form, and saving old content is allowed
1881 if ( m_xActiveController
.is() && bNeedSave
)
1883 // beim Wechsel des Controllers den Inhalt speichern, ein Commit
1884 // wurde bereits ausgefuehrt
1885 if ( m_aActiveControllerFeatures
->commitCurrentControl() )
1888 if ( m_aActiveControllerFeatures
->isModifiedRow() )
1890 bool bIsNew
= m_aActiveControllerFeatures
->isInsertionRow();
1891 bool bResult
= m_aActiveControllerFeatures
->commitCurrentRecord();
1892 if ( !bResult
&& m_bSetFocus
)
1894 // if we couldn't save the current record, set the focus back to the
1896 Reference
< XWindow
> xWindow( m_xActiveController
->getCurrentControl(), UNO_QUERY
);
1898 xWindow
->setFocus();
1899 m_bInActivate
= false;
1902 else if ( bResult
&& bIsNew
)
1904 Reference
< XResultSet
> xCursor( m_aActiveControllerFeatures
->getCursor().get() );
1907 DO_SAFE( xCursor
->last(); );
1916 impl_switchActiveControllerListening( false );
1918 m_aActiveControllerFeatures
.dispose();
1919 m_xActiveController
= xController
;
1920 if ( m_xActiveController
.is() )
1921 m_aActiveControllerFeatures
.assign( m_xActiveController
);
1923 impl_switchActiveControllerListening( true );
1925 if ( m_xActiveController
.is() )
1926 m_xActiveForm
= getInternalForm( Reference
< XForm
>( m_xActiveController
->getModel(), UNO_QUERY
) );
1928 m_xActiveForm
= NULL
;
1932 // activate all dispatchers belonging to form of the new navigation controller
1933 xNavigationForm
= NULL
;
1934 if (m_xNavigationController
.is())
1935 xNavigationForm
= Reference
< XResultSet
>(m_xNavigationController
->getModel(), UNO_QUERY
);
1937 m_bInActivate
= false;
1939 m_pShell
->UIFeatureChanged();
1940 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
1942 InvalidateSlot(SID_FM_FILTER_NAVIGATOR_CONTROL
, true);
1947 void FmXFormShell::getCurrentSelection( InterfaceBag
& /* [out] */ _rSelection
) const
1949 _rSelection
= m_aCurrentSelection
;
1953 bool FmXFormShell::setCurrentSelectionFromMark( const SdrMarkList
& _rMarkList
)
1955 m_aLastKnownMarkedControls
.clear();
1957 if ( ( _rMarkList
.GetMarkCount() > 0 ) && isControlList( _rMarkList
) )
1958 collectInterfacesFromMarkList( _rMarkList
, m_aLastKnownMarkedControls
);
1960 return setCurrentSelection( m_aLastKnownMarkedControls
);
1964 bool FmXFormShell::selectLastMarkedControls()
1966 return setCurrentSelection( m_aLastKnownMarkedControls
);
1970 bool FmXFormShell::setCurrentSelection( const InterfaceBag
& _rSelection
)
1972 if ( impl_checkDisposed() )
1975 DBG_ASSERT( m_pShell
->IsDesignMode(), "FmXFormShell::setCurrentSelection: only to be used in design mode!" );
1977 if ( _rSelection
.empty() && m_aCurrentSelection
.empty() )
1981 if ( _rSelection
.size() == m_aCurrentSelection
.size() )
1983 InterfaceBag::const_iterator aNew
= _rSelection
.begin();
1984 InterfaceBag::const_iterator aOld
= m_aCurrentSelection
.begin();
1985 for ( ; aNew
!= _rSelection
.end(); ++aNew
, ++aOld
)
1987 OSL_ENSURE( Reference
< XInterface
>( *aNew
, UNO_QUERY
).get() == aNew
->get(), "FmXFormShell::setCurrentSelection: new interface not normalized!" );
1988 OSL_ENSURE( Reference
< XInterface
>( *aOld
, UNO_QUERY
).get() == aOld
->get(), "FmXFormShell::setCurrentSelection: old interface not normalized!" );
1990 if ( aNew
->get() != aOld
->get() )
1994 if ( aNew
== _rSelection
.end() )
1999 // the following is some strange code to ensure that when you have two grid controls in a document,
2000 // only one of them can have a selected column.
2001 // TODO: this should happen elsewhere, but not here - shouldn't it?
2002 if ( !m_aCurrentSelection
.empty() )
2004 Reference
< XChild
> xCur
; if ( m_aCurrentSelection
.size() == 1 ) xCur
.set(*m_aCurrentSelection
.begin(), css::uno::UNO_QUERY
);
2005 Reference
< XChild
> xNew
; if ( _rSelection
.size() == 1 ) xNew
.set(*_rSelection
.begin(), css::uno::UNO_QUERY
);
2007 // is there nothing to be selected, or the parents differ, and the parent of the current object
2008 // is a selection supplier, then deselect
2009 if ( xCur
.is() && ( !xNew
.is() || ( xCur
->getParent() != xNew
->getParent() ) ) )
2011 Reference
< XSelectionSupplier
> xSel( xCur
->getParent(), UNO_QUERY
);
2013 xSel
->select( Any() );
2017 m_aCurrentSelection
= _rSelection
;
2019 // determine the form which all the selected objects belong to, if any
2020 Reference
< XForm
> xNewCurrentForm
;
2021 for ( InterfaceBag::const_iterator loop
= m_aCurrentSelection
.begin();
2022 loop
!= m_aCurrentSelection
.end();
2026 Reference
< XForm
> xThisRoundsForm( GetForm( *loop
) );
2027 OSL_ENSURE( xThisRoundsForm
.is(), "FmXFormShell::setCurrentSelection: *everything* should belong to a form!" );
2029 if ( !xNewCurrentForm
.is() )
2030 { // the first form we encounterd
2031 xNewCurrentForm
= xThisRoundsForm
;
2033 else if ( xNewCurrentForm
!= xThisRoundsForm
)
2034 { // different forms -> no "current form" at all
2035 xNewCurrentForm
.clear();
2040 if ( !m_aCurrentSelection
.empty() )
2041 impl_updateCurrentForm( xNewCurrentForm
);
2043 // ensure some slots are updated
2044 for ( size_t i
= 0; i
< sizeof( SelObjectSlotMap
) / sizeof( SelObjectSlotMap
[0] ); ++i
)
2045 InvalidateSlot( SelObjectSlotMap
[i
], false);
2051 bool FmXFormShell::isSolelySelected( const Reference
< XInterface
>& _rxObject
)
2053 return ( m_aCurrentSelection
.size() == 1 ) && ( *m_aCurrentSelection
.begin() == _rxObject
);
2057 void FmXFormShell::forgetCurrentForm()
2059 if ( !m_xCurrentForm
.is() )
2063 impl_updateCurrentForm( NULL
);
2065 // ... and try finding a new current form
2066 // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
2067 impl_defaultCurrentForm_nothrow();
2071 void FmXFormShell::impl_updateCurrentForm( const Reference
< XForm
>& _rxNewCurForm
)
2073 if ( impl_checkDisposed() )
2076 m_xCurrentForm
= _rxNewCurForm
;
2078 // propagate to the FormPage(Impl)
2079 FmFormPage
* pPage
= m_pShell
->GetCurPage();
2081 pPage
->GetImpl().setCurForm( m_xCurrentForm
);
2083 // ensure the UI which depends on the current form is up-to-date
2084 for ( size_t i
= 0; i
< sizeof( DlgSlotMap
) / sizeof( DlgSlotMap
[0] ); ++i
)
2085 InvalidateSlot( DlgSlotMap
[i
], false );
2089 void FmXFormShell::startListening()
2091 if ( impl_checkDisposed() )
2094 Reference
< XRowSet
> xDatabaseForm(m_xActiveForm
, UNO_QUERY
);
2095 if (xDatabaseForm
.is() && getConnection(xDatabaseForm
).is())
2097 Reference
< XPropertySet
> xActiveFormSet(m_xActiveForm
, UNO_QUERY
);
2098 if (xActiveFormSet
.is())
2100 // wenn es eine Datenquelle gibt, dann den Listener aufbauen
2101 // TODO: this is strange - shouldn't this depend on a isLoaded instead of
2102 // a "has command value"? Finally, the command value only means that it was
2103 // intended to be loaded, not that it actually *is* loaded
2104 OUString aSource
= ::comphelper::getString(xActiveFormSet
->getPropertyValue(FM_PROP_COMMAND
));
2105 if (!aSource
.isEmpty())
2107 m_bDatabaseBar
= true;
2109 xActiveFormSet
->getPropertyValue(FM_PROP_NAVIGATION
) >>= m_eNavigate
;
2111 switch (m_eNavigate
)
2113 case NavigationBarMode_PARENT
:
2115 // suchen des Controllers, ueber den eine Navigation moeglich ist
2116 Reference
< XChild
> xChild(m_xActiveController
, UNO_QUERY
);
2117 Reference
< runtime::XFormController
> xParent
;
2120 xChild
= Reference
< XChild
>(xChild
->getParent(), UNO_QUERY
);
2121 xParent
= Reference
< runtime::XFormController
>(xChild
, UNO_QUERY
);
2122 Reference
< XPropertySet
> xParentSet
;
2124 xParentSet
= Reference
< XPropertySet
>(xParent
->getModel(), UNO_QUERY
);
2125 if (xParentSet
.is())
2127 xParentSet
->getPropertyValue(FM_PROP_NAVIGATION
) >>= m_eNavigate
;
2128 if (m_eNavigate
== NavigationBarMode_CURRENT
)
2132 m_xNavigationController
= xParent
;
2136 case NavigationBarMode_CURRENT
:
2137 m_xNavigationController
= m_xActiveController
;
2141 m_xNavigationController
= NULL
;
2142 m_bDatabaseBar
= false;
2145 m_aNavControllerFeatures
.dispose();
2146 if ( m_xNavigationController
.is() && ( m_xNavigationController
!= m_xActiveController
) )
2147 m_aNavControllerFeatures
.assign( m_xNavigationController
);
2149 // an dem Controller, der die Navigation regelt, wg. RecordCount lauschen
2150 Reference
< XPropertySet
> xNavigationSet
;
2151 if (m_xNavigationController
.is())
2153 xNavigationSet
= Reference
< XPropertySet
>(m_xNavigationController
->getModel(), UNO_QUERY
);
2154 if (xNavigationSet
.is())
2155 xNavigationSet
->addPropertyChangeListener(FM_PROP_ROWCOUNT
,this);
2162 m_eNavigate
= NavigationBarMode_NONE
;
2163 m_bDatabaseBar
= false;
2164 m_xNavigationController
= NULL
;
2168 void FmXFormShell::stopListening()
2170 if ( impl_checkDisposed() )
2173 Reference
< XRowSet
> xDatabaseForm(m_xActiveForm
, UNO_QUERY
);
2174 if ( xDatabaseForm
.is() )
2176 if (m_xNavigationController
.is())
2178 Reference
< XPropertySet
> xSet(m_xNavigationController
->getModel(), UNO_QUERY
);
2180 xSet
->removePropertyChangeListener(FM_PROP_ROWCOUNT
, this);
2185 m_bDatabaseBar
= false;
2186 m_eNavigate
= NavigationBarMode_NONE
;
2187 m_xNavigationController
= NULL
;
2191 void FmXFormShell::ShowSelectionProperties( bool bShow
)
2193 if ( impl_checkDisposed() )
2196 // if the window is already visible, only update the state
2197 bool bHasChild
= m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_PROPERTIES
);
2198 if ( bHasChild
&& bShow
)
2199 UpdateSlot( SID_FM_PROPERTY_CONTROL
);
2201 // else toggle state
2203 m_pShell
->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES
);
2205 InvalidateSlot( SID_FM_PROPERTIES
, false );
2206 InvalidateSlot( SID_FM_CTL_PROPERTIES
, false );
2210 IMPL_LINK(FmXFormShell
, OnFoundData
, FmFoundRecordInformation
*, pfriWhere
)
2212 if ( impl_checkDisposed() )
2215 DBG_ASSERT((pfriWhere
->nContext
>= 0) && (pfriWhere
->nContext
< (sal_Int16
)m_aSearchForms
.size()),
2216 "FmXFormShell::OnFoundData : ungueltiger Kontext !");
2217 Reference
< XForm
> xForm( m_aSearchForms
.at(pfriWhere
->nContext
));
2218 DBG_ASSERT(xForm
.is(), "FmXFormShell::OnFoundData : ungueltige Form !");
2220 Reference
< XRowLocate
> xCursor(xForm
, UNO_QUERY
);
2222 return 0; // was soll ich da machen ?
2227 xCursor
->moveToBookmark(pfriWhere
->aPosition
);
2229 catch(const SQLException
&)
2231 OSL_FAIL("Can position on bookmark!");
2234 LoopGrids(GA_FORCE_SYNC
);
2236 // und zum Feld (dazu habe ich vor dem Start des Suchens die XVclComponent-Interfaces eingesammelt)
2237 SAL_WARN_IF(static_cast<size_t>(pfriWhere
->nFieldPos
) >=
2238 m_arrSearchedControls
.size(),
2239 "svx.form", "FmXFormShell::OnFoundData : invalid index!");
2240 SdrObject
* pObject
= m_arrSearchedControls
.at(pfriWhere
->nFieldPos
);
2242 m_pShell
->GetFormView()->UnMarkAll(m_pShell
->GetFormView()->GetSdrPageView());
2243 m_pShell
->GetFormView()->MarkObj(pObject
, m_pShell
->GetFormView()->GetSdrPageView());
2245 FmFormObj
* pFormObject
= FmFormObj::GetFormObject( pObject
);
2246 Reference
< XControlModel
> xControlModel( pFormObject
? pFormObject
->GetUnoControlModel() : Reference
< XControlModel
>() );
2247 DBG_ASSERT( xControlModel
.is(), "FmXFormShell::OnFoundData: invalid control!" );
2248 if ( !xControlModel
.is() )
2251 // disable the permanent cursor for the last grid we found a record
2252 if (m_xLastGridFound
.is() && (m_xLastGridFound
!= xControlModel
))
2254 Reference
< XPropertySet
> xOldSet(m_xLastGridFound
, UNO_QUERY
);
2255 xOldSet
->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR
, makeAny( false ) );
2256 Reference
< XPropertyState
> xOldSetState(xOldSet
, UNO_QUERY
);
2257 if (xOldSetState
.is())
2258 xOldSetState
->setPropertyToDefault(FM_PROP_CURSORCOLOR
);
2260 xOldSet
->setPropertyValue(FM_PROP_CURSORCOLOR
, Any());
2263 // wenn das Feld sich in einem GridControl befindet, muss ich dort noch in die entsprechende Spalte gehen
2264 sal_Int32 nGridColumn
= m_arrRelativeGridColumn
[pfriWhere
->nFieldPos
];
2265 if (nGridColumn
!= -1)
2266 { // dummer weise muss ich mir das Control erst wieder besorgen
2267 Reference
<XControl
> xControl( pFormObject
? impl_getControl( xControlModel
, *pFormObject
) : Reference
< XControl
>() );
2268 Reference
< XGrid
> xGrid(xControl
, UNO_QUERY
);
2269 DBG_ASSERT(xGrid
.is(), "FmXFormShell::OnFoundData : ungueltiges Control !");
2270 // wenn eine der Asserts anschlaegt, habe ich beim Aufbauen von m_arrSearchedControls wohl was falsch gemacht
2272 // enable a permanent cursor for the grid so we can see the found text
2273 Reference
< XPropertySet
> xModelSet(xControlModel
, UNO_QUERY
);
2274 DBG_ASSERT(xModelSet
.is(), "FmXFormShell::OnFoundData : invalid control model (no property set) !");
2275 xModelSet
->setPropertyValue( FM_PROP_ALWAYSSHOWCURSOR
, makeAny( true ) );
2276 xModelSet
->setPropertyValue( FM_PROP_CURSORCOLOR
, makeAny( sal_Int32( COL_LIGHTRED
) ) );
2277 m_xLastGridFound
= xControlModel
;
2280 xGrid
->setCurrentColumnPosition((sal_Int16
)nGridColumn
);
2283 // als der Cursor neu positioniert wurde, habe ich (in positioned) meine Formularleisten-Slots invalidiert, aber das greift
2284 // hier dummerweise nicht, da i.A. ja der (modale) Suchdialog oben ist ... also Gewalt ...
2285 sal_uInt16 nPos
= 0;
2286 while (DatabaseSlotMap
[nPos
])
2287 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Update(DatabaseSlotMap
[nPos
++]);
2288 // leider geht das Update im Gegensatz zum Invalidate nur mit einzelnen Slots)
2294 IMPL_LINK(FmXFormShell
, OnCanceledNotFound
, FmFoundRecordInformation
*, pfriWhere
)
2296 if ( impl_checkDisposed() )
2299 DBG_ASSERT((pfriWhere
->nContext
>= 0) && (pfriWhere
->nContext
< (sal_Int16
)m_aSearchForms
.size()),
2300 "FmXFormShell::OnCanceledNotFound : ungueltiger Kontext !");
2301 Reference
< XForm
> xForm( m_aSearchForms
.at(pfriWhere
->nContext
));
2302 DBG_ASSERT(xForm
.is(), "FmXFormShell::OnCanceledNotFound : ungueltige Form !");
2304 Reference
< XRowLocate
> xCursor(xForm
, UNO_QUERY
);
2306 return 0; // was soll ich da machen ?
2311 xCursor
->moveToBookmark(pfriWhere
->aPosition
);
2313 catch(const SQLException
&)
2315 OSL_FAIL("Can position on bookmark!");
2319 m_pShell
->GetFormView()->UnMarkAll(m_pShell
->GetFormView()->GetSdrPageView());
2324 IMPL_LINK(FmXFormShell
, OnSearchContextRequest
, FmSearchContext
*, pfmscContextInfo
)
2326 if ( impl_checkDisposed() )
2329 DBG_ASSERT(pfmscContextInfo
->nContext
< (sal_Int16
)m_aSearchForms
.size(), "FmXFormShell::OnSearchContextRequest : invalid parameter !");
2330 Reference
< XForm
> xForm( m_aSearchForms
.at(pfmscContextInfo
->nContext
));
2331 DBG_ASSERT(xForm
.is(), "FmXFormShell::OnSearchContextRequest : unexpected : invalid context !");
2333 Reference
< XResultSet
> xIter(xForm
, UNO_QUERY
);
2334 DBG_ASSERT(xIter
.is(), "FmXFormShell::OnSearchContextRequest : unexpected : context has no iterator !");
2337 // assemble the list of fields to involve (that is, the ControlSources of all fields that have such a property)
2338 OUString strFieldList
, sFieldDisplayNames
;
2339 m_arrSearchedControls
.clear();
2340 m_arrRelativeGridColumn
.clear();
2342 // small problem: To mark found fields, I need SdrObjects. To determine which controls
2343 // to include in the search, I need Controls (that is, XControl interfaces). So I have
2344 // to iterate over one of them and get the other in some way. Unfortunately, there is
2345 // no direct connexion between the two worlds (except from a GetUnoControl to a
2346 // SdrUnoObject, but this requires an OutputDevice I can not do anything with.
2347 // However I can get to the Model from the Control and also from the SdrObject, and in
2348 // this way the assignment SdrObject<->Control is possible with a double loop.
2349 // The alternative to this (ugly but certainly not entirely fixable) solution would be
2350 // to renounce the caching of the SdrObjects, which would lead to significant extra
2351 // work in OnFoundData (since there I'd have to get the SdrObject first thing every
2352 // time). But since OnFoundData is usually called more often than ExecuteSeearch, I'll
2355 Reference
< XNameAccess
> xValidFormFields
;
2356 Reference
< XColumnsSupplier
> xSupplyCols(xIter
, UNO_QUERY
);
2357 DBG_ASSERT(xSupplyCols
.is(), "FmXFormShell::OnSearchContextRequest : invalid cursor : no columns supplier !");
2358 if (xSupplyCols
.is())
2359 xValidFormFields
= xSupplyCols
->getColumns();
2360 DBG_ASSERT(xValidFormFields
.is(), "FmXFormShell::OnSearchContextRequest : form has no fields !");
2362 // current Page/Controller
2363 FmFormPage
* pCurrentPage
= m_pShell
->GetCurPage();
2364 assert(pCurrentPage
&& "FmXFormShell::OnSearchContextRequest : no page !");
2365 // Search all SdrControls of this page...
2366 OUString sControlSource
, aName
;
2368 SdrObjListIter
aPageIter( *pCurrentPage
);
2369 while ( aPageIter
.IsMore() )
2371 SdrObject
* pCurrent
= aPageIter
.Next();
2372 FmFormObj
* pFormObject
= FmFormObj::GetFormObject( pCurrent
);
2373 // note that in case pCurrent is a virtual object, pFormObject points to the referenced object
2378 // the current object's model, in different tastes
2379 Reference
< XControlModel
> xControlModel( pFormObject
->GetUnoControlModel() );
2380 Reference
< XFormComponent
> xCurrentFormComponent( xControlModel
, UNO_QUERY
);
2381 DBG_ASSERT( xCurrentFormComponent
.is(), "FmXFormShell::OnSearchContextRequest: invalid objects!" );
2382 if ( !xCurrentFormComponent
.is() )
2385 // does the component belong to the form which we're interested in?
2386 if ( xCurrentFormComponent
->getParent() != xForm
)
2389 // ... ask for the ControlSource property
2390 SearchableControlIterator
iter( xCurrentFormComponent
);
2391 Reference
< XControl
> xControl
;
2392 // the control that has model xControlModel
2393 // (the following while can be passed through several times, without the Control
2394 // being modified, so I don't have to search every time from scratch)
2396 Reference
< XInterface
> xSearchable( iter
.Next() );
2397 while ( xSearchable
.is() )
2399 sControlSource
= iter
.getCurrentValue();
2400 if ( sControlSource
.isEmpty() )
2402 // the current element has no ControlSource, so it is a GridControl (that
2403 // is the only thing that still permits the SearchableControlIteratore)
2404 xControl
= impl_getControl( xControlModel
, *pFormObject
);
2405 DBG_ASSERT(xControl
.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
2407 Reference
< XGridPeer
> xGridPeer
;
2408 if ( xControl
.is() )
2409 xGridPeer
.set( xControl
->getPeer(), UNO_QUERY
);
2412 if (!xGridPeer
.is())
2415 Reference
< XIndexAccess
> xPeerContainer(xGridPeer
, UNO_QUERY
);
2416 if (!xPeerContainer
.is())
2419 Reference
< XIndexAccess
> xModelColumns(xGridPeer
->getColumns(), UNO_QUERY
);
2420 DBG_ASSERT(xModelColumns
.is(), "FmXFormShell::OnSearchContextRequest : there is a grid control without columns !");
2421 // the case 'no columns' should be indicated with an empty container, I think ...
2422 DBG_ASSERT(xModelColumns
->getCount() >= xPeerContainer
->getCount(), "FmXFormShell::OnSearchContextRequest : impossible : have more view than model columns !");
2424 Reference
< XInterface
> xCurrentColumn
;
2425 for (sal_Int16 nViewPos
=0; nViewPos
<xPeerContainer
->getCount(); ++nViewPos
)
2427 xPeerContainer
->getByIndex(nViewPos
) >>= xCurrentColumn
;
2428 if (!xCurrentColumn
.is())
2431 // can we use this column control for searching ?
2432 if (!IsSearchableControl(xCurrentColumn
))
2435 sal_Int16 nModelPos
= GridView2ModelPos(xModelColumns
, nViewPos
);
2436 Reference
< XPropertySet
> xCurrentColModel
;
2437 xModelColumns
->getByIndex(nModelPos
) >>= xCurrentColModel
;
2438 aName
= ::comphelper::getString(xCurrentColModel
->getPropertyValue(FM_PROP_CONTROLSOURCE
));
2439 // the cursor has a field matching the control source ?
2440 if (xValidFormFields
->hasByName(aName
))
2442 strFieldList
= strFieldList
+ OUString(aName
.getStr()) + ";";
2444 sFieldDisplayNames
= sFieldDisplayNames
+
2445 OUString(::comphelper::getString(xCurrentColModel
->getPropertyValue(FM_PROP_LABEL
)).getStr()) +
2448 pfmscContextInfo
->arrFields
.push_back(xCurrentColumn
);
2450 // and the SdrOject to the Field
2451 m_arrSearchedControls
.push_back(pCurrent
);
2452 // the number of the column
2453 m_arrRelativeGridColumn
.push_back(nViewPos
);
2460 if (!sControlSource
.isEmpty() && xValidFormFields
->hasByName(sControlSource
))
2462 // now I need the Control to SdrObject
2465 xControl
= impl_getControl( xControlModel
, *pFormObject
);
2466 DBG_ASSERT(xControl
.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
2469 if (IsSearchableControl(xControl
))
2471 // all tests passed -> take along in the list
2472 strFieldList
= strFieldList
+ OUString(sControlSource
.getStr()) + ";";
2474 // the label which should appear for the control :
2475 sFieldDisplayNames
= sFieldDisplayNames
+
2476 OUString(getLabelName(Reference
< XPropertySet
>(xControlModel
, UNO_QUERY
)).getStr()) +
2479 // mark the SdrObject (accelerates the treatment in OnFoundData)
2480 m_arrSearchedControls
.push_back(pCurrent
);
2482 // the number of the column (here a dummy, since it is only interesting for GridControls)
2483 m_arrRelativeGridColumn
.push_back(-1);
2485 // and for the formatted search...
2486 pfmscContextInfo
->arrFields
.push_back(Reference
<XInterface
>( xControl
, UNO_QUERY
));
2491 xSearchable
= iter
.Next();
2495 strFieldList
= comphelper::string::stripEnd(strFieldList
, ';');
2496 sFieldDisplayNames
= comphelper::string::stripEnd(sFieldDisplayNames
, ';');
2498 if (pfmscContextInfo
->arrFields
.empty())
2500 pfmscContextInfo
->arrFields
.clear();
2501 pfmscContextInfo
->xCursor
= NULL
;
2502 pfmscContextInfo
->strUsedFields
.clear();
2506 pfmscContextInfo
->xCursor
= xIter
;
2507 pfmscContextInfo
->strUsedFields
= strFieldList
;
2508 pfmscContextInfo
->sFieldDisplayNames
= sFieldDisplayNames
;
2510 // 66463 - 31.05.99 - FS
2511 // when the cursor is a non-STANDARD RecordMode, set it back
2512 Reference
< XPropertySet
> xCursorSet(pfmscContextInfo
->xCursor
, UNO_QUERY
);
2513 Reference
< XResultSetUpdate
> xUpdateCursor(pfmscContextInfo
->xCursor
, UNO_QUERY
);
2514 if (xUpdateCursor
.is() && xCursorSet
.is())
2516 if (::comphelper::getBOOL(xCursorSet
->getPropertyValue(FM_PROP_ISNEW
)))
2517 xUpdateCursor
->moveToCurrentRow();
2518 else if (::comphelper::getBOOL(xCursorSet
->getPropertyValue(FM_PROP_ISMODIFIED
)))
2519 xUpdateCursor
->cancelRowUpdates();
2522 return pfmscContextInfo
->arrFields
.size();
2525 // XContainerListener
2527 void FmXFormShell::elementInserted(const ContainerEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
2529 if ( impl_checkDisposed() )
2532 // new object to listen to
2533 Reference
< XInterface
> xTemp
;
2534 evt
.Element
>>= xTemp
;
2538 m_pShell
->DetermineForms(true);
2542 void FmXFormShell::elementReplaced(const ContainerEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
2544 if ( impl_checkDisposed() )
2547 Reference
< XInterface
> xTemp
;
2548 evt
.ReplacedElement
>>= xTemp
;
2549 RemoveElement(xTemp
);
2550 evt
.Element
>>= xTemp
;
2555 void FmXFormShell::elementRemoved(const ContainerEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
2557 if ( impl_checkDisposed() )
2560 Reference
< XInterface
> xTemp
;
2561 evt
.Element
>>= xTemp
;
2562 RemoveElement(xTemp
);
2565 m_pShell
->DetermineForms(true);
2569 void FmXFormShell::UpdateForms( bool _bInvalidate
)
2571 if ( impl_checkDisposed() )
2574 Reference
< XIndexAccess
> xForms
;
2576 FmFormPage
* pPage
= m_pShell
->GetCurPage();
2579 if ( m_pShell
->m_bDesignMode
)
2580 xForms
.set(pPage
->GetForms( false ), css::uno::UNO_QUERY
);
2583 if ( m_xForms
!= xForms
)
2585 RemoveElement( m_xForms
);
2587 AddElement( m_xForms
);
2591 m_pShell
->DetermineForms( _bInvalidate
);
2595 void FmXFormShell::AddElement(const Reference
< XInterface
>& _xElement
)
2597 if ( impl_checkDisposed() )
2599 impl_AddElement_nothrow(_xElement
);
2602 void FmXFormShell::impl_AddElement_nothrow(const Reference
< XInterface
>& Element
)
2604 // am Container horchen
2605 const Reference
< XIndexContainer
> xContainer(Element
, UNO_QUERY
);
2606 if (xContainer
.is())
2608 const sal_uInt32 nCount
= xContainer
->getCount();
2609 Reference
< XInterface
> xElement
;
2610 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
2612 xElement
.set(xContainer
->getByIndex(i
),UNO_QUERY
);
2613 impl_AddElement_nothrow(xElement
);
2616 const Reference
< XContainer
> xCont(Element
, UNO_QUERY
);
2618 xCont
->addContainerListener(this);
2621 const Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(Element
, UNO_QUERY
);
2622 if (xSelSupplier
.is())
2623 xSelSupplier
->addSelectionChangeListener(this);
2627 void FmXFormShell::RemoveElement(const Reference
< XInterface
>& Element
)
2629 if ( impl_checkDisposed() )
2631 impl_RemoveElement_nothrow(Element
);
2634 void FmXFormShell::impl_RemoveElement_nothrow(const Reference
< XInterface
>& Element
)
2636 const Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(Element
, UNO_QUERY
);
2637 if (xSelSupplier
.is())
2638 xSelSupplier
->removeSelectionChangeListener(this);
2640 // remove connection to children
2641 const Reference
< XIndexContainer
> xContainer(Element
, UNO_QUERY
);
2642 if (xContainer
.is())
2644 const Reference
< XContainer
> xCont(Element
, UNO_QUERY
);
2646 xCont
->removeContainerListener(this);
2648 const sal_uInt32 nCount
= xContainer
->getCount();
2649 Reference
< XInterface
> xElement
;
2650 for (sal_uInt32 i
= 0; i
< nCount
; i
++)
2652 xElement
.set(xContainer
->getByIndex(i
),UNO_QUERY
);
2653 impl_RemoveElement_nothrow(xElement
);
2657 InterfaceBag::iterator wasSelectedPos
= m_aCurrentSelection
.find( Element
);
2658 if ( wasSelectedPos
!= m_aCurrentSelection
.end() )
2659 m_aCurrentSelection
.erase( wasSelectedPos
);
2663 void FmXFormShell::selectionChanged(const lang::EventObject
& rEvent
) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
2665 if ( impl_checkDisposed() )
2668 Reference
< XSelectionSupplier
> xSupplier( rEvent
.Source
, UNO_QUERY
);
2669 Reference
< XInterface
> xSelObj( xSupplier
->getSelection(), UNO_QUERY
);
2670 // a selection was removed, this can only be done by the shell
2671 if ( !xSelObj
.is() )
2674 EnableTrackProperties(false);
2676 bool bMarkChanged
= m_pShell
->GetFormView()->checkUnMarkAll(rEvent
.Source
);
2677 Reference
< XForm
> xNewForm( GetForm( rEvent
.Source
) );
2679 InterfaceBag aNewSelection
;
2680 aNewSelection
.insert( Reference
<XInterface
>( xSelObj
, UNO_QUERY
) );
2682 if ( setCurrentSelection( aNewSelection
) && IsPropBrwOpen() )
2683 ShowSelectionProperties( true );
2685 EnableTrackProperties(true);
2688 m_pShell
->NotifyMarkListChanged( m_pShell
->GetFormView() );
2692 IMPL_LINK_NOARG_TYPED(FmXFormShell
, OnTimeOut
, Timer
*, void)
2694 if ( impl_checkDisposed() )
2697 if (m_pShell
->IsDesignMode() && m_pShell
->GetFormView())
2698 SetSelection(m_pShell
->GetFormView()->GetMarkedObjectList());
2702 void FmXFormShell::SetSelectionDelayed()
2704 if ( impl_checkDisposed() )
2707 if (m_pShell
->IsDesignMode() && IsTrackPropertiesEnabled() && !m_aMarkTimer
.IsActive())
2708 m_aMarkTimer
.Start();
2712 void FmXFormShell::SetSelection(const SdrMarkList
& rMarkList
)
2714 if ( impl_checkDisposed() )
2717 DetermineSelection(rMarkList
);
2718 m_pShell
->NotifyMarkListChanged(m_pShell
->GetFormView());
2722 void FmXFormShell::DetermineSelection(const SdrMarkList
& rMarkList
)
2724 if ( setCurrentSelectionFromMark( rMarkList
) && IsPropBrwOpen() )
2725 ShowSelectionProperties( true );
2729 bool FmXFormShell::IsPropBrwOpen() const
2731 if ( impl_checkDisposed() )
2734 return m_pShell
->GetViewShell() && m_pShell
->GetViewShell()->GetViewFrame()
2735 && m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES
);
2739 class FmXFormShell::SuspendPropertyTracking
2742 FmXFormShell
& m_rShell
;
2746 SuspendPropertyTracking( FmXFormShell
& _rShell
)
2747 :m_rShell( _rShell
)
2748 ,m_bEnabled( false )
2750 if ( m_rShell
.IsTrackPropertiesEnabled() )
2752 m_rShell
.EnableTrackProperties( false );
2757 ~SuspendPropertyTracking( )
2759 if ( m_bEnabled
) // note that ( false != m_bEnabled ) implies ( NULL != m_pShell )
2760 m_rShell
.EnableTrackProperties( true );
2765 void FmXFormShell::SetDesignMode(bool bDesign
)
2767 if ( impl_checkDisposed() )
2770 DBG_ASSERT(m_pShell
->GetFormView(), "FmXFormShell::SetDesignMode : invalid call (have no shell or no view) !");
2771 m_bChangingDesignMode
= true;
2773 // 67506 - 15.07.99 - FS
2774 // if we're switching off the design mode we have to force the property browser to be closed
2775 // so it can commit it's changes _before_ we load the forms
2778 m_bHadPropertyBrowserInDesignMode
= m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES
);
2779 if (m_bHadPropertyBrowserInDesignMode
)
2780 m_pShell
->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES
);
2783 FmFormView
* pFormView
= m_pShell
->GetFormView();
2786 // we are currently filtering, so stop filtering
2788 stopFiltering(false);
2790 // unsubscribe from the objects of my MarkList
2791 pFormView
->GetImpl()->stopMarkListWatching();
2795 m_aMarkTimer
.Stop();
2797 SuspendPropertyTracking
aSuspend( *this );
2798 pFormView
->GetImpl()->saveMarkList( true );
2801 if (bDesign
&& m_xExternalViewController
.is())
2802 CloseExternalFormViewer();
2804 pFormView
->ChangeDesignMode(bDesign
);
2806 // notify listensers
2807 FmDesignModeChangedHint
aChangedHint( bDesign
);
2808 m_pShell
->Broadcast(aChangedHint
);
2810 m_pShell
->m_bDesignMode
= bDesign
;
2811 UpdateForms( false );
2813 m_pTextShell
->designModeChanged( m_pShell
->m_bDesignMode
);
2819 // during changing the mark list, don't track the selected objects in the property browser
2820 SuspendPropertyTracking
aSuspend( *this );
2821 // restore the marks
2822 pFormView
->GetImpl()->restoreMarkList( aList
);
2825 // synchronize with the restored mark list
2826 if ( aList
.GetMarkCount() )
2827 SetSelection( aList
);
2831 // subscribe to the model of the view (so that I'm informed when someone deletes
2832 // during the alive mode controls that I had saved in the saveMarklist (60343)
2833 pFormView
->GetImpl()->startMarkListWatching();
2836 m_pShell
->UIFeatureChanged();
2838 // 67506 - 15.07.99 - FS
2839 if (bDesign
&& m_bHadPropertyBrowserInDesignMode
)
2841 // The UIFeatureChanged performs an update (a check of the available features) asynchronously.
2842 // So we can't call ShowSelectionProperties directly as the according feature isn't enabled yet.
2843 // That's why we use an asynchron execution on the dispatcher.
2844 // (And that's why this has to be done AFTER the UIFeatureChanged.)
2845 m_pShell
->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER
, SfxCallMode::ASYNCHRON
);
2847 m_bChangingDesignMode
= false;
2851 Reference
< XControl
> FmXFormShell::impl_getControl( const Reference
< XControlModel
>& i_rxModel
, const FmFormObj
& i_rKnownFormObj
)
2853 if ( impl_checkDisposed() )
2856 Reference
< XControl
> xControl
;
2859 Reference
< XControlContainer
> xControlContainer( getControlContainerForView(), UNO_SET_THROW
);
2861 Sequence
< Reference
< XControl
> > seqControls( xControlContainer
->getControls() );
2862 const Reference
< XControl
>* pControls
= seqControls
.getArray();
2863 // ... that I can then search
2864 for (sal_Int32 i
=0; i
<seqControls
.getLength(); ++i
)
2866 xControl
.set( pControls
[i
], UNO_SET_THROW
);
2867 Reference
< XControlModel
> xCurrentModel( xControl
->getModel() );
2868 if ( xCurrentModel
== i_rxModel
)
2873 if ( !xControl
.is() )
2875 // fallabck (some controls might not have been created, yet, since they were never visible so far)
2876 Reference
< XControl
> xContainerControl( xControlContainer
, UNO_QUERY_THROW
);
2877 const vcl::Window
* pContainerWindow
= VCLUnoHelper::GetWindow( xContainerControl
->getPeer() );
2878 ENSURE_OR_THROW( pContainerWindow
, "unexpected control container implementation" );
2880 const SdrView
* pSdrView
= m_pShell
? m_pShell
->GetFormView() : NULL
;
2881 ENSURE_OR_THROW( pSdrView
, "no current view" );
2883 xControl
.set( i_rKnownFormObj
.GetUnoControl( *pSdrView
, *pContainerWindow
), UNO_QUERY_THROW
);
2886 catch( const Exception
& )
2888 DBG_UNHANDLED_EXCEPTION();
2891 OSL_ENSURE( xControl
.is(), "FmXFormShell::impl_getControl: no control found!" );
2896 void FmXFormShell::impl_collectFormSearchContexts_nothrow( const Reference
< XInterface
>& _rxStartingPoint
,
2897 const OUString
& _rCurrentLevelPrefix
, FmFormArray
& _out_rForms
, ::std::vector
< OUString
>& _out_rNames
)
2901 Reference
< XIndexAccess
> xContainer( _rxStartingPoint
, UNO_QUERY
);
2902 if ( !xContainer
.is() )
2905 sal_Int32
nCount( xContainer
->getCount() );
2909 OUString sCurrentFormName
;
2910 OUStringBuffer aNextLevelPrefix
;
2911 for ( sal_Int32 i
=0; i
<nCount
; ++i
)
2913 // is the current child a form?
2914 Reference
< XForm
> xCurrentAsForm( xContainer
->getByIndex(i
), UNO_QUERY
);
2915 if ( !xCurrentAsForm
.is() )
2918 Reference
< XNamed
> xNamed( xCurrentAsForm
, UNO_QUERY_THROW
);
2919 sCurrentFormName
= xNamed
->getName();
2921 // the name of the current form
2922 OUStringBuffer
sCompleteCurrentName( sCurrentFormName
);
2923 if ( !_rCurrentLevelPrefix
.isEmpty() )
2925 sCompleteCurrentName
.appendAscii( " (" );
2926 sCompleteCurrentName
.append ( _rCurrentLevelPrefix
);
2927 sCompleteCurrentName
.appendAscii( ")" );
2930 // the prefix for the next level
2931 aNextLevelPrefix
= _rCurrentLevelPrefix
;
2932 if ( !_rCurrentLevelPrefix
.isEmpty() )
2933 aNextLevelPrefix
.append( '/' );
2934 aNextLevelPrefix
.append( sCurrentFormName
);
2936 // remember both the form and it's "display name"
2937 _out_rForms
.push_back( xCurrentAsForm
);
2938 _out_rNames
.push_back( sCompleteCurrentName
.makeStringAndClear() );
2941 impl_collectFormSearchContexts_nothrow( xCurrentAsForm
, aNextLevelPrefix
.makeStringAndClear(), _out_rForms
, _out_rNames
);
2944 catch( const Exception
& )
2946 DBG_UNHANDLED_EXCEPTION();
2951 void FmXFormShell::startFiltering()
2953 if ( impl_checkDisposed() )
2956 // setting all forms in filter mode
2957 FmXFormView
* pXView
= m_pShell
->GetFormView()->GetImpl();
2959 // if the active controller is our external one we have to use the trigger controller
2960 Reference
< XControlContainer
> xContainer
;
2961 if (getActiveController() == m_xExternalViewController
)
2963 DBG_ASSERT(m_xExtViewTriggerController
.is(), "FmXFormShell::startFiltering : inconsistent : active external controller, but no one triggered this !");
2964 xContainer
= m_xExtViewTriggerController
->getContainer();
2967 xContainer
= getActiveController()->getContainer();
2969 PFormViewPageWindowAdapter pAdapter
= pXView
->findWindow( xContainer
);
2970 if ( pAdapter
.is() )
2972 const ::std::vector
< Reference
< runtime::XFormController
> >& rControllerList
= pAdapter
->GetList();
2973 for ( ::std::vector
< Reference
< runtime::XFormController
> >::const_iterator j
= rControllerList
.begin();
2974 j
!= rControllerList
.end();
2978 Reference
< XModeSelector
> xModeSelector(*j
, UNO_QUERY
);
2979 if (xModeSelector
.is())
2980 xModeSelector
->setMode( OUString( "FilterMode" ) );
2984 m_bFilterMode
= true;
2986 m_pShell
->UIFeatureChanged();
2987 SfxViewFrame
* pViewFrame
= m_pShell
->GetViewShell()->GetViewFrame();
2988 pViewFrame
->GetBindings().InvalidateShell( *m_pShell
);
2990 if ( pViewFrame
->KnowsChildWindow( SID_FM_FILTER_NAVIGATOR
)
2991 && !pViewFrame
->HasChildWindow( SID_FM_FILTER_NAVIGATOR
)
2994 pViewFrame
->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR
);
2999 void saveFilter(const Reference
< runtime::XFormController
>& _rxController
)
3001 Reference
< XPropertySet
> xFormAsSet(_rxController
->getModel(), UNO_QUERY
);
3002 Reference
< XPropertySet
> xControllerAsSet(_rxController
, UNO_QUERY
);
3003 Reference
< XIndexAccess
> xControllerAsIndex(_rxController
, UNO_QUERY
);
3005 // call the subcontroller
3006 Reference
< runtime::XFormController
> xController
;
3007 for (sal_Int32 i
= 0, nCount
= xControllerAsIndex
->getCount(); i
< nCount
; ++i
)
3009 xControllerAsIndex
->getByIndex(i
) >>= xController
;
3010 saveFilter(xController
);
3016 xFormAsSet
->setPropertyValue(FM_PROP_FILTER
, xControllerAsSet
->getPropertyValue(FM_PROP_FILTER
));
3017 xFormAsSet
->setPropertyValue(FM_PROP_APPLYFILTER
, makeAny( true ) );
3019 catch (const Exception
& )
3021 DBG_UNHANDLED_EXCEPTION();
3027 void FmXFormShell::stopFiltering(bool bSave
)
3029 if ( impl_checkDisposed() )
3032 m_bFilterMode
= false;
3034 FmXFormView
* pXView
= m_pShell
->GetFormView()->GetImpl();
3036 // if the active controller is our external one we have to use the trigger controller
3037 Reference
< XControlContainer
> xContainer
;
3038 if (getActiveController() == m_xExternalViewController
)
3040 DBG_ASSERT(m_xExtViewTriggerController
.is(), "FmXFormShell::stopFiltering : inconsistent : active external controller, but no one triggered this !");
3041 xContainer
= m_xExtViewTriggerController
->getContainer();
3044 xContainer
= getActiveController()->getContainer();
3046 PFormViewPageWindowAdapter pAdapter
= pXView
->findWindow(xContainer
);
3047 if ( pAdapter
.is() )
3049 const ::std::vector
< Reference
< runtime::XFormController
> >& rControllerList
= pAdapter
->GetList();
3050 ::std::vector
< OUString
> aOriginalFilters
;
3051 ::std::vector
< sal_Bool
> aOriginalApplyFlags
;
3055 for (::std::vector
< Reference
< runtime::XFormController
> > ::const_iterator j
= rControllerList
.begin();
3056 j
!= rControllerList
.end(); ++j
)
3059 { // remember the current filter settings in case we're goin to reload the forms below (which may fail)
3062 Reference
< XPropertySet
> xFormAsSet((*j
)->getModel(), UNO_QUERY
);
3063 aOriginalFilters
.push_back(::comphelper::getString(xFormAsSet
->getPropertyValue(FM_PROP_FILTER
)));
3064 aOriginalApplyFlags
.push_back(::comphelper::getBOOL(xFormAsSet
->getPropertyValue(FM_PROP_APPLYFILTER
)));
3068 OSL_FAIL("FmXFormShell::stopFiltering : could not get the original filter !");
3069 // put dummies into the arrays so the they have the right size
3071 if (aOriginalFilters
.size() == aOriginalApplyFlags
.size())
3072 // the first getPropertyValue failed -> use two dummies
3073 aOriginalFilters
.push_back( OUString() );
3074 aOriginalApplyFlags
.push_back( sal_False
);
3080 for (::std::vector
< Reference
< runtime::XFormController
> > ::const_iterator j
= rControllerList
.begin();
3081 j
!= rControllerList
.end(); ++j
)
3084 Reference
< XModeSelector
> xModeSelector(*j
, UNO_QUERY
);
3085 if (xModeSelector
.is())
3086 xModeSelector
->setMode( OUString( "DataMode" ) );
3088 if (bSave
) // execute the filter
3090 const ::std::vector
< Reference
< runtime::XFormController
> > & rControllers
= pAdapter
->GetList();
3091 for (::std::vector
< Reference
< runtime::XFormController
> > ::const_iterator j
= rControllers
.begin();
3092 j
!= rControllers
.end(); ++j
)
3094 Reference
< XLoadable
> xReload((*j
)->getModel(), UNO_QUERY
);
3097 Reference
< XPropertySet
> xFormSet(xReload
, UNO_QUERY
);
3105 OSL_FAIL("FmXFormShell::stopFiltering: Exception occurred!");
3108 if (!isRowSetAlive(xFormSet
))
3109 { // something went wrong -> restore the original state
3110 OUString sOriginalFilter
= aOriginalFilters
[ j
- rControllers
.begin() ];
3111 bool bOriginalApplyFlag
= aOriginalApplyFlags
[ j
- rControllers
.begin() ];
3114 xFormSet
->setPropertyValue(FM_PROP_FILTER
, makeAny(sOriginalFilter
));
3115 xFormSet
->setPropertyValue(FM_PROP_APPLYFILTER
, makeAny(bOriginalApplyFlag
));
3118 catch(const Exception
&)
3120 DBG_UNHANDLED_EXCEPTION();
3127 m_pShell
->UIFeatureChanged();
3128 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
3132 void FmXFormShell::CreateExternalView()
3134 if ( impl_checkDisposed() )
3137 DBG_ASSERT(m_xAttachedFrame
.is(), "FmXFormShell::CreateExternalView : no frame !");
3139 // the frame the external view is displayed in
3140 bool bAlreadyExistent
= m_xExternalViewController
.is();
3141 Reference
< ::com::sun::star::frame::XFrame
> xExternalViewFrame
;
3142 OUString
sFrameName("_beamer");
3143 sal_Int32 nSearchFlags
= ::com::sun::star::frame::FrameSearchFlag::CHILDREN
| ::com::sun::star::frame::FrameSearchFlag::CREATE
;
3145 Reference
< runtime::XFormController
> xCurrentNavController( getNavController());
3146 // the creation of the "partwindow" may cause a deactivate of the document which will result in our nav controller to be set to NULL
3148 // _first_ check if we have any valid fields we can use for the grid view
3149 // FS - 21.10.99 - 69219
3151 FmXBoundFormFieldIterator
aModelIterator(xCurrentNavController
->getModel());
3152 Reference
< XPropertySet
> xCurrentModelSet
;
3153 bool bHaveUsableControls
= false;
3154 while ((xCurrentModelSet
= Reference
< XPropertySet
>(aModelIterator
.Next(), UNO_QUERY
)).is())
3156 // the FmXBoundFormFieldIterator only supplies controls with a valid control source
3157 // so we just have to check the field type
3158 sal_Int16 nClassId
= ::comphelper::getINT16(xCurrentModelSet
->getPropertyValue(FM_PROP_CLASSID
));
3161 case FormComponentType::IMAGECONTROL
:
3162 case FormComponentType::CONTROL
:
3165 bHaveUsableControls
= true;
3169 if (!bHaveUsableControls
)
3171 ScopedVclPtrInstance
<MessageDialog
>::Create(nullptr, SVX_RESSTR(RID_STR_NOCONTROLS_FOR_EXTERNALDISPLAY
))->Execute();
3176 // load the component for external form views
3177 if (!bAlreadyExistent
)
3179 URL aWantToDispatch
;
3180 aWantToDispatch
.Complete
= FMURL_COMPONENT_FORMGRIDVIEW
;
3182 Reference
< ::com::sun::star::frame::XDispatchProvider
> xProv(m_xAttachedFrame
, UNO_QUERY
);
3183 Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
3185 xDisp
= xProv
->queryDispatch(aWantToDispatch
, sFrameName
, nSearchFlags
);
3188 xDisp
->dispatch(aWantToDispatch
, Sequence
< PropertyValue
>());
3191 // with this the component should be loaded, now search the frame where it resides in
3192 xExternalViewFrame
= m_xAttachedFrame
->findFrame(sFrameName
, ::com::sun::star::frame::FrameSearchFlag::CHILDREN
);
3193 if (xExternalViewFrame
.is())
3195 m_xExternalViewController
= xExternalViewFrame
->getController();
3196 Reference
< ::com::sun::star::lang::XComponent
> xComp(m_xExternalViewController
, UNO_QUERY
);
3198 xComp
->addEventListener((XEventListener
*)(XPropertyChangeListener
*)this);
3203 xExternalViewFrame
= m_xExternalViewController
->getFrame();
3204 Reference
< ::com::sun::star::frame::XDispatchProvider
> xCommLink(xExternalViewFrame
, UNO_QUERY
);
3206 // if we display the active form we interpret the slot as "remove it"
3207 Reference
< XForm
> xCurrentModel(xCurrentNavController
->getModel(), UNO_QUERY
);
3208 if ((xCurrentModel
== m_xExternalDisplayedForm
) || (getInternalForm(xCurrentModel
) == m_xExternalDisplayedForm
))
3210 if ( m_xExternalViewController
== getActiveController() )
3212 Reference
< runtime::XFormController
> xAsFormController( m_xExternalViewController
, UNO_QUERY
);
3213 ControllerFeatures
aHelper( xAsFormController
, NULL
);
3214 (void)aHelper
->commitCurrentControl();
3217 Reference
< runtime::XFormController
> xNewController(m_xExtViewTriggerController
);
3218 CloseExternalFormViewer();
3219 setActiveController(xNewController
);
3224 aClearURL
.Complete
= FMURL_GRIDVIEW_CLEARVIEW
;
3226 Reference
< ::com::sun::star::frame::XDispatch
> xClear( xCommLink
->queryDispatch(aClearURL
, OUString(), 0));
3228 xClear
->dispatch(aClearURL
, Sequence
< PropertyValue
>());
3231 // TODO: We need an interceptor at the xSupplier, which forwards all queryDispatch requests to the FormController
3232 // instance for which this "external view" was triggered
3234 // get the dispatch interface of the frame so we can communicate (interceptable) with the controller
3235 Reference
< ::com::sun::star::frame::XDispatchProvider
> xCommLink(xExternalViewFrame
, UNO_QUERY
);
3237 if (m_xExternalViewController
.is())
3239 DBG_ASSERT(xCommLink
.is(), "FmXFormShell::CreateExternalView : the component doesn't have the necessary interfaces !");
3240 // collect the dispatchers we will need
3242 aAddColumnURL
.Complete
= FMURL_GRIDVIEW_ADDCOLUMN
;
3243 Reference
< ::com::sun::star::frame::XDispatch
> xAddColumnDispatch( xCommLink
->queryDispatch(aAddColumnURL
, OUString(), 0));
3245 aAttachURL
.Complete
= FMURL_GRIDVIEW_ATTACHTOFORM
;
3246 Reference
< ::com::sun::star::frame::XDispatch
> xAttachDispatch( xCommLink
->queryDispatch(aAttachURL
, OUString(), 0));
3248 if (xAddColumnDispatch
.is() && xAttachDispatch
.is())
3250 DBG_ASSERT(xCurrentNavController
.is(), "FmXFormShell::CreateExternalView : invalid call : have no nav controller !");
3251 // first : dispatch the descriptions for the columns to add
3252 sal_Int16 nAddedColumns
= 0;
3254 // for radio buttons we need some special structures
3255 typedef std::map
< OUString
, Sequence
< OUString
> > MapUString2UstringSeq
;
3256 typedef std::map
< OUString
, OUString
> FmMapUString2UString
;
3257 typedef std::map
< OUString
, sal_Int16
> FmMapUString2Int16
;
3259 MapUString2UstringSeq aRadioValueLists
;
3260 MapUString2UstringSeq aRadioListSources
;
3261 FmMapUString2UString aRadioControlSources
;
3262 FmMapUString2Int16 aRadioPositions
;
3264 FmXBoundFormFieldIterator
aModelIterator(xCurrentNavController
->getModel());
3265 Reference
< XPropertySet
> xCurrentModelSet
;
3266 OUString sColumnType
,aGroupName
,sControlSource
;
3267 Sequence
< Property
> aProps
;
3268 Reference
< XPropertySet
> xCurrentBoundField
;
3269 while ((xCurrentModelSet
= Reference
< XPropertySet
>(aModelIterator
.Next(), UNO_QUERY
)).is())
3271 xCurrentModelSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xCurrentBoundField
;
3272 OSL_ENSURE(xCurrentModelSet
.is(),"xCurrentModelSet is null!");
3273 // create a description of the column to be created
3274 // first : determine it's type
3276 sal_Int16 nClassId
= ::comphelper::getINT16(xCurrentModelSet
->getPropertyValue(FM_PROP_CLASSID
));
3279 case FormComponentType::RADIOBUTTON
:
3281 // get the label of the button (this is the access key for our structures)
3282 aGroupName
= getLabelName(xCurrentModelSet
);
3284 // add the reference value of the radio button to the list source sequence
3285 Sequence
< OUString
>& aThisGroupLabels
= aRadioListSources
[aGroupName
];
3286 sal_Int32 nNewSizeL
= aThisGroupLabels
.getLength() + 1;
3287 aThisGroupLabels
.realloc(nNewSizeL
);
3288 aThisGroupLabels
.getArray()[nNewSizeL
- 1] = ::comphelper::getString(xCurrentModelSet
->getPropertyValue(FM_PROP_REFVALUE
));
3290 // add the label to the value list sequence
3291 Sequence
< OUString
>& aThisGroupControlSources
= aRadioValueLists
[aGroupName
];
3292 sal_Int32 nNewSizeC
= aThisGroupControlSources
.getLength() + 1;
3293 aThisGroupControlSources
.realloc(nNewSizeC
);
3294 aThisGroupControlSources
.getArray()[nNewSizeC
- 1] = ::comphelper::getString(xCurrentModelSet
->getPropertyValue(FM_PROP_LABEL
));
3296 // remember the controls source of the radio group
3297 sControlSource
= ::comphelper::getString(xCurrentModelSet
->getPropertyValue(FM_PROP_CONTROLSOURCE
));
3298 if (aRadioControlSources
.find(aGroupName
) == aRadioControlSources
.end())
3299 aRadioControlSources
[aGroupName
] = sControlSource
;
3302 DBG_ASSERT(aRadioControlSources
[aGroupName
] == sControlSource
,
3303 "FmXFormShell::CreateExternalView : inconsistent radio buttons detected !");
3304 // (radio buttons with the same name should have the same control source)
3306 // remember the position within the columns
3307 if (aRadioPositions
.find(aGroupName
) == aRadioPositions
.end())
3308 aRadioPositions
[aGroupName
] = (sal_Int16
)nAddedColumns
;
3310 // any further handling is done below
3314 case FormComponentType::IMAGECONTROL
:
3315 case FormComponentType::CONTROL
:
3316 // no grid columns for these types (though they have a control source)
3318 case FormComponentType::CHECKBOX
:
3319 sColumnType
= FM_COL_CHECKBOX
; break;
3320 case FormComponentType::LISTBOX
:
3321 sColumnType
= FM_COL_LISTBOX
; break;
3322 case FormComponentType::COMBOBOX
:
3323 sColumnType
= FM_COL_COMBOBOX
; break;
3324 case FormComponentType::DATEFIELD
:
3325 sColumnType
= FM_COL_DATEFIELD
; break;
3326 case FormComponentType::TIMEFIELD
:
3327 sColumnType
= FM_COL_TIMEFIELD
; break;
3328 case FormComponentType::NUMERICFIELD
:
3329 sColumnType
= FM_COL_NUMERICFIELD
; break;
3330 case FormComponentType::CURRENCYFIELD
:
3331 sColumnType
= FM_COL_CURRENCYFIELD
; break;
3332 case FormComponentType::PATTERNFIELD
:
3333 sColumnType
= FM_COL_PATTERNFIELD
; break;
3335 case FormComponentType::TEXTFIELD
:
3337 sColumnType
= FM_COL_TEXTFIELD
;
3338 // we know at least two different controls which are TextFields : the basic edit field and the formatted
3339 // field. we distinguish them by their service name
3340 Reference
< lang::XServiceInfo
> xInfo(xCurrentModelSet
, UNO_QUERY
);
3343 sal_Int16 nObjectType
= getControlTypeByObject(xInfo
);
3344 if (OBJ_FM_FORMATTEDFIELD
== nObjectType
)
3345 sColumnType
= FM_COL_FORMATTEDFIELD
;
3350 sColumnType
= FM_COL_TEXTFIELD
; break;
3353 const sal_Int16 nDispatchArgs
= 3;
3354 Sequence
< PropertyValue
> aDispatchArgs(nDispatchArgs
);
3355 PropertyValue
* pDispatchArgs
= aDispatchArgs
.getArray();
3357 // properties describing "meta data" about the column
3359 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNTYPE
;
3360 pDispatchArgs
->Value
<<= sColumnType
;
3363 // the pos : append the col
3364 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNPOS
;
3365 pDispatchArgs
->Value
<<= nAddedColumns
;
3368 // the properties to forward to the new column
3369 Sequence
< PropertyValue
> aColumnProps(1);
3370 PropertyValue
* pColumnProps
= aColumnProps
.getArray();
3373 pColumnProps
->Name
= FM_PROP_LABEL
;
3374 pColumnProps
->Value
<<= getLabelName(xCurrentModelSet
);
3377 // for all other props : transfer them
3378 Reference
< XPropertySetInfo
> xControlModelInfo( xCurrentModelSet
->getPropertySetInfo());
3379 DBG_ASSERT(xControlModelInfo
.is(), "FmXFormShell::CreateExternalView : the control model has no property info ! This will crash !");
3380 aProps
= xControlModelInfo
->getProperties();
3381 const Property
* pProps
= aProps
.getConstArray();
3383 // realloc the control description sequence
3384 sal_Int32 nExistentDescs
= pColumnProps
- aColumnProps
.getArray();
3385 aColumnProps
.realloc(nExistentDescs
+ aProps
.getLength());
3386 pColumnProps
= aColumnProps
.getArray() + nExistentDescs
;
3388 for (sal_Int32 i
=0; i
<aProps
.getLength(); ++i
, ++pProps
)
3390 if (pProps
->Name
== FM_PROP_LABEL
)
3393 if (pProps
->Name
== FM_PROP_DEFAULTCONTROL
)
3394 // allow the column's own "default control"
3396 if (pProps
->Attributes
& PropertyAttribute::READONLY
)
3397 // assume that properties which are readonly for the control are ro for the column to be created, too
3400 pColumnProps
->Name
= pProps
->Name
;
3401 pColumnProps
->Value
= xCurrentModelSet
->getPropertyValue(pProps
->Name
);
3404 aColumnProps
.realloc(pColumnProps
- aColumnProps
.getArray());
3406 // columns props are a dispatch argument
3407 pDispatchArgs
->Name
= "ColumnProperties"; // TODO : fmurl.*
3408 pDispatchArgs
->Value
= makeAny(aColumnProps
);
3410 DBG_ASSERT(nDispatchArgs
== (pDispatchArgs
- aDispatchArgs
.getConstArray()),
3411 "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
3413 // dispatch the "add column"
3414 xAddColumnDispatch
->dispatch(aAddColumnURL
, aDispatchArgs
);
3418 // now for the radio button handling
3419 sal_Int16
nOffset(0);
3420 // properties describing the "direct" column properties
3421 const sal_Int16 nListBoxDescription
= 6;
3422 Sequence
< PropertyValue
> aListBoxDescription(nListBoxDescription
);
3423 for ( FmMapUString2UString::const_iterator aCtrlSource
= aRadioControlSources
.begin();
3424 aCtrlSource
!= aRadioControlSources
.end();
3425 ++aCtrlSource
, ++nOffset
3429 PropertyValue
* pListBoxDescription
= aListBoxDescription
.getArray();
3431 pListBoxDescription
->Name
= FM_PROP_LABEL
;
3432 pListBoxDescription
->Value
<<= (*aCtrlSource
).first
;
3433 ++pListBoxDescription
;
3436 pListBoxDescription
->Name
= FM_PROP_CONTROLSOURCE
;
3437 pListBoxDescription
->Value
<<= (*aCtrlSource
).second
;
3438 ++pListBoxDescription
;
3441 pListBoxDescription
->Name
= FM_PROP_BOUNDCOLUMN
;
3442 pListBoxDescription
->Value
<<= (sal_Int16
)1;
3443 ++pListBoxDescription
;
3446 pListBoxDescription
->Name
= FM_PROP_LISTSOURCETYPE
;
3447 ListSourceType eType
= ListSourceType_VALUELIST
;
3448 pListBoxDescription
->Value
= makeAny(eType
);
3449 ++pListBoxDescription
;
3452 MapUString2UstringSeq::const_iterator aCurrentListSource
= aRadioListSources
.find((*aCtrlSource
).first
);
3453 DBG_ASSERT(aCurrentListSource
!= aRadioListSources
.end(),
3454 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3455 pListBoxDescription
->Name
= FM_PROP_LISTSOURCE
;
3456 pListBoxDescription
->Value
= makeAny((*aCurrentListSource
).second
);
3457 ++pListBoxDescription
;
3460 MapUString2UstringSeq::const_iterator aCurrentValueList
= aRadioValueLists
.find((*aCtrlSource
).first
);
3461 DBG_ASSERT(aCurrentValueList
!= aRadioValueLists
.end(),
3462 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3463 pListBoxDescription
->Name
= FM_PROP_STRINGITEMLIST
;
3464 pListBoxDescription
->Value
= makeAny(((*aCurrentValueList
).second
));
3465 ++pListBoxDescription
;
3467 DBG_ASSERT(nListBoxDescription
== (pListBoxDescription
- aListBoxDescription
.getConstArray()),
3468 "FmXFormShell::CreateExternalView : forgot to adjust nListBoxDescription ?");
3470 // properties describing the column "meta data"
3471 const sal_Int16 nDispatchArgs
= 3;
3472 Sequence
< PropertyValue
> aDispatchArgs(nDispatchArgs
);
3473 PropertyValue
* pDispatchArgs
= aDispatchArgs
.getArray();
3475 // column type : listbox
3476 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNTYPE
;
3477 OUString fColName
= FM_COL_LISTBOX
;
3478 pDispatchArgs
->Value
<<= fColName
;
3479 // pDispatchArgs->Value <<= (OUString)FM_COL_LISTBOX;
3483 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNPOS
;
3484 FmMapUString2Int16::const_iterator aOffset
= aRadioPositions
.find((*aCtrlSource
).first
);
3485 DBG_ASSERT(aOffset
!= aRadioPositions
.end(),
3486 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3487 sal_Int16 nPosition
= (*aOffset
).second
;
3488 nPosition
= nPosition
+ nOffset
;
3489 // we already inserted nOffset additional columns ....
3490 pDispatchArgs
->Value
<<= nPosition
;
3494 pDispatchArgs
->Name
= "ColumnProperties"; // TODO : fmurl.*
3495 pDispatchArgs
->Value
= makeAny(aListBoxDescription
);
3497 DBG_ASSERT(nDispatchArgs
== (pDispatchArgs
- aDispatchArgs
.getConstArray()),
3498 "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
3500 // dispatch the "add column"
3501 xAddColumnDispatch
->dispatch(aAddColumnURL
, aDispatchArgs
);
3506 DBG_ASSERT(nAddedColumns
> 0, "FmXFormShell::CreateExternalView : no controls (inconsistent) !");
3507 // we should have checked if we have any usable controls (see above).
3509 // "load" the "form" of the external view
3511 aArg
.Name
= FMARG_ATTACHTO_MASTERFORM
;
3512 Reference
< XResultSet
> xForm(xCurrentNavController
->getModel(), UNO_QUERY
);
3513 aArg
.Value
<<= xForm
;
3515 m_xExternalDisplayedForm
= xForm
;
3516 // do this before dispatching the "attach" command, as the attach may result in a call to our queryDispatch (for the FormSlots)
3517 // whichs needs the m_xExternalDisplayedForm
3519 xAttachDispatch
->dispatch(aAttachURL
, Sequence
< PropertyValue
>(&aArg
, 1));
3521 m_xExtViewTriggerController
= xCurrentNavController
;
3523 // we want to know modifications done in the external view
3524 // if the external controller is a XFormController we can use all our default handlings for it
3525 Reference
< runtime::XFormController
> xFormController( m_xExternalViewController
, UNO_QUERY
);
3526 OSL_ENSURE( xFormController
.is(), "FmXFormShell::CreateExternalView:: invalid external view controller!" );
3527 if (xFormController
.is())
3528 xFormController
->addActivateListener((XFormControllerListener
*)this);
3534 OSL_FAIL("FmXFormShell::CreateExternalView : could not create the external form view !");
3537 InvalidateSlot( SID_FM_VIEW_AS_GRID
, false );
3541 void FmXFormShell::implAdjustConfigCache()
3543 // get (cache) the wizard usage flag
3544 Sequence
< OUString
> aNames(1);
3545 aNames
[0] = "FormControlPilotsEnabled";
3546 Sequence
< Any
> aFlags
= GetProperties(aNames
);
3547 if (1 == aFlags
.getLength())
3548 m_bUseWizards
= ::cppu::any2bool(aFlags
[0]);
3552 void FmXFormShell::Notify( const com::sun::star::uno::Sequence
< OUString
>& _rPropertyNames
)
3554 if ( impl_checkDisposed() )
3557 const OUString
* pSearch
= _rPropertyNames
.getConstArray();
3558 const OUString
* pSearchTil
= pSearch
+ _rPropertyNames
.getLength();
3559 for (;pSearch
< pSearchTil
; ++pSearch
)
3560 if (*pSearch
== "FormControlPilotsEnabled")
3562 implAdjustConfigCache();
3563 InvalidateSlot( SID_FM_USE_WIZARDS
, true );
3567 void FmXFormShell::ImplCommit()
3572 void FmXFormShell::SetWizardUsing(bool _bUseThem
)
3574 m_bUseWizards
= _bUseThem
;
3576 Sequence
< OUString
> aNames(1);
3577 aNames
[0] = "FormControlPilotsEnabled";
3578 Sequence
< Any
> aValues(1);
3579 aValues
[0] <<= m_bUseWizards
;
3580 PutProperties(aNames
, aValues
);
3584 void FmXFormShell::viewDeactivated( FmFormView
& _rCurrentView
, bool _bDeactivateController
/* = sal_True */ )
3587 if ( _rCurrentView
.GetImpl() && !_rCurrentView
.IsDesignMode() )
3589 _rCurrentView
.GetImpl()->Deactivate( _bDeactivateController
);
3592 // if we have an async load operation pending for the 0-th page for this view,
3593 // we need to cancel this
3594 FmFormPage
* pPage
= _rCurrentView
.GetCurPage();
3597 // move all events from our queue to a new one, omit the events for the deactivated
3599 ::std::queue
< FmLoadAction
> aNewEvents
;
3600 while ( !m_aLoadingPages
.empty() )
3602 FmLoadAction aAction
= m_aLoadingPages
.front();
3603 m_aLoadingPages
.pop();
3604 if ( pPage
!= aAction
.pPage
)
3606 aNewEvents
.push( aAction
);
3610 Application::RemoveUserEvent( aAction
.nEventId
);
3613 m_aLoadingPages
= aNewEvents
;
3616 // remove callbacks at the page
3619 pPage
->GetImpl().SetFormsCreationHdl( Link
<>() );
3621 UpdateForms( true );
3625 IMPL_LINK_NOARG( FmXFormShell
, OnFirstTimeActivation
)
3627 if ( impl_checkDisposed() )
3630 m_nActivationEvent
= 0;
3631 SfxObjectShell
* pDocument
= m_pShell
->GetObjectShell();
3633 if ( pDocument
&& !pDocument
->HasName() )
3635 if ( isEnhancedForm() )
3637 // show the data navigator
3638 if ( !m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_DATANAVIGATOR
) )
3639 m_pShell
->GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_SHOW_DATANAVIGATOR
);
3647 IMPL_LINK( FmXFormShell
, OnFormsCreated
, FmFormPage
*, /*_pPage*/ )
3649 UpdateForms( true );
3654 void FmXFormShell::viewActivated( FmFormView
& _rCurrentView
, bool _bSyncAction
/* = sal_False */ )
3657 FmFormPage
* pPage
= _rCurrentView
.GetCurPage();
3659 // activate our view if we are activated ourself
3660 // FS - 30.06.99 - 67308
3661 if ( _rCurrentView
.GetImpl() && !_rCurrentView
.IsDesignMode() )
3663 // load forms for the page the current view belongs to
3666 if ( !pPage
->GetImpl().hasEverBeenActivated() )
3667 loadForms( pPage
, FORMS_LOAD
| ( _bSyncAction
? FORMS_SYNC
: FORMS_ASYNC
) );
3668 pPage
->GetImpl().setHasBeenActivated( );
3671 // first-time initializations for the views
3672 if ( !_rCurrentView
.GetImpl()->hasEverBeenActivated( ) )
3674 _rCurrentView
.GetImpl()->onFirstViewActivation( PTR_CAST( FmFormModel
, _rCurrentView
.GetModel() ) );
3675 _rCurrentView
.GetImpl()->setHasBeenActivated( );
3678 // activate the current view
3679 _rCurrentView
.GetImpl()->Activate( _bSyncAction
);
3682 // set callbacks at the page
3685 pPage
->GetImpl().SetFormsCreationHdl( LINK( this, FmXFormShell
, OnFormsCreated
) );
3688 UpdateForms( true );
3690 if ( !hasEverBeenActivated() )
3692 m_nActivationEvent
= Application::PostUserEvent( LINK( this, FmXFormShell
, OnFirstTimeActivation
) );
3693 setHasBeenActivated();
3696 // find a default "current form", if there is none, yet
3697 // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
3698 impl_defaultCurrentForm_nothrow();
3702 void FmXFormShell::impl_defaultCurrentForm_nothrow()
3704 if ( impl_checkDisposed() )
3707 if ( m_xCurrentForm
.is() )
3708 // no action required
3711 FmFormView
* pFormView
= m_pShell
->GetFormView();
3712 FmFormPage
* pPage
= pFormView
? pFormView
->GetCurPage() : NULL
;
3718 Reference
< XIndexAccess
> xForms( pPage
->GetForms( false ), UNO_QUERY
);
3719 if ( !xForms
.is() || !xForms
->hasElements() )
3722 Reference
< XForm
> xNewCurrentForm( xForms
->getByIndex(0), UNO_QUERY_THROW
);
3723 impl_updateCurrentForm( xNewCurrentForm
);
3725 catch( const Exception
& )
3727 DBG_UNHANDLED_EXCEPTION();
3732 void FmXFormShell::smartControlReset( const Reference
< XIndexAccess
>& _rxModels
)
3734 if (!_rxModels
.is())
3736 OSL_FAIL("FmXFormShell::smartControlReset: invalid container!");
3740 static const OUString sClassIdPropertyName
= FM_PROP_CLASSID
;
3741 static const OUString sBoundFieldPropertyName
= FM_PROP_BOUNDFIELD
;
3742 sal_Int32 nCount
= _rxModels
->getCount();
3743 Reference
< XPropertySet
> xCurrent
;
3744 Reference
< XPropertySetInfo
> xCurrentInfo
;
3745 Reference
< XPropertySet
> xBoundField
;
3747 for (sal_Int32 i
=0; i
<nCount
; ++i
)
3749 _rxModels
->getByIndex(i
) >>= xCurrent
;
3751 xCurrentInfo
= xCurrent
->getPropertySetInfo();
3753 xCurrentInfo
.clear();
3754 if (!xCurrentInfo
.is())
3757 if (xCurrentInfo
->hasPropertyByName(sClassIdPropertyName
))
3758 { // it's a control model
3760 // check if this control is bound to a living database field
3761 if (xCurrentInfo
->hasPropertyByName(sBoundFieldPropertyName
))
3762 xCurrent
->getPropertyValue(sBoundFieldPropertyName
) >>= xBoundField
;
3764 xBoundField
.clear();
3766 // reset only if it's *not* bound
3767 bool bReset
= !xBoundField
.is();
3769 // and additionally, check if it has an external value binding
3770 Reference
< XBindableValue
> xBindable( xCurrent
, UNO_QUERY
);
3771 if ( xBindable
.is() && xBindable
->getValueBinding().is() )
3776 Reference
< XReset
> xControlReset( xCurrent
, UNO_QUERY
);
3777 if ( xControlReset
.is() )
3778 xControlReset
->reset();
3783 Reference
< XIndexAccess
> xContainer(xCurrent
, UNO_QUERY
);
3784 if (xContainer
.is())
3785 smartControlReset(xContainer
);
3791 IMPL_LINK( FmXFormShell
, OnLoadForms
, FmFormPage
*, /*_pPage*/ )
3793 FmLoadAction aAction
= m_aLoadingPages
.front();
3794 m_aLoadingPages
.pop();
3796 loadForms( aAction
.pPage
, aAction
.nFlags
& ~FORMS_ASYNC
);
3803 bool lcl_isLoadable( const Reference
< XInterface
>& _rxLoadable
)
3805 // determines whether a form should be loaded or not
3806 // if there is no datasource or connection there is no reason to load a form
3807 Reference
< XPropertySet
> xSet( _rxLoadable
, UNO_QUERY
);
3812 Reference
< XConnection
> xConn
;
3813 if ( isEmbeddedInDatabase( _rxLoadable
.get(), xConn
) )
3816 // is there already a active connection
3817 xSet
->getPropertyValue(FM_PROP_ACTIVE_CONNECTION
) >>= xConn
;
3821 OUString sPropertyValue
;
3822 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_DATASOURCE
) >>= sPropertyValue
);
3823 if ( !sPropertyValue
.isEmpty() )
3826 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_URL
) >>= sPropertyValue
);
3827 if ( !sPropertyValue
.isEmpty() )
3830 catch(const Exception
&)
3832 DBG_UNHANDLED_EXCEPTION();
3839 void FmXFormShell::loadForms( FmFormPage
* _pPage
, const sal_uInt16 _nBehaviour
/* FORMS_LOAD | FORMS_SYNC */ )
3841 DBG_ASSERT( ( _nBehaviour
& ( FORMS_ASYNC
| FORMS_UNLOAD
) ) != ( FORMS_ASYNC
| FORMS_UNLOAD
),
3842 "FmXFormShell::loadForms: async loading not supported - this will heavily fail!" );
3844 if ( _nBehaviour
& FORMS_ASYNC
)
3846 m_aLoadingPages
.push( FmLoadAction(
3849 Application::PostUserEvent( LINK( this, FmXFormShell
, OnLoadForms
), _pPage
)
3854 DBG_ASSERT( _pPage
, "FmXFormShell::loadForms: invalid page!" );
3857 // lock the undo env so the forms can change non-transient properties while loading
3858 // (without this my doc's modified flag would be set)
3859 FmFormModel
* pModel
= PTR_CAST( FmFormModel
, _pPage
->GetModel() );
3860 DBG_ASSERT( pModel
, "FmXFormShell::loadForms: invalid model!" );
3862 pModel
->GetUndoEnv().Lock();
3865 Reference
< XIndexAccess
> xForms
;
3866 xForms
.set(_pPage
->GetForms( false ), css::uno::UNO_QUERY
);
3870 Reference
< XLoadable
> xForm
;
3871 for ( sal_Int32 j
= 0, nCount
= xForms
->getCount(); j
< nCount
; ++j
)
3873 xForms
->getByIndex( j
) >>= xForm
;
3874 bool bFormWasLoaded
= false;
3875 // a database form must be loaded for
3878 if ( 0 == ( _nBehaviour
& FORMS_UNLOAD
) )
3880 if ( lcl_isLoadable( xForm
) && !xForm
->isLoaded() )
3885 if ( xForm
->isLoaded() )
3887 bFormWasLoaded
= true;
3892 catch( const Exception
& )
3894 DBG_UNHANDLED_EXCEPTION();
3897 // reset the form if it was loaded
3898 if ( bFormWasLoaded
)
3900 Reference
< XIndexAccess
> xContainer( xForm
, UNO_QUERY
);
3901 DBG_ASSERT( xContainer
.is(), "FmXFormShell::loadForms: the form is no container!" );
3902 if ( xContainer
.is() )
3903 smartControlReset( xContainer
);
3909 // unlock the environment
3910 pModel
->GetUndoEnv().UnLock();
3915 void FmXFormShell::ExecuteTextAttribute( SfxRequest
& _rReq
)
3917 m_pTextShell
->ExecuteTextAttribute( _rReq
);
3921 void FmXFormShell::GetTextAttributeState( SfxItemSet
& _rSet
)
3923 m_pTextShell
->GetTextAttributeState( _rSet
);
3927 bool FmXFormShell::IsActiveControl( bool _bCountRichTextOnly
) const
3929 return m_pTextShell
->IsActiveControl( _bCountRichTextOnly
);
3933 void FmXFormShell::ForgetActiveControl()
3935 m_pTextShell
->ForgetActiveControl();
3939 void FmXFormShell::SetControlActivationHandler( const Link
<>& _rHdl
)
3941 m_pTextShell
->SetControlActivationHandler( _rHdl
);
3944 void FmXFormShell::handleShowPropertiesRequest()
3946 if ( onlyControlsAreMarked() )
3947 ShowSelectionProperties( true );
3951 void FmXFormShell::handleMouseButtonDown( const SdrViewEvent
& _rViewEvent
)
3953 // catch simple double clicks
3954 if ( ( _rViewEvent
.nMouseClicks
== 2 ) && ( _rViewEvent
.nMouseCode
== MOUSE_LEFT
) )
3956 if ( _rViewEvent
.eHit
== SDRHIT_MARKEDOBJECT
)
3958 if ( onlyControlsAreMarked() )
3959 ShowSelectionProperties( true );
3965 bool FmXFormShell::HasControlFocus() const
3967 bool bHasControlFocus
= false;
3971 Reference
< runtime::XFormController
> xController( getActiveController() );
3972 Reference
< XControl
> xCurrentControl
;
3973 if ( xController
.is() )
3974 xCurrentControl
.set( xController
->getCurrentControl() );
3975 if ( xCurrentControl
.is() )
3977 Reference
< XWindow2
> xPeerWindow( xCurrentControl
->getPeer(), UNO_QUERY_THROW
);
3978 bHasControlFocus
= xPeerWindow
->hasFocus();
3981 catch( const Exception
& )
3983 DBG_UNHANDLED_EXCEPTION();
3986 return bHasControlFocus
;
3991 SearchableControlIterator::SearchableControlIterator(Reference
< XInterface
> xStartingPoint
)
3992 :IndexAccessIterator(xStartingPoint
)
3997 bool SearchableControlIterator::ShouldHandleElement(const Reference
< XInterface
>& xElement
)
3999 // wenn das Ding eine ControlSource und einen BoundField-Property hat
4000 Reference
< XPropertySet
> xProperties(xElement
, UNO_QUERY
);
4001 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE
, xProperties
) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xProperties
))
4003 // und das BoundField gueltig ist
4004 Reference
< XPropertySet
> xField
;
4005 xProperties
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
4009 m_sCurrentValue
= ::comphelper::getString(xProperties
->getPropertyValue(FM_PROP_CONTROLSOURCE
));
4014 // wenn es ein Grid-Control ist
4015 if (::comphelper::hasProperty(FM_PROP_CLASSID
, xProperties
))
4017 Any
aClassId( xProperties
->getPropertyValue(FM_PROP_CLASSID
) );
4018 if (::comphelper::getINT16(aClassId
) == FormComponentType::GRIDCONTROL
)
4020 m_sCurrentValue
.clear();
4029 bool SearchableControlIterator::ShouldStepInto(const Reference
< XInterface
>& /*xContainer*/) const
4037 SFX_IMPL_MENU_CONTROL(ControlConversionMenuController
, SfxBoolItem
);
4040 ControlConversionMenuController::ControlConversionMenuController( sal_uInt16 _nId
, Menu
& _rMenu
, SfxBindings
& _rBindings
)
4041 :SfxMenuControl( _nId
, _rBindings
)
4042 ,m_pMainMenu( &_rMenu
)
4043 ,m_pConversionMenu( NULL
)
4045 if ( _nId
== SID_FM_CHANGECONTROLTYPE
)
4047 m_pConversionMenu
= FmXFormShell::GetConversionMenu();
4048 _rMenu
.SetPopupMenu( _nId
, m_pConversionMenu
);
4050 for (sal_Int16 i
=0; i
<m_pConversionMenu
->GetItemCount(); ++i
)
4052 _rBindings
.Invalidate(m_pConversionMenu
->GetItemId(i
));
4053 SfxStatusForwarder
* pForwarder
= new SfxStatusForwarder(m_pConversionMenu
->GetItemId(i
), *this);
4054 m_aStatusForwarders
.push_back(pForwarder
);
4060 ControlConversionMenuController::~ControlConversionMenuController()
4062 m_pMainMenu
->SetPopupMenu(SID_FM_CHANGECONTROLTYPE
, NULL
);
4063 delete m_pConversionMenu
;
4067 void ControlConversionMenuController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
4069 if (nSID
== GetId())
4070 SfxMenuControl::StateChanged(nSID
, eState
, pState
);
4071 else if (FmXFormShell::isControlConversionSlot(nSID
))
4073 if ((m_pConversionMenu
->GetItemPos(nSID
) != MENU_ITEM_NOTFOUND
) && (eState
== SfxItemState::DISABLED
))
4075 m_pConversionMenu
->RemoveItem(m_pConversionMenu
->GetItemPos(nSID
));
4077 else if ((m_pConversionMenu
->GetItemPos(nSID
) == MENU_ITEM_NOTFOUND
) && (eState
!= SfxItemState::DISABLED
))
4079 // We can't simply re-insert the item because we have a clear order for all the our items.
4080 // So first we have to determine the position of the item to insert.
4081 boost::scoped_ptr
<PopupMenu
> pSource(FmXFormShell::GetConversionMenu());
4082 sal_uInt16 nSourcePos
= pSource
->GetItemPos(nSID
);
4083 DBG_ASSERT(nSourcePos
!= MENU_ITEM_NOTFOUND
, "ControlConversionMenuController::StateChanged : FmXFormShell supplied an invalid menu !");
4084 sal_uInt16 nPrevInSource
= nSourcePos
;
4085 sal_uInt16 nPrevInConversion
= MENU_ITEM_NOTFOUND
;
4086 while (nPrevInSource
>0)
4088 sal_Int16 nPrevId
= pSource
->GetItemId(--nPrevInSource
);
4090 // do we have the source's predecessor in our conversion menu, too ?
4091 nPrevInConversion
= m_pConversionMenu
->GetItemPos(nPrevId
);
4092 if (nPrevInConversion
!= MENU_ITEM_NOTFOUND
)
4095 if (MENU_ITEM_NOTFOUND
== nPrevInConversion
)
4096 // none of the items which precede the nSID-slot in the source menu are present in our conversion menu
4097 nPrevInConversion
= sal::static_int_cast
< sal_uInt16
>(-1); // put the item at the first position
4098 m_pConversionMenu
->InsertItem(nSID
, pSource
->GetItemText(nSID
),
4099 pSource
->GetItemBits(nSID
), OString(), ++nPrevInConversion
);
4100 m_pConversionMenu
->SetItemImage(nSID
, pSource
->GetItemImage(nSID
));
4101 m_pConversionMenu
->SetHelpId(nSID
, pSource
->GetHelpId(nSID
));
4103 m_pMainMenu
->EnableItem(SID_FM_CHANGECONTROLTYPE
, m_pConversionMenu
->GetItemCount() > 0);
4107 OSL_FAIL("ControlConversionMenuController::StateChanged : unknown id !");
4113 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */