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 #include <svx/dialmgr.hxx> 27 #include <svx/fmshell.hxx> 28 #include <svx/fmmodel.hxx> 29 #include <svx/fmpage.hxx> 30 #include <svx/svdpagv.hxx> 31 #include "svx/svditer.hxx" 32 33 #include "fmhelp.hrc" 34 #include "fmexpl.hrc" 35 #include "fmexpl.hxx" 36 #include "svx/fmresids.hrc" 37 #include "fmshimp.hxx" 38 #include "fmservs.hxx" 39 #include "fmundo.hxx" 40 #include "fmpgeimp.hxx" 41 #include "fmitems.hxx" 42 #include "fmobj.hxx" 43 #include "fmprop.hrc" 44 #include <vcl/wrkwin.hxx> 45 #include <sfx2/viewsh.hxx> 46 #include <sfx2/dispatch.hxx> 47 #include <sfx2/viewfrm.hxx> 48 #include <comphelper/processfactory.hxx> 49 #include <comphelper/property.hxx> 50 #include <com/sun/star/form/FormComponentType.hpp> 51 #include <com/sun/star/sdb/CommandType.hpp> 52 #include <com/sun/star/beans/PropertyAttribute.hpp> 53 #include <com/sun/star/script/XEventAttacherManager.hpp> 54 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> 55 #include <com/sun/star/datatransfer/XTransferable.hpp> 56 #include <svx/sdrpaintwindow.hxx> 57 58 #include <svx/svxdlg.hxx> //CHINA001 59 #include <svx/dialogs.hrc> //CHINA001 60 #include <rtl/logfile.hxx> 61 //............................................................................ 62 namespace svxform 63 { 64 //............................................................................ 65 66 #define DROP_ACTION_TIMER_INITIAL_TICKS 10 67 // solange dauert es, bis das Scrollen anspringt 68 #define DROP_ACTION_TIMER_SCROLL_TICKS 3 69 // in diesen Intervallen wird jeweils eine Zeile gescrollt 70 #define DROP_ACTION_TIMER_TICK_BASE 10 71 // das ist die Basis, mit der beide Angaben multipliziert werden (in ms) 72 73 #define EXPLORER_SYNC_DELAY 200 74 // dieser Betrag an Millisekunden wird gewartet, ehe der Explorer nach einem Select oder Deselect die ::com::sun::star::sdbcx::View synchronisiert 75 76 using namespace ::com::sun::star::uno; 77 using namespace ::com::sun::star::lang; 78 using namespace ::com::sun::star::beans; 79 using namespace ::com::sun::star::form; 80 using namespace ::com::sun::star::awt; 81 using namespace ::com::sun::star::container; 82 using namespace ::com::sun::star::script; 83 using namespace ::com::sun::star::datatransfer; 84 using namespace ::com::sun::star::datatransfer::clipboard; 85 using namespace ::com::sun::star::sdb; 86 87 //======================================================================== 88 // helper 89 //======================================================================== 90 91 typedef ::std::map< Reference< XInterface >, SdrObject*, ::comphelper::OInterfaceCompare< XInterface > > 92 MapModelToShape; 93 typedef MapModelToShape::value_type ModelShapePair; 94 95 //------------------------------------------------------------------------ 96 void collectShapeModelMapping( SdrPage* _pPage, MapModelToShape& _rMapping ) 97 { 98 OSL_ENSURE( _pPage, "collectShapeModelMapping: invalid arg!" ); 99 100 _rMapping.clear(); 101 102 SdrObjListIter aIter( *_pPage ); 103 while ( aIter.IsMore() ) 104 { 105 SdrObject* pSdrObject = aIter.Next(); 106 FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject ); 107 if ( !pFormObject ) 108 continue; 109 110 Reference< XInterface > xNormalizedModel( pFormObject->GetUnoControlModel(), UNO_QUERY ); 111 // note that this is normalized (i.e. queried for XInterface explicitly) 112 113 #ifdef DBG_UTIL 114 ::std::pair< MapModelToShape::iterator, bool > aPos = 115 #endif 116 _rMapping.insert( ModelShapePair( xNormalizedModel, pSdrObject ) ); 117 DBG_ASSERT( aPos.second, "collectShapeModelMapping: model was already existent!" ); 118 // if this asserts, this would mean we have 2 shapes pointing to the same model 119 } 120 } 121 122 //------------------------------------------------------------------------ 123 sal_Bool isModelShapeMarked( FmEntryData* _pEntry, const MapModelToShape& _rModelMap, SdrMarkView* _pView ) 124 { 125 DBG_ASSERT( _pEntry && _pView, "isModelShapeMarked: invalid arguments!" ); 126 if ( !_pEntry || !_pView ) 127 return sal_False; 128 129 DBG_ASSERT( _pEntry->GetElement().get() == Reference< XInterface >( _pEntry->GetElement(), UNO_QUERY ).get(), 130 "isModelShapeMarked: element of the FmEntryData is not normalized!" ); 131 // normalization of the XInterface is a prerequisite for properly finding it in the map 132 133 sal_Bool bIsMarked = sal_False; 134 135 MapModelToShape::const_iterator aPos = _rModelMap.find( _pEntry->GetElement() ); 136 if ( _rModelMap.end() != aPos ) 137 { // there is a shape for this model .... 138 bIsMarked = _pView->IsObjMarked( aPos->second ); 139 if ( !bIsMarked ) 140 { 141 // IsObjMarked does not step down grouped objects, so the sal_False we 142 // have is not really reliable (while a sal_True would have been) 143 // Okay, travel the mark list, and see if there is a group marked, and our shape 144 // is a part of this group 145 sal_uInt32 nMarked = _pView->GetMarkedObjectList().GetMarkCount(); 146 for ( sal_uInt32 i = 0; (i<nMarked ) && !bIsMarked; ++i ) 147 { 148 SdrMark* pMark = _pView->GetMarkedObjectList().GetMark( i ); 149 SdrObject* pObj = pMark ? pMark->GetMarkedSdrObj() : NULL; 150 if ( pObj && pObj->IsGroupObject() ) 151 { // the i-th marked shape is a group shape 152 SdrObjListIter aIter( *pObj ); 153 while ( aIter.IsMore() ) 154 { 155 if ( aIter.Next() == aPos->second ) 156 { 157 bIsMarked = sal_True; 158 break; 159 } 160 } 161 } 162 } 163 } 164 } 165 166 return bIsMarked; 167 } 168 169 //======================================================================== 170 // class NavigatorTree 171 //======================================================================== 172 173 //------------------------------------------------------------------------ 174 NavigatorTree::NavigatorTree( const Reference< XMultiServiceFactory >& _xORB, 175 Window* pParent ) 176 :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL ) // #100258# OJ WB_HSCROLL added 177 ,m_aControlExchange(this) 178 ,m_xORB(_xORB) 179 ,m_pNavModel( NULL ) 180 ,m_pRootEntry(NULL) 181 ,m_pEditEntry(NULL) 182 ,nEditEvent(0) 183 ,m_sdiState(SDI_DIRTY) 184 ,m_aTimerTriggered(-1,-1) 185 ,m_aDropActionType( DA_SCROLLUP ) 186 ,m_nSelectLock(0) 187 ,m_nFormsSelected(0) 188 ,m_nControlsSelected(0) 189 ,m_nHiddenControls(0) 190 ,m_aTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS ) 191 ,m_bDragDataDirty(sal_False) 192 ,m_bPrevSelectionMixed(sal_False) 193 ,m_bMarkingObjects(sal_False) 194 ,m_bRootSelected(sal_False) 195 ,m_bInitialUpdate(sal_True) 196 ,m_bKeyboardCut( sal_False ) 197 { 198 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::NavigatorTree" ); 199 SetHelpId( HID_FORM_NAVIGATOR ); 200 201 m_aNavigatorImages = ImageList( SVX_RES( RID_SVXIMGLIST_FMEXPL ) ); 202 m_aNavigatorImagesHC = ImageList( SVX_RES( RID_SVXIMGLIST_FMEXPL_HC ) ); 203 204 SetNodeBitmaps( 205 m_aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ), 206 m_aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ), 207 BMP_COLOR_NORMAL 208 ); 209 SetNodeBitmaps( 210 m_aNavigatorImagesHC.GetImage( RID_SVXIMG_COLLAPSEDNODE ), 211 m_aNavigatorImagesHC.GetImage( RID_SVXIMG_EXPANDEDNODE ), 212 BMP_COLOR_HIGHCONTRAST 213 ); 214 215 SetDragDropMode(0xFFFF); 216 EnableInplaceEditing( sal_True ); 217 SetSelectionMode(MULTIPLE_SELECTION); 218 219 m_pNavModel = new NavigatorTreeModel( m_aNavigatorImages, m_aNavigatorImagesHC ); 220 Clear(); 221 222 StartListening( *m_pNavModel ); 223 224 m_aDropActionTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnDropActionTimer)); 225 226 m_aSynchronizeTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnSynchronizeTimer)); 227 SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel)); 228 SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel)); 229 } 230 231 //------------------------------------------------------------------------ 232 NavigatorTree::~NavigatorTree() 233 { 234 if( nEditEvent ) 235 Application::RemoveUserEvent( nEditEvent ); 236 237 if (m_aSynchronizeTimer.IsActive()) 238 m_aSynchronizeTimer.Stop(); 239 240 DBG_ASSERT(GetNavModel() != NULL, "NavigatorTree::~NavigatorTree : unerwartet : kein ExplorerModel"); 241 EndListening( *m_pNavModel ); 242 Clear(); 243 delete m_pNavModel; 244 } 245 246 //------------------------------------------------------------------------ 247 void NavigatorTree::Clear() 248 { 249 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Clear" ); 250 m_pNavModel->Clear(); 251 } 252 253 //------------------------------------------------------------------------ 254 void NavigatorTree::UpdateContent( FmFormShell* pFormShell ) 255 { 256 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::UpdateContent" ); 257 if (m_bInitialUpdate) 258 { 259 GrabFocus(); 260 m_bInitialUpdate = sal_False; 261 } 262 263 FmFormShell* pOldShell = GetNavModel()->GetFormShell(); 264 FmFormPage* pOldPage = GetNavModel()->GetFormPage(); 265 FmFormPage* pNewPage = pFormShell ? pFormShell->GetCurPage() : NULL; 266 267 if ((pOldShell != pFormShell) || (pOldPage != pNewPage)) 268 { 269 // neue Shell, waehrend ich gerade editiere ? 270 if (IsEditingActive()) 271 CancelTextEditing(); 272 273 m_bDragDataDirty = sal_True; // sicherheitshalber, auch wenn ich gar nicht dragge 274 } 275 GetNavModel()->UpdateContent( pFormShell ); 276 277 // wenn es eine Form gibt, die Root expandieren 278 if (m_pRootEntry && !IsExpanded(m_pRootEntry)) 279 Expand(m_pRootEntry); 280 // wenn es GENAU eine Form gibt, auch diese expandieren 281 if (m_pRootEntry) 282 { 283 SvLBoxEntry* pFirst = FirstChild(m_pRootEntry); 284 if (pFirst && !NextSibling(pFirst)) 285 Expand(pFirst); 286 } 287 } 288 289 //------------------------------------------------------------------------------ 290 sal_Bool NavigatorTree::implAllowExchange( sal_Int8 _nAction, sal_Bool* _pHasNonHidden ) 291 { 292 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAllowExchange" ); 293 SvLBoxEntry* pCurEntry = GetCurEntry(); 294 if (!pCurEntry) 295 return sal_False; 296 297 // die Informationen fuer das AcceptDrop und ExecuteDrop 298 CollectSelectionData(SDI_ALL); 299 if (!m_arrCurrentSelection.Count()) 300 // nothing to do 301 return sal_False; 302 303 // testen, ob es sich vielleicht ausschliesslich um hidden controls handelt (dann koennte ich pCtrlExch noch ein 304 // zusaetzliches Format geben) 305 sal_Bool bHasNonHidden = sal_False; 306 for (sal_Int32 i=0; i<m_arrCurrentSelection.Count(); i++) 307 { 308 FmEntryData* pCurrent = static_cast< FmEntryData* >( m_arrCurrentSelection[(sal_uInt16)i]->GetUserData() ); 309 if ( IsHiddenControl( pCurrent ) ) 310 continue; 311 bHasNonHidden = sal_True; 312 break; 313 } 314 315 if ( bHasNonHidden && ( 0 == ( _nAction & DND_ACTION_MOVE ) ) ) 316 // non-hidden controls need to be moved 317 return sal_False; 318 319 if ( _pHasNonHidden ) 320 *_pHasNonHidden = bHasNonHidden; 321 322 return sal_True; 323 } 324 325 //------------------------------------------------------------------------------ 326 sal_Bool NavigatorTree::implPrepareExchange( sal_Int8 _nAction ) 327 { 328 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implPrepareExchange" ); 329 sal_Int32 i; 330 331 EndSelection(); 332 333 sal_Bool bHasNonHidden = sal_False; 334 if ( !implAllowExchange( _nAction, &bHasNonHidden ) ) 335 return sal_False; 336 337 m_aControlExchange.prepareDrag(); 338 m_aControlExchange->setFocusEntry( GetCurEntry() ); 339 340 for ( i = 0; i < m_arrCurrentSelection.Count(); ++i ) 341 m_aControlExchange->addSelectedEntry(m_arrCurrentSelection[(sal_uInt16)i]); 342 343 m_aControlExchange->setFormsRoot( GetNavModel()->GetFormPage()->GetForms() ); 344 m_aControlExchange->buildPathFormat( this, m_pRootEntry ); 345 346 if (!bHasNonHidden) 347 { 348 // eine entsprechende Sequenz aufbauen 349 Sequence< Reference< XInterface > > seqIFaces(m_arrCurrentSelection.Count()); 350 Reference< XInterface >* pArray = seqIFaces.getArray(); 351 for (i=0; i<m_arrCurrentSelection.Count(); ++i, ++pArray) 352 *pArray = static_cast< FmEntryData* >( m_arrCurrentSelection[(sal_uInt16)i]->GetUserData() )->GetElement(); 353 354 // und das neue Format 355 m_aControlExchange->addHiddenControlsFormat(seqIFaces); 356 } 357 358 m_bDragDataDirty = sal_False; 359 return sal_True; 360 } 361 362 //------------------------------------------------------------------------------ 363 void NavigatorTree::StartDrag( sal_Int8 /*nAction*/, const ::Point& /*rPosPixel*/ ) 364 { 365 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::StartDrag" ); 366 EndSelection(); 367 368 if ( !implPrepareExchange( DND_ACTION_COPYMOVE ) ) 369 // nothing to do or something went wrong 370 return; 371 372 // jetzt haben wir alle in der aktuelle Situation moeglichen Formate eingesammelt, es kann also losgehen ... 373 m_aControlExchange.startDrag( DND_ACTION_COPYMOVE ); 374 } 375 376 //------------------------------------------------------------------------------ 377 void NavigatorTree::Command( const CommandEvent& rEvt ) 378 { 379 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Command" ); 380 sal_Bool bHandled = sal_False; 381 switch( rEvt.GetCommand() ) 382 { 383 case COMMAND_CONTEXTMENU: 384 { 385 // die Stelle, an der geklickt wurde 386 ::Point ptWhere; 387 if (rEvt.IsMouseEvent()) 388 { 389 ptWhere = rEvt.GetMousePosPixel(); 390 SvLBoxEntry* ptClickedOn = GetEntry(ptWhere); 391 if (ptClickedOn == NULL) 392 break; 393 if ( !IsSelected(ptClickedOn) ) 394 { 395 SelectAll(sal_False); 396 Select(ptClickedOn, sal_True); 397 SetCurEntry(ptClickedOn); 398 } 399 } 400 else 401 { 402 if (m_arrCurrentSelection.Count() == 0) // kann nur bei Kontextmenue ueber Tastatur passieren 403 break; 404 405 SvLBoxEntry* pCurrent = GetCurEntry(); 406 if (!pCurrent) 407 break; 408 ptWhere = GetEntryPosition(pCurrent); 409 } 410 411 // meine Selektionsdaten auf den aktuellen Stand 412 CollectSelectionData(SDI_ALL); 413 414 // wenn mindestens ein Nicht-Root-Eintrag selektiert ist und die Root auch, dann nehme ich letztere aus der Selektion 415 // fix wieder raus 416 if ( (m_arrCurrentSelection.Count() > 1) && m_bRootSelected ) 417 { 418 Select( m_pRootEntry, sal_False ); 419 SetCursor( m_arrCurrentSelection.GetObject(0), sal_True); 420 } 421 sal_Bool bSingleSelection = (m_arrCurrentSelection.Count() == 1); 422 423 424 DBG_ASSERT( (m_arrCurrentSelection.Count() > 0) || m_bRootSelected, "keine Eintraege selektiert" ); 425 // solte nicht passieren, da ich oben bei der IsSelected-Abfrage auf jeden Fall einen selektiert haette, 426 // wenn das vorher nicht der Fall gewesen waere 427 428 429 // das Menue zusammenbasteln 430 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 431 FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; 432 if( pFormShell && pFormModel ) 433 { 434 PopupMenu aContextMenu(SVX_RES(RID_FMEXPLORER_POPUPMENU)); 435 PopupMenu* pSubMenuNew = aContextMenu.GetPopupMenu( SID_FM_NEW ); 436 437 // das 'Neu'-Untermenue gibt es nur, wenn genau die Root oder genau ein Formular selektiert sind 438 aContextMenu.EnableItem( SID_FM_NEW, bSingleSelection && (m_nFormsSelected || m_bRootSelected) ); 439 440 // 'Neu'\'Formular' unter genau den selben Bedingungen 441 pSubMenuNew->EnableItem( SID_FM_NEW_FORM, bSingleSelection && (m_nFormsSelected || m_bRootSelected) ); 442 pSubMenuNew->SetItemImage(SID_FM_NEW_FORM, m_aNavigatorImages.GetImage(RID_SVXIMG_FORM)); 443 pSubMenuNew->SetItemImage(SID_FM_NEW_HIDDEN, m_aNavigatorImages.GetImage(RID_SVXIMG_HIDDEN)); 444 445 // 'Neu'\'verstecktes...', wenn genau ein Formular selektiert ist 446 pSubMenuNew->EnableItem( SID_FM_NEW_HIDDEN, bSingleSelection && m_nFormsSelected ); 447 448 // 'Delete': everything which is not root can be removed 449 aContextMenu.EnableItem( SID_FM_DELETE, !m_bRootSelected ); 450 451 // 'Cut', 'Copy' and 'Paste' 452 aContextMenu.EnableItem( SID_CUT, !m_bRootSelected && implAllowExchange( DND_ACTION_MOVE ) ); 453 aContextMenu.EnableItem( SID_COPY, !m_bRootSelected && implAllowExchange( DND_ACTION_COPY ) ); 454 aContextMenu.EnableItem( SID_PASTE, implAcceptPaste( ) ); 455 456 // der TabDialog, wenn es genau ein Formular ist ... 457 aContextMenu.EnableItem( SID_FM_TAB_DIALOG, bSingleSelection && m_nFormsSelected ); 458 459 // in XML forms, we don't allow for the properties of a form 460 // #i36484# / 2004-11-04 /- fs@openoffice.org 461 if ( pFormShell->GetImpl()->isEnhancedForm() && !m_nControlsSelected ) 462 aContextMenu.RemoveItem( aContextMenu.GetItemPos( SID_FM_SHOW_PROPERTY_BROWSER ) ); 463 464 // if the property browser is already open, we don't allow for the properties, too 465 if( pFormShell->GetImpl()->IsPropBrwOpen() ) 466 aContextMenu.RemoveItem( aContextMenu.GetItemPos( SID_FM_SHOW_PROPERTY_BROWSER ) ); 467 // and finally, if there's a mixed selection of forms and controls, disable the entry, too 468 else 469 aContextMenu.EnableItem( SID_FM_SHOW_PROPERTY_BROWSER, 470 (m_nControlsSelected && !m_nFormsSelected) || (!m_nControlsSelected && m_nFormsSelected) ); 471 472 // Umbenennen gdw wenn ein Element und nicht die Root 473 aContextMenu.EnableItem( SID_FM_RENAME_OBJECT, bSingleSelection && !m_bRootSelected ); 474 475 // der Reandonly-Eintrag ist nur auf der Root erlaubt 476 aContextMenu.EnableItem( SID_FM_OPEN_READONLY, m_bRootSelected ); 477 // the same for automatic control focus 478 aContextMenu.EnableItem( SID_FM_AUTOCONTROLFOCUS, m_bRootSelected ); 479 480 // die ConvertTo-Slots sind enabled, wenn genau ein Control selektiert ist, der 481 // dem Control entsprechende Slot ist disabled 482 if (!m_bRootSelected && !m_nFormsSelected && (m_nControlsSelected == 1)) 483 { 484 aContextMenu.SetPopupMenu( SID_FM_CHANGECONTROLTYPE, FmXFormShell::GetConversionMenu() ); 485 #if OSL_DEBUG_LEVEL > 0 486 FmControlData* pCurrent = (FmControlData*)(m_arrCurrentSelection[0]->GetUserData()); 487 OSL_ENSURE( pFormShell->GetImpl()->isSolelySelected( pCurrent->GetFormComponent() ), 488 "NavigatorTree::Command: inconsistency between the navigator selection, and the selection as the shell knows it!" ); 489 #endif 490 491 pFormShell->GetImpl()->checkControlConversionSlotsForCurrentSelection( *aContextMenu.GetPopupMenu( SID_FM_CHANGECONTROLTYPE ) ); 492 } 493 else 494 aContextMenu.EnableItem( SID_FM_CHANGECONTROLTYPE, sal_False ); 495 496 // jetzt alles, was disabled wurde, wech 497 aContextMenu.RemoveDisabledEntries(sal_True, sal_True); 498 ////////////////////////////////////////////////////////// 499 // OpenReadOnly setzen 500 501 aContextMenu.CheckItem( SID_FM_OPEN_READONLY, pFormModel->GetOpenInDesignMode() ); 502 aContextMenu.CheckItem( SID_FM_AUTOCONTROLFOCUS, pFormModel->GetAutoControlFocus() ); 503 504 sal_uInt16 nSlotId = aContextMenu.Execute( this, ptWhere ); 505 switch( nSlotId ) 506 { 507 case SID_FM_NEW_FORM: 508 { 509 XubString aStr(SVX_RES(RID_STR_FORM)); 510 XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); 511 aUndoStr.SearchAndReplace('#', aStr); 512 513 pFormModel->BegUndo(aUndoStr); 514 // der Slot war nur verfuegbar, wenn es genau einen selektierten Eintrag gibt und dieser die Root 515 // oder ein Formular ist 516 NewForm( m_arrCurrentSelection.GetObject(0) ); 517 pFormModel->EndUndo(); 518 519 } break; 520 case SID_FM_NEW_HIDDEN: 521 { 522 XubString aStr(SVX_RES(RID_STR_CONTROL)); 523 XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); 524 aUndoStr.SearchAndReplace('#', aStr); 525 526 pFormModel->BegUndo(aUndoStr); 527 // dieser Slot war guletig bei (genau) einem selektierten Formular 528 rtl::OUString fControlName = FM_COMPONENT_HIDDEN; 529 NewControl( fControlName, m_arrCurrentSelection.GetObject(0) ); 530 pFormModel->EndUndo(); 531 532 } break; 533 534 case SID_CUT: 535 doCut(); 536 break; 537 538 case SID_COPY: 539 doCopy(); 540 break; 541 542 case SID_PASTE: 543 doPaste(); 544 break; 545 546 case SID_FM_DELETE: 547 { 548 DeleteSelection(); 549 } 550 break; 551 case SID_FM_TAB_DIALOG: 552 { 553 // dieser Slot galt bei genau einem selektierten Formular 554 SvLBoxEntry* pSelectedForm = m_arrCurrentSelection.GetObject(0); 555 DBG_ASSERT( IsFormEntry(pSelectedForm), "NavigatorTree::Command: Dieser Eintrag muss ein FormEntry sein." ); 556 557 FmFormData* pFormData = (FmFormData*)pSelectedForm->GetUserData(); 558 Reference< XForm > xForm( pFormData->GetFormIface()); 559 560 Reference< XTabControllerModel > xTabController(xForm, UNO_QUERY); 561 if( !xTabController.is() ) 562 break; 563 GetNavModel()->GetFormShell()->GetImpl()->ExecuteTabOrderDialog( xTabController ); 564 } 565 break; 566 567 case SID_FM_SHOW_PROPERTY_BROWSER: 568 { 569 ShowSelectionProperties(sal_True); 570 } 571 break; 572 case SID_FM_RENAME_OBJECT: 573 { 574 // das war bei genau einem Nicht-Root-Eintrag erlaubt 575 EditEntry( m_arrCurrentSelection.GetObject(0) ); 576 } 577 break; 578 case SID_FM_OPEN_READONLY: 579 { 580 pFormModel->SetOpenInDesignMode( !pFormModel->GetOpenInDesignMode() ); 581 pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_OPEN_READONLY); 582 } 583 break; 584 case SID_FM_AUTOCONTROLFOCUS: 585 { 586 pFormModel->SetAutoControlFocus( !pFormModel->GetAutoControlFocus() ); 587 pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS); 588 } 589 break; 590 default: 591 if (pFormShell->GetImpl()->isControlConversionSlot(nSlotId)) 592 { 593 FmControlData* pCurrent = (FmControlData*)(m_arrCurrentSelection[0]->GetUserData()); 594 if ( pFormShell->GetImpl()->executeControlConversionSlot( pCurrent->GetFormComponent(), nSlotId ) ) 595 ShowSelectionProperties(); 596 } 597 } 598 } 599 bHandled = sal_True; 600 } break; 601 } 602 603 if (!bHandled) 604 SvTreeListBox::Command( rEvt ); 605 } 606 607 //------------------------------------------------------------------------ 608 sal_Bool NavigatorTree::IsDeleteAllowed() 609 { 610 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsDeleteAllowed" ); 611 ////////////////////////////////////////////////////////////////////// 612 // Haben wir eine Form... 613 SvLBoxEntry* pCurEntry = GetCurEntry(); 614 sal_uInt32 nCurEntryPos = GetModel()->GetAbsPos( pCurEntry ); 615 616 if( nCurEntryPos==0 ) // Root kann nicht geloescht werden 617 return sal_False; 618 else 619 return IsFormEntry(pCurEntry) || IsFormComponentEntry(pCurEntry); 620 } 621 622 //------------------------------------------------------------------------ 623 SvLBoxEntry* NavigatorTree::FindEntry( FmEntryData* pEntryData ) 624 { 625 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::FindEntry" ); 626 if( !pEntryData ) return NULL; 627 SvLBoxEntry* pCurEntry = First(); 628 FmEntryData* pCurEntryData; 629 while( pCurEntry ) 630 { 631 pCurEntryData = (FmEntryData*)pCurEntry->GetUserData(); 632 if( pCurEntryData && pCurEntryData->IsEqualWithoutChilds(pEntryData) ) 633 return pCurEntry; 634 635 pCurEntry = Next( pCurEntry ); 636 } 637 638 return NULL; 639 } 640 641 //------------------------------------------------------------------------ 642 void NavigatorTree::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) 643 { 644 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Notify" ); 645 if( rHint.ISA(FmNavRemovedHint) ) 646 { 647 FmNavRemovedHint* pRemovedHint = (FmNavRemovedHint*)&rHint; 648 FmEntryData* pEntryData = pRemovedHint->GetEntryData(); 649 Remove( pEntryData ); 650 } 651 652 else if( rHint.ISA(FmNavInsertedHint) ) 653 { 654 FmNavInsertedHint* pInsertedHint = (FmNavInsertedHint*)&rHint; 655 FmEntryData* pEntryData = pInsertedHint->GetEntryData(); 656 sal_uInt32 nRelPos = pInsertedHint->GetRelPos(); 657 Insert( pEntryData, nRelPos ); 658 } 659 660 else if( rHint.ISA(FmNavModelReplacedHint) ) 661 { 662 FmEntryData* pData = ((FmNavModelReplacedHint*)&rHint)->GetEntryData(); 663 SvLBoxEntry* pEntry = FindEntry( pData ); 664 if (pEntry) 665 { // das Image neu setzen 666 SetCollapsedEntryBmp( pEntry, pData->GetNormalImage(), BMP_COLOR_NORMAL ); 667 SetExpandedEntryBmp( pEntry, pData->GetNormalImage(), BMP_COLOR_NORMAL ); 668 669 SetCollapsedEntryBmp( pEntry, pData->GetHCImage(), BMP_COLOR_HIGHCONTRAST ); 670 SetExpandedEntryBmp( pEntry, pData->GetHCImage(), BMP_COLOR_HIGHCONTRAST ); 671 } 672 } 673 674 else if( rHint.ISA(FmNavNameChangedHint) ) 675 { 676 FmNavNameChangedHint* pNameChangedHint = (FmNavNameChangedHint*)&rHint; 677 SvLBoxEntry* pEntry = FindEntry( pNameChangedHint->GetEntryData() ); 678 SetEntryText( pEntry, pNameChangedHint->GetNewName() ); 679 } 680 681 else if( rHint.ISA(FmNavClearedHint) ) 682 { 683 SvTreeListBox::Clear(); 684 685 ////////////////////////////////////////////////////////////////////// 686 // Default-Eintrag "Formulare" 687 Image aRootImage( m_aNavigatorImages.GetImage( RID_SVXIMG_FORMS ) ); 688 m_pRootEntry = InsertEntry( SVX_RES(RID_STR_FORMS), aRootImage, aRootImage, 689 NULL, sal_False, 0, NULL ); 690 691 if ( m_pRootEntry ) 692 { 693 Image aHCRootImage( m_aNavigatorImagesHC.GetImage( RID_SVXIMG_FORMS ) ); 694 SetExpandedEntryBmp( m_pRootEntry, aHCRootImage, BMP_COLOR_HIGHCONTRAST ); 695 SetCollapsedEntryBmp( m_pRootEntry, aHCRootImage, BMP_COLOR_HIGHCONTRAST ); 696 } 697 } 698 else if (!m_bMarkingObjects && rHint.ISA(FmNavRequestSelectHint)) 699 { // wenn m_bMarkingObjects sal_True ist, markiere ich gerade selber Objekte, und da der ganze Mechanismus dahinter synchron ist, 700 // ist das genau der Hint, der durch mein Markieren ausgeloest wird, also kann ich ihn ignorieren 701 FmNavRequestSelectHint* pershHint = (FmNavRequestSelectHint*)&rHint; 702 FmEntryDataArray& arredToSelect = pershHint->GetItems(); 703 SynchronizeSelection(arredToSelect); 704 705 if (pershHint->IsMixedSelection()) 706 // in diesem Fall habe ich alles deselektiert, obwohl die View u.U. eine gemischte Markierung hatte 707 // ich muss also im naechsten Select den Navigator an die View anpassen 708 m_bPrevSelectionMixed = sal_True; 709 } 710 } 711 712 //------------------------------------------------------------------------ 713 SvLBoxEntry* NavigatorTree::Insert( FmEntryData* pEntryData, sal_uIntPtr nRelPos ) 714 { 715 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Insert" ); 716 ////////////////////////////////////////////////////////////////////// 717 // Aktuellen Eintrag einfuegen 718 SvLBoxEntry* pParentEntry = FindEntry( pEntryData->GetParent() ); 719 SvLBoxEntry* pNewEntry; 720 721 if( !pParentEntry ) 722 pNewEntry = InsertEntry( pEntryData->GetText(), 723 pEntryData->GetNormalImage(), pEntryData->GetNormalImage(), 724 m_pRootEntry, sal_False, nRelPos, pEntryData ); 725 726 else 727 pNewEntry = InsertEntry( pEntryData->GetText(), 728 pEntryData->GetNormalImage(), pEntryData->GetNormalImage(), 729 pParentEntry, sal_False, nRelPos, pEntryData ); 730 731 if ( pNewEntry ) 732 { 733 SetExpandedEntryBmp( pNewEntry, pEntryData->GetHCImage(), BMP_COLOR_HIGHCONTRAST ); 734 SetCollapsedEntryBmp( pNewEntry, pEntryData->GetHCImage(), BMP_COLOR_HIGHCONTRAST ); 735 } 736 737 ////////////////////////////////////////////////////////////////////// 738 // Wenn Root-Eintrag Root expandieren 739 if( !pParentEntry ) 740 Expand( m_pRootEntry ); 741 742 ////////////////////////////////////////////////////////////////////// 743 // Childs einfuegen 744 FmEntryDataList* pChildList = pEntryData->GetChildList(); 745 sal_uInt32 nChildCount = pChildList->Count(); 746 FmEntryData* pChildData; 747 for( sal_uInt32 i=0; i<nChildCount; i++ ) 748 { 749 pChildData = pChildList->GetObject(i); 750 Insert( pChildData, LIST_APPEND ); 751 } 752 753 return pNewEntry; 754 } 755 756 //------------------------------------------------------------------------ 757 void NavigatorTree::Remove( FmEntryData* pEntryData ) 758 { 759 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Remove" ); 760 if( !pEntryData ) 761 return; 762 763 // der Entry zu den Daten 764 SvLBoxEntry* pEntry = FindEntry( pEntryData ); 765 if (!pEntry) 766 return; 767 768 // Eintrag aus TreeListBox entfernen 769 // ich darf das Select, das ich ausloese, nicht behandeln : 770 // Select aendert die MarkList der View, wenn das gerade auch jemand anders macht und dabei ein Remove 771 // triggert, haben wir mit ziemlicher Sicherheit ein Problem - Paradebeispiel war das Gruppieren von Controls mit 772 // offenem Navigator ...) 773 LockSelectionHandling(); 774 775 // ein kleines Problem : ich merke mir meine selektierten Daten, wenn mir jetzt jemand einen selektierten Eintrag 776 // unter dem Hintern wegschiesst, werde ich inkonsistent ... was schlecht waere 777 Select(pEntry, sal_False); 778 779 // beim eigentlichen Entfernen kann die Selection geaendert werden, da ich aber das SelectionHandling abgeschaltet 780 // habe, muss ich mich hinterher darum kuemmern 781 sal_uIntPtr nExpectedSelectionCount = GetSelectionCount(); 782 783 if( pEntry ) 784 GetModel()->Remove( pEntry ); 785 786 if (nExpectedSelectionCount != GetSelectionCount()) 787 SynchronizeSelection(); 788 789 // und standardmaessig behandle ich das Select natuerlich 790 UnlockSelectionHandling(); 791 } 792 793 //------------------------------------------------------------------------ 794 sal_Bool NavigatorTree::IsFormEntry( SvLBoxEntry* pEntry ) 795 { 796 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsFormEntry" ); 797 FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData(); 798 return !pEntryData || pEntryData->ISA(FmFormData); 799 } 800 801 //------------------------------------------------------------------------ 802 sal_Bool NavigatorTree::IsFormComponentEntry( SvLBoxEntry* pEntry ) 803 { 804 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsFormComponentEntry" ); 805 FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData(); 806 return pEntryData && pEntryData->ISA(FmControlData); 807 } 808 809 //------------------------------------------------------------------------ 810 sal_Bool NavigatorTree::implAcceptPaste( ) 811 { 812 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAcceptPaste" ); 813 SvLBoxEntry* pFirstSelected = FirstSelected(); 814 if ( !pFirstSelected || NextSelected( pFirstSelected ) ) 815 // no selected entry, or at least two selected entries 816 return sal_False; 817 818 // get the clipboard 819 TransferableDataHelper aClipboardContent( TransferableDataHelper::CreateFromSystemClipboard( this ) ); 820 821 sal_Int8 nAction = m_aControlExchange.isClipboardOwner() && doingKeyboardCut( ) ? DND_ACTION_MOVE : DND_ACTION_COPY; 822 return ( nAction == implAcceptDataTransfer( aClipboardContent.GetDataFlavorExVector(), nAction, pFirstSelected, sal_False ) ); 823 } 824 825 //------------------------------------------------------------------------ 826 sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, const ::Point& _rDropPos, sal_Bool _bDnD ) 827 { 828 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAcceptDataTransfer" ); 829 return implAcceptDataTransfer( _rFlavors, _nAction, GetEntry( _rDropPos ), _bDnD ); 830 } 831 832 //------------------------------------------------------------------------ 833 sal_Int8 NavigatorTree::implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, SvLBoxEntry* _pTargetEntry, sal_Bool _bDnD ) 834 { 835 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implAcceptDataTransfer" ); 836 // no target -> no drop 837 if (!_pTargetEntry) 838 return DND_ACTION_NONE; 839 840 // format check 841 sal_Bool bHasDefControlFormat = OControlExchange::hasFieldExchangeFormat( _rFlavors ); 842 sal_Bool bHasControlPathFormat = OControlExchange::hasControlPathFormat( _rFlavors ); 843 sal_Bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( _rFlavors ); 844 if (!bHasDefControlFormat && !bHasControlPathFormat && !bHasHiddenControlsFormat) 845 return DND_ACTION_NONE; 846 847 sal_Bool bSelfSource = _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner(); 848 849 if ( bHasHiddenControlsFormat ) 850 { // bHasHiddenControlsFormat means that only hidden controls are part of the data 851 852 // hidden controls can be copied to a form only 853 if ( !_pTargetEntry || ( _pTargetEntry == m_pRootEntry ) || !IsFormEntry( _pTargetEntry ) ) 854 return DND_ACTION_NONE; 855 856 return bSelfSource ? ( DND_ACTION_COPYMOVE & _nAction ) : DND_ACTION_COPY; 857 } 858 859 if ( !bSelfSource ) 860 { 861 // DnD or CnP crossing navigator boundaries 862 // The main problem here is that the current API does not allow us to sneak into the content which 863 // is to be inserted. So we have to allow it for the moment, but maybe reject later on (in the real drop). 864 865 // TODO: this smart behaviour later on ... at the moment, we disallow data transfer crossing navigator 866 // boundaries. 867 868 return DND_ACTION_NONE; 869 } 870 871 DBG_ASSERT( _bDnD ? m_aControlExchange.isDragSource() : m_aControlExchange.isClipboardOwner(), 872 "NavigatorTree::implAcceptDataTransfer: here only with source=dest!" ); 873 // somebody changed the logic of this method ... 874 875 // from here on, I can work with m_aControlExchange instead of _rData! 876 877 sal_Bool bForeignCollection = m_aControlExchange->getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get(); 878 if ( bForeignCollection ) 879 { 880 // crossing shell/page boundaries, we can exchange hidden controls only 881 // But if we survived the checks above, we do not have hidden controls. 882 // -> no data transfer 883 DBG_ASSERT( !bHasHiddenControlsFormat, "NavigatorTree::implAcceptDataTransfer: still hidden controls format!" ); 884 // somebody changed the logic of this method ... 885 886 return DND_ACTION_COPY; 887 } 888 889 if (DND_ACTION_MOVE != _nAction) // 'normal' controls within a shell are moved only (never copied) 890 return DND_ACTION_NONE; 891 892 if ( m_bDragDataDirty || !bHasDefControlFormat ) 893 { 894 if (!bHasControlPathFormat) 895 // ich befinde mich zwar in der Shell/Page, aus der die Controls stammen, habe aber kein Format, das den stattgefundenen 896 // Shell-Wechsel ueberlebt hat (SVX_FM_CONTROLS_AS_PATH) 897 return DND_ACTION_NONE; 898 899 // da die Shell waehrend des Draggens umgeschaltet wude, muss ich die Liste des ExchangeObjektes wieder neu aufbauen 900 // (dort stehen SvLBoxEntries drin, und die sind bei der Umschaltung floeten gegangen) 901 m_aControlExchange->buildListFromPath(this, m_pRootEntry); 902 m_bDragDataDirty = sal_False; 903 } 904 905 // die Liste der gedroppten Eintraege aus dem DragServer 906 const ListBoxEntrySet& aDropped = m_aControlExchange->selected(); 907 DBG_ASSERT(aDropped.size() >= 1, "NavigatorTree::implAcceptDataTransfer: keine Eintraege !"); 908 909 sal_Bool bDropTargetIsComponent = IsFormComponentEntry( _pTargetEntry ); 910 //SvLBoxEntry* pDropTargetParent = GetParent( _pTargetEntry ); 911 912 // conditions to disallow the drop 913 // 0) the root entry is part of the list (can't DnD the root!) 914 // 1) one of the draged entries is to be dropped onto it's own parent 915 // 2) - " - is to be dropped onto itself 916 // 3) - " - is a Form and to be dropped onto one of it's descendants 917 // 4) one of the entries is a control and to be dropped onto the root 918 // 5) a control or form will be dropped onto a control which is _not_ a sibling (dropping onto a sibling 919 // means moving the control) 920 921 // collect the ancestors of the drop targte (speeds up 3) 922 SvLBoxEntrySortedArray arrDropAnchestors; 923 SvLBoxEntry* pLoop = _pTargetEntry; 924 while (pLoop) 925 { 926 arrDropAnchestors.Insert(pLoop); 927 pLoop = GetParent(pLoop); 928 } 929 930 for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin(); 931 dropped != aDropped.end(); 932 ++dropped 933 ) 934 { 935 SvLBoxEntry* pCurrent = *dropped; 936 SvLBoxEntry* pCurrentParent = GetParent(pCurrent); 937 938 // test for 0) 939 if (pCurrent == m_pRootEntry) 940 return DND_ACTION_NONE; 941 942 // test for 1) 943 if ( _pTargetEntry == pCurrentParent ) 944 return DND_ACTION_NONE; 945 946 // test for 2) 947 if (pCurrent == _pTargetEntry) 948 return DND_ACTION_NONE; 949 950 // test for 5) 951 // if ( bDropTargetIsComponent && (pDropTargetParent != pCurrentParent) ) 952 if ( bDropTargetIsComponent ) // TODO : die obige Zeile wieder rein, dann muss aber ExecuteDrop das Vertauschen auch beherrschen 953 return DND_ACTION_NONE; 954 955 // test for 3) 956 if ( IsFormEntry(pCurrent) ) 957 { 958 sal_uInt16 nPosition; 959 if ( arrDropAnchestors.Seek_Entry(pCurrent, &nPosition) ) 960 return DND_ACTION_NONE; 961 } else if ( IsFormComponentEntry(pCurrent) ) 962 { 963 // test for 4) 964 if (_pTargetEntry == m_pRootEntry) 965 return DND_ACTION_NONE; 966 } 967 } 968 969 return DND_ACTION_MOVE; 970 } 971 972 //------------------------------------------------------------------------ 973 sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& rEvt ) 974 { 975 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::AcceptDrop" ); 976 ::Point aDropPos = rEvt.maPosPixel; 977 978 // kuemmern wir uns erst mal um moeglich DropActions (Scrollen und Aufklappen) 979 if (rEvt.mbLeaving) 980 { 981 if (m_aDropActionTimer.IsActive()) 982 m_aDropActionTimer.Stop(); 983 } else 984 { 985 sal_Bool bNeedTrigger = sal_False; 986 // auf dem ersten Eintrag ? 987 if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight())) 988 { 989 m_aDropActionType = DA_SCROLLUP; 990 bNeedTrigger = sal_True; 991 } else 992 // auf dem letzten (bzw. in dem Bereich, den ein Eintrag einnehmen wuerde, wenn er unten genau buendig 993 // abschliessen wuerde) ? 994 if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight())) 995 { 996 m_aDropActionType = DA_SCROLLDOWN; 997 bNeedTrigger = sal_True; 998 } else 999 { // auf einem Entry mit Childs, der nicht aufgeklappt ist ? 1000 SvLBoxEntry* pDropppedOn = GetEntry(aDropPos); 1001 if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn)) 1002 { 1003 // -> aufklappen 1004 m_aDropActionType = DA_EXPANDNODE; 1005 bNeedTrigger = sal_True; 1006 } 1007 } 1008 1009 if (bNeedTrigger && (m_aTimerTriggered != aDropPos)) 1010 { 1011 // neu anfangen zu zaehlen 1012 m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS; 1013 // die Pos merken, da ich auch AcceptDrops bekomme, wenn sich die Maus gar nicht bewegt hat 1014 m_aTimerTriggered = aDropPos; 1015 // und den Timer los 1016 if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ? 1017 { 1018 m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE); 1019 m_aDropActionTimer.Start(); 1020 } 1021 } else if (!bNeedTrigger) 1022 m_aDropActionTimer.Stop(); 1023 } 1024 1025 return implAcceptDataTransfer( GetDataFlavorExVector(), rEvt.mnAction, aDropPos, sal_True ); 1026 } 1027 1028 //------------------------------------------------------------------------ 1029 sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const ::Point& _rDropPos, sal_Bool _bDnD ) 1030 { 1031 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implExecuteDataTransfer" ); 1032 return implExecuteDataTransfer( _rData, _nAction, GetEntry( _rDropPos ), _bDnD ); 1033 } 1034 1035 //------------------------------------------------------------------------ 1036 sal_Int8 NavigatorTree::implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, SvLBoxEntry* _pTargetEntry, sal_Bool _bDnD ) 1037 { 1038 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::implExecuteDataTransfer" ); 1039 const DataFlavorExVector& rDataFlavors = _rData.GetDataFlavorExVector(); 1040 1041 if ( DND_ACTION_NONE == implAcceptDataTransfer( rDataFlavors, _nAction, _pTargetEntry, _bDnD ) ) 1042 // under some platforms, it may happen that ExecuteDrop is called though AcceptDrop returned DND_ACTION_NONE 1043 return DND_ACTION_NONE; 1044 1045 // ware schlecht, wenn nach dem Droppen noch gescrollt wird ... 1046 if (m_aDropActionTimer.IsActive()) 1047 m_aDropActionTimer.Stop(); 1048 1049 if (!_pTargetEntry) 1050 // no target -> no drop 1051 return DND_ACTION_NONE; 1052 1053 // format checks 1054 #ifdef DBG_UTIL 1055 sal_Bool bHasHiddenControlsFormat = OControlExchange::hasHiddenControlModelsFormat( rDataFlavors ); 1056 sal_Bool bForeignCollection = _rData.getFormsRoot().get() != GetNavModel()->GetFormPage()->GetForms().get(); 1057 DBG_ASSERT(!bForeignCollection || bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: invalid format (AcceptDrop shouldn't have let this pass) !"); 1058 DBG_ASSERT(bForeignCollection || !m_bDragDataDirty, "NavigatorTree::implExecuteDataTransfer: invalid state (shell changed since last exchange resync) !"); 1059 // das sollte in AcceptDrop erledigt worden sein : dort wird in _rData die Liste der Controls aufgebaut und m_bDragDataDirty 1060 // zurueckgesetzt 1061 #endif 1062 1063 if ( DND_ACTION_COPY == _nAction ) 1064 { // bHasHiddenControlsFormat means that only hidden controls are part of the data 1065 DBG_ASSERT( bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: copy allowed for hidden controls only!" ); 1066 DBG_ASSERT( _pTargetEntry && ( _pTargetEntry != m_pRootEntry ) && IsFormEntry( _pTargetEntry ), 1067 "NavigatorTree::implExecuteDataTransfer: should not be here!" ); 1068 // implAcceptDataTransfer should have caught both cases 1069 1070 DBG_ASSERT(bHasHiddenControlsFormat, "NavigatorTree::implExecuteDataTransfer: only copying of hidden controls is supported !"); 1071 // das sollte das AcceptDrop abgefangen haben 1072 1073 // da ich gleich die Zielobjekte alle selektieren will (und nur die) 1074 SelectAll(sal_False); 1075 1076 Sequence< Reference< XInterface > > aControls = _rData.hiddenControls(); 1077 sal_Int32 nCount = aControls.getLength(); 1078 const Reference< XInterface >* pControls = aControls.getConstArray(); 1079 1080 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 1081 FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; 1082 1083 // innerhalb eines Undo ... 1084 if (pFormModel) 1085 { 1086 XubString aStr(SVX_RES(RID_STR_CONTROL)); 1087 XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); 1088 aUndoStr.SearchAndReplace('#', aStr); 1089 pFormModel->BegUndo(aUndoStr); 1090 } 1091 1092 // die Conrtols kopieren 1093 for (sal_Int32 i=0; i<nCount; ++i) 1094 { 1095 // neues Control anlegen 1096 rtl::OUString fControlName = FM_COMPONENT_HIDDEN; 1097 FmControlData* pNewControlData = NewControl( fControlName, _pTargetEntry, sal_False); 1098 Reference< XPropertySet > xNewPropSet( pNewControlData->GetPropertySet() ); 1099 1100 // und die Properties des alten in das neue kopieren 1101 Reference< XPropertySet > xCurrent(pControls[i], UNO_QUERY); 1102 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL 1103 // nur mal eben sehen, ob das Ding tatsaechlich ein hidden control ist 1104 sal_Int16 nClassId = ::comphelper::getINT16(xCurrent->getPropertyValue(FM_PROP_CLASSID)); 1105 OSL_ENSURE(nClassId == FormComponentType::HIDDENCONTROL, "NavigatorTree::implExecuteDataTransfer: invalid control in drop list !"); 1106 // wenn das SVX_FM_HIDDEN_CONTROLS-Format vorhanden ist, dann sollten wirklich nur hidden controls in der Sequenz 1107 // stecken 1108 #endif // (OSL_DEBUG_LEVEL > 1) || DBG_UTIL 1109 Reference< XPropertySetInfo > xPropInfo( xCurrent->getPropertySetInfo()); 1110 Sequence< Property> seqAllCurrentProps = xPropInfo->getProperties(); 1111 Property* pAllCurrentProps = seqAllCurrentProps.getArray(); 1112 for (sal_Int32 j=0; j<seqAllCurrentProps.getLength(); ++j) 1113 { 1114 ::rtl::OUString sCurrentProp = pAllCurrentProps[j].Name; 1115 if (((pAllCurrentProps[j].Attributes & PropertyAttribute::READONLY) == 0) && (sCurrentProp != FM_PROP_NAME)) 1116 { // (read-only attribs werden natuerlich nicht gesetzt, dito der Name, den hat das NewControl schon eindeutig 1117 // festgelegt) 1118 xNewPropSet->setPropertyValue(sCurrentProp, xCurrent->getPropertyValue(sCurrentProp)); 1119 } 1120 } 1121 1122 SvLBoxEntry* pToSelect = FindEntry(pNewControlData); 1123 Select(pToSelect, sal_True); 1124 if (i == 0) 1125 SetCurEntry(pToSelect); 1126 } 1127 1128 if (pFormModel) 1129 pFormModel->EndUndo(); 1130 1131 return _nAction; 1132 } 1133 1134 if ( !OControlExchange::hasFieldExchangeFormat( _rData.GetDataFlavorExVector() ) ) 1135 { 1136 // can't do anything without the internal format here ... usually happens when doing DnD or CnP 1137 // over navigator boundaries 1138 return DND_ACTION_NONE; 1139 } 1140 1141 // some data for the target 1142 sal_Bool bDropTargetIsForm = IsFormEntry(_pTargetEntry); 1143 FmFormData* pTargetData = bDropTargetIsForm ? (FmFormData*)_pTargetEntry->GetUserData() : NULL; 1144 1145 DBG_ASSERT( DND_ACTION_COPY != _nAction, "NavigatorTree::implExecuteDataTransfer: somebody changed the logics!" ); 1146 1147 // die Liste der gedraggten Eintraege 1148 ListBoxEntrySet aDropped = _rData.selected(); 1149 DBG_ASSERT(aDropped.size() >= 1, "NavigatorTree::implExecuteDataTransfer: no entries!"); 1150 1151 // die Shell und das Model 1152 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 1153 FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; 1154 if (!pFormModel) 1155 return DND_ACTION_NONE; 1156 1157 // fuer's Undo 1158 const bool bUndo = pFormModel->IsUndoEnabled(); 1159 1160 if( bUndo ) 1161 { 1162 XubString strUndoDescription(SVX_RES(RID_STR_UNDO_CONTAINER_REPLACE)); 1163 pFormModel->BegUndo(strUndoDescription); 1164 } 1165 1166 // ich nehme vor dem Einfuegen eines Eintrages seine Selection raus, damit die Markierung dabei nicht flackert 1167 // -> das Handeln des Select locken 1168 LockSelectionHandling(); 1169 1170 // jetzt durch alle gedroppten Eintraege ... 1171 for ( ListBoxEntrySet::const_iterator dropped = aDropped.begin(); 1172 dropped != aDropped.end(); 1173 ++dropped 1174 ) 1175 { 1176 // ein paar Daten zum aktuellen Element 1177 SvLBoxEntry* pCurrent = *dropped; 1178 DBG_ASSERT(pCurrent != NULL, "NavigatorTree::implExecuteDataTransfer: ungueltiger Eintrag"); 1179 DBG_ASSERT(GetParent(pCurrent) != NULL, "NavigatorTree::implExecuteDataTransfer: ungueltiger Eintrag"); 1180 // die Root darf nicht gedraggt werden 1181 1182 FmEntryData* pCurrentUserData = (FmEntryData*)pCurrent->GetUserData(); 1183 1184 Reference< XChild > xCurrentChild(pCurrentUserData->GetChildIFace(), UNO_QUERY); 1185 Reference< XIndexContainer > xContainer(xCurrentChild->getParent(), UNO_QUERY); 1186 1187 FmFormData* pCurrentParentUserData = (FmFormData*)pCurrentUserData->GetParent(); 1188 DBG_ASSERT(pCurrentParentUserData == NULL || pCurrentParentUserData->ISA(FmFormData), "NavigatorTree::implExecuteDataTransfer: ungueltiges Parent"); 1189 1190 // beim Vater austragen 1191 if (pCurrentParentUserData) 1192 pCurrentParentUserData->GetChildList()->Remove(pCurrentUserData); 1193 else 1194 GetNavModel()->GetRootList()->Remove(pCurrentUserData); 1195 1196 // aus dem Container entfernen 1197 sal_Int32 nIndex = getElementPos(Reference< XIndexAccess > (xContainer, UNO_QUERY), xCurrentChild); 1198 GetNavModel()->m_pPropChangeList->Lock(); 1199 // die Undo-Action fuer das Rausnehmen 1200 if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo()) 1201 { 1202 pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Removed, 1203 xContainer, xCurrentChild, nIndex)); 1204 } 1205 else if( !GetNavModel()->m_pPropChangeList->CanUndo() ) 1206 { 1207 FmUndoContainerAction::DisposeElement( xCurrentChild ); 1208 } 1209 1210 // Events mitkopieren 1211 Reference< XEventAttacherManager > xManager(xContainer, UNO_QUERY); 1212 Sequence< ScriptEventDescriptor > aEvts; 1213 1214 if (xManager.is() && nIndex >= 0) 1215 aEvts = xManager->getScriptEvents(nIndex); 1216 xContainer->removeByIndex(nIndex); 1217 1218 // die Selection raus 1219 Select(pCurrent, sal_False); 1220 // und weg 1221 Remove(pCurrentUserData); 1222 1223 // die Stelle innerhalb des DropParents, an der ich die gedroppten Eintraege einfuegen muss 1224 if (pTargetData) 1225 xContainer = Reference< XIndexContainer > (pTargetData->GetElement(), UNO_QUERY); 1226 else 1227 xContainer = Reference< XIndexContainer > (GetNavModel()->GetForms(), UNO_QUERY); 1228 1229 // immer ganz hinten einfuegen 1230 nIndex = xContainer->getCount(); 1231 1232 // UndoAction fuer das Einfuegen 1233 if ( bUndo && GetNavModel()->m_pPropChangeList->CanUndo()) 1234 pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Inserted, 1235 xContainer, xCurrentChild, nIndex)); 1236 1237 // einfuegen im neuen Container 1238 if (pTargetData) 1239 { 1240 // es wird in eine Form eingefuegt, dann brauche ich eine FormComponent 1241 xContainer->insertByIndex( nIndex, 1242 makeAny( Reference< XFormComponent >( xCurrentChild, UNO_QUERY ) ) ); 1243 } 1244 else 1245 { 1246 xContainer->insertByIndex( nIndex, 1247 makeAny( Reference< XForm >( xCurrentChild, UNO_QUERY ) ) ); 1248 } 1249 1250 if (aEvts.getLength()) 1251 { 1252 xManager = Reference< XEventAttacherManager > (xContainer, UNO_QUERY); 1253 if (xManager.is()) 1254 xManager->registerScriptEvents(nIndex, aEvts); 1255 } 1256 1257 GetNavModel()->m_pPropChangeList->UnLock(); 1258 1259 // zuerst dem Eintrag das neue Parent 1260 pCurrentUserData->SetParent(pTargetData); 1261 1262 // dann dem Parent das neue Child 1263 if (pTargetData) 1264 pTargetData->GetChildList()->Insert(pCurrentUserData, nIndex); 1265 else 1266 GetNavModel()->GetRootList()->Insert(pCurrentUserData, nIndex); 1267 1268 // dann bei mir selber bekanntgeben und neu selektieren 1269 SvLBoxEntry* pNew = Insert( pCurrentUserData, nIndex ); 1270 if ( ( aDropped.begin() == dropped ) && pNew ) 1271 { 1272 SvLBoxEntry* pParent = GetParent( pNew ); 1273 if ( pParent ) 1274 Expand( pParent ); 1275 } 1276 } 1277 1278 UnlockSelectionHandling(); 1279 1280 if( bUndo ) 1281 pFormModel->EndUndo(); 1282 1283 // During the move, the markings of the underlying view did not change (because the view is not affected by the logical 1284 // hierarchy of the form/control models. But my selection changed - which means I have to adjust it according to the 1285 // view marks, again. 1286 SynchronizeSelection(); 1287 1288 // in addition, with the move of controls such things as "the current form" may have changed - force the shell 1289 // to update itself accordingly 1290 if( pFormShell && pFormShell->GetImpl() && pFormShell->GetFormView() ) 1291 pFormShell->GetImpl()->DetermineSelection( pFormShell->GetFormView()->GetMarkedObjectList() ); 1292 1293 if ( m_aControlExchange.isClipboardOwner() && ( DND_ACTION_MOVE == _nAction ) ) 1294 m_aControlExchange->clear(); 1295 1296 return _nAction; 1297 } 1298 1299 //------------------------------------------------------------------------ 1300 sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& rEvt ) 1301 { 1302 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::ExecuteDrop" ); 1303 sal_Int8 nResult( DND_ACTION_NONE ); 1304 1305 if ( m_aControlExchange.isDragSource() ) 1306 nResult = implExecuteDataTransfer( *m_aControlExchange, rEvt.mnAction, rEvt.maPosPixel, sal_True ); 1307 else 1308 { 1309 OControlTransferData aDroppedData( rEvt.maDropEvent.Transferable ); 1310 nResult = implExecuteDataTransfer( aDroppedData, rEvt.mnAction, rEvt.maPosPixel, sal_True ); 1311 } 1312 1313 return nResult; 1314 } 1315 1316 //------------------------------------------------------------------------ 1317 void NavigatorTree::doPaste() 1318 { 1319 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::doPaste" ); 1320 try 1321 { 1322 if ( m_aControlExchange.isClipboardOwner() ) 1323 { 1324 implExecuteDataTransfer( *m_aControlExchange, doingKeyboardCut( ) ? DND_ACTION_MOVE : DND_ACTION_COPY, FirstSelected(), sal_False ); 1325 } 1326 else 1327 { 1328 // the clipboard content 1329 Reference< XClipboard > xClipboard( GetClipboard() ); 1330 Reference< XTransferable > xTransferable; 1331 if ( xClipboard.is() ) 1332 xTransferable = xClipboard->getContents(); 1333 1334 OControlTransferData aClipboardContent( xTransferable ); 1335 implExecuteDataTransfer( aClipboardContent, DND_ACTION_COPY, FirstSelected(), sal_False ); 1336 } 1337 } 1338 catch( const Exception& ) 1339 { 1340 DBG_ERROR( "NavigatorTree::doPaste: caught an exception!" ); 1341 } 1342 } 1343 1344 //------------------------------------------------------------------------ 1345 void NavigatorTree::doCopy() 1346 { 1347 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::doCopy" ); 1348 if ( implPrepareExchange( DND_ACTION_COPY ) ) 1349 { 1350 m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) ); 1351 m_aControlExchange.copyToClipboard( ); 1352 } 1353 } 1354 1355 //------------------------------------------------------------------------ 1356 void NavigatorTree::ModelHasRemoved( SvListEntry* _pEntry ) 1357 { 1358 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::ModelHasRemoved" ); 1359 SvLBoxEntry* pTypedEntry = static_cast< SvLBoxEntry* >( _pEntry ); 1360 if ( doingKeyboardCut() ) 1361 m_aCutEntries.erase( pTypedEntry ); 1362 1363 if ( m_aControlExchange.isDataExchangeActive() ) 1364 { 1365 if ( 0 == m_aControlExchange->onEntryRemoved( pTypedEntry ) ) 1366 { 1367 // last of the entries which we put into the clipboard has been deleted from the tree. 1368 // Give up the clipboard ownership. 1369 m_aControlExchange.clear(); 1370 } 1371 } 1372 } 1373 1374 //------------------------------------------------------------------------ 1375 void NavigatorTree::doCut() 1376 { 1377 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::doCut" ); 1378 if ( implPrepareExchange( DND_ACTION_MOVE ) ) 1379 { 1380 m_aControlExchange.setClipboardListener( LINK( this, NavigatorTree, OnClipboardAction ) ); 1381 m_aControlExchange.copyToClipboard( ); 1382 m_bKeyboardCut = sal_True; 1383 1384 // mark all the entries we just "cut" into the clipboard as "nearly moved" 1385 for ( sal_Int32 i=0; i<m_arrCurrentSelection.Count(); ++i ) 1386 { 1387 SvLBoxEntry* pEntry = m_arrCurrentSelection[ (sal_uInt16)i ]; 1388 if ( pEntry ) 1389 { 1390 m_aCutEntries.insert( pEntry ); 1391 pEntry->SetFlags( pEntry->GetFlags() | SV_ENTRYFLAG_SEMITRANSPARENT ); 1392 InvalidateEntry( pEntry ); 1393 } 1394 } 1395 } 1396 } 1397 1398 //------------------------------------------------------------------------ 1399 void NavigatorTree::KeyInput(const ::KeyEvent& rKEvt) 1400 { 1401 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::KeyInput" ); 1402 const KeyCode& rCode = rKEvt.GetKeyCode(); 1403 1404 // delete? 1405 if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE && !rKEvt.GetKeyCode().GetModifier()) 1406 { 1407 DeleteSelection(); 1408 return; 1409 } 1410 1411 // copy'n'paste? 1412 switch ( rCode.GetFunction() ) 1413 { 1414 case KEYFUNC_CUT: 1415 doCut(); 1416 break; 1417 1418 case KEYFUNC_PASTE: 1419 if ( implAcceptPaste() ) 1420 doPaste(); 1421 break; 1422 1423 case KEYFUNC_COPY: 1424 doCopy(); 1425 break; 1426 1427 default: 1428 break; 1429 } 1430 1431 SvTreeListBox::KeyInput(rKEvt); 1432 } 1433 1434 //------------------------------------------------------------------------ 1435 sal_Bool NavigatorTree::EditingEntry( SvLBoxEntry* pEntry, Selection& rSelection ) 1436 { 1437 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::EditingEntry" ); 1438 if (!SvTreeListBox::EditingEntry( pEntry, rSelection )) 1439 return sal_False; 1440 1441 return (pEntry && (pEntry->GetUserData() != NULL)); 1442 // die Wurzel, die ich nicht umbenennen darf, hat als UserData NULL 1443 } 1444 1445 //------------------------------------------------------------------------ 1446 void NavigatorTree::NewForm( SvLBoxEntry* pParentEntry ) 1447 { 1448 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::NewForm" ); 1449 ////////////////////////////////////////////////////////////////////// 1450 // ParentFormData holen 1451 if( !IsFormEntry(pParentEntry) ) 1452 return; 1453 1454 FmFormData* pParentFormData = (FmFormData*)pParentEntry->GetUserData(); 1455 1456 ////////////////////////////////////////////////////////////////////// 1457 // Neue Form erzeugen 1458 Reference< XForm > xNewForm(m_xORB->createInstance(FM_SUN_COMPONENT_FORM), UNO_QUERY); 1459 if (!xNewForm.is()) 1460 return; 1461 1462 FmFormData* pNewFormData = new FmFormData( xNewForm, m_aNavigatorImages, m_aNavigatorImagesHC, pParentFormData ); 1463 1464 ////////////////////////////////////////////////////////////////////// 1465 // Namen setzen 1466 ::rtl::OUString aName = GenerateName(pNewFormData); 1467 pNewFormData->SetText(aName); 1468 1469 Reference< XPropertySet > xPropertySet(xNewForm, UNO_QUERY); 1470 if (!xPropertySet.is()) 1471 return; 1472 try 1473 { 1474 xPropertySet->setPropertyValue( FM_PROP_NAME, makeAny(aName) ); 1475 // a form should always have the command type table as default 1476 xPropertySet->setPropertyValue( FM_PROP_COMMANDTYPE, makeAny(sal_Int32(CommandType::TABLE))); 1477 } 1478 catch ( const Exception& ) 1479 { 1480 DBG_ERROR("NavigatorTree::NewForm : could not set esssential properties !"); 1481 } 1482 1483 1484 ////////////////////////////////////////////////////////////////////// 1485 // Form einfuegen 1486 GetNavModel()->Insert( pNewFormData, LIST_APPEND, sal_True ); 1487 1488 ////////////////////////////////////////////////////////////////////// 1489 // Neue Form als aktive Form setzen 1490 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 1491 if( pFormShell ) 1492 { 1493 InterfaceBag aSelection; 1494 aSelection.insert( Reference< XInterface >( xNewForm, UNO_QUERY ) ); 1495 pFormShell->GetImpl()->setCurrentSelection( aSelection ); 1496 1497 pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_PROPERTIES,sal_True,sal_True); 1498 } 1499 GetNavModel()->SetModified(); 1500 1501 ////////////////////////////////////////////////////////////////////// 1502 // In EditMode schalten 1503 SvLBoxEntry* pNewEntry = FindEntry( pNewFormData ); 1504 EditEntry( pNewEntry ); 1505 } 1506 1507 //------------------------------------------------------------------------ 1508 FmControlData* NavigatorTree::NewControl( const ::rtl::OUString& rServiceName, SvLBoxEntry* pParentEntry, sal_Bool bEditName ) 1509 { 1510 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::NewControl" ); 1511 ////////////////////////////////////////////////////////////////////// 1512 // ParentForm holen 1513 if (!GetNavModel()->GetFormShell()) 1514 return NULL; 1515 if (!IsFormEntry(pParentEntry)) 1516 return NULL; 1517 1518 FmFormData* pParentFormData = (FmFormData*)pParentEntry->GetUserData();; 1519 Reference< XForm > xParentForm( pParentFormData->GetFormIface()); 1520 1521 ////////////////////////////////////////////////////////////////////// 1522 // Neue Component erzeugen 1523 Reference< XFormComponent > xNewComponent(::comphelper::getProcessServiceFactory()->createInstance(rServiceName), UNO_QUERY); 1524 if (!xNewComponent.is()) 1525 return NULL; 1526 1527 FmControlData* pNewFormControlData = new FmControlData( xNewComponent, m_aNavigatorImages, m_aNavigatorImagesHC, pParentFormData ); 1528 1529 ////////////////////////////////////////////////////////////////////// 1530 // Namen setzen 1531 FmFormView* pFormView = GetNavModel()->GetFormShell()->GetFormView(); 1532 SdrPageView* pPageView = pFormView->GetSdrPageView(); 1533 FmFormPage* pPage = (FmFormPage*)pPageView->GetPage(); 1534 1535 ::rtl::OUString sName = pPage->GetImpl().setUniqueName( xNewComponent, xParentForm ); 1536 1537 pNewFormControlData->SetText( sName ); 1538 1539 ////////////////////////////////////////////////////////////////////// 1540 // FormComponent einfuegen 1541 GetNavModel()->Insert( pNewFormControlData, LIST_APPEND, sal_True ); 1542 GetNavModel()->SetModified(); 1543 1544 if (bEditName) 1545 { 1546 ////////////////////////////////////////////////////////////////////// 1547 // In EditMode schalten 1548 SvLBoxEntry* pNewEntry = FindEntry( pNewFormControlData ); 1549 Select( pNewEntry, sal_True ); 1550 EditEntry( pNewEntry ); 1551 } 1552 1553 return pNewFormControlData; 1554 } 1555 1556 //------------------------------------------------------------------------ 1557 ::rtl::OUString NavigatorTree::GenerateName( FmEntryData* pEntryData ) 1558 { 1559 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::GenerateName" ); 1560 const sal_uInt16 nMaxCount = 99; 1561 ::rtl::OUString aNewName; 1562 1563 ////////////////////////////////////////////////////////////////////// 1564 // BasisNamen erzeugen 1565 UniString aBaseName; 1566 if( pEntryData->ISA(FmFormData) ) 1567 aBaseName = SVX_RES( RID_STR_STDFORMNAME ); 1568 1569 else if( pEntryData->ISA(FmControlData) ) 1570 aBaseName = SVX_RES( RID_STR_CONTROL ); 1571 1572 ////////////////////////////////////////////////////////////////////// 1573 // Neuen Namen erstellen 1574 FmFormData* pFormParentData = (FmFormData*)pEntryData->GetParent(); 1575 1576 for( sal_Int32 i=0; i<nMaxCount; i++ ) 1577 { 1578 aNewName = aBaseName; 1579 if( i>0 ) 1580 { 1581 aNewName += ::rtl::OUString::createFromAscii(" "); 1582 aNewName += ::rtl::OUString::valueOf(i).getStr(); 1583 } 1584 1585 if( GetNavModel()->FindData(aNewName, pFormParentData,sal_False) == NULL ) 1586 break; 1587 } 1588 1589 return aNewName; 1590 } 1591 1592 //------------------------------------------------------------------------ 1593 sal_Bool NavigatorTree::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText ) 1594 { 1595 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::EditedEntry" ); 1596 if (EditingCanceled()) 1597 return sal_True; 1598 1599 GrabFocus(); 1600 FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData(); 1601 sal_Bool bRes = GetNavModel()->Rename( pEntryData, rNewText); 1602 if( !bRes ) 1603 { 1604 m_pEditEntry = pEntry; 1605 nEditEvent = Application::PostUserEvent( LINK(this, NavigatorTree, OnEdit) ); 1606 } else 1607 SetCursor(pEntry, sal_True); 1608 1609 return bRes; 1610 } 1611 1612 //------------------------------------------------------------------------ 1613 IMPL_LINK( NavigatorTree, OnEdit, void*, EMPTYARG ) 1614 { 1615 nEditEvent = 0; 1616 EditEntry( m_pEditEntry ); 1617 m_pEditEntry = NULL; 1618 1619 return 0L; 1620 } 1621 1622 //------------------------------------------------------------------------ 1623 IMPL_LINK( NavigatorTree, OnDropActionTimer, void*, EMPTYARG ) 1624 { 1625 if (--m_aTimerCounter > 0) 1626 return 0L; 1627 1628 switch ( m_aDropActionType ) 1629 { 1630 case DA_EXPANDNODE: 1631 { 1632 SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered); 1633 if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand)) 1634 // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich 1635 // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ... 1636 // aber ich denke, die BK sollte es auch so vertragen 1637 Expand(pToExpand); 1638 1639 // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun 1640 m_aDropActionTimer.Stop(); 1641 } 1642 break; 1643 1644 case DA_SCROLLUP : 1645 ScrollOutputArea( 1 ); 1646 m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS; 1647 break; 1648 1649 case DA_SCROLLDOWN : 1650 ScrollOutputArea( -1 ); 1651 m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS; 1652 break; 1653 1654 } 1655 1656 return 0L; 1657 } 1658 1659 //------------------------------------------------------------------------ 1660 IMPL_LINK(NavigatorTree, OnEntrySelDesel, NavigatorTree*, /*pThis*/) 1661 { 1662 m_sdiState = SDI_DIRTY; 1663 1664 if (IsSelectionHandlingLocked()) 1665 return 0L; 1666 1667 if (m_aSynchronizeTimer.IsActive()) 1668 m_aSynchronizeTimer.Stop(); 1669 1670 m_aSynchronizeTimer.SetTimeout(EXPLORER_SYNC_DELAY); 1671 m_aSynchronizeTimer.Start(); 1672 1673 return 0L; 1674 } 1675 1676 //------------------------------------------------------------------------ 1677 IMPL_LINK(NavigatorTree, OnSynchronizeTimer, void*, EMPTYARG) 1678 { 1679 SynchronizeMarkList(); 1680 return 0L; 1681 } 1682 1683 1684 //------------------------------------------------------------------------ 1685 IMPL_LINK( NavigatorTree, OnClipboardAction, void*, EMPTYARG ) 1686 { 1687 if ( !m_aControlExchange.isClipboardOwner() ) 1688 { 1689 if ( doingKeyboardCut() ) 1690 { 1691 for ( ListBoxEntrySet::const_iterator i = m_aCutEntries.begin(); 1692 i != m_aCutEntries.end(); 1693 ++i 1694 ) 1695 { 1696 SvLBoxEntry* pEntry = *i; 1697 if ( !pEntry ) 1698 continue; 1699 1700 pEntry->SetFlags( pEntry->GetFlags() & ~SV_ENTRYFLAG_SEMITRANSPARENT ); 1701 InvalidateEntry( pEntry ); 1702 } 1703 ListBoxEntrySet aEmpty; 1704 m_aCutEntries.swap( aEmpty ); 1705 1706 m_bKeyboardCut = sal_False; 1707 } 1708 } 1709 return 0L; 1710 } 1711 1712 //------------------------------------------------------------------------ 1713 void NavigatorTree::ShowSelectionProperties(sal_Bool bForce) 1714 { 1715 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::ShowSelectionProperties" ); 1716 // zuerst brauche ich die FormShell 1717 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 1718 if (!pFormShell) 1719 // keine Shell -> ich koennte kein curObject setzen -> raus 1720 return; 1721 1722 CollectSelectionData(SDI_ALL); 1723 DBG_ASSERT( m_nFormsSelected + m_nControlsSelected + (m_bRootSelected ? 1 : 0) == m_arrCurrentSelection.Count(), 1724 "NavigatorTree::ShowSelectionProperties : selection meta data invalid !"); 1725 1726 1727 InterfaceBag aSelection; 1728 sal_Bool bSetSelectionAsMarkList = sal_False; 1729 1730 if (m_bRootSelected) 1731 ; // no properties for the root, neither for single nor for multi selection 1732 else if ( m_nFormsSelected + m_nControlsSelected == 0 ) // none of the two should be less 0 1733 ; // no selection -> no properties 1734 else if ( m_nFormsSelected * m_nControlsSelected != 0 ) 1735 ; // mixed selection -> no properties 1736 else 1737 { // either only forms, or only controls are selected 1738 if (m_arrCurrentSelection.Count() == 1) 1739 { 1740 if (m_nFormsSelected > 0) 1741 { // es ist genau eine Form selektiert 1742 FmFormData* pFormData = (FmFormData*)m_arrCurrentSelection.GetObject(0)->GetUserData(); 1743 aSelection.insert( Reference< XInterface >( pFormData->GetFormIface(), UNO_QUERY ) ); 1744 } 1745 else 1746 { // es ist genau ein Control selektiert (egal ob hidden oder normal) 1747 FmEntryData* pEntryData = (FmEntryData*)m_arrCurrentSelection.GetObject(0)->GetUserData(); 1748 1749 aSelection.insert( Reference< XInterface >( pEntryData->GetElement(), UNO_QUERY ) ); 1750 } 1751 } 1752 else 1753 { // wir haben eine MultiSelection, also muessen wir ein MultiSet dafuer aufbauen 1754 if (m_nFormsSelected > 0) 1755 { // ... nur Forms 1756 // erstmal die PropertySet-Interfaces der Forms einsammeln 1757 for ( sal_Int32 i = 0; i < m_nFormsSelected; ++i ) 1758 { 1759 FmFormData* pFormData = (FmFormData*)m_arrCurrentSelection.GetObject((sal_uInt16)i)->GetUserData(); 1760 aSelection.insert( pFormData->GetPropertySet().get() ); 1761 } 1762 } 1763 else 1764 { // ... nur Controls 1765 if (m_nHiddenControls == m_nControlsSelected) 1766 { // ein MultiSet fuer die Properties der hidden controls 1767 for ( sal_Int32 i = 0; i < m_nHiddenControls; ++i ) 1768 { 1769 FmEntryData* pEntryData = (FmEntryData*)m_arrCurrentSelection.GetObject((sal_uInt16)i)->GetUserData(); 1770 aSelection.insert( pEntryData->GetPropertySet().get() ); 1771 } 1772 } 1773 else if (m_nHiddenControls == 0) 1774 { // nur normale Controls 1775 bSetSelectionAsMarkList = sal_True; 1776 } 1777 } 1778 } 1779 1780 } 1781 1782 // und dann meine Form und mein SelObject 1783 if ( bSetSelectionAsMarkList ) 1784 pFormShell->GetImpl()->setCurrentSelectionFromMark( pFormShell->GetFormView()->GetMarkedObjectList() ); 1785 else 1786 pFormShell->GetImpl()->setCurrentSelection( aSelection ); 1787 1788 if ( pFormShell->GetImpl()->IsPropBrwOpen() || bForce ) 1789 { 1790 // und jetzt kann ich das Ganze dem PropertyBrowser uebergeben 1791 pFormShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON ); 1792 } 1793 } 1794 1795 //------------------------------------------------------------------------ 1796 void NavigatorTree::DeleteSelection() 1797 { 1798 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::DeleteSelection" ); 1799 // die Root darf ich natuerlich nicht mitloeschen 1800 sal_Bool bRootSelected = IsSelected(m_pRootEntry); 1801 sal_uIntPtr nSelectedEntries = GetSelectionCount(); 1802 if (bRootSelected && (nSelectedEntries > 1)) // die Root plus andere Elemente ? 1803 Select(m_pRootEntry, sal_False); // ja -> die Root raus 1804 1805 if ((nSelectedEntries == 0) || bRootSelected) // immer noch die Root ? 1806 return; // -> sie ist das einzige selektierte -> raus 1807 1808 DBG_ASSERT(!m_bPrevSelectionMixed, "NavigatorTree::DeleteSelection() : loeschen nicht erlaubt wenn Markierung und Selektion nciht konsistent"); 1809 1810 // ich brauche unten das FormModel ... 1811 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 1812 if (!pFormShell) 1813 return; 1814 FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; 1815 if (!pFormModel) 1816 return; 1817 1818 // jetzt muss ich noch die DeleteList etwas absichern : wenn man ein Formular und ein abhaengiges 1819 // Element loescht - und zwar in dieser Reihenfolge - dann ist der SvLBoxEntryPtr des abhaengigen Elementes 1820 // natuerlich schon ungueltig, wenn es geloescht werden soll ... diesen GPF, den es dann mit Sicherheit gibt, 1821 // gilt es zu verhindern, also die 'normalisierte' Liste 1822 CollectSelectionData( SDI_NORMALIZED ); 1823 1824 // see below for why we need this mapping from models to shapes 1825 FmFormView* pFormView = pFormShell->GetFormView(); 1826 SdrPageView* pPageView = pFormView ? pFormView->GetSdrPageView() : NULL; 1827 SdrPage* pPage = pPageView ? pPageView->GetPage() : NULL; 1828 DBG_ASSERT( pPage, "NavigatorTree::DeleteSelection: invalid form page!" ); 1829 1830 MapModelToShape aModelShapes; 1831 if ( pPage ) 1832 collectShapeModelMapping( pPage, aModelShapes ); 1833 1834 // problem: we have to use ExplorerModel::Remove, since only this one properly deletes Form objects. 1835 // But, the controls themself must be deleted via DeleteMarked (else, the Writer has some problems 1836 // somewhere). In case I'd first delete the structure, then the controls, the UNDO would not work 1837 // (since UNDO then would mean to first restore the controls, then the structure, means their parent 1838 // form). The other way round, the EntryDatas would be invalid, if I'd first delete the controls and 1839 // then go on to the strucure. This means I have to delete the forms *after* the normal controls, so 1840 // that during UNDO, they're restored in the proper order. 1841 pFormShell->GetImpl()->EnableTrackProperties(sal_False); 1842 sal_uInt16 i; 1843 for (i = m_arrCurrentSelection.Count(); i>0; --i) 1844 { 1845 FmEntryData* pCurrent = (FmEntryData*)(m_arrCurrentSelection.GetObject(i - 1)->GetUserData()); 1846 1847 // eine Form ? 1848 sal_Bool bIsForm = pCurrent->ISA(FmFormData); 1849 1850 // da ich das Loeschen im folgenden der View ueberlasse und dabei auf deren MarkList aufbaue, im Normalfall aber bei 1851 // einem makierten Formular nur die direkt, nicht die indirekt abhaengigen Controls markiert werden, muss ich das hier 1852 // noch nachholen 1853 if (bIsForm) 1854 MarkViewObj((FmFormData*)pCurrent, sal_True, sal_True); // das zweite sal_True heisst "deep" 1855 1856 // ein hidden control ? 1857 sal_Bool bIsHidden = IsHiddenControl(pCurrent); 1858 1859 // Forms und hidden Controls muss ich behalten, alles andere nicht 1860 if (!bIsForm && !bIsHidden) 1861 { 1862 // well, no form and no hidden control -> we can remove it from m_arrCurrentSelection, as it will 1863 // be deleted automatically. This is because for every model (except forms and hidden control models) 1864 // there exist a shape, which is marked _if_and_only_if_ the model is selected in our tree. 1865 if ( aModelShapes.find( pCurrent->GetElement() ) != aModelShapes.end() ) 1866 { 1867 // if there's a shape for the current entry, then either it is marked or it is in a 1868 // hidden layer (#i28502#), or something like this. 1869 // In the first case, it will be deleted below, in the second case, we currently don't 1870 // delete it, as there's no real (working!) API for this, neither in UNO nor in non-UNO. 1871 m_arrCurrentSelection.Remove( i - 1, 1 ); 1872 } 1873 // In case there is no shape for the current entry, we keep the entry in m_arrCurrentSelection, 1874 // since then we can definately remove it. 1875 // #103597# 1876 } 1877 } 1878 pFormShell->GetImpl()->EnableTrackProperties(sal_True); 1879 1880 // let the view delete the marked controls 1881 pFormShell->GetFormView()->DeleteMarked(); 1882 1883 // start UNDO at this point. Unfortunately, this results in 2 UNDO actions, since DeleteMarked is 1884 // creating an own one. However, if we'd move it before DeleteMarked, Writer does not really like 1885 // this ... :( 1886 // 2004-07-05 - #i31038# - fs@openoffice.org 1887 { 1888 // --------------- 1889 // initialize UNDO 1890 String aUndoStr; 1891 if ( m_arrCurrentSelection.Count() == 1 ) 1892 { 1893 aUndoStr = SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE); 1894 if (m_nFormsSelected) 1895 aUndoStr.SearchAndReplaceAscii( "#", SVX_RES( RID_STR_FORM ) ); 1896 else 1897 // it must be a control (else the root would be selected, but it cannot be deleted) 1898 aUndoStr.SearchAndReplaceAscii( "#", SVX_RES( RID_STR_CONTROL ) ); 1899 } 1900 else 1901 { 1902 aUndoStr = SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE_MULTIPLE); 1903 aUndoStr.SearchAndReplaceAscii( "#", String::CreateFromInt32( m_arrCurrentSelection.Count() ) ); 1904 } 1905 pFormModel->BegUndo(aUndoStr); 1906 } 1907 1908 // remove remaining structure 1909 for (i=0; i<m_arrCurrentSelection.Count(); ++i) 1910 { 1911 FmEntryData* pCurrent = (FmEntryData*)(m_arrCurrentSelection.GetObject(i)->GetUserData()); 1912 1913 // if the entry still has children, we skipped deletion of one of those children. 1914 // This may for instance be because the shape is in a hidden layer, where we're unable 1915 // to remove it 1916 if ( pCurrent->GetChildList()->Count() ) 1917 continue; 1918 1919 // noch ein kleines Problem, bevor ich das ganz loesche : wenn es eine Form ist und die Shell diese als CurrentObject 1920 // kennt, dann muss ich ihr das natuerlich ausreden 1921 if (pCurrent->ISA(FmFormData)) 1922 { 1923 Reference< XForm > xCurrentForm( static_cast< FmFormData* >( pCurrent )->GetFormIface() ); 1924 if ( pFormShell->GetImpl()->getCurrentForm() == xCurrentForm ) // die Shell kennt die zu loeschende Form ? 1925 pFormShell->GetImpl()->forgetCurrentForm(); // -> wegnehmen ... 1926 } 1927 GetNavModel()->Remove(pCurrent, sal_True); 1928 } 1929 pFormModel->EndUndo(); 1930 } 1931 1932 //------------------------------------------------------------------------ 1933 void NavigatorTree::CollectSelectionData(SELDATA_ITEMS sdiHow) 1934 { 1935 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::CollectSelectionData" ); 1936 DBG_ASSERT(sdiHow != SDI_DIRTY, "NavigatorTree::CollectSelectionData : ever thought about your parameter ? DIRTY ?"); 1937 if (sdiHow == m_sdiState) 1938 return; 1939 1940 m_arrCurrentSelection.Remove((sal_uInt16)0, m_arrCurrentSelection.Count()); 1941 m_nFormsSelected = m_nControlsSelected = m_nHiddenControls = 0; 1942 m_bRootSelected = sal_False; 1943 1944 SvLBoxEntry* pSelectionLoop = FirstSelected(); 1945 while (pSelectionLoop) 1946 { 1947 // erst mal die Zaehlung der verschiedenen Elemente 1948 if (pSelectionLoop == m_pRootEntry) 1949 m_bRootSelected = sal_True; 1950 else 1951 { 1952 if (IsFormEntry(pSelectionLoop)) 1953 ++m_nFormsSelected; 1954 else 1955 { 1956 ++m_nControlsSelected; 1957 if (IsHiddenControl((FmEntryData*)(pSelectionLoop->GetUserData()))) 1958 ++m_nHiddenControls; 1959 } 1960 } 1961 1962 if (sdiHow == SDI_NORMALIZED) 1963 { 1964 // alles, was schon einen selektierten Vorfahr hat, nicht mitnehmen 1965 if (pSelectionLoop == m_pRootEntry) 1966 m_arrCurrentSelection.Insert(pSelectionLoop); 1967 else 1968 { 1969 SvLBoxEntry* pParentLoop = GetParent(pSelectionLoop); 1970 while (pParentLoop) 1971 { 1972 // eigentlich muesste ich testen, ob das Parent in der m_arrCurrentSelection steht ... 1973 // Aber wenn es selektiert ist, dann steht es in m_arrCurrentSelection, oder wenigstens einer seiner Vorfahren, 1974 // wenn der auch schon selektiert war. In beiden Faellen reicht also die Abfrage IsSelected 1975 if (IsSelected(pParentLoop)) 1976 break; 1977 else 1978 { 1979 if (m_pRootEntry == pParentLoop) 1980 { 1981 // bis (exclusive) zur Root gab es kein selektiertes Parent -> der Eintrag gehoert in die normalisierte Liste 1982 m_arrCurrentSelection.Insert(pSelectionLoop); 1983 break; 1984 } 1985 else 1986 pParentLoop = GetParent(pParentLoop); 1987 } 1988 } 1989 } 1990 } 1991 else if (sdiHow == SDI_NORMALIZED_FORMARK) 1992 { 1993 SvLBoxEntry* pParent = GetParent(pSelectionLoop); 1994 if (!pParent || !IsSelected(pParent) || IsFormEntry(pSelectionLoop)) 1995 m_arrCurrentSelection.Insert(pSelectionLoop); 1996 } 1997 else 1998 m_arrCurrentSelection.Insert(pSelectionLoop); 1999 2000 2001 pSelectionLoop = NextSelected(pSelectionLoop); 2002 } 2003 2004 m_sdiState = sdiHow; 2005 } 2006 2007 //------------------------------------------------------------------------ 2008 void NavigatorTree::SynchronizeSelection(FmEntryDataArray& arredToSelect) 2009 { 2010 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::SynchronizeSelection" ); 2011 LockSelectionHandling(); 2012 if (arredToSelect.Count() == 0) 2013 { 2014 SelectAll(sal_False); 2015 } 2016 else 2017 { 2018 // erst mal gleiche ich meine aktuelle Selektion mit der geforderten SelectList ab 2019 SvLBoxEntry* pSelection = FirstSelected(); 2020 while (pSelection) 2021 { 2022 FmEntryData* pCurrent = (FmEntryData*)pSelection->GetUserData(); 2023 if (pCurrent != NULL) 2024 { 2025 sal_uInt16 nPosition; 2026 if ( arredToSelect.Seek_Entry(pCurrent, &nPosition) ) 2027 { // der Entry ist schon selektiert, steht aber auch in der SelectList -> er kann aus letzterer 2028 // raus 2029 arredToSelect.Remove(nPosition, 1); 2030 } else 2031 { // der Entry ist selektiert, aber steht nicht in der SelectList -> Selektion rausnehmen 2032 Select(pSelection, sal_False); 2033 // und sichtbar machen (kann ja sein, dass das die einzige Modifikation ist, die ich hier in dem 2034 // ganzen Handler mache, dann sollte das zu sehen sein) 2035 MakeVisible(pSelection); 2036 } 2037 } 2038 else 2039 Select(pSelection, sal_False); 2040 2041 pSelection = NextSelected(pSelection); 2042 } 2043 2044 // jetzt habe ich in der SelectList genau die Eintraege, die noch selektiert werden muessen 2045 // zwei Moeglichkeiten : 1) ich gehe durch die SelectList, besorge mir zu jedem Eintrag meinen SvLBoxEntry 2046 // und selektiere diesen (waere irgendwie intuitiver ;)) 2) ich gehe durch alle meine SvLBoxEntries und selektiere 2047 // genau die, die ich in der SelectList finde 2048 // 1) braucht O(k*n) (k=Laenge der SelectList, n=Anzahl meiner Entries), plus den Fakt, dass FindEntry nicht den 2049 // Pointer auf die UserDaten vergleicht, sondern ein aufwendigeres IsEqualWithoutChilds durchfuehrt 2050 // 2) braucht O(n*log k), dupliziert aber etwas Code (naemlich den aus FindEntry) 2051 // da das hier eine relativ oft aufgerufenen Stelle sein koennte (bei jeder Aenderung in der Markierung in der View !), 2052 // nehme ich doch lieber letzteres 2053 SvLBoxEntry* pLoop = First(); 2054 while( pLoop ) 2055 { 2056 FmEntryData* pCurEntryData = (FmEntryData*)pLoop->GetUserData(); 2057 sal_uInt16 nPosition; 2058 if ( arredToSelect.Seek_Entry(pCurEntryData, &nPosition) ) 2059 { 2060 Select(pLoop, sal_True); 2061 MakeVisible(pLoop); 2062 SetCursor(pLoop, sal_True); 2063 } 2064 2065 pLoop = Next( pLoop ); 2066 } 2067 } 2068 UnlockSelectionHandling(); 2069 } 2070 2071 //------------------------------------------------------------------------ 2072 void NavigatorTree::SynchronizeSelection() 2073 { 2074 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::SynchronizeSelection" ); 2075 // Shell und View 2076 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 2077 if(!pFormShell) return; 2078 2079 FmFormView* pFormView = pFormShell->GetFormView(); 2080 if (!pFormView) return; 2081 2082 GetNavModel()->BroadcastMarkedObjects(pFormView->GetMarkedObjectList()); 2083 } 2084 2085 //------------------------------------------------------------------------ 2086 void NavigatorTree::SynchronizeMarkList() 2087 { 2088 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::SynchronizeMarkList" ); 2089 // die Shell werde ich brauchen ... 2090 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 2091 if (!pFormShell) return; 2092 2093 CollectSelectionData(SDI_NORMALIZED_FORMARK); 2094 2095 // Die View soll jetzt kein Notify bei einer Aenderung der MarkList rauslassen 2096 pFormShell->GetImpl()->EnableTrackProperties(sal_False); 2097 2098 UnmarkAllViewObj(); 2099 2100 for (sal_uInt32 i=0; i<m_arrCurrentSelection.Count(); ++i) 2101 { 2102 SvLBoxEntry* pSelectionLoop = m_arrCurrentSelection.GetObject((sal_uInt16)i); 2103 // Bei Formselektion alle Controls dieser Form markieren 2104 if (IsFormEntry(pSelectionLoop) && (pSelectionLoop != m_pRootEntry)) 2105 MarkViewObj((FmFormData*)pSelectionLoop->GetUserData(), sal_True, sal_False); 2106 2107 // Bei Controlselektion Control-SdrObjects markieren 2108 else if (IsFormComponentEntry(pSelectionLoop)) 2109 { 2110 FmControlData* pControlData = (FmControlData*)pSelectionLoop->GetUserData(); 2111 if (pControlData) 2112 { 2113 ///////////////////////////////////////////////////////////////// 2114 // Beim HiddenControl kann kein Object selektiert werden 2115 Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent()); 2116 if (!xFormComponent.is()) 2117 continue; 2118 Reference< XPropertySet > xSet(xFormComponent, UNO_QUERY); 2119 if (!xSet.is()) 2120 continue; 2121 2122 sal_uInt16 nClassId = ::comphelper::getINT16(xSet->getPropertyValue(FM_PROP_CLASSID)); 2123 if (nClassId != FormComponentType::HIDDENCONTROL) 2124 MarkViewObj(pControlData, sal_True, sal_True); 2125 } 2126 } 2127 } 2128 2129 // wenn der PropertyBrowser offen ist, muss ich den entsprechend meiner Selektion anpassen 2130 // (NICHT entsprechend der MarkList der View : wenn ich ein Formular selektiert habe, sind in der 2131 // View alle zugehoerigen Controls markiert, trotzdem moechte ich natuerlich die Formular-Eigenschaften 2132 // sehen) 2133 ShowSelectionProperties(sal_False); 2134 2135 // Flag an View wieder zuruecksetzen 2136 pFormShell->GetImpl()->EnableTrackProperties(sal_True); 2137 2138 // wenn jetzt genau eine Form selektiert ist, sollte die Shell das als CurrentForm mitbekommen 2139 // (wenn SelectionHandling nicht locked ist, kuemmert sich die View eigentlich in MarkListHasChanged drum, 2140 // aber der Mechanismus greift zum Beispiel nicht, wenn die Form leer ist) 2141 if ((m_arrCurrentSelection.Count() == 1) && (m_nFormsSelected == 1)) 2142 { 2143 FmFormData* pSingleSelectionData = PTR_CAST( FmFormData, static_cast< FmEntryData* >( FirstSelected()->GetUserData() ) ); 2144 DBG_ASSERT( pSingleSelectionData, "NavigatorTree::SynchronizeMarkList: invalid selected form!" ); 2145 if ( pSingleSelectionData ) 2146 { 2147 InterfaceBag aSelection; 2148 aSelection.insert( Reference< XInterface >( pSingleSelectionData->GetFormIface(), UNO_QUERY ) ); 2149 pFormShell->GetImpl()->setCurrentSelection( aSelection ); 2150 } 2151 } 2152 } 2153 2154 //------------------------------------------------------------------------ 2155 sal_Bool NavigatorTree::IsHiddenControl(FmEntryData* pEntryData) 2156 { 2157 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::IsHiddenControl" ); 2158 if (pEntryData == NULL) return sal_False; 2159 2160 Reference< XPropertySet > xProperties( pEntryData->GetPropertySet() ); 2161 if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties)) 2162 { 2163 Any aClassID = xProperties->getPropertyValue( FM_PROP_CLASSID ); 2164 return (::comphelper::getINT16(aClassID) == FormComponentType::HIDDENCONTROL); 2165 } 2166 return sal_False; 2167 } 2168 2169 //------------------------------------------------------------------------ 2170 sal_Bool NavigatorTree::Select( SvLBoxEntry* pEntry, sal_Bool bSelect ) 2171 { 2172 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::Select" ); 2173 if (bSelect == IsSelected(pEntry)) // das passiert manchmal, ich glaube, die Basisklasse geht zu sehr auf Nummer sicher ;) 2174 return sal_True; 2175 2176 return SvTreeListBox::Select(pEntry, bSelect ); 2177 } 2178 2179 //------------------------------------------------------------------------ 2180 void NavigatorTree::UnmarkAllViewObj() 2181 { 2182 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::UnmarkAllViewObj" ); 2183 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 2184 if( !pFormShell ) 2185 return; 2186 FmFormView* pFormView = pFormShell->GetFormView(); 2187 pFormView->UnMarkAll(); 2188 } 2189 //------------------------------------------------------------------------ 2190 void NavigatorTree::MarkViewObj(FmFormData* pFormData, sal_Bool bMark, sal_Bool bDeep ) 2191 { 2192 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::MarkViewObjects" ); 2193 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 2194 if( !pFormShell ) 2195 return; 2196 2197 // first collect all sdrobjects 2198 ::std::set< Reference< XFormComponent > > aObjects; 2199 CollectObjects(pFormData,bDeep,aObjects); 2200 2201 ////////////////////////////////////////////////////////////////////// 2202 // In der Page das entsprechende SdrObj finden und selektieren 2203 FmFormView* pFormView = pFormShell->GetFormView(); 2204 SdrPageView* pPageView = pFormView->GetSdrPageView(); 2205 SdrPage* pPage = pPageView->GetPage(); 2206 //FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( pPage ); 2207 2208 SdrObjListIter aIter( *pPage ); 2209 while ( aIter.IsMore() ) 2210 { 2211 SdrObject* pSdrObject = aIter.Next(); 2212 FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject ); 2213 if ( !pFormObject ) 2214 continue; 2215 2216 Reference< XFormComponent > xControlModel( pFormObject->GetUnoControlModel(),UNO_QUERY ); 2217 if ( xControlModel.is() && aObjects.find(xControlModel) != aObjects.end() && bMark != pFormView->IsObjMarked( pSdrObject ) ) 2218 { 2219 // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first 2220 pFormView->MarkObj( pSdrObject, pPageView, !bMark, sal_False ); 2221 } 2222 } // while ( aIter.IsMore() ) 2223 if ( bMark ) 2224 { 2225 // make the mark visible 2226 ::Rectangle aMarkRect( pFormView->GetAllMarkedRect()); 2227 for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i ) 2228 { 2229 SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i ); 2230 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); 2231 if ( ( OUTDEV_WINDOW == rOutDev.GetOutDevType() ) && !aMarkRect.IsEmpty() ) 2232 { 2233 pFormView->MakeVisible( aMarkRect, (Window&)rOutDev ); 2234 } 2235 } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i ) 2236 } 2237 } 2238 //------------------------------------------------------------------------ 2239 void NavigatorTree::CollectObjects(FmFormData* pFormData, sal_Bool bDeep, ::std::set< Reference< XFormComponent > >& _rObjects) 2240 { 2241 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::MarkViewObjects" ); 2242 FmEntryDataList* pChildList = pFormData->GetChildList(); 2243 FmEntryData* pEntryData; 2244 FmControlData* pControlData; 2245 for( sal_uInt32 i=0; i < pChildList->Count(); ++i ) 2246 { 2247 pEntryData = pChildList->GetObject(i); 2248 if( pEntryData->ISA(FmControlData) ) 2249 { 2250 pControlData = (FmControlData*)pEntryData; 2251 _rObjects.insert(pControlData->GetFormComponent()); 2252 } // if( pEntryData->ISA(FmControlData) ) 2253 else if (bDeep && (pEntryData->ISA(FmFormData))) 2254 CollectObjects((FmFormData*)pEntryData,bDeep,_rObjects); 2255 } // for( sal_uInt32 i=0; i<pChildList->Count(); i++ ) 2256 } 2257 //------------------------------------------------------------------------ 2258 void NavigatorTree::MarkViewObj( FmControlData* pControlData, sal_Bool bMarkHandles, sal_Bool bMark) 2259 { 2260 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "NavigatorTree::MarkViewObj" ); 2261 if( !pControlData ) 2262 return; 2263 FmFormShell* pFormShell = GetNavModel()->GetFormShell(); 2264 if( !pFormShell ) 2265 return; 2266 2267 ////////////////////////////////////////////////////////////////////// 2268 // In der Page das entsprechende SdrObj finden und selektieren 2269 FmFormView* pFormView = pFormShell->GetFormView(); 2270 Reference< XFormComponent > xFormComponent( pControlData->GetFormComponent()); 2271 SdrPageView* pPageView = pFormView->GetSdrPageView(); 2272 SdrPage* pPage = pPageView->GetPage(); 2273 2274 bool bPaint = false; 2275 SdrObjListIter aIter( *pPage ); 2276 while ( aIter.IsMore() ) 2277 { 2278 SdrObject* pSdrObject = aIter.Next(); 2279 FmFormObj* pFormObject = FmFormObj::GetFormObject( pSdrObject ); 2280 if ( !pFormObject ) 2281 continue; 2282 2283 Reference< XInterface > xControlModel( pFormObject->GetUnoControlModel() ); 2284 if ( xControlModel != xFormComponent ) 2285 continue; 2286 2287 // mark the object 2288 if ( bMark != pFormView->IsObjMarked( pSdrObject ) ) 2289 // unfortunately, the writer doesn't like marking an already-marked object, again, so reset the mark first 2290 pFormView->MarkObj( pSdrObject, pPageView, !bMark, sal_False ); 2291 2292 if ( !bMarkHandles || !bMark ) 2293 continue; 2294 2295 bPaint = true; 2296 2297 } // while ( aIter.IsMore() ) 2298 if ( bPaint ) 2299 { 2300 // make the mark visible 2301 ::Rectangle aMarkRect( pFormView->GetAllMarkedRect()); 2302 for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i ) 2303 { 2304 SdrPaintWindow* pPaintWindow = pFormView->GetPaintWindow( i ); 2305 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); 2306 if ( OUTDEV_WINDOW == rOutDev.GetOutDevType() ) 2307 { 2308 pFormView->MakeVisible( aMarkRect, (Window&)rOutDev ); 2309 } 2310 } // for ( sal_uInt32 i = 0; i < pFormView->PaintWindowCount(); ++i ) 2311 } 2312 } 2313 2314 //............................................................................ 2315 } // namespace svxform 2316 //............................................................................ 2317 2318 2319