Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / navipi / content.cxx
blob69bcec78fa60e6599418e81dbb7f930353a4c887
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svditer.hxx>
21 #include <svx/svdobj.hxx>
22 #include <svx/svdpage.hxx>
23 #include <svx/svdpagv.hxx>
24 #include <svx/svdview.hxx>
25 #include <svx/svdxcgv.hxx>
26 #include <sfx2/linkmgr.hxx>
27 #include <sfx2/docfile.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <vcl/help.hxx>
30 #include <vcl/svapp.hxx>
31 #include <tools/urlobj.hxx>
32 #include <svl/urlbmk.hxx>
33 #include "svtools/svlbitm.hxx"
34 #include <stdlib.h>
36 #include "content.hxx"
37 #include "navipi.hxx"
38 #include "global.hxx"
39 #include "docsh.hxx"
40 #include "scmod.hxx"
41 #include "rangenam.hxx"
42 #include "dbdata.hxx"
43 #include "tablink.hxx"
44 #include "popmenu.hxx"
45 #include "drwlayer.hxx"
46 #include "transobj.hxx"
47 #include "drwtrans.hxx"
48 #include "lnktrans.hxx"
49 #include "formulacell.hxx"
50 #include "dociter.hxx"
51 #include "scresid.hxx"
52 #include "globstr.hrc"
53 #include "navipi.hrc"
54 #include "arealink.hxx"
55 #include "navicfg.hxx"
56 #include "navsett.hxx"
57 #include "postit.hxx"
58 #include "clipparam.hxx"
59 #include "markdata.hxx"
61 using namespace com::sun::star;
63 // Reihenfolge der Kategorien im Navigator -------------------------------------
65 static const sal_uInt16 pTypeList[SC_CONTENT_COUNT] =
67 SC_CONTENT_ROOT, // ROOT (0) muss vorne stehen
68 SC_CONTENT_TABLE,
69 SC_CONTENT_RANGENAME,
70 SC_CONTENT_DBAREA,
71 SC_CONTENT_AREALINK,
72 SC_CONTENT_GRAPHIC,
73 SC_CONTENT_OLEOBJECT,
74 SC_CONTENT_NOTE,
75 SC_CONTENT_DRAWING
78 sal_Bool ScContentTree::bIsInDrag = false;
81 ScDocShell* ScContentTree::GetManualOrCurrent()
83 ScDocShell* pSh = NULL;
84 if ( !aManualDoc.isEmpty() )
86 TypeId aScType = TYPE(ScDocShell);
87 SfxObjectShell* pObjSh = SfxObjectShell::GetFirst( &aScType );
88 while ( pObjSh && !pSh )
90 if ( pObjSh->GetTitle() == aManualDoc )
91 pSh = PTR_CAST( ScDocShell, pObjSh );
92 pObjSh = SfxObjectShell::GetNext( *pObjSh, &aScType );
95 else
97 // Current nur, wenn keine manuell eingestellt ist
98 // (damit erkannt wird, wenn das Dokument nicht mehr existiert)
100 SfxViewShell* pViewSh = SfxViewShell::Current();
101 if ( pViewSh )
103 SfxObjectShell* pObjSh = pViewSh->GetViewFrame()->GetObjectShell();
104 pSh = PTR_CAST( ScDocShell, pObjSh );
108 return pSh;
112 // ScContentTree
115 ScContentTree::ScContentTree( Window* pParent, const ResId& rResId ) :
116 SvTreeListBox ( pParent, rResId ),
117 aEntryImages ( ScResId( RID_IMAGELIST_NAVCONT ) ),
118 nRootType ( SC_CONTENT_ROOT ),
119 bHiddenDoc ( false ),
120 pHiddenDocument ( NULL )
122 sal_uInt16 i;
123 for (i=0; i<SC_CONTENT_COUNT; i++)
124 pPosList[pTypeList[i]] = i; // invers zum suchen
126 pParentWindow = (ScNavigatorDlg*)pParent;
128 pRootNodes[0] = NULL;
129 for (i=1; i<SC_CONTENT_COUNT; i++)
130 InitRoot(i);
132 SetNodeDefaultImages();
134 SetDoubleClickHdl( LINK( this, ScContentTree, ContentDoubleClickHdl ) );
136 SetStyle( GetStyle() | WB_QUICK_SEARCH );
139 ScContentTree::~ScContentTree()
143 void ScContentTree::InitRoot( sal_uInt16 nType )
145 if ( !nType )
146 return;
148 if ( nRootType && nRootType != nType ) // ausgeblendet ?
150 pRootNodes[nType] = NULL;
151 return;
154 const Image& rImage = aEntryImages.GetImage( nType );
155 OUString aName( ScResId( SCSTR_CONTENT_ROOT + nType ) );
156 // wieder an die richtige Position:
157 sal_uInt16 nPos = nRootType ? 0 : pPosList[nType]-1;
158 SvTreeListEntry* pNew = InsertEntry( aName, rImage, rImage, NULL, false, nPos );
160 pRootNodes[nType] = pNew;
163 void ScContentTree::ClearAll()
165 Clear();
166 for (sal_uInt16 i=1; i<SC_CONTENT_COUNT; i++)
167 InitRoot(i);
170 void ScContentTree::ClearType(sal_uInt16 nType)
172 if (!nType)
173 ClearAll();
174 else
176 SvTreeListEntry* pParent = pRootNodes[nType];
177 if ( !pParent || GetChildCount(pParent) ) // nicht, wenn ohne Children schon da
179 if (pParent)
180 GetModel()->Remove( pParent ); // mit allen Children
181 InitRoot( nType ); // ggf. neu eintragen
186 void ScContentTree::InsertContent( sal_uInt16 nType, const OUString& rValue )
188 if (nType >= SC_CONTENT_COUNT)
190 OSL_FAIL("ScContentTree::InsertContent mit falschem Typ");
191 return;
194 SvTreeListEntry* pParent = pRootNodes[nType];
195 if (pParent)
196 InsertEntry( rValue, pParent );
197 else
199 OSL_FAIL("InsertContent ohne Parent");
203 void ScContentTree::GetEntryIndexes( sal_uInt16& rnRootIndex, sal_uLong& rnChildIndex, SvTreeListEntry* pEntry ) const
205 rnRootIndex = SC_CONTENT_ROOT;
206 rnChildIndex = SC_CONTENT_NOCHILD;
208 if( !pEntry )
209 return;
211 SvTreeListEntry* pParent = GetParent( pEntry );
212 bool bFound = false;
213 for( sal_uInt16 nRoot = 1; !bFound && (nRoot < SC_CONTENT_COUNT); ++nRoot )
215 if( pEntry == pRootNodes[ nRoot ] )
217 rnRootIndex = nRoot;
218 rnChildIndex = ~0UL;
219 bFound = true;
221 else if( pParent && (pParent == pRootNodes[ nRoot ]) )
223 rnRootIndex = nRoot;
225 // search the entry in all child entries of the parent
226 sal_uLong nEntry = 0;
227 SvTreeListEntry* pIterEntry = FirstChild( pParent );
228 while( !bFound && pIterEntry )
230 if ( pEntry == pIterEntry )
232 rnChildIndex = nEntry;
233 bFound = true; // exit the while loop
235 pIterEntry = NextSibling( pIterEntry );
236 ++nEntry;
239 bFound = true; // exit the for loop
244 sal_uLong ScContentTree::GetChildIndex( SvTreeListEntry* pEntry ) const
246 sal_uInt16 nRoot;
247 sal_uLong nChild;
248 GetEntryIndexes( nRoot, nChild, pEntry );
249 return nChild;
252 static OUString lcl_GetDBAreaRange( ScDocument* pDoc, const OUString& rDBName )
254 OUString aRet;
255 if (pDoc)
257 ScDBCollection* pDbNames = pDoc->GetDBCollection();
258 const ScDBData* pData = pDbNames->getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rDBName));
259 if (pData)
261 ScRange aRange;
262 pData->GetArea(aRange);
263 aRet = aRange.Format(SCR_ABS_3D, pDoc);
266 return aRet;
269 IMPL_LINK_NOARG(ScContentTree, ContentDoubleClickHdl)
271 sal_uInt16 nType;
272 sal_uLong nChild;
273 SvTreeListEntry* pEntry = GetCurEntry();
274 GetEntryIndexes( nType, nChild, pEntry );
276 if( pEntry && (nType != SC_CONTENT_ROOT) && (nChild != SC_CONTENT_NOCHILD) )
278 if ( bHiddenDoc )
279 return 0; //! spaeter...
281 OUString aText( GetEntryText( pEntry ) );
283 if ( !aManualDoc.isEmpty() )
284 pParentWindow->SetCurrentDoc( aManualDoc );
286 switch( nType )
288 case SC_CONTENT_TABLE:
289 pParentWindow->SetCurrentTableStr( aText );
290 break;
292 case SC_CONTENT_RANGENAME:
293 pParentWindow->SetCurrentCellStr( aText );
294 break;
296 case SC_CONTENT_DBAREA:
298 // Wenn gleiche Bereichs- und DB-Namen existieren, wird
299 // bei SID_CURRENTCELL der Bereichsname genommen.
300 // DB-Bereiche darum direkt ueber die Adresse anspringen.
302 OUString aRangeStr = lcl_GetDBAreaRange( GetSourceDocument(), aText );
303 if (!aRangeStr.isEmpty())
304 pParentWindow->SetCurrentCellStr( aRangeStr );
306 break;
308 case SC_CONTENT_OLEOBJECT:
309 case SC_CONTENT_GRAPHIC:
310 case SC_CONTENT_DRAWING:
311 pParentWindow->SetCurrentObject( aText );
312 break;
314 case SC_CONTENT_NOTE:
316 ScAddress aPos = GetNotePos( nChild );
317 pParentWindow->SetCurrentTable( aPos.Tab() );
318 pParentWindow->SetCurrentCell( aPos.Col(), aPos.Row() );
320 break;
322 case SC_CONTENT_AREALINK:
324 const ScAreaLink* pLink = GetLink( nChild );
325 if( pLink )
327 ScRange aRange = pLink->GetDestArea();
328 ScDocument* pSrcDoc = GetSourceDocument();
329 OUString aRangeStr(aRange.Format(SCR_ABS_3D, pSrcDoc, pSrcDoc->GetAddressConvention()));
330 pParentWindow->SetCurrentCellStr( aRangeStr );
333 break;
336 ScNavigatorDlg::ReleaseFocus(); // set focus into document
339 return 0;
342 void ScContentTree::MouseButtonDown( const MouseEvent& rMEvt )
344 SvTreeListBox::MouseButtonDown( rMEvt );
345 StoreSettings();
348 void ScContentTree::KeyInput( const KeyEvent& rKEvt )
350 bool bUsed = false;
352 const KeyCode aCode = rKEvt.GetKeyCode();
353 if (aCode.GetCode() == KEY_RETURN)
355 switch (aCode.GetModifier())
357 case KEY_MOD1:
358 ToggleRoot(); // toggle root mode (as in Writer)
359 bUsed = true;
360 break;
361 case 0:
363 SvTreeListEntry* pEntry = GetCurEntry();
364 if( pEntry )
366 sal_uInt16 nType;
367 sal_uLong nChild;
368 GetEntryIndexes( nType, nChild, pEntry );
370 if( (nType != SC_CONTENT_ROOT) && (nChild == SC_CONTENT_NOCHILD) )
372 if ( IsExpanded( pEntry ) )
373 Collapse( pEntry );
374 else
375 Expand( pEntry );
377 else
378 ContentDoubleClickHdl(0); // select content as if double clicked
381 bUsed = true;
383 break;
386 StoreSettings();
388 if( !bUsed )
389 SvTreeListBox::KeyInput(rKEvt);
392 sal_Int8 ScContentTree::AcceptDrop( const AcceptDropEvent& /* rEvt */ )
394 return DND_ACTION_NONE;
397 sal_Int8 ScContentTree::ExecuteDrop( const ExecuteDropEvent& /* rEvt */ )
399 return DND_ACTION_NONE;
402 void ScContentTree::StartDrag( sal_Int8 /* nAction */, const Point& /* rPosPixel */ )
404 DoDrag();
407 void ScContentTree::DragFinished( sal_Int8 /* nAction */ )
411 void ScContentTree::Command( const CommandEvent& rCEvt )
413 bool bDone = false;
415 switch ( rCEvt.GetCommand() )
417 case COMMAND_STARTDRAG:
418 // Aus dem ExecuteDrag heraus kann der Navigator geloescht werden
419 // (beim Umschalten auf einen anderen Dokument-Typ), das wuerde aber
420 // den StarView MouseMove-Handler, der Command() aufruft, umbringen.
421 // Deshalb Drag&Drop asynchron:
423 Application::PostUserEvent( STATIC_LINK( this, ScContentTree, ExecDragHdl ) );
425 bDone = true;
426 break;
428 case COMMAND_CONTEXTMENU:
430 // Drag-Drop Modus
432 PopupMenu aPop;
433 ScPopupMenu aDropMenu( ScResId( RID_POPUP_DROPMODE ) );
434 aDropMenu.CheckItem( RID_DROPMODE_URL + pParentWindow->GetDropMode() );
435 aPop.InsertItem( 1, pParentWindow->GetStrDragMode() );
436 aPop.SetPopupMenu( 1, &aDropMenu );
438 // angezeigtes Dokument
440 ScPopupMenu aDocMenu;
441 aDocMenu.SetMenuFlags( aDocMenu.GetMenuFlags() | MENU_FLAG_NOAUTOMNEMONICS );
442 sal_uInt16 i=0;
443 sal_uInt16 nPos=0;
444 // geladene Dokumente
445 ScDocShell* pCurrentSh = PTR_CAST( ScDocShell, SfxObjectShell::Current() );
446 SfxObjectShell* pSh = SfxObjectShell::GetFirst();
447 while ( pSh )
449 if ( pSh->ISA(ScDocShell) )
451 OUString aName = pSh->GetTitle();
452 OUString aEntry = aName;
453 if ( pSh == pCurrentSh )
454 aEntry += pParentWindow->aStrActive;
455 else
456 aEntry += pParentWindow->aStrNotActive;
457 aDocMenu.InsertItem( ++i, aEntry );
458 if ( !bHiddenDoc && aName == aManualDoc )
459 nPos = i;
461 pSh = SfxObjectShell::GetNext( *pSh );
463 // "aktives Fenster"
464 aDocMenu.InsertItem( ++i, pParentWindow->aStrActiveWin );
465 if (!bHiddenDoc && aManualDoc.isEmpty())
466 nPos = i;
467 // verstecktes Dokument
468 if ( !aHiddenTitle.isEmpty() )
470 OUString aEntry = aHiddenTitle;
471 aEntry += pParentWindow->aStrHidden;
472 aDocMenu.InsertItem( ++i, aEntry );
473 if (bHiddenDoc)
474 nPos = i;
476 aDocMenu.CheckItem( nPos );
477 aPop.InsertItem( 2, pParentWindow->GetStrDisplay() );
478 aPop.SetPopupMenu( 2, &aDocMenu );
480 // ausfuehren
482 aPop.Execute( this, rCEvt.GetMousePosPixel() );
484 if ( aDropMenu.WasHit() ) // Drag-Drop Modus
486 sal_uInt16 nId = aDropMenu.GetSelected();
487 if ( nId >= RID_DROPMODE_URL && nId <= RID_DROPMODE_COPY )
488 pParentWindow->SetDropMode( nId - RID_DROPMODE_URL );
490 else if ( aDocMenu.WasHit() ) // angezeigtes Dokument
492 sal_uInt16 nId = aDocMenu.GetSelected();
493 OUString aName = aDocMenu.GetItemText(nId);
494 SelectDoc( aName );
497 break;
500 if (!bDone)
501 SvTreeListBox::Command(rCEvt);
504 void ScContentTree::RequestHelp( const HelpEvent& rHEvt )
506 bool bDone = false;
507 if( rHEvt.GetMode() & HELPMODE_QUICK )
509 Point aPos( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
510 SvTreeListEntry* pEntry = GetEntry( aPos );
511 if ( pEntry )
513 bool bRet = false;
514 OUString aHelpText;
515 SvTreeListEntry* pParent = GetParent(pEntry);
516 if ( !pParent ) // Top-Level ?
518 aHelpText = OUString::number( GetChildCount(pEntry) ) +
519 " " + GetEntryText(pEntry);
520 bRet = true;
522 else if ( pParent == pRootNodes[SC_CONTENT_NOTE] )
524 aHelpText = GetEntryText(pEntry); // Notizen als Help-Text
525 bRet = true;
527 else if ( pParent == pRootNodes[SC_CONTENT_AREALINK] )
529 sal_uLong nIndex = GetChildIndex(pEntry);
530 if( nIndex != SC_CONTENT_NOCHILD )
532 const ScAreaLink* pLink = GetLink(nIndex);
533 if (pLink)
535 aHelpText = pLink->GetFile(); // Source-Datei als Help-Text
536 bRet = true;
541 if (bRet)
543 SvLBoxTab* pTab;
544 SvLBoxString* pItem = (SvLBoxString*)(GetItem( pEntry, aPos.X(), &pTab ));
545 if( pItem )
547 aPos = GetEntryPosition( pEntry );
548 aPos.X() = GetTabPos( pEntry, pTab );
549 aPos = OutputToScreenPixel(aPos);
550 Size aSize( pItem->GetSize( this, pEntry ) );
552 Rectangle aItemRect( aPos, aSize );
553 Help::ShowQuickHelp( this, aItemRect, aHelpText );
554 bDone = true;
559 if (!bDone)
560 Window::RequestHelp( rHEvt );
563 ScDocument* ScContentTree::GetSourceDocument()
565 if (bHiddenDoc)
566 return pHiddenDocument;
567 else
569 ScDocShell* pSh = GetManualOrCurrent();
570 if (pSh)
571 return pSh->GetDocument();
574 return NULL;
577 void ScContentTree::Refresh( sal_uInt16 nType )
579 if ( bHiddenDoc && !pHiddenDocument )
580 return; // anderes Dokument angezeigt
582 // wenn sich nichts geaendert hat, gleich abbrechen (gegen Geflacker)
584 if ( nType == SC_CONTENT_NOTE )
585 if (!NoteStringsChanged())
586 return;
587 if ( nType == SC_CONTENT_GRAPHIC )
588 if (!DrawNamesChanged(SC_CONTENT_GRAPHIC))
589 return;
590 if ( nType == SC_CONTENT_OLEOBJECT )
591 if (!DrawNamesChanged(SC_CONTENT_OLEOBJECT))
592 return;
593 if ( nType == SC_CONTENT_DRAWING )
594 if (!DrawNamesChanged(SC_CONTENT_DRAWING))
595 return;
597 SetUpdateMode(false);
599 ClearType( nType );
601 if ( !nType || nType == SC_CONTENT_TABLE )
602 GetTableNames();
603 if ( !nType || nType == SC_CONTENT_RANGENAME )
604 GetAreaNames();
605 if ( !nType || nType == SC_CONTENT_DBAREA )
606 GetDbNames();
607 if ( !nType || nType == SC_CONTENT_GRAPHIC )
608 GetGraphicNames();
609 if ( !nType || nType == SC_CONTENT_OLEOBJECT )
610 GetOleNames();
611 if ( !nType || nType == SC_CONTENT_DRAWING )
612 GetDrawingNames();
613 if ( !nType || nType == SC_CONTENT_NOTE )
614 GetNoteStrings();
615 if ( !nType || nType == SC_CONTENT_AREALINK )
616 GetLinkNames();
618 ApplySettings();
619 SetUpdateMode(sal_True);
622 void ScContentTree::GetTableNames()
624 if ( nRootType && nRootType != SC_CONTENT_TABLE ) // ausgeblendet ?
625 return;
627 ScDocument* pDoc = GetSourceDocument();
628 if (!pDoc)
629 return;
631 OUString aName;
632 SCTAB nCount = pDoc->GetTableCount();
633 for ( SCTAB i=0; i<nCount; i++ )
635 pDoc->GetName( i, aName );
636 InsertContent( SC_CONTENT_TABLE, aName );
640 namespace {
642 OUString createLocalRangeName(const OUString& rName, const OUString& rTableName)
644 OUStringBuffer aString (rName);
645 aString.append(OUString(" ("));
646 aString.append(rTableName);
647 aString.append(OUString(")"));
648 return aString.makeStringAndClear();
652 void ScContentTree::GetAreaNames()
654 if ( nRootType && nRootType != SC_CONTENT_RANGENAME ) // ausgeblendet ?
655 return;
657 ScDocument* pDoc = GetSourceDocument();
658 if (!pDoc)
659 return;
661 ScRange aDummy;
662 std::set<OUString> aSet;
663 ScRangeName* pRangeNames = pDoc->GetRangeName();
664 if (!pRangeNames->empty())
666 ScRangeName::const_iterator itrBeg = pRangeNames->begin(), itrEnd = pRangeNames->end();
667 for (ScRangeName::const_iterator itr = itrBeg; itr != itrEnd; ++itr)
669 if (itr->second->IsValidReference(aDummy))
670 aSet.insert(itr->second->GetName());
673 for (SCTAB i = 0; i < pDoc->GetTableCount(); ++i)
675 ScRangeName* pLocalRangeName = pDoc->GetRangeName(i);
676 if (pLocalRangeName && !pLocalRangeName->empty())
678 OUString aTableName;
679 pDoc->GetName(i, aTableName);
680 for (ScRangeName::const_iterator itr = pLocalRangeName->begin(); itr != pLocalRangeName->end(); ++itr)
682 if (itr->second->IsValidReference(aDummy))
683 aSet.insert(createLocalRangeName(itr->second->GetName(), aTableName));
688 if (!aSet.empty())
690 for (std::set<OUString>::iterator itr = aSet.begin();
691 itr != aSet.end(); ++itr)
693 InsertContent(SC_CONTENT_RANGENAME, *itr);
698 void ScContentTree::GetDbNames()
700 if ( nRootType && nRootType != SC_CONTENT_DBAREA ) // ausgeblendet ?
701 return;
703 ScDocument* pDoc = GetSourceDocument();
704 if (!pDoc)
705 return;
707 ScDBCollection* pDbNames = pDoc->GetDBCollection();
708 const ScDBCollection::NamedDBs& rDBs = pDbNames->getNamedDBs();
709 ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
710 for (; itr != itrEnd; ++itr)
712 const OUString& aStrName = itr->GetName();
713 InsertContent(SC_CONTENT_DBAREA, aStrName);
717 bool ScContentTree::IsPartOfType( sal_uInt16 nContentType, sal_uInt16 nObjIdentifier )
719 bool bRet = false;
720 switch ( nContentType )
722 case SC_CONTENT_GRAPHIC:
723 bRet = ( nObjIdentifier == OBJ_GRAF );
724 break;
725 case SC_CONTENT_OLEOBJECT:
726 bRet = ( nObjIdentifier == OBJ_OLE2 );
727 break;
728 case SC_CONTENT_DRAWING:
729 bRet = ( nObjIdentifier != OBJ_GRAF && nObjIdentifier != OBJ_OLE2 ); // everything else
730 break;
731 default:
732 OSL_FAIL("unknown content type");
734 return bRet;
737 void ScContentTree::GetDrawNames( sal_uInt16 nType )
739 if ( nRootType && nRootType != nType ) // ausgeblendet ?
740 return;
742 ScDocument* pDoc = GetSourceDocument();
743 if (!pDoc)
744 return;
746 // iterate in flat mode for groups
747 SdrIterMode eIter = ( nType == SC_CONTENT_DRAWING ) ? IM_FLAT : IM_DEEPNOGROUPS;
749 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
750 SfxObjectShell* pShell = pDoc->GetDocumentShell();
751 if (pDrawLayer && pShell)
753 SCTAB nTabCount = pDoc->GetTableCount();
754 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
756 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
757 OSL_ENSURE(pPage,"Page ?");
758 if (pPage)
760 SdrObjListIter aIter( *pPage, eIter );
761 SdrObject* pObject = aIter.Next();
762 while (pObject)
764 if ( IsPartOfType( nType, pObject->GetObjIdentifier() ) )
766 OUString aName = ScDrawLayer::GetVisibleName( pObject );
767 if (!aName.isEmpty())
768 InsertContent( nType, aName );
771 pObject = aIter.Next();
778 void ScContentTree::GetGraphicNames()
780 GetDrawNames( SC_CONTENT_GRAPHIC );
783 void ScContentTree::GetOleNames()
785 GetDrawNames( SC_CONTENT_OLEOBJECT );
788 void ScContentTree::GetDrawingNames()
790 GetDrawNames( SC_CONTENT_DRAWING );
793 void ScContentTree::GetLinkNames()
795 if ( nRootType && nRootType != SC_CONTENT_AREALINK ) // ausgeblendet ?
796 return;
798 ScDocument* pDoc = GetSourceDocument();
799 if (!pDoc)
800 return;
802 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
803 OSL_ENSURE(pLinkManager, "kein LinkManager am Dokument?");
804 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
805 sal_uInt16 nCount = rLinks.size();
806 for (sal_uInt16 i=0; i<nCount; i++)
808 ::sfx2::SvBaseLink* pBase = *rLinks[i];
809 if (pBase->ISA(ScAreaLink))
810 InsertContent( SC_CONTENT_AREALINK, ((ScAreaLink*)pBase)->GetSource() );
812 // in der Liste die Namen der Quellbereiche
816 const ScAreaLink* ScContentTree::GetLink( sal_uLong nIndex )
818 ScDocument* pDoc = GetSourceDocument();
819 if (!pDoc)
820 return NULL;
822 sal_uLong nFound = 0;
823 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
824 OSL_ENSURE(pLinkManager, "kein LinkManager am Dokument?");
825 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
826 sal_uInt16 nCount = rLinks.size();
827 for (sal_uInt16 i=0; i<nCount; i++)
829 ::sfx2::SvBaseLink* pBase = *rLinks[i];
830 if (pBase->ISA(ScAreaLink))
832 if (nFound == nIndex)
833 return (const ScAreaLink*) pBase;
834 ++nFound;
838 OSL_FAIL("link not found");
839 return NULL;
842 static OUString lcl_NoteString( const ScPostIt& rNote )
844 OUString aText = rNote.GetText();
845 sal_Int32 nAt;
846 while ( (nAt = aText.indexOf( '\n' )) != -1 )
847 aText = aText.replaceAt( nAt, 1, " " );
848 return aText;
851 void ScContentTree::GetNoteStrings()
853 if ( nRootType && nRootType != SC_CONTENT_NOTE ) // ausgeblendet ?
854 return;
856 ScDocument* pDoc = GetSourceDocument();
857 if (!pDoc)
858 return;
860 // loop over cell notes
861 std::vector<sc::NoteEntry> aEntries;
862 pDoc->GetAllNoteEntries(aEntries);
863 std::vector<sc::NoteEntry>::const_iterator it = aEntries.begin(), itEnd = aEntries.end();
864 for (; it != itEnd; ++it)
865 InsertContent(SC_CONTENT_NOTE, lcl_NoteString(*it->mpNote));
868 ScAddress ScContentTree::GetNotePos( sal_uLong nIndex )
870 ScDocument* pDoc = GetSourceDocument();
871 if (!pDoc)
872 return ScAddress();
874 return pDoc->GetNotePosition(nIndex);
877 sal_Bool ScContentTree::NoteStringsChanged()
879 ScDocument* pDoc = GetSourceDocument();
880 if (!pDoc)
881 return false;
883 SvTreeListEntry* pParent = pRootNodes[SC_CONTENT_NOTE];
884 if (!pParent)
885 return false;
887 SvTreeListEntry* pEntry = FirstChild( pParent );
889 std::vector<sc::NoteEntry> aEntries;
890 pDoc->GetAllNoteEntries(aEntries);
891 std::vector<sc::NoteEntry>::const_iterator it = aEntries.begin(), itEnd = aEntries.end();
892 for (; it != itEnd; ++it)
894 const ScPostIt* pNote = it->mpNote;
895 if (!pEntry)
896 return true;
898 if (lcl_NoteString(*pNote) != GetEntryText(pEntry))
899 return true;
901 pEntry = NextSibling(pEntry);
904 if ( pEntry )
905 return true;
907 return false;
910 sal_Bool ScContentTree::DrawNamesChanged( sal_uInt16 nType )
912 ScDocument* pDoc = GetSourceDocument();
913 if (!pDoc)
914 return false;
916 SvTreeListEntry* pParent = pRootNodes[nType];
917 if (!pParent)
918 return false;
920 SvTreeListEntry* pEntry = FirstChild( pParent );
922 // iterate in flat mode for groups
923 SdrIterMode eIter = ( nType == SC_CONTENT_DRAWING ) ? IM_FLAT : IM_DEEPNOGROUPS;
925 sal_Bool bEqual = sal_True;
926 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
927 SfxObjectShell* pShell = pDoc->GetDocumentShell();
928 if (pDrawLayer && pShell)
930 SCTAB nTabCount = pDoc->GetTableCount();
931 for (SCTAB nTab=0; nTab<nTabCount && bEqual; nTab++)
933 SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
934 OSL_ENSURE(pPage,"Page ?");
935 if (pPage)
937 SdrObjListIter aIter( *pPage, eIter );
938 SdrObject* pObject = aIter.Next();
939 while (pObject && bEqual)
941 if ( IsPartOfType( nType, pObject->GetObjIdentifier() ) )
943 if ( !pEntry )
944 bEqual = false;
945 else
947 if ( ScDrawLayer::GetVisibleName( pObject ) != GetEntryText(pEntry) )
948 bEqual = false;
950 pEntry = NextSibling( pEntry );
953 pObject = aIter.Next();
959 if ( pEntry )
960 bEqual = false; // kommt noch was
962 return !bEqual;
965 static bool lcl_GetRange( ScDocument* pDoc, sal_uInt16 nType, const OUString& rName, ScRange& rRange )
967 bool bFound = false;
969 if ( nType == SC_CONTENT_RANGENAME )
971 ScRangeName* pList = pDoc->GetRangeName();
972 if (pList)
974 const ScRangeData* p = pList->findByUpperName(ScGlobal::pCharClass->uppercase(rName));
975 if (p && p->IsValidReference(rRange))
976 bFound = true;
979 else if ( nType == SC_CONTENT_DBAREA )
981 ScDBCollection* pList = pDoc->GetDBCollection();
982 if (pList)
984 const ScDBData* p = pList->getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(rName));
985 if (p)
987 SCTAB nTab;
988 SCCOL nCol1, nCol2;
989 SCROW nRow1, nRow2;
990 p->GetArea(nTab, nCol1, nRow1, nCol2, nRow2);
991 rRange = ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
992 bFound = true;
997 return bFound;
1000 static void lcl_DoDragObject( ScDocShell* pSrcShell, const OUString& rName, sal_uInt16 nType, Window* pWin )
1002 ScDocument* pSrcDoc = pSrcShell->GetDocument();
1003 ScDrawLayer* pModel = pSrcDoc->GetDrawLayer();
1004 if (pModel)
1006 bool bOle = ( nType == SC_CONTENT_OLEOBJECT );
1007 bool bGraf = ( nType == SC_CONTENT_GRAPHIC );
1008 sal_uInt16 nDrawId = sal::static_int_cast<sal_uInt16>( bOle ? OBJ_OLE2 : ( bGraf ? OBJ_GRAF : OBJ_GRUP ) );
1009 SCTAB nTab = 0;
1010 SdrObject* pObject = pModel->GetNamedObject( rName, nDrawId, nTab );
1011 if (pObject)
1013 SdrView aEditView( pModel );
1014 aEditView.ShowSdrPage(aEditView.GetModel()->GetPage(nTab));
1015 SdrPageView* pPV = aEditView.GetSdrPageView();
1016 aEditView.MarkObj(pObject, pPV);
1018 SdrModel* pDragModel = aEditView.GetMarkedObjModel();
1020 TransferableObjectDescriptor aObjDesc;
1021 pSrcShell->FillTransferableObjectDescriptor( aObjDesc );
1022 aObjDesc.maDisplayName = pSrcShell->GetMedium()->GetURLObject().GetURLNoPass();
1023 // maSize is set in ScDrawTransferObj ctor
1025 ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pDragModel, pSrcShell, aObjDesc );
1026 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
1028 pTransferObj->SetDragSourceObj( pObject, nTab );
1029 pTransferObj->SetDragSourceFlags( SC_DROP_NAVIGATOR );
1031 SC_MOD()->SetDragObject( NULL, pTransferObj );
1032 pWin->ReleaseMouse();
1033 pTransferObj->StartDrag( pWin, DND_ACTION_COPYMOVE | DND_ACTION_LINK );
1038 static void lcl_DoDragCells( ScDocShell* pSrcShell, const ScRange& rRange, sal_uInt16 nFlags, Window* pWin )
1040 ScMarkData aMark;
1041 aMark.SelectTable( rRange.aStart.Tab(), sal_True );
1042 aMark.SetMarkArea( rRange );
1044 ScDocument* pSrcDoc = pSrcShell->GetDocument();
1045 if ( !pSrcDoc->HasSelectedBlockMatrixFragment( rRange.aStart.Col(), rRange.aStart.Row(),
1046 rRange.aEnd.Col(), rRange.aEnd.Row(),
1047 aMark ) )
1049 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
1050 ScClipParam aClipParam(rRange, false);
1051 pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aMark);
1052 // pClipDoc->ExtendMerge( rRange, sal_True );
1054 TransferableObjectDescriptor aObjDesc;
1055 pSrcShell->FillTransferableObjectDescriptor( aObjDesc );
1056 aObjDesc.maDisplayName = pSrcShell->GetMedium()->GetURLObject().GetURLNoPass();
1057 // maSize is set in ScTransferObj ctor
1059 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
1060 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
1062 pTransferObj->SetDragSource( pSrcShell, aMark );
1063 pTransferObj->SetDragSourceFlags( nFlags );
1065 SC_MOD()->SetDragObject( pTransferObj, NULL ); // for internal D&D
1066 pWin->ReleaseMouse();
1067 pTransferObj->StartDrag( pWin, DND_ACTION_COPYMOVE | DND_ACTION_LINK );
1071 void ScContentTree::DoDrag()
1073 ScDocumentLoader* pDocLoader = NULL;
1074 bIsInDrag = sal_True;
1076 ScModule* pScMod = SC_MOD();
1078 sal_uInt16 nType;
1079 sal_uLong nChild;
1080 SvTreeListEntry* pEntry = GetCurEntry();
1081 GetEntryIndexes( nType, nChild, pEntry );
1083 if( pEntry &&
1084 (nChild != SC_CONTENT_NOCHILD) &&
1085 (nType != SC_CONTENT_ROOT) &&
1086 (nType != SC_CONTENT_NOTE) &&
1087 (nType != SC_CONTENT_AREALINK) )
1089 OUString aText( GetEntryText( pEntry ) );
1091 ScDocument* pLocalDoc = NULL; // fuer URL-Drop
1092 OUString aDocName;
1093 if (bHiddenDoc)
1094 aDocName = aHiddenName;
1095 else
1097 ScDocShell* pDocSh = GetManualOrCurrent();
1098 if (pDocSh)
1100 if (pDocSh->HasName())
1101 aDocName = pDocSh->GetMedium()->GetName();
1102 else
1103 pLocalDoc = pDocSh->GetDocument(); // Drop nur in dieses Dokument
1107 bool bDoLinkTrans = false; // use ScLinkTransferObj
1108 OUString aLinkURL; // for ScLinkTransferObj
1109 OUString aLinkText;
1111 sal_uInt16 nDropMode = pParentWindow->GetDropMode();
1112 switch ( nDropMode )
1114 case SC_DROPMODE_URL:
1116 OUString aUrl = aDocName + "#" + aText;
1118 pScMod->SetDragJump( pLocalDoc, aUrl, aText );
1120 if (!aDocName.isEmpty())
1122 // provide URL to outside only if the document has a name
1123 // (without name, only internal D&D via SetDragJump)
1125 aLinkURL = aUrl;
1126 aLinkText = aText;
1128 bDoLinkTrans = true;
1130 break;
1131 case SC_DROPMODE_LINK:
1133 if ( !aDocName.isEmpty() ) // link only to named documents
1135 // for internal D&D, set flag to insert a link
1137 switch ( nType )
1139 case SC_CONTENT_TABLE:
1140 pScMod->SetDragLink( aDocName, aText, EMPTY_OUSTRING );
1141 bDoLinkTrans = true;
1142 break;
1143 case SC_CONTENT_RANGENAME:
1144 case SC_CONTENT_DBAREA:
1145 pScMod->SetDragLink( aDocName, EMPTY_OUSTRING, aText );
1146 bDoLinkTrans = true;
1147 break;
1149 // other types cannot be linked
1153 break;
1154 case SC_DROPMODE_COPY:
1156 ScDocShell* pSrcShell = NULL;
1157 if ( bHiddenDoc )
1159 OUString aFilter, aOptions;
1160 OUString aURL = aHiddenName;
1161 pDocLoader = new ScDocumentLoader( aURL, aFilter, aOptions );
1162 if (!pDocLoader->IsError())
1163 pSrcShell = pDocLoader->GetDocShell();
1165 else
1166 pSrcShell = GetManualOrCurrent();
1168 if ( pSrcShell )
1170 ScDocument* pSrcDoc = pSrcShell->GetDocument();
1171 if ( nType == SC_CONTENT_RANGENAME || nType == SC_CONTENT_DBAREA )
1173 ScRange aRange;
1174 if ( lcl_GetRange( pSrcDoc, nType, aText, aRange ) )
1176 lcl_DoDragCells( pSrcShell, aRange, SC_DROP_NAVIGATOR, this );
1179 else if ( nType == SC_CONTENT_TABLE )
1181 SCTAB nTab;
1182 if ( pSrcDoc->GetTable( aText, nTab ) )
1184 ScRange aRange( 0,0,nTab, MAXCOL,MAXROW,nTab );
1185 lcl_DoDragCells( pSrcShell, aRange, SC_DROP_NAVIGATOR | SC_DROP_TABLE, this );
1188 else if ( nType == SC_CONTENT_GRAPHIC || nType == SC_CONTENT_OLEOBJECT ||
1189 nType == SC_CONTENT_DRAWING )
1191 lcl_DoDragObject( pSrcShell, aText, nType, this );
1193 // in ExecuteDrag kann der Navigator geloescht worden sein
1194 // -> nicht mehr auf Member zugreifen !!!
1198 break;
1201 if (bDoLinkTrans)
1203 ScLinkTransferObj* pTransferObj = new ScLinkTransferObj;
1204 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
1206 if ( !aLinkURL.isEmpty() )
1207 pTransferObj->SetLinkURL( aLinkURL, aLinkText );
1209 // SetDragJump / SetDragLink has been done above
1211 ReleaseMouse();
1212 pTransferObj->StartDrag( this, DND_ACTION_COPYMOVE | DND_ACTION_LINK );
1216 bIsInDrag = false; // static Member
1218 delete pDocLoader; // falls Dokument zum Draggen geladen wurde
1221 IMPL_STATIC_LINK(ScContentTree, ExecDragHdl, void*, EMPTYARG)
1223 // als Link, damit asynchron ohne ImpMouseMoveMsg auf dem Stack auch der
1224 // Navigator geloescht werden darf
1226 pThis->DoDrag();
1227 return 0;
1230 sal_Bool ScContentTree::LoadFile( const OUString& rUrl )
1232 OUString aDocName = rUrl;
1233 sal_Int32 nPos = aDocName.indexOf('#');
1234 if ( nPos != -1 )
1235 aDocName = aDocName.copy(0, nPos); // nur der Name, ohne #...
1237 sal_Bool bReturn = false;
1238 OUString aURL = aDocName;
1239 OUString aFilter, aOptions;
1240 ScDocumentLoader aLoader( aURL, aFilter, aOptions );
1241 if ( !aLoader.IsError() )
1243 bHiddenDoc = sal_True;
1244 aHiddenName = aDocName;
1245 aHiddenTitle = aLoader.GetTitle();
1246 pHiddenDocument = aLoader.GetDocument();
1248 Refresh(); // Inhalte aus geladenem Dokument holen
1250 pHiddenDocument = NULL;
1252 pParentWindow->GetDocNames( &aHiddenTitle ); // Liste fuellen
1255 // Dokument wird im dtor von ScDocumentLoader wieder geschlossen
1257 return bReturn;
1260 void ScContentTree::InitWindowBits( sal_Bool bButtons )
1262 WinBits nFlags = GetStyle()|WB_CLIPCHILDREN|WB_HSCROLL;
1263 if (bButtons)
1264 nFlags |= WB_HASBUTTONS|WB_HASBUTTONSATROOT;
1266 SetStyle( nFlags );
1269 void ScContentTree::SetRootType( sal_uInt16 nNew )
1271 if ( nNew != nRootType )
1273 nRootType = nNew;
1274 InitWindowBits( nNew == 0 );
1275 Refresh();
1277 ScNavipiCfg& rCfg = SC_MOD()->GetNavipiCfg();
1278 rCfg.SetRootType( nRootType );
1282 void ScContentTree::ToggleRoot() // nach Selektion
1284 sal_uInt16 nNew = SC_CONTENT_ROOT;
1285 if ( nRootType == SC_CONTENT_ROOT )
1287 SvTreeListEntry* pEntry = GetCurEntry();
1288 if (pEntry)
1290 SvTreeListEntry* pParent = GetParent(pEntry);
1291 for (sal_uInt16 i=1; i<SC_CONTENT_COUNT; i++)
1292 if ( pEntry == pRootNodes[i] || pParent == pRootNodes[i] )
1293 nNew = i;
1297 SetRootType( nNew );
1300 void ScContentTree::ResetManualDoc()
1302 aManualDoc = "";
1303 bHiddenDoc = false;
1305 ActiveDocChanged();
1308 void ScContentTree::ActiveDocChanged()
1310 if ( !bHiddenDoc && aManualDoc.isEmpty() )
1311 Refresh(); // Inhalte nur wenn automatisch
1313 // Listbox muss immer geupdated werden, wegen aktiv-Flag
1315 OUString aCurrent;
1316 if ( bHiddenDoc )
1317 aCurrent = aHiddenTitle;
1318 else
1320 ScDocShell* pSh = GetManualOrCurrent();
1321 if (pSh)
1322 aCurrent = pSh->GetTitle();
1323 else
1325 // eingestelltes Dokument existiert nicht mehr
1327 aManualDoc = ""; // wieder automatisch
1328 Refresh();
1329 pSh = GetManualOrCurrent(); // sollte jetzt aktives sein
1330 if (pSh)
1331 aCurrent = pSh->GetTitle();
1334 pParentWindow->GetDocNames( &aCurrent ); // selektieren
1337 void ScContentTree::SetManualDoc(const OUString& rName)
1339 aManualDoc = rName;
1340 if (!bHiddenDoc)
1342 Refresh();
1343 pParentWindow->GetDocNames( &aManualDoc ); // selektieren
1347 void ScContentTree::SelectDoc(const OUString& rName) // rName wie im Menue/Listbox angezeigt
1349 if ( rName == pParentWindow->aStrActiveWin )
1351 ResetManualDoc();
1352 return;
1355 // "aktiv" oder "inaktiv" weglassen
1357 OUString aRealName = rName;
1358 sal_Int32 nLen = rName.getLength();
1359 sal_Int32 nActiveStart = nLen - pParentWindow->aStrActive.getLength();
1360 if ( rName.copy( nActiveStart ) == pParentWindow->aStrActive )
1361 aRealName = rName.copy( 0, nActiveStart );
1362 sal_Int32 nNotActiveStart = nLen - pParentWindow->aStrNotActive.getLength();
1363 if ( rName.copy( nNotActiveStart ) == pParentWindow->aStrNotActive )
1364 aRealName = rName.copy( 0, nNotActiveStart );
1366 bool bLoaded = false;
1368 // ist es ein normal geladenes Doc ?
1370 SfxObjectShell* pSh = SfxObjectShell::GetFirst();
1371 while ( pSh && !bLoaded )
1373 if ( pSh->ISA(ScDocShell) )
1374 if ( pSh->GetTitle() == aRealName )
1375 bLoaded = true;
1376 pSh = SfxObjectShell::GetNext( *pSh );
1379 if (bLoaded)
1381 bHiddenDoc = false;
1382 SetManualDoc(aRealName);
1384 else if (!aHiddenTitle.isEmpty()) // verstecktes ausgewaehlt
1386 if (!bHiddenDoc)
1387 LoadFile(aHiddenName);
1389 else
1391 OSL_FAIL("SelectDoc: nicht gefunden");
1395 void ScContentTree::ApplySettings()
1397 const ScNavigatorSettings* pSettings = pParentWindow->GetNavigatorSettings();
1398 if( pSettings )
1400 sal_uInt16 nRootSel = pSettings->GetRootSelected();
1401 sal_uLong nChildSel = pSettings->GetChildSelected();
1403 for( sal_uInt16 nEntry = 1; nEntry < SC_CONTENT_COUNT; ++nEntry )
1405 if( pRootNodes[ nEntry ] )
1407 // expand
1408 sal_Bool bExp = pSettings->IsExpanded( nEntry );
1409 if( bExp != IsExpanded( pRootNodes[ nEntry ] ) )
1411 if( bExp )
1412 Expand( pRootNodes[ nEntry ] );
1413 else
1414 Collapse( pRootNodes[ nEntry ] );
1417 // select
1418 if( nRootSel == nEntry )
1420 SvTreeListEntry* pEntry = NULL;
1421 if( bExp && (nChildSel != SC_CONTENT_NOCHILD) )
1422 pEntry = GetEntry( pRootNodes[ nEntry ], nChildSel );
1423 Select( pEntry ? pEntry : pRootNodes[ nEntry ] );
1430 void ScContentTree::StoreSettings() const
1432 ScNavigatorSettings* pSettings = pParentWindow->GetNavigatorSettings();
1433 if( pSettings )
1435 for( sal_uInt16 nEntry = 1; nEntry < SC_CONTENT_COUNT; ++nEntry )
1437 sal_Bool bExp = pRootNodes[ nEntry ] && IsExpanded( pRootNodes[ nEntry ] );
1438 pSettings->SetExpanded( nEntry, bExp );
1440 sal_uInt16 nRoot;
1441 sal_uLong nChild;
1442 GetEntryIndexes( nRoot, nChild, GetCurEntry() );
1443 pSettings->SetRootSelected( nRoot );
1444 pSettings->SetChildSelected( nChild );
1450 //------------------------------------------------------------------------
1457 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */