1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svx.hxx" 30 31 #include "fmitems.hxx" 32 #include "fmobj.hxx" 33 #include "fmpgeimp.hxx" 34 #include "svx/fmtools.hxx" 35 #include "fmprop.hrc" 36 #include "svx/fmresids.hrc" 37 #include "fmservs.hxx" 38 #include "fmshimp.hxx" 39 #include "fmtextcontrolshell.hxx" 40 #include "fmundo.hxx" 41 #include "fmurl.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" 57 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 === **/ 90 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 <connectivity/dbtools.hxx> 97 #include <cppuhelper/servicefactory.hxx> 98 #include <osl/mutex.hxx> 99 #include <rtl/logfile.hxx> 100 #include <sfx2/dispatch.hxx> 101 #include <sfx2/docfile.hxx> 102 #include <sfx2/frame.hxx> 103 #include <sfx2/objsh.hxx> 104 #include <sfx2/viewfrm.hxx> 105 #include <sfx2/viewsh.hxx> 106 #include <toolkit/helper/vclunohelper.hxx> 107 #include <tools/color.hxx> 108 #include <tools/diagnose_ex.h> 109 #include <tools/shl.hxx> 110 #include <tools/urlobj.hxx> 111 #include <vcl/msgbox.hxx> 112 #include <vcl/waitobj.hxx> 113 #include <vos/mutex.hxx> 114 115 #include <algorithm> 116 #include <functional> 117 118 // wird fuer Invalidate verwendet -> mitpflegen 119 sal_uInt16 DatabaseSlotMap[] = 120 { 121 SID_FM_RECORD_FIRST, 122 SID_FM_RECORD_NEXT, 123 SID_FM_RECORD_PREV, 124 SID_FM_RECORD_LAST, 125 SID_FM_RECORD_NEW, 126 SID_FM_RECORD_DELETE, 127 SID_FM_RECORD_ABSOLUTE, 128 SID_FM_RECORD_TOTAL, 129 SID_FM_RECORD_SAVE, 130 SID_FM_RECORD_UNDO, 131 SID_FM_REMOVE_FILTER_SORT, 132 SID_FM_SORTUP, 133 SID_FM_SORTDOWN, 134 SID_FM_ORDERCRIT, 135 SID_FM_AUTOFILTER, 136 SID_FM_FORM_FILTERED, 137 SID_FM_REFRESH, 138 SID_FM_REFRESH_FORM_CONTROL, 139 SID_FM_SEARCH, 140 SID_FM_FILTER_START, 141 SID_FM_VIEW_AS_GRID, 142 0 143 }; 144 145 // wird fuer Invalidate verwendet -> mitpflegen 146 // aufsteigend sortieren !!!!!! 147 sal_Int16 DlgSlotMap[] = // slots des Controllers 148 { 149 SID_FM_CTL_PROPERTIES, 150 SID_FM_PROPERTIES, 151 SID_FM_TAB_DIALOG, 152 SID_FM_ADD_FIELD, 153 SID_FM_SHOW_FMEXPLORER, 154 SID_FM_FIELDS_CONTROL, 155 SID_FM_SHOW_PROPERTIES, 156 SID_FM_PROPERTY_CONTROL, 157 SID_FM_FMEXPLORER_CONTROL, 158 SID_FM_SHOW_DATANAVIGATOR, 159 SID_FM_DATANAVIGATOR_CONTROL, 160 0 161 }; 162 163 sal_Int16 SelObjectSlotMap[] = // vom SelObject abhaengige Slots 164 { 165 SID_FM_CONVERTTO_EDIT, 166 SID_FM_CONVERTTO_BUTTON, 167 SID_FM_CONVERTTO_FIXEDTEXT, 168 SID_FM_CONVERTTO_LISTBOX, 169 SID_FM_CONVERTTO_CHECKBOX, 170 SID_FM_CONVERTTO_RADIOBUTTON, 171 SID_FM_CONVERTTO_GROUPBOX, 172 SID_FM_CONVERTTO_COMBOBOX, 173 SID_FM_CONVERTTO_IMAGEBUTTON, 174 SID_FM_CONVERTTO_FILECONTROL, 175 SID_FM_CONVERTTO_DATE, 176 SID_FM_CONVERTTO_TIME, 177 SID_FM_CONVERTTO_NUMERIC, 178 SID_FM_CONVERTTO_CURRENCY, 179 SID_FM_CONVERTTO_PATTERN, 180 SID_FM_CONVERTTO_IMAGECONTROL, 181 SID_FM_CONVERTTO_FORMATTED, 182 SID_FM_CONVERTTO_SCROLLBAR, 183 SID_FM_CONVERTTO_SPINBUTTON, 184 SID_FM_CONVERTTO_NAVIGATIONBAR, 185 186 SID_FM_FMEXPLORER_CONTROL, 187 SID_FM_DATANAVIGATOR_CONTROL, 188 189 0 190 }; 191 192 // die folgenden Arrays muessen kosistent sein, also einander entsprechende Eintraege an der selben relativen Position 193 // innerhalb ihres jeweiligen Arrays stehen 194 sal_Int16 nConvertSlots[] = 195 { 196 SID_FM_CONVERTTO_EDIT, 197 SID_FM_CONVERTTO_BUTTON, 198 SID_FM_CONVERTTO_FIXEDTEXT, 199 SID_FM_CONVERTTO_LISTBOX, 200 SID_FM_CONVERTTO_CHECKBOX, 201 SID_FM_CONVERTTO_RADIOBUTTON, 202 SID_FM_CONVERTTO_GROUPBOX, 203 SID_FM_CONVERTTO_COMBOBOX, 204 SID_FM_CONVERTTO_IMAGEBUTTON, 205 SID_FM_CONVERTTO_FILECONTROL, 206 SID_FM_CONVERTTO_DATE, 207 SID_FM_CONVERTTO_TIME, 208 SID_FM_CONVERTTO_NUMERIC, 209 SID_FM_CONVERTTO_CURRENCY, 210 SID_FM_CONVERTTO_PATTERN, 211 SID_FM_CONVERTTO_IMAGECONTROL, 212 SID_FM_CONVERTTO_FORMATTED, 213 SID_FM_CONVERTTO_SCROLLBAR, 214 SID_FM_CONVERTTO_SPINBUTTON, 215 SID_FM_CONVERTTO_NAVIGATIONBAR 216 }; 217 218 sal_Int16 nCreateSlots[] = 219 { 220 SID_FM_EDIT, 221 SID_FM_PUSHBUTTON, 222 SID_FM_FIXEDTEXT, 223 SID_FM_LISTBOX, 224 SID_FM_CHECKBOX, 225 SID_FM_RADIOBUTTON, 226 SID_FM_GROUPBOX, 227 SID_FM_COMBOBOX, 228 SID_FM_IMAGEBUTTON, 229 SID_FM_FILECONTROL, 230 SID_FM_DATEFIELD, 231 SID_FM_TIMEFIELD, 232 SID_FM_NUMERICFIELD, 233 SID_FM_CURRENCYFIELD, 234 SID_FM_PATTERNFIELD, 235 SID_FM_IMAGECONTROL, 236 SID_FM_FORMATTEDFIELD, 237 SID_FM_SCROLLBAR, 238 SID_FM_SPINBUTTON, 239 SID_FM_NAVIGATIONBAR 240 }; 241 242 sal_Int16 nObjectTypes[] = 243 { 244 OBJ_FM_EDIT, 245 OBJ_FM_BUTTON, 246 OBJ_FM_FIXEDTEXT, 247 OBJ_FM_LISTBOX, 248 OBJ_FM_CHECKBOX, 249 OBJ_FM_RADIOBUTTON, 250 OBJ_FM_GROUPBOX, 251 OBJ_FM_COMBOBOX, 252 OBJ_FM_IMAGEBUTTON, 253 OBJ_FM_FILECONTROL, 254 OBJ_FM_DATEFIELD, 255 OBJ_FM_TIMEFIELD, 256 OBJ_FM_NUMERICFIELD, 257 OBJ_FM_CURRENCYFIELD, 258 OBJ_FM_PATTERNFIELD, 259 OBJ_FM_IMAGECONTROL, 260 OBJ_FM_FORMATTEDFIELD, 261 OBJ_FM_SCROLLBAR, 262 OBJ_FM_SPINBUTTON, 263 OBJ_FM_NAVIGATIONBAR 264 }; 265 266 using namespace ::com::sun::star; 267 using namespace ::com::sun::star::ui; 268 using namespace ::com::sun::star::uno; 269 using namespace ::com::sun::star::sdb; 270 using namespace ::com::sun::star::sdbc; 271 using namespace ::com::sun::star::sdbcx; 272 using namespace ::com::sun::star::beans; 273 using namespace ::com::sun::star::container; 274 using namespace ::com::sun::star::form; 275 using namespace ::com::sun::star::form::binding; 276 using namespace ::com::sun::star::form::runtime; 277 using namespace ::com::sun::star::awt; 278 using namespace ::com::sun::star::view; 279 using namespace ::com::sun::star::lang; 280 using namespace ::com::sun::star::util; 281 using namespace ::com::sun::star::frame; 282 using namespace ::com::sun::star::script; 283 using namespace ::svxform; 284 using namespace ::svx; 285 286 //============================================================================== 287 //= helper 288 //============================================================================== 289 namespace 290 { 291 //.......................................................................... 292 void collectInterfacesFromMarkList( const SdrMarkList& _rMarkList, InterfaceBag& /* [out] */ _rInterfaces ) 293 { 294 _rInterfaces.clear(); 295 296 sal_uInt32 nMarkCount = _rMarkList.GetMarkCount(); 297 for ( sal_uInt32 i = 0; i < nMarkCount; ++i) 298 { 299 SdrObject* pCurrent = _rMarkList.GetMark( i )->GetMarkedSdrObj(); 300 301 SdrObjListIter* pGroupIterator = NULL; 302 if ( pCurrent->IsGroupObject() ) 303 { 304 pGroupIterator = new SdrObjListIter( *pCurrent->GetSubList() ); 305 pCurrent = pGroupIterator->IsMore() ? pGroupIterator->Next() : NULL; 306 } 307 308 while ( pCurrent ) 309 { 310 FmFormObj* pAsFormObject = FmFormObj::GetFormObject( pCurrent ); 311 // note this will de-reference virtual objects, if necessary/possible 312 if ( pAsFormObject ) 313 { 314 Reference< XInterface > xControlModel( pAsFormObject->GetUnoControlModel(), UNO_QUERY ); 315 // the UNO_QUERY is important for normalization 316 if ( xControlModel.is() ) 317 _rInterfaces.insert( xControlModel ); 318 } 319 320 // next element 321 pCurrent = pGroupIterator && pGroupIterator->IsMore() ? pGroupIterator->Next() : NULL; 322 } 323 324 if ( pGroupIterator ) 325 delete pGroupIterator; 326 } 327 } 328 329 //.......................................................................... 330 sal_Int16 GridView2ModelPos(const Reference< XIndexAccess>& rColumns, sal_Int16 nViewPos) 331 { 332 try 333 { 334 if (rColumns.is()) 335 { 336 // loop through all columns 337 sal_Int16 i; 338 Reference< XPropertySet> xCur; 339 for (i=0; i<rColumns->getCount(); ++i) 340 { 341 rColumns->getByIndex(i) >>= xCur; 342 if (!::comphelper::getBOOL(xCur->getPropertyValue(FM_PROP_HIDDEN))) 343 { 344 // for every visible col : if nViewPos is greater zero, decrement it, else we 345 // have found the model position 346 if (!nViewPos) 347 break; 348 else 349 --nViewPos; 350 } 351 } 352 if (i<rColumns->getCount()) 353 return i; 354 } 355 } 356 catch(const Exception&) 357 { 358 DBG_UNHANDLED_EXCEPTION(); 359 } 360 return (sal_Int16)-1; 361 } 362 363 //.......................................................................... 364 void TransferEventScripts(const Reference< XControlModel>& xModel, const Reference< XControl>& xControl, 365 const Sequence< ScriptEventDescriptor>& rTransferIfAvailable) 366 { 367 // first check if we have a XEventAttacherManager for the model 368 Reference< XChild> xModelChild(xModel, UNO_QUERY); 369 if (!xModelChild.is()) 370 return; // nothing to do 371 372 Reference< XEventAttacherManager> xEventManager(xModelChild->getParent(), UNO_QUERY); 373 if (!xEventManager.is()) 374 return; // nothing to do 375 376 if (!rTransferIfAvailable.getLength()) 377 return; // nothing to do 378 379 // check for the index of the model within it's parent 380 Reference< XIndexAccess> xParentIndex(xModelChild->getParent(), UNO_QUERY); 381 if (!xParentIndex.is()) 382 return; // nothing to do 383 sal_Int32 nIndex = getElementPos(xParentIndex, xModel); 384 if (nIndex<0 || nIndex>=xParentIndex->getCount()) 385 return; // nothing to do 386 387 // then we need informations about the listeners supported by the control and the model 388 Sequence< Type> aModelListeners; 389 Sequence< Type> aControlListeners; 390 391 Reference< XIntrospection> xModelIntrospection(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.beans.Introspection")), UNO_QUERY); 392 Reference< XIntrospection> xControlIntrospection(::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.beans.Introspection")), UNO_QUERY); 393 394 if (xModelIntrospection.is() && xModel.is()) 395 { 396 Any aModel(makeAny(xModel)); 397 aModelListeners = xModelIntrospection->inspect(aModel)->getSupportedListeners(); 398 } 399 400 if (xControlIntrospection.is() && xControl.is()) 401 { 402 Any aControl(makeAny(xControl)); 403 aControlListeners = xControlIntrospection->inspect(aControl)->getSupportedListeners(); 404 } 405 406 sal_Int32 nMaxNewLen = aModelListeners.getLength() + aControlListeners.getLength(); 407 if (!nMaxNewLen) 408 return; // the model and the listener don't support any listeners (or we were unable to retrieve these infos) 409 410 Sequence< ScriptEventDescriptor> aTransferable(nMaxNewLen); 411 ScriptEventDescriptor* pTransferable = aTransferable.getArray(); 412 413 const ScriptEventDescriptor* pCurrent = rTransferIfAvailable.getConstArray(); 414 sal_Int32 i,j,k; 415 for (i=0; i<rTransferIfAvailable.getLength(); ++i, ++pCurrent) 416 { 417 // search the model/control idl classes for the event described by pCurrent 418 for ( Sequence< Type>* pCurrentArray = &aModelListeners; 419 pCurrentArray; 420 pCurrentArray = (pCurrentArray == &aModelListeners) ? &aControlListeners : NULL 421 ) 422 { 423 const Type* pCurrentListeners = pCurrentArray->getConstArray(); 424 for (j=0; j<pCurrentArray->getLength(); ++j, ++pCurrentListeners) 425 { 426 UniString aListener = (*pCurrentListeners).getTypeName(); 427 xub_StrLen nTokens = aListener.GetTokenCount('.'); 428 if (nTokens) 429 aListener = aListener.GetToken(nTokens - 1, '.'); 430 431 if (aListener == pCurrent->ListenerType.getStr()) 432 // the current ScriptEventDescriptor doesn't match the current listeners class 433 continue; 434 435 // now check the methods 436 Sequence< ::rtl::OUString> aMethodsNames = ::comphelper::getEventMethodsForType(*pCurrentListeners); 437 438 const ::rtl::OUString* pMethodsNames = aMethodsNames.getConstArray(); 439 for (k=0; k<aMethodsNames.getLength(); ++k, ++pMethodsNames) 440 { 441 if ((*pMethodsNames).compareTo(pCurrent->EventMethod) != COMPARE_EQUAL) 442 // the current ScriptEventDescriptor doesn't match the current listeners current method 443 continue; 444 445 // we can transfer the script event : the model (control) supports it 446 *pTransferable = *pCurrent; 447 ++pTransferable; 448 break; 449 } 450 if (k<aMethodsNames.getLength()) 451 break; 452 } 453 } 454 } 455 456 sal_Int32 nRealNewLen = pTransferable - aTransferable.getArray(); 457 aTransferable.realloc(nRealNewLen); 458 459 xEventManager->registerScriptEvents(nIndex, aTransferable); 460 } 461 462 //------------------------------------------------------------------------------ 463 ::rtl::OUString getServiceNameByControlType(sal_Int16 nType) 464 { 465 switch (nType) 466 { 467 case OBJ_FM_EDIT : return FM_COMPONENT_TEXTFIELD; 468 case OBJ_FM_BUTTON : return FM_COMPONENT_COMMANDBUTTON; 469 case OBJ_FM_FIXEDTEXT : return FM_COMPONENT_FIXEDTEXT; 470 case OBJ_FM_LISTBOX : return FM_COMPONENT_LISTBOX; 471 case OBJ_FM_CHECKBOX : return FM_COMPONENT_CHECKBOX; 472 case OBJ_FM_RADIOBUTTON : return FM_COMPONENT_RADIOBUTTON; 473 case OBJ_FM_GROUPBOX : return FM_COMPONENT_GROUPBOX; 474 case OBJ_FM_COMBOBOX : return FM_COMPONENT_COMBOBOX; 475 case OBJ_FM_GRID : return FM_COMPONENT_GRIDCONTROL; 476 case OBJ_FM_IMAGEBUTTON : return FM_COMPONENT_IMAGEBUTTON; 477 case OBJ_FM_FILECONTROL : return FM_COMPONENT_FILECONTROL; 478 case OBJ_FM_DATEFIELD : return FM_COMPONENT_DATEFIELD; 479 case OBJ_FM_TIMEFIELD : return FM_COMPONENT_TIMEFIELD; 480 case OBJ_FM_NUMERICFIELD : return FM_COMPONENT_NUMERICFIELD; 481 case OBJ_FM_CURRENCYFIELD : return FM_COMPONENT_CURRENCYFIELD; 482 case OBJ_FM_PATTERNFIELD : return FM_COMPONENT_PATTERNFIELD; 483 case OBJ_FM_HIDDEN : return FM_COMPONENT_HIDDENCONTROL; 484 case OBJ_FM_IMAGECONTROL : return FM_COMPONENT_IMAGECONTROL; 485 case OBJ_FM_FORMATTEDFIELD : return FM_COMPONENT_FORMATTEDFIELD; 486 case OBJ_FM_SCROLLBAR : return FM_SUN_COMPONENT_SCROLLBAR; 487 case OBJ_FM_SPINBUTTON : return FM_SUN_COMPONENT_SPINBUTTON; 488 case OBJ_FM_NAVIGATIONBAR : return FM_SUN_COMPONENT_NAVIGATIONBAR; 489 } 490 return ::rtl::OUString(); 491 } 492 493 } 494 495 //------------------------------------------------------------------------------ 496 // check if the control has one of the interfaces we can use for searching 497 // *_pCurrentText will be filled with the current text of the control (as used when searching this control) 498 sal_Bool IsSearchableControl( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>& _rxControl, 499 ::rtl::OUString* _pCurrentText ) 500 { 501 if ( !_rxControl.is() ) 502 return sal_False; 503 504 Reference< XTextComponent > xAsText( _rxControl, UNO_QUERY ); 505 if ( xAsText.is() ) 506 { 507 if ( _pCurrentText ) 508 *_pCurrentText = xAsText->getText(); 509 return sal_True; 510 } 511 512 Reference< XListBox > xListBox( _rxControl, UNO_QUERY ); 513 if ( xListBox.is() ) 514 { 515 if ( _pCurrentText ) 516 *_pCurrentText = xListBox->getSelectedItem(); 517 return sal_True; 518 } 519 520 Reference< XCheckBox > xCheckBox( _rxControl, UNO_QUERY ); 521 if ( xCheckBox.is() ) 522 { 523 if ( _pCurrentText ) 524 { 525 switch ( (TriState)xCheckBox->getState() ) 526 { 527 case STATE_NOCHECK: *_pCurrentText = ::rtl::OUString::createFromAscii( "0" ); break; 528 case STATE_CHECK: *_pCurrentText = ::rtl::OUString::createFromAscii( "1" ); break; 529 default: *_pCurrentText = ::rtl::OUString(); break; 530 } 531 } 532 return sal_True; 533 } 534 535 return sal_False; 536 } 537 538 //------------------------------------------------------------------------------ 539 sal_Bool FmXBoundFormFieldIterator::ShouldStepInto(const Reference< XInterface>& _rContainer) const 540 { 541 if (_rContainer == m_xStartingPoint) 542 // would be quite stupid to step over the root .... 543 return sal_True; 544 545 return Reference< XControlModel>(_rContainer, UNO_QUERY).is(); 546 } 547 548 //------------------------------------------------------------------------------ 549 sal_Bool FmXBoundFormFieldIterator::ShouldHandleElement(const Reference< XInterface>& _rElement) 550 { 551 if (!_rElement.is()) 552 // NULL element 553 return sal_False; 554 555 if (Reference< XForm>(_rElement, UNO_QUERY).is() || Reference< XGrid>(_rElement, UNO_QUERY).is()) 556 // a forms or a grid 557 return sal_False; 558 559 Reference< XPropertySet> xSet(_rElement, UNO_QUERY); 560 if (!xSet.is() || !::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xSet)) 561 // no "BoundField" property 562 return sal_False; 563 564 Any aVal( xSet->getPropertyValue(FM_PROP_BOUNDFIELD) ); 565 if (aVal.getValueTypeClass() != TypeClass_INTERFACE) 566 // void or invalid property value 567 return sal_False; 568 569 return aVal.hasValue(); 570 } 571 572 //------------------------------------------------------------------------------ 573 sal_Bool isControlList(const SdrMarkList& rMarkList) 574 { 575 // enthaelt die liste nur Controls und mindestens ein control 576 sal_uInt32 nMarkCount = rMarkList.GetMarkCount(); 577 sal_Bool bControlList = nMarkCount != 0; 578 579 sal_Bool bHadAnyLeafs = sal_False; 580 581 for (sal_uInt32 i = 0; i < nMarkCount && bControlList; i++) 582 { 583 SdrObject *pObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); 584 E3dObject* pAs3DObject = PTR_CAST(E3dObject, pObj); 585 // E3dObject's do not contain any 2D-objects (by definition) 586 // we need this extra check here : an E3dObject->IsGroupObject says "YES", but an SdrObjListIter working 587 // with an E3dObject doesn't give me any Nodes (E3dObject has a sub list, but no members in that list, 588 // cause there implementation differs from the one of "normal" SdrObject's. Unfortunally SdrObject::IsGroupObject 589 // doesn't check the element count of the sub list, which is simply a bug in IsGroupObject we can't fix at the moment). 590 // So at the end of this function bControlList would have the same value it was initialized with above : sal_True 591 // And this would be wrong :) 592 // 03.02.00 - 72529 - FS 593 if (!pAs3DObject) 594 { 595 if (pObj->IsGroupObject()) 596 { 597 SdrObjListIter aIter(*pObj->GetSubList()); 598 while (aIter.IsMore() && bControlList) 599 { 600 bControlList = FmFormInventor == aIter.Next()->GetObjInventor(); 601 bHadAnyLeafs = sal_True; 602 } 603 } 604 else 605 { 606 bHadAnyLeafs = sal_True; 607 bControlList = FmFormInventor == pObj->GetObjInventor(); 608 } 609 } 610 } 611 612 return bControlList && bHadAnyLeafs; 613 } 614 615 //------------------------------------------------------------------------ 616 Reference< XForm > GetForm(const Reference< XInterface>& _rxElement) 617 { 618 Reference< XForm > xForm( _rxElement, UNO_QUERY ); 619 if ( xForm.is() ) 620 return xForm; 621 622 Reference< XChild > xChild( _rxElement, UNO_QUERY ); 623 if ( xChild.is() ) 624 return GetForm( xChild->getParent() ); 625 626 return Reference< XForm >(); 627 } 628 629 //======================================================================== 630 // class FmXFormShell_Base_Disambiguation 631 //======================================================================== 632 FmXFormShell_Base_Disambiguation::FmXFormShell_Base_Disambiguation( ::osl::Mutex& _rMutex ) 633 :FmXFormShell_BD_BASE( _rMutex ) 634 { 635 } 636 637 void SAL_CALL FmXFormShell_Base_Disambiguation::disposing() 638 { 639 WeakComponentImplHelperBase::disposing(); 640 // Note: 641 // This is a HACK. 642 // Normally it should be sufficient to call the "disposing" of our direct 643 // base class, but SUN PRO 5 does not like this and claims there is a conflict 644 // with the XEventListener::disposing(EventObject) of our various listener 645 // base classes. 646 } 647 648 //======================================================================== 649 // class FmXFormShell 650 //======================================================================== 651 DBG_NAME(FmXFormShell); 652 //------------------------------------------------------------------------ 653 FmXFormShell::FmXFormShell( FmFormShell& _rShell, SfxViewFrame* _pViewFrame ) 654 :FmXFormShell_BASE(m_aMutex) 655 ,FmXFormShell_CFGBASE(::rtl::OUString::createFromAscii("Office.Common/Misc"), CONFIG_MODE_DELAYED_UPDATE) 656 ,m_eNavigate( NavigationBarMode_NONE ) 657 ,m_nInvalidationEvent( 0 ) 658 ,m_nActivationEvent( 0 ) 659 ,m_pShell( &_rShell ) 660 ,m_pTextShell( new ::svx::FmTextControlShell( _pViewFrame ) ) 661 ,m_aActiveControllerFeatures( ::comphelper::getProcessServiceFactory(), this ) 662 ,m_aNavControllerFeatures( ::comphelper::getProcessServiceFactory(), this ) 663 ,m_eDocumentType( eUnknownDocumentType ) 664 ,m_nLockSlotInvalidation( 0 ) 665 ,m_bHadPropertyBrowserInDesignMode( sal_False ) 666 ,m_bTrackProperties( sal_True ) 667 ,m_bUseWizards( sal_True ) 668 ,m_bDatabaseBar( sal_False ) 669 ,m_bInActivate( sal_False ) 670 ,m_bSetFocus( sal_False ) 671 ,m_bFilterMode( sal_False ) 672 ,m_bChangingDesignMode( sal_False ) 673 ,m_bPreparedClose( sal_False ) 674 ,m_bFirstActivation( sal_True ) 675 { 676 DBG_CTOR(FmXFormShell,NULL); 677 m_aMarkTimer.SetTimeout(100); 678 m_aMarkTimer.SetTimeoutHdl(LINK(this,FmXFormShell,OnTimeOut)); 679 680 if ( _pViewFrame ) 681 m_xAttachedFrame = _pViewFrame->GetFrame().GetFrameInterface(); 682 683 // to prevent deletion of this we acquire our refcounter once 684 ::comphelper::increment(FmXFormShell_BASE::m_refCount); 685 686 // correct the refcounter 687 ::comphelper::decrement(FmXFormShell_BASE::m_refCount); 688 689 // cache the current configuration settings we're interested in 690 implAdjustConfigCache(); 691 // and register for changes on this settings 692 Sequence< ::rtl::OUString > aNames(1); 693 aNames[0] = ::rtl::OUString::createFromAscii("FormControlPilotsEnabled"); 694 EnableNotification(aNames); 695 } 696 697 //------------------------------------------------------------------------ 698 FmXFormShell::~FmXFormShell() 699 { 700 delete m_pTextShell; 701 DBG_DTOR(FmXFormShell,NULL); 702 } 703 704 //------------------------------------------------------------------ 705 Reference< XModel > FmXFormShell::getContextDocument() const 706 { 707 Reference< XModel > xModel; 708 709 // determine the type of document we live in 710 try 711 { 712 Reference< XController > xController; 713 if ( m_xAttachedFrame.is() ) 714 xController = m_xAttachedFrame->getController(); 715 if ( xController.is() ) 716 xModel = xController->getModel(); 717 } 718 catch( const Exception& ) 719 { 720 DBG_UNHANDLED_EXCEPTION(); 721 } 722 return xModel; 723 } 724 725 //------------------------------------------------------------------ 726 bool FmXFormShell::isEnhancedForm() const 727 { 728 return getDocumentType() == eEnhancedForm; 729 } 730 731 //------------------------------------------------------------------ 732 bool FmXFormShell::impl_checkDisposed() const 733 { 734 if ( !m_pShell ) 735 { 736 OSL_ENSURE( false, "FmXFormShell::impl_checkDisposed: already disposed!" ); 737 return true; 738 } 739 return false; 740 } 741 742 //------------------------------------------------------------------ 743 ::svxform::DocumentType FmXFormShell::getDocumentType() const 744 { 745 if ( m_eDocumentType != eUnknownDocumentType ) 746 return m_eDocumentType; 747 748 // determine the type of document we live in 749 Reference< XModel > xModel = getContextDocument(); 750 if ( xModel.is() ) 751 m_eDocumentType = DocumentClassification::classifyDocument( xModel ); 752 else 753 { 754 OSL_ENSURE( sal_False, "FmXFormShell::getDocumentType: can't determine the document type!" ); 755 m_eDocumentType = eTextDocument; 756 // fallback, just to have a defined state 757 } 758 759 return m_eDocumentType; 760 } 761 762 //------------------------------------------------------------------ 763 bool FmXFormShell::IsReadonlyDoc() const 764 { 765 if ( impl_checkDisposed() ) 766 return true; 767 768 FmFormModel* pModel = m_pShell->GetFormModel(); 769 if ( pModel && pModel->GetObjectShell() ) 770 return pModel->GetObjectShell()->IsReadOnly() || pModel->GetObjectShell()->IsReadOnlyUI(); 771 return true; 772 } 773 774 //------------------------------------------------------------------ 775 Any SAL_CALL FmXFormShell::queryInterface( const Type& type) throw ( RuntimeException ) 776 { 777 return FmXFormShell_BASE::queryInterface(type); 778 } 779 //------------------------------------------------------------------------------ 780 Sequence< Type > SAL_CALL FmXFormShell::getTypes( ) throw(RuntimeException) 781 { 782 return FmXFormShell_BASE::getTypes(); 783 } 784 //------------------------------------------------------------------------------ 785 Sequence< sal_Int8 > SAL_CALL FmXFormShell::getImplementationId() throw(RuntimeException) 786 { 787 static ::cppu::OImplementationId* pId = 0; 788 if (! pId) 789 { 790 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 791 if (! pId) 792 { 793 static ::cppu::OImplementationId aId; 794 pId = &aId; 795 } 796 } 797 return pId->getImplementationId(); 798 } 799 // EventListener 800 //------------------------------------------------------------------------------ 801 void SAL_CALL FmXFormShell::disposing(const EventObject& e) throw( RuntimeException ) 802 { 803 impl_checkDisposed(); 804 805 if (m_xActiveController == e.Source) 806 { 807 // wird der Controller freigeben dann alles loslassen 808 stopListening(); 809 m_xActiveForm = NULL; 810 m_xActiveController = NULL; 811 m_xNavigationController = NULL; 812 813 m_aActiveControllerFeatures.dispose(); 814 m_aNavControllerFeatures.dispose(); 815 816 if ( m_pShell ) 817 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell); 818 } 819 820 if (e.Source == m_xExternalViewController) 821 { 822 Reference< runtime::XFormController > xFormController( m_xExternalViewController, UNO_QUERY ); 823 OSL_ENSURE( xFormController.is(), "FmXFormShell::disposing: invalid external view controller!" ); 824 if (xFormController.is()) 825 xFormController->removeActivateListener((XFormControllerListener*)this); 826 827 Reference< ::com::sun::star::lang::XComponent> xComp(m_xExternalViewController, UNO_QUERY); 828 if (xComp.is()) 829 xComp->removeEventListener((XEventListener*)(XPropertyChangeListener*)this); 830 831 m_xExternalViewController = NULL; 832 m_xExternalDisplayedForm = NULL; 833 m_xExtViewTriggerController = NULL; 834 835 InvalidateSlot( SID_FM_VIEW_AS_GRID, sal_False ); 836 } 837 } 838 839 //------------------------------------------------------------------------------ 840 void SAL_CALL FmXFormShell::propertyChange(const PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException) 841 { 842 if ( impl_checkDisposed() ) 843 return; 844 845 if (evt.PropertyName == FM_PROP_ROWCOUNT) 846 { 847 // Das gleich folgenden Update erzwingt ein Neu-Painten der entsprechenden Slots. Wenn ich mich aber hier nicht 848 // in dem HauptThread der Applikation befinde (weil zum Beispiel ein Cursor gerade Datensaetze zaehlt und mir dabei 849 // immer diese PropertyChanges beschert), kann sich das mit en normalen Paints im HauptThread der Applikation beissen. 850 // (Solche Paints passieren zum Beispiel, wenn man einfach nur eine andere Applikation ueber das Office legt und wieder 851 // zurueckschaltet). 852 // Deshalb die Benutzung des SolarMutex, der sichert das ab. 853 ::vos::IMutex& rSolarSafety = Application::GetSolarMutex(); 854 if (rSolarSafety.tryToAcquire()) 855 { 856 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_RECORD_TOTAL , sal_True, sal_False); 857 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update(SID_FM_RECORD_TOTAL); 858 rSolarSafety.release(); 859 } 860 else 861 { 862 // with the following the slot is invalidated asynchron 863 LockSlotInvalidation(sal_True); 864 InvalidateSlot(SID_FM_RECORD_TOTAL, sal_False); 865 LockSlotInvalidation(sal_False); 866 } 867 } 868 869 // this may be called from a non-main-thread so invalidate the shell asynchronously 870 LockSlotInvalidation(sal_True); 871 InvalidateSlot(0, 0); // special meaning : invalidate m_pShell 872 LockSlotInvalidation(sal_False); 873 } 874 875 //------------------------------------------------------------------------------ 876 void FmXFormShell::invalidateFeatures( const ::std::vector< sal_Int32 >& _rFeatures ) 877 { 878 if ( impl_checkDisposed() ) 879 return; 880 881 OSL_ENSURE( _rFeatures.size() > 0, "FmXFormShell::invalidateFeatures: invalid arguments!" ); 882 883 if ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() ) 884 { 885 // unfortunately, SFX requires sal_uInt16 886 ::std::vector< sal_uInt16 > aSlotIds; 887 aSlotIds.reserve( _rFeatures.size() ); 888 ::std::copy( _rFeatures.begin(), 889 _rFeatures.end(), 890 ::std::insert_iterator< ::std::vector< sal_uInt16 > >( aSlotIds, aSlotIds.begin() ) 891 ); 892 893 // furthermore, SFX wants a terminating 0 894 aSlotIds.push_back( 0 ); 895 896 // and, last but not least, SFX wants the ids to be sorted 897 ::std::sort( aSlotIds.begin(), aSlotIds.end() - 1 ); 898 899 sal_uInt16 *pSlotIds = aSlotIds.empty() ? 0 : &(aSlotIds[0]); 900 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( pSlotIds ); 901 } 902 } 903 904 //------------------------------------------------------------------------------ 905 void SAL_CALL FmXFormShell::formActivated(const EventObject& rEvent) throw( RuntimeException ) 906 { 907 if ( impl_checkDisposed() ) 908 return; 909 910 Reference< runtime::XFormController > xController( rEvent.Source, UNO_QUERY_THROW ); 911 m_pTextShell->formActivated( xController ); 912 setActiveController( xController ); 913 } 914 915 //------------------------------------------------------------------------------ 916 void SAL_CALL FmXFormShell::formDeactivated(const EventObject& rEvent) throw( RuntimeException ) 917 { 918 if ( impl_checkDisposed() ) 919 return; 920 921 Reference< runtime::XFormController > xController( rEvent.Source, UNO_QUERY_THROW ); 922 m_pTextShell->formDeactivated( xController ); 923 } 924 925 //------------------------------------------------------------------------------ 926 void FmXFormShell::disposing() 927 { 928 impl_checkDisposed(); 929 930 FmXFormShell_BASE::disposing(); 931 932 if ( m_pShell && !m_pShell->IsDesignMode() ) 933 setActiveController( NULL, sal_True ); 934 // do NOT save the content of the old form (the second parameter tells this) 935 // if we're here, then we expect that PrepareClose has been called, and thus the user 936 // got a chance to commit or reject any changes. So in case we're here and there 937 // are still uncommitted changes, the user explicitly wanted this. 938 // 2002-11-11 - 104702 - fs@openoffice.org 939 940 m_pTextShell->dispose(); 941 942 m_xAttachedFrame = NULL; 943 944 CloseExternalFormViewer(); 945 946 while ( m_aLoadingPages.size() ) 947 { 948 Application::RemoveUserEvent( m_aLoadingPages.front().nEventId ); 949 m_aLoadingPages.pop(); 950 } 951 952 { 953 ::osl::MutexGuard aGuard(m_aInvalidationSafety); 954 if (m_nInvalidationEvent) 955 { 956 Application::RemoveUserEvent(m_nInvalidationEvent); 957 m_nInvalidationEvent = 0; 958 } 959 if ( m_nActivationEvent ) 960 { 961 Application::RemoveUserEvent( m_nActivationEvent ); 962 m_nActivationEvent = 0; 963 } 964 } 965 966 { 967 ::osl::ClearableMutexGuard aGuard(m_aAsyncSafety); 968 aGuard.clear(); 969 970 DBG_ASSERT(!m_nInvalidationEvent, "FmXFormShell::~FmXFormShell : still have an invalidation event !"); 971 // should habe been deleted while beeing disposed 972 973 m_aMarkTimer.Stop(); 974 } 975 976 DisableNotification(); 977 978 RemoveElement( m_xForms ); 979 m_xForms.clear(); 980 981 impl_switchActiveControllerListening( false ); 982 m_xActiveController = NULL; 983 m_xActiveForm = NULL; 984 985 m_pShell = NULL; 986 m_xNavigationController = NULL; 987 m_xCurrentForm = NULL; 988 m_xLastGridFound = NULL; 989 m_xAttachedFrame = NULL; 990 m_xExternalViewController = NULL; 991 m_xExtViewTriggerController = NULL; 992 m_xExternalDisplayedForm = NULL; 993 m_xLastGridFound = NULL; 994 995 InterfaceBag aEmpty; 996 m_aCurrentSelection.swap( aEmpty ); 997 998 m_aActiveControllerFeatures.dispose(); 999 m_aNavControllerFeatures.dispose(); 1000 } 1001 1002 //------------------------------------------------------------------------------ 1003 void FmXFormShell::UpdateSlot( sal_Int16 _nId ) 1004 { 1005 if ( impl_checkDisposed() ) 1006 return; 1007 1008 ::osl::MutexGuard aGuard(m_aInvalidationSafety); 1009 1010 if ( m_nLockSlotInvalidation ) 1011 { 1012 OSL_ENSURE( sal_False, "FmXFormShell::UpdateSlot: cannot update if invalidation is currently locked!" ); 1013 InvalidateSlot( _nId, sal_False ); 1014 } 1015 else 1016 { 1017 OSL_ENSURE( _nId, "FmXFormShell::UpdateSlot: can't update the complete shell!" ); 1018 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate( _nId, sal_True, sal_True ); 1019 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update( _nId ); 1020 } 1021 } 1022 1023 //------------------------------------------------------------------------------ 1024 void FmXFormShell::InvalidateSlot( sal_Int16 nId, sal_Bool bWithId ) 1025 { 1026 if ( impl_checkDisposed() ) 1027 return; 1028 1029 ::osl::MutexGuard aGuard(m_aInvalidationSafety); 1030 if (m_nLockSlotInvalidation) 1031 { 1032 m_arrInvalidSlots.Insert(nId, m_arrInvalidSlots.Count()); 1033 sal_uInt8 nFlags = ( bWithId ? 0x01 : 0 ); 1034 m_arrInvalidSlots_Flags.push_back(nFlags); 1035 } 1036 else 1037 if (nId) 1038 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(nId, sal_True, bWithId); 1039 else 1040 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell); 1041 } 1042 1043 //------------------------------------------------------------------------------ 1044 void FmXFormShell::LockSlotInvalidation(sal_Bool bLock) 1045 { 1046 if ( impl_checkDisposed() ) 1047 return; 1048 1049 ::osl::MutexGuard aGuard(m_aInvalidationSafety); 1050 DBG_ASSERT(bLock || m_nLockSlotInvalidation>0, "FmXFormShell::LockSlotInvalidation : invalid call !"); 1051 1052 if (bLock) 1053 ++m_nLockSlotInvalidation; 1054 else if (!--m_nLockSlotInvalidation) 1055 { 1056 // alles, was sich waehrend der gelockten Phase angesammelt hat, (asynchron) invalidieren 1057 if (!m_nInvalidationEvent) 1058 m_nInvalidationEvent = Application::PostUserEvent(LINK(this, FmXFormShell, OnInvalidateSlots)); 1059 } 1060 } 1061 1062 //------------------------------------------------------------------------------ 1063 IMPL_LINK(FmXFormShell, OnInvalidateSlots, void*, EMPTYARG) 1064 { 1065 if ( impl_checkDisposed() ) 1066 return 0L; 1067 1068 ::osl::MutexGuard aGuard(m_aInvalidationSafety); 1069 m_nInvalidationEvent = 0; 1070 1071 DBG_ASSERT(m_arrInvalidSlots.Count() == m_arrInvalidSlots_Flags.size(), 1072 "FmXFormShell::OnInvalidateSlots : inconsistent slot arrays !"); 1073 sal_uInt8 nFlags; 1074 for (sal_Int16 i=0; i<m_arrInvalidSlots.Count(); ++i) 1075 { 1076 nFlags = m_arrInvalidSlots_Flags[i]; 1077 1078 if (m_arrInvalidSlots[i]) 1079 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(m_arrInvalidSlots[i], sal_True, (nFlags & 0x01)); 1080 else 1081 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell); 1082 } 1083 1084 m_arrInvalidSlots.Remove(0, m_arrInvalidSlots.Count()); 1085 m_arrInvalidSlots_Flags.clear(); 1086 return 0L; 1087 } 1088 1089 //------------------------------------------------------------------------------ 1090 void FmXFormShell::ForceUpdateSelection(sal_Bool bAllowInvalidation) 1091 { 1092 if ( impl_checkDisposed() ) 1093 return; 1094 1095 if (IsSelectionUpdatePending()) 1096 { 1097 m_aMarkTimer.Stop(); 1098 1099 // die Invalidierung der Slots, die implizit von SetSelection besorgt wird, eventuell abschalten 1100 if (!bAllowInvalidation) 1101 LockSlotInvalidation(sal_True); 1102 1103 SetSelection(m_pShell->GetFormView()->GetMarkedObjectList()); 1104 1105 if (!bAllowInvalidation) 1106 LockSlotInvalidation(sal_False); 1107 } 1108 } 1109 1110 //------------------------------------------------------------------------------ 1111 PopupMenu* FmXFormShell::GetConversionMenu() 1112 { 1113 const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); 1114 sal_Bool bIsHiContrastMode = rSettings.GetHighContrastMode(); 1115 1116 PopupMenu* pNewMenu = new PopupMenu(SVX_RES( RID_FMSHELL_CONVERSIONMENU )); 1117 1118 ImageList aImageList( SVX_RES( bIsHiContrastMode ? RID_SVXIMGLIST_FMEXPL_HC : RID_SVXIMGLIST_FMEXPL) ); 1119 for ( size_t i = 0; i < sizeof( nConvertSlots ) / sizeof( nConvertSlots[0] ); ++i ) 1120 { 1121 // das entsprechende Image dran 1122 pNewMenu->SetItemImage(nConvertSlots[i], aImageList.GetImage(nCreateSlots[i])); 1123 } 1124 1125 return pNewMenu; 1126 } 1127 1128 //------------------------------------------------------------------------------ 1129 bool FmXFormShell::isControlConversionSlot( sal_uInt16 nSlotId ) 1130 { 1131 for ( size_t i = 0; i < sizeof( nConvertSlots ) / sizeof( nConvertSlots[0] ); ++i ) 1132 if (nConvertSlots[i] == nSlotId) 1133 return true; 1134 return false; 1135 } 1136 1137 //------------------------------------------------------------------------------ 1138 bool FmXFormShell::executeControlConversionSlot( sal_uInt16 _nSlotId ) 1139 { 1140 OSL_PRECOND( canConvertCurrentSelectionToControl( _nSlotId ), "FmXFormShell::executeControlConversionSlot: illegal call!" ); 1141 InterfaceBag::const_iterator aSelectedElement = m_aCurrentSelection.begin(); 1142 if ( aSelectedElement == m_aCurrentSelection.end() ) 1143 return false; 1144 1145 return executeControlConversionSlot( Reference< XFormComponent >( *aSelectedElement, UNO_QUERY ), _nSlotId ); 1146 } 1147 1148 //------------------------------------------------------------------------------ 1149 bool FmXFormShell::executeControlConversionSlot( const Reference< XFormComponent >& _rxObject, sal_uInt16 _nSlotId ) 1150 { 1151 if ( impl_checkDisposed() ) 1152 return false; 1153 1154 OSL_ENSURE( _rxObject.is(), "FmXFormShell::executeControlConversionSlot: invalid object!" ); 1155 if ( !_rxObject.is() ) 1156 return false; 1157 1158 SdrPage* pPage = m_pShell->GetCurPage(); 1159 FmFormPage* pFormPage = pPage ? dynamic_cast< FmFormPage* >( pPage ) : NULL; 1160 OSL_ENSURE( pFormPage, "FmXFormShell::executeControlConversionSlot: no current (form) page!" ); 1161 if ( !pFormPage ) 1162 return false; 1163 1164 OSL_ENSURE( isSolelySelected( _rxObject ), 1165 "FmXFormShell::executeControlConversionSlot: hmm ... shouldn't this parameter be redundant?" ); 1166 1167 for ( size_t lookupSlot = 0; lookupSlot < sizeof( nConvertSlots ) / sizeof( nConvertSlots[0] ); ++lookupSlot ) 1168 { 1169 if (nConvertSlots[lookupSlot] == _nSlotId) 1170 { 1171 Reference< XInterface > xNormalizedObject( _rxObject, UNO_QUERY ); 1172 1173 FmFormObj* pFormObject = NULL; 1174 SdrObjListIter aPageIter( *pFormPage ); 1175 while ( aPageIter.IsMore() ) 1176 { 1177 SdrObject* pCurrent = aPageIter.Next(); 1178 pFormObject = FmFormObj::GetFormObject( pCurrent ); 1179 if ( !pFormObject ) 1180 continue; 1181 1182 Reference< XInterface > xCurrentNormalized( pFormObject->GetUnoControlModel(), UNO_QUERY ); 1183 if ( xCurrentNormalized.get() == xNormalizedObject.get() ) 1184 break; 1185 1186 pFormObject = NULL; 1187 } 1188 1189 if ( !pFormObject ) 1190 return false; 1191 1192 ::rtl::OUString sNewName( getServiceNameByControlType( nObjectTypes[ lookupSlot ] ) ); 1193 Reference< XControlModel> xNewModel( ::comphelper::getProcessServiceFactory()->createInstance( sNewName ), UNO_QUERY ); 1194 if (!xNewModel.is()) 1195 return false; 1196 1197 Reference< XControlModel> xOldModel( pFormObject->GetUnoControlModel() ); 1198 Reference< XServiceInfo> xModelInfo(xOldModel, UNO_QUERY); 1199 1200 // Properties uebertragen 1201 Reference< XPropertySet> xOldSet(xOldModel, UNO_QUERY); 1202 Reference< XPropertySet> xNewSet(xNewModel, UNO_QUERY); 1203 1204 1205 Locale aNewLanguage = Application::GetSettings().GetUILocale(); 1206 TransferFormComponentProperties(xOldSet, xNewSet, aNewLanguage); 1207 1208 Sequence< ::com::sun::star::script::ScriptEventDescriptor> aOldScripts; 1209 Reference< XChild> xChild(xOldModel, UNO_QUERY); 1210 if (xChild.is()) 1211 { 1212 Reference< XIndexAccess> xParent(xChild->getParent(), UNO_QUERY); 1213 1214 // remember old script events 1215 Reference< ::com::sun::star::script::XEventAttacherManager> xEvManager(xChild->getParent(), UNO_QUERY); 1216 if (xParent.is() && xEvManager.is()) 1217 { 1218 sal_Int32 nIndex = getElementPos(xParent, xOldModel); 1219 if (nIndex>=0 && nIndex<xParent->getCount()) 1220 aOldScripts = xEvManager->getScriptEvents(nIndex); 1221 } 1222 1223 // replace the mdoel within the parent container 1224 Reference< XIndexContainer> xIndexParent(xChild->getParent(), UNO_QUERY); //Modified by BerryJia for fixing Bug102516 Time(China):2002-9-5 16:00 1225 if (xIndexParent.is()) 1226 { 1227 // the form container works with FormComponents 1228 Reference< XFormComponent> xComponent(xNewModel, UNO_QUERY); 1229 DBG_ASSERT(xComponent.is(), "FmXFormShell::executeControlConversionSlot: the new model is no form component !"); 1230 Any aNewModel(makeAny(xComponent)); 1231 try 1232 { 1233 //Modified by BerryJia for fixing Bug102516 Time(China):2002-9-5 16:00 1234 sal_Int32 nIndex = getElementPos(xParent, xOldModel); 1235 if (nIndex>=0 && nIndex<xParent->getCount()) 1236 xIndexParent->replaceByIndex(nIndex, aNewModel); 1237 else 1238 { 1239 DBG_ERROR("FmXFormShell::executeControlConversionSlot: could not replace the model !"); 1240 Reference< ::com::sun::star::lang::XComponent> xNewComponent(xNewModel, UNO_QUERY); 1241 if (xNewComponent.is()) 1242 xNewComponent->dispose(); 1243 return false; 1244 } 1245 } 1246 catch(Exception&) 1247 { 1248 DBG_ERROR("FmXFormShell::executeControlConversionSlot: could not replace the model !"); 1249 Reference< ::com::sun::star::lang::XComponent> xNewComponent(xNewModel, UNO_QUERY); 1250 if (xNewComponent.is()) 1251 xNewComponent->dispose(); 1252 return false; 1253 } 1254 1255 } 1256 } 1257 1258 // special handling for the LabelControl-property : can only be set when the model is placed 1259 // within the forms hierarchy 1260 if (::comphelper::hasProperty(FM_PROP_CONTROLLABEL, xOldSet) && ::comphelper::hasProperty(FM_PROP_CONTROLLABEL, xNewSet)) 1261 { 1262 try 1263 { 1264 xNewSet->setPropertyValue(FM_PROP_CONTROLLABEL, xOldSet->getPropertyValue(FM_PROP_CONTROLLABEL)); 1265 } 1266 catch(Exception&) 1267 { 1268 } 1269 1270 } 1271 1272 // neues Model setzen 1273 pFormObject->SetChanged(); 1274 pFormObject->SetUnoControlModel(xNewModel); 1275 1276 // transfer script events 1277 // (do this _after_ SetUnoControlModel as we need the new (implicitly created) control) 1278 if (aOldScripts.getLength()) 1279 { 1280 // das Control zum Model suchen 1281 Reference< XControlContainer > xControlContainer( getControlContainerForView() ); 1282 1283 Sequence< Reference< XControl> > aControls( xControlContainer->getControls() ); 1284 const Reference< XControl>* pControls = aControls.getConstArray(); 1285 1286 sal_uInt32 nLen = aControls.getLength(); 1287 Reference< XControl> xControl; 1288 for (sal_uInt32 i=0 ; i<nLen; ++i) 1289 { 1290 if (pControls[i]->getModel() == xNewModel) 1291 { 1292 xControl = pControls[i]; 1293 break; 1294 } 1295 } 1296 TransferEventScripts(xNewModel, xControl, aOldScripts); 1297 } 1298 1299 // transfer value bindings, if possible 1300 { 1301 Reference< XBindableValue > xOldBindable( xOldModel, UNO_QUERY ); 1302 Reference< XBindableValue > xNewBindable( xNewModel, UNO_QUERY ); 1303 if ( xOldBindable.is() ) 1304 { 1305 try 1306 { 1307 if ( xNewBindable.is() ) 1308 xNewBindable->setValueBinding( xOldBindable->getValueBinding() ); 1309 xOldBindable->setValueBinding( NULL ); 1310 } 1311 catch(const Exception&) 1312 { 1313 DBG_UNHANDLED_EXCEPTION(); 1314 } 1315 } 1316 } 1317 // same for list entry sources 1318 { 1319 Reference< XListEntrySink > xOldSink( xOldModel, UNO_QUERY ); 1320 Reference< XListEntrySink > xNewSink( xNewModel, UNO_QUERY ); 1321 if ( xOldSink.is() ) 1322 { 1323 try 1324 { 1325 if ( xNewSink.is() ) 1326 xNewSink->setListEntrySource( xOldSink->getListEntrySource() ); 1327 xOldSink->setListEntrySource( NULL ); 1328 } 1329 catch(const Exception&) 1330 { 1331 DBG_UNHANDLED_EXCEPTION(); 1332 } 1333 } 1334 } 1335 1336 // create an undo action 1337 FmFormModel* pModel = m_pShell->GetFormModel(); 1338 DBG_ASSERT(pModel != NULL, "FmXFormShell::executeControlConversionSlot: my shell has no model !"); 1339 if (pModel && pModel->IsUndoEnabled() ) 1340 { 1341 pModel->AddUndo(new FmUndoModelReplaceAction(*pModel, pFormObject, xOldModel)); 1342 } 1343 else 1344 { 1345 FmUndoModelReplaceAction::DisposeElement( xOldModel ); 1346 } 1347 1348 return true; 1349 } 1350 } 1351 return false; 1352 } 1353 1354 //------------------------------------------------------------------------------ 1355 bool FmXFormShell::canConvertCurrentSelectionToControl( sal_Int16 nConversionSlot ) 1356 { 1357 if ( m_aCurrentSelection.empty() ) 1358 return false; 1359 1360 InterfaceBag::const_iterator aCheck = m_aCurrentSelection.begin(); 1361 Reference< XServiceInfo > xElementInfo( *aCheck, UNO_QUERY ); 1362 if ( !xElementInfo.is() ) 1363 // no service info -> cannot determine this 1364 return false; 1365 1366 if ( ++aCheck != m_aCurrentSelection.end() ) 1367 // more than one element 1368 return false; 1369 1370 if ( Reference< XForm >::query( xElementInfo ).is() ) 1371 // it's a form 1372 return false; 1373 1374 sal_Int16 nObjectType = getControlTypeByObject( xElementInfo ); 1375 1376 if ( ( OBJ_FM_HIDDEN == nObjectType ) 1377 || ( OBJ_FM_CONTROL == nObjectType ) 1378 || ( OBJ_FM_GRID == nObjectType ) 1379 ) 1380 return false; // those types cannot be converted 1381 1382 DBG_ASSERT(sizeof(nConvertSlots)/sizeof(nConvertSlots[0]) == sizeof(nObjectTypes)/sizeof(nObjectTypes[0]), 1383 "FmXFormShell::canConvertCurrentSelectionToControl: nConvertSlots & nObjectTypes must have the same size !"); 1384 1385 for ( size_t i = 0; i < sizeof( nConvertSlots ) / sizeof( nConvertSlots[0] ); ++i ) 1386 if (nConvertSlots[i] == nConversionSlot) 1387 return nObjectTypes[i] != nObjectType; 1388 1389 return sal_True; // all other slots: assume "yes" 1390 } 1391 1392 //------------------------------------------------------------------------------ 1393 void FmXFormShell::checkControlConversionSlotsForCurrentSelection( Menu& rMenu ) 1394 { 1395 for (sal_Int16 i=0; i<rMenu.GetItemCount(); ++i) 1396 // der Context ist schon von einem Typ, der dem Eitnrag entspricht -> disable 1397 rMenu.EnableItem( rMenu.GetItemId(i), canConvertCurrentSelectionToControl( rMenu.GetItemId( i ) ) ); 1398 } 1399 1400 //------------------------------------------------------------------------------ 1401 void FmXFormShell::LoopGrids(sal_Int16 nWhat) 1402 { 1403 if ( impl_checkDisposed() ) 1404 return; 1405 1406 Reference< XIndexContainer> xControlModels(m_xActiveForm, UNO_QUERY); 1407 if (xControlModels.is()) 1408 { 1409 for (sal_Int16 i=0; i<xControlModels->getCount(); ++i) 1410 { 1411 Reference< XPropertySet> xModelSet; 1412 xControlModels->getByIndex(i) >>= xModelSet; 1413 if (!xModelSet.is()) 1414 continue; 1415 1416 if (!::comphelper::hasProperty(FM_PROP_CLASSID, xModelSet)) 1417 continue; 1418 sal_Int16 nClassId = ::comphelper::getINT16(xModelSet->getPropertyValue(FM_PROP_CLASSID)); 1419 if (FormComponentType::GRIDCONTROL != nClassId) 1420 continue; 1421 1422 if (!::comphelper::hasProperty(FM_PROP_CURSORCOLOR, xModelSet) || !::comphelper::hasProperty(FM_PROP_ALWAYSSHOWCURSOR, xModelSet) || !::comphelper::hasProperty(FM_PROP_DISPLAYSYNCHRON, xModelSet)) 1423 continue; 1424 1425 switch (nWhat & GA_SYNC_MASK) 1426 { 1427 case GA_DISABLE_SYNC: 1428 { 1429 sal_Bool bB(sal_False); 1430 xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(&bB,getBooleanCppuType())); 1431 } 1432 break; 1433 case GA_FORCE_SYNC: 1434 { 1435 Any aOldVal( xModelSet->getPropertyValue(FM_PROP_DISPLAYSYNCHRON) ); 1436 sal_Bool bB(sal_True); 1437 xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(&bB,getBooleanCppuType())); 1438 xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, aOldVal); 1439 } 1440 break; 1441 case GA_ENABLE_SYNC: 1442 { 1443 sal_Bool bB(sal_True); 1444 xModelSet->setPropertyValue(FM_PROP_DISPLAYSYNCHRON, Any(&bB,getBooleanCppuType())); 1445 } 1446 break; 1447 } 1448 1449 if (nWhat & GA_DISABLE_ROCTRLR) 1450 { 1451 sal_Bool bB(sal_False); 1452 xModelSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, Any(&bB,getBooleanCppuType())); 1453 Reference< XPropertyState> xModelPropState(xModelSet, UNO_QUERY); 1454 if (xModelPropState.is()) 1455 xModelPropState->setPropertyToDefault(FM_PROP_CURSORCOLOR); 1456 else 1457 xModelSet->setPropertyValue(FM_PROP_CURSORCOLOR, Any()); // this should be the default 1458 } 1459 else if (nWhat & GA_ENABLE_ROCTRLR) 1460 { 1461 sal_Bool bB(sal_True); 1462 xModelSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, Any(&bB,getBooleanCppuType())); 1463 xModelSet->setPropertyValue(FM_PROP_CURSORCOLOR, makeAny(sal_Int32(COL_LIGHTRED))); 1464 } 1465 } 1466 } 1467 } 1468 1469 //------------------------------------------------------------------------------ 1470 Reference< XControlContainer > FmXFormShell::getControlContainerForView() 1471 { 1472 if ( impl_checkDisposed() ) 1473 return NULL; 1474 1475 SdrPageView* pPageView = NULL; 1476 if ( m_pShell && m_pShell->GetFormView() ) 1477 pPageView = m_pShell->GetFormView()->GetSdrPageView(); 1478 1479 Reference< XControlContainer> xControlContainer; 1480 if ( pPageView ) 1481 xControlContainer = pPageView->GetPageWindow(0)->GetControlContainer(); 1482 1483 return xControlContainer; 1484 } 1485 1486 //------------------------------------------------------------------------------ 1487 void FmXFormShell::ExecuteTabOrderDialog( const Reference< XTabControllerModel >& _rxForForm ) 1488 { 1489 if ( impl_checkDisposed() ) 1490 return; 1491 1492 OSL_PRECOND( _rxForForm.is(), "FmXFormShell::ExecuteTabOrderDialog: invalid tabbing model!" ); 1493 if ( !_rxForForm.is() ) 1494 return; 1495 1496 try 1497 { 1498 Sequence< Any > aDialogArgs( 3 ); 1499 aDialogArgs[0] <<= NamedValue( 1500 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TabbingModel" ) ), 1501 makeAny( _rxForForm ) 1502 ); 1503 aDialogArgs[1] <<= NamedValue( 1504 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ControlContext" ) ), 1505 makeAny( getControlContainerForView() ) 1506 ); 1507 1508 Reference< XWindow > xParentWindow; 1509 if ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() ) 1510 xParentWindow = VCLUnoHelper::GetInterface ( &m_pShell->GetViewShell()->GetViewFrame()->GetWindow() ); 1511 aDialogArgs[2] <<= NamedValue( 1512 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" ) ), 1513 makeAny( xParentWindow ) 1514 ); 1515 1516 Reference< dialogs::XExecutableDialog > xDialog( 1517 ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( 1518 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.ui.TabOrderDialog" ) ), 1519 aDialogArgs 1520 ), 1521 UNO_QUERY 1522 ); 1523 OSL_ENSURE( xDialog.is(), "FmXFormShell::ExecuteTabOrderDialog: could not create the dialog!" ); 1524 1525 if ( xDialog.is() ) 1526 xDialog->execute(); 1527 } 1528 catch( const Exception& ) 1529 { 1530 OSL_ENSURE( sal_False, "FmXFormShell::ExecuteTabOrderDialog: caught an exception!" ); 1531 } 1532 } 1533 1534 //------------------------------------------------------------------------------ 1535 void FmXFormShell::ExecuteSearch() 1536 { 1537 if ( impl_checkDisposed() ) 1538 return; 1539 1540 // eine Sammlung aller (logischen) Formulare 1541 FmFormArray aEmpty; 1542 m_aSearchForms.swap( aEmpty ); 1543 ::std::vector< String > aContextNames; 1544 impl_collectFormSearchContexts_nothrow( m_pShell->GetCurPage()->GetForms(), ::rtl::OUString(), m_aSearchForms, aContextNames ); 1545 OSL_POSTCOND( m_aSearchForms.size() == aContextNames.size(), 1546 "FmXFormShell::ExecuteSearch: nonsense!" ); 1547 if ( m_aSearchForms.size() != aContextNames.size() ) 1548 return; 1549 1550 // filter out the forms which do not contain valid controls at all 1551 { 1552 FmFormArray aValidForms; 1553 ::std::vector< String > aValidContexts; 1554 FmFormArray::const_iterator form = m_aSearchForms.begin(); 1555 ::std::vector< String >::const_iterator contextName = aContextNames.begin(); 1556 for ( ; form != m_aSearchForms.end(); ++form, ++contextName ) 1557 { 1558 FmSearchContext aTestContext; 1559 aTestContext.nContext = static_cast< sal_Int16 >( form - m_aSearchForms.begin() ); 1560 sal_uInt32 nValidControls = OnSearchContextRequest( &aTestContext ); 1561 if ( nValidControls > 0 ) 1562 { 1563 aValidForms.push_back( *form ); 1564 aValidContexts.push_back( *contextName ); 1565 } 1566 } 1567 1568 m_aSearchForms.swap( aValidForms ); 1569 aContextNames.swap( aValidContexts ); 1570 } 1571 1572 if (m_aSearchForms.empty() ) 1573 { // es gibt keine Controls, die alle Bedingungen fuer eine Suche erfuellen 1574 ErrorBox(NULL, WB_OK, SVX_RESSTR(RID_STR_NODATACONTROLS)).Execute(); 1575 return; 1576 } 1577 1578 // jetzt brauche ich noch einen 'initial context' 1579 sal_Int16 nInitialContext = 0; 1580 Reference< XForm> xActiveForm( getActiveForm()); 1581 for ( size_t i=0; i<m_aSearchForms.size(); ++i ) 1582 { 1583 if (m_aSearchForms.at(i) == xActiveForm) 1584 { 1585 nInitialContext = (sal_Int16)i; 1586 break; 1587 } 1588 } 1589 1590 // wenn der Dialog initial den Text des aktiven Controls anbieten soll, muss dieses ein XTextComponent-Interface habe, 1591 // ausserdem macht das nur Sinn, wenn das aktuelle Feld auch an ein Tabellen- (oder was-auch-immer-)Feld gebunden ist 1592 UniString strActiveField; 1593 UniString strInitialText; 1594 // ... das bekomme ich von meinem FormController 1595 DBG_ASSERT(m_xActiveController.is(), "FmXFormShell::ExecuteSearch : no active controller !"); 1596 Reference< XControl> xActiveControl( m_xActiveController->getCurrentControl()); 1597 if (xActiveControl.is()) 1598 { 1599 // das Control kann mir sein Model sagen ... 1600 Reference< XControlModel> xActiveModel( xActiveControl->getModel()); 1601 DBG_ASSERT(xActiveModel.is(), "FmXFormShell::ExecuteSearch : active control has no model !"); 1602 1603 // das Model frage ich nach der ControlSource-Eigenschaft ... 1604 Reference< XPropertySet> xProperties(xActiveControl->getModel(), UNO_QUERY); 1605 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xProperties) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xProperties)) 1606 { 1607 Reference< XPropertySet> xField; 1608 xProperties->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField; 1609 if (xField.is()) // (nur wenn das Ding wirklich gebunden ist) 1610 { 1611 // und das Control selber nach einem TextComponent-Interface (damit ich mir dort den Text abholen kann) 1612 Reference< XTextComponent> xText(xActiveControl, UNO_QUERY); 1613 if (xText.is()) 1614 { 1615 strActiveField = getLabelName(xProperties).getStr(); 1616 strInitialText = xText->getText().getStr(); 1617 } 1618 } 1619 } 1620 else 1621 { 1622 // das Control selber hat keine ControlSource, aber vielleicht ist es ein GridControl 1623 Reference< XGrid> xGrid(xActiveControl, UNO_QUERY); 1624 if (xGrid.is()) 1625 { 1626 // fuer strActiveField brauche ich die die ControlSource der Column, dafuer den Columns-Container, dafuer die 1627 // GridPeer 1628 Reference< XGridPeer> xGridPeer(xActiveControl->getPeer(), UNO_QUERY); 1629 Reference< XIndexAccess> xColumns; 1630 if (xGridPeer.is()) 1631 xColumns = Reference< XIndexAccess>(xGridPeer->getColumns(),UNO_QUERY); 1632 1633 sal_Int16 nViewCol = xGrid->getCurrentColumnPosition(); 1634 sal_Int16 nModelCol = GridView2ModelPos(xColumns, nViewCol); 1635 Reference< XPropertySet> xCurrentCol; 1636 if(xColumns.is()) 1637 xColumns->getByIndex(nModelCol) >>= xCurrentCol; 1638 if (xCurrentCol.is()) 1639 strActiveField = ::comphelper::getString(xCurrentCol->getPropertyValue(FM_PROP_LABEL)).getStr(); 1640 1641 // the text fo the current column 1642 Reference< XIndexAccess> xColControls(xGridPeer, UNO_QUERY); 1643 Reference< XInterface> xCurControl; 1644 xColControls->getByIndex(nViewCol) >>= xCurControl; 1645 ::rtl::OUString sInitialText; 1646 if (IsSearchableControl(xCurControl, &sInitialText)) 1647 strInitialText = sInitialText.getStr(); 1648 } 1649 } 1650 } 1651 1652 // um eventuelle GridControls, die ich kenne, kuemmern 1653 LoopGrids(GA_DISABLE_SYNC /*| GA_ENABLE_ROCTRLR*/); 1654 1655 // jetzt bin ich reif fuer den Dialog 1656 // wenn die potentiellen Deadlocks, die durch die Benutzung des Solar-Mutex in MTs VCLX...-Klasen entstehen, irgendwann mal 1657 // ausgeraeumt sind, sollte hier ein SM_USETHREAD rein, denn die Suche in einem eigenen Thread ist doch etwas fluessiger 1658 // sollte allerdings irgendwie von dem unterliegenden Cursor abhaengig gemacht werden, DAO zum Beispiel ist nicht thread-sicher 1659 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); 1660 AbstractFmSearchDialog* pDialog = NULL; 1661 if ( pFact ) 1662 pDialog = pFact->CreateFmSearchDialog( &m_pShell->GetViewShell()->GetViewFrame()->GetWindow(), strInitialText, aContextNames, nInitialContext, LINK( this, FmXFormShell, OnSearchContextRequest ) ); 1663 DBG_ASSERT( pDialog, "FmXFormShell::ExecuteSearch: could not create the search dialog!" ); 1664 if ( pDialog ) 1665 { 1666 pDialog->SetActiveField( strActiveField ); 1667 pDialog->SetFoundHandler( LINK( this, FmXFormShell, OnFoundData ) ); 1668 pDialog->SetCanceledNotFoundHdl( LINK( this, FmXFormShell, OnCanceledNotFound ) ); 1669 pDialog->Execute(); 1670 delete pDialog; 1671 } 1672 1673 // GridControls wieder restaurieren 1674 LoopGrids(GA_ENABLE_SYNC | GA_DISABLE_ROCTRLR); 1675 1676 m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView()); 1677 // da ich in OnFoundData (fals ich dort war) Controls markiert habe 1678 } 1679 1680 //------------------------------------------------------------------------------ 1681 sal_Bool FmXFormShell::GetY2KState(sal_uInt16& n) 1682 { 1683 if ( impl_checkDisposed() ) 1684 return sal_False; 1685 1686 if (m_pShell->IsDesignMode()) 1687 // im Design-Modus (ohne aktive Controls) soll sich das Haupt-Dokument darum kuemmern 1688 return sal_False; 1689 1690 Reference< XForm> xForm( getActiveForm()); 1691 if (!xForm.is()) 1692 // kein aktuelles Formular (also insbesondere kein aktuelles Control) -> das Haupt-Dokument soll sich kuemmern 1693 return sal_False; 1694 1695 Reference< XRowSet> xDB(xForm, UNO_QUERY); 1696 DBG_ASSERT(xDB.is(), "FmXFormShell::GetY2KState : current form has no dbform-interface !"); 1697 1698 Reference< XNumberFormatsSupplier> xSupplier( getNumberFormats(OStaticDataAccessTools().getRowSetConnection(xDB), sal_False)); 1699 if (xSupplier.is()) 1700 { 1701 Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings()); 1702 if (xSet.is()) 1703 { 1704 try 1705 { 1706 Any aVal( xSet->getPropertyValue(::rtl::OUString::createFromAscii("TwoDigitDateStart")) ); 1707 aVal >>= n; 1708 return sal_True; 1709 } 1710 catch(Exception&) 1711 { 1712 } 1713 1714 } 1715 } 1716 return sal_False; 1717 } 1718 1719 //------------------------------------------------------------------------------ 1720 void FmXFormShell::SetY2KState(sal_uInt16 n) 1721 { 1722 if ( impl_checkDisposed() ) 1723 return; 1724 1725 Reference< XForm > xActiveForm( getActiveForm()); 1726 Reference< XRowSet > xActiveRowSet( xActiveForm, UNO_QUERY ); 1727 if ( xActiveRowSet.is() ) 1728 { 1729 Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( getRowSetConnection( xActiveRowSet ), sal_False ) ); 1730 if (xSupplier.is()) 1731 { 1732 Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings()); 1733 if (xSet.is()) 1734 { 1735 try 1736 { 1737 Any aVal; 1738 aVal <<= n; 1739 xSet->setPropertyValue(::rtl::OUString::createFromAscii("TwoDigitDateStart"), aVal); 1740 } 1741 catch(Exception&) 1742 { 1743 DBG_ERROR("FmXFormShell::SetY2KState: Exception occured!"); 1744 } 1745 1746 } 1747 return; 1748 } 1749 } 1750 1751 // kein aktives Formular gefunden -> alle aktuell vorhandenen Formulare durchiterieren 1752 Reference< XIndexAccess> xCurrentForms( m_xForms); 1753 if (!xCurrentForms.is()) 1754 { // im alive-Modus sind meine Forms nicht gesetzt, wohl aber die an der Page 1755 if (m_pShell->GetCurPage()) 1756 xCurrentForms = Reference< XIndexAccess>( m_pShell->GetCurPage()->GetForms( false ), UNO_QUERY ); 1757 } 1758 if (!xCurrentForms.is()) 1759 return; 1760 1761 ::comphelper::IndexAccessIterator aIter(xCurrentForms); 1762 Reference< XInterface> xCurrentElement( aIter.Next()); 1763 while (xCurrentElement.is()) 1764 { 1765 // ist das aktuelle Element eine DatabaseForm ? 1766 Reference< XRowSet> xElementAsRowSet( xCurrentElement, UNO_QUERY ); 1767 if ( xElementAsRowSet.is() ) 1768 { 1769 Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( getRowSetConnection( xElementAsRowSet ), sal_False ) ); 1770 if (!xSupplier.is()) 1771 continue; 1772 1773 Reference< XPropertySet> xSet(xSupplier->getNumberFormatSettings()); 1774 if (xSet.is()) 1775 { 1776 try 1777 { 1778 Any aVal; 1779 aVal <<= n; 1780 xSet->setPropertyValue(::rtl::OUString::createFromAscii("TwoDigitDateStart"), aVal); 1781 } 1782 catch(Exception&) 1783 { 1784 DBG_ERROR("FmXFormShell::SetY2KState: Exception occured!"); 1785 } 1786 1787 } 1788 } 1789 xCurrentElement = aIter.Next(); 1790 } 1791 } 1792 1793 //------------------------------------------------------------------------------ 1794 void FmXFormShell::CloseExternalFormViewer() 1795 { 1796 if ( impl_checkDisposed() ) 1797 return; 1798 1799 if (!m_xExternalViewController.is()) 1800 return; 1801 1802 Reference< ::com::sun::star::frame::XFrame> xExternalViewFrame( m_xExternalViewController->getFrame()); 1803 Reference< ::com::sun::star::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY); 1804 if (!xCommLink.is()) 1805 return; 1806 1807 xExternalViewFrame->setComponent(NULL,NULL); 1808 ::comphelper::disposeComponent(xExternalViewFrame); 1809 m_xExternalViewController = NULL; 1810 m_xExtViewTriggerController = NULL; 1811 m_xExternalDisplayedForm = NULL; 1812 } 1813 1814 //------------------------------------------------------------------------------ 1815 Reference< XResultSet> FmXFormShell::getInternalForm(const Reference< XResultSet>& _xForm) const 1816 { 1817 if ( impl_checkDisposed() ) 1818 return NULL; 1819 1820 Reference< runtime::XFormController> xExternalCtrlr(m_xExternalViewController, UNO_QUERY); 1821 if (xExternalCtrlr.is() && (_xForm == xExternalCtrlr->getModel())) 1822 { 1823 DBG_ASSERT(m_xExternalDisplayedForm.is(), "FmXFormShell::getInternalForm : invalid external form !"); 1824 return m_xExternalDisplayedForm; 1825 } 1826 return _xForm; 1827 } 1828 1829 //------------------------------------------------------------------------------ 1830 Reference< XForm> FmXFormShell::getInternalForm(const Reference< XForm>& _xForm) const 1831 { 1832 if ( impl_checkDisposed() ) 1833 return NULL; 1834 1835 Reference< runtime::XFormController > xExternalCtrlr(m_xExternalViewController, UNO_QUERY); 1836 if (xExternalCtrlr.is() && (_xForm == xExternalCtrlr->getModel())) 1837 { 1838 DBG_ASSERT(m_xExternalDisplayedForm.is(), "FmXFormShell::getInternalForm : invalid external form !"); 1839 return Reference< XForm>(m_xExternalDisplayedForm, UNO_QUERY); 1840 } 1841 return _xForm; 1842 } 1843 1844 //------------------------------------------------------------------------ 1845 namespace 1846 { 1847 static bool lcl_isNavigationRelevant( sal_Int32 _nWhich ) 1848 { 1849 return ( _nWhich == SID_FM_RECORD_FIRST ) 1850 || ( _nWhich == SID_FM_RECORD_PREV ) 1851 || ( _nWhich == SID_FM_RECORD_NEXT ) 1852 || ( _nWhich == SID_FM_RECORD_LAST ) 1853 || ( _nWhich == SID_FM_RECORD_NEW ); 1854 } 1855 } 1856 1857 //------------------------------------------------------------------------------ 1858 bool FmXFormShell::IsFormSlotEnabled( sal_Int32 _nSlot, FeatureState* _pCompleteState ) 1859 { 1860 const ::svx::ControllerFeatures& rController = 1861 lcl_isNavigationRelevant( _nSlot ) 1862 ? getNavControllerFeatures() 1863 : getActiveControllerFeatures(); 1864 1865 if ( !_pCompleteState ) 1866 return rController->isEnabled( _nSlot ); 1867 1868 rController->getState( _nSlot, *_pCompleteState ); 1869 return _pCompleteState->Enabled; 1870 } 1871 1872 //------------------------------------------------------------------------------ 1873 void FmXFormShell::ExecuteFormSlot( sal_Int32 _nSlot ) 1874 { 1875 const ::svx::ControllerFeatures& rController = 1876 lcl_isNavigationRelevant( _nSlot ) 1877 ? getNavControllerFeatures() 1878 : getActiveControllerFeatures(); 1879 1880 rController->execute( _nSlot ); 1881 1882 if ( _nSlot == SID_FM_RECORD_UNDO ) 1883 { 1884 // if we're doing an UNDO, *and* if the affected form is the form which we also display 1885 // as external view, then we need to reset the controls of the external form, too 1886 if ( getInternalForm( getActiveForm() ) == m_xExternalDisplayedForm ) 1887 { 1888 Reference< XIndexAccess > xContainer( m_xExternalDisplayedForm, UNO_QUERY ); 1889 if ( xContainer.is() ) 1890 { 1891 Reference< XReset > xReset; 1892 for ( sal_Int32 i = 0; i < xContainer->getCount(); ++i ) 1893 { 1894 if ( ( xContainer->getByIndex( i ) >>= xReset ) && xReset.is() ) 1895 { 1896 // no resets on sub forms 1897 Reference< XForm > xAsForm( xReset, UNO_QUERY ); 1898 if ( !xAsForm.is() ) 1899 xReset->reset(); 1900 } 1901 } 1902 } 1903 } 1904 } 1905 } 1906 1907 //------------------------------------------------------------------------------ 1908 void FmXFormShell::impl_switchActiveControllerListening( const bool _bListen ) 1909 { 1910 Reference< XComponent> xComp( m_xActiveController, UNO_QUERY ); 1911 if ( !xComp.is() ) 1912 return; 1913 1914 if ( _bListen ) 1915 xComp->addEventListener( (XFormControllerListener*)this ); 1916 else 1917 xComp->removeEventListener( (XFormControllerListener*)this ); 1918 } 1919 1920 //------------------------------------------------------------------------------ 1921 void FmXFormShell::setActiveController( const Reference< runtime::XFormController >& xController, sal_Bool _bNoSaveOldContent ) 1922 { 1923 if ( impl_checkDisposed() ) 1924 return; 1925 1926 if (m_bChangingDesignMode) 1927 return; 1928 DBG_ASSERT(!m_pShell->IsDesignMode(), "nur im alive mode verwenden"); 1929 1930 // Ist die Routine ein zweites Mal gerufen worden, 1931 // dann sollte der Focus nicht mehr umgesetzt werden 1932 if (m_bInActivate) 1933 { 1934 m_bSetFocus = xController != m_xActiveController; 1935 return; 1936 } 1937 1938 if (xController != m_xActiveController) 1939 { 1940 ::osl::ClearableMutexGuard aGuard(m_aAsyncSafety); 1941 // switch all nav dispatchers belonging to the form of the current nav controller to 'non active' 1942 Reference< XResultSet> xNavigationForm; 1943 if (m_xNavigationController.is()) 1944 xNavigationForm = Reference< XResultSet>(m_xNavigationController->getModel(), UNO_QUERY); 1945 aGuard.clear(); 1946 1947 m_bInActivate = sal_True; 1948 1949 // check if the 2 controllers serve different forms 1950 Reference< XResultSet> xOldForm; 1951 if (m_xActiveController.is()) 1952 xOldForm = Reference< XResultSet>(m_xActiveController->getModel(), UNO_QUERY); 1953 Reference< XResultSet> xNewForm; 1954 if (xController.is()) 1955 xNewForm = Reference< XResultSet>(xController->getModel(), UNO_QUERY); 1956 xOldForm = getInternalForm(xOldForm); 1957 xNewForm = getInternalForm(xNewForm); 1958 1959 sal_Bool bDifferentForm = ( xOldForm.get() != xNewForm.get() ); 1960 sal_Bool bNeedSave = bDifferentForm && !_bNoSaveOldContent; 1961 // we save the content of the old form if we move to a new form, and saving old content is allowed 1962 1963 if ( m_xActiveController.is() && bNeedSave ) 1964 { 1965 // beim Wechsel des Controllers den Inhalt speichern, ein Commit 1966 // wurde bereits ausgefuehrt 1967 if ( m_aActiveControllerFeatures->commitCurrentControl() ) 1968 { 1969 m_bSetFocus = sal_True; 1970 if ( m_aActiveControllerFeatures->isModifiedRow() ) 1971 { 1972 sal_Bool bIsNew = m_aActiveControllerFeatures->isInsertionRow(); 1973 sal_Bool bResult = m_aActiveControllerFeatures->commitCurrentRecord(); 1974 if ( !bResult && m_bSetFocus ) 1975 { 1976 // if we couldn't save the current record, set the focus back to the 1977 // current control 1978 Reference< XWindow > xWindow( m_xActiveController->getCurrentControl(), UNO_QUERY ); 1979 if ( xWindow.is() ) 1980 xWindow->setFocus(); 1981 m_bInActivate = sal_False; 1982 return; 1983 } 1984 else if ( bResult && bIsNew ) 1985 { 1986 Reference< XResultSet > xCursor( m_aActiveControllerFeatures->getCursor().get() ); 1987 if ( xCursor.is() ) 1988 { 1989 DO_SAFE( xCursor->last(); ); 1990 } 1991 } 1992 } 1993 } 1994 } 1995 1996 stopListening(); 1997 1998 impl_switchActiveControllerListening( false ); 1999 2000 m_aActiveControllerFeatures.dispose(); 2001 m_xActiveController = xController; 2002 if ( m_xActiveController.is() ) 2003 m_aActiveControllerFeatures.assign( m_xActiveController ); 2004 2005 impl_switchActiveControllerListening( true ); 2006 2007 if ( m_xActiveController.is() ) 2008 m_xActiveForm = getInternalForm( Reference< XForm >( m_xActiveController->getModel(), UNO_QUERY ) ); 2009 else 2010 m_xActiveForm = NULL; 2011 2012 startListening(); 2013 2014 // activate all dispatchers belonging to form of the new navigation controller 2015 xNavigationForm = NULL; 2016 if (m_xNavigationController.is()) 2017 xNavigationForm = Reference< XResultSet>(m_xNavigationController->getModel(), UNO_QUERY); 2018 2019 m_bInActivate = sal_False; 2020 2021 m_pShell->UIFeatureChanged(); 2022 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell); 2023 2024 InvalidateSlot(SID_FM_FILTER_NAVIGATOR_CONTROL, sal_True); 2025 } 2026 } 2027 2028 //------------------------------------------------------------------------------ 2029 void FmXFormShell::getCurrentSelection( InterfaceBag& /* [out] */ _rSelection ) const 2030 { 2031 _rSelection = m_aCurrentSelection; 2032 } 2033 2034 //------------------------------------------------------------------------------ 2035 bool FmXFormShell::setCurrentSelectionFromMark( const SdrMarkList& _rMarkList ) 2036 { 2037 m_aLastKnownMarkedControls.clear(); 2038 2039 if ( ( _rMarkList.GetMarkCount() > 0 ) && isControlList( _rMarkList ) ) 2040 collectInterfacesFromMarkList( _rMarkList, m_aLastKnownMarkedControls ); 2041 2042 return setCurrentSelection( m_aLastKnownMarkedControls ); 2043 } 2044 2045 //------------------------------------------------------------------------------ 2046 bool FmXFormShell::selectLastMarkedControls() 2047 { 2048 return setCurrentSelection( m_aLastKnownMarkedControls ); 2049 } 2050 2051 //------------------------------------------------------------------------------ 2052 bool FmXFormShell::setCurrentSelection( const InterfaceBag& _rSelection ) 2053 { 2054 if ( impl_checkDisposed() ) 2055 return false; 2056 2057 DBG_ASSERT( m_pShell->IsDesignMode(), "FmXFormShell::setCurrentSelection: only to be used in design mode!" ); 2058 2059 if ( _rSelection.empty() && m_aCurrentSelection.empty() ) 2060 // nothing to do 2061 return false; 2062 2063 if ( _rSelection.size() == m_aCurrentSelection.size() ) 2064 { 2065 InterfaceBag::const_iterator aNew = _rSelection.begin(); 2066 InterfaceBag::const_iterator aOld = m_aCurrentSelection.begin(); 2067 for ( ; aNew != _rSelection.end(); ++aNew, ++aOld ) 2068 { 2069 OSL_ENSURE( Reference< XInterface >( *aNew, UNO_QUERY ).get() == aNew->get(), "FmXFormShell::setCurrentSelection: new interface not normalized!" ); 2070 OSL_ENSURE( Reference< XInterface >( *aOld, UNO_QUERY ).get() == aOld->get(), "FmXFormShell::setCurrentSelection: old interface not normalized!" ); 2071 2072 if ( aNew->get() != aOld->get() ) 2073 break; 2074 } 2075 2076 if ( aNew == _rSelection.end() ) 2077 // both bags equal 2078 return false; 2079 } 2080 2081 // the following is some strange code to ensure that when you have two grid controls in a document, 2082 // only one of them can have a selected column. 2083 // TODO: this should happen elsewhere, but not here - shouldn't it? 2084 if ( !m_aCurrentSelection.empty() ) 2085 { 2086 Reference< XChild > xCur; if ( m_aCurrentSelection.size() == 1 ) xCur = xCur.query( *m_aCurrentSelection.begin() ); 2087 Reference< XChild > xNew; if ( _rSelection.size() == 1 ) xNew = xNew.query( *_rSelection.begin() ); 2088 2089 // is there nothing to be selected, or the parents differ, and the parent of the current object 2090 // is a selection supplier, then deselect 2091 if ( xCur.is() && ( !xNew.is() || ( xCur->getParent() != xNew->getParent() ) ) ) 2092 { 2093 Reference< XSelectionSupplier > xSel( xCur->getParent(), UNO_QUERY ); 2094 if ( xSel.is() ) 2095 xSel->select( Any() ); 2096 } 2097 } 2098 2099 m_aCurrentSelection = _rSelection; 2100 2101 // determine the form which all the selected obj�cts belong to, if any 2102 Reference< XForm > xNewCurrentForm; 2103 for ( InterfaceBag::const_iterator loop = m_aCurrentSelection.begin(); 2104 loop != m_aCurrentSelection.end(); 2105 ++loop 2106 ) 2107 { 2108 Reference< XForm > xThisRoundsForm( GetForm( *loop ) ); 2109 OSL_ENSURE( xThisRoundsForm.is(), "FmXFormShell::setCurrentSelection: *everything* should belong to a form!" ); 2110 2111 if ( !xNewCurrentForm.is() ) 2112 { // the first form we encounterd 2113 xNewCurrentForm = xThisRoundsForm; 2114 } 2115 else if ( xNewCurrentForm != xThisRoundsForm ) 2116 { // different forms -> no "current form" at all 2117 xNewCurrentForm.clear(); 2118 break; 2119 } 2120 } 2121 2122 if ( !m_aCurrentSelection.empty() ) 2123 impl_updateCurrentForm( xNewCurrentForm ); 2124 2125 // ensure some slots are updated 2126 for ( size_t i = 0; i < sizeof( SelObjectSlotMap ) / sizeof( SelObjectSlotMap[0] ); ++i ) 2127 InvalidateSlot( SelObjectSlotMap[i], sal_False); 2128 2129 return true; 2130 } 2131 2132 //------------------------------------------------------------------------------ 2133 bool FmXFormShell::isSolelySelected( const Reference< XInterface >& _rxObject ) 2134 { 2135 return ( m_aCurrentSelection.size() == 1 ) && ( *m_aCurrentSelection.begin() == _rxObject ); 2136 } 2137 2138 //------------------------------------------------------------------------------ 2139 void FmXFormShell::forgetCurrentForm() 2140 { 2141 if ( !m_xCurrentForm.is() ) 2142 return; 2143 2144 // reset ... 2145 impl_updateCurrentForm( NULL ); 2146 2147 // ... and try finding a new current form 2148 // #i88186# / 2008-04-12 / frank.schoenheit@sun.com 2149 impl_defaultCurrentForm_nothrow(); 2150 } 2151 2152 //------------------------------------------------------------------------------ 2153 void FmXFormShell::impl_updateCurrentForm( const Reference< XForm >& _rxNewCurForm ) 2154 { 2155 if ( impl_checkDisposed() ) 2156 return; 2157 2158 m_xCurrentForm = _rxNewCurForm; 2159 2160 // propagate to the FormPage(Impl) 2161 FmFormPage* pPage = m_pShell->GetCurPage(); 2162 if ( pPage ) 2163 pPage->GetImpl().setCurForm( m_xCurrentForm ); 2164 2165 // ensure the UI which depends on the current form is up-to-date 2166 for ( size_t i = 0; i < sizeof( DlgSlotMap ) / sizeof( DlgSlotMap[0] ); ++i ) 2167 InvalidateSlot( DlgSlotMap[i], sal_False ); 2168 } 2169 2170 //------------------------------------------------------------------------------ 2171 void FmXFormShell::startListening() 2172 { 2173 if ( impl_checkDisposed() ) 2174 return; 2175 2176 Reference< XRowSet> xDatabaseForm(m_xActiveForm, UNO_QUERY); 2177 if (xDatabaseForm.is() && getRowSetConnection(xDatabaseForm).is()) 2178 { 2179 Reference< XPropertySet> xActiveFormSet(m_xActiveForm, UNO_QUERY); 2180 if (xActiveFormSet.is()) 2181 { 2182 // wenn es eine Datenquelle gibt, dann den Listener aufbauen 2183 // TODO: this is strange - shouldn't this depend on a isLoaded instead of 2184 // a "has command value"? Finally, the command value only means that it was 2185 // intended to be loaded, not that it actually *is* loaded 2186 ::rtl::OUString aSource = ::comphelper::getString(xActiveFormSet->getPropertyValue(FM_PROP_COMMAND)); 2187 if (aSource.getLength()) 2188 { 2189 m_bDatabaseBar = sal_True; 2190 2191 xActiveFormSet->getPropertyValue(FM_PROP_NAVIGATION) >>= m_eNavigate; 2192 2193 switch (m_eNavigate) 2194 { 2195 case NavigationBarMode_PARENT: 2196 { 2197 // suchen des Controllers, ueber den eine Navigation moeglich ist 2198 Reference< XChild> xChild(m_xActiveController, UNO_QUERY); 2199 Reference< runtime::XFormController > xParent; 2200 while (xChild.is()) 2201 { 2202 xChild = Reference< XChild>(xChild->getParent(), UNO_QUERY); 2203 xParent = Reference< runtime::XFormController >(xChild, UNO_QUERY); 2204 Reference< XPropertySet> xParentSet; 2205 if (xParent.is()) 2206 xParentSet = Reference< XPropertySet>(xParent->getModel(), UNO_QUERY); 2207 if (xParentSet.is()) 2208 { 2209 xParentSet->getPropertyValue(FM_PROP_NAVIGATION) >>= m_eNavigate; 2210 if (m_eNavigate == NavigationBarMode_CURRENT) 2211 break; 2212 } 2213 } 2214 m_xNavigationController = xParent; 2215 } 2216 break; 2217 2218 case NavigationBarMode_CURRENT: 2219 m_xNavigationController = m_xActiveController; 2220 break; 2221 2222 default: 2223 m_xNavigationController = NULL; 2224 m_bDatabaseBar = sal_False; 2225 } 2226 2227 m_aNavControllerFeatures.dispose(); 2228 if ( m_xNavigationController.is() && ( m_xNavigationController != m_xActiveController ) ) 2229 m_aNavControllerFeatures.assign( m_xNavigationController ); 2230 2231 // an dem Controller, der die Navigation regelt, wg. RecordCount lauschen 2232 Reference< XPropertySet> xNavigationSet; 2233 if (m_xNavigationController.is()) 2234 { 2235 xNavigationSet = Reference< XPropertySet>(m_xNavigationController->getModel(), UNO_QUERY); 2236 if (xNavigationSet.is()) 2237 xNavigationSet->addPropertyChangeListener(FM_PROP_ROWCOUNT,this); 2238 } 2239 return; 2240 } 2241 } 2242 } 2243 2244 m_eNavigate = NavigationBarMode_NONE; 2245 m_bDatabaseBar = sal_False; 2246 m_xNavigationController = NULL; 2247 } 2248 2249 //------------------------------------------------------------------------------ 2250 void FmXFormShell::stopListening() 2251 { 2252 if ( impl_checkDisposed() ) 2253 return; 2254 2255 Reference< XRowSet> xDatabaseForm(m_xActiveForm, UNO_QUERY); 2256 if ( xDatabaseForm.is() ) 2257 { 2258 if (m_xNavigationController.is()) 2259 { 2260 Reference< XPropertySet> xSet(m_xNavigationController->getModel(), UNO_QUERY); 2261 if (xSet.is()) 2262 xSet->removePropertyChangeListener(FM_PROP_ROWCOUNT, this); 2263 2264 } 2265 } 2266 2267 m_bDatabaseBar = sal_False; 2268 m_eNavigate = NavigationBarMode_NONE; 2269 m_xNavigationController = NULL; 2270 } 2271 2272 //------------------------------------------------------------------------------ 2273 void FmXFormShell::ShowSelectionProperties( sal_Bool bShow ) 2274 { 2275 if ( impl_checkDisposed() ) 2276 return; 2277 2278 // if the window is already visible, only update the state 2279 sal_Bool bHasChild = m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_PROPERTIES ); 2280 if ( bHasChild && bShow ) 2281 UpdateSlot( SID_FM_PROPERTY_CONTROL ); 2282 2283 // else toggle state 2284 else 2285 m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES); 2286 2287 InvalidateSlot( SID_FM_PROPERTIES, sal_False ); 2288 InvalidateSlot( SID_FM_CTL_PROPERTIES, sal_False ); 2289 } 2290 2291 //------------------------------------------------------------------------------ 2292 IMPL_LINK(FmXFormShell, OnFoundData, FmFoundRecordInformation*, pfriWhere) 2293 { 2294 if ( impl_checkDisposed() ) 2295 return 0; 2296 2297 DBG_ASSERT((pfriWhere->nContext >= 0) && (pfriWhere->nContext < (sal_Int16)m_aSearchForms.size()), 2298 "FmXFormShell::OnFoundData : ungueltiger Kontext !"); 2299 Reference< XForm> xForm( m_aSearchForms.at(pfriWhere->nContext)); 2300 DBG_ASSERT(xForm.is(), "FmXFormShell::OnFoundData : ungueltige Form !"); 2301 2302 Reference< XRowLocate> xCursor(xForm, UNO_QUERY); 2303 if (!xCursor.is()) 2304 return 0; // was soll ich da machen ? 2305 2306 // zum Datensatz 2307 try 2308 { 2309 xCursor->moveToBookmark(pfriWhere->aPosition); 2310 } 2311 catch(const SQLException&) 2312 { 2313 OSL_ENSURE(0,"Can position on bookmark!"); 2314 } 2315 2316 LoopGrids(GA_FORCE_SYNC); 2317 2318 // und zum Feld (dazu habe ich vor dem Start des Suchens die XVclComponent-Interfaces eingesammelt) 2319 DBG_ASSERT(pfriWhere->nFieldPos < m_arrSearchedControls.Count(), "FmXFormShell::OnFoundData : ungueltige Daten uebergeben !"); 2320 SdrObject* pObject = m_arrSearchedControls.GetObject(pfriWhere->nFieldPos); 2321 DBG_ASSERT(pObject != NULL, "FmXFormShell::OnFoundData : unerwartet : ungueltiges VclControl-Interface"); 2322 2323 m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView()); 2324 m_pShell->GetFormView()->MarkObj(pObject, m_pShell->GetFormView()->GetSdrPageView()); 2325 2326 FmFormObj* pFormObject = FmFormObj::GetFormObject( pObject ); 2327 Reference< XControlModel > xControlModel( pFormObject ? pFormObject->GetUnoControlModel() : Reference< XControlModel >() ); 2328 DBG_ASSERT( xControlModel.is(), "FmXFormShell::OnFoundData: invalid control!" ); 2329 if ( !xControlModel.is() ) 2330 return 0; 2331 2332 // disable the permanent cursor for the last grid we found a record 2333 if (m_xLastGridFound.is() && (m_xLastGridFound != xControlModel)) 2334 { 2335 Reference< XPropertySet> xOldSet(m_xLastGridFound, UNO_QUERY); 2336 xOldSet->setPropertyValue(FM_PROP_ALWAYSSHOWCURSOR, makeAny( (sal_Bool)sal_False ) ); 2337 Reference< XPropertyState> xOldSetState(xOldSet, UNO_QUERY); 2338 if (xOldSetState.is()) 2339 xOldSetState->setPropertyToDefault(FM_PROP_CURSORCOLOR); 2340 else 2341 xOldSet->setPropertyValue(FM_PROP_CURSORCOLOR, Any()); 2342 } 2343 2344 // wenn das Feld sich in einem GridControl befindet, muss ich dort noch in die entsprechende Spalte gehen 2345 sal_Int32 nGridColumn = m_arrRelativeGridColumn.GetObject(pfriWhere->nFieldPos); 2346 if (nGridColumn != -1) 2347 { // dummer weise muss ich mir das Control erst wieder besorgen 2348 Reference< XControl> xControl( impl_getControl( xControlModel, *pFormObject ) ); 2349 Reference< XGrid> xGrid(xControl, UNO_QUERY); 2350 DBG_ASSERT(xGrid.is(), "FmXFormShell::OnFoundData : ungueltiges Control !"); 2351 // wenn eine der Asserts anschlaegt, habe ich beim Aufbauen von m_arrSearchedControls wohl was falsch gemacht 2352 2353 // enable a permanent cursor for the grid so we can see the found text 2354 Reference< XPropertySet> xModelSet(xControlModel, UNO_QUERY); 2355 DBG_ASSERT(xModelSet.is(), "FmXFormShell::OnFoundData : invalid control model (no property set) !"); 2356 xModelSet->setPropertyValue( FM_PROP_ALWAYSSHOWCURSOR, makeAny( (sal_Bool)sal_True ) ); 2357 xModelSet->setPropertyValue( FM_PROP_CURSORCOLOR, makeAny( sal_Int32( COL_LIGHTRED ) ) ); 2358 m_xLastGridFound = xControlModel; 2359 2360 if ( xGrid.is() ) 2361 xGrid->setCurrentColumnPosition((sal_Int16)nGridColumn); 2362 } 2363 2364 // als der Cursor neu positioniert wurde, habe ich (in positioned) meine Formularleisten-Slots invalidiert, aber das greift 2365 // hier dummerweise nicht, da i.A. ja der (modale) Suchdialog oben ist ... also Gewalt ... 2366 sal_uInt16 nPos = 0; 2367 while (DatabaseSlotMap[nPos]) 2368 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().Update(DatabaseSlotMap[nPos++]); 2369 // leider geht das Update im Gegensatz zum Invalidate nur mit einzelnen Slots) 2370 2371 return 0; 2372 } 2373 2374 //------------------------------------------------------------------------------ 2375 IMPL_LINK(FmXFormShell, OnCanceledNotFound, FmFoundRecordInformation*, pfriWhere) 2376 { 2377 if ( impl_checkDisposed() ) 2378 return 0; 2379 2380 DBG_ASSERT((pfriWhere->nContext >= 0) && (pfriWhere->nContext < (sal_Int16)m_aSearchForms.size()), 2381 "FmXFormShell::OnCanceledNotFound : ungueltiger Kontext !"); 2382 Reference< XForm> xForm( m_aSearchForms.at(pfriWhere->nContext)); 2383 DBG_ASSERT(xForm.is(), "FmXFormShell::OnCanceledNotFound : ungueltige Form !"); 2384 2385 Reference< XRowLocate> xCursor(xForm, UNO_QUERY); 2386 if (!xCursor.is()) 2387 return 0; // was soll ich da machen ? 2388 2389 // zum Datensatz 2390 try 2391 { 2392 xCursor->moveToBookmark(pfriWhere->aPosition); 2393 } 2394 catch(const SQLException&) 2395 { 2396 OSL_ENSURE(0,"Can position on bookmark!"); 2397 } 2398 2399 2400 m_pShell->GetFormView()->UnMarkAll(m_pShell->GetFormView()->GetSdrPageView()); 2401 return 0L; 2402 } 2403 2404 //------------------------------------------------------------------------------ 2405 IMPL_LINK(FmXFormShell, OnSearchContextRequest, FmSearchContext*, pfmscContextInfo) 2406 { 2407 if ( impl_checkDisposed() ) 2408 return 0; 2409 2410 DBG_ASSERT(pfmscContextInfo->nContext < (sal_Int16)m_aSearchForms.size(), "FmXFormShell::OnSearchContextRequest : invalid parameter !"); 2411 Reference< XForm> xForm( m_aSearchForms.at(pfmscContextInfo->nContext)); 2412 DBG_ASSERT(xForm.is(), "FmXFormShell::OnSearchContextRequest : unexpected : invalid context !"); 2413 2414 Reference< XResultSet> xIter(xForm, UNO_QUERY); 2415 DBG_ASSERT(xIter.is(), "FmXFormShell::OnSearchContextRequest : unexpected : context has no iterator !"); 2416 2417 // -------------------------------------------------------------------------------------------- 2418 // die Liste der zu involvierenden Felder zusammenstellen (sind die ControlSources aller Felder, die eine solche Eigenschaft habe) 2419 UniString strFieldList, sFieldDisplayNames; 2420 m_arrSearchedControls.Remove(0, m_arrSearchedControls.Count()); 2421 m_arrRelativeGridColumn.Remove(0, m_arrRelativeGridColumn.Count()); 2422 2423 // folgendes kleines Problem : Ich brauche, um gefundene Felder zu markieren, SdrObjekte. Um hier festzustellen, welche Controls 2424 // ich in die Suche einbeziehen soll, brauche ich Controls (also XControl-Interfaces). Ich muss also ueber eines von beiden 2425 // iterieren und mir das jeweils andere besorgen. Dummerweise gibt es keine direkte Verbindung zwischen beiden Welten (abgesehen 2426 // von einem GetUnoControl an SdrUnoObject, das aber ein OutputDevice verlangt, womit ich nichts anfangen kann). 2427 // Allerdings komme ich sowohl von einem Control als auch von einem SdrObject zum Model, und damit ist mir mit einer doppelten 2428 // Schleife die Zuordnung SdrObject<->Control moeglich. 2429 // Die Alternative zu dieser (unschoenen und sicher auch nicht ganz fixen) Loesung waere, auf das Cachen der SdrObjects zu 2430 // verzichten, was dann aber in OnFoundData zu wesentlicher Mehrarbeit fuehren wuerde (da ich mir dort jedesmal das SdrObject 2431 // erst besorgen muesste). Da aber OnFoundData i.d.R. oefter aufgerufen wird als ExecuteSearch, erledige ich das hier. 2432 2433 Reference< XNameAccess> xValidFormFields; 2434 Reference< XColumnsSupplier> xSupplyCols(xIter, UNO_QUERY); 2435 DBG_ASSERT(xSupplyCols.is(), "FmXFormShell::OnSearchContextRequest : invalid cursor : no columns supplier !"); 2436 if (xSupplyCols.is()) 2437 xValidFormFields = xSupplyCols->getColumns(); 2438 DBG_ASSERT(xValidFormFields.is(), "FmXFormShell::OnSearchContextRequest : form has no fields !"); 2439 2440 // aktuelle(r) Page/Controller 2441 FmFormPage* pCurrentPage = m_pShell->GetCurPage(); 2442 DBG_ASSERT(pCurrentPage!=NULL, "FmXFormShell::OnSearchContextRequest : no page !"); 2443 // alle Sdr-Controls dieser Seite durchsuchen ... 2444 ::rtl::OUString sControlSource, aName; 2445 2446 SdrObjListIter aPageIter( *pCurrentPage ); 2447 while ( aPageIter.IsMore() ) 2448 { 2449 SdrObject* pCurrent = aPageIter.Next(); 2450 FmFormObj* pFormObject = FmFormObj::GetFormObject( pCurrent ); 2451 // note that in case pCurrent is a virtual object, pFormObject points to the referenced object 2452 2453 if ( !pFormObject ) 2454 continue; 2455 2456 // the current object's model, in different tastes 2457 Reference< XControlModel> xControlModel( pFormObject->GetUnoControlModel() ); 2458 Reference< XFormComponent > xCurrentFormComponent( xControlModel, UNO_QUERY ); 2459 DBG_ASSERT( xCurrentFormComponent.is(), "FmXFormShell::OnSearchContextRequest: invalid objects!" ); 2460 if ( !xCurrentFormComponent.is() ) 2461 continue; 2462 2463 // does the component belong to the form which we're interested in? 2464 if ( xCurrentFormComponent->getParent() != xForm ) 2465 continue; 2466 2467 // ... nach der ControlSource-Eigenschaft fragen 2468 SearchableControlIterator iter( xCurrentFormComponent ); 2469 Reference< XControl> xControl; 2470 // das Control, das als Model xControlModel hat 2471 // (das folgende while kann mehrmals durchlaufen werden, ohne dass das Control sich aendert, dann muss 2472 // ich nicht jedesmal neu suchen) 2473 2474 Reference< XInterface > xSearchable( iter.Next() ); 2475 while ( xSearchable.is() ) 2476 { 2477 sControlSource = iter.getCurrentValue(); 2478 if ( sControlSource.getLength() == 0 ) 2479 { // das aktuelle Element hat keine ControlSource, also ist es ein GridControl (das ist das einzige, was 2480 // der SearchableControlIterator noch zulaesst) 2481 xControl = impl_getControl( xControlModel, *pFormObject ); 2482 DBG_ASSERT(xControl.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !"); 2483 2484 Reference< XGridPeer> xGridPeer; 2485 if ( xControl.is() ) 2486 xGridPeer.set( xControl->getPeer(), UNO_QUERY ); 2487 do 2488 { 2489 if (!xGridPeer.is()) 2490 break; 2491 2492 Reference< XIndexAccess> xPeerContainer(xGridPeer, UNO_QUERY); 2493 if (!xPeerContainer.is()) 2494 break; 2495 2496 Reference< XIndexAccess> xModelColumns(xGridPeer->getColumns(), UNO_QUERY); 2497 DBG_ASSERT(xModelColumns.is(), "FmXFormShell::OnSearchContextRequest : there is a grid control without columns !"); 2498 // the case 'no columns' should be indicated with an empty container, I think ... 2499 DBG_ASSERT(xModelColumns->getCount() >= xPeerContainer->getCount(), "FmXFormShell::OnSearchContextRequest : impossible : have more view than model columns !"); 2500 2501 Reference< XInterface> xCurrentColumn; 2502 for (sal_Int16 nViewPos=0; nViewPos<xPeerContainer->getCount(); ++nViewPos) 2503 { 2504 xPeerContainer->getByIndex(nViewPos) >>= xCurrentColumn; 2505 if (!xCurrentColumn.is()) 2506 continue; 2507 2508 // can we use this column control fo searching ? 2509 if (!IsSearchableControl(xCurrentColumn)) 2510 continue; 2511 2512 sal_Int16 nModelPos = GridView2ModelPos(xModelColumns, nViewPos); 2513 Reference< XPropertySet> xCurrentColModel; 2514 xModelColumns->getByIndex(nModelPos) >>= xCurrentColModel; 2515 aName = ::comphelper::getString(xCurrentColModel->getPropertyValue(FM_PROP_CONTROLSOURCE)); 2516 // the cursor has a field matching the control source ? 2517 if (xValidFormFields->hasByName(aName)) 2518 { 2519 strFieldList += aName.getStr(); 2520 strFieldList += ';'; 2521 2522 sFieldDisplayNames += ::comphelper::getString(xCurrentColModel->getPropertyValue(FM_PROP_LABEL)).getStr(); 2523 sFieldDisplayNames += ';'; 2524 2525 pfmscContextInfo->arrFields.push_back(xCurrentColumn); 2526 2527 // und das SdrObjekt zum Feld 2528 m_arrSearchedControls.C40_INSERT(SdrObject, pCurrent, m_arrSearchedControls.Count()); 2529 // die Nummer der Spalte 2530 m_arrRelativeGridColumn.Insert(nViewPos, m_arrRelativeGridColumn.Count()); 2531 } 2532 } 2533 } while (sal_False); 2534 } 2535 else 2536 { 2537 if (sControlSource.getLength() && xValidFormFields->hasByName(sControlSource)) 2538 { 2539 // jetzt brauche ich das Control zum SdrObject 2540 if (!xControl.is()) 2541 { 2542 xControl = impl_getControl( xControlModel, *pFormObject ); 2543 DBG_ASSERT(xControl.is(), "FmXFormShell::OnSearchContextRequest : didn't ::std::find a control with requested model !"); 2544 } 2545 2546 if (IsSearchableControl(xControl)) 2547 { // alle Tests ueberstanden -> in die Liste mit aufnehmen 2548 strFieldList += sControlSource.getStr(); 2549 strFieldList += ';'; 2550 2551 // the label which should appear for the control : 2552 sFieldDisplayNames += getLabelName(Reference< XPropertySet>(xControlModel, UNO_QUERY)).getStr(); 2553 sFieldDisplayNames += ';'; 2554 2555 // das SdrObjekt merken (beschleunigt die Behandlung in OnFoundData) 2556 m_arrSearchedControls.C40_INSERT(SdrObject, pCurrent, m_arrSearchedControls.Count()); 2557 2558 // die Nummer der Spalte (hier ein Dummy, nur fuer GridControls interesant) 2559 m_arrRelativeGridColumn.Insert(-1, m_arrRelativeGridColumn.Count()); 2560 2561 // und fuer die formatierte Suche ... 2562 pfmscContextInfo->arrFields.push_back(Reference< XInterface>(xControl, UNO_QUERY)); 2563 } 2564 } 2565 } 2566 2567 xSearchable = iter.Next(); 2568 } 2569 } 2570 2571 strFieldList.EraseTrailingChars(';'); 2572 sFieldDisplayNames.EraseTrailingChars(';'); 2573 2574 if (pfmscContextInfo->arrFields.empty()) 2575 { 2576 pfmscContextInfo->arrFields.clear(); 2577 pfmscContextInfo->xCursor = NULL; 2578 pfmscContextInfo->strUsedFields.Erase(); 2579 return 0L; 2580 } 2581 2582 pfmscContextInfo->xCursor = xIter; 2583 pfmscContextInfo->strUsedFields = strFieldList; 2584 pfmscContextInfo->sFieldDisplayNames = sFieldDisplayNames; 2585 2586 // 66463 - 31.05.99 - FS 2587 // wenn der Cursor sich in einem anderen RecordMode als STANDARD befindet, ruecksetzen 2588 Reference< XPropertySet> xCursorSet(pfmscContextInfo->xCursor, UNO_QUERY); 2589 Reference< XResultSetUpdate> xUpdateCursor(pfmscContextInfo->xCursor, UNO_QUERY); 2590 if (xUpdateCursor.is() && xCursorSet.is() && xCursorSet.is()) 2591 { 2592 if (::comphelper::getBOOL(xCursorSet->getPropertyValue(FM_PROP_ISNEW))) 2593 xUpdateCursor->moveToCurrentRow(); 2594 else if (::comphelper::getBOOL(xCursorSet->getPropertyValue(FM_PROP_ISMODIFIED))) 2595 xUpdateCursor->cancelRowUpdates(); 2596 } 2597 2598 return pfmscContextInfo->arrFields.size(); 2599 } 2600 2601 // XContainerListener 2602 //------------------------------------------------------------------------------ 2603 void FmXFormShell::elementInserted(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException) 2604 { 2605 if ( impl_checkDisposed() ) 2606 return; 2607 2608 // neues Object zum lauschen 2609 Reference< XInterface> xTemp; 2610 evt.Element >>= xTemp; 2611 AddElement(xTemp); 2612 m_pShell->DetermineForms(sal_True); 2613 } 2614 2615 //------------------------------------------------------------------------------ 2616 void FmXFormShell::elementReplaced(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException) 2617 { 2618 if ( impl_checkDisposed() ) 2619 return; 2620 2621 Reference< XInterface> xTemp; 2622 evt.ReplacedElement >>= xTemp; 2623 RemoveElement(xTemp); 2624 evt.Element >>= xTemp; 2625 AddElement(xTemp); 2626 } 2627 2628 //------------------------------------------------------------------------------ 2629 void FmXFormShell::elementRemoved(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException) 2630 { 2631 if ( impl_checkDisposed() ) 2632 return; 2633 2634 Reference< XInterface> xTemp; 2635 evt.Element >>= xTemp; 2636 RemoveElement(xTemp); 2637 m_pShell->DetermineForms(sal_True); 2638 } 2639 2640 //------------------------------------------------------------------------------ 2641 void FmXFormShell::UpdateForms( sal_Bool _bInvalidate ) 2642 { 2643 if ( impl_checkDisposed() ) 2644 return; 2645 2646 Reference< XIndexAccess > xForms; 2647 2648 FmFormPage* pPage = m_pShell->GetCurPage(); 2649 if ( pPage ) 2650 { 2651 if ( m_pShell->m_bDesignMode ) 2652 xForms = xForms.query( pPage->GetForms( false ) ); 2653 } 2654 2655 if ( m_xForms != xForms ) 2656 { 2657 RemoveElement( m_xForms ); 2658 m_xForms = xForms; 2659 AddElement( m_xForms ); 2660 } 2661 2662 m_pShell->DetermineForms( _bInvalidate ); 2663 } 2664 2665 //------------------------------------------------------------------------------ 2666 void FmXFormShell::AddElement(const Reference< XInterface>& _xElement) 2667 { 2668 if ( impl_checkDisposed() ) 2669 return; 2670 impl_AddElement_nothrow(_xElement); 2671 } 2672 // ----------------------------------------------------------------------------- 2673 void FmXFormShell::impl_AddElement_nothrow(const Reference< XInterface>& Element) 2674 { 2675 // am Container horchen 2676 const Reference< XIndexContainer> xContainer(Element, UNO_QUERY); 2677 if (xContainer.is()) 2678 { 2679 const sal_uInt32 nCount = xContainer->getCount(); 2680 Reference< XInterface> xElement; 2681 for (sal_uInt32 i = 0; i < nCount; ++i) 2682 { 2683 xElement.set(xContainer->getByIndex(i),UNO_QUERY); 2684 impl_AddElement_nothrow(xElement); 2685 } 2686 2687 const Reference< XContainer> xCont(Element, UNO_QUERY); 2688 if (xCont.is()) 2689 xCont->addContainerListener(this); 2690 } 2691 2692 const Reference< ::com::sun::star::view::XSelectionSupplier> xSelSupplier(Element, UNO_QUERY); 2693 if (xSelSupplier.is()) 2694 xSelSupplier->addSelectionChangeListener(this); 2695 } 2696 2697 //------------------------------------------------------------------------------ 2698 void FmXFormShell::RemoveElement(const Reference< XInterface>& Element) 2699 { 2700 if ( impl_checkDisposed() ) 2701 return; 2702 impl_RemoveElement_nothrow(Element); 2703 } 2704 //------------------------------------------------------------------------------ 2705 void FmXFormShell::impl_RemoveElement_nothrow(const Reference< XInterface>& Element) 2706 { 2707 const Reference< ::com::sun::star::view::XSelectionSupplier> xSelSupplier(Element, UNO_QUERY); 2708 if (xSelSupplier.is()) 2709 xSelSupplier->removeSelectionChangeListener(this); 2710 2711 // Verbindung zu Kindern aufheben 2712 const Reference< XIndexContainer> xContainer(Element, UNO_QUERY); 2713 if (xContainer.is()) 2714 { 2715 const Reference< XContainer> xCont(Element, UNO_QUERY); 2716 if (xCont.is()) 2717 xCont->removeContainerListener(this); 2718 2719 const sal_uInt32 nCount = xContainer->getCount(); 2720 Reference< XInterface> xElement; 2721 for (sal_uInt32 i = 0; i < nCount; i++) 2722 { 2723 xElement.set(xContainer->getByIndex(i),UNO_QUERY); 2724 impl_RemoveElement_nothrow(xElement); 2725 } 2726 } 2727 2728 InterfaceBag::iterator wasSelectedPos = m_aCurrentSelection.find( Element ); 2729 if ( wasSelectedPos != m_aCurrentSelection.end() ) 2730 m_aCurrentSelection.erase( wasSelectedPos ); 2731 } 2732 2733 //------------------------------------------------------------------------------ 2734 void FmXFormShell::selectionChanged(const EventObject& rEvent) throw(::com::sun::star::uno::RuntimeException) 2735 { 2736 if ( impl_checkDisposed() ) 2737 return; 2738 2739 Reference< XSelectionSupplier > xSupplier( rEvent.Source, UNO_QUERY ); 2740 Reference< XInterface > xSelObj( xSupplier->getSelection(), UNO_QUERY ); 2741 // es wurde eine Selektion weggenommen, dieses kann nur durch die Shell vorgenommen werden 2742 if ( !xSelObj.is() ) 2743 return; 2744 2745 EnableTrackProperties(sal_False); 2746 2747 sal_Bool bMarkChanged = m_pShell->GetFormView()->checkUnMarkAll(rEvent.Source); 2748 Reference< XForm > xNewForm( GetForm( rEvent.Source ) ); 2749 2750 InterfaceBag aNewSelection; 2751 aNewSelection.insert( Reference< XInterface >( xSelObj, UNO_QUERY ) ); 2752 2753 if ( setCurrentSelection( aNewSelection ) && IsPropBrwOpen() ) 2754 ShowSelectionProperties( sal_True ); 2755 2756 EnableTrackProperties(sal_True); 2757 2758 if ( bMarkChanged ) 2759 m_pShell->NotifyMarkListChanged( m_pShell->GetFormView() ); 2760 } 2761 2762 //------------------------------------------------------------------------------ 2763 IMPL_LINK(FmXFormShell, OnTimeOut, void*, /*EMPTYTAG*/) 2764 { 2765 if ( impl_checkDisposed() ) 2766 return 0; 2767 2768 if (m_pShell->IsDesignMode() && m_pShell->GetFormView()) 2769 SetSelection(m_pShell->GetFormView()->GetMarkedObjectList()); 2770 2771 return 0; 2772 } 2773 2774 //------------------------------------------------------------------------ 2775 void FmXFormShell::SetSelectionDelayed() 2776 { 2777 if ( impl_checkDisposed() ) 2778 return; 2779 2780 if (m_pShell->IsDesignMode() && IsTrackPropertiesEnabled() && !m_aMarkTimer.IsActive()) 2781 m_aMarkTimer.Start(); 2782 } 2783 2784 //------------------------------------------------------------------------ 2785 void FmXFormShell::SetSelection(const SdrMarkList& rMarkList) 2786 { 2787 if ( impl_checkDisposed() ) 2788 return; 2789 2790 DetermineSelection(rMarkList); 2791 m_pShell->NotifyMarkListChanged(m_pShell->GetFormView()); 2792 } 2793 2794 //------------------------------------------------------------------------ 2795 void FmXFormShell::DetermineSelection(const SdrMarkList& rMarkList) 2796 { 2797 if ( setCurrentSelectionFromMark( rMarkList ) && IsPropBrwOpen() ) 2798 ShowSelectionProperties( sal_True ); 2799 } 2800 2801 //------------------------------------------------------------------------------ 2802 sal_Bool FmXFormShell::IsPropBrwOpen() const 2803 { 2804 if ( impl_checkDisposed() ) 2805 return sal_False; 2806 2807 return( ( m_pShell->GetViewShell() && m_pShell->GetViewShell()->GetViewFrame() ) ? 2808 m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES) : sal_False ); 2809 } 2810 2811 //------------------------------------------------------------------------------ 2812 class FmXFormShell::SuspendPropertyTracking 2813 { 2814 private: 2815 FmXFormShell& m_rShell; 2816 sal_Bool m_bEnabled; 2817 2818 public: 2819 SuspendPropertyTracking( FmXFormShell& _rShell ) 2820 :m_rShell( _rShell ) 2821 ,m_bEnabled( sal_False ) 2822 { 2823 if ( m_rShell.IsTrackPropertiesEnabled() ) 2824 { 2825 m_rShell.EnableTrackProperties( sal_False ); 2826 m_bEnabled = sal_True; 2827 } 2828 } 2829 2830 ~SuspendPropertyTracking( ) 2831 { 2832 if ( m_bEnabled ) // note that ( sal_False != m_bEnabled ) implies ( NULL != m_pShell ) 2833 m_rShell.EnableTrackProperties( sal_True ); 2834 } 2835 }; 2836 2837 //------------------------------------------------------------------------------ 2838 void FmXFormShell::SetDesignMode(sal_Bool bDesign) 2839 { 2840 if ( impl_checkDisposed() ) 2841 return; 2842 2843 DBG_ASSERT(m_pShell->GetFormView(), "FmXFormShell::SetDesignMode : invalid call (have no shell or no view) !"); 2844 m_bChangingDesignMode = sal_True; 2845 2846 // 67506 - 15.07.99 - FS 2847 // if we're switching off the design mode we have to force the property browser to be closed 2848 // so it can commit it's changes _before_ we load the forms 2849 if (!bDesign) 2850 { 2851 m_bHadPropertyBrowserInDesignMode = m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow(SID_FM_SHOW_PROPERTIES); 2852 if (m_bHadPropertyBrowserInDesignMode) 2853 m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow(SID_FM_SHOW_PROPERTIES); 2854 } 2855 2856 FmFormView* pFormView = m_pShell->GetFormView(); 2857 if (bDesign) 2858 { 2859 // we are currently filtering, so stop filtering 2860 if (m_bFilterMode) 2861 stopFiltering(sal_False); 2862 2863 // an den Objekten meiner MarkList als Listener abmelden 2864 pFormView->GetImpl()->stopMarkListWatching(); 2865 } 2866 else 2867 { 2868 m_aMarkTimer.Stop(); 2869 2870 SuspendPropertyTracking aSuspend( *this ); 2871 pFormView->GetImpl()->saveMarkList( sal_True ); 2872 } 2873 2874 if (bDesign && m_xExternalViewController.is()) 2875 CloseExternalFormViewer(); 2876 2877 pFormView->ChangeDesignMode(bDesign); 2878 2879 // Listener benachrichtigen 2880 FmDesignModeChangedHint aChangedHint( bDesign ); 2881 m_pShell->Broadcast(aChangedHint); 2882 2883 m_pShell->m_bDesignMode = bDesign; 2884 UpdateForms( sal_False ); 2885 2886 m_pTextShell->designModeChanged( m_pShell->m_bDesignMode ); 2887 2888 if (bDesign) 2889 { 2890 SdrMarkList aList; 2891 { 2892 // during changing the mark list, don't track the selected objects in the property browser 2893 SuspendPropertyTracking aSuspend( *this ); 2894 // restore the marks 2895 pFormView->GetImpl()->restoreMarkList( aList ); 2896 } 2897 2898 // synchronize with the restored mark list 2899 if ( aList.GetMarkCount() ) 2900 SetSelection( aList ); 2901 } 2902 else 2903 { 2904 // am Model der View als Listener anmelden (damit ich mitbekomme, wenn jemand waehrend des Alive-Modus 2905 // Controls loescht, die ich eigentlich mit saveMarkList gespeichert habe) (60343) 2906 pFormView->GetImpl()->startMarkListWatching(); 2907 } 2908 2909 m_pShell->UIFeatureChanged(); 2910 2911 // 67506 - 15.07.99 - FS 2912 if (bDesign && m_bHadPropertyBrowserInDesignMode) 2913 { 2914 // The UIFeatureChanged performes an update (a check of the available features) asynchronously. 2915 // So we can't call ShowSelectionProperties directly as the according feature isn't enabled yet. 2916 // That's why we use an asynchron execution on the dispatcher. 2917 // (And that's why this has to be done AFTER the UIFeatureChanged.) 2918 m_pShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON ); 2919 } 2920 m_bChangingDesignMode = sal_False; 2921 } 2922 2923 //------------------------------------------------------------------------------ 2924 Reference< XControl> FmXFormShell::impl_getControl( const Reference< XControlModel >& i_rxModel, const FmFormObj& i_rKnownFormObj ) 2925 { 2926 if ( impl_checkDisposed() ) 2927 return NULL; 2928 2929 Reference< XControl > xControl; 2930 try 2931 { 2932 Reference< XControlContainer> xControlContainer( getControlContainerForView(), UNO_SET_THROW ); 2933 2934 Sequence< Reference< XControl > > seqControls( xControlContainer->getControls() ); 2935 const Reference< XControl >* pControls = seqControls.getArray(); 2936 // ... die ich dann durchsuchen kann 2937 for (sal_Int32 i=0; i<seqControls.getLength(); ++i) 2938 { 2939 xControl.set( pControls[i], UNO_SET_THROW ); 2940 Reference< XControlModel > xCurrentModel( xControl->getModel() ); 2941 if ( xCurrentModel == i_rxModel ) 2942 break; 2943 xControl.clear(); 2944 } 2945 2946 if ( !xControl.is() ) 2947 { 2948 // fallabck (some controls might not have been created, yet, since they were never visible so far) 2949 Reference< XControl > xContainerControl( xControlContainer, UNO_QUERY_THROW ); 2950 const Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerControl->getPeer() ); 2951 ENSURE_OR_THROW( pContainerWindow, "unexpected control container implementation" ); 2952 2953 const SdrView* pSdrView = m_pShell ? m_pShell->GetFormView() : NULL; 2954 ENSURE_OR_THROW( pSdrView, "no current view" ); 2955 2956 xControl.set( i_rKnownFormObj.GetUnoControl( *pSdrView, *pContainerWindow ), UNO_QUERY_THROW ); 2957 } 2958 } 2959 catch( const Exception& ) 2960 { 2961 DBG_UNHANDLED_EXCEPTION(); 2962 } 2963 2964 OSL_ENSURE( xControl.is(), "FmXFormShell::impl_getControl: no control found!" ); 2965 return xControl; 2966 } 2967 2968 //------------------------------------------------------------------------------ 2969 void FmXFormShell::impl_collectFormSearchContexts_nothrow( const Reference< XInterface>& _rxStartingPoint, 2970 const ::rtl::OUString& _rCurrentLevelPrefix, FmFormArray& _out_rForms, ::std::vector< String >& _out_rNames ) 2971 { 2972 try 2973 { 2974 Reference< XIndexAccess> xContainer( _rxStartingPoint, UNO_QUERY ); 2975 if ( !xContainer.is() ) 2976 return; 2977 2978 sal_Int32 nCount( xContainer->getCount() ); 2979 if ( nCount == 0 ) 2980 return; 2981 2982 ::rtl::OUString sCurrentFormName; 2983 ::rtl::OUStringBuffer aNextLevelPrefix; 2984 for ( sal_Int32 i=0; i<nCount; ++i ) 2985 { 2986 // is the current child a form? 2987 Reference< XForm > xCurrentAsForm( xContainer->getByIndex(i), UNO_QUERY ); 2988 if ( !xCurrentAsForm.is() ) 2989 continue; 2990 2991 Reference< XNamed > xNamed( xCurrentAsForm, UNO_QUERY_THROW ); 2992 sCurrentFormName = xNamed->getName(); 2993 2994 // the name of the current form 2995 ::rtl::OUStringBuffer sCompleteCurrentName( sCurrentFormName ); 2996 if ( _rCurrentLevelPrefix.getLength() ) 2997 { 2998 sCompleteCurrentName.appendAscii( " (" ); 2999 sCompleteCurrentName.append ( _rCurrentLevelPrefix ); 3000 sCompleteCurrentName.appendAscii( ")" ); 3001 } 3002 3003 // the prefix for the next level 3004 aNextLevelPrefix = _rCurrentLevelPrefix; 3005 if ( _rCurrentLevelPrefix.getLength() ) 3006 aNextLevelPrefix.append( (sal_Unicode)'/' ); 3007 aNextLevelPrefix.append( sCurrentFormName ); 3008 3009 // remember both the form and it's "display name" 3010 _out_rForms.push_back( xCurrentAsForm ); 3011 _out_rNames.push_back( sCompleteCurrentName.makeStringAndClear() ); 3012 3013 // und absteigen 3014 impl_collectFormSearchContexts_nothrow( xCurrentAsForm, aNextLevelPrefix.makeStringAndClear(), _out_rForms, _out_rNames ); 3015 } 3016 } 3017 catch( const Exception& ) 3018 { 3019 DBG_UNHANDLED_EXCEPTION(); 3020 } 3021 } 3022 3023 //------------------------------------------------------------------------------ 3024 void FmXFormShell::startFiltering() 3025 { 3026 if ( impl_checkDisposed() ) 3027 return; 3028 3029 // setting all forms in filter mode 3030 FmXFormView* pXView = m_pShell->GetFormView()->GetImpl(); 3031 3032 // if the active controller is our external one we have to use the trigger controller 3033 Reference< XControlContainer> xContainer; 3034 if (getActiveController() == m_xExternalViewController) 3035 { 3036 DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::startFiltering : inconsistent : active external controller, but noone triggered this !"); 3037 xContainer = m_xExtViewTriggerController->getContainer(); 3038 } 3039 else 3040 xContainer = getActiveController()->getContainer(); 3041 3042 PFormViewPageWindowAdapter pAdapter = pXView->findWindow( xContainer ); 3043 if ( pAdapter.is() ) 3044 { 3045 const ::std::vector< Reference< runtime::XFormController> >& rControllerList = pAdapter->GetList(); 3046 for ( ::std::vector< Reference< runtime::XFormController> >::const_iterator j = rControllerList.begin(); 3047 j != rControllerList.end(); 3048 ++j 3049 ) 3050 { 3051 Reference< XModeSelector> xModeSelector(*j, UNO_QUERY); 3052 if (xModeSelector.is()) 3053 xModeSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterMode" ) ) ); 3054 } 3055 } 3056 3057 m_bFilterMode = sal_True; 3058 3059 m_pShell->UIFeatureChanged(); 3060 SfxViewFrame* pViewFrame = m_pShell->GetViewShell()->GetViewFrame(); 3061 pViewFrame->GetBindings().InvalidateShell( *m_pShell ); 3062 3063 if ( pViewFrame->KnowsChildWindow( SID_FM_FILTER_NAVIGATOR ) 3064 && !pViewFrame->HasChildWindow( SID_FM_FILTER_NAVIGATOR ) 3065 ) 3066 { 3067 pViewFrame->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR ); 3068 } 3069 } 3070 3071 //------------------------------------------------------------------------------ 3072 void saveFilter(const Reference< runtime::XFormController >& _rxController) 3073 { 3074 Reference< XPropertySet> xFormAsSet(_rxController->getModel(), UNO_QUERY); 3075 Reference< XPropertySet> xControllerAsSet(_rxController, UNO_QUERY); 3076 Reference< XIndexAccess> xControllerAsIndex(_rxController, UNO_QUERY); 3077 3078 // call the subcontroller 3079 Reference< runtime::XFormController > xController; 3080 for (sal_Int32 i = 0, nCount = xControllerAsIndex->getCount(); i < nCount; ++i) 3081 { 3082 xControllerAsIndex->getByIndex(i) >>= xController; 3083 saveFilter(xController); 3084 } 3085 3086 try 3087 { 3088 3089 xFormAsSet->setPropertyValue(FM_PROP_FILTER, xControllerAsSet->getPropertyValue(FM_PROP_FILTER)); 3090 xFormAsSet->setPropertyValue(FM_PROP_APPLYFILTER, makeAny( (sal_Bool)sal_True ) ); 3091 } 3092 catch (const Exception& ) 3093 { 3094 DBG_UNHANDLED_EXCEPTION(); 3095 } 3096 3097 } 3098 3099 //------------------------------------------------------------------------------ 3100 void FmXFormShell::stopFiltering(sal_Bool bSave) 3101 { 3102 if ( impl_checkDisposed() ) 3103 return; 3104 3105 m_bFilterMode = sal_False; 3106 3107 FmXFormView* pXView = m_pShell->GetFormView()->GetImpl(); 3108 3109 // if the active controller is our external one we have to use the trigger controller 3110 Reference< XControlContainer> xContainer; 3111 if (getActiveController() == m_xExternalViewController) 3112 { 3113 DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::stopFiltering : inconsistent : active external controller, but noone triggered this !"); 3114 xContainer = m_xExtViewTriggerController->getContainer(); 3115 } 3116 else 3117 xContainer = getActiveController()->getContainer(); 3118 3119 PFormViewPageWindowAdapter pAdapter = pXView->findWindow(xContainer); 3120 if ( pAdapter.is() ) 3121 { 3122 const ::std::vector< Reference< runtime::XFormController > >& rControllerList = pAdapter->GetList(); 3123 ::std::vector < ::rtl::OUString > aOriginalFilters; 3124 ::std::vector < sal_Bool > aOriginalApplyFlags; 3125 3126 if (bSave) 3127 { 3128 for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllerList.begin(); 3129 j != rControllerList.end(); ++j) 3130 { 3131 if (bSave) 3132 { // remember the current filter settings in case we're goin to reload the forms below (which may fail) 3133 try 3134 { 3135 Reference< XPropertySet > xFormAsSet((*j)->getModel(), UNO_QUERY); 3136 aOriginalFilters.push_back(::comphelper::getString(xFormAsSet->getPropertyValue(FM_PROP_FILTER))); 3137 aOriginalApplyFlags.push_back(::comphelper::getBOOL(xFormAsSet->getPropertyValue(FM_PROP_APPLYFILTER))); 3138 } 3139 catch(Exception&) 3140 { 3141 DBG_ERROR("FmXFormShell::stopFiltering : could not get the original filter !"); 3142 // put dummies into the arrays so the they have the right size 3143 3144 if (aOriginalFilters.size() == aOriginalApplyFlags.size()) 3145 // the first getPropertyValue failed -> use two dummies 3146 aOriginalFilters.push_back( ::rtl::OUString() ); 3147 aOriginalApplyFlags.push_back( sal_False ); 3148 } 3149 } 3150 saveFilter(*j); 3151 } 3152 } 3153 for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllerList.begin(); 3154 j != rControllerList.end(); ++j) 3155 { 3156 3157 Reference< XModeSelector> xModeSelector(*j, UNO_QUERY); 3158 if (xModeSelector.is()) 3159 xModeSelector->setMode( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DataMode" ) ) ); 3160 } 3161 if (bSave) // execute the filter 3162 { 3163 const ::std::vector< Reference< runtime::XFormController > > & rControllers = pAdapter->GetList(); 3164 for (::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllers.begin(); 3165 j != rControllers.end(); ++j) 3166 { 3167 Reference< XLoadable> xReload((*j)->getModel(), UNO_QUERY); 3168 if (!xReload.is()) 3169 continue; 3170 Reference< XPropertySet > xFormSet(xReload, UNO_QUERY); 3171 3172 try 3173 { 3174 xReload->reload(); 3175 } 3176 catch(Exception&) 3177 { 3178 DBG_ERROR("FmXFormShell::stopFiltering: Exception occured!"); 3179 } 3180 3181 if (!isRowSetAlive(xFormSet)) 3182 { // something went wrong -> restore the original state 3183 ::rtl::OUString sOriginalFilter = aOriginalFilters[ j - rControllers.begin() ]; 3184 sal_Bool bOriginalApplyFlag = aOriginalApplyFlags[ j - rControllers.begin() ]; 3185 try 3186 { 3187 xFormSet->setPropertyValue(FM_PROP_FILTER, makeAny(sOriginalFilter)); 3188 xFormSet->setPropertyValue(FM_PROP_APPLYFILTER, makeAny(bOriginalApplyFlag)); 3189 xReload->reload(); 3190 } 3191 catch(const Exception&) 3192 { 3193 DBG_UNHANDLED_EXCEPTION(); 3194 } 3195 } 3196 } 3197 } 3198 } 3199 3200 m_pShell->UIFeatureChanged(); 3201 m_pShell->GetViewShell()->GetViewFrame()->GetBindings().InvalidateShell(*m_pShell); 3202 } 3203 3204 //------------------------------------------------------------------------------ 3205 void clearFilter(const Reference< runtime::XFormController >& _rxController) 3206 { 3207 Reference< XPropertySet> xControllerAsSet(_rxController, UNO_QUERY); 3208 Reference< XIndexAccess> xControllerAsIndex(_rxController, UNO_QUERY); 3209 3210 // call the subcontroller 3211 Reference< runtime::XFormController > xController; 3212 for (sal_Int32 i = 0, nCount = xControllerAsIndex->getCount(); 3213 i < nCount; i++) 3214 { 3215 xControllerAsIndex->getByIndex(i) >>= xController; 3216 clearFilter(xController); 3217 } 3218 3219 // clear the filter 3220 Reference< XIndexContainer> xContainer; 3221 xControllerAsSet->getPropertyValue(FM_PROP_FILTERSUPPLIER) >>= xContainer; 3222 if (xContainer.is()) 3223 { 3224 // clear the current filter 3225 Sequence< PropertyValue> aCondition; 3226 3227 // as there is always an empty row, if we have a filter: 3228 if (xContainer->getCount()) 3229 { 3230 xControllerAsSet->setPropertyValue(FM_PROP_CURRENTFILTER, makeAny(sal_Int32(xContainer->getCount() - 1))); 3231 while (xContainer->getCount() > 1) 3232 xContainer->removeByIndex(0); 3233 } 3234 } 3235 } 3236 3237 //------------------------------------------------------------------------------ 3238 void FmXFormShell::clearFilter() 3239 { 3240 if ( impl_checkDisposed() ) 3241 return; 3242 3243 FmXFormView* pXView = m_pShell->GetFormView()->GetImpl(); 3244 3245 // if the active controller is our external one we have to use the trigger controller 3246 Reference< XControlContainer> xContainer; 3247 if (getActiveController() == m_xExternalViewController) 3248 { 3249 DBG_ASSERT(m_xExtViewTriggerController.is(), "FmXFormShell::clearFilter : inconsistent : active external controller, but noone triggered this !"); 3250 xContainer = m_xExtViewTriggerController->getContainer(); 3251 } 3252 else 3253 xContainer = getActiveController()->getContainer(); 3254 3255 PFormViewPageWindowAdapter pAdapter = pXView->findWindow(xContainer); 3256 if ( pAdapter.is() ) 3257 { 3258 const ::std::vector< Reference< runtime::XFormController > > & rControllerList = pAdapter->GetList(); 3259 for ( ::std::vector< Reference< runtime::XFormController > > ::const_iterator j = rControllerList.begin(); 3260 j != rControllerList.end(); 3261 ++j 3262 ) 3263 { 3264 ::clearFilter(*j); 3265 } 3266 } 3267 } 3268 3269 //------------------------------------------------------------------------------ 3270 void FmXFormShell::CreateExternalView() 3271 { 3272 if ( impl_checkDisposed() ) 3273 return; 3274 3275 DBG_ASSERT(m_xAttachedFrame.is(), "FmXFormShell::CreateExternalView : no frame !"); 3276 3277 // the frame the external view is displayed in 3278 sal_Bool bAlreadyExistent = m_xExternalViewController.is(); 3279 Reference< ::com::sun::star::frame::XFrame> xExternalViewFrame; 3280 ::rtl::OUString sFrameName = ::rtl::OUString::createFromAscii("_beamer"); 3281 sal_Int32 nSearchFlags = ::com::sun::star::frame::FrameSearchFlag::CHILDREN | ::com::sun::star::frame::FrameSearchFlag::CREATE; 3282 3283 Reference< runtime::XFormController > xCurrentNavController( getNavController()); 3284 // the creation of the "partwindow" may cause a deactivate of the document which will result in our nav controller to be set to NULL 3285 3286 // _first_ check if we have any valid fields we can use for the grid view 3287 // FS - 21.10.99 - 69219 3288 { 3289 FmXBoundFormFieldIterator aModelIterator(xCurrentNavController->getModel()); 3290 Reference< XPropertySet> xCurrentModelSet; 3291 sal_Bool bHaveUsableControls = sal_False; 3292 while ((xCurrentModelSet = Reference< XPropertySet>(aModelIterator.Next(), UNO_QUERY)).is()) 3293 { 3294 // the FmXBoundFormFieldIterator only supplies controls with a valid control source 3295 // so we just have to check the field type 3296 sal_Int16 nClassId = ::comphelper::getINT16(xCurrentModelSet->getPropertyValue(FM_PROP_CLASSID)); 3297 switch (nClassId) 3298 { 3299 case FormComponentType::IMAGECONTROL: 3300 case FormComponentType::CONTROL: 3301 continue; 3302 } 3303 bHaveUsableControls = sal_True; 3304 break; 3305 } 3306 3307 if (!bHaveUsableControls) 3308 { 3309 ErrorBox(NULL, WB_OK, SVX_RESSTR(RID_STR_NOCONTROLS_FOR_EXTERNALDISPLAY)).Execute(); 3310 return; 3311 } 3312 } 3313 3314 // load the component for external form views 3315 if (!bAlreadyExistent) 3316 { 3317 URL aWantToDispatch; 3318 aWantToDispatch.Complete = FMURL_COMPONENT_FORMGRIDVIEW; 3319 3320 Reference< ::com::sun::star::frame::XDispatchProvider> xProv(m_xAttachedFrame, UNO_QUERY); 3321 Reference< ::com::sun::star::frame::XDispatch> xDisp; 3322 if (xProv.is()) 3323 xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, nSearchFlags); 3324 if (xDisp.is()) 3325 { 3326 xDisp->dispatch(aWantToDispatch, Sequence< PropertyValue>()); 3327 } 3328 3329 // with this the component should be loaded, now search the frame where it resides in 3330 xExternalViewFrame = m_xAttachedFrame->findFrame(sFrameName, ::com::sun::star::frame::FrameSearchFlag::CHILDREN); 3331 if (xExternalViewFrame.is()) 3332 { 3333 m_xExternalViewController = xExternalViewFrame->getController(); 3334 Reference< ::com::sun::star::lang::XComponent> xComp(m_xExternalViewController, UNO_QUERY); 3335 if (xComp.is()) 3336 xComp->addEventListener((XEventListener*)(XPropertyChangeListener*)this); 3337 } 3338 } 3339 else 3340 { 3341 xExternalViewFrame = m_xExternalViewController->getFrame(); 3342 Reference< ::com::sun::star::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY); 3343 3344 // if we display the active form we interpret the slot as "remove it" 3345 Reference< XForm> xCurrentModel(xCurrentNavController->getModel(), UNO_QUERY); 3346 if ((xCurrentModel == m_xExternalDisplayedForm) || (getInternalForm(xCurrentModel) == m_xExternalDisplayedForm)) 3347 { 3348 if ( m_xExternalViewController == getActiveController() ) 3349 { 3350 Reference< runtime::XFormController > xAsFormController( m_xExternalViewController, UNO_QUERY ); 3351 ControllerFeatures aHelper( ::comphelper::getProcessServiceFactory(), xAsFormController, NULL ); 3352 aHelper->commitCurrentControl(); 3353 } 3354 3355 Reference< runtime::XFormController > xNewController(m_xExtViewTriggerController); 3356 CloseExternalFormViewer(); 3357 setActiveController(xNewController); 3358 return; 3359 } 3360 3361 URL aClearURL; 3362 aClearURL.Complete = FMURL_GRIDVIEW_CLEARVIEW; 3363 3364 Reference< ::com::sun::star::frame::XDispatch> xClear( xCommLink->queryDispatch(aClearURL, ::rtl::OUString::createFromAscii(""), 0)); 3365 if (xClear.is()) 3366 xClear->dispatch(aClearURL, Sequence< PropertyValue>()); 3367 } 3368 3369 // TODO: We need an interceptor at the xSupplier, which forwards all queryDispatch requests to the FormController 3370 // instance for which this "external view" was triggered 3371 3372 // get the dispatch interface of the frame so we can communicate (interceptable) with the controller 3373 Reference< ::com::sun::star::frame::XDispatchProvider> xCommLink(xExternalViewFrame, UNO_QUERY); 3374 3375 if (m_xExternalViewController.is()) 3376 { 3377 DBG_ASSERT(xCommLink.is(), "FmXFormShell::CreateExternalView : the component doesn't have the necessary interfaces !"); 3378 // collect the dispatchers we will need 3379 URL aAddColumnURL; 3380 aAddColumnURL.Complete = FMURL_GRIDVIEW_ADDCOLUMN; 3381 Reference< ::com::sun::star::frame::XDispatch> xAddColumnDispatch( xCommLink->queryDispatch(aAddColumnURL, ::rtl::OUString::createFromAscii(""), 0)); 3382 URL aAttachURL; 3383 aAttachURL.Complete = FMURL_GRIDVIEW_ATTACHTOFORM; 3384 Reference< ::com::sun::star::frame::XDispatch> xAttachDispatch( xCommLink->queryDispatch(aAttachURL, ::rtl::OUString::createFromAscii(""), 0)); 3385 3386 if (xAddColumnDispatch.is() && xAttachDispatch.is()) 3387 { 3388 DBG_ASSERT(xCurrentNavController.is(), "FmXFormShell::CreateExternalView : invalid call : have no nav controller !"); 3389 // first : dispatch the descriptions for the columns to add 3390 Sequence< Reference< XControl> > aCurrentControls(xCurrentNavController->getControls()); 3391 3392 sal_Int16 nAddedColumns = 0; 3393 3394 // for radio buttons we need some special structures 3395 DECLARE_STL_USTRINGACCESS_MAP(Sequence< ::rtl::OUString>, MapUString2UstringSeq); 3396 DECLARE_STL_ITERATORS(MapUString2UstringSeq); 3397 DECLARE_STL_USTRINGACCESS_MAP(::rtl::OUString, FmMapUString2UString); 3398 DECLARE_STL_USTRINGACCESS_MAP(sal_Int16, FmMapUString2Int16); 3399 DECLARE_STL_ITERATORS(FmMapUString2Int16); 3400 3401 MapUString2UstringSeq aRadioValueLists; 3402 MapUString2UstringSeq aRadioListSources; 3403 FmMapUString2UString aRadioControlSources; 3404 FmMapUString2Int16 aRadioPositions; 3405 3406 FmXBoundFormFieldIterator aModelIterator(xCurrentNavController->getModel()); 3407 Reference< XPropertySet> xCurrentModelSet; 3408 Any aCurrentBoundField; 3409 ::rtl::OUString sColumnType,aGroupName,sControlSource; 3410 Sequence< Property> aProps; 3411 Reference< XPropertySet> xCurrentBoundField; 3412 while ((xCurrentModelSet = Reference< XPropertySet>(aModelIterator.Next(), UNO_QUERY)).is()) 3413 { 3414 xCurrentModelSet->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xCurrentBoundField; 3415 OSL_ENSURE(xCurrentModelSet.is(),"xCurrentModelSet is null!"); 3416 // create a description of the column to be created 3417 // first : determine it's type 3418 3419 sal_Int16 nClassId = ::comphelper::getINT16(xCurrentModelSet->getPropertyValue(FM_PROP_CLASSID)); 3420 switch (nClassId) 3421 { 3422 case FormComponentType::RADIOBUTTON: 3423 { 3424 // get the label of the button (this is the access key for our structures) 3425 aGroupName = getLabelName(xCurrentModelSet); 3426 3427 // add the reference value of the radio button to the list source sequence 3428 Sequence< ::rtl::OUString>& aThisGroupLabels = aRadioListSources[aGroupName]; 3429 sal_Int32 nNewSizeL = aThisGroupLabels.getLength() + 1; 3430 aThisGroupLabels.realloc(nNewSizeL); 3431 aThisGroupLabels.getArray()[nNewSizeL - 1] = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_REFVALUE)); 3432 3433 // add the label to the value list sequence 3434 Sequence< ::rtl::OUString>& aThisGroupControlSources = aRadioValueLists[aGroupName]; 3435 sal_Int32 nNewSizeC = aThisGroupControlSources.getLength() + 1; 3436 aThisGroupControlSources.realloc(nNewSizeC); 3437 aThisGroupControlSources.getArray()[nNewSizeC - 1] = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_LABEL)); 3438 3439 // remember the controls source of the radio group 3440 sControlSource = ::comphelper::getString(xCurrentModelSet->getPropertyValue(FM_PROP_CONTROLSOURCE)); 3441 if (aRadioControlSources.find(aGroupName) == aRadioControlSources.end()) 3442 aRadioControlSources[aGroupName] = sControlSource; 3443 #ifdef DBG_UTIL 3444 else 3445 DBG_ASSERT(aRadioControlSources[aGroupName] == sControlSource, 3446 "FmXFormShell::CreateExternalView : inconsistent radio buttons detected !"); 3447 // (radio buttons with the same name should have the same control source) 3448 #endif 3449 // remember the position within the columns 3450 if (aRadioPositions.find(aGroupName) == aRadioPositions.end()) 3451 aRadioPositions[aGroupName] = (sal_Int16)nAddedColumns; 3452 3453 // any further handling is done below 3454 } 3455 continue; 3456 3457 case FormComponentType::IMAGECONTROL: 3458 case FormComponentType::CONTROL: 3459 // no grid columns for these types (though they have a control source) 3460 continue; 3461 case FormComponentType::CHECKBOX: 3462 sColumnType = FM_COL_CHECKBOX; break; 3463 case FormComponentType::LISTBOX: 3464 sColumnType = FM_COL_LISTBOX; break; 3465 case FormComponentType::COMBOBOX: 3466 sColumnType = FM_COL_COMBOBOX; break; 3467 case FormComponentType::DATEFIELD: 3468 sColumnType = FM_COL_DATEFIELD; break; 3469 case FormComponentType::TIMEFIELD: 3470 sColumnType = FM_COL_TIMEFIELD; break; 3471 case FormComponentType::NUMERICFIELD: 3472 sColumnType = FM_COL_NUMERICFIELD; break; 3473 case FormComponentType::CURRENCYFIELD: 3474 sColumnType = FM_COL_CURRENCYFIELD; break; 3475 case FormComponentType::PATTERNFIELD: 3476 sColumnType = FM_COL_PATTERNFIELD; break; 3477 3478 case FormComponentType::TEXTFIELD: 3479 { 3480 sColumnType = FM_COL_TEXTFIELD; 3481 // we know at least two different controls which are TextFields : the basic edit field and the formatted 3482 // field. we distinguish them by their service name 3483 Reference< XServiceInfo> xInfo(xCurrentModelSet, UNO_QUERY); 3484 if (xInfo.is()) 3485 { 3486 sal_Int16 nObjectType = getControlTypeByObject(xInfo); 3487 if (OBJ_FM_FORMATTEDFIELD == nObjectType) 3488 sColumnType = FM_COL_FORMATTEDFIELD; 3489 } 3490 } 3491 break; 3492 default: 3493 sColumnType = FM_COL_TEXTFIELD; break; 3494 } 3495 3496 const sal_Int16 nDispatchArgs = 3; 3497 Sequence< PropertyValue> aDispatchArgs(nDispatchArgs); 3498 PropertyValue* pDispatchArgs = aDispatchArgs.getArray(); 3499 3500 // properties describing "meta data" about the column 3501 // the type 3502 pDispatchArgs->Name = FMARG_ADDCOL_COLUMNTYPE; 3503 pDispatchArgs->Value <<= sColumnType; 3504 ++pDispatchArgs; 3505 3506 // the pos : append the col 3507 pDispatchArgs->Name = FMARG_ADDCOL_COLUMNPOS; 3508 pDispatchArgs->Value <<= nAddedColumns; 3509 ++pDispatchArgs; 3510 3511 // the properties to forward to the new column 3512 Sequence< PropertyValue> aColumnProps(1); 3513 PropertyValue* pColumnProps = aColumnProps.getArray(); 3514 3515 // the label 3516 pColumnProps->Name = FM_PROP_LABEL; 3517 pColumnProps->Value <<= getLabelName(xCurrentModelSet); 3518 ++pColumnProps; 3519 3520 // for all other props : transfer them 3521 Reference< XPropertySetInfo> xControlModelInfo( xCurrentModelSet->getPropertySetInfo()); 3522 DBG_ASSERT(xControlModelInfo.is(), "FmXFormShell::CreateExternalView : the control model has no property info ! This will crash !"); 3523 aProps = xControlModelInfo->getProperties(); 3524 const Property* pProps = aProps.getConstArray(); 3525 3526 // realloc the control description sequence 3527 sal_Int32 nExistentDescs = pColumnProps - aColumnProps.getArray(); 3528 aColumnProps.realloc(nExistentDescs + aProps.getLength()); 3529 pColumnProps = aColumnProps.getArray() + nExistentDescs; 3530 3531 for (sal_Int32 i=0; i<aProps.getLength(); ++i, ++pProps) 3532 { 3533 if (pProps->Name.equals(FM_PROP_LABEL)) 3534 // already set 3535 continue; 3536 if (pProps->Name.equals(FM_PROP_DEFAULTCONTROL)) 3537 // allow the column's own "default control" 3538 continue; 3539 if (pProps->Attributes & PropertyAttribute::READONLY) 3540 // assume that properties which are readonly for the control are ro for the column to be created, too 3541 continue; 3542 3543 pColumnProps->Name = pProps->Name; 3544 pColumnProps->Value = xCurrentModelSet->getPropertyValue(pProps->Name); 3545 ++pColumnProps; 3546 } 3547 aColumnProps.realloc(pColumnProps - aColumnProps.getArray()); 3548 3549 // columns props are a dispatch argument 3550 pDispatchArgs->Name = ::rtl::OUString::createFromAscii("ColumnProperties"); // TODO : fmurl.* 3551 pDispatchArgs->Value = makeAny(aColumnProps); 3552 ++pDispatchArgs; 3553 DBG_ASSERT(nDispatchArgs == (pDispatchArgs - aDispatchArgs.getConstArray()), 3554 "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?"); 3555 3556 // dispatch the "add column" 3557 xAddColumnDispatch->dispatch(aAddColumnURL, aDispatchArgs); 3558 ++nAddedColumns; 3559 } 3560 3561 // now for the radio button handling 3562 sal_Int16 nOffset(0); 3563 // properties describing the "direct" column properties 3564 const sal_Int16 nListBoxDescription = 6; 3565 Sequence< PropertyValue> aListBoxDescription(nListBoxDescription); 3566 for ( ConstFmMapUString2UStringIterator aCtrlSource = aRadioControlSources.begin(); 3567 aCtrlSource != aRadioControlSources.end(); 3568 ++aCtrlSource, ++nOffset 3569 ) 3570 { 3571 3572 PropertyValue* pListBoxDescription = aListBoxDescription.getArray(); 3573 // label 3574 pListBoxDescription->Name = FM_PROP_LABEL; 3575 pListBoxDescription->Value <<= (*aCtrlSource).first; 3576 ++pListBoxDescription; 3577 3578 // control source 3579 pListBoxDescription->Name = FM_PROP_CONTROLSOURCE; 3580 pListBoxDescription->Value <<= (*aCtrlSource).second; 3581 ++pListBoxDescription; 3582 3583 // bound column 3584 pListBoxDescription->Name = FM_PROP_BOUNDCOLUMN; 3585 pListBoxDescription->Value <<= (sal_Int16)1; 3586 ++pListBoxDescription; 3587 3588 // content type 3589 pListBoxDescription->Name = FM_PROP_LISTSOURCETYPE; 3590 ListSourceType eType = ListSourceType_VALUELIST; 3591 pListBoxDescription->Value = makeAny(eType); 3592 ++pListBoxDescription; 3593 3594 // list source 3595 MapUString2UstringSeq::const_iterator aCurrentListSource = aRadioListSources.find((*aCtrlSource).first); 3596 DBG_ASSERT(aCurrentListSource != aRadioListSources.end(), 3597 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !"); 3598 pListBoxDescription->Name = FM_PROP_LISTSOURCE; 3599 pListBoxDescription->Value = makeAny((*aCurrentListSource).second); 3600 ++pListBoxDescription; 3601 3602 // value list 3603 MapUString2UstringSeq::const_iterator aCurrentValueList = aRadioValueLists.find((*aCtrlSource).first); 3604 DBG_ASSERT(aCurrentValueList != aRadioValueLists.end(), 3605 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !"); 3606 pListBoxDescription->Name = FM_PROP_STRINGITEMLIST; 3607 pListBoxDescription->Value = makeAny(((*aCurrentValueList).second)); 3608 ++pListBoxDescription; 3609 3610 DBG_ASSERT(nListBoxDescription == (pListBoxDescription - aListBoxDescription.getConstArray()), 3611 "FmXFormShell::CreateExternalView : forgot to adjust nListBoxDescription ?"); 3612 3613 // properties describing the column "meta data" 3614 const sal_Int16 nDispatchArgs = 3; 3615 Sequence< PropertyValue> aDispatchArgs(nDispatchArgs); 3616 PropertyValue* pDispatchArgs = aDispatchArgs.getArray(); 3617 3618 // column type : listbox 3619 pDispatchArgs->Name = FMARG_ADDCOL_COLUMNTYPE; 3620 ::rtl::OUString fColName = FM_COL_LISTBOX; 3621 pDispatchArgs->Value <<= fColName; 3622 // pDispatchArgs->Value <<= (::rtl::OUString)FM_COL_LISTBOX; 3623 ++pDispatchArgs; 3624 3625 // column position 3626 pDispatchArgs->Name = FMARG_ADDCOL_COLUMNPOS; 3627 FmMapUString2Int16::const_iterator aOffset = aRadioPositions.find((*aCtrlSource).first); 3628 DBG_ASSERT(aOffset != aRadioPositions.end(), 3629 "FmXFormShell::CreateExternalView : inconsistent radio descriptions !"); 3630 sal_Int16 nPosition = (*aOffset).second; 3631 nPosition = nPosition + nOffset; 3632 // we alread inserted nOffset additinal columns .... 3633 pDispatchArgs->Value <<= nPosition; 3634 ++pDispatchArgs; 3635 3636 // the 3637 pDispatchArgs->Name = ::rtl::OUString::createFromAscii("ColumnProperties"); // TODO : fmurl.* 3638 pDispatchArgs->Value = makeAny(aListBoxDescription); 3639 ++pDispatchArgs; 3640 DBG_ASSERT(nDispatchArgs == (pDispatchArgs - aDispatchArgs.getConstArray()), 3641 "FmXFormShell::CreateExternalView : forgot to adjust nDispatchArgs ?"); 3642 3643 // dispatch the "add column" 3644 xAddColumnDispatch->dispatch(aAddColumnURL, aDispatchArgs); 3645 ++nAddedColumns; 3646 } 3647 3648 3649 DBG_ASSERT(nAddedColumns > 0, "FmXFormShell::CreateExternalView : no controls (inconsistent) !"); 3650 // we should have checked if we have any usable controls (see above). 3651 3652 // "load" the "form" of the external view 3653 PropertyValue aArg; 3654 aArg.Name = FMARG_ATTACHTO_MASTERFORM; 3655 Reference< XResultSet> xForm(xCurrentNavController->getModel(), UNO_QUERY); 3656 aArg.Value <<= xForm; 3657 3658 m_xExternalDisplayedForm = Reference< XResultSet>(xForm, UNO_QUERY); 3659 // do this before dispatching the "attach" command, as the atach may result in a call to our queryDispatch (for the FormSlots) 3660 // whichs needs the m_xExternalDisplayedForm 3661 3662 xAttachDispatch->dispatch(aAttachURL, Sequence< PropertyValue>(&aArg, 1)); 3663 3664 m_xExtViewTriggerController = xCurrentNavController; 3665 3666 // we want to know modifications done in the external view 3667 // if the external controller is a XFormController we can use all our default handlings for it 3668 Reference< runtime::XFormController > xFormController( m_xExternalViewController, UNO_QUERY ); 3669 OSL_ENSURE( xFormController.is(), "FmXFormShell::CreateExternalView:: invalid external view controller!" ); 3670 if (xFormController.is()) 3671 xFormController->addActivateListener((XFormControllerListener*)this); 3672 } 3673 } 3674 #ifdef DBG_UTIL 3675 else 3676 { 3677 DBG_ERROR("FmXFormShell::CreateExternalView : could not create the external form view !"); 3678 } 3679 #endif 3680 InvalidateSlot( SID_FM_VIEW_AS_GRID, sal_False ); 3681 } 3682 3683 //------------------------------------------------------------------------ 3684 void FmXFormShell::implAdjustConfigCache() 3685 { 3686 // get (cache) the wizard usage flag 3687 Sequence< ::rtl::OUString > aNames(1); 3688 aNames[0] = ::rtl::OUString::createFromAscii("FormControlPilotsEnabled"); 3689 Sequence< Any > aFlags = GetProperties(aNames); 3690 if (1 == aFlags.getLength()) 3691 m_bUseWizards = ::cppu::any2bool(aFlags[0]); 3692 } 3693 3694 //------------------------------------------------------------------------ 3695 void FmXFormShell::Notify( const com::sun::star::uno::Sequence< rtl::OUString >& _rPropertyNames) 3696 { 3697 if ( impl_checkDisposed() ) 3698 return; 3699 3700 const ::rtl::OUString* pSearch = _rPropertyNames.getConstArray(); 3701 const ::rtl::OUString* pSearchTil = pSearch + _rPropertyNames.getLength(); 3702 for (;pSearch < pSearchTil; ++pSearch) 3703 if (0 == pSearch->compareToAscii("FormControlPilotsEnabled")) 3704 { 3705 implAdjustConfigCache(); 3706 InvalidateSlot( SID_FM_USE_WIZARDS, sal_True ); 3707 } 3708 } 3709 3710 void FmXFormShell::Commit() 3711 { 3712 } 3713 3714 //------------------------------------------------------------------------ 3715 void FmXFormShell::SetWizardUsing(sal_Bool _bUseThem) 3716 { 3717 m_bUseWizards = _bUseThem; 3718 3719 Sequence< ::rtl::OUString > aNames(1); 3720 aNames[0] = ::rtl::OUString::createFromAscii("FormControlPilotsEnabled"); 3721 Sequence< Any > aValues(1); 3722 aValues[0] = ::cppu::bool2any(m_bUseWizards); 3723 PutProperties(aNames, aValues); 3724 } 3725 3726 //------------------------------------------------------------------------ 3727 void FmXFormShell::viewDeactivated( FmFormView& _rCurrentView, sal_Bool _bDeactivateController /* = sal_True */ ) 3728 { 3729 3730 if ( _rCurrentView.GetImpl() && !_rCurrentView.IsDesignMode() ) 3731 { 3732 _rCurrentView.GetImpl()->Deactivate( _bDeactivateController ); 3733 } 3734 3735 // if we have an async load operation pending for the 0-th page for this view, 3736 // we need to cancel this 3737 // 103727 - 2002-09-26 - fs@openoffice.org 3738 FmFormPage* pPage = _rCurrentView.GetCurPage(); 3739 if ( pPage ) 3740 { 3741 // move all events from our queue to a new one, omit the events for the deactivated 3742 // page 3743 ::std::queue< FmLoadAction > aNewEvents; 3744 while ( !m_aLoadingPages.empty() ) 3745 { 3746 FmLoadAction aAction = m_aLoadingPages.front(); 3747 m_aLoadingPages.pop(); 3748 if ( pPage != aAction.pPage ) 3749 { 3750 aNewEvents.push( aAction ); 3751 } 3752 else 3753 { 3754 Application::RemoveUserEvent( aAction.nEventId ); 3755 } 3756 } 3757 m_aLoadingPages = aNewEvents; 3758 } 3759 3760 // remove callbacks at the page 3761 if ( pPage ) 3762 { 3763 pPage->GetImpl().SetFormsCreationHdl( Link() ); 3764 } 3765 UpdateForms( sal_True ); 3766 } 3767 3768 //------------------------------------------------------------------------ 3769 IMPL_LINK( FmXFormShell, OnFirstTimeActivation, void*, /*NOTINTERESTEDIN*/ ) 3770 { 3771 if ( impl_checkDisposed() ) 3772 return 0L; 3773 3774 m_nActivationEvent = 0; 3775 SfxObjectShell* pDocument = m_pShell->GetObjectShell(); 3776 3777 if ( pDocument && !pDocument->HasName() ) 3778 { 3779 if ( isEnhancedForm() ) 3780 { 3781 // show the data navigator 3782 if ( !m_pShell->GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_SHOW_DATANAVIGATOR ) ) 3783 m_pShell->GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_SHOW_DATANAVIGATOR ); 3784 } 3785 } 3786 3787 return 0L; 3788 } 3789 3790 //------------------------------------------------------------------------ 3791 IMPL_LINK( FmXFormShell, OnFormsCreated, FmFormPage*, /*_pPage*/ ) 3792 { 3793 UpdateForms( sal_True ); 3794 return 0L; 3795 } 3796 3797 //------------------------------------------------------------------------ 3798 void FmXFormShell::viewActivated( FmFormView& _rCurrentView, sal_Bool _bSyncAction /* = sal_False */ ) 3799 { 3800 3801 FmFormPage* pPage = _rCurrentView.GetCurPage(); 3802 3803 // activate our view if we are activated ourself 3804 // FS - 30.06.99 - 67308 3805 if ( _rCurrentView.GetImpl() && !_rCurrentView.IsDesignMode() ) 3806 { 3807 // load forms for the page the current view belongs to 3808 if ( pPage ) 3809 { 3810 if ( !pPage->GetImpl().hasEverBeenActivated() ) 3811 loadForms( pPage, FORMS_LOAD | ( _bSyncAction ? FORMS_SYNC : FORMS_ASYNC ) ); 3812 pPage->GetImpl().setHasBeenActivated( ); 3813 } 3814 3815 // first-time initializations for the views 3816 if ( !_rCurrentView.GetImpl()->hasEverBeenActivated( ) ) 3817 { 3818 _rCurrentView.GetImpl()->onFirstViewActivation( PTR_CAST( FmFormModel, _rCurrentView.GetModel() ) ); 3819 _rCurrentView.GetImpl()->setHasBeenActivated( ); 3820 } 3821 3822 // activate the current view 3823 _rCurrentView.GetImpl()->Activate( _bSyncAction ); 3824 } 3825 3826 // set callbacks at the page 3827 if ( pPage ) 3828 { 3829 pPage->GetImpl().SetFormsCreationHdl( LINK( this, FmXFormShell, OnFormsCreated ) ); 3830 } 3831 3832 UpdateForms( sal_True ); 3833 3834 if ( !hasEverBeenActivated() ) 3835 { 3836 m_nActivationEvent = Application::PostUserEvent( LINK( this, FmXFormShell, OnFirstTimeActivation ) ); 3837 setHasBeenActivated(); 3838 } 3839 3840 // find a default "current form", if there is none, yet 3841 // #i88186# / 2008-04-12 / frank.schoenheit@sun.com 3842 impl_defaultCurrentForm_nothrow(); 3843 } 3844 3845 //------------------------------------------------------------------------------ 3846 void FmXFormShell::impl_defaultCurrentForm_nothrow() 3847 { 3848 if ( impl_checkDisposed() ) 3849 return; 3850 3851 if ( m_xCurrentForm.is() ) 3852 // no action required 3853 return; 3854 3855 FmFormView* pFormView = m_pShell->GetFormView(); 3856 FmFormPage* pPage = pFormView ? pFormView->GetCurPage() : NULL; 3857 if ( !pPage ) 3858 return; 3859 3860 try 3861 { 3862 Reference< XIndexAccess > xForms( pPage->GetForms( false ), UNO_QUERY ); 3863 if ( !xForms.is() || !xForms->hasElements() ) 3864 return; 3865 3866 Reference< XForm > xNewCurrentForm( xForms->getByIndex(0), UNO_QUERY_THROW ); 3867 impl_updateCurrentForm( xNewCurrentForm ); 3868 } 3869 catch( const Exception& ) 3870 { 3871 DBG_UNHANDLED_EXCEPTION(); 3872 } 3873 } 3874 3875 //------------------------------------------------------------------------------ 3876 void FmXFormShell::smartControlReset( const Reference< XIndexAccess >& _rxModels ) 3877 { 3878 if (!_rxModels.is()) 3879 { 3880 DBG_ERROR("FmXFormShell::smartControlReset: invalid container!"); 3881 return; 3882 } 3883 3884 static const ::rtl::OUString sClassIdPropertyName = FM_PROP_CLASSID; 3885 static const ::rtl::OUString sBoundFieldPropertyName = FM_PROP_BOUNDFIELD; 3886 sal_Int32 nCount = _rxModels->getCount(); 3887 Reference< XPropertySet > xCurrent; 3888 Reference< XPropertySetInfo > xCurrentInfo; 3889 Reference< XPropertySet > xBoundField; 3890 3891 for (sal_Int32 i=0; i<nCount; ++i) 3892 { 3893 _rxModels->getByIndex(i) >>= xCurrent; 3894 if (xCurrent.is()) 3895 xCurrentInfo = xCurrent->getPropertySetInfo(); 3896 else 3897 xCurrentInfo.clear(); 3898 if (!xCurrentInfo.is()) 3899 continue; 3900 3901 if (xCurrentInfo->hasPropertyByName(sClassIdPropertyName)) 3902 { // it's a control model 3903 3904 // check if this control is bound to a living database field 3905 if (xCurrentInfo->hasPropertyByName(sBoundFieldPropertyName)) 3906 xCurrent->getPropertyValue(sBoundFieldPropertyName) >>= xBoundField; 3907 else 3908 xBoundField.clear(); 3909 3910 // reset only if it's *not* bound 3911 bool bReset = !xBoundField.is(); 3912 3913 // and additionally, check if it has an external value binding 3914 Reference< XBindableValue > xBindable( xCurrent, UNO_QUERY ); 3915 if ( xBindable.is() && xBindable->getValueBinding().is() ) 3916 bReset = false; 3917 3918 if ( bReset ) 3919 { 3920 Reference< XReset > xControlReset( xCurrent, UNO_QUERY ); 3921 if ( xControlReset.is() ) 3922 xControlReset->reset(); 3923 } 3924 } 3925 else 3926 { 3927 Reference< XIndexAccess > xContainer(xCurrent, UNO_QUERY); 3928 if (xContainer.is()) 3929 smartControlReset(xContainer); 3930 } 3931 } 3932 } 3933 3934 //------------------------------------------------------------------------ 3935 IMPL_LINK( FmXFormShell, OnLoadForms, FmFormPage*, /*_pPage*/ ) 3936 { 3937 FmLoadAction aAction = m_aLoadingPages.front(); 3938 m_aLoadingPages.pop(); 3939 3940 loadForms( aAction.pPage, aAction.nFlags & ~FORMS_ASYNC ); 3941 return 0L; 3942 } 3943 3944 //------------------------------------------------------------------------------ 3945 namespace 3946 { 3947 sal_Bool lcl_isLoadable( const Reference< XInterface >& _rxLoadable ) 3948 { 3949 // determines whether a form should be loaded or not 3950 // if there is no datasource or connection there is no reason to load a form 3951 Reference< XPropertySet > xSet( _rxLoadable, UNO_QUERY ); 3952 if ( !xSet.is() ) 3953 return sal_False; 3954 try 3955 { 3956 Reference< XConnection > xConn; 3957 if ( OStaticDataAccessTools().isEmbeddedInDatabase( _rxLoadable.get(), xConn ) ) 3958 return sal_True; 3959 3960 // is there already a active connection 3961 xSet->getPropertyValue(FM_PROP_ACTIVE_CONNECTION) >>= xConn; 3962 if ( xConn.is() ) 3963 return sal_True; 3964 3965 ::rtl::OUString sPropertyValue; 3966 OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DATASOURCE ) >>= sPropertyValue ); 3967 if ( sPropertyValue.getLength() ) 3968 return sal_True; 3969 3970 OSL_VERIFY( xSet->getPropertyValue( FM_PROP_URL ) >>= sPropertyValue ); 3971 if ( sPropertyValue.getLength() ) 3972 return sal_True; 3973 } 3974 catch(const Exception&) 3975 { 3976 DBG_UNHANDLED_EXCEPTION(); 3977 } 3978 return sal_False; 3979 } 3980 } 3981 3982 //------------------------------------------------------------------------ 3983 void FmXFormShell::loadForms( FmFormPage* _pPage, const sal_uInt16 _nBehaviour /* FORMS_LOAD | FORMS_SYNC */ ) 3984 { 3985 DBG_ASSERT( ( _nBehaviour & ( FORMS_ASYNC | FORMS_UNLOAD ) ) != ( FORMS_ASYNC | FORMS_UNLOAD ), 3986 "FmXFormShell::loadForms: async loading not supported - this will heavily fail!" ); 3987 3988 if ( _nBehaviour & FORMS_ASYNC ) 3989 { 3990 m_aLoadingPages.push( FmLoadAction( 3991 _pPage, 3992 _nBehaviour, 3993 Application::PostUserEvent( LINK( this, FmXFormShell, OnLoadForms ), _pPage ) 3994 ) ); 3995 return; 3996 } 3997 3998 DBG_ASSERT( _pPage, "FmXFormShell::loadForms: invalid page!" ); 3999 if ( _pPage ) 4000 { 4001 // lock the undo env so the forms can change non-transient properties while loading 4002 // (without this my doc's modified flag would be set) 4003 FmFormModel* pModel = PTR_CAST( FmFormModel, _pPage->GetModel() ); 4004 DBG_ASSERT( pModel, "FmXFormShell::loadForms: invalid model!" ); 4005 if ( pModel ) 4006 pModel->GetUndoEnv().Lock(); 4007 4008 // load all forms 4009 Reference< XIndexAccess > xForms; 4010 xForms = xForms.query( _pPage->GetForms( false ) ); 4011 4012 if ( xForms.is() ) 4013 { 4014 Reference< XLoadable > xForm; 4015 sal_Bool bFormWasLoaded = sal_False; 4016 for ( sal_Int32 j = 0, nCount = xForms->getCount(); j < nCount; ++j ) 4017 { 4018 xForms->getByIndex( j ) >>= xForm; 4019 bFormWasLoaded = sal_False; 4020 // a database form must be loaded for 4021 try 4022 { 4023 if ( 0 == ( _nBehaviour & FORMS_UNLOAD ) ) 4024 { 4025 if ( lcl_isLoadable( xForm ) && !xForm->isLoaded() ) 4026 xForm->load(); 4027 } 4028 else 4029 { 4030 if ( xForm->isLoaded() ) 4031 { 4032 bFormWasLoaded = sal_True; 4033 xForm->unload(); 4034 } 4035 } 4036 } 4037 catch( const Exception& ) 4038 { 4039 DBG_UNHANDLED_EXCEPTION(); 4040 } 4041 4042 // reset the form if it was loaded 4043 if ( bFormWasLoaded ) 4044 { 4045 Reference< XIndexAccess > xContainer( xForm, UNO_QUERY ); 4046 DBG_ASSERT( xContainer.is(), "FmXFormShell::loadForms: the form is no container!" ); 4047 if ( xContainer.is() ) 4048 smartControlReset( xContainer ); 4049 } 4050 } 4051 } 4052 4053 if ( pModel ) 4054 // unlock the environment 4055 pModel->GetUndoEnv().UnLock(); 4056 } 4057 } 4058 4059 //------------------------------------------------------------------------ 4060 void FmXFormShell::ExecuteTextAttribute( SfxRequest& _rReq ) 4061 { 4062 m_pTextShell->ExecuteTextAttribute( _rReq ); 4063 } 4064 4065 //------------------------------------------------------------------------ 4066 void FmXFormShell::GetTextAttributeState( SfxItemSet& _rSet ) 4067 { 4068 m_pTextShell->GetTextAttributeState( _rSet ); 4069 } 4070 4071 //------------------------------------------------------------------------ 4072 bool FmXFormShell::IsActiveControl( bool _bCountRichTextOnly ) const 4073 { 4074 return m_pTextShell->IsActiveControl( _bCountRichTextOnly ); 4075 } 4076 4077 //------------------------------------------------------------------------ 4078 void FmXFormShell::ForgetActiveControl() 4079 { 4080 m_pTextShell->ForgetActiveControl(); 4081 } 4082 4083 //------------------------------------------------------------------------ 4084 void FmXFormShell::SetControlActivationHandler( const Link& _rHdl ) 4085 { 4086 m_pTextShell->SetControlActivationHandler( _rHdl ); 4087 } 4088 //------------------------------------------------------------------------ 4089 void FmXFormShell::handleShowPropertiesRequest() 4090 { 4091 if ( onlyControlsAreMarked() ) 4092 ShowSelectionProperties( sal_True ); 4093 } 4094 4095 //------------------------------------------------------------------------ 4096 void FmXFormShell::handleMouseButtonDown( const SdrViewEvent& _rViewEvent ) 4097 { 4098 // catch simple double clicks 4099 if ( ( _rViewEvent.nMouseClicks == 2 ) && ( _rViewEvent.nMouseCode == MOUSE_LEFT ) ) 4100 { 4101 if ( _rViewEvent.eHit == SDRHIT_MARKEDOBJECT ) 4102 { 4103 if ( onlyControlsAreMarked() ) 4104 ShowSelectionProperties( sal_True ); 4105 } 4106 } 4107 } 4108 4109 //------------------------------------------------------------------------------ 4110 bool FmXFormShell::HasControlFocus() const 4111 { 4112 bool bHasControlFocus = false; 4113 4114 try 4115 { 4116 Reference< XFormController > xController( getActiveController() ); 4117 Reference< XControl > xCurrentControl; 4118 if ( xController.is() ) 4119 xCurrentControl.set( xController->getCurrentControl() ); 4120 if ( xCurrentControl.is() ) 4121 { 4122 Reference< XWindow2 > xPeerWindow( xCurrentControl->getPeer(), UNO_QUERY_THROW ); 4123 bHasControlFocus = xPeerWindow->hasFocus(); 4124 } 4125 } 4126 catch( const Exception& ) 4127 { 4128 DBG_UNHANDLED_EXCEPTION(); 4129 } 4130 4131 return bHasControlFocus; 4132 } 4133 4134 //============================================================================== 4135 //============================================================================== 4136 SearchableControlIterator::SearchableControlIterator(Reference< XInterface> xStartingPoint) 4137 :IndexAccessIterator(xStartingPoint) 4138 { 4139 } 4140 4141 //------------------------------------------------------------------------------ 4142 sal_Bool SearchableControlIterator::ShouldHandleElement(const Reference< XInterface>& xElement) 4143 { 4144 // wenn das Ding eine ControlSource und einen BoundField-Property hat 4145 Reference< XPropertySet> xProperties(xElement, UNO_QUERY); 4146 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xProperties) && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD, xProperties)) 4147 { 4148 // und das BoundField gueltig ist 4149 Reference< XPropertySet> xField; 4150 xProperties->getPropertyValue(FM_PROP_BOUNDFIELD) >>= xField; 4151 if (xField.is()) 4152 { 4153 // nehmen wir's 4154 m_sCurrentValue = ::comphelper::getString(xProperties->getPropertyValue(FM_PROP_CONTROLSOURCE)); 4155 return sal_True; 4156 } 4157 } 4158 4159 // wenn es ein Grid-Control ist 4160 if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties)) 4161 { 4162 Any aClassId( xProperties->getPropertyValue(FM_PROP_CLASSID) ); 4163 if (::comphelper::getINT16(aClassId) == FormComponentType::GRIDCONTROL) 4164 { 4165 m_sCurrentValue = ::rtl::OUString(); 4166 return sal_True; 4167 } 4168 } 4169 4170 return sal_False; 4171 } 4172 4173 //------------------------------------------------------------------------------ 4174 sal_Bool SearchableControlIterator::ShouldStepInto(const Reference< XInterface>& /*xContainer*/) const 4175 { 4176 return sal_True; 4177 } 4178 4179 //============================================================================== 4180 //============================================================================== 4181 4182 SV_IMPL_PTRARR(StatusForwarderArray, SfxStatusForwarder*) 4183 4184 SFX_IMPL_MENU_CONTROL(ControlConversionMenuController, SfxBoolItem); 4185 4186 //------------------------------------------------------------------------------ 4187 ControlConversionMenuController::ControlConversionMenuController( sal_uInt16 _nId, Menu& _rMenu, SfxBindings& _rBindings ) 4188 :SfxMenuControl( _nId, _rBindings ) 4189 ,m_pMainMenu( &_rMenu ) 4190 ,m_pConversionMenu( NULL ) 4191 { 4192 if ( _nId == SID_FM_CHANGECONTROLTYPE ) 4193 { 4194 m_pConversionMenu = FmXFormShell::GetConversionMenu(); 4195 _rMenu.SetPopupMenu( _nId, m_pConversionMenu ); 4196 4197 for (sal_Int16 i=0; i<m_pConversionMenu->GetItemCount(); ++i) 4198 { 4199 _rBindings.Invalidate(m_pConversionMenu->GetItemId(i)); 4200 SfxStatusForwarder* pForwarder = new SfxStatusForwarder(m_pConversionMenu->GetItemId(i), *this); 4201 m_aStatusForwarders.C40_INSERT(SfxStatusForwarder, pForwarder, m_aStatusForwarders.Count()); 4202 } 4203 } 4204 } 4205 4206 //------------------------------------------------------------------------------ 4207 ControlConversionMenuController::~ControlConversionMenuController() 4208 { 4209 m_pMainMenu->SetPopupMenu(SID_FM_CHANGECONTROLTYPE, NULL); 4210 delete m_pConversionMenu; 4211 } 4212 4213 //------------------------------------------------------------------------------ 4214 void ControlConversionMenuController::StateChanged(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState) 4215 { 4216 if (nSID == GetId()) 4217 SfxMenuControl::StateChanged(nSID, eState, pState); 4218 else if (FmXFormShell::isControlConversionSlot(nSID)) 4219 { 4220 if ((m_pConversionMenu->GetItemPos(nSID) != MENU_ITEM_NOTFOUND) && (eState == SFX_ITEM_DISABLED)) 4221 { 4222 m_pConversionMenu->RemoveItem(m_pConversionMenu->GetItemPos(nSID)); 4223 } 4224 else if ((m_pConversionMenu->GetItemPos(nSID) == MENU_ITEM_NOTFOUND) && (eState != SFX_ITEM_DISABLED)) 4225 { 4226 // We can't simply re-insert the item because we have a clear order for all the our items. 4227 // So first we have to determine the position of the item to insert. 4228 PopupMenu* pSource = FmXFormShell::GetConversionMenu(); 4229 sal_uInt16 nSourcePos = pSource->GetItemPos(nSID); 4230 DBG_ASSERT(nSourcePos != MENU_ITEM_NOTFOUND, "ControlConversionMenuController::StateChanged : FmXFormShell supplied an invalid menu !"); 4231 sal_uInt16 nPrevInSource = nSourcePos; 4232 sal_uInt16 nPrevInConversion = MENU_ITEM_NOTFOUND; 4233 while (nPrevInSource>0) 4234 { 4235 sal_Int16 nPrevId = pSource->GetItemId(--nPrevInSource); 4236 4237 // do we have the source's predecessor in our conversion menu, too ? 4238 nPrevInConversion = m_pConversionMenu->GetItemPos(nPrevId); 4239 if (nPrevInConversion != MENU_ITEM_NOTFOUND) 4240 break; 4241 } 4242 if (MENU_ITEM_NOTFOUND == nPrevInConversion) 4243 // none of the items which precede the nSID-slot in the source menu are present in our conversion menu 4244 nPrevInConversion = sal::static_int_cast< sal_uInt16 >(-1); // put the item at the first position 4245 m_pConversionMenu->InsertItem(nSID, pSource->GetItemText(nSID), pSource->GetItemBits(nSID), ++nPrevInConversion); 4246 m_pConversionMenu->SetItemImage(nSID, pSource->GetItemImage(nSID)); 4247 m_pConversionMenu->SetHelpId(nSID, pSource->GetHelpId(nSID)); 4248 4249 delete pSource; 4250 } 4251 m_pMainMenu->EnableItem(SID_FM_CHANGECONTROLTYPE, m_pConversionMenu->GetItemCount() > 0); 4252 } 4253 else 4254 { 4255 DBG_ERROR("ControlConversionMenuController::StateChanged : unknown id !"); 4256 } 4257 } 4258 4259 //============================================================================== 4260