1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <sal/macros.h>
31 #include "fmitems.hxx"
33 #include "fmpgeimp.hxx"
34 #include "svx/fmtools.hxx"
36 #include "svx/fmresids.hrc"
37 #include "fmservs.hxx"
38 #include "fmshimp.hxx"
39 #include "fmtextcontrolshell.hxx"
42 #include "fmvwimp.hxx"
43 #include "formtoolbars.hxx"
44 #include "gridcols.hxx"
45 #include "svx/svditer.hxx"
46 #include "svx/dialmgr.hxx"
47 #include "svx/dialogs.hrc"
48 #include "svx/fmglob.hxx"
49 #include "svx/fmmodel.hxx"
50 #include "svx/fmpage.hxx"
51 #include "svx/fmshell.hxx"
52 #include "svx/obj3d.hxx"
53 #include "svx/sdrpagewindow.hxx"
54 #include "svx/svdpagv.hxx"
55 #include "svx/svxdlg.hxx"
56 #include "svx/svxids.hrc"
58 /** === begin UNO includes === **/
59 #include <com/sun/star/awt/XWindow2.hpp>
60 #include <com/sun/star/awt/XCheckBox.hpp>
61 #include <com/sun/star/awt/XListBox.hpp>
62 #include <com/sun/star/awt/XTextComponent.hpp>
63 #include <com/sun/star/beans/NamedValue.hpp>
64 #include <com/sun/star/beans/PropertyAttribute.hpp>
65 #include <com/sun/star/beans/XPropertyState.hpp>
66 #include <com/sun/star/container/XContainer.hpp>
67 #include <com/sun/star/container/XEnumeration.hpp>
68 #include <com/sun/star/container/XEnumerationAccess.hpp>
69 #include <com/sun/star/container/XIndexAccess.hpp>
70 #include <com/sun/star/container/XNamed.hpp>
71 #include <com/sun/star/form/ListSourceType.hpp>
72 #include <com/sun/star/form/XBoundComponent.hpp>
73 #include <com/sun/star/form/XBoundControl.hpp>
74 #include <com/sun/star/form/XGrid.hpp>
75 #include <com/sun/star/form/XGridPeer.hpp>
76 #include <com/sun/star/form/XLoadable.hpp>
77 #include <com/sun/star/form/XReset.hpp>
78 #include <com/sun/star/form/binding/XBindableValue.hpp>
79 #include <com/sun/star/form/binding/XListEntrySink.hpp>
80 #include <com/sun/star/frame/FrameSearchFlag.hpp>
81 #include <com/sun/star/script/XEventAttacherManager.hpp>
82 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
83 #include <com/sun/star/util/XCancellable.hpp>
84 #include <com/sun/star/util/XModeSelector.hpp>
85 #include <com/sun/star/util/XModifyBroadcaster.hpp>
86 #include <com/sun/star/util/XNumberFormatter.hpp>
87 #include <com/sun/star/view/XSelectionSupplier.hpp>
88 #include <com/sun/star/beans/XIntrospection.hpp>
89 /** === end UNO includes === **/
91 #include <comphelper/extract.hxx>
92 #include <comphelper/evtmethodhelper.hxx>
93 #include <comphelper/processfactory.hxx>
94 #include <comphelper/property.hxx>
95 #include <comphelper/stl_types.hxx>
96 #include <comphelper/string.hxx>
97 #include <connectivity/dbtools.hxx>
98 #include <cppuhelper/servicefactory.hxx>
99 #include <osl/mutex.hxx>
100 #include <rtl/logfile.hxx>
101 #include <sfx2/dispatch.hxx>
102 #include <sfx2/docfile.hxx>
103 #include <sfx2/frame.hxx>
104 #include <sfx2/objsh.hxx>
105 #include <sfx2/viewfrm.hxx>
106 #include <sfx2/viewsh.hxx>
107 #include <toolkit/helper/vclunohelper.hxx>
108 #include <tools/diagnose_ex.h>
109 #include <tools/shl.hxx>
110 #include <vcl/msgbox.hxx>
111 #include <vcl/waitobj.hxx>
114 #include <functional>
117 // wird fuer Invalidate verwendet -> mitpflegen
118 static sal_uInt16 DatabaseSlotMap
[] =
125 SID_FM_RECORD_DELETE
,
126 SID_FM_RECORD_ABSOLUTE
,
130 SID_FM_REMOVE_FILTER_SORT
,
135 SID_FM_FORM_FILTERED
,
137 SID_FM_REFRESH_FORM_CONTROL
,
144 // wird fuer Invalidate verwendet -> mitpflegen
145 // aufsteigend sortieren !!!!!!
146 static sal_Int16 DlgSlotMap
[] = // slots des Controllers
148 SID_FM_CTL_PROPERTIES
,
152 SID_FM_SHOW_FMEXPLORER
,
153 SID_FM_FIELDS_CONTROL
,
154 SID_FM_SHOW_PROPERTIES
,
155 SID_FM_PROPERTY_CONTROL
,
156 SID_FM_FMEXPLORER_CONTROL
,
157 SID_FM_SHOW_DATANAVIGATOR
,
158 SID_FM_DATANAVIGATOR_CONTROL
,
162 static sal_Int16 SelObjectSlotMap
[] = // vom SelObject abhaengige Slots
164 SID_FM_CONVERTTO_EDIT
,
165 SID_FM_CONVERTTO_BUTTON
,
166 SID_FM_CONVERTTO_FIXEDTEXT
,
167 SID_FM_CONVERTTO_LISTBOX
,
168 SID_FM_CONVERTTO_CHECKBOX
,
169 SID_FM_CONVERTTO_RADIOBUTTON
,
170 SID_FM_CONVERTTO_GROUPBOX
,
171 SID_FM_CONVERTTO_COMBOBOX
,
172 SID_FM_CONVERTTO_IMAGEBUTTON
,
173 SID_FM_CONVERTTO_FILECONTROL
,
174 SID_FM_CONVERTTO_DATE
,
175 SID_FM_CONVERTTO_TIME
,
176 SID_FM_CONVERTTO_NUMERIC
,
177 SID_FM_CONVERTTO_CURRENCY
,
178 SID_FM_CONVERTTO_PATTERN
,
179 SID_FM_CONVERTTO_IMAGECONTROL
,
180 SID_FM_CONVERTTO_FORMATTED
,
181 SID_FM_CONVERTTO_SCROLLBAR
,
182 SID_FM_CONVERTTO_SPINBUTTON
,
183 SID_FM_CONVERTTO_NAVIGATIONBAR
,
185 SID_FM_FMEXPLORER_CONTROL
,
186 SID_FM_DATANAVIGATOR_CONTROL
,
191 // die folgenden Arrays muessen kosistent sein, also einander entsprechende Eintraege an der selben relativen Position
192 // innerhalb ihres jeweiligen Arrays stehen
193 static sal_Int16 nConvertSlots
[] =
195 SID_FM_CONVERTTO_EDIT
,
196 SID_FM_CONVERTTO_BUTTON
,
197 SID_FM_CONVERTTO_FIXEDTEXT
,
198 SID_FM_CONVERTTO_LISTBOX
,
199 SID_FM_CONVERTTO_CHECKBOX
,
200 SID_FM_CONVERTTO_RADIOBUTTON
,
201 SID_FM_CONVERTTO_GROUPBOX
,
202 SID_FM_CONVERTTO_COMBOBOX
,
203 SID_FM_CONVERTTO_IMAGEBUTTON
,
204 SID_FM_CONVERTTO_FILECONTROL
,
205 SID_FM_CONVERTTO_DATE
,
206 SID_FM_CONVERTTO_TIME
,
207 SID_FM_CONVERTTO_NUMERIC
,
208 SID_FM_CONVERTTO_CURRENCY
,
209 SID_FM_CONVERTTO_PATTERN
,
210 SID_FM_CONVERTTO_IMAGECONTROL
,
211 SID_FM_CONVERTTO_FORMATTED
,
212 SID_FM_CONVERTTO_SCROLLBAR
,
213 SID_FM_CONVERTTO_SPINBUTTON
,
214 SID_FM_CONVERTTO_NAVIGATIONBAR
217 static sal_Int16 nCreateSlots
[] =
232 SID_FM_CURRENCYFIELD
,
235 SID_FM_FORMATTEDFIELD
,
241 static sal_Int16 nObjectTypes
[] =
256 OBJ_FM_CURRENCYFIELD
,
259 OBJ_FM_FORMATTEDFIELD
,
265 using namespace ::com::sun::star
;
266 using namespace ::com::sun::star::ui
;
267 using namespace ::com::sun::star::uno
;
268 using namespace ::com::sun::star::sdb
;
269 using namespace ::com::sun::star::sdbc
;
270 using namespace ::com::sun::star::sdbcx
;
271 using namespace ::com::sun::star::beans
;
272 using namespace ::com::sun::star::container
;
273 using namespace ::com::sun::star::form
;
274 using namespace ::com::sun::star::form::binding
;
275 using namespace ::com::sun::star::form::runtime
;
276 using namespace ::com::sun::star::awt
;
277 using namespace ::com::sun::star::view
;
278 using namespace ::com::sun::star::lang
;
279 using namespace ::com::sun::star::util
;
280 using namespace ::com::sun::star::frame
;
281 using namespace ::com::sun::star::script
;
282 using namespace ::svxform
;
283 using namespace ::svx
;
285 //==============================================================================
287 //==============================================================================
290 //..........................................................................
291 void collectInterfacesFromMarkList( const SdrMarkList
& _rMarkList
, InterfaceBag
& /* [out] */ _rInterfaces
)
293 _rInterfaces
.clear();
295 sal_uInt32 nMarkCount
= _rMarkList
.GetMarkCount();
296 for ( sal_uInt32 i
= 0; i
< nMarkCount
; ++i
)
298 SdrObject
* pCurrent
= _rMarkList
.GetMark( i
)->GetMarkedSdrObj();
300 SdrObjListIter
* pGroupIterator
= NULL
;
301 if ( pCurrent
->IsGroupObject() )
303 pGroupIterator
= new SdrObjListIter( *pCurrent
->GetSubList() );
304 pCurrent
= pGroupIterator
->IsMore() ? pGroupIterator
->Next() : NULL
;
309 FmFormObj
* pAsFormObject
= FmFormObj::GetFormObject( pCurrent
);
310 // note this will de-reference virtual objects, if necessary/possible
313 Reference
< XInterface
> xControlModel( pAsFormObject
->GetUnoControlModel(), UNO_QUERY
);
314 // the UNO_QUERY is important for normalization
315 if ( xControlModel
.is() )
316 _rInterfaces
.insert( xControlModel
);
320 pCurrent
= pGroupIterator
&& pGroupIterator
->IsMore() ? pGroupIterator
->Next() : NULL
;
323 if ( pGroupIterator
)
324 delete pGroupIterator
;
328 //..........................................................................
329 sal_Int16
GridView2ModelPos(const Reference
< XIndexAccess
>& rColumns
, sal_Int16 nViewPos
)
335 // loop through all columns
337 Reference
< XPropertySet
> xCur
;
338 for (i
=0; i
<rColumns
->getCount(); ++i
)
340 rColumns
->getByIndex(i
) >>= xCur
;
341 if (!::comphelper::getBOOL(xCur
->getPropertyValue(FM_PROP_HIDDEN
)))
343 // for every visible col : if nViewPos is greater zero, decrement it, else we
344 // have found the model position
351 if (i
<rColumns
->getCount())
355 catch(const Exception
&)
357 DBG_UNHANDLED_EXCEPTION();
359 return (sal_Int16
)-1;
362 //..........................................................................
363 void TransferEventScripts(const Reference
< XControlModel
>& xModel
, const Reference
< XControl
>& xControl
,
364 const Sequence
< ScriptEventDescriptor
>& rTransferIfAvailable
)
366 // first check if we have a XEventAttacherManager for the model
367 Reference
< XChild
> xModelChild(xModel
, UNO_QUERY
);
368 if (!xModelChild
.is())
369 return; // nothing to do
371 Reference
< XEventAttacherManager
> xEventManager(xModelChild
->getParent(), UNO_QUERY
);
372 if (!xEventManager
.is())
373 return; // nothing to do
375 if (!rTransferIfAvailable
.getLength())
376 return; // nothing to do
378 // check for the index of the model within it's parent
379 Reference
< XIndexAccess
> xParentIndex(xModelChild
->getParent(), UNO_QUERY
);
380 if (!xParentIndex
.is())
381 return; // nothing to do
382 sal_Int32 nIndex
= getElementPos(xParentIndex
, xModel
);
383 if (nIndex
<0 || nIndex
>=xParentIndex
->getCount())
384 return; // nothing to do
386 // then we need informations about the listeners supported by the control and the model
387 Sequence
< Type
> aModelListeners
;
388 Sequence
< Type
> aControlListeners
;
390 Reference
< XIntrospection
> xModelIntrospection(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString("com.sun.star.beans.Introspection")), UNO_QUERY
);
391 Reference
< XIntrospection
> xControlIntrospection(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString("com.sun.star.beans.Introspection")), UNO_QUERY
);
393 if (xModelIntrospection
.is() && xModel
.is())
395 Any
aModel(makeAny(xModel
));
396 aModelListeners
= xModelIntrospection
->inspect(aModel
)->getSupportedListeners();
399 if (xControlIntrospection
.is() && xControl
.is())
401 Any
aControl(makeAny(xControl
));
402 aControlListeners
= xControlIntrospection
->inspect(aControl
)->getSupportedListeners();
405 sal_Int32 nMaxNewLen
= aModelListeners
.getLength() + aControlListeners
.getLength();
407 return; // the model and the listener don't support any listeners (or we were unable to retrieve these infos)
409 Sequence
< ScriptEventDescriptor
> aTransferable(nMaxNewLen
);
410 ScriptEventDescriptor
* pTransferable
= aTransferable
.getArray();
412 const ScriptEventDescriptor
* pCurrent
= rTransferIfAvailable
.getConstArray();
414 for (i
=0; i
<rTransferIfAvailable
.getLength(); ++i
, ++pCurrent
)
416 // search the model/control idl classes for the event described by pCurrent
417 for ( Sequence
< Type
>* pCurrentArray
= &aModelListeners
;
419 pCurrentArray
= (pCurrentArray
== &aModelListeners
) ? &aControlListeners
: NULL
422 const Type
* pCurrentListeners
= pCurrentArray
->getConstArray();
423 for (j
=0; j
<pCurrentArray
->getLength(); ++j
, ++pCurrentListeners
)
425 rtl::OUString aListener
= (*pCurrentListeners
).getTypeName();
426 sal_Int32 nTokens
= comphelper::string::getTokenCount(aListener
, '.');
428 aListener
= comphelper::string::getToken(aListener
, nTokens
- 1, '.');
430 if (aListener
== pCurrent
->ListenerType
.getStr())
431 // the current ScriptEventDescriptor doesn't match the current listeners class
434 // now check the methods
435 Sequence
< ::rtl::OUString
> aMethodsNames
= ::comphelper::getEventMethodsForType(*pCurrentListeners
);
437 const ::rtl::OUString
* pMethodsNames
= aMethodsNames
.getConstArray();
438 for (k
=0; k
<aMethodsNames
.getLength(); ++k
, ++pMethodsNames
)
440 if ((*pMethodsNames
).compareTo(pCurrent
->EventMethod
) != COMPARE_EQUAL
)
441 // the current ScriptEventDescriptor doesn't match the current listeners current method
444 // we can transfer the script event : the model (control) supports it
445 *pTransferable
= *pCurrent
;
449 if (k
<aMethodsNames
.getLength())
455 sal_Int32 nRealNewLen
= pTransferable
- aTransferable
.getArray();
456 aTransferable
.realloc(nRealNewLen
);
458 xEventManager
->registerScriptEvents(nIndex
, aTransferable
);
461 //------------------------------------------------------------------------------
462 ::rtl::OUString
getServiceNameByControlType(sal_Int16 nType
)
466 case OBJ_FM_EDIT
: return FM_COMPONENT_TEXTFIELD
;
467 case OBJ_FM_BUTTON
: return FM_COMPONENT_COMMANDBUTTON
;
468 case OBJ_FM_FIXEDTEXT
: return FM_COMPONENT_FIXEDTEXT
;
469 case OBJ_FM_LISTBOX
: return FM_COMPONENT_LISTBOX
;
470 case OBJ_FM_CHECKBOX
: return FM_COMPONENT_CHECKBOX
;
471 case OBJ_FM_RADIOBUTTON
: return FM_COMPONENT_RADIOBUTTON
;
472 case OBJ_FM_GROUPBOX
: return FM_COMPONENT_GROUPBOX
;
473 case OBJ_FM_COMBOBOX
: return FM_COMPONENT_COMBOBOX
;
474 case OBJ_FM_GRID
: return FM_COMPONENT_GRIDCONTROL
;
475 case OBJ_FM_IMAGEBUTTON
: return FM_COMPONENT_IMAGEBUTTON
;
476 case OBJ_FM_FILECONTROL
: return FM_COMPONENT_FILECONTROL
;
477 case OBJ_FM_DATEFIELD
: return FM_COMPONENT_DATEFIELD
;
478 case OBJ_FM_TIMEFIELD
: return FM_COMPONENT_TIMEFIELD
;
479 case OBJ_FM_NUMERICFIELD
: return FM_COMPONENT_NUMERICFIELD
;
480 case OBJ_FM_CURRENCYFIELD
: return FM_COMPONENT_CURRENCYFIELD
;
481 case OBJ_FM_PATTERNFIELD
: return FM_COMPONENT_PATTERNFIELD
;
482 case OBJ_FM_HIDDEN
: return FM_COMPONENT_HIDDENCONTROL
;
483 case OBJ_FM_IMAGECONTROL
: return FM_COMPONENT_IMAGECONTROL
;
484 case OBJ_FM_FORMATTEDFIELD
: return FM_COMPONENT_FORMATTEDFIELD
;
485 case OBJ_FM_SCROLLBAR
: return FM_SUN_COMPONENT_SCROLLBAR
;
486 case OBJ_FM_SPINBUTTON
: return FM_SUN_COMPONENT_SPINBUTTON
;
487 case OBJ_FM_NAVIGATIONBAR
: return FM_SUN_COMPONENT_NAVIGATIONBAR
;
489 return ::rtl::OUString();
494 //------------------------------------------------------------------------------
495 // check if the control has one of the interfaces we can use for searching
496 // *_pCurrentText will be filled with the current text of the control (as used when searching this control)
497 sal_Bool
IsSearchableControl( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _rxControl
,
498 ::rtl::OUString
* _pCurrentText
)
500 if ( !_rxControl
.is() )
503 Reference
< XTextComponent
> xAsText( _rxControl
, UNO_QUERY
);
507 *_pCurrentText
= xAsText
->getText();
511 Reference
< XListBox
> xListBox( _rxControl
, UNO_QUERY
);
515 *_pCurrentText
= xListBox
->getSelectedItem();
519 Reference
< XCheckBox
> xCheckBox( _rxControl
, UNO_QUERY
);
520 if ( xCheckBox
.is() )
524 switch ( (TriState
)xCheckBox
->getState() )
526 case STATE_NOCHECK
: *_pCurrentText
= ::rtl::OUString("0" ); break;
527 case STATE_CHECK
: *_pCurrentText
= ::rtl::OUString("1" ); break;
528 default: *_pCurrentText
= ::rtl::OUString(); break;
537 //------------------------------------------------------------------------------
538 sal_Bool
FmXBoundFormFieldIterator::ShouldStepInto(const Reference
< XInterface
>& _rContainer
) const
540 if (_rContainer
== m_xStartingPoint
)
541 // would be quite stupid to step over the root ....
544 return Reference
< XControlModel
>(_rContainer
, UNO_QUERY
).is();
547 //------------------------------------------------------------------------------
548 sal_Bool
FmXBoundFormFieldIterator::ShouldHandleElement(const Reference
< XInterface
>& _rElement
)
554 if (Reference
< XForm
>(_rElement
, UNO_QUERY
).is() || Reference
< XGrid
>(_rElement
, UNO_QUERY
).is())
558 Reference
< XPropertySet
> xSet(_rElement
, UNO_QUERY
);
559 if (!xSet
.is() || !::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xSet
))
560 // no "BoundField" property
563 Any
aVal( xSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) );
564 if (aVal
.getValueTypeClass() != TypeClass_INTERFACE
)
565 // void or invalid property value
568 return aVal
.hasValue();
571 //------------------------------------------------------------------------------
572 sal_Bool
isControlList(const SdrMarkList
& rMarkList
)
574 // enthaelt die liste nur Controls und mindestens ein control
575 sal_uInt32 nMarkCount
= rMarkList
.GetMarkCount();
576 sal_Bool bControlList
= nMarkCount
!= 0;
578 sal_Bool bHadAnyLeafs
= sal_False
;
580 for (sal_uInt32 i
= 0; i
< nMarkCount
&& bControlList
; i
++)
582 SdrObject
*pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
583 E3dObject
* pAs3DObject
= PTR_CAST(E3dObject
, pObj
);
584 // E3dObject's do not contain any 2D-objects (by definition)
585 // we need this extra check here : an E3dObject->IsGroupObject says "YES", but an SdrObjListIter working
586 // with an E3dObject doesn't give me any Nodes (E3dObject has a sub list, but no members in that list,
587 // cause there implementation differs from the one of "normal" SdrObject's. Unfortunally SdrObject::IsGroupObject
588 // doesn't check the element count of the sub list, which is simply a bug in IsGroupObject we can't fix at the moment).
589 // So at the end of this function bControlList would have the same value it was initialized with above : sal_True
590 // And this would be wrong :)
591 // 03.02.00 - 72529 - FS
594 if (pObj
->IsGroupObject())
596 SdrObjListIter
aIter(*pObj
->GetSubList());
597 while (aIter
.IsMore() && bControlList
)
599 bControlList
= FmFormInventor
== aIter
.Next()->GetObjInventor();
600 bHadAnyLeafs
= sal_True
;
605 bHadAnyLeafs
= sal_True
;
606 bControlList
= FmFormInventor
== pObj
->GetObjInventor();
611 return bControlList
&& bHadAnyLeafs
;
614 //------------------------------------------------------------------------
615 Reference
< XForm
> GetForm(const Reference
< XInterface
>& _rxElement
)
617 Reference
< XForm
> xForm( _rxElement
, UNO_QUERY
);
621 Reference
< XChild
> xChild( _rxElement
, UNO_QUERY
);
623 return GetForm( xChild
->getParent() );
625 return Reference
< XForm
>();
628 //========================================================================
629 // class FmXFormShell_Base_Disambiguation
630 //========================================================================
631 FmXFormShell_Base_Disambiguation::FmXFormShell_Base_Disambiguation( ::osl::Mutex
& _rMutex
)
632 :FmXFormShell_BD_BASE( _rMutex
)
636 void SAL_CALL
FmXFormShell_Base_Disambiguation::disposing()
638 WeakComponentImplHelperBase::disposing();
641 // Normally it should be sufficient to call the "disposing" of our direct
642 // base class, but SUN PRO 5 does not like this and claims there is a conflict
643 // with the XEventListener::disposing(EventObject) of our various listener
647 //========================================================================
648 // class FmXFormShell
649 //========================================================================
650 DBG_NAME(FmXFormShell
);
651 //------------------------------------------------------------------------
652 FmXFormShell::FmXFormShell( FmFormShell
& _rShell
, SfxViewFrame
* _pViewFrame
)
653 :FmXFormShell_BASE(m_aMutex
)
654 ,FmXFormShell_CFGBASE(::rtl::OUString("Office.Common/Misc"), CONFIG_MODE_DELAYED_UPDATE
)
655 ,m_eNavigate( NavigationBarMode_NONE
)
656 ,m_nInvalidationEvent( 0 )
657 ,m_nActivationEvent( 0 )
658 ,m_pShell( &_rShell
)
659 ,m_pTextShell( new ::svx::FmTextControlShell( _pViewFrame
) )
660 ,m_aActiveControllerFeatures( ::comphelper::getProcessServiceFactory(), this )
661 ,m_aNavControllerFeatures( ::comphelper::getProcessServiceFactory(), this )
662 ,m_eDocumentType( eUnknownDocumentType
)
663 ,m_nLockSlotInvalidation( 0 )
664 ,m_bHadPropertyBrowserInDesignMode( sal_False
)
665 ,m_bTrackProperties( sal_True
)
666 ,m_bUseWizards( sal_True
)
667 ,m_bDatabaseBar( sal_False
)
668 ,m_bInActivate( sal_False
)
669 ,m_bSetFocus( sal_False
)
670 ,m_bFilterMode( sal_False
)
671 ,m_bChangingDesignMode( sal_False
)
672 ,m_bPreparedClose( sal_False
)
673 ,m_bFirstActivation( sal_True
)
675 DBG_CTOR(FmXFormShell
,NULL
);
676 m_aMarkTimer
.SetTimeout(100);
677 m_aMarkTimer
.SetTimeoutHdl(LINK(this,FmXFormShell
,OnTimeOut
));
680 m_xAttachedFrame
= _pViewFrame
->GetFrame().GetFrameInterface();
682 // to prevent deletion of this we acquire our refcounter once
683 ::comphelper::increment(FmXFormShell_BASE::m_refCount
);
685 // correct the refcounter
686 ::comphelper::decrement(FmXFormShell_BASE::m_refCount
);
688 // cache the current configuration settings we're interested in
689 implAdjustConfigCache();
690 // and register for changes on this settings
691 Sequence
< ::rtl::OUString
> aNames(1);
692 aNames
[0] = ::rtl::OUString("FormControlPilotsEnabled");
693 EnableNotification(aNames
);
696 //------------------------------------------------------------------------
697 FmXFormShell::~FmXFormShell()
700 DBG_DTOR(FmXFormShell
,NULL
);
703 //------------------------------------------------------------------
704 Reference
< XModel
> FmXFormShell::getContextDocument() const
706 Reference
< XModel
> xModel
;
708 // determine the type of document we live in
711 Reference
< XController
> xController
;
712 if ( m_xAttachedFrame
.is() )
713 xController
= m_xAttachedFrame
->getController();
714 if ( xController
.is() )
715 xModel
= xController
->getModel();
717 catch( const Exception
& )
719 DBG_UNHANDLED_EXCEPTION();
724 //------------------------------------------------------------------
725 bool FmXFormShell::isEnhancedForm() const
727 return getDocumentType() == eEnhancedForm
;
730 //------------------------------------------------------------------
731 bool FmXFormShell::impl_checkDisposed() const
735 OSL_FAIL( "FmXFormShell::impl_checkDisposed: already disposed!" );
741 //------------------------------------------------------------------
742 ::svxform::DocumentType
FmXFormShell::getDocumentType() const
744 if ( m_eDocumentType
!= eUnknownDocumentType
)
745 return m_eDocumentType
;
747 // determine the type of document we live in
748 Reference
< XModel
> xModel
= getContextDocument();
750 m_eDocumentType
= DocumentClassification::classifyDocument( xModel
);
753 OSL_FAIL( "FmXFormShell::getDocumentType: can't determine the document type!" );
754 m_eDocumentType
= eTextDocument
;
755 // fallback, just to have a defined state
758 return m_eDocumentType
;
761 //------------------------------------------------------------------
762 bool FmXFormShell::IsReadonlyDoc() const
764 if ( impl_checkDisposed() )
767 FmFormModel
* pModel
= m_pShell
->GetFormModel();
768 if ( pModel
&& pModel
->GetObjectShell() )
769 return pModel
->GetObjectShell()->IsReadOnly() || pModel
->GetObjectShell()->IsReadOnlyUI();
773 //------------------------------------------------------------------
774 Any SAL_CALL
FmXFormShell::queryInterface( const Type
& type
) throw ( RuntimeException
)
776 return FmXFormShell_BASE::queryInterface(type
);
778 //------------------------------------------------------------------------------
779 Sequence
< Type
> SAL_CALL
FmXFormShell::getTypes( ) throw(RuntimeException
)
781 return FmXFormShell_BASE::getTypes();
783 //------------------------------------------------------------------------------
784 Sequence
< sal_Int8
> SAL_CALL
FmXFormShell::getImplementationId() throw(RuntimeException
)
786 static ::cppu::OImplementationId
* pId
= 0;
789 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
792 static ::cppu::OImplementationId aId
;
796 return pId
->getImplementationId();
799 //------------------------------------------------------------------------------
800 void SAL_CALL
FmXFormShell::disposing(const EventObject
& e
) throw( RuntimeException
)
802 impl_checkDisposed();
804 if (m_xActiveController
== e
.Source
)
806 // wird der Controller freigeben dann alles loslassen
808 m_xActiveForm
= NULL
;
809 m_xActiveController
= NULL
;
810 m_xNavigationController
= NULL
;
812 m_aActiveControllerFeatures
.dispose();
813 m_aNavControllerFeatures
.dispose();
816 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
819 if (e
.Source
== m_xExternalViewController
)
821 Reference
< runtime::XFormController
> xFormController( m_xExternalViewController
, UNO_QUERY
);
822 OSL_ENSURE( xFormController
.is(), "FmXFormShell::disposing: invalid external view controller!" );
823 if (xFormController
.is())
824 xFormController
->removeActivateListener((XFormControllerListener
*)this);
826 Reference
< ::com::sun::star::lang::XComponent
> xComp(m_xExternalViewController
, UNO_QUERY
);
828 xComp
->removeEventListener((XEventListener
*)(XPropertyChangeListener
*)this);
830 m_xExternalViewController
= NULL
;
831 m_xExternalDisplayedForm
= NULL
;
832 m_xExtViewTriggerController
= NULL
;
834 InvalidateSlot( SID_FM_VIEW_AS_GRID
, sal_False
);
838 //------------------------------------------------------------------------------
839 void SAL_CALL
FmXFormShell::propertyChange(const PropertyChangeEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
)
841 if ( impl_checkDisposed() )
844 if (evt
.PropertyName
== FM_PROP_ROWCOUNT
)
846 // Das gleich folgenden Update erzwingt ein Neu-Painten der entsprechenden Slots. Wenn ich mich aber hier nicht
847 // in dem HauptThread der Applikation befinde (weil zum Beispiel ein Cursor gerade Datensaetze zaehlt und mir dabei
848 // immer diese PropertyChanges beschert), kann sich das mit en normalen Paints im HauptThread der Applikation beissen.
849 // (Solche Paints passieren zum Beispiel, wenn man einfach nur eine andere Applikation ueber das Office legt und wieder
851 // Deshalb die Benutzung des SolarMutex, der sichert das ab.
852 ::osl::SolarMutex
& rSolarSafety
= Application::GetSolarMutex();
853 if (rSolarSafety
.tryToAcquire())
855 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_RECORD_TOTAL
, sal_True
, sal_False
);
856 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Update(SID_FM_RECORD_TOTAL
);
857 rSolarSafety
.release();
861 // with the following the slot is invalidated asynchron
862 LockSlotInvalidation(sal_True
);
863 InvalidateSlot(SID_FM_RECORD_TOTAL
, sal_False
);
864 LockSlotInvalidation(sal_False
);
868 // this may be called from a non-main-thread so invalidate the shell asynchronously
869 LockSlotInvalidation(sal_True
);
870 InvalidateSlot(0, 0); // special meaning : invalidate m_pShell
871 LockSlotInvalidation(sal_False
);
874 //------------------------------------------------------------------------------
875 void FmXFormShell::invalidateFeatures( const ::std::vector
< sal_Int32
>& _rFeatures
)
877 if ( impl_checkDisposed() )
880 OSL_ENSURE( _rFeatures
.size() > 0, "FmXFormShell::invalidateFeatures: invalid arguments!" );
882 if ( m_pShell
->GetViewShell() && m_pShell
->GetViewShell()->GetViewFrame() )
884 // unfortunately, SFX requires sal_uInt16
885 ::std::vector
< sal_uInt16
> aSlotIds
;
886 aSlotIds
.reserve( _rFeatures
.size() );
887 ::std::copy( _rFeatures
.begin(),
889 ::std::insert_iterator
< ::std::vector
< sal_uInt16
> >( aSlotIds
, aSlotIds
.begin() )
892 // furthermore, SFX wants a terminating 0
893 aSlotIds
.push_back( 0 );
895 // and, last but not least, SFX wants the ids to be sorted
896 ::std::sort( aSlotIds
.begin(), aSlotIds
.end() - 1 );
898 sal_uInt16
*pSlotIds
= aSlotIds
.empty() ? 0 : &(aSlotIds
[0]);
899 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( pSlotIds
);
903 //------------------------------------------------------------------------------
904 void SAL_CALL
FmXFormShell::formActivated(const EventObject
& rEvent
) throw( RuntimeException
)
906 if ( impl_checkDisposed() )
909 Reference
< runtime::XFormController
> xController( rEvent
.Source
, UNO_QUERY_THROW
);
910 m_pTextShell
->formActivated( xController
);
911 setActiveController( xController
);
914 //------------------------------------------------------------------------------
915 void SAL_CALL
FmXFormShell::formDeactivated(const EventObject
& rEvent
) throw( RuntimeException
)
917 if ( impl_checkDisposed() )
920 Reference
< runtime::XFormController
> xController( rEvent
.Source
, UNO_QUERY_THROW
);
921 m_pTextShell
->formDeactivated( xController
);
924 //------------------------------------------------------------------------------
925 void FmXFormShell::disposing()
927 impl_checkDisposed();
929 FmXFormShell_BASE::disposing();
931 if ( m_pShell
&& !m_pShell
->IsDesignMode() )
932 setActiveController( NULL
, sal_True
);
933 // do NOT save the content of the old form (the second parameter tells this)
934 // if we're here, then we expect that PrepareClose has been called, and thus the user
935 // got a chance to commit or reject any changes. So in case we're here and there
936 // are still uncommitted changes, the user explicitly wanted this.
938 m_pTextShell
->dispose();
940 m_xAttachedFrame
= NULL
;
942 CloseExternalFormViewer();
944 while ( m_aLoadingPages
.size() )
946 Application::RemoveUserEvent( m_aLoadingPages
.front().nEventId
);
947 m_aLoadingPages
.pop();
951 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
952 if (m_nInvalidationEvent
)
954 Application::RemoveUserEvent(m_nInvalidationEvent
);
955 m_nInvalidationEvent
= 0;
957 if ( m_nActivationEvent
)
959 Application::RemoveUserEvent( m_nActivationEvent
);
960 m_nActivationEvent
= 0;
965 ::osl::ClearableMutexGuard
aGuard(m_aAsyncSafety
);
968 DBG_ASSERT(!m_nInvalidationEvent
, "FmXFormShell::~FmXFormShell : still have an invalidation event !");
969 // should habe been deleted while beeing disposed
974 DisableNotification();
976 RemoveElement( m_xForms
);
979 impl_switchActiveControllerListening( false );
980 m_xActiveController
= NULL
;
981 m_xActiveForm
= NULL
;
984 m_xNavigationController
= NULL
;
985 m_xCurrentForm
= NULL
;
986 m_xLastGridFound
= NULL
;
987 m_xAttachedFrame
= NULL
;
988 m_xExternalViewController
= NULL
;
989 m_xExtViewTriggerController
= NULL
;
990 m_xExternalDisplayedForm
= NULL
;
991 m_xLastGridFound
= NULL
;
994 m_aCurrentSelection
.swap( aEmpty
);
996 m_aActiveControllerFeatures
.dispose();
997 m_aNavControllerFeatures
.dispose();
1000 //------------------------------------------------------------------------------
1001 void FmXFormShell::UpdateSlot( sal_Int16 _nId
)
1003 if ( impl_checkDisposed() )
1006 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
1008 if ( m_nLockSlotInvalidation
)
1010 OSL_FAIL( "FmXFormShell::UpdateSlot: cannot update if invalidation is currently locked!" );
1011 InvalidateSlot( _nId
, sal_False
);
1015 OSL_ENSURE( _nId
, "FmXFormShell::UpdateSlot: can't update the complete shell!" );
1016 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( _nId
, sal_True
, sal_True
);
1017 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Update( _nId
);
1021 //------------------------------------------------------------------------------
1022 void FmXFormShell::InvalidateSlot( sal_Int16 nId
, sal_Bool bWithId
)
1024 if ( impl_checkDisposed() )
1027 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
1028 if (m_nLockSlotInvalidation
)
1030 sal_uInt8 nFlags
= ( bWithId
? 0x01 : 0 );
1031 m_arrInvalidSlots
.push_back( InvalidSlotInfo(nId
, nFlags
) );
1035 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(nId
, sal_True
, bWithId
);
1037 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
1040 //------------------------------------------------------------------------------
1041 void FmXFormShell::LockSlotInvalidation(sal_Bool bLock
)
1043 if ( impl_checkDisposed() )
1046 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
1047 DBG_ASSERT(bLock
|| m_nLockSlotInvalidation
>0, "FmXFormShell::LockSlotInvalidation : invalid call !");
1050 ++m_nLockSlotInvalidation
;
1051 else if (!--m_nLockSlotInvalidation
)
1053 // alles, was sich waehrend der gelockten Phase angesammelt hat, (asynchron) invalidieren
1054 if (!m_nInvalidationEvent
)
1055 m_nInvalidationEvent
= Application::PostUserEvent(LINK(this, FmXFormShell
, OnInvalidateSlots
));
1059 //------------------------------------------------------------------------------
1060 IMPL_LINK_NOARG(FmXFormShell
, OnInvalidateSlots
)
1062 if ( impl_checkDisposed() )
1065 ::osl::MutexGuard
aGuard(m_aInvalidationSafety
);
1066 m_nInvalidationEvent
= 0;
1068 for (std::vector
<InvalidSlotInfo
>::const_iterator i
= m_arrInvalidSlots
.begin(); i
< m_arrInvalidSlots
.end(); ++i
)
1071 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(i
->id
, sal_True
, (i
->flags
& 0x01));
1073 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
1075 m_arrInvalidSlots
.clear();
1079 //------------------------------------------------------------------------------
1080 void FmXFormShell::ForceUpdateSelection(sal_Bool bAllowInvalidation
)
1082 if ( impl_checkDisposed() )
1085 if (IsSelectionUpdatePending())
1087 m_aMarkTimer
.Stop();
1089 // die Invalidierung der Slots, die implizit von SetSelection besorgt wird, eventuell abschalten
1090 if (!bAllowInvalidation
)
1091 LockSlotInvalidation(sal_True
);
1093 SetSelection(m_pShell
->GetFormView()->GetMarkedObjectList());
1095 if (!bAllowInvalidation
)
1096 LockSlotInvalidation(sal_False
);
1100 //------------------------------------------------------------------------------
1101 PopupMenu
* FmXFormShell::GetConversionMenu()
1104 PopupMenu
* pNewMenu
= new PopupMenu(SVX_RES( RID_FMSHELL_CONVERSIONMENU
));
1106 ImageList
aImageList( SVX_RES( RID_SVXIMGLIST_FMEXPL
) );
1107 for ( size_t i
= 0; i
< sizeof (nConvertSlots
) / sizeof (nConvertSlots
[0]); ++i
)
1109 // das entsprechende Image dran
1110 pNewMenu
->SetItemImage(nConvertSlots
[i
], aImageList
.GetImage(nCreateSlots
[i
]));
1116 //------------------------------------------------------------------------------
1117 bool FmXFormShell::isControlConversionSlot( sal_uInt16 nSlotId
)
1119 for ( size_t i
= 0; i
< sizeof (nConvertSlots
) / sizeof (nConvertSlots
[0]); ++i
)
1120 if (nConvertSlots
[i
] == nSlotId
)
1125 //------------------------------------------------------------------------------
1126 bool FmXFormShell::executeControlConversionSlot( sal_uInt16 _nSlotId
)
1128 OSL_PRECOND( canConvertCurrentSelectionToControl( _nSlotId
), "FmXFormShell::executeControlConversionSlot: illegal call!" );
1129 InterfaceBag::const_iterator aSelectedElement
= m_aCurrentSelection
.begin();
1130 if ( aSelectedElement
== m_aCurrentSelection
.end() )
1133 return executeControlConversionSlot( Reference
< XFormComponent
>( *aSelectedElement
, UNO_QUERY
), _nSlotId
);
1136 //------------------------------------------------------------------------------
1137 bool FmXFormShell::executeControlConversionSlot( const Reference
< XFormComponent
>& _rxObject
, sal_uInt16 _nSlotId
)
1139 if ( impl_checkDisposed() )
1142 OSL_ENSURE( _rxObject
.is(), "FmXFormShell::executeControlConversionSlot: invalid object!" );
1143 if ( !_rxObject
.is() )
1146 SdrPage
* pPage
= m_pShell
->GetCurPage();
1147 FmFormPage
* pFormPage
= pPage
? dynamic_cast< FmFormPage
* >( pPage
) : NULL
;
1148 OSL_ENSURE( pFormPage
, "FmXFormShell::executeControlConversionSlot: no current (form) page!" );
1152 OSL_ENSURE( isSolelySelected( _rxObject
),
1153 "FmXFormShell::executeControlConversionSlot: hmm ... shouldn't this parameter be redundant?" );
1155 for ( size_t lookupSlot
= 0; lookupSlot
< sizeof( nConvertSlots
) / sizeof( nConvertSlots
[0] ); ++lookupSlot
)
1157 if (nConvertSlots
[lookupSlot
] == _nSlotId
)
1159 Reference
< XInterface
> xNormalizedObject( _rxObject
, UNO_QUERY
);
1161 FmFormObj
* pFormObject
= NULL
;
1162 SdrObjListIter
aPageIter( *pFormPage
);
1163 while ( aPageIter
.IsMore() )
1165 SdrObject
* pCurrent
= aPageIter
.Next();
1166 pFormObject
= FmFormObj::GetFormObject( pCurrent
);
1170 Reference
< XInterface
> xCurrentNormalized( pFormObject
->GetUnoControlModel(), UNO_QUERY
);
1171 if ( xCurrentNormalized
.get() == xNormalizedObject
.get() )
1180 ::rtl::OUString
sNewName( getServiceNameByControlType( nObjectTypes
[ lookupSlot
] ) );
1181 Reference
< XControlModel
> xNewModel( ::comphelper::getProcessServiceFactory()->createInstance( sNewName
), UNO_QUERY
);
1182 if (!xNewModel
.is())
1185 Reference
< XControlModel
> xOldModel( pFormObject
->GetUnoControlModel() );
1186 Reference
< XServiceInfo
> xModelInfo(xOldModel
, UNO_QUERY
);
1188 // Properties uebertragen
1189 Reference
< XPropertySet
> xOldSet(xOldModel
, UNO_QUERY
);
1190 Reference
< XPropertySet
> xNewSet(xNewModel
, UNO_QUERY
);
1193 Locale aNewLanguage
= Application::GetSettings().GetUILocale();
1194 TransferFormComponentProperties(xOldSet
, xNewSet
, aNewLanguage
);
1196 Sequence
< ::com::sun::star::script::ScriptEventDescriptor
> aOldScripts
;
1197 Reference
< XChild
> xChild(xOldModel
, UNO_QUERY
);
1200 Reference
< XIndexAccess
> xParent(xChild
->getParent(), UNO_QUERY
);
1202 // remember old script events
1203 Reference
< ::com::sun::star::script::XEventAttacherManager
> xEvManager(xChild
->getParent(), UNO_QUERY
);
1204 if (xParent
.is() && xEvManager
.is())
1206 sal_Int32 nIndex
= getElementPos(xParent
, xOldModel
);
1207 if (nIndex
>=0 && nIndex
<xParent
->getCount())
1208 aOldScripts
= xEvManager
->getScriptEvents(nIndex
);
1211 // replace the mdoel within the parent container
1212 Reference
< XIndexContainer
> xIndexParent(xChild
->getParent(), UNO_QUERY
);
1213 if (xIndexParent
.is())
1215 // the form container works with FormComponents
1216 Reference
< XFormComponent
> xComponent(xNewModel
, UNO_QUERY
);
1217 DBG_ASSERT(xComponent
.is(), "FmXFormShell::executeControlConversionSlot: the new model is no form component !");
1218 Any
aNewModel(makeAny(xComponent
));
1222 sal_Int32 nIndex
= getElementPos(xParent
, xOldModel
);
1223 if (nIndex
>=0 && nIndex
<xParent
->getCount())
1224 xIndexParent
->replaceByIndex(nIndex
, aNewModel
);
1227 OSL_FAIL("FmXFormShell::executeControlConversionSlot: could not replace the model !");
1228 Reference
< ::com::sun::star::lang::XComponent
> xNewComponent(xNewModel
, UNO_QUERY
);
1229 if (xNewComponent
.is())
1230 xNewComponent
->dispose();
1236 OSL_FAIL("FmXFormShell::executeControlConversionSlot: could not replace the model !");
1237 Reference
< ::com::sun::star::lang::XComponent
> xNewComponent(xNewModel
, UNO_QUERY
);
1238 if (xNewComponent
.is())
1239 xNewComponent
->dispose();
1246 // special handling for the LabelControl-property : can only be set when the model is placed
1247 // within the forms hierarchy
1248 if (::comphelper::hasProperty(FM_PROP_CONTROLLABEL
, xOldSet
) && ::comphelper::hasProperty(FM_PROP_CONTROLLABEL
, xNewSet
))
1252 xNewSet
->setPropertyValue(FM_PROP_CONTROLLABEL
, xOldSet
->getPropertyValue(FM_PROP_CONTROLLABEL
));
1260 // neues Model setzen
1261 pFormObject
->SetChanged();
1262 pFormObject
->SetUnoControlModel(xNewModel
);
1264 // transfer script events
1265 // (do this _after_ SetUnoControlModel as we need the new (implicitly created) control)
1266 if (aOldScripts
.getLength())
1268 // das Control zum Model suchen
1269 Reference
< XControlContainer
> xControlContainer( getControlContainerForView() );
1271 Sequence
< Reference
< XControl
> > aControls( xControlContainer
->getControls() );
1272 const Reference
< XControl
>* pControls
= aControls
.getConstArray();
1274 sal_uInt32 nLen
= aControls
.getLength();
1275 Reference
< XControl
> xControl
;
1276 for (sal_uInt32 i
=0 ; i
<nLen
; ++i
)
1278 if (pControls
[i
]->getModel() == xNewModel
)
1280 xControl
= pControls
[i
];
1284 TransferEventScripts(xNewModel
, xControl
, aOldScripts
);
1287 // transfer value bindings, if possible
1289 Reference
< XBindableValue
> xOldBindable( xOldModel
, UNO_QUERY
);
1290 Reference
< XBindableValue
> xNewBindable( xNewModel
, UNO_QUERY
);
1291 if ( xOldBindable
.is() )
1295 if ( xNewBindable
.is() )
1296 xNewBindable
->setValueBinding( xOldBindable
->getValueBinding() );
1297 xOldBindable
->setValueBinding( NULL
);
1299 catch(const Exception
&)
1301 DBG_UNHANDLED_EXCEPTION();
1305 // same for list entry sources
1307 Reference
< XListEntrySink
> xOldSink( xOldModel
, UNO_QUERY
);
1308 Reference
< XListEntrySink
> xNewSink( xNewModel
, UNO_QUERY
);
1309 if ( xOldSink
.is() )
1313 if ( xNewSink
.is() )
1314 xNewSink
->setListEntrySource( xOldSink
->getListEntrySource() );
1315 xOldSink
->setListEntrySource( NULL
);
1317 catch(const Exception
&)
1319 DBG_UNHANDLED_EXCEPTION();
1324 // create an undo action
1325 FmFormModel
* pModel
= m_pShell
->GetFormModel();
1326 DBG_ASSERT(pModel
!= NULL
, "FmXFormShell::executeControlConversionSlot: my shell has no model !");
1327 if (pModel
&& pModel
->IsUndoEnabled() )
1329 pModel
->AddUndo(new FmUndoModelReplaceAction(*pModel
, pFormObject
, xOldModel
));
1333 FmUndoModelReplaceAction::DisposeElement( xOldModel
);
1342 //------------------------------------------------------------------------------
1343 bool FmXFormShell::canConvertCurrentSelectionToControl( sal_Int16 nConversionSlot
)
1345 if ( m_aCurrentSelection
.empty() )
1348 InterfaceBag::const_iterator aCheck
= m_aCurrentSelection
.begin();
1349 Reference
< XServiceInfo
> xElementInfo( *aCheck
, UNO_QUERY
);
1350 if ( !xElementInfo
.is() )
1351 // no service info -> cannot determine this
1354 if ( ++aCheck
!= m_aCurrentSelection
.end() )
1355 // more than one element
1358 if ( Reference
< XForm
>::query( xElementInfo
).is() )
1362 sal_Int16 nObjectType
= getControlTypeByObject( xElementInfo
);
1364 if ( ( OBJ_FM_HIDDEN
== nObjectType
)
1365 || ( OBJ_FM_CONTROL
== nObjectType
)
1366 || ( OBJ_FM_GRID
== nObjectType
)
1368 return false; // those types cannot be converted
1370 DBG_ASSERT(sizeof(nConvertSlots
)/sizeof(nConvertSlots
[0]) == sizeof(nObjectTypes
)/sizeof(nObjectTypes
[0]),
1371 "FmXFormShell::canConvertCurrentSelectionToControl: nConvertSlots & nObjectTypes must have the same size !");
1373 for ( size_t i
= 0; i
< sizeof( nConvertSlots
) / sizeof( nConvertSlots
[0] ); ++i
)
1374 if (nConvertSlots
[i
] == nConversionSlot
)
1375 return nObjectTypes
[i
] != nObjectType
;
1377 return sal_True
; // all other slots: assume "yes"
1380 //------------------------------------------------------------------------------
1381 void FmXFormShell::checkControlConversionSlotsForCurrentSelection( Menu
& rMenu
)
1383 for (sal_Int16 i
=0; i
<rMenu
.GetItemCount(); ++i
)
1384 // der Context ist schon von einem Typ, der dem Eitnrag entspricht -> disable
1385 rMenu
.EnableItem( rMenu
.GetItemId(i
), canConvertCurrentSelectionToControl( rMenu
.GetItemId( i
) ) );
1388 //------------------------------------------------------------------------------
1389 void FmXFormShell::LoopGrids(sal_Int16 nWhat
)
1391 if ( impl_checkDisposed() )
1394 Reference
< XIndexContainer
> xControlModels(m_xActiveForm
, UNO_QUERY
);
1395 if (xControlModels
.is())
1397 for (sal_Int16 i
=0; i
<xControlModels
->getCount(); ++i
)
1399 Reference
< XPropertySet
> xModelSet
;
1400 xControlModels
->getByIndex(i
) >>= xModelSet
;
1401 if (!xModelSet
.is())
1404 if (!::comphelper::hasProperty(FM_PROP_CLASSID
, xModelSet
))
1406 sal_Int16 nClassId
= ::comphelper::getINT16(xModelSet
->getPropertyValue(FM_PROP_CLASSID
));
1407 if (FormComponentType::GRIDCONTROL
!= nClassId
)
1410 if (!::comphelper::hasProperty(FM_PROP_CURSORCOLOR
, xModelSet
) || !::comphelper::hasProperty(FM_PROP_ALWAYSSHOWCURSOR
, xModelSet
) || !::comphelper::hasProperty(FM_PROP_DISPLAYSYNCHRON
, xModelSet
))
1413 switch (nWhat
& GA_SYNC_MASK
)
1415 case GA_DISABLE_SYNC
:
1417 sal_Bool
bB(sal_False
);
1418 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, Any(&bB
,getBooleanCppuType()));
1423 Any
aOldVal( xModelSet
->getPropertyValue(FM_PROP_DISPLAYSYNCHRON
) );
1424 sal_Bool
bB(sal_True
);
1425 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, Any(&bB
,getBooleanCppuType()));
1426 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, aOldVal
);
1429 case GA_ENABLE_SYNC
:
1431 sal_Bool
bB(sal_True
);
1432 xModelSet
->setPropertyValue(FM_PROP_DISPLAYSYNCHRON
, Any(&bB
,getBooleanCppuType()));
1437 if (nWhat
& GA_DISABLE_ROCTRLR
)
1439 sal_Bool
bB(sal_False
);
1440 xModelSet
->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR
, Any(&bB
,getBooleanCppuType()));
1441 Reference
< XPropertyState
> xModelPropState(xModelSet
, UNO_QUERY
);
1442 if (xModelPropState
.is())
1443 xModelPropState
->setPropertyToDefault(FM_PROP_CURSORCOLOR
);
1445 xModelSet
->setPropertyValue(FM_PROP_CURSORCOLOR
, Any()); // this should be the default
1447 else if (nWhat
& GA_ENABLE_ROCTRLR
)
1449 sal_Bool
bB(sal_True
);
1450 xModelSet
->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR
, Any(&bB
,getBooleanCppuType()));
1451 xModelSet
->setPropertyValue(FM_PROP_CURSORCOLOR
, makeAny(sal_Int32(COL_LIGHTRED
)));
1457 //------------------------------------------------------------------------------
1458 Reference
< XControlContainer
> FmXFormShell::getControlContainerForView()
1460 if ( impl_checkDisposed() )
1463 SdrPageView
* pPageView
= NULL
;
1464 if ( m_pShell
&& m_pShell
->GetFormView() )
1465 pPageView
= m_pShell
->GetFormView()->GetSdrPageView();
1467 Reference
< XControlContainer
> xControlContainer
;
1469 xControlContainer
= pPageView
->GetPageWindow(0)->GetControlContainer();
1471 return xControlContainer
;
1474 //------------------------------------------------------------------------------
1475 void FmXFormShell::ExecuteTabOrderDialog( const Reference
< XTabControllerModel
>& _rxForForm
)
1477 if ( impl_checkDisposed() )
1480 OSL_PRECOND( _rxForForm
.is(), "FmXFormShell::ExecuteTabOrderDialog: invalid tabbing model!" );
1481 if ( !_rxForForm
.is() )
1486 Sequence
< Any
> aDialogArgs( 3 );
1487 aDialogArgs
[0] <<= NamedValue(
1488 ::rtl::OUString( "TabbingModel" ),
1489 makeAny( _rxForForm
)
1491 aDialogArgs
[1] <<= NamedValue(
1492 ::rtl::OUString( "ControlContext" ),
1493 makeAny( getControlContainerForView() )
1496 Reference
< XWindow
> xParentWindow
;
1497 if ( m_pShell
->GetViewShell() && m_pShell
->GetViewShell()->GetViewFrame() )
1498 xParentWindow
= VCLUnoHelper::GetInterface ( &m_pShell
->GetViewShell()->GetViewFrame()->GetWindow() );
1499 aDialogArgs
[2] <<= NamedValue(
1500 ::rtl::OUString( "ParentWindow" ),
1501 makeAny( xParentWindow
)
1504 Reference
< dialogs::XExecutableDialog
> xDialog(
1505 ::comphelper::getProcessServiceFactory()->createInstanceWithArguments(
1506 ::rtl::OUString( "com.sun.star.form.ui.TabOrderDialog" ),
1511 OSL_ENSURE( xDialog
.is(), "FmXFormShell::ExecuteTabOrderDialog: could not create the dialog!" );
1516 catch( const Exception
& )
1518 OSL_FAIL( "FmXFormShell::ExecuteTabOrderDialog: caught an exception!" );
1522 //------------------------------------------------------------------------------
1523 void FmXFormShell::ExecuteSearch()
1525 if ( impl_checkDisposed() )
1528 // eine Sammlung aller (logischen) Formulare
1530 m_aSearchForms
.swap( aEmpty
);
1531 ::std::vector
< String
> aContextNames
;
1532 impl_collectFormSearchContexts_nothrow( m_pShell
->GetCurPage()->GetForms(), ::rtl::OUString(), m_aSearchForms
, aContextNames
);
1533 OSL_POSTCOND( m_aSearchForms
.size() == aContextNames
.size(),
1534 "FmXFormShell::ExecuteSearch: nonsense!" );
1535 if ( m_aSearchForms
.size() != aContextNames
.size() )
1538 // filter out the forms which do not contain valid controls at all
1540 FmFormArray aValidForms
;
1541 ::std::vector
< String
> aValidContexts
;
1542 FmFormArray::const_iterator form
= m_aSearchForms
.begin();
1543 ::std::vector
< String
>::const_iterator contextName
= aContextNames
.begin();
1544 for ( ; form
!= m_aSearchForms
.end(); ++form
, ++contextName
)
1546 FmSearchContext aTestContext
;
1547 aTestContext
.nContext
= static_cast< sal_Int16
>( form
- m_aSearchForms
.begin() );
1548 sal_uInt32 nValidControls
= OnSearchContextRequest( &aTestContext
);
1549 if ( nValidControls
> 0 )
1551 aValidForms
.push_back( *form
);
1552 aValidContexts
.push_back( *contextName
);
1556 m_aSearchForms
.swap( aValidForms
);
1557 aContextNames
.swap( aValidContexts
);
1560 if (m_aSearchForms
.empty() )
1561 { // es gibt keine Controls, die alle Bedingungen fuer eine Suche erfuellen
1562 ErrorBox(NULL
, WB_OK
, SVX_RESSTR(RID_STR_NODATACONTROLS
)).Execute();
1566 // jetzt brauche ich noch einen 'initial context'
1567 sal_Int16 nInitialContext
= 0;
1568 Reference
< XForm
> xActiveForm( getActiveForm());
1569 for ( size_t i
=0; i
<m_aSearchForms
.size(); ++i
)
1571 if (m_aSearchForms
.at(i
) == xActiveForm
)
1573 nInitialContext
= (sal_Int16
)i
;
1578 // wenn der Dialog initial den Text des aktiven Controls anbieten soll, muss dieses ein XTextComponent-Interface habe,
1579 // ausserdem macht das nur Sinn, wenn das aktuelle Feld auch an ein Tabellen- (oder was-auch-immer-)Feld gebunden ist
1580 UniString strActiveField
;
1581 UniString strInitialText
;
1582 // ... das bekomme ich von meinem FormController
1583 DBG_ASSERT(m_xActiveController
.is(), "FmXFormShell::ExecuteSearch : no active controller !");
1584 Reference
< XControl
> xActiveControl( m_xActiveController
->getCurrentControl());
1585 if (xActiveControl
.is())
1587 // das Control kann mir sein Model sagen ...
1588 Reference
< XControlModel
> xActiveModel( xActiveControl
->getModel());
1589 DBG_ASSERT(xActiveModel
.is(), "FmXFormShell::ExecuteSearch : active control has no model !");
1591 // das Model frage ich nach der ControlSource-Eigenschaft ...
1592 Reference
< XPropertySet
> xProperties(xActiveControl
->getModel(), UNO_QUERY
);
1593 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE
, xProperties
) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xProperties
))
1595 Reference
< XPropertySet
> xField
;
1596 xProperties
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
1597 if (xField
.is()) // (nur wenn das Ding wirklich gebunden ist)
1599 // und das Control selber nach einem TextComponent-Interface (damit ich mir dort den Text abholen kann)
1600 Reference
< XTextComponent
> xText(xActiveControl
, UNO_QUERY
);
1603 strActiveField
= getLabelName(xProperties
).getStr();
1604 strInitialText
= xText
->getText().getStr();
1610 // das Control selber hat keine ControlSource, aber vielleicht ist es ein GridControl
1611 Reference
< XGrid
> xGrid(xActiveControl
, UNO_QUERY
);
1614 // fuer strActiveField brauche ich die die ControlSource der Column, dafuer den Columns-Container, dafuer die
1616 Reference
< XGridPeer
> xGridPeer(xActiveControl
->getPeer(), UNO_QUERY
);
1617 Reference
< XIndexAccess
> xColumns
;
1619 xColumns
= Reference
< XIndexAccess
>(xGridPeer
->getColumns(),UNO_QUERY
);
1621 sal_Int16 nViewCol
= xGrid
->getCurrentColumnPosition();
1622 sal_Int16 nModelCol
= GridView2ModelPos(xColumns
, nViewCol
);
1623 Reference
< XPropertySet
> xCurrentCol
;
1625 xColumns
->getByIndex(nModelCol
) >>= xCurrentCol
;
1626 if (xCurrentCol
.is())
1627 strActiveField
= ::comphelper::getString(xCurrentCol
->getPropertyValue(FM_PROP_LABEL
)).getStr();
1629 // the text fo the current column
1630 Reference
< XIndexAccess
> xColControls(xGridPeer
, UNO_QUERY
);
1631 Reference
< XInterface
> xCurControl
;
1632 xColControls
->getByIndex(nViewCol
) >>= xCurControl
;
1633 ::rtl::OUString sInitialText
;
1634 if (IsSearchableControl(xCurControl
, &sInitialText
))
1635 strInitialText
= sInitialText
.getStr();
1640 // um eventuelle GridControls, die ich kenne, kuemmern
1641 LoopGrids(GA_DISABLE_SYNC
/*| GA_ENABLE_ROCTRLR*/);
1643 // jetzt bin ich reif fuer den Dialog
1644 // wenn die potentiellen Deadlocks, die durch die Benutzung des Solar-Mutex in MTs VCLX...-Klasen entstehen, irgendwann mal
1645 // ausgeraeumt sind, sollte hier ein SM_USETHREAD rein, denn die Suche in einem eigenen Thread ist doch etwas fluessiger
1646 // sollte allerdings irgendwie von dem unterliegenden Cursor abhaengig gemacht werden, DAO zum Beispiel ist nicht thread-sicher
1647 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1648 AbstractFmSearchDialog
* pDialog
= NULL
;
1650 pDialog
= pFact
->CreateFmSearchDialog( &m_pShell
->GetViewShell()->GetViewFrame()->GetWindow(), strInitialText
, aContextNames
, nInitialContext
, LINK( this, FmXFormShell
, OnSearchContextRequest
) );
1651 DBG_ASSERT( pDialog
, "FmXFormShell::ExecuteSearch: could not create the search dialog!" );
1654 pDialog
->SetActiveField( strActiveField
);
1655 pDialog
->SetFoundHandler( LINK( this, FmXFormShell
, OnFoundData
) );
1656 pDialog
->SetCanceledNotFoundHdl( LINK( this, FmXFormShell
, OnCanceledNotFound
) );
1661 // GridControls wieder restaurieren
1662 LoopGrids(GA_ENABLE_SYNC
| GA_DISABLE_ROCTRLR
);
1664 m_pShell
->GetFormView()->UnMarkAll(m_pShell
->GetFormView()->GetSdrPageView());
1665 // da ich in OnFoundData (fals ich dort war) Controls markiert habe
1668 //------------------------------------------------------------------------------
1669 sal_Bool
FmXFormShell::GetY2KState(sal_uInt16
& n
)
1671 if ( impl_checkDisposed() )
1674 if (m_pShell
->IsDesignMode())
1675 // im Design-Modus (ohne aktive Controls) soll sich das Haupt-Dokument darum kuemmern
1678 Reference
< XForm
> xForm( getActiveForm());
1680 // kein aktuelles Formular (also insbesondere kein aktuelles Control) -> das Haupt-Dokument soll sich kuemmern
1683 Reference
< XRowSet
> xDB(xForm
, UNO_QUERY
);
1684 DBG_ASSERT(xDB
.is(), "FmXFormShell::GetY2KState : current form has no dbform-interface !");
1686 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats(OStaticDataAccessTools().getRowSetConnection(xDB
), sal_False
));
1689 Reference
< XPropertySet
> xSet(xSupplier
->getNumberFormatSettings());
1694 Any
aVal( xSet
->getPropertyValue(::rtl::OUString("TwoDigitDateStart")) );
1707 //------------------------------------------------------------------------------
1708 void FmXFormShell::SetY2KState(sal_uInt16 n
)
1710 if ( impl_checkDisposed() )
1713 Reference
< XForm
> xActiveForm( getActiveForm());
1714 Reference
< XRowSet
> xActiveRowSet( xActiveForm
, UNO_QUERY
);
1715 if ( xActiveRowSet
.is() )
1717 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats( getRowSetConnection( xActiveRowSet
), sal_False
) );
1720 Reference
< XPropertySet
> xSet(xSupplier
->getNumberFormatSettings());
1727 xSet
->setPropertyValue(::rtl::OUString("TwoDigitDateStart"), aVal
);
1731 OSL_FAIL("FmXFormShell::SetY2KState: Exception occurred!");
1739 // kein aktives Formular gefunden -> alle aktuell vorhandenen Formulare durchiterieren
1740 Reference
< XIndexAccess
> xCurrentForms( m_xForms
);
1741 if (!xCurrentForms
.is())
1742 { // im alive-Modus sind meine Forms nicht gesetzt, wohl aber die an der Page
1743 if (m_pShell
->GetCurPage())
1744 xCurrentForms
= Reference
< XIndexAccess
>( m_pShell
->GetCurPage()->GetForms( false ), UNO_QUERY
);
1746 if (!xCurrentForms
.is())
1749 ::comphelper::IndexAccessIterator
aIter(xCurrentForms
);
1750 Reference
< XInterface
> xCurrentElement( aIter
.Next());
1751 while (xCurrentElement
.is())
1753 // ist das aktuelle Element eine DatabaseForm ?
1754 Reference
< XRowSet
> xElementAsRowSet( xCurrentElement
, UNO_QUERY
);
1755 if ( xElementAsRowSet
.is() )
1757 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats( getRowSetConnection( xElementAsRowSet
), sal_False
) );
1758 if (!xSupplier
.is())
1761 Reference
< XPropertySet
> xSet(xSupplier
->getNumberFormatSettings());
1768 xSet
->setPropertyValue(::rtl::OUString("TwoDigitDateStart"), aVal
);
1772 OSL_FAIL("FmXFormShell::SetY2KState: Exception occurred!");
1777 xCurrentElement
= aIter
.Next();
1781 //------------------------------------------------------------------------------
1782 void FmXFormShell::CloseExternalFormViewer()
1784 if ( impl_checkDisposed() )
1787 if (!m_xExternalViewController
.is())
1790 Reference
< ::com::sun::star::frame::XFrame
> xExternalViewFrame( m_xExternalViewController
->getFrame());
1791 Reference
< ::com::sun::star::frame::XDispatchProvider
> xCommLink(xExternalViewFrame
, UNO_QUERY
);
1792 if (!xCommLink
.is())
1795 xExternalViewFrame
->setComponent(NULL
,NULL
);
1796 ::comphelper::disposeComponent(xExternalViewFrame
);
1797 m_xExternalViewController
= NULL
;
1798 m_xExtViewTriggerController
= NULL
;
1799 m_xExternalDisplayedForm
= NULL
;
1802 //------------------------------------------------------------------------------
1803 Reference
< XResultSet
> FmXFormShell::getInternalForm(const Reference
< XResultSet
>& _xForm
) const
1805 if ( impl_checkDisposed() )
1808 Reference
< runtime::XFormController
> xExternalCtrlr(m_xExternalViewController
, UNO_QUERY
);
1809 if (xExternalCtrlr
.is() && (_xForm
== xExternalCtrlr
->getModel()))
1811 DBG_ASSERT(m_xExternalDisplayedForm
.is(), "FmXFormShell::getInternalForm : invalid external form !");
1812 return m_xExternalDisplayedForm
;
1817 //------------------------------------------------------------------------------
1818 Reference
< XForm
> FmXFormShell::getInternalForm(const Reference
< XForm
>& _xForm
) const
1820 if ( impl_checkDisposed() )
1823 Reference
< runtime::XFormController
> xExternalCtrlr(m_xExternalViewController
, UNO_QUERY
);
1824 if (xExternalCtrlr
.is() && (_xForm
== xExternalCtrlr
->getModel()))
1826 DBG_ASSERT(m_xExternalDisplayedForm
.is(), "FmXFormShell::getInternalForm : invalid external form !");
1827 return Reference
< XForm
>(m_xExternalDisplayedForm
, UNO_QUERY
);
1832 //------------------------------------------------------------------------
1835 static bool lcl_isNavigationRelevant( sal_Int32 _nWhich
)
1837 return ( _nWhich
== SID_FM_RECORD_FIRST
)
1838 || ( _nWhich
== SID_FM_RECORD_PREV
)
1839 || ( _nWhich
== SID_FM_RECORD_NEXT
)
1840 || ( _nWhich
== SID_FM_RECORD_LAST
)
1841 || ( _nWhich
== SID_FM_RECORD_NEW
);
1845 //------------------------------------------------------------------------------
1846 bool FmXFormShell::IsFormSlotEnabled( sal_Int32 _nSlot
, FeatureState
* _pCompleteState
)
1848 const ::svx::ControllerFeatures
& rController
=
1849 lcl_isNavigationRelevant( _nSlot
)
1850 ? getNavControllerFeatures()
1851 : getActiveControllerFeatures();
1853 if ( !_pCompleteState
)
1854 return rController
->isEnabled( _nSlot
);
1856 rController
->getState( _nSlot
, *_pCompleteState
);
1857 return _pCompleteState
->Enabled
;
1860 //------------------------------------------------------------------------------
1861 void FmXFormShell::ExecuteFormSlot( sal_Int32 _nSlot
)
1863 const ::svx::ControllerFeatures
& rController
=
1864 lcl_isNavigationRelevant( _nSlot
)
1865 ? getNavControllerFeatures()
1866 : getActiveControllerFeatures();
1868 rController
->execute( _nSlot
);
1870 if ( _nSlot
== SID_FM_RECORD_UNDO
)
1872 // if we're doing an UNDO, *and* if the affected form is the form which we also display
1873 // as external view, then we need to reset the controls of the external form, too
1874 if ( getInternalForm( getActiveForm() ) == m_xExternalDisplayedForm
)
1876 Reference
< XIndexAccess
> xContainer( m_xExternalDisplayedForm
, UNO_QUERY
);
1877 if ( xContainer
.is() )
1879 Reference
< XReset
> xReset
;
1880 for ( sal_Int32 i
= 0; i
< xContainer
->getCount(); ++i
)
1882 if ( ( xContainer
->getByIndex( i
) >>= xReset
) && xReset
.is() )
1884 // no resets on sub forms
1885 Reference
< XForm
> xAsForm( xReset
, UNO_QUERY
);
1886 if ( !xAsForm
.is() )
1895 //------------------------------------------------------------------------------
1896 void FmXFormShell::impl_switchActiveControllerListening( const bool _bListen
)
1898 Reference
< XComponent
> xComp( m_xActiveController
, UNO_QUERY
);
1903 xComp
->addEventListener( (XFormControllerListener
*)this );
1905 xComp
->removeEventListener( (XFormControllerListener
*)this );
1908 //------------------------------------------------------------------------------
1909 void FmXFormShell::setActiveController( const Reference
< runtime::XFormController
>& xController
, sal_Bool _bNoSaveOldContent
)
1911 if ( impl_checkDisposed() )
1914 if (m_bChangingDesignMode
)
1916 DBG_ASSERT(!m_pShell
->IsDesignMode(), "nur im alive mode verwenden");
1918 // Ist die Routine ein zweites Mal gerufen worden,
1919 // dann sollte der Focus nicht mehr umgesetzt werden
1922 m_bSetFocus
= xController
!= m_xActiveController
;
1926 if (xController
!= m_xActiveController
)
1928 ::osl::ClearableMutexGuard
aGuard(m_aAsyncSafety
);
1929 // switch all nav dispatchers belonging to the form of the current nav controller to 'non active'
1930 Reference
< XResultSet
> xNavigationForm
;
1931 if (m_xNavigationController
.is())
1932 xNavigationForm
= Reference
< XResultSet
>(m_xNavigationController
->getModel(), UNO_QUERY
);
1935 m_bInActivate
= sal_True
;
1937 // check if the 2 controllers serve different forms
1938 Reference
< XResultSet
> xOldForm
;
1939 if (m_xActiveController
.is())
1940 xOldForm
= Reference
< XResultSet
>(m_xActiveController
->getModel(), UNO_QUERY
);
1941 Reference
< XResultSet
> xNewForm
;
1942 if (xController
.is())
1943 xNewForm
= Reference
< XResultSet
>(xController
->getModel(), UNO_QUERY
);
1944 xOldForm
= getInternalForm(xOldForm
);
1945 xNewForm
= getInternalForm(xNewForm
);
1947 sal_Bool bDifferentForm
= ( xOldForm
.get() != xNewForm
.get() );
1948 sal_Bool bNeedSave
= bDifferentForm
&& !_bNoSaveOldContent
;
1949 // we save the content of the old form if we move to a new form, and saving old content is allowed
1951 if ( m_xActiveController
.is() && bNeedSave
)
1953 // beim Wechsel des Controllers den Inhalt speichern, ein Commit
1954 // wurde bereits ausgefuehrt
1955 if ( m_aActiveControllerFeatures
->commitCurrentControl() )
1957 m_bSetFocus
= sal_True
;
1958 if ( m_aActiveControllerFeatures
->isModifiedRow() )
1960 sal_Bool bIsNew
= m_aActiveControllerFeatures
->isInsertionRow();
1961 sal_Bool bResult
= m_aActiveControllerFeatures
->commitCurrentRecord();
1962 if ( !bResult
&& m_bSetFocus
)
1964 // if we couldn't save the current record, set the focus back to the
1966 Reference
< XWindow
> xWindow( m_xActiveController
->getCurrentControl(), UNO_QUERY
);
1968 xWindow
->setFocus();
1969 m_bInActivate
= sal_False
;
1972 else if ( bResult
&& bIsNew
)
1974 Reference
< XResultSet
> xCursor( m_aActiveControllerFeatures
->getCursor().get() );
1977 DO_SAFE( xCursor
->last(); );
1986 impl_switchActiveControllerListening( false );
1988 m_aActiveControllerFeatures
.dispose();
1989 m_xActiveController
= xController
;
1990 if ( m_xActiveController
.is() )
1991 m_aActiveControllerFeatures
.assign( m_xActiveController
);
1993 impl_switchActiveControllerListening( true );
1995 if ( m_xActiveController
.is() )
1996 m_xActiveForm
= getInternalForm( Reference
< XForm
>( m_xActiveController
->getModel(), UNO_QUERY
) );
1998 m_xActiveForm
= NULL
;
2002 // activate all dispatchers belonging to form of the new navigation controller
2003 xNavigationForm
= NULL
;
2004 if (m_xNavigationController
.is())
2005 xNavigationForm
= Reference
< XResultSet
>(m_xNavigationController
->getModel(), UNO_QUERY
);
2007 m_bInActivate
= sal_False
;
2009 m_pShell
->UIFeatureChanged();
2010 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
2012 InvalidateSlot(SID_FM_FILTER_NAVIGATOR_CONTROL
, sal_True
);
2016 //------------------------------------------------------------------------------
2017 void FmXFormShell::getCurrentSelection( InterfaceBag
& /* [out] */ _rSelection
) const
2019 _rSelection
= m_aCurrentSelection
;
2022 //------------------------------------------------------------------------------
2023 bool FmXFormShell::setCurrentSelectionFromMark( const SdrMarkList
& _rMarkList
)
2025 m_aLastKnownMarkedControls
.clear();
2027 if ( ( _rMarkList
.GetMarkCount() > 0 ) && isControlList( _rMarkList
) )
2028 collectInterfacesFromMarkList( _rMarkList
, m_aLastKnownMarkedControls
);
2030 return setCurrentSelection( m_aLastKnownMarkedControls
);
2033 //------------------------------------------------------------------------------
2034 bool FmXFormShell::selectLastMarkedControls()
2036 return setCurrentSelection( m_aLastKnownMarkedControls
);
2039 //------------------------------------------------------------------------------
2040 bool FmXFormShell::setCurrentSelection( const InterfaceBag
& _rSelection
)
2042 if ( impl_checkDisposed() )
2045 DBG_ASSERT( m_pShell
->IsDesignMode(), "FmXFormShell::setCurrentSelection: only to be used in design mode!" );
2047 if ( _rSelection
.empty() && m_aCurrentSelection
.empty() )
2051 if ( _rSelection
.size() == m_aCurrentSelection
.size() )
2053 InterfaceBag::const_iterator aNew
= _rSelection
.begin();
2054 InterfaceBag::const_iterator aOld
= m_aCurrentSelection
.begin();
2055 for ( ; aNew
!= _rSelection
.end(); ++aNew
, ++aOld
)
2057 OSL_ENSURE( Reference
< XInterface
>( *aNew
, UNO_QUERY
).get() == aNew
->get(), "FmXFormShell::setCurrentSelection: new interface not normalized!" );
2058 OSL_ENSURE( Reference
< XInterface
>( *aOld
, UNO_QUERY
).get() == aOld
->get(), "FmXFormShell::setCurrentSelection: old interface not normalized!" );
2060 if ( aNew
->get() != aOld
->get() )
2064 if ( aNew
== _rSelection
.end() )
2069 // the following is some strange code to ensure that when you have two grid controls in a document,
2070 // only one of them can have a selected column.
2071 // TODO: this should happen elsewhere, but not here - shouldn't it?
2072 if ( !m_aCurrentSelection
.empty() )
2074 Reference
< XChild
> xCur
; if ( m_aCurrentSelection
.size() == 1 ) xCur
= xCur
.query( *m_aCurrentSelection
.begin() );
2075 Reference
< XChild
> xNew
; if ( _rSelection
.size() == 1 ) xNew
= xNew
.query( *_rSelection
.begin() );
2077 // is there nothing to be selected, or the parents differ, and the parent of the current object
2078 // is a selection supplier, then deselect
2079 if ( xCur
.is() && ( !xNew
.is() || ( xCur
->getParent() != xNew
->getParent() ) ) )
2081 Reference
< XSelectionSupplier
> xSel( xCur
->getParent(), UNO_QUERY
);
2083 xSel
->select( Any() );
2087 m_aCurrentSelection
= _rSelection
;
2089 // determine the form which all the selected obj�cts belong to, if any
2090 Reference
< XForm
> xNewCurrentForm
;
2091 for ( InterfaceBag::const_iterator loop
= m_aCurrentSelection
.begin();
2092 loop
!= m_aCurrentSelection
.end();
2096 Reference
< XForm
> xThisRoundsForm( GetForm( *loop
) );
2097 OSL_ENSURE( xThisRoundsForm
.is(), "FmXFormShell::setCurrentSelection: *everything* should belong to a form!" );
2099 if ( !xNewCurrentForm
.is() )
2100 { // the first form we encounterd
2101 xNewCurrentForm
= xThisRoundsForm
;
2103 else if ( xNewCurrentForm
!= xThisRoundsForm
)
2104 { // different forms -> no "current form" at all
2105 xNewCurrentForm
.clear();
2110 if ( !m_aCurrentSelection
.empty() )
2111 impl_updateCurrentForm( xNewCurrentForm
);
2113 // ensure some slots are updated
2114 for ( size_t i
= 0; i
< sizeof( SelObjectSlotMap
) / sizeof( SelObjectSlotMap
[0] ); ++i
)
2115 InvalidateSlot( SelObjectSlotMap
[i
], sal_False
);
2120 //------------------------------------------------------------------------------
2121 bool FmXFormShell::isSolelySelected( const Reference
< XInterface
>& _rxObject
)
2123 return ( m_aCurrentSelection
.size() == 1 ) && ( *m_aCurrentSelection
.begin() == _rxObject
);
2126 //------------------------------------------------------------------------------
2127 void FmXFormShell::forgetCurrentForm()
2129 if ( !m_xCurrentForm
.is() )
2133 impl_updateCurrentForm( NULL
);
2135 // ... and try finding a new current form
2136 // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
2137 impl_defaultCurrentForm_nothrow();
2140 //------------------------------------------------------------------------------
2141 void FmXFormShell::impl_updateCurrentForm( const Reference
< XForm
>& _rxNewCurForm
)
2143 if ( impl_checkDisposed() )
2146 m_xCurrentForm
= _rxNewCurForm
;
2148 // propagate to the FormPage(Impl)
2149 FmFormPage
* pPage
= m_pShell
->GetCurPage();
2151 pPage
->GetImpl().setCurForm( m_xCurrentForm
);
2153 // ensure the UI which depends on the current form is up-to-date
2154 for ( size_t i
= 0; i
< sizeof( DlgSlotMap
) / sizeof( DlgSlotMap
[0] ); ++i
)
2155 InvalidateSlot( DlgSlotMap
[i
], sal_False
);
2158 //------------------------------------------------------------------------------
2159 void FmXFormShell::startListening()
2161 if ( impl_checkDisposed() )
2164 Reference
< XRowSet
> xDatabaseForm(m_xActiveForm
, UNO_QUERY
);
2165 if (xDatabaseForm
.is() && getRowSetConnection(xDatabaseForm
).is())
2167 Reference
< XPropertySet
> xActiveFormSet(m_xActiveForm
, UNO_QUERY
);
2168 if (xActiveFormSet
.is())
2170 // wenn es eine Datenquelle gibt, dann den Listener aufbauen
2171 // TODO: this is strange - shouldn't this depend on a isLoaded instead of
2172 // a "has command value"? Finally, the command value only means that it was
2173 // intended to be loaded, not that it actually *is* loaded
2174 ::rtl::OUString aSource
= ::comphelper::getString(xActiveFormSet
->getPropertyValue(FM_PROP_COMMAND
));
2175 if (!aSource
.isEmpty())
2177 m_bDatabaseBar
= sal_True
;
2179 xActiveFormSet
->getPropertyValue(FM_PROP_NAVIGATION
) >>= m_eNavigate
;
2181 switch (m_eNavigate
)
2183 case NavigationBarMode_PARENT
:
2185 // suchen des Controllers, ueber den eine Navigation moeglich ist
2186 Reference
< XChild
> xChild(m_xActiveController
, UNO_QUERY
);
2187 Reference
< runtime::XFormController
> xParent
;
2190 xChild
= Reference
< XChild
>(xChild
->getParent(), UNO_QUERY
);
2191 xParent
= Reference
< runtime::XFormController
>(xChild
, UNO_QUERY
);
2192 Reference
< XPropertySet
> xParentSet
;
2194 xParentSet
= Reference
< XPropertySet
>(xParent
->getModel(), UNO_QUERY
);
2195 if (xParentSet
.is())
2197 xParentSet
->getPropertyValue(FM_PROP_NAVIGATION
) >>= m_eNavigate
;
2198 if (m_eNavigate
== NavigationBarMode_CURRENT
)
2202 m_xNavigationController
= xParent
;
2206 case NavigationBarMode_CURRENT
:
2207 m_xNavigationController
= m_xActiveController
;
2211 m_xNavigationController
= NULL
;
2212 m_bDatabaseBar
= sal_False
;
2215 m_aNavControllerFeatures
.dispose();
2216 if ( m_xNavigationController
.is() && ( m_xNavigationController
!= m_xActiveController
) )
2217 m_aNavControllerFeatures
.assign( m_xNavigationController
);
2219 // an dem Controller, der die Navigation regelt, wg. RecordCount lauschen
2220 Reference
< XPropertySet
> xNavigationSet
;
2221 if (m_xNavigationController
.is())
2223 xNavigationSet
= Reference
< XPropertySet
>(m_xNavigationController
->getModel(), UNO_QUERY
);
2224 if (xNavigationSet
.is())
2225 xNavigationSet
->addPropertyChangeListener(FM_PROP_ROWCOUNT
,this);
2232 m_eNavigate
= NavigationBarMode_NONE
;
2233 m_bDatabaseBar
= sal_False
;
2234 m_xNavigationController
= NULL
;
2237 //------------------------------------------------------------------------------
2238 void FmXFormShell::stopListening()
2240 if ( impl_checkDisposed() )
2243 Reference
< XRowSet
> xDatabaseForm(m_xActiveForm
, UNO_QUERY
);
2244 if ( xDatabaseForm
.is() )
2246 if (m_xNavigationController
.is())
2248 Reference
< XPropertySet
> xSet(m_xNavigationController
->getModel(), UNO_QUERY
);
2250 xSet
->removePropertyChangeListener(FM_PROP_ROWCOUNT
, this);
2255 m_bDatabaseBar
= sal_False
;
2256 m_eNavigate
= NavigationBarMode_NONE
;
2257 m_xNavigationController
= NULL
;
2260 //------------------------------------------------------------------------------
2261 void FmXFormShell::ShowSelectionProperties( sal_Bool bShow
)
2263 if ( impl_checkDisposed() )
2266 // if the window is already visible, only update the state
2267 sal_Bool bHasChild
= m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_PROPERTIES
);
2268 if ( bHasChild
&& bShow
)
2269 UpdateSlot( SID_FM_PROPERTY_CONTROL
);
2271 // else toggle state
2273 m_pShell
->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES
);
2275 InvalidateSlot( SID_FM_PROPERTIES
, sal_False
);
2276 InvalidateSlot( SID_FM_CTL_PROPERTIES
, sal_False
);
2279 //------------------------------------------------------------------------------
2280 IMPL_LINK(FmXFormShell
, OnFoundData
, FmFoundRecordInformation
*, pfriWhere
)
2282 if ( impl_checkDisposed() )
2285 DBG_ASSERT((pfriWhere
->nContext
>= 0) && (pfriWhere
->nContext
< (sal_Int16
)m_aSearchForms
.size()),
2286 "FmXFormShell::OnFoundData : ungueltiger Kontext !");
2287 Reference
< XForm
> xForm( m_aSearchForms
.at(pfriWhere
->nContext
));
2288 DBG_ASSERT(xForm
.is(), "FmXFormShell::OnFoundData : ungueltige Form !");
2290 Reference
< XRowLocate
> xCursor(xForm
, UNO_QUERY
);
2292 return 0; // was soll ich da machen ?
2297 xCursor
->moveToBookmark(pfriWhere
->aPosition
);
2299 catch(const SQLException
&)
2301 OSL_FAIL("Can position on bookmark!");
2304 LoopGrids(GA_FORCE_SYNC
);
2306 // und zum Feld (dazu habe ich vor dem Start des Suchens die XVclComponent-Interfaces eingesammelt)
2307 SAL_WARN_IF(static_cast<size_t>(pfriWhere
->nFieldPos
) >=
2308 m_arrSearchedControls
.size(),
2309 "svx.form", "FmXFormShell::OnFoundData : invalid index!");
2310 SdrObject
* pObject
= m_arrSearchedControls
.at(pfriWhere
->nFieldPos
);
2312 m_pShell
->GetFormView()->UnMarkAll(m_pShell
->GetFormView()->GetSdrPageView());
2313 m_pShell
->GetFormView()->MarkObj(pObject
, m_pShell
->GetFormView()->GetSdrPageView());
2315 FmFormObj
* pFormObject
= FmFormObj::GetFormObject( pObject
);
2316 Reference
< XControlModel
> xControlModel( pFormObject
? pFormObject
->GetUnoControlModel() : Reference
< XControlModel
>() );
2317 DBG_ASSERT( xControlModel
.is(), "FmXFormShell::OnFoundData: invalid control!" );
2318 if ( !xControlModel
.is() )
2321 // disable the permanent cursor for the last grid we found a record
2322 if (m_xLastGridFound
.is() && (m_xLastGridFound
!= xControlModel
))
2324 Reference
< XPropertySet
> xOldSet(m_xLastGridFound
, UNO_QUERY
);
2325 xOldSet
->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR
, makeAny( (sal_Bool
)sal_False
) );
2326 Reference
< XPropertyState
> xOldSetState(xOldSet
, UNO_QUERY
);
2327 if (xOldSetState
.is())
2328 xOldSetState
->setPropertyToDefault(FM_PROP_CURSORCOLOR
);
2330 xOldSet
->setPropertyValue(FM_PROP_CURSORCOLOR
, Any());
2333 // wenn das Feld sich in einem GridControl befindet, muss ich dort noch in die entsprechende Spalte gehen
2334 sal_Int32 nGridColumn
= m_arrRelativeGridColumn
[pfriWhere
->nFieldPos
];
2335 if (nGridColumn
!= -1)
2336 { // dummer weise muss ich mir das Control erst wieder besorgen
2337 Reference
< XControl
> xControl( impl_getControl( xControlModel
, *pFormObject
) );
2338 Reference
< XGrid
> xGrid(xControl
, UNO_QUERY
);
2339 DBG_ASSERT(xGrid
.is(), "FmXFormShell::OnFoundData : ungueltiges Control !");
2340 // wenn eine der Asserts anschlaegt, habe ich beim Aufbauen von m_arrSearchedControls wohl was falsch gemacht
2342 // enable a permanent cursor for the grid so we can see the found text
2343 Reference
< XPropertySet
> xModelSet(xControlModel
, UNO_QUERY
);
2344 DBG_ASSERT(xModelSet
.is(), "FmXFormShell::OnFoundData : invalid control model (no property set) !");
2345 xModelSet
->setPropertyValue( FM_PROP_ALWAYSSHOWCURSOR
, makeAny( (sal_Bool
)sal_True
) );
2346 xModelSet
->setPropertyValue( FM_PROP_CURSORCOLOR
, makeAny( sal_Int32( COL_LIGHTRED
) ) );
2347 m_xLastGridFound
= xControlModel
;
2350 xGrid
->setCurrentColumnPosition((sal_Int16
)nGridColumn
);
2353 // als der Cursor neu positioniert wurde, habe ich (in positioned) meine Formularleisten-Slots invalidiert, aber das greift
2354 // hier dummerweise nicht, da i.A. ja der (modale) Suchdialog oben ist ... also Gewalt ...
2355 sal_uInt16 nPos
= 0;
2356 while (DatabaseSlotMap
[nPos
])
2357 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().Update(DatabaseSlotMap
[nPos
++]);
2358 // leider geht das Update im Gegensatz zum Invalidate nur mit einzelnen Slots)
2363 //------------------------------------------------------------------------------
2364 IMPL_LINK(FmXFormShell
, OnCanceledNotFound
, FmFoundRecordInformation
*, pfriWhere
)
2366 if ( impl_checkDisposed() )
2369 DBG_ASSERT((pfriWhere
->nContext
>= 0) && (pfriWhere
->nContext
< (sal_Int16
)m_aSearchForms
.size()),
2370 "FmXFormShell::OnCanceledNotFound : ungueltiger Kontext !");
2371 Reference
< XForm
> xForm( m_aSearchForms
.at(pfriWhere
->nContext
));
2372 DBG_ASSERT(xForm
.is(), "FmXFormShell::OnCanceledNotFound : ungueltige Form !");
2374 Reference
< XRowLocate
> xCursor(xForm
, UNO_QUERY
);
2376 return 0; // was soll ich da machen ?
2381 xCursor
->moveToBookmark(pfriWhere
->aPosition
);
2383 catch(const SQLException
&)
2385 OSL_FAIL("Can position on bookmark!");
2389 m_pShell
->GetFormView()->UnMarkAll(m_pShell
->GetFormView()->GetSdrPageView());
2393 //------------------------------------------------------------------------------
2394 IMPL_LINK(FmXFormShell
, OnSearchContextRequest
, FmSearchContext
*, pfmscContextInfo
)
2396 if ( impl_checkDisposed() )
2399 DBG_ASSERT(pfmscContextInfo
->nContext
< (sal_Int16
)m_aSearchForms
.size(), "FmXFormShell::OnSearchContextRequest : invalid parameter !");
2400 Reference
< XForm
> xForm( m_aSearchForms
.at(pfmscContextInfo
->nContext
));
2401 DBG_ASSERT(xForm
.is(), "FmXFormShell::OnSearchContextRequest : unexpected : invalid context !");
2403 Reference
< XResultSet
> xIter(xForm
, UNO_QUERY
);
2404 DBG_ASSERT(xIter
.is(), "FmXFormShell::OnSearchContextRequest : unexpected : context has no iterator !");
2406 // --------------------------------------------------------------------------------------------
2407 // assemble the list of fields to involve (that is, the ControlSources of all fields that have such a property)
2408 UniString strFieldList
, sFieldDisplayNames
;
2409 m_arrSearchedControls
.clear();
2410 m_arrRelativeGridColumn
.clear();
2412 // small problem: To mark found fields, I need SdrObjects. To determine which controls
2413 // to include in the search, I need Controls (that is, XControl interfaces). So I have
2414 // to iterate over one of them and get the other in some way. Unfortunately, there is
2415 // no direct connexion between the two worlds (except from a GetUnoControl to a
2416 // SdrUnoObject, but this requires an OutputDevice I can not do anything with.
2417 // However I can get to the Model from the Control and also from the SdrObject, and in
2418 // this way the assignment SdrObject<->Control is possible with a double loop.
2419 // The alternative to this (ugly but certainly not entirely fixable) solution would be
2420 // to renounce the caching of the SdrObjects, which would lead to significant extra
2421 // work in OnFoundData (since there I'd have to get the SdrObject first thing every
2422 // time). But since OnFoundData is usually called more often than ExecuteSeearch, I'll
2425 Reference
< XNameAccess
> xValidFormFields
;
2426 Reference
< XColumnsSupplier
> xSupplyCols(xIter
, UNO_QUERY
);
2427 DBG_ASSERT(xSupplyCols
.is(), "FmXFormShell::OnSearchContextRequest : invalid cursor : no columns supplier !");
2428 if (xSupplyCols
.is())
2429 xValidFormFields
= xSupplyCols
->getColumns();
2430 DBG_ASSERT(xValidFormFields
.is(), "FmXFormShell::OnSearchContextRequest : form has no fields !");
2432 // current Page/Controller
2433 FmFormPage
* pCurrentPage
= m_pShell
->GetCurPage();
2434 DBG_ASSERT(pCurrentPage
!=NULL
, "FmXFormShell::OnSearchContextRequest : no page !");
2435 // Search all SdrControls of this page...
2436 ::rtl::OUString sControlSource
, aName
;
2438 SdrObjListIter
aPageIter( *pCurrentPage
);
2439 while ( aPageIter
.IsMore() )
2441 SdrObject
* pCurrent
= aPageIter
.Next();
2442 FmFormObj
* pFormObject
= FmFormObj::GetFormObject( pCurrent
);
2443 // note that in case pCurrent is a virtual object, pFormObject points to the referenced object
2448 // the current object's model, in different tastes
2449 Reference
< XControlModel
> xControlModel( pFormObject
->GetUnoControlModel() );
2450 Reference
< XFormComponent
> xCurrentFormComponent( xControlModel
, UNO_QUERY
);
2451 DBG_ASSERT( xCurrentFormComponent
.is(), "FmXFormShell::OnSearchContextRequest: invalid objects!" );
2452 if ( !xCurrentFormComponent
.is() )
2455 // does the component belong to the form which we're interested in?
2456 if ( xCurrentFormComponent
->getParent() != xForm
)
2459 // ... ask for the ControlSource property
2460 SearchableControlIterator
iter( xCurrentFormComponent
);
2461 Reference
< XControl
> xControl
;
2462 // the control that has model xControlModel
2463 // (the following while can be passed through several times, without the Control
2464 // being modified, so I don't have to search every time from scratch)
2466 Reference
< XInterface
> xSearchable( iter
.Next() );
2467 while ( xSearchable
.is() )
2469 sControlSource
= iter
.getCurrentValue();
2470 if ( sControlSource
.isEmpty() )
2472 // the current element has no ControlSource, so it is a GridControl (that
2473 // is the only thing that still permits the SearchableControlIteratore)
2474 xControl
= impl_getControl( xControlModel
, *pFormObject
);
2475 DBG_ASSERT(xControl
.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
2477 Reference
< XGridPeer
> xGridPeer
;
2478 if ( xControl
.is() )
2479 xGridPeer
.set( xControl
->getPeer(), UNO_QUERY
);
2482 if (!xGridPeer
.is())
2485 Reference
< XIndexAccess
> xPeerContainer(xGridPeer
, UNO_QUERY
);
2486 if (!xPeerContainer
.is())
2489 Reference
< XIndexAccess
> xModelColumns(xGridPeer
->getColumns(), UNO_QUERY
);
2490 DBG_ASSERT(xModelColumns
.is(), "FmXFormShell::OnSearchContextRequest : there is a grid control without columns !");
2491 // the case 'no columns' should be indicated with an empty container, I think ...
2492 DBG_ASSERT(xModelColumns
->getCount() >= xPeerContainer
->getCount(), "FmXFormShell::OnSearchContextRequest : impossible : have more view than model columns !");
2494 Reference
< XInterface
> xCurrentColumn
;
2495 for (sal_Int16 nViewPos
=0; nViewPos
<xPeerContainer
->getCount(); ++nViewPos
)
2497 xPeerContainer
->getByIndex(nViewPos
) >>= xCurrentColumn
;
2498 if (!xCurrentColumn
.is())
2501 // can we use this column control for searching ?
2502 if (!IsSearchableControl(xCurrentColumn
))
2505 sal_Int16 nModelPos
= GridView2ModelPos(xModelColumns
, nViewPos
);
2506 Reference
< XPropertySet
> xCurrentColModel
;
2507 xModelColumns
->getByIndex(nModelPos
) >>= xCurrentColModel
;
2508 aName
= ::comphelper::getString(xCurrentColModel
->getPropertyValue(FM_PROP_CONTROLSOURCE
));
2509 // the cursor has a field matching the control source ?
2510 if (xValidFormFields
->hasByName(aName
))
2512 strFieldList
+= aName
.getStr();
2513 strFieldList
+= ';';
2515 sFieldDisplayNames
+= ::comphelper::getString(xCurrentColModel
->getPropertyValue(FM_PROP_LABEL
)).getStr();
2516 sFieldDisplayNames
+= ';';
2518 pfmscContextInfo
->arrFields
.push_back(xCurrentColumn
);
2520 // and the SdrOject to the Field
2521 m_arrSearchedControls
.push_back(pCurrent
);
2522 // the number of the column
2523 m_arrRelativeGridColumn
.push_back(nViewPos
);
2526 } while (sal_False
);
2530 if (!sControlSource
.isEmpty() && xValidFormFields
->hasByName(sControlSource
))
2532 // now I need the Control to SdrObject
2535 xControl
= impl_getControl( xControlModel
, *pFormObject
);
2536 DBG_ASSERT(xControl
.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !");
2539 if (IsSearchableControl(xControl
))
2541 // all tests passed -> take along in the list
2542 strFieldList
+= sControlSource
.getStr();
2543 strFieldList
+= ';';
2545 // the label which should appear for the control :
2546 sFieldDisplayNames
+= getLabelName(Reference
< XPropertySet
>(xControlModel
, UNO_QUERY
)).getStr();
2547 sFieldDisplayNames
+= ';';
2549 // mark the SdrObject (accelerates the treatment in OnFoundData)
2550 m_arrSearchedControls
.push_back(pCurrent
);
2552 // the number of the colum (here a dummy, since it is only interesting for GridControls)
2553 m_arrRelativeGridColumn
.push_back(-1);
2555 // and for the formatted search...
2556 pfmscContextInfo
->arrFields
.push_back(Reference
< XInterface
>(xControl
, UNO_QUERY
));
2561 xSearchable
= iter
.Next();
2565 strFieldList
.EraseTrailingChars(';');
2566 sFieldDisplayNames
.EraseTrailingChars(';');
2568 if (pfmscContextInfo
->arrFields
.empty())
2570 pfmscContextInfo
->arrFields
.clear();
2571 pfmscContextInfo
->xCursor
= NULL
;
2572 pfmscContextInfo
->strUsedFields
.Erase();
2576 pfmscContextInfo
->xCursor
= xIter
;
2577 pfmscContextInfo
->strUsedFields
= strFieldList
;
2578 pfmscContextInfo
->sFieldDisplayNames
= sFieldDisplayNames
;
2580 // 66463 - 31.05.99 - FS
2581 // when the cursor is a non-STANDARD RecordMode, set it back
2582 Reference
< XPropertySet
> xCursorSet(pfmscContextInfo
->xCursor
, UNO_QUERY
);
2583 Reference
< XResultSetUpdate
> xUpdateCursor(pfmscContextInfo
->xCursor
, UNO_QUERY
);
2584 if (xUpdateCursor
.is() && xCursorSet
.is() && xCursorSet
.is())
2586 if (::comphelper::getBOOL(xCursorSet
->getPropertyValue(FM_PROP_ISNEW
)))
2587 xUpdateCursor
->moveToCurrentRow();
2588 else if (::comphelper::getBOOL(xCursorSet
->getPropertyValue(FM_PROP_ISMODIFIED
)))
2589 xUpdateCursor
->cancelRowUpdates();
2592 return pfmscContextInfo
->arrFields
.size();
2595 // XContainerListener
2596 //------------------------------------------------------------------------------
2597 void FmXFormShell::elementInserted(const ContainerEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
)
2599 if ( impl_checkDisposed() )
2602 // new object to listen to
2603 Reference
< XInterface
> xTemp
;
2604 evt
.Element
>>= xTemp
;
2606 m_pShell
->DetermineForms(sal_True
);
2609 //------------------------------------------------------------------------------
2610 void FmXFormShell::elementReplaced(const ContainerEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
)
2612 if ( impl_checkDisposed() )
2615 Reference
< XInterface
> xTemp
;
2616 evt
.ReplacedElement
>>= xTemp
;
2617 RemoveElement(xTemp
);
2618 evt
.Element
>>= xTemp
;
2622 //------------------------------------------------------------------------------
2623 void FmXFormShell::elementRemoved(const ContainerEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
)
2625 if ( impl_checkDisposed() )
2628 Reference
< XInterface
> xTemp
;
2629 evt
.Element
>>= xTemp
;
2630 RemoveElement(xTemp
);
2631 m_pShell
->DetermineForms(sal_True
);
2634 //------------------------------------------------------------------------------
2635 void FmXFormShell::UpdateForms( sal_Bool _bInvalidate
)
2637 if ( impl_checkDisposed() )
2640 Reference
< XIndexAccess
> xForms
;
2642 FmFormPage
* pPage
= m_pShell
->GetCurPage();
2645 if ( m_pShell
->m_bDesignMode
)
2646 xForms
= xForms
.query( pPage
->GetForms( false ) );
2649 if ( m_xForms
!= xForms
)
2651 RemoveElement( m_xForms
);
2653 AddElement( m_xForms
);
2656 m_pShell
->DetermineForms( _bInvalidate
);
2659 //------------------------------------------------------------------------------
2660 void FmXFormShell::AddElement(const Reference
< XInterface
>& _xElement
)
2662 if ( impl_checkDisposed() )
2664 impl_AddElement_nothrow(_xElement
);
2666 // -----------------------------------------------------------------------------
2667 void FmXFormShell::impl_AddElement_nothrow(const Reference
< XInterface
>& Element
)
2669 // am Container horchen
2670 const Reference
< XIndexContainer
> xContainer(Element
, UNO_QUERY
);
2671 if (xContainer
.is())
2673 const sal_uInt32 nCount
= xContainer
->getCount();
2674 Reference
< XInterface
> xElement
;
2675 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
2677 xElement
.set(xContainer
->getByIndex(i
),UNO_QUERY
);
2678 impl_AddElement_nothrow(xElement
);
2681 const Reference
< XContainer
> xCont(Element
, UNO_QUERY
);
2683 xCont
->addContainerListener(this);
2686 const Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(Element
, UNO_QUERY
);
2687 if (xSelSupplier
.is())
2688 xSelSupplier
->addSelectionChangeListener(this);
2691 //------------------------------------------------------------------------------
2692 void FmXFormShell::RemoveElement(const Reference
< XInterface
>& Element
)
2694 if ( impl_checkDisposed() )
2696 impl_RemoveElement_nothrow(Element
);
2698 //------------------------------------------------------------------------------
2699 void FmXFormShell::impl_RemoveElement_nothrow(const Reference
< XInterface
>& Element
)
2701 const Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(Element
, UNO_QUERY
);
2702 if (xSelSupplier
.is())
2703 xSelSupplier
->removeSelectionChangeListener(this);
2705 // remove connection to children
2706 const Reference
< XIndexContainer
> xContainer(Element
, UNO_QUERY
);
2707 if (xContainer
.is())
2709 const Reference
< XContainer
> xCont(Element
, UNO_QUERY
);
2711 xCont
->removeContainerListener(this);
2713 const sal_uInt32 nCount
= xContainer
->getCount();
2714 Reference
< XInterface
> xElement
;
2715 for (sal_uInt32 i
= 0; i
< nCount
; i
++)
2717 xElement
.set(xContainer
->getByIndex(i
),UNO_QUERY
);
2718 impl_RemoveElement_nothrow(xElement
);
2722 InterfaceBag::iterator wasSelectedPos
= m_aCurrentSelection
.find( Element
);
2723 if ( wasSelectedPos
!= m_aCurrentSelection
.end() )
2724 m_aCurrentSelection
.erase( wasSelectedPos
);
2727 //------------------------------------------------------------------------------
2728 void FmXFormShell::selectionChanged(const EventObject
& rEvent
) throw(::com::sun::star::uno::RuntimeException
)
2730 if ( impl_checkDisposed() )
2733 Reference
< XSelectionSupplier
> xSupplier( rEvent
.Source
, UNO_QUERY
);
2734 Reference
< XInterface
> xSelObj( xSupplier
->getSelection(), UNO_QUERY
);
2735 // a selection was removed, this can only be done by the shell
2736 if ( !xSelObj
.is() )
2739 EnableTrackProperties(sal_False
);
2741 sal_Bool bMarkChanged
= m_pShell
->GetFormView()->checkUnMarkAll(rEvent
.Source
);
2742 Reference
< XForm
> xNewForm( GetForm( rEvent
.Source
) );
2744 InterfaceBag aNewSelection
;
2745 aNewSelection
.insert( Reference
< XInterface
>( xSelObj
, UNO_QUERY
) );
2747 if ( setCurrentSelection( aNewSelection
) && IsPropBrwOpen() )
2748 ShowSelectionProperties( sal_True
);
2750 EnableTrackProperties(sal_True
);
2753 m_pShell
->NotifyMarkListChanged( m_pShell
->GetFormView() );
2756 //------------------------------------------------------------------------------
2757 IMPL_LINK(FmXFormShell
, OnTimeOut
, void*, /*EMPTYTAG*/)
2759 if ( impl_checkDisposed() )
2762 if (m_pShell
->IsDesignMode() && m_pShell
->GetFormView())
2763 SetSelection(m_pShell
->GetFormView()->GetMarkedObjectList());
2768 //------------------------------------------------------------------------
2769 void FmXFormShell::SetSelectionDelayed()
2771 if ( impl_checkDisposed() )
2774 if (m_pShell
->IsDesignMode() && IsTrackPropertiesEnabled() && !m_aMarkTimer
.IsActive())
2775 m_aMarkTimer
.Start();
2778 //------------------------------------------------------------------------
2779 void FmXFormShell::SetSelection(const SdrMarkList
& rMarkList
)
2781 if ( impl_checkDisposed() )
2784 DetermineSelection(rMarkList
);
2785 m_pShell
->NotifyMarkListChanged(m_pShell
->GetFormView());
2788 //------------------------------------------------------------------------
2789 void FmXFormShell::DetermineSelection(const SdrMarkList
& rMarkList
)
2791 if ( setCurrentSelectionFromMark( rMarkList
) && IsPropBrwOpen() )
2792 ShowSelectionProperties( sal_True
);
2795 //------------------------------------------------------------------------------
2796 sal_Bool
FmXFormShell::IsPropBrwOpen() const
2798 if ( impl_checkDisposed() )
2801 return( ( m_pShell
->GetViewShell() && m_pShell
->GetViewShell()->GetViewFrame() ) ?
2802 m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES
) : sal_False
);
2805 //------------------------------------------------------------------------------
2806 class FmXFormShell::SuspendPropertyTracking
2809 FmXFormShell
& m_rShell
;
2810 sal_Bool m_bEnabled
;
2813 SuspendPropertyTracking( FmXFormShell
& _rShell
)
2814 :m_rShell( _rShell
)
2815 ,m_bEnabled( sal_False
)
2817 if ( m_rShell
.IsTrackPropertiesEnabled() )
2819 m_rShell
.EnableTrackProperties( sal_False
);
2820 m_bEnabled
= sal_True
;
2824 ~SuspendPropertyTracking( )
2826 if ( m_bEnabled
) // note that ( sal_False != m_bEnabled ) implies ( NULL != m_pShell )
2827 m_rShell
.EnableTrackProperties( sal_True
);
2831 //------------------------------------------------------------------------------
2832 void FmXFormShell::SetDesignMode(sal_Bool bDesign
)
2834 if ( impl_checkDisposed() )
2837 DBG_ASSERT(m_pShell
->GetFormView(), "FmXFormShell::SetDesignMode : invalid call (have no shell or no view) !");
2838 m_bChangingDesignMode
= sal_True
;
2840 // 67506 - 15.07.99 - FS
2841 // if we're switching off the design mode we have to force the property browser to be closed
2842 // so it can commit it's changes _before_ we load the forms
2845 m_bHadPropertyBrowserInDesignMode
= m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES
);
2846 if (m_bHadPropertyBrowserInDesignMode
)
2847 m_pShell
->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES
);
2850 FmFormView
* pFormView
= m_pShell
->GetFormView();
2853 // we are currently filtering, so stop filtering
2855 stopFiltering(sal_False
);
2857 // unsubscribe from the objects of my MarkList
2858 pFormView
->GetImpl()->stopMarkListWatching();
2862 m_aMarkTimer
.Stop();
2864 SuspendPropertyTracking
aSuspend( *this );
2865 pFormView
->GetImpl()->saveMarkList( sal_True
);
2868 if (bDesign
&& m_xExternalViewController
.is())
2869 CloseExternalFormViewer();
2871 pFormView
->ChangeDesignMode(bDesign
);
2873 // notify listensers
2874 FmDesignModeChangedHint
aChangedHint( bDesign
);
2875 m_pShell
->Broadcast(aChangedHint
);
2877 m_pShell
->m_bDesignMode
= bDesign
;
2878 UpdateForms( sal_False
);
2880 m_pTextShell
->designModeChanged( m_pShell
->m_bDesignMode
);
2886 // during changing the mark list, don't track the selected objects in the property browser
2887 SuspendPropertyTracking
aSuspend( *this );
2888 // restore the marks
2889 pFormView
->GetImpl()->restoreMarkList( aList
);
2892 // synchronize with the restored mark list
2893 if ( aList
.GetMarkCount() )
2894 SetSelection( aList
);
2898 // subscribe to the model of the view (so that I'm informed when someone deletes
2899 // during the alive mode controls that I had saved in the saveMarklist (60343)
2900 pFormView
->GetImpl()->startMarkListWatching();
2903 m_pShell
->UIFeatureChanged();
2905 // 67506 - 15.07.99 - FS
2906 if (bDesign
&& m_bHadPropertyBrowserInDesignMode
)
2908 // The UIFeatureChanged performes an update (a check of the available features) asynchronously.
2909 // So we can't call ShowSelectionProperties directly as the according feature isn't enabled yet.
2910 // That's why we use an asynchron execution on the dispatcher.
2911 // (And that's why this has to be done AFTER the UIFeatureChanged.)
2912 m_pShell
->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER
, SFX_CALLMODE_ASYNCHRON
);
2914 m_bChangingDesignMode
= sal_False
;
2917 //------------------------------------------------------------------------------
2918 Reference
< XControl
> FmXFormShell::impl_getControl( const Reference
< XControlModel
>& i_rxModel
, const FmFormObj
& i_rKnownFormObj
)
2920 if ( impl_checkDisposed() )
2923 Reference
< XControl
> xControl
;
2926 Reference
< XControlContainer
> xControlContainer( getControlContainerForView(), UNO_SET_THROW
);
2928 Sequence
< Reference
< XControl
> > seqControls( xControlContainer
->getControls() );
2929 const Reference
< XControl
>* pControls
= seqControls
.getArray();
2930 // ... that I can then search
2931 for (sal_Int32 i
=0; i
<seqControls
.getLength(); ++i
)
2933 xControl
.set( pControls
[i
], UNO_SET_THROW
);
2934 Reference
< XControlModel
> xCurrentModel( xControl
->getModel() );
2935 if ( xCurrentModel
== i_rxModel
)
2940 if ( !xControl
.is() )
2942 // fallabck (some controls might not have been created, yet, since they were never visible so far)
2943 Reference
< XControl
> xContainerControl( xControlContainer
, UNO_QUERY_THROW
);
2944 const Window
* pContainerWindow
= VCLUnoHelper::GetWindow( xContainerControl
->getPeer() );
2945 ENSURE_OR_THROW( pContainerWindow
, "unexpected control container implementation" );
2947 const SdrView
* pSdrView
= m_pShell
? m_pShell
->GetFormView() : NULL
;
2948 ENSURE_OR_THROW( pSdrView
, "no current view" );
2950 xControl
.set( i_rKnownFormObj
.GetUnoControl( *pSdrView
, *pContainerWindow
), UNO_QUERY_THROW
);
2953 catch( const Exception
& )
2955 DBG_UNHANDLED_EXCEPTION();
2958 OSL_ENSURE( xControl
.is(), "FmXFormShell::impl_getControl: no control found!" );
2962 //------------------------------------------------------------------------------
2963 void FmXFormShell::impl_collectFormSearchContexts_nothrow( const Reference
< XInterface
>& _rxStartingPoint
,
2964 const ::rtl::OUString
& _rCurrentLevelPrefix
, FmFormArray
& _out_rForms
, ::std::vector
< String
>& _out_rNames
)
2968 Reference
< XIndexAccess
> xContainer( _rxStartingPoint
, UNO_QUERY
);
2969 if ( !xContainer
.is() )
2972 sal_Int32
nCount( xContainer
->getCount() );
2976 ::rtl::OUString sCurrentFormName
;
2977 ::rtl::OUStringBuffer aNextLevelPrefix
;
2978 for ( sal_Int32 i
=0; i
<nCount
; ++i
)
2980 // is the current child a form?
2981 Reference
< XForm
> xCurrentAsForm( xContainer
->getByIndex(i
), UNO_QUERY
);
2982 if ( !xCurrentAsForm
.is() )
2985 Reference
< XNamed
> xNamed( xCurrentAsForm
, UNO_QUERY_THROW
);
2986 sCurrentFormName
= xNamed
->getName();
2988 // the name of the current form
2989 ::rtl::OUStringBuffer
sCompleteCurrentName( sCurrentFormName
);
2990 if ( !_rCurrentLevelPrefix
.isEmpty() )
2992 sCompleteCurrentName
.appendAscii( " (" );
2993 sCompleteCurrentName
.append ( _rCurrentLevelPrefix
);
2994 sCompleteCurrentName
.appendAscii( ")" );
2997 // the prefix for the next level
2998 aNextLevelPrefix
= _rCurrentLevelPrefix
;
2999 if ( !_rCurrentLevelPrefix
.isEmpty() )
3000 aNextLevelPrefix
.append( (sal_Unicode
)'/' );
3001 aNextLevelPrefix
.append( sCurrentFormName
);
3003 // remember both the form and it's "display name"
3004 _out_rForms
.push_back( xCurrentAsForm
);
3005 _out_rNames
.push_back( sCompleteCurrentName
.makeStringAndClear() );
3008 impl_collectFormSearchContexts_nothrow( xCurrentAsForm
, aNextLevelPrefix
.makeStringAndClear(), _out_rForms
, _out_rNames
);
3011 catch( const Exception
& )
3013 DBG_UNHANDLED_EXCEPTION();
3017 //------------------------------------------------------------------------------
3018 void FmXFormShell::startFiltering()
3020 if ( impl_checkDisposed() )
3023 // setting all forms in filter mode
3024 FmXFormView
* pXView
= m_pShell
->GetFormView()->GetImpl();
3026 // if the active controller is our external one we have to use the trigger controller
3027 Reference
< XControlContainer
> xContainer
;
3028 if (getActiveController() == m_xExternalViewController
)
3030 DBG_ASSERT(m_xExtViewTriggerController
.is(), "FmXFormShell::startFiltering : inconsistent : active external controller, but noone triggered this !");
3031 xContainer
= m_xExtViewTriggerController
->getContainer();
3034 xContainer
= getActiveController()->getContainer();
3036 PFormViewPageWindowAdapter pAdapter
= pXView
->findWindow( xContainer
);
3037 if ( pAdapter
.is() )
3039 const ::std::vector
< Reference
< runtime::XFormController
> >& rControllerList
= pAdapter
->GetList();
3040 for ( ::std::vector
< Reference
< runtime::XFormController
> >::const_iterator j
= rControllerList
.begin();
3041 j
!= rControllerList
.end();
3045 Reference
< XModeSelector
> xModeSelector(*j
, UNO_QUERY
);
3046 if (xModeSelector
.is())
3047 xModeSelector
->setMode( ::rtl::OUString( "FilterMode" ) );
3051 m_bFilterMode
= sal_True
;
3053 m_pShell
->UIFeatureChanged();
3054 SfxViewFrame
* pViewFrame
= m_pShell
->GetViewShell()->GetViewFrame();
3055 pViewFrame
->GetBindings().InvalidateShell( *m_pShell
);
3057 if ( pViewFrame
->KnowsChildWindow( SID_FM_FILTER_NAVIGATOR
)
3058 && !pViewFrame
->HasChildWindow( SID_FM_FILTER_NAVIGATOR
)
3061 pViewFrame
->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR
);
3065 //------------------------------------------------------------------------------
3066 void saveFilter(const Reference
< runtime::XFormController
>& _rxController
)
3068 Reference
< XPropertySet
> xFormAsSet(_rxController
->getModel(), UNO_QUERY
);
3069 Reference
< XPropertySet
> xControllerAsSet(_rxController
, UNO_QUERY
);
3070 Reference
< XIndexAccess
> xControllerAsIndex(_rxController
, UNO_QUERY
);
3072 // call the subcontroller
3073 Reference
< runtime::XFormController
> xController
;
3074 for (sal_Int32 i
= 0, nCount
= xControllerAsIndex
->getCount(); i
< nCount
; ++i
)
3076 xControllerAsIndex
->getByIndex(i
) >>= xController
;
3077 saveFilter(xController
);
3083 xFormAsSet
->setPropertyValue(FM_PROP_FILTER
, xControllerAsSet
->getPropertyValue(FM_PROP_FILTER
));
3084 xFormAsSet
->setPropertyValue(FM_PROP_APPLYFILTER
, makeAny( (sal_Bool
)sal_True
) );
3086 catch (const Exception
& )
3088 DBG_UNHANDLED_EXCEPTION();
3093 //------------------------------------------------------------------------------
3094 void FmXFormShell::stopFiltering(sal_Bool bSave
)
3096 if ( impl_checkDisposed() )
3099 m_bFilterMode
= sal_False
;
3101 FmXFormView
* pXView
= m_pShell
->GetFormView()->GetImpl();
3103 // if the active controller is our external one we have to use the trigger controller
3104 Reference
< XControlContainer
> xContainer
;
3105 if (getActiveController() == m_xExternalViewController
)
3107 DBG_ASSERT(m_xExtViewTriggerController
.is(), "FmXFormShell::stopFiltering : inconsistent : active external controller, but noone triggered this !");
3108 xContainer
= m_xExtViewTriggerController
->getContainer();
3111 xContainer
= getActiveController()->getContainer();
3113 PFormViewPageWindowAdapter pAdapter
= pXView
->findWindow(xContainer
);
3114 if ( pAdapter
.is() )
3116 const ::std::vector
< Reference
< runtime::XFormController
> >& rControllerList
= pAdapter
->GetList();
3117 ::std::vector
< ::rtl::OUString
> aOriginalFilters
;
3118 ::std::vector
< sal_Bool
> aOriginalApplyFlags
;
3122 for (::std::vector
< Reference
< runtime::XFormController
> > ::const_iterator j
= rControllerList
.begin();
3123 j
!= rControllerList
.end(); ++j
)
3126 { // remember the current filter settings in case we're goin to reload the forms below (which may fail)
3129 Reference
< XPropertySet
> xFormAsSet((*j
)->getModel(), UNO_QUERY
);
3130 aOriginalFilters
.push_back(::comphelper::getString(xFormAsSet
->getPropertyValue(FM_PROP_FILTER
)));
3131 aOriginalApplyFlags
.push_back(::comphelper::getBOOL(xFormAsSet
->getPropertyValue(FM_PROP_APPLYFILTER
)));
3135 OSL_FAIL("FmXFormShell::stopFiltering : could not get the original filter !");
3136 // put dummies into the arrays so the they have the right size
3138 if (aOriginalFilters
.size() == aOriginalApplyFlags
.size())
3139 // the first getPropertyValue failed -> use two dummies
3140 aOriginalFilters
.push_back( ::rtl::OUString() );
3141 aOriginalApplyFlags
.push_back( sal_False
);
3147 for (::std::vector
< Reference
< runtime::XFormController
> > ::const_iterator j
= rControllerList
.begin();
3148 j
!= rControllerList
.end(); ++j
)
3151 Reference
< XModeSelector
> xModeSelector(*j
, UNO_QUERY
);
3152 if (xModeSelector
.is())
3153 xModeSelector
->setMode( ::rtl::OUString( "DataMode" ) );
3155 if (bSave
) // execute the filter
3157 const ::std::vector
< Reference
< runtime::XFormController
> > & rControllers
= pAdapter
->GetList();
3158 for (::std::vector
< Reference
< runtime::XFormController
> > ::const_iterator j
= rControllers
.begin();
3159 j
!= rControllers
.end(); ++j
)
3161 Reference
< XLoadable
> xReload((*j
)->getModel(), UNO_QUERY
);
3164 Reference
< XPropertySet
> xFormSet(xReload
, UNO_QUERY
);
3172 OSL_FAIL("FmXFormShell::stopFiltering: Exception occurred!");
3175 if (!isRowSetAlive(xFormSet
))
3176 { // something went wrong -> restore the original state
3177 ::rtl::OUString sOriginalFilter
= aOriginalFilters
[ j
- rControllers
.begin() ];
3178 sal_Bool bOriginalApplyFlag
= aOriginalApplyFlags
[ j
- rControllers
.begin() ];
3181 xFormSet
->setPropertyValue(FM_PROP_FILTER
, makeAny(sOriginalFilter
));
3182 xFormSet
->setPropertyValue(FM_PROP_APPLYFILTER
, makeAny(bOriginalApplyFlag
));
3185 catch(const Exception
&)
3187 DBG_UNHANDLED_EXCEPTION();
3194 m_pShell
->UIFeatureChanged();
3195 m_pShell
->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell
);
3198 //------------------------------------------------------------------------------
3199 void FmXFormShell::CreateExternalView()
3201 if ( impl_checkDisposed() )
3204 DBG_ASSERT(m_xAttachedFrame
.is(), "FmXFormShell::CreateExternalView : no frame !");
3206 // the frame the external view is displayed in
3207 sal_Bool bAlreadyExistent
= m_xExternalViewController
.is();
3208 Reference
< ::com::sun::star::frame::XFrame
> xExternalViewFrame
;
3209 ::rtl::OUString
sFrameName("_beamer");
3210 sal_Int32 nSearchFlags
= ::com::sun::star::frame::FrameSearchFlag::CHILDREN
| ::com::sun::star::frame::FrameSearchFlag::CREATE
;
3212 Reference
< runtime::XFormController
> xCurrentNavController( getNavController());
3213 // the creation of the "partwindow" may cause a deactivate of the document which will result in our nav controller to be set to NULL
3215 // _first_ check if we have any valid fields we can use for the grid view
3216 // FS - 21.10.99 - 69219
3218 FmXBoundFormFieldIterator
aModelIterator(xCurrentNavController
->getModel());
3219 Reference
< XPropertySet
> xCurrentModelSet
;
3220 sal_Bool bHaveUsableControls
= sal_False
;
3221 while ((xCurrentModelSet
= Reference
< XPropertySet
>(aModelIterator
.Next(), UNO_QUERY
)).is())
3223 // the FmXBoundFormFieldIterator only supplies controls with a valid control source
3224 // so we just have to check the field type
3225 sal_Int16 nClassId
= ::comphelper::getINT16(xCurrentModelSet
->getPropertyValue(FM_PROP_CLASSID
));
3228 case FormComponentType::IMAGECONTROL
:
3229 case FormComponentType::CONTROL
:
3232 bHaveUsableControls
= sal_True
;
3236 if (!bHaveUsableControls
)
3238 ErrorBox(NULL
, WB_OK
, SVX_RESSTR(RID_STR_NOCONTROLS_FOR_EXTERNALDISPLAY
)).Execute();
3243 // load the component for external form views
3244 if (!bAlreadyExistent
)
3246 URL aWantToDispatch
;
3247 aWantToDispatch
.Complete
= FMURL_COMPONENT_FORMGRIDVIEW
;
3249 Reference
< ::com::sun::star::frame::XDispatchProvider
> xProv(m_xAttachedFrame
, UNO_QUERY
);
3250 Reference
< ::com::sun::star::frame::XDispatch
> xDisp
;
3252 xDisp
= xProv
->queryDispatch(aWantToDispatch
, sFrameName
, nSearchFlags
);
3255 xDisp
->dispatch(aWantToDispatch
, Sequence
< PropertyValue
>());
3258 // with this the component should be loaded, now search the frame where it resides in
3259 xExternalViewFrame
= m_xAttachedFrame
->findFrame(sFrameName
, ::com::sun::star::frame::FrameSearchFlag::CHILDREN
);
3260 if (xExternalViewFrame
.is())
3262 m_xExternalViewController
= xExternalViewFrame
->getController();
3263 Reference
< ::com::sun::star::lang::XComponent
> xComp(m_xExternalViewController
, UNO_QUERY
);
3265 xComp
->addEventListener((XEventListener
*)(XPropertyChangeListener
*)this);
3270 xExternalViewFrame
= m_xExternalViewController
->getFrame();
3271 Reference
< ::com::sun::star::frame::XDispatchProvider
> xCommLink(xExternalViewFrame
, UNO_QUERY
);
3273 // if we display the active form we interpret the slot as "remove it"
3274 Reference
< XForm
> xCurrentModel(xCurrentNavController
->getModel(), UNO_QUERY
);
3275 if ((xCurrentModel
== m_xExternalDisplayedForm
) || (getInternalForm(xCurrentModel
) == m_xExternalDisplayedForm
))
3277 if ( m_xExternalViewController
== getActiveController() )
3279 Reference
< runtime::XFormController
> xAsFormController( m_xExternalViewController
, UNO_QUERY
);
3280 ControllerFeatures
aHelper( ::comphelper::getProcessServiceFactory(), xAsFormController
, NULL
);
3281 aHelper
->commitCurrentControl();
3284 Reference
< runtime::XFormController
> xNewController(m_xExtViewTriggerController
);
3285 CloseExternalFormViewer();
3286 setActiveController(xNewController
);
3291 aClearURL
.Complete
= FMURL_GRIDVIEW_CLEARVIEW
;
3293 Reference
< ::com::sun::star::frame::XDispatch
> xClear( xCommLink
->queryDispatch(aClearURL
, ::rtl::OUString(), 0));
3295 xClear
->dispatch(aClearURL
, Sequence
< PropertyValue
>());
3298 // TODO: We need an interceptor at the xSupplier, which forwards all queryDispatch requests to the FormController
3299 // instance for which this "external view" was triggered
3301 // get the dispatch interface of the frame so we can communicate (interceptable) with the controller
3302 Reference
< ::com::sun::star::frame::XDispatchProvider
> xCommLink(xExternalViewFrame
, UNO_QUERY
);
3304 if (m_xExternalViewController
.is())
3306 DBG_ASSERT(xCommLink
.is(), "FmXFormShell::CreateExternalView : the component doesn't have the necessary interfaces !");
3307 // collect the dispatchers we will need
3309 aAddColumnURL
.Complete
= FMURL_GRIDVIEW_ADDCOLUMN
;
3310 Reference
< ::com::sun::star::frame::XDispatch
> xAddColumnDispatch( xCommLink
->queryDispatch(aAddColumnURL
, ::rtl::OUString(), 0));
3312 aAttachURL
.Complete
= FMURL_GRIDVIEW_ATTACHTOFORM
;
3313 Reference
< ::com::sun::star::frame::XDispatch
> xAttachDispatch( xCommLink
->queryDispatch(aAttachURL
, ::rtl::OUString(), 0));
3315 if (xAddColumnDispatch
.is() && xAttachDispatch
.is())
3317 DBG_ASSERT(xCurrentNavController
.is(), "FmXFormShell::CreateExternalView : invalid call : have no nav controller !");
3318 // first : dispatch the descriptions for the columns to add
3319 Sequence
< Reference
< XControl
> > aCurrentControls(xCurrentNavController
->getControls());
3321 sal_Int16 nAddedColumns
= 0;
3323 // for radio buttons we need some special structures
3324 DECLARE_STL_USTRINGACCESS_MAP(Sequence
< ::rtl::OUString
>, MapUString2UstringSeq
);
3325 DECLARE_STL_ITERATORS(MapUString2UstringSeq
);
3326 DECLARE_STL_USTRINGACCESS_MAP(::rtl::OUString
, FmMapUString2UString
);
3327 DECLARE_STL_USTRINGACCESS_MAP(sal_Int16
, FmMapUString2Int16
);
3328 DECLARE_STL_ITERATORS(FmMapUString2Int16
);
3330 MapUString2UstringSeq aRadioValueLists
;
3331 MapUString2UstringSeq aRadioListSources
;
3332 FmMapUString2UString aRadioControlSources
;
3333 FmMapUString2Int16 aRadioPositions
;
3335 FmXBoundFormFieldIterator
aModelIterator(xCurrentNavController
->getModel());
3336 Reference
< XPropertySet
> xCurrentModelSet
;
3337 Any aCurrentBoundField
;
3338 ::rtl::OUString sColumnType
,aGroupName
,sControlSource
;
3339 Sequence
< Property
> aProps
;
3340 Reference
< XPropertySet
> xCurrentBoundField
;
3341 while ((xCurrentModelSet
= Reference
< XPropertySet
>(aModelIterator
.Next(), UNO_QUERY
)).is())
3343 xCurrentModelSet
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xCurrentBoundField
;
3344 OSL_ENSURE(xCurrentModelSet
.is(),"xCurrentModelSet is null!");
3345 // create a description of the column to be created
3346 // first : determine it's type
3348 sal_Int16 nClassId
= ::comphelper::getINT16(xCurrentModelSet
->getPropertyValue(FM_PROP_CLASSID
));
3351 case FormComponentType::RADIOBUTTON
:
3353 // get the label of the button (this is the access key for our structures)
3354 aGroupName
= getLabelName(xCurrentModelSet
);
3356 // add the reference value of the radio button to the list source sequence
3357 Sequence
< ::rtl::OUString
>& aThisGroupLabels
= aRadioListSources
[aGroupName
];
3358 sal_Int32 nNewSizeL
= aThisGroupLabels
.getLength() + 1;
3359 aThisGroupLabels
.realloc(nNewSizeL
);
3360 aThisGroupLabels
.getArray()[nNewSizeL
- 1] = ::comphelper::getString(xCurrentModelSet
->getPropertyValue(FM_PROP_REFVALUE
));
3362 // add the label to the value list sequence
3363 Sequence
< ::rtl::OUString
>& aThisGroupControlSources
= aRadioValueLists
[aGroupName
];
3364 sal_Int32 nNewSizeC
= aThisGroupControlSources
.getLength() + 1;
3365 aThisGroupControlSources
.realloc(nNewSizeC
);
3366 aThisGroupControlSources
.getArray()[nNewSizeC
- 1] = ::comphelper::getString(xCurrentModelSet
->getPropertyValue(FM_PROP_LABEL
));
3368 // remember the controls source of the radio group
3369 sControlSource
= ::comphelper::getString(xCurrentModelSet
->getPropertyValue(FM_PROP_CONTROLSOURCE
));
3370 if (aRadioControlSources
.find(aGroupName
) == aRadioControlSources
.end())
3371 aRadioControlSources
[aGroupName
] = sControlSource
;
3374 DBG_ASSERT(aRadioControlSources
[aGroupName
] == sControlSource
,
3375 "FmXFormShell::CreateExternalView : inconsistent radio buttons detected !");
3376 // (radio buttons with the same name should have the same control source)
3378 // remember the position within the columns
3379 if (aRadioPositions
.find(aGroupName
) == aRadioPositions
.end())
3380 aRadioPositions
[aGroupName
] = (sal_Int16
)nAddedColumns
;
3382 // any further handling is done below
3386 case FormComponentType::IMAGECONTROL
:
3387 case FormComponentType::CONTROL
:
3388 // no grid columns for these types (though they have a control source)
3390 case FormComponentType::CHECKBOX
:
3391 sColumnType
= FM_COL_CHECKBOX
; break;
3392 case FormComponentType::LISTBOX
:
3393 sColumnType
= FM_COL_LISTBOX
; break;
3394 case FormComponentType::COMBOBOX
:
3395 sColumnType
= FM_COL_COMBOBOX
; break;
3396 case FormComponentType::DATEFIELD
:
3397 sColumnType
= FM_COL_DATEFIELD
; break;
3398 case FormComponentType::TIMEFIELD
:
3399 sColumnType
= FM_COL_TIMEFIELD
; break;
3400 case FormComponentType::NUMERICFIELD
:
3401 sColumnType
= FM_COL_NUMERICFIELD
; break;
3402 case FormComponentType::CURRENCYFIELD
:
3403 sColumnType
= FM_COL_CURRENCYFIELD
; break;
3404 case FormComponentType::PATTERNFIELD
:
3405 sColumnType
= FM_COL_PATTERNFIELD
; break;
3407 case FormComponentType::TEXTFIELD
:
3409 sColumnType
= FM_COL_TEXTFIELD
;
3410 // we know at least two different controls which are TextFields : the basic edit field and the formatted
3411 // field. we distinguish them by their service name
3412 Reference
< XServiceInfo
> xInfo(xCurrentModelSet
, UNO_QUERY
);
3415 sal_Int16 nObjectType
= getControlTypeByObject(xInfo
);
3416 if (OBJ_FM_FORMATTEDFIELD
== nObjectType
)
3417 sColumnType
= FM_COL_FORMATTEDFIELD
;
3422 sColumnType
= FM_COL_TEXTFIELD
; break;
3425 const sal_Int16 nDispatchArgs
= 3;
3426 Sequence
< PropertyValue
> aDispatchArgs(nDispatchArgs
);
3427 PropertyValue
* pDispatchArgs
= aDispatchArgs
.getArray();
3429 // properties describing "meta data" about the column
3431 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNTYPE
;
3432 pDispatchArgs
->Value
<<= sColumnType
;
3435 // the pos : append the col
3436 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNPOS
;
3437 pDispatchArgs
->Value
<<= nAddedColumns
;
3440 // the properties to forward to the new column
3441 Sequence
< PropertyValue
> aColumnProps(1);
3442 PropertyValue
* pColumnProps
= aColumnProps
.getArray();
3445 pColumnProps
->Name
= FM_PROP_LABEL
;
3446 pColumnProps
->Value
<<= getLabelName(xCurrentModelSet
);
3449 // for all other props : transfer them
3450 Reference
< XPropertySetInfo
> xControlModelInfo( xCurrentModelSet
->getPropertySetInfo());
3451 DBG_ASSERT(xControlModelInfo
.is(), "FmXFormShell::CreateExternalView : the control model has no property info ! This will crash !");
3452 aProps
= xControlModelInfo
->getProperties();
3453 const Property
* pProps
= aProps
.getConstArray();
3455 // realloc the control description sequence
3456 sal_Int32 nExistentDescs
= pColumnProps
- aColumnProps
.getArray();
3457 aColumnProps
.realloc(nExistentDescs
+ aProps
.getLength());
3458 pColumnProps
= aColumnProps
.getArray() + nExistentDescs
;
3460 for (sal_Int32 i
=0; i
<aProps
.getLength(); ++i
, ++pProps
)
3462 if (pProps
->Name
.equals(FM_PROP_LABEL
))
3465 if (pProps
->Name
.equals(FM_PROP_DEFAULTCONTROL
))
3466 // allow the column's own "default control"
3468 if (pProps
->Attributes
& PropertyAttribute::READONLY
)
3469 // assume that properties which are readonly for the control are ro for the column to be created, too
3472 pColumnProps
->Name
= pProps
->Name
;
3473 pColumnProps
->Value
= xCurrentModelSet
->getPropertyValue(pProps
->Name
);
3476 aColumnProps
.realloc(pColumnProps
- aColumnProps
.getArray());
3478 // columns props are a dispatch argument
3479 pDispatchArgs
->Name
= ::rtl::OUString("ColumnProperties"); // TODO : fmurl.*
3480 pDispatchArgs
->Value
= makeAny(aColumnProps
);
3482 DBG_ASSERT(nDispatchArgs
== (pDispatchArgs
- aDispatchArgs
.getConstArray()),
3483 "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
3485 // dispatch the "add column"
3486 xAddColumnDispatch
->dispatch(aAddColumnURL
, aDispatchArgs
);
3490 // now for the radio button handling
3491 sal_Int16
nOffset(0);
3492 // properties describing the "direct" column properties
3493 const sal_Int16 nListBoxDescription
= 6;
3494 Sequence
< PropertyValue
> aListBoxDescription(nListBoxDescription
);
3495 for ( ConstFmMapUString2UStringIterator aCtrlSource
= aRadioControlSources
.begin();
3496 aCtrlSource
!= aRadioControlSources
.end();
3497 ++aCtrlSource
, ++nOffset
3501 PropertyValue
* pListBoxDescription
= aListBoxDescription
.getArray();
3503 pListBoxDescription
->Name
= FM_PROP_LABEL
;
3504 pListBoxDescription
->Value
<<= (*aCtrlSource
).first
;
3505 ++pListBoxDescription
;
3508 pListBoxDescription
->Name
= FM_PROP_CONTROLSOURCE
;
3509 pListBoxDescription
->Value
<<= (*aCtrlSource
).second
;
3510 ++pListBoxDescription
;
3513 pListBoxDescription
->Name
= FM_PROP_BOUNDCOLUMN
;
3514 pListBoxDescription
->Value
<<= (sal_Int16
)1;
3515 ++pListBoxDescription
;
3518 pListBoxDescription
->Name
= FM_PROP_LISTSOURCETYPE
;
3519 ListSourceType eType
= ListSourceType_VALUELIST
;
3520 pListBoxDescription
->Value
= makeAny(eType
);
3521 ++pListBoxDescription
;
3524 MapUString2UstringSeq::const_iterator aCurrentListSource
= aRadioListSources
.find((*aCtrlSource
).first
);
3525 DBG_ASSERT(aCurrentListSource
!= aRadioListSources
.end(),
3526 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3527 pListBoxDescription
->Name
= FM_PROP_LISTSOURCE
;
3528 pListBoxDescription
->Value
= makeAny((*aCurrentListSource
).second
);
3529 ++pListBoxDescription
;
3532 MapUString2UstringSeq::const_iterator aCurrentValueList
= aRadioValueLists
.find((*aCtrlSource
).first
);
3533 DBG_ASSERT(aCurrentValueList
!= aRadioValueLists
.end(),
3534 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3535 pListBoxDescription
->Name
= FM_PROP_STRINGITEMLIST
;
3536 pListBoxDescription
->Value
= makeAny(((*aCurrentValueList
).second
));
3537 ++pListBoxDescription
;
3539 DBG_ASSERT(nListBoxDescription
== (pListBoxDescription
- aListBoxDescription
.getConstArray()),
3540 "FmXFormShell::CreateExternalView : forgot to adjust nListBoxDescription ?");
3542 // properties describing the column "meta data"
3543 const sal_Int16 nDispatchArgs
= 3;
3544 Sequence
< PropertyValue
> aDispatchArgs(nDispatchArgs
);
3545 PropertyValue
* pDispatchArgs
= aDispatchArgs
.getArray();
3547 // column type : listbox
3548 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNTYPE
;
3549 ::rtl::OUString fColName
= FM_COL_LISTBOX
;
3550 pDispatchArgs
->Value
<<= fColName
;
3551 // pDispatchArgs->Value <<= (::rtl::OUString)FM_COL_LISTBOX;
3555 pDispatchArgs
->Name
= FMARG_ADDCOL_COLUMNPOS
;
3556 FmMapUString2Int16::const_iterator aOffset
= aRadioPositions
.find((*aCtrlSource
).first
);
3557 DBG_ASSERT(aOffset
!= aRadioPositions
.end(),
3558 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !");
3559 sal_Int16 nPosition
= (*aOffset
).second
;
3560 nPosition
= nPosition
+ nOffset
;
3561 // we alread inserted nOffset additinal columns ....
3562 pDispatchArgs
->Value
<<= nPosition
;
3566 pDispatchArgs
->Name
= ::rtl::OUString("ColumnProperties"); // TODO : fmurl.*
3567 pDispatchArgs
->Value
= makeAny(aListBoxDescription
);
3569 DBG_ASSERT(nDispatchArgs
== (pDispatchArgs
- aDispatchArgs
.getConstArray()),
3570 "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?");
3572 // dispatch the "add column"
3573 xAddColumnDispatch
->dispatch(aAddColumnURL
, aDispatchArgs
);
3578 DBG_ASSERT(nAddedColumns
> 0, "FmXFormShell::CreateExternalView : no controls (inconsistent) !");
3579 // we should have checked if we have any usable controls (see above).
3581 // "load" the "form" of the external view
3583 aArg
.Name
= FMARG_ATTACHTO_MASTERFORM
;
3584 Reference
< XResultSet
> xForm(xCurrentNavController
->getModel(), UNO_QUERY
);
3585 aArg
.Value
<<= xForm
;
3587 m_xExternalDisplayedForm
= Reference
< XResultSet
>(xForm
, UNO_QUERY
);
3588 // do this before dispatching the "attach" command, as the atach may result in a call to our queryDispatch (for the FormSlots)
3589 // whichs needs the m_xExternalDisplayedForm
3591 xAttachDispatch
->dispatch(aAttachURL
, Sequence
< PropertyValue
>(&aArg
, 1));
3593 m_xExtViewTriggerController
= xCurrentNavController
;
3595 // we want to know modifications done in the external view
3596 // if the external controller is a XFormController we can use all our default handlings for it
3597 Reference
< runtime::XFormController
> xFormController( m_xExternalViewController
, UNO_QUERY
);
3598 OSL_ENSURE( xFormController
.is(), "FmXFormShell::CreateExternalView:: invalid external view controller!" );
3599 if (xFormController
.is())
3600 xFormController
->addActivateListener((XFormControllerListener
*)this);
3606 OSL_FAIL("FmXFormShell::CreateExternalView : could not create the external form view !");
3609 InvalidateSlot( SID_FM_VIEW_AS_GRID
, sal_False
);
3612 //------------------------------------------------------------------------
3613 void FmXFormShell::implAdjustConfigCache()
3615 // get (cache) the wizard usage flag
3616 Sequence
< ::rtl::OUString
> aNames(1);
3617 aNames
[0] = ::rtl::OUString("FormControlPilotsEnabled");
3618 Sequence
< Any
> aFlags
= GetProperties(aNames
);
3619 if (1 == aFlags
.getLength())
3620 m_bUseWizards
= ::cppu::any2bool(aFlags
[0]);
3623 //------------------------------------------------------------------------
3624 void FmXFormShell::Notify( const com::sun::star::uno::Sequence
< rtl::OUString
>& _rPropertyNames
)
3626 if ( impl_checkDisposed() )
3629 const ::rtl::OUString
* pSearch
= _rPropertyNames
.getConstArray();
3630 const ::rtl::OUString
* pSearchTil
= pSearch
+ _rPropertyNames
.getLength();
3631 for (;pSearch
< pSearchTil
; ++pSearch
)
3632 if (0 == pSearch
->compareToAscii("FormControlPilotsEnabled"))
3634 implAdjustConfigCache();
3635 InvalidateSlot( SID_FM_USE_WIZARDS
, sal_True
);
3639 void FmXFormShell::Commit()
3643 //------------------------------------------------------------------------
3644 void FmXFormShell::SetWizardUsing(sal_Bool _bUseThem
)
3646 m_bUseWizards
= _bUseThem
;
3648 Sequence
< ::rtl::OUString
> aNames(1);
3649 aNames
[0] = ::rtl::OUString("FormControlPilotsEnabled");
3650 Sequence
< Any
> aValues(1);
3651 aValues
[0] = ::cppu::bool2any(m_bUseWizards
);
3652 PutProperties(aNames
, aValues
);
3655 //------------------------------------------------------------------------
3656 void FmXFormShell::viewDeactivated( FmFormView
& _rCurrentView
, sal_Bool _bDeactivateController
/* = sal_True */ )
3659 if ( _rCurrentView
.GetImpl() && !_rCurrentView
.IsDesignMode() )
3661 _rCurrentView
.GetImpl()->Deactivate( _bDeactivateController
);
3664 // if we have an async load operation pending for the 0-th page for this view,
3665 // we need to cancel this
3666 FmFormPage
* pPage
= _rCurrentView
.GetCurPage();
3669 // move all events from our queue to a new one, omit the events for the deactivated
3671 ::std::queue
< FmLoadAction
> aNewEvents
;
3672 while ( !m_aLoadingPages
.empty() )
3674 FmLoadAction aAction
= m_aLoadingPages
.front();
3675 m_aLoadingPages
.pop();
3676 if ( pPage
!= aAction
.pPage
)
3678 aNewEvents
.push( aAction
);
3682 Application::RemoveUserEvent( aAction
.nEventId
);
3685 m_aLoadingPages
= aNewEvents
;
3688 // remove callbacks at the page
3691 pPage
->GetImpl().SetFormsCreationHdl( Link() );
3693 UpdateForms( sal_True
);
3696 //------------------------------------------------------------------------
3697 IMPL_LINK( FmXFormShell
, OnFirstTimeActivation
, void*, /*NOTINTERESTEDIN*/ )
3699 if ( impl_checkDisposed() )
3702 m_nActivationEvent
= 0;
3703 SfxObjectShell
* pDocument
= m_pShell
->GetObjectShell();
3705 if ( pDocument
&& !pDocument
->HasName() )
3707 if ( isEnhancedForm() )
3709 // show the data navigator
3710 if ( !m_pShell
->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_DATANAVIGATOR
) )
3711 m_pShell
->GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_SHOW_DATANAVIGATOR
);
3718 //------------------------------------------------------------------------
3719 IMPL_LINK( FmXFormShell
, OnFormsCreated
, FmFormPage
*, /*_pPage*/ )
3721 UpdateForms( sal_True
);
3725 //------------------------------------------------------------------------
3726 void FmXFormShell::viewActivated( FmFormView
& _rCurrentView
, sal_Bool _bSyncAction
/* = sal_False */ )
3729 FmFormPage
* pPage
= _rCurrentView
.GetCurPage();
3731 // activate our view if we are activated ourself
3732 // FS - 30.06.99 - 67308
3733 if ( _rCurrentView
.GetImpl() && !_rCurrentView
.IsDesignMode() )
3735 // load forms for the page the current view belongs to
3738 if ( !pPage
->GetImpl().hasEverBeenActivated() )
3739 loadForms( pPage
, FORMS_LOAD
| ( _bSyncAction
? FORMS_SYNC
: FORMS_ASYNC
) );
3740 pPage
->GetImpl().setHasBeenActivated( );
3743 // first-time initializations for the views
3744 if ( !_rCurrentView
.GetImpl()->hasEverBeenActivated( ) )
3746 _rCurrentView
.GetImpl()->onFirstViewActivation( PTR_CAST( FmFormModel
, _rCurrentView
.GetModel() ) );
3747 _rCurrentView
.GetImpl()->setHasBeenActivated( );
3750 // activate the current view
3751 _rCurrentView
.GetImpl()->Activate( _bSyncAction
);
3754 // set callbacks at the page
3757 pPage
->GetImpl().SetFormsCreationHdl( LINK( this, FmXFormShell
, OnFormsCreated
) );
3760 UpdateForms( sal_True
);
3762 if ( !hasEverBeenActivated() )
3764 m_nActivationEvent
= Application::PostUserEvent( LINK( this, FmXFormShell
, OnFirstTimeActivation
) );
3765 setHasBeenActivated();
3768 // find a default "current form", if there is none, yet
3769 // #i88186# / 2008-04-12 / frank.schoenheit@sun.com
3770 impl_defaultCurrentForm_nothrow();
3773 //------------------------------------------------------------------------------
3774 void FmXFormShell::impl_defaultCurrentForm_nothrow()
3776 if ( impl_checkDisposed() )
3779 if ( m_xCurrentForm
.is() )
3780 // no action required
3783 FmFormView
* pFormView
= m_pShell
->GetFormView();
3784 FmFormPage
* pPage
= pFormView
? pFormView
->GetCurPage() : NULL
;
3790 Reference
< XIndexAccess
> xForms( pPage
->GetForms( false ), UNO_QUERY
);
3791 if ( !xForms
.is() || !xForms
->hasElements() )
3794 Reference
< XForm
> xNewCurrentForm( xForms
->getByIndex(0), UNO_QUERY_THROW
);
3795 impl_updateCurrentForm( xNewCurrentForm
);
3797 catch( const Exception
& )
3799 DBG_UNHANDLED_EXCEPTION();
3803 //------------------------------------------------------------------------------
3804 void FmXFormShell::smartControlReset( const Reference
< XIndexAccess
>& _rxModels
)
3806 if (!_rxModels
.is())
3808 OSL_FAIL("FmXFormShell::smartControlReset: invalid container!");
3812 static const ::rtl::OUString sClassIdPropertyName
= FM_PROP_CLASSID
;
3813 static const ::rtl::OUString sBoundFieldPropertyName
= FM_PROP_BOUNDFIELD
;
3814 sal_Int32 nCount
= _rxModels
->getCount();
3815 Reference
< XPropertySet
> xCurrent
;
3816 Reference
< XPropertySetInfo
> xCurrentInfo
;
3817 Reference
< XPropertySet
> xBoundField
;
3819 for (sal_Int32 i
=0; i
<nCount
; ++i
)
3821 _rxModels
->getByIndex(i
) >>= xCurrent
;
3823 xCurrentInfo
= xCurrent
->getPropertySetInfo();
3825 xCurrentInfo
.clear();
3826 if (!xCurrentInfo
.is())
3829 if (xCurrentInfo
->hasPropertyByName(sClassIdPropertyName
))
3830 { // it's a control model
3832 // check if this control is bound to a living database field
3833 if (xCurrentInfo
->hasPropertyByName(sBoundFieldPropertyName
))
3834 xCurrent
->getPropertyValue(sBoundFieldPropertyName
) >>= xBoundField
;
3836 xBoundField
.clear();
3838 // reset only if it's *not* bound
3839 bool bReset
= !xBoundField
.is();
3841 // and additionally, check if it has an external value binding
3842 Reference
< XBindableValue
> xBindable( xCurrent
, UNO_QUERY
);
3843 if ( xBindable
.is() && xBindable
->getValueBinding().is() )
3848 Reference
< XReset
> xControlReset( xCurrent
, UNO_QUERY
);
3849 if ( xControlReset
.is() )
3850 xControlReset
->reset();
3855 Reference
< XIndexAccess
> xContainer(xCurrent
, UNO_QUERY
);
3856 if (xContainer
.is())
3857 smartControlReset(xContainer
);
3862 //------------------------------------------------------------------------
3863 IMPL_LINK( FmXFormShell
, OnLoadForms
, FmFormPage
*, /*_pPage*/ )
3865 FmLoadAction aAction
= m_aLoadingPages
.front();
3866 m_aLoadingPages
.pop();
3868 loadForms( aAction
.pPage
, aAction
.nFlags
& ~FORMS_ASYNC
);
3872 //------------------------------------------------------------------------------
3875 sal_Bool
lcl_isLoadable( const Reference
< XInterface
>& _rxLoadable
)
3877 // determines whether a form should be loaded or not
3878 // if there is no datasource or connection there is no reason to load a form
3879 Reference
< XPropertySet
> xSet( _rxLoadable
, UNO_QUERY
);
3884 Reference
< XConnection
> xConn
;
3885 if ( OStaticDataAccessTools().isEmbeddedInDatabase( _rxLoadable
.get(), xConn
) )
3888 // is there already a active connection
3889 xSet
->getPropertyValue(FM_PROP_ACTIVE_CONNECTION
) >>= xConn
;
3893 ::rtl::OUString sPropertyValue
;
3894 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_DATASOURCE
) >>= sPropertyValue
);
3895 if ( !sPropertyValue
.isEmpty() )
3898 OSL_VERIFY( xSet
->getPropertyValue( FM_PROP_URL
) >>= sPropertyValue
);
3899 if ( !sPropertyValue
.isEmpty() )
3902 catch(const Exception
&)
3904 DBG_UNHANDLED_EXCEPTION();
3910 //------------------------------------------------------------------------
3911 void FmXFormShell::loadForms( FmFormPage
* _pPage
, const sal_uInt16 _nBehaviour
/* FORMS_LOAD | FORMS_SYNC */ )
3913 DBG_ASSERT( ( _nBehaviour
& ( FORMS_ASYNC
| FORMS_UNLOAD
) ) != ( FORMS_ASYNC
| FORMS_UNLOAD
),
3914 "FmXFormShell::loadForms: async loading not supported - this will heavily fail!" );
3916 if ( _nBehaviour
& FORMS_ASYNC
)
3918 m_aLoadingPages
.push( FmLoadAction(
3921 Application::PostUserEvent( LINK( this, FmXFormShell
, OnLoadForms
), _pPage
)
3926 DBG_ASSERT( _pPage
, "FmXFormShell::loadForms: invalid page!" );
3929 // lock the undo env so the forms can change non-transient properties while loading
3930 // (without this my doc's modified flag would be set)
3931 FmFormModel
* pModel
= PTR_CAST( FmFormModel
, _pPage
->GetModel() );
3932 DBG_ASSERT( pModel
, "FmXFormShell::loadForms: invalid model!" );
3934 pModel
->GetUndoEnv().Lock();
3937 Reference
< XIndexAccess
> xForms
;
3938 xForms
= xForms
.query( _pPage
->GetForms( false ) );
3942 Reference
< XLoadable
> xForm
;
3943 sal_Bool bFormWasLoaded
= sal_False
;
3944 for ( sal_Int32 j
= 0, nCount
= xForms
->getCount(); j
< nCount
; ++j
)
3946 xForms
->getByIndex( j
) >>= xForm
;
3947 bFormWasLoaded
= sal_False
;
3948 // a database form must be loaded for
3951 if ( 0 == ( _nBehaviour
& FORMS_UNLOAD
) )
3953 if ( lcl_isLoadable( xForm
) && !xForm
->isLoaded() )
3958 if ( xForm
->isLoaded() )
3960 bFormWasLoaded
= sal_True
;
3965 catch( const Exception
& )
3967 DBG_UNHANDLED_EXCEPTION();
3970 // reset the form if it was loaded
3971 if ( bFormWasLoaded
)
3973 Reference
< XIndexAccess
> xContainer( xForm
, UNO_QUERY
);
3974 DBG_ASSERT( xContainer
.is(), "FmXFormShell::loadForms: the form is no container!" );
3975 if ( xContainer
.is() )
3976 smartControlReset( xContainer
);
3982 // unlock the environment
3983 pModel
->GetUndoEnv().UnLock();
3987 //------------------------------------------------------------------------
3988 void FmXFormShell::ExecuteTextAttribute( SfxRequest
& _rReq
)
3990 m_pTextShell
->ExecuteTextAttribute( _rReq
);
3993 //------------------------------------------------------------------------
3994 void FmXFormShell::GetTextAttributeState( SfxItemSet
& _rSet
)
3996 m_pTextShell
->GetTextAttributeState( _rSet
);
3999 //------------------------------------------------------------------------
4000 bool FmXFormShell::IsActiveControl( bool _bCountRichTextOnly
) const
4002 return m_pTextShell
->IsActiveControl( _bCountRichTextOnly
);
4005 //------------------------------------------------------------------------
4006 void FmXFormShell::ForgetActiveControl()
4008 m_pTextShell
->ForgetActiveControl();
4011 //------------------------------------------------------------------------
4012 void FmXFormShell::SetControlActivationHandler( const Link
& _rHdl
)
4014 m_pTextShell
->SetControlActivationHandler( _rHdl
);
4016 //------------------------------------------------------------------------
4017 void FmXFormShell::handleShowPropertiesRequest()
4019 if ( onlyControlsAreMarked() )
4020 ShowSelectionProperties( sal_True
);
4023 //------------------------------------------------------------------------
4024 void FmXFormShell::handleMouseButtonDown( const SdrViewEvent
& _rViewEvent
)
4026 // catch simple double clicks
4027 if ( ( _rViewEvent
.nMouseClicks
== 2 ) && ( _rViewEvent
.nMouseCode
== MOUSE_LEFT
) )
4029 if ( _rViewEvent
.eHit
== SDRHIT_MARKEDOBJECT
)
4031 if ( onlyControlsAreMarked() )
4032 ShowSelectionProperties( sal_True
);
4037 //------------------------------------------------------------------------------
4038 bool FmXFormShell::HasControlFocus() const
4040 bool bHasControlFocus
= false;
4044 Reference
< XFormController
> xController( getActiveController() );
4045 Reference
< XControl
> xCurrentControl
;
4046 if ( xController
.is() )
4047 xCurrentControl
.set( xController
->getCurrentControl() );
4048 if ( xCurrentControl
.is() )
4050 Reference
< XWindow2
> xPeerWindow( xCurrentControl
->getPeer(), UNO_QUERY_THROW
);
4051 bHasControlFocus
= xPeerWindow
->hasFocus();
4054 catch( const Exception
& )
4056 DBG_UNHANDLED_EXCEPTION();
4059 return bHasControlFocus
;
4062 //==============================================================================
4063 //==============================================================================
4064 SearchableControlIterator::SearchableControlIterator(Reference
< XInterface
> xStartingPoint
)
4065 :IndexAccessIterator(xStartingPoint
)
4069 //------------------------------------------------------------------------------
4070 sal_Bool
SearchableControlIterator::ShouldHandleElement(const Reference
< XInterface
>& xElement
)
4072 // wenn das Ding eine ControlSource und einen BoundField-Property hat
4073 Reference
< XPropertySet
> xProperties(xElement
, UNO_QUERY
);
4074 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE
, xProperties
) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD
, xProperties
))
4076 // und das BoundField gueltig ist
4077 Reference
< XPropertySet
> xField
;
4078 xProperties
->getPropertyValue(FM_PROP_BOUNDFIELD
) >>= xField
;
4082 m_sCurrentValue
= ::comphelper::getString(xProperties
->getPropertyValue(FM_PROP_CONTROLSOURCE
));
4087 // wenn es ein Grid-Control ist
4088 if (::comphelper::hasProperty(FM_PROP_CLASSID
, xProperties
))
4090 Any
aClassId( xProperties
->getPropertyValue(FM_PROP_CLASSID
) );
4091 if (::comphelper::getINT16(aClassId
) == FormComponentType::GRIDCONTROL
)
4093 m_sCurrentValue
= ::rtl::OUString();
4101 //------------------------------------------------------------------------------
4102 sal_Bool
SearchableControlIterator::ShouldStepInto(const Reference
< XInterface
>& /*xContainer*/) const
4107 //==============================================================================
4108 //==============================================================================
4110 SFX_IMPL_MENU_CONTROL(ControlConversionMenuController
, SfxBoolItem
);
4112 //------------------------------------------------------------------------------
4113 ControlConversionMenuController::ControlConversionMenuController( sal_uInt16 _nId
, Menu
& _rMenu
, SfxBindings
& _rBindings
)
4114 :SfxMenuControl( _nId
, _rBindings
)
4115 ,m_pMainMenu( &_rMenu
)
4116 ,m_pConversionMenu( NULL
)
4118 if ( _nId
== SID_FM_CHANGECONTROLTYPE
)
4120 m_pConversionMenu
= FmXFormShell::GetConversionMenu();
4121 _rMenu
.SetPopupMenu( _nId
, m_pConversionMenu
);
4123 for (sal_Int16 i
=0; i
<m_pConversionMenu
->GetItemCount(); ++i
)
4125 _rBindings
.Invalidate(m_pConversionMenu
->GetItemId(i
));
4126 SfxStatusForwarder
* pForwarder
= new SfxStatusForwarder(m_pConversionMenu
->GetItemId(i
), *this);
4127 m_aStatusForwarders
.push_back(pForwarder
);
4132 //------------------------------------------------------------------------------
4133 ControlConversionMenuController::~ControlConversionMenuController()
4135 m_pMainMenu
->SetPopupMenu(SID_FM_CHANGECONTROLTYPE
, NULL
);
4136 delete m_pConversionMenu
;
4139 //------------------------------------------------------------------------------
4140 void ControlConversionMenuController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
4142 if (nSID
== GetId())
4143 SfxMenuControl::StateChanged(nSID
, eState
, pState
);
4144 else if (FmXFormShell::isControlConversionSlot(nSID
))
4146 if ((m_pConversionMenu
->GetItemPos(nSID
) != MENU_ITEM_NOTFOUND
) && (eState
== SFX_ITEM_DISABLED
))
4148 m_pConversionMenu
->RemoveItem(m_pConversionMenu
->GetItemPos(nSID
));
4150 else if ((m_pConversionMenu
->GetItemPos(nSID
) == MENU_ITEM_NOTFOUND
) && (eState
!= SFX_ITEM_DISABLED
))
4152 // We can't simply re-insert the item because we have a clear order for all the our items.
4153 // So first we have to determine the position of the item to insert.
4154 PopupMenu
* pSource
= FmXFormShell::GetConversionMenu();
4155 sal_uInt16 nSourcePos
= pSource
->GetItemPos(nSID
);
4156 DBG_ASSERT(nSourcePos
!= MENU_ITEM_NOTFOUND
, "ControlConversionMenuController::StateChanged : FmXFormShell supplied an invalid menu !");
4157 sal_uInt16 nPrevInSource
= nSourcePos
;
4158 sal_uInt16 nPrevInConversion
= MENU_ITEM_NOTFOUND
;
4159 while (nPrevInSource
>0)
4161 sal_Int16 nPrevId
= pSource
->GetItemId(--nPrevInSource
);
4163 // do we have the source's predecessor in our conversion menu, too ?
4164 nPrevInConversion
= m_pConversionMenu
->GetItemPos(nPrevId
);
4165 if (nPrevInConversion
!= MENU_ITEM_NOTFOUND
)
4168 if (MENU_ITEM_NOTFOUND
== nPrevInConversion
)
4169 // none of the items which precede the nSID-slot in the source menu are present in our conversion menu
4170 nPrevInConversion
= sal::static_int_cast
< sal_uInt16
>(-1); // put the item at the first position
4171 m_pConversionMenu
->InsertItem(nSID
, pSource
->GetItemText(nSID
), pSource
->GetItemBits(nSID
), ++nPrevInConversion
);
4172 m_pConversionMenu
->SetItemImage(nSID
, pSource
->GetItemImage(nSID
));
4173 m_pConversionMenu
->SetHelpId(nSID
, pSource
->GetHelpId(nSID
));
4177 m_pMainMenu
->EnableItem(SID_FM_CHANGECONTROLTYPE
, m_pConversionMenu
->GetItemCount() > 0);
4181 OSL_FAIL("ControlConversionMenuController::StateChanged : unknown id !");
4185 //==============================================================================
4187 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */