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