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