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