fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / sd / source / ui / view / outlview.cxx
blob3c863013afd00d2cd408b8729a2303ed0402d9dd
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 .
21 #include "OutlineView.hxx"
22 #include <memory>
23 #include <editeng/forbiddencharacterstable.hxx>
24 #include <sfx2/progress.hxx>
25 #include <vcl/wrkwin.hxx>
26 #include <svx/svxids.hrc>
27 #include <editeng/outliner.hxx>
28 #include <editeng/eeitem.hxx>
29 #include <editeng/editstat.hxx>
30 #include <editeng/lrspitem.hxx>
31 #include <svx/svdotext.hxx>
32 #include <sfx2/printer.hxx>
33 #include <sfx2/imagemgr.hxx>
34 #include <sfx2/app.hxx>
35 #include <sfx2/bindings.hxx>
36 #include <svl/itempool.hxx>
37 #include <svl/style.hxx>
38 #include <svx/svdorect.hxx>
39 #include <svx/svdundo.hxx>
40 #include <svl/brdcst.hxx>
41 #include <vcl/msgbox.hxx>
42 #include <editeng/adjustitem.hxx>
43 #include <editeng/tstpitem.hxx>
44 #include <editeng/lspcitem.hxx>
45 #include <editeng/numitem.hxx>
46 #include <editeng/outlobj.hxx>
47 #include <editeng/editeng.hxx>
49 #include <editeng/editobj.hxx>
50 #include <editeng/editund2.hxx>
52 #include <editeng/editview.hxx>
53 #include <editeng/svxfont.hxx>
54 #include <editeng/fhgtitem.hxx>
56 #include "DrawDocShell.hxx"
57 #include "drawdoc.hxx"
58 #include "Window.hxx"
59 #include "sdpage.hxx"
60 #include "pres.hxx"
61 #include "OutlineViewShell.hxx"
62 #include "app.hrc"
63 #include "glob.hrc"
64 #include "sdresid.hxx"
65 #include "Outliner.hxx"
66 #include "strings.hrc"
67 #include "EventMultiplexer.hxx"
68 #include "ViewShellBase.hxx"
69 #include "undo/undoobjects.hxx"
70 #include "undo/undomanager.hxx"
71 #include "stlsheet.hxx"
73 using namespace ::com::sun::star::uno;
74 using namespace ::com::sun::star::frame;
76 namespace sd {
78 // width: DIN A4, two margins à 1 cm each
79 #define OUTLINE_PAPERWIDTH 19000
81 // a progress bar gets displayed when more than
82 // PROCESS_WITH_PROGRESS_THRESHOLD pages are concerned
83 #define PROCESS_WITH_PROGRESS_THRESHOLD 5
85 struct SdParaAndPos
87 Paragraph* pPara;
88 sal_uInt16 nPos;
91 TYPEINIT1( OutlineView, ::sd::View );
94 OutlineView::OutlineView( DrawDocShell& rDocSh, ::Window* pWindow, OutlineViewShell& rOutlineViewSh)
95 : ::sd::View(*rDocSh.GetDoc(), pWindow, &rOutlineViewSh)
96 , mrOutlineViewShell(rOutlineViewSh)
97 , mrOutliner(*mrDoc.GetOutliner(sal_True))
98 , mnPagesToProcess(0)
99 , mnPagesProcessed(0)
100 , mbFirstPaint(sal_True)
101 , mpProgress(NULL)
102 , maDocColor( COL_WHITE )
103 , maLRSpaceItem( 0, 0, 2000, 0, EE_PARA_OUTLLRSPACE )
105 sal_Bool bInitOutliner = sal_False;
107 if (mrOutliner.GetViewCount() == 0)
109 // initialize Outliner: set Reference Device
110 bInitOutliner = sal_True;
111 mrOutliner.Init( OUTLINERMODE_OUTLINEVIEW );
112 mrOutliner.SetRefDevice( SD_MOD()->GetRefDevice( rDocSh ) );
113 sal_uLong nWidth = OUTLINE_PAPERWIDTH;
114 mrOutliner.SetPaperSize(Size(nWidth, 400000000));
117 // insert View into Outliner
118 for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
120 mpOutlinerView[nView] = NULL;
123 mpOutlinerView[0] = new OutlinerView(&mrOutliner, pWindow);
124 Rectangle aNullRect;
125 mpOutlinerView[0]->SetOutputArea(aNullRect);
126 mrOutliner.SetUpdateMode(sal_False);
127 mrOutliner.InsertView(mpOutlinerView[0], LIST_APPEND);
129 onUpdateStyleSettings( true );
131 if (bInitOutliner)
133 // fill Outliner with contents
134 FillOutliner();
137 Link aLink( LINK(this,OutlineView,EventMultiplexerListener) );
138 mrOutlineViewShell.GetViewShellBase().GetEventMultiplexer()->AddEventListener(
139 aLink,
140 tools::EventMultiplexerEvent::EID_CURRENT_PAGE
141 | tools::EventMultiplexerEvent::EID_PAGE_ORDER);
143 LanguageType eLang = mrOutliner.GetDefaultLanguage();
144 maPageNumberFont = OutputDevice::GetDefaultFont( DEFAULTFONT_SANS_UNICODE, eLang, 0 );
145 maPageNumberFont.SetHeight( 500 );
147 maBulletFont.SetColor( COL_AUTO );
148 maBulletFont.SetHeight( 1000 );
149 maBulletFont.SetCharSet(RTL_TEXTENCODING_MS_1252); // and replacing other values by standard
150 maBulletFont.SetName( OUString( "StarSymbol" ) );
151 maBulletFont.SetWeight(WEIGHT_NORMAL);
152 maBulletFont.SetUnderline(UNDERLINE_NONE);
153 maBulletFont.SetStrikeout(STRIKEOUT_NONE);
154 maBulletFont.SetItalic(ITALIC_NONE);
155 maBulletFont.SetOutline(sal_False);
156 maBulletFont.SetShadow(sal_False);
159 Reference<XFrame> xFrame (mrOutlineViewShell.GetViewShellBase().GetFrame()->GetTopFrame().GetFrameInterface(), UNO_QUERY);
161 const OUString aSlotURL( ".uno:ShowSlide" );
162 maSlideImage = GetImage( xFrame, aSlotURL, true );
164 // Tell undo manager of the document about the undo manager of the
165 // outliner, so that the former can synchronize with the later.
166 sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager());
167 if (pDocUndoMgr != NULL)
168 pDocUndoMgr->SetLinkedUndoManager(&mrOutliner.GetUndoManager());
172 * Destructor, restore Links, clear Oultiner
174 OutlineView::~OutlineView()
176 DBG_ASSERT(maDragAndDropModelGuard.get() == 0, "sd::OutlineView::~OutlineView(), prior drag operation not finished correctly!" );
178 Link aLink( LINK(this,OutlineView,EventMultiplexerListener) );
179 mrOutlineViewShell.GetViewShellBase().GetEventMultiplexer()->RemoveEventListener( aLink );
180 DisconnectFromApplication();
182 if( mpProgress )
183 delete mpProgress;
185 // unregister OutlinerViews and destroy them
186 for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
188 if (mpOutlinerView[nView] != NULL)
190 mrOutliner.RemoveView( mpOutlinerView[nView] );
191 delete mpOutlinerView[nView];
192 mpOutlinerView[nView] = NULL;
196 if (mrOutliner.GetViewCount() == 0)
198 // uninitialize Outliner: enable color display
199 ResetLinks();
200 sal_uLong nCntrl = mrOutliner.GetControlWord();
201 mrOutliner.SetUpdateMode(sal_False); // otherwise there will be drawn on SetControlWord
202 mrOutliner.SetControlWord(nCntrl & ~EE_CNTRL_NOCOLORS);
203 SvtAccessibilityOptions aOptions;
204 mrOutliner.ForceAutoColor( aOptions.GetIsAutomaticFontColor() );
205 mrOutliner.Clear();
212 void OutlineView::ConnectToApplication (void)
214 mrOutlineViewShell.GetActiveWindow()->GrabFocus();
215 Application::AddEventListener(LINK(this, OutlineView, AppEventListenerHdl));
221 void OutlineView::DisconnectFromApplication (void)
223 Application::RemoveEventListener(LINK(this, OutlineView, AppEventListenerHdl));
230 void OutlineView::Paint(const Rectangle& rRect, ::sd::Window* pWin)
232 OutlinerView* pOlView = GetViewByWindow(pWin);
234 if (pOlView)
236 pOlView->HideCursor();
237 pOlView->Paint(rRect);
239 pOlView->ShowCursor(mbFirstPaint);
241 mbFirstPaint = sal_False;
245 void OutlineView::InvalidateSlideNumberArea()
250 * Window size was changed
253 void OutlineView::AdjustPosSizePixel(const Point &,const Size &,::sd::Window*)
258 void OutlineView::AddWindowToPaintView(OutputDevice* pWin)
260 sal_Bool bAdded = sal_False;
261 sal_Bool bValidArea = sal_False;
262 Rectangle aOutputArea;
263 const Color aWhiteColor( COL_WHITE );
264 sal_uInt16 nView = 0;
266 while (nView < MAX_OUTLINERVIEWS && !bAdded)
268 if (mpOutlinerView[nView] == NULL)
270 mpOutlinerView[nView] = new OutlinerView(&mrOutliner, dynamic_cast< ::sd::Window* >(pWin));
271 mpOutlinerView[nView]->SetBackgroundColor( aWhiteColor );
272 mrOutliner.InsertView(mpOutlinerView[nView], LIST_APPEND);
273 bAdded = sal_True;
275 if (bValidArea)
277 mpOutlinerView[nView]->SetOutputArea(aOutputArea);
280 else if (!bValidArea)
282 aOutputArea = mpOutlinerView[nView]->GetOutputArea();
283 bValidArea = sal_True;
286 nView++;
289 // white background in Outliner
290 pWin->SetBackground( Wallpaper( aWhiteColor ) );
292 ::sd::View::AddWindowToPaintView(pWin);
296 void OutlineView::DeleteWindowFromPaintView(OutputDevice* pWin)
298 sal_Bool bRemoved = sal_False;
299 sal_uInt16 nView = 0;
300 ::Window* pWindow;
302 while (nView < MAX_OUTLINERVIEWS && !bRemoved)
304 if (mpOutlinerView[nView] != NULL)
306 pWindow = mpOutlinerView[nView]->GetWindow();
308 if (pWindow == pWin)
310 mrOutliner.RemoveView( mpOutlinerView[nView] );
311 delete mpOutlinerView[nView];
312 mpOutlinerView[nView] = NULL;
313 bRemoved = sal_True;
317 nView++;
320 ::sd::View::DeleteWindowFromPaintView(pWin);
324 * Return a pointer to the OutlinerView corresponding to the window
326 OutlinerView* OutlineView::GetViewByWindow (::Window* pWin) const
328 OutlinerView* pOlView = NULL;
329 for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
331 if (mpOutlinerView[nView] != NULL)
333 if ( pWin == mpOutlinerView[nView]->GetWindow() )
335 pOlView = mpOutlinerView[nView];
339 return (pOlView);
344 * Return the title before a random paragraph
346 Paragraph* OutlineView::GetPrevTitle(const Paragraph* pPara)
348 sal_Int32 nPos = mrOutliner.GetAbsPos(const_cast<Paragraph*>(pPara));
350 if (nPos > 0)
352 while(nPos)
354 pPara = mrOutliner.GetParagraph(--nPos);
355 if( mrOutliner.HasParaFlag(pPara, PARAFLAG_ISPAGE) )
357 return const_cast< Paragraph* >( pPara );
362 return NULL;
366 * Return the title after a random paragraph
368 Paragraph* OutlineView::GetNextTitle(const Paragraph* pPara)
370 Paragraph* pResult = const_cast< Paragraph* >( pPara );
372 sal_Int32 nPos = mrOutliner.GetAbsPos(pResult);
376 pResult = mrOutliner.GetParagraph(++nPos);
377 if( pResult && mrOutliner.HasParaFlag(pResult, PARAFLAG_ISPAGE) )
378 return pResult;
380 while( pResult );
382 return NULL;
386 * Handler for inserting pages (paragraphs)
388 IMPL_LINK( OutlineView, ParagraphInsertedHdl, ::Outliner *, pOutliner )
390 // we get calls to this handler during binary insert of drag and drop contents but
391 // we ignore it here and handle it later in OnEndPasteOrDrop()
392 if( maDragAndDropModelGuard.get() == 0 )
394 OutlineViewPageChangesGuard aGuard(this);
396 Paragraph* pPara = pOutliner->GetHdlParagraph();
398 sal_Int32 nAbsPos = mrOutliner.GetAbsPos( pPara );
400 UpdateParagraph( nAbsPos );
402 if( (nAbsPos == 0) || mrOutliner.HasParaFlag(pPara,PARAFLAG_ISPAGE) || mrOutliner.HasParaFlag(mrOutliner.GetParagraph( nAbsPos-1 ), PARAFLAG_ISPAGE) )
404 InsertSlideForParagraph( pPara );
405 InvalidateSlideNumberArea();
409 return 0;
412 /** creates and inserts an empty slide for the given paragraph */
413 SdPage* OutlineView::InsertSlideForParagraph( Paragraph* pPara )
415 DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::InsertSlideForParagraph(), model change without undo?!" );
417 OutlineViewPageChangesGuard aGuard(this);
419 mrOutliner.SetParaFlag( pPara, PARAFLAG_ISPAGE );
420 // how many titles are there before the new title paragraph?
421 sal_uLong nExample = 0L; // position of the "example" page
422 sal_uLong nTarget = 0L; // position of insertion
423 while(pPara)
425 pPara = GetPrevTitle(pPara);
426 if (pPara)
427 nTarget++;
430 // if a new paragraph is created via RETURN before the first paragraph, the
431 // Outliner reports the old paragraph (which was moved down) as a new
432 // paragraph
433 if (nTarget == 1)
435 String aTest(mrOutliner.GetText( mrOutliner.GetParagraph( 0 ) ));
436 if (aTest.Len() == 0)
438 nTarget = 0;
443 // the "example" page is the previous page - if it is available
444 if (nTarget > 0)
446 nExample = nTarget - 1;
448 sal_uInt16 nPageCount = mrDoc.GetSdPageCount( PK_STANDARD );
449 if( nExample >= nPageCount )
450 nExample = nPageCount - 1;
453 /**********************************************************************
454 * All the time, a standard page is created before a notes page.
455 * It is ensured that after each standard page the corresponding notes page
456 * follows. A handout page is exactly one handout page.
457 **********************************************************************/
459 // this page is exemplary
460 SdPage* pExample = (SdPage*)mrDoc.GetSdPage((sal_uInt16)nExample, PK_STANDARD);
461 SdPage* pPage = (SdPage*)mrDoc.AllocPage(sal_False);
463 pPage->SetLayoutName(pExample->GetLayoutName());
465 // insert (page)
466 mrDoc.InsertPage(pPage, (sal_uInt16)(nTarget) * 2 + 1);
467 if( isRecordingUndo() )
468 AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoNewPage(*pPage));
470 // assign a master page to the standard page
471 pPage->TRG_SetMasterPage(pExample->TRG_GetMasterPage());
473 // set page size
474 pPage->SetSize(pExample->GetSize());
475 pPage->SetBorder( pExample->GetLftBorder(),
476 pExample->GetUppBorder(),
477 pExample->GetRgtBorder(),
478 pExample->GetLwrBorder() );
480 // create new presentation objects (after <Title> or <Title with subtitle>
481 // follows <Title with outline>, otherwise apply the layout of the previous
482 // page
483 AutoLayout eAutoLayout = pExample->GetAutoLayout();
484 if (eAutoLayout == AUTOLAYOUT_TITLE ||
485 eAutoLayout == AUTOLAYOUT_ONLY_TITLE)
487 pPage->SetAutoLayout(AUTOLAYOUT_ENUM, sal_True);
489 else
491 pPage->SetAutoLayout(pExample->GetAutoLayout(), sal_True);
494 /**********************************************************************
495 |* now the notes page
496 \*********************************************************************/
497 pExample = (SdPage*)mrDoc.GetSdPage((sal_uInt16)nExample, PK_NOTES);
498 SdPage* pNotesPage = (SdPage*)mrDoc.AllocPage(sal_False);
500 pNotesPage->SetLayoutName(pExample->GetLayoutName());
502 pNotesPage->SetPageKind(PK_NOTES);
504 // insert (notes page)
505 mrDoc.InsertPage(pNotesPage, (sal_uInt16)(nTarget) * 2 + 2);
506 if( isRecordingUndo() )
507 AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoNewPage(*pNotesPage));
509 // assign a master page to the notes page
510 pNotesPage->TRG_SetMasterPage(pExample->TRG_GetMasterPage());
512 // set page size, there must be already one page available
513 pNotesPage->SetSize(pExample->GetSize());
514 pNotesPage->SetBorder( pExample->GetLftBorder(),
515 pExample->GetUppBorder(),
516 pExample->GetRgtBorder(),
517 pExample->GetLwrBorder() );
519 // create presentation objects
520 pNotesPage->SetAutoLayout(pExample->GetAutoLayout(), sal_True);
522 mrOutliner.UpdateFields();
524 return pPage;
528 * Handler for deleting pages (paragraphs)
530 IMPL_LINK( OutlineView, ParagraphRemovingHdl, ::Outliner *, pOutliner )
532 DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::ParagraphRemovingHdl(), model change without undo?!" );
534 OutlineViewPageChangesGuard aGuard(this);
536 Paragraph* pPara = pOutliner->GetHdlParagraph();
537 if( pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) )
539 // how many titles are in front of the title paragraph in question?
540 sal_uLong nPos = 0L;
541 while(pPara)
543 pPara = GetPrevTitle(pPara);
544 if (pPara) nPos++;
547 // delete page and notes page
548 sal_uInt16 nAbsPos = (sal_uInt16)nPos * 2 + 1;
549 SdrPage* pPage = mrDoc.GetPage(nAbsPos);
550 if( isRecordingUndo() )
551 AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
552 mrDoc.RemovePage(nAbsPos);
554 nAbsPos = (sal_uInt16)nPos * 2 + 1;
555 pPage = mrDoc.GetPage(nAbsPos);
556 if( isRecordingUndo() )
557 AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
558 mrDoc.RemovePage(nAbsPos);
560 // progress display if necessary
561 if (mnPagesToProcess)
563 mnPagesProcessed++;
565 if(mpProgress)
566 mpProgress->SetState(mnPagesProcessed);
568 if (mnPagesProcessed == mnPagesToProcess)
570 if(mpProgress)
572 delete mpProgress;
573 mpProgress = NULL;
575 mnPagesToProcess = 0;
576 mnPagesProcessed = 0;
579 pOutliner->UpdateFields();
582 InvalidateSlideNumberArea();
584 return 0;
588 * Handler for changing the indentation depth of paragraphs (requires inserting
589 * or deleting of pages in some cases)
591 IMPL_LINK( OutlineView, DepthChangedHdl, ::Outliner *, pOutliner )
593 DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::DepthChangedHdl(), no undo for model change?!" );
595 OutlineViewPageChangesGuard aGuard(this);
597 Paragraph* pPara = pOutliner->GetHdlParagraph();
598 if( pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) && ((pOutliner->GetPrevFlags() & PARAFLAG_ISPAGE) == 0) )
600 // the current paragraph is transformed into a slide
602 mrOutliner.SetDepth( pPara, -1 );
604 // are multiple level 1 paragraphs being brought to level 0 and we
605 // should start a progress view or a timer and didn't already?
606 if (mnPagesToProcess == 0)
608 Window* pActWin = mrOutlineViewShell.GetActiveWindow();
609 OutlinerView* pOlView = GetViewByWindow(pActWin);
611 std::vector<Paragraph*> aSelList;
612 pOlView->CreateSelectionList(aSelList);
614 Paragraph *pParagraph = NULL;
615 for (std::vector<Paragraph*>::const_iterator iter = aSelList.begin(); iter != aSelList.end(); ++iter)
617 pParagraph = *iter;
619 if( !pOutliner->HasParaFlag( pParagraph, PARAFLAG_ISPAGE ) &&
620 (pOutliner->GetDepth( pOutliner->GetAbsPos( pParagraph ) ) <= 0) )
621 mnPagesToProcess++;
624 mnPagesToProcess++; // the paragraph being in level 0 already
625 // should be included
626 mnPagesProcessed = 0;
628 if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD)
630 if( mpProgress )
631 delete mpProgress;
633 const String aStr(SdResId(STR_CREATE_PAGES));
634 mpProgress = new SfxProgress( GetDocSh(), aStr, mnPagesToProcess );
636 else
638 mpDocSh->SetWaitCursor( sal_True );
642 ParagraphInsertedHdl(pOutliner);
644 mnPagesProcessed++;
646 // should there be a progress display?
647 if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD)
649 if (mpProgress)
650 mpProgress->SetState(mnPagesProcessed);
653 // was this the last page?
654 if (mnPagesProcessed == mnPagesToProcess)
656 if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD && mpProgress)
658 delete mpProgress;
659 mpProgress = NULL;
661 else
662 mpDocSh->SetWaitCursor( sal_False );
664 mnPagesToProcess = 0;
665 mnPagesProcessed = 0;
667 pOutliner->UpdateFields();
669 else if( !pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) && ((pOutliner->GetPrevFlags() & PARAFLAG_ISPAGE) != 0) )
671 // the paragraph was a page but now becomes a normal paragraph
673 // how many titles are before the title paragraph in question?
674 sal_uLong nPos = 0L;
675 Paragraph* pParagraph = pPara;
676 while(pParagraph)
678 pParagraph = GetPrevTitle(pParagraph);
679 if (pParagraph)
680 nPos++;
682 // delete page and notes page
684 sal_uInt16 nAbsPos = (sal_uInt16)nPos * 2 + 1;
685 SdrPage* pPage = mrDoc.GetPage(nAbsPos);
686 if( isRecordingUndo() )
687 AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
688 mrDoc.RemovePage(nAbsPos);
690 nAbsPos = (sal_uInt16)nPos * 2 + 1;
691 pPage = mrDoc.GetPage(nAbsPos);
692 if( isRecordingUndo() )
693 AddUndo(mrDoc.GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
694 mrDoc.RemovePage(nAbsPos);
696 pPage = GetPageForParagraph( pPara );
698 mrOutliner.SetDepth( pPara, (pPage && (static_cast<SdPage*>(pPage)->GetAutoLayout() == AUTOLAYOUT_TITLE)) ? -1 : 0 );
700 // progress display if necessary
701 if (mnPagesToProcess)
703 mnPagesProcessed++;
704 if (mpProgress)
705 mpProgress->SetState(mnPagesProcessed);
707 if (mnPagesProcessed == mnPagesToProcess)
709 if(mpProgress)
711 delete mpProgress;
712 mpProgress = NULL;
714 mnPagesToProcess = 0;
715 mnPagesProcessed = 0;
718 pOutliner->UpdateFields();
720 else if ( (pOutliner->GetPrevDepth() == 1) && ( pOutliner->GetDepth( pOutliner->GetAbsPos( pPara ) ) == 2 ) )
722 // how many titles are in front of the title paragraph in question?
723 sal_Int32 nPos = -1L;
725 Paragraph* pParagraph = pPara;
726 while(pParagraph)
728 pParagraph = GetPrevTitle(pParagraph);
729 if (pParagraph)
730 nPos++;
733 if(nPos >= 0)
735 SdPage*pPage = (SdPage*)mrDoc.GetSdPage( (sal_uInt16) nPos, PK_STANDARD);
737 if(pPage && pPage->GetPresObj(PRESOBJ_TEXT))
738 pOutliner->SetDepth( pPara, 0 );
742 // how many titles are in front of the title paragraph in question?
743 sal_Int32 nPos = -1L;
745 Paragraph* pTempPara = pPara;
746 while(pTempPara)
748 pTempPara = GetPrevTitle(pTempPara);
749 if (pTempPara)
750 nPos++;
753 if( nPos >= 0 )
755 SdPage* pPage = (SdPage*) mrDoc.GetSdPage( (sal_uInt16) nPos, PK_STANDARD );
757 if( pPage )
759 SfxStyleSheet* pStyleSheet = NULL;
760 sal_Int32 nPara = pOutliner->GetAbsPos( pPara );
761 sal_Int16 nDepth = pOutliner->GetDepth( nPara );
762 bool bSubTitle = pPage->GetPresObj(PRESOBJ_TEXT) != NULL;
764 if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
766 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_TITLE );
768 else if( bSubTitle )
770 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_TEXT );
772 else
774 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_OUTLINE );
776 if( nDepth > 0 )
778 String aNewStyleSheetName( pStyleSheet->GetName() );
779 aNewStyleSheetName.Erase( aNewStyleSheetName.Len()-1, 1 );
780 aNewStyleSheetName += OUString::number( nDepth+1 );
781 SfxStyleSheetBasePool* pStylePool = mrDoc.GetStyleSheetPool();
782 pStyleSheet = (SfxStyleSheet*) pStylePool->Find( aNewStyleSheetName, pStyleSheet->GetFamily() );
786 // before we set the style sheet we need to preserve the bullet item
787 // since all items will be deleted while setting a new style sheet
788 SfxItemSet aOldAttrs( pOutliner->GetParaAttribs( nPara ) );
790 pOutliner->SetStyleSheet( nPara, pStyleSheet );
792 // restore the old bullet item but not if the style changed
793 if ( pOutliner->GetPrevDepth() != -1 && nDepth != -1 &&
794 aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SFX_ITEM_ON )
796 SfxItemSet aAttrs( pOutliner->GetParaAttribs( nPara ) );
797 aAttrs.Put( *aOldAttrs.GetItem( EE_PARA_NUMBULLET ) );
798 pOutliner->SetParaAttribs( nPara, aAttrs );
803 InvalidateSlideNumberArea();
805 return 0;
809 * Handler for StatusEvents
811 IMPL_LINK_NOARG(OutlineView, StatusEventHdl)
813 ::sd::Window* pWin = mrOutlineViewShell.GetActiveWindow();
814 OutlinerView* pOutlinerView = GetViewByWindow(pWin);
815 Rectangle aVis = pOutlinerView->GetVisArea();
816 sal_uLong nWidth = OUTLINE_PAPERWIDTH;
817 Rectangle aText = Rectangle(Point(0,0),
818 Size(nWidth,
819 mrOutliner.GetTextHeight()));
820 Rectangle aWin(Point(0,0), pWin->GetOutputSizePixel());
821 aWin = pWin->PixelToLogic(aWin);
823 if (!aVis.IsEmpty()) // not when opening
825 aText.Bottom() += aWin.GetHeight();
827 mrOutlineViewShell.InitWindows(Point(0,0), aText.GetSize(),
828 Point(aVis.TopLeft()));
829 mrOutlineViewShell.UpdateScrollBars();
832 InvalidateSlideNumberArea();
833 return 0;
836 IMPL_LINK_NOARG(OutlineView, BeginDropHdl)
838 DBG_ASSERT(maDragAndDropModelGuard.get() == 0, "sd::OutlineView::BeginDropHdl(), prior drag operation not finished correctly!" );
840 maDragAndDropModelGuard.reset( new OutlineViewModelChangeGuard( *this ) );
841 return 0;
844 IMPL_LINK_NOARG(OutlineView, EndDropHdl)
846 maDragAndDropModelGuard.reset(0);
847 InvalidateSlideNumberArea();
848 return 0;
852 * Handler for the start of a paragraph movement
854 IMPL_LINK( OutlineView, BeginMovingHdl, ::Outliner *, pOutliner )
856 OutlineViewPageChangesGuard aGuard(this);
858 // list of selected title paragraphs
859 mpOutlinerView[0]->CreateSelectionList(maSelectedParas);
861 for (std::vector<Paragraph*>::iterator it = maSelectedParas.begin(); it != maSelectedParas.end();)
863 if (!pOutliner->HasParaFlag(*it, PARAFLAG_ISPAGE))
864 it = maSelectedParas.erase(it);
865 else
866 ++it;
869 // select the pages belonging to the paragraphs on level 0 to select
870 sal_uInt16 nPos = 0;
871 sal_Int32 nParaPos = 0;
872 Paragraph* pPara = pOutliner->GetParagraph( 0 );
873 std::vector<Paragraph*>::const_iterator fiter;
875 while(pPara)
877 if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) ) // one page?
879 maOldParaOrder.push_back(pPara);
880 SdPage* pPage = mrDoc.GetSdPage(nPos, PK_STANDARD);
882 fiter = std::find(maSelectedParas.begin(),maSelectedParas.end(),pPara);
884 pPage->SetSelected(fiter != maSelectedParas.end());
886 ++nPos;
888 pPara = pOutliner->GetParagraph( ++nParaPos );
891 return 0;
895 * Handler for the end of a paragraph movement
897 IMPL_LINK( OutlineView, EndMovingHdl, ::Outliner *, pOutliner )
899 OutlineViewPageChangesGuard aGuard(this);
901 DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::EndMovingHdl(), model change without undo?!" );
903 // look for insertion position via the first paragraph
904 Paragraph* pSearchIt = maSelectedParas.empty() ? NULL : *(maSelectedParas.begin());
906 // look for the first of the selected paragraphs in the new ordering
907 sal_uInt16 nPosNewOrder = 0;
908 sal_Int32 nParaPos = 0;
909 Paragraph* pPara = pOutliner->GetParagraph( 0 );
910 Paragraph* pPrev = NULL;
911 while (pPara && pPara != pSearchIt)
913 if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
915 nPosNewOrder++;
916 pPrev = pPara;
918 pPara = pOutliner->GetParagraph( ++nParaPos );
921 sal_uInt16 nPos = nPosNewOrder; // don't change nPosNewOrder
922 if (nPos == 0)
924 nPos = (sal_uInt16)-1; // insert before the first page
926 else
928 // look for the predecessor in the old ordering
929 std::vector<Paragraph*>::const_iterator it = std::find(maOldParaOrder.begin(),
930 maOldParaOrder.end(),
931 pPrev);
933 if (it != maOldParaOrder.end())
934 nPos = static_cast<sal_uInt16>(it-maOldParaOrder.begin());
935 else
936 nPos = 0xffff;
938 DBG_ASSERT(nPos != 0xffff, "Paragraph not found");
941 mrDoc.MovePages(nPos);
943 // deselect the pages again
944 sal_uInt16 nPageCount = (sal_uInt16)maSelectedParas.size();
945 while (nPageCount)
947 SdPage* pPage = mrDoc.GetSdPage(nPosNewOrder, PK_STANDARD);
948 pPage->SetSelected(sal_False);
949 nPosNewOrder++;
950 nPageCount--;
953 pOutliner->UpdateFields();
955 maSelectedParas.clear();
956 maOldParaOrder.clear();
958 InvalidateSlideNumberArea();
960 return 0;
964 * Look for the title text object in one page of the model
966 SdrTextObj* OutlineView::GetTitleTextObject(SdrPage* pPage)
968 sal_uLong nObjectCount = pPage->GetObjCount();
969 SdrObject* pObject = NULL;
970 SdrTextObj* pResult = NULL;
972 for (sal_uLong nObject = 0; nObject < nObjectCount; nObject++)
974 pObject = pPage->GetObj(nObject);
975 if (pObject->GetObjInventor() == SdrInventor &&
976 pObject->GetObjIdentifier() == OBJ_TITLETEXT)
978 pResult = (SdrTextObj*)pObject;
979 break;
982 return pResult;
987 * Look for the outline text object in one page of the model
989 SdrTextObj* OutlineView::GetOutlineTextObject(SdrPage* pPage)
991 sal_uLong nObjectCount = pPage->GetObjCount();
992 SdrObject* pObject = NULL;
993 SdrTextObj* pResult = NULL;
995 for (sal_uLong nObject = 0; nObject < nObjectCount; nObject++)
997 pObject = pPage->GetObj(nObject);
998 if (pObject->GetObjInventor() == SdrInventor &&
999 pObject->GetObjIdentifier() == OBJ_OUTLINETEXT)
1001 pResult = (SdrTextObj*)pObject;
1002 break;
1005 return pResult;
1008 SdrTextObj* OutlineView::CreateTitleTextObject(SdPage* pPage)
1010 DBG_ASSERT( GetTitleTextObject(pPage) == 0, "sd::OutlineView::CreateTitleTextObject(), there is already a title text object!" );
1012 if( pPage->GetAutoLayout() == AUTOLAYOUT_NONE )
1014 // simple case
1015 pPage->SetAutoLayout( AUTOLAYOUT_ONLY_TITLE, true );
1017 else
1019 // we already have a layout with a title but the title
1020 // object was deleted, create a new one
1021 pPage->InsertAutoLayoutShape( 0, PRESOBJ_TITLE, false, pPage->GetTitleRect(), true );
1024 return GetTitleTextObject(pPage);
1027 SdrTextObj* OutlineView::CreateOutlineTextObject(SdPage* pPage)
1029 DBG_ASSERT( GetOutlineTextObject(pPage) == 0, "sd::OutlineView::CreateOutlineTextObject(), there is already a layout text object!" );
1031 AutoLayout eNewLayout = pPage->GetAutoLayout();
1032 switch( eNewLayout )
1034 case AUTOLAYOUT_NONE:
1035 case AUTOLAYOUT_ONLY_TITLE:
1036 case AUTOLAYOUT_TITLE: eNewLayout = AUTOLAYOUT_ENUM; break;
1038 case AUTOLAYOUT_CHART: eNewLayout = AUTOLAYOUT_CHARTTEXT; break;
1040 case AUTOLAYOUT_ORG:
1041 case AUTOLAYOUT_TAB:
1042 case AUTOLAYOUT_OBJ: eNewLayout = AUTOLAYOUT_OBJTEXT; break;
1043 default:
1044 break;
1047 if( eNewLayout != pPage->GetAutoLayout() )
1049 pPage->SetAutoLayout( eNewLayout, true );
1051 else
1053 // we already have a layout with a text but the text
1054 // object was deleted, create a new one
1055 pPage->InsertAutoLayoutShape( 0,
1056 (eNewLayout == AUTOLAYOUT_TITLE) ? PRESOBJ_TEXT : PRESOBJ_OUTLINE,
1057 false, pPage->GetLayoutRect(), true );
1060 return GetOutlineTextObject(pPage);
1063 /** updates draw model with all changes from outliner model */
1064 sal_Bool OutlineView::PrepareClose(sal_Bool)
1066 ::sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager());
1067 if (pDocUndoMgr != NULL)
1068 pDocUndoMgr->SetLinkedUndoManager(NULL);
1070 mrOutliner.GetUndoManager().Clear();
1072 const String aUndoStr(SdResId(STR_UNDO_CHANGE_TITLE_AND_LAYOUT));
1073 BegUndo(aUndoStr);
1074 UpdateDocument();
1075 EndUndo();
1076 mrDoc.SetSelected(GetActualPage(), sal_True);
1077 return sal_True;
1082 * Set attributes of the selected text
1084 sal_Bool OutlineView::SetAttributes(const SfxItemSet& rSet, sal_Bool )
1086 sal_Bool bOk = sal_False;
1088 OutlinerView* pOlView = GetViewByWindow(mrOutlineViewShell.GetActiveWindow());
1090 if (pOlView)
1092 pOlView->SetAttribs(rSet);
1093 bOk = sal_True;
1096 mrOutlineViewShell.Invalidate (SID_PREVIEW_STATE);
1098 return (bOk);
1102 * Get attributes of the selected text
1104 sal_Bool OutlineView::GetAttributes( SfxItemSet& rTargetSet, sal_Bool ) const
1106 OutlinerView* pOlView = GetViewByWindow(
1107 mrOutlineViewShell.GetActiveWindow());
1108 DBG_ASSERT(pOlView, "keine OutlinerView gefunden");
1110 rTargetSet.Put( pOlView->GetAttribs(), sal_False );
1111 return sal_True;
1114 /** creates outliner model from draw model */
1115 void OutlineView::FillOutliner()
1117 mrOutliner.GetUndoManager().Clear();
1118 mrOutliner.EnableUndo(sal_False);
1119 ResetLinks();
1120 mrOutliner.SetUpdateMode(false);
1122 Paragraph* pTitleToSelect = NULL;
1123 sal_uLong nPageCount = mrDoc.GetSdPageCount(PK_STANDARD);
1125 // fill outliner with paragraphs from slides title & (outlines|subtitles)
1126 for (sal_uInt16 nPage = 0; nPage < nPageCount; nPage++)
1128 SdPage* pPage = (SdPage*)mrDoc.GetSdPage(nPage, PK_STANDARD);
1129 Paragraph * pPara = NULL;
1131 // take text from title shape
1132 SdrTextObj* pTO = GetTitleTextObject(pPage);
1133 if(pTO && !(pTO->IsEmptyPresObj()))
1135 OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1136 if (pOPO)
1138 sal_Bool bVertical = pOPO->IsVertical();
1139 pOPO->SetVertical( sal_False );
1140 mrOutliner.AddText(*pOPO);
1141 pOPO->SetVertical( bVertical );
1142 pPara = mrOutliner.GetParagraph( mrOutliner.GetParagraphCount()-1 );
1146 if( pPara == 0 ) // no title, insert an empty paragraph
1148 pPara = mrOutliner.Insert(String());
1149 mrOutliner.SetDepth(pPara, -1);
1151 // do not apply hard attributes from the previous paragraph
1152 mrOutliner.SetParaAttribs( mrOutliner.GetAbsPos(pPara),
1153 mrOutliner.GetEmptyItemSet() );
1155 mrOutliner.SetStyleSheet( mrOutliner.GetAbsPos( pPara ), pPage->GetStyleSheetForPresObj( PRESOBJ_TITLE ) );
1158 mrOutliner.SetParaFlag( pPara, PARAFLAG_ISPAGE );
1160 sal_Int32 nPara = mrOutliner.GetAbsPos( pPara );
1162 UpdateParagraph( nPara );
1164 // remember paragraph of currently selected page
1165 if (pPage->IsSelected())
1166 pTitleToSelect = pPara;
1168 // take text from subtitle or outline
1169 pTO = static_cast<SdrTextObj*>(pPage->GetPresObj(PRESOBJ_TEXT));
1170 const bool bSubTitle = pTO != 0;
1172 if (!pTO) // if no subtile found, try outline
1173 pTO = GetOutlineTextObject(pPage);
1175 if(pTO && !(pTO->IsEmptyPresObj())) // found some text
1177 OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1178 if (pOPO)
1180 sal_Int32 nParaCount1 = mrOutliner.GetParagraphCount();
1181 sal_Bool bVertical = pOPO->IsVertical();
1182 pOPO->SetVertical( sal_False );
1183 mrOutliner.AddText(*pOPO);
1184 pOPO->SetVertical( bVertical );
1186 sal_Int32 nParaCount2 = mrOutliner.GetParagraphCount();
1187 for (sal_Int32 n = nParaCount1; n < nParaCount2; n++)
1189 if( bSubTitle )
1191 Paragraph* p = mrOutliner.GetParagraph(n);
1192 if(p && mrOutliner.GetDepth( n ) > 0 )
1193 mrOutliner.SetDepth(p, 0);
1196 UpdateParagraph( n );
1202 // place cursor at the start
1203 Paragraph* pFirstPara = mrOutliner.GetParagraph( 0 );
1204 mpOutlinerView[0]->Select( pFirstPara, sal_True, sal_False );
1205 mpOutlinerView[0]->Select( pFirstPara, sal_False, sal_False );
1207 // select title of slide that was selected
1208 if (pTitleToSelect)
1209 mpOutlinerView[0]->Select(pTitleToSelect, sal_True, sal_False);
1211 SetLinks();
1213 mrOutliner.EnableUndo(sal_True);
1215 mrOutliner.SetUpdateMode(true);
1219 * Handler for deleting of level 0 paragraphs (pages): Warning
1221 IMPL_LINK_NOARG(OutlineView, RemovingPagesHdl)
1223 sal_Int32 nNumOfPages = mrOutliner.GetSelPageCount();
1225 if (nNumOfPages > PROCESS_WITH_PROGRESS_THRESHOLD)
1227 mnPagesToProcess = nNumOfPages;
1228 mnPagesProcessed = 0;
1231 if (mnPagesToProcess)
1233 if( mpProgress )
1234 delete mpProgress;
1236 String aStr(SdResId(STR_DELETE_PAGES));
1237 mpProgress = new SfxProgress( GetDocSh(), aStr, mnPagesToProcess );
1239 mrOutliner.UpdateFields();
1241 InvalidateSlideNumberArea();
1243 return 1;
1247 * Handler for indenting level 0 paragraphs (pages): Warning
1249 IMPL_LINK_INLINE_START( OutlineView, IndentingPagesHdl, OutlinerView *, pOutlinerView )
1251 return RemovingPagesHdl(pOutlinerView);
1253 IMPL_LINK_INLINE_END( OutlineView, IndentingPagesHdl, OutlinerView *, pOutlinerView )
1256 /** returns the first slide that is selected in the outliner or where
1257 the cursor is located */
1258 SdPage* OutlineView::GetActualPage()
1260 ::sd::Window* pWin = mrOutlineViewShell.GetActiveWindow();
1261 OutlinerView* pActiveView = GetViewByWindow(pWin);
1263 std::vector<Paragraph*> aSelList;
1264 pActiveView->CreateSelectionList(aSelList);
1266 Paragraph *pPar = aSelList.empty() ? NULL : *(aSelList.begin());
1267 SdPage* pCurrent = GetPageForParagraph(pPar);
1269 DBG_ASSERT( pCurrent ||
1270 (mpDocSh->GetUndoManager() && static_cast< sd::UndoManager *>(mpDocSh->GetUndoManager())->IsDoing()) ||
1271 maDragAndDropModelGuard.get(),
1272 "sd::OutlineView::GetActualPage(), no current page?" );
1274 if( pCurrent )
1275 return pCurrent;
1277 return mrDoc.GetSdPage( 0, PK_STANDARD );
1280 SdPage* OutlineView::GetPageForParagraph( Paragraph* pPara )
1282 if( !mrOutliner.HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1283 pPara = GetPrevTitle(pPara);
1285 sal_uInt32 nPageToSelect = 0;
1286 while(pPara)
1288 pPara = GetPrevTitle(pPara);
1289 if(pPara)
1290 nPageToSelect++;
1293 if( nPageToSelect < (sal_uInt32)mrDoc.GetSdPageCount( PK_STANDARD ) )
1294 return static_cast< SdPage* >( mrDoc.GetSdPage( (sal_uInt16)nPageToSelect, PK_STANDARD) );
1296 return 0;
1299 Paragraph* OutlineView::GetParagraphForPage( ::Outliner& rOutl, SdPage* pPage )
1301 // get the number of paragraphs with ident 0 we need to skip before
1302 // we finde the actual page
1303 sal_uInt32 nPagesToSkip = (pPage->GetPageNum() - 1) >> 1;
1305 sal_Int32 nParaPos = 0;
1306 Paragraph* pPara = rOutl.GetParagraph( 0 );
1307 while( pPara )
1309 // if this paragraph is a page ...
1310 if( mrOutliner.HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1312 // see if we already skiped enough pages
1313 if( 0 == nPagesToSkip )
1314 break; // and if so, end the loop
1316 // we skiped another page
1317 nPagesToSkip--;
1320 // get next paragraph
1321 pPara = mrOutliner.GetParagraph( ++nParaPos );
1324 return pPara;
1327 /** selects the paragraph for the given page at the outliner view*/
1328 void OutlineView::SetActualPage( SdPage* pActual )
1330 if( pActual && dynamic_cast<Outliner&>(mrOutliner).GetIgnoreCurrentPageChangesLevel()==0 && !mbFirstPaint)
1332 // if we found a paragraph, select its text at the outliner view
1333 Paragraph* pPara = GetParagraphForPage( mrOutliner, pActual );
1334 if( pPara )
1335 mpOutlinerView[0]->Select( pPara, sal_True, sal_False );
1340 * Get StyleSheet from the selection
1342 SfxStyleSheet* OutlineView::GetStyleSheet() const
1344 ::sd::Window* pActWin = mrOutlineViewShell.GetActiveWindow();
1345 OutlinerView* pOlView = GetViewByWindow(pActWin);
1346 SfxStyleSheet* pResult = pOlView->GetStyleSheet();
1347 return pResult;
1353 * Mark pages as selected / not selected
1355 void OutlineView::SetSelectedPages()
1357 // list of selected title paragraphs
1358 std::vector<Paragraph*> aSelParas;
1359 mpOutlinerView[0]->CreateSelectionList(aSelParas);
1361 for (std::vector<Paragraph*>::iterator it = aSelParas.begin(); it != aSelParas.end();)
1363 if (!mrOutliner.HasParaFlag(*it, PARAFLAG_ISPAGE))
1364 it = aSelParas.erase(it);
1365 else
1366 ++it;
1369 // select the pages belonging to the paragraphs on level 0 to select
1370 sal_uInt16 nPos = 0;
1371 sal_Int32 nParaPos = 0;
1372 Paragraph *pPara = mrOutliner.GetParagraph( 0 );
1373 std::vector<Paragraph*>::const_iterator fiter;
1375 while(pPara)
1377 if( mrOutliner.HasParaFlag(pPara, PARAFLAG_ISPAGE) ) // one page
1379 SdPage* pPage = mrDoc.GetSdPage(nPos, PK_STANDARD);
1380 DBG_ASSERT(pPage!=NULL,
1381 "Trying to select non-existing page OutlineView::SetSelectedPages()");
1383 if (pPage)
1385 fiter = std::find(aSelParas.begin(),aSelParas.end(),pPara);
1386 pPage->SetSelected(fiter != aSelParas.end());
1389 nPos++;
1392 pPara = mrOutliner.GetParagraph( ++nParaPos );
1398 * Set new links
1400 void OutlineView::SetLinks()
1402 // set notification links
1403 mrOutliner.SetParaInsertedHdl(LINK(this, OutlineView, ParagraphInsertedHdl));
1404 mrOutliner.SetParaRemovingHdl(LINK(this, OutlineView, ParagraphRemovingHdl));
1405 mrOutliner.SetDepthChangedHdl(LINK(this, OutlineView, DepthChangedHdl));
1406 mrOutliner.SetBeginMovingHdl(LINK(this, OutlineView, BeginMovingHdl));
1407 mrOutliner.SetEndMovingHdl(LINK(this, OutlineView, EndMovingHdl));
1408 mrOutliner.SetRemovingPagesHdl(LINK(this, OutlineView, RemovingPagesHdl));
1409 mrOutliner.SetIndentingPagesHdl(LINK(this, OutlineView, IndentingPagesHdl));
1410 mrOutliner.SetStatusEventHdl(LINK(this, OutlineView, StatusEventHdl));
1411 mrOutliner.SetBeginDropHdl(LINK(this,OutlineView, BeginDropHdl));
1412 mrOutliner.SetEndDropHdl(LINK(this,OutlineView, EndDropHdl));
1413 mrOutliner.SetPaintFirstLineHdl(LINK(this,OutlineView,PaintingFirstLineHdl));
1414 mrOutliner.SetBeginPasteOrDropHdl(LINK(this,OutlineView, BeginPasteOrDropHdl));
1415 mrOutliner.SetEndPasteOrDropHdl(LINK(this,OutlineView, EndPasteOrDropHdl));
1421 * Restore old links
1423 void OutlineView::ResetLinks() const
1425 Link aEmptyLink;
1426 mrOutliner.SetParaInsertedHdl(aEmptyLink);
1427 mrOutliner.SetParaRemovingHdl(aEmptyLink);
1428 mrOutliner.SetDepthChangedHdl(aEmptyLink);
1429 mrOutliner.SetBeginMovingHdl(aEmptyLink);
1430 mrOutliner.SetEndMovingHdl(aEmptyLink);
1431 mrOutliner.SetStatusEventHdl(aEmptyLink);
1432 mrOutliner.SetRemovingPagesHdl(aEmptyLink);
1433 mrOutliner.SetIndentingPagesHdl(aEmptyLink);
1434 mrOutliner.SetDrawPortionHdl(aEmptyLink);
1435 mrOutliner.SetBeginPasteOrDropHdl(aEmptyLink);
1436 mrOutliner.SetEndPasteOrDropHdl(aEmptyLink);
1440 sal_Int8 OutlineView::AcceptDrop( const AcceptDropEvent&, DropTargetHelper&, ::sd::Window*, sal_uInt16, sal_uInt16)
1442 return DND_ACTION_NONE;
1446 sal_Int8 OutlineView::ExecuteDrop( const ExecuteDropEvent&, DropTargetHelper&, ::sd::Window*, sal_uInt16, sal_uInt16)
1448 return DND_ACTION_NONE;
1451 // Re-implement GetScriptType for this view to get correct results
1452 sal_uInt16 OutlineView::GetScriptType() const
1454 sal_uInt16 nScriptType = ::sd::View::GetScriptType();
1456 OutlinerParaObject* pTempOPObj = mrOutliner.CreateParaObject();
1457 if(pTempOPObj)
1459 nScriptType = pTempOPObj->GetTextObject().GetScriptType();
1460 delete pTempOPObj;
1463 return nScriptType;
1466 void OutlineView::onUpdateStyleSettings( bool bForceUpdate /* = false */ )
1468 svtools::ColorConfig aColorConfig;
1469 const Color aDocColor( aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor );
1470 if( bForceUpdate || (maDocColor != aDocColor) )
1472 sal_uInt16 nView;
1473 for( nView = 0; nView < MAX_OUTLINERVIEWS; nView++ )
1475 if (mpOutlinerView[nView] != NULL)
1477 mpOutlinerView[nView]->SetBackgroundColor( aDocColor );
1479 ::Window* pWindow = mpOutlinerView[nView]->GetWindow();
1481 if( pWindow )
1482 pWindow->SetBackground( Wallpaper( aDocColor ) );
1487 mrOutliner.SetBackgroundColor( aDocColor );
1489 maDocColor = aDocColor;
1493 IMPL_LINK_NOARG(OutlineView, AppEventListenerHdl)
1495 onUpdateStyleSettings();
1496 return 0;
1502 IMPL_LINK(OutlineView, EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent*, pEvent)
1504 if (pEvent != NULL)
1506 switch (pEvent->meEventId)
1508 case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
1509 SetActualPage(mrOutlineViewShell.GetActualPage());
1510 InvalidateSlideNumberArea();
1511 break;
1513 case tools::EventMultiplexerEvent::EID_PAGE_ORDER:
1514 if (dynamic_cast<Outliner&>(mrOutliner).GetIgnoreCurrentPageChangesLevel()==0)
1516 if (((mrDoc.GetPageCount()-1)%2) == 0)
1518 mrOutliner.Clear();
1519 FillOutliner();
1520 ::sd::Window* pWindow = mrOutlineViewShell.GetActiveWindow();
1521 if (pWindow != NULL)
1522 pWindow->Invalidate();
1525 break;
1528 return 0;
1531 void OutlineView::IgnoreCurrentPageChanges (bool bIgnoreChanges)
1533 if (bIgnoreChanges)
1534 dynamic_cast<Outliner&>(mrOutliner).IncreIgnoreCurrentPageChangesLevel();
1535 else
1536 dynamic_cast<Outliner&>(mrOutliner).DecreIgnoreCurrentPageChangesLevel();
1539 /** call this method before you do anything that can modify the outliner
1540 and or the drawing document model. It will create needed undo actions */
1541 void OutlineView::BeginModelChange()
1543 const String aEmpty;
1544 mrOutliner.GetUndoManager().EnterListAction(aEmpty,aEmpty);
1545 const String aUndoStr(SdResId(STR_UNDO_CHANGE_TITLE_AND_LAYOUT));
1546 BegUndo(aUndoStr);
1549 /** call this method after BeginModelChange(), when all possible model
1550 changes are done. */
1551 void OutlineView::EndModelChange()
1553 UpdateDocument();
1555 ::svl::IUndoManager* pDocUndoMgr = mpDocSh->GetUndoManager();
1557 bool bHasUndoActions = pDocUndoMgr->GetUndoActionCount() != 0;
1559 EndUndo();
1561 DBG_ASSERT( bHasUndoActions == (mrOutliner.GetUndoManager().GetUndoActionCount() != 0), "sd::OutlineView::EndModelChange(), undo actions not in sync!" );
1563 mrOutliner.GetUndoManager().LeaveListAction();
1565 if( bHasUndoActions && mrOutliner.GetEditEngine().HasTriedMergeOnLastAddUndo() )
1566 TryToMergeUndoActions();
1568 mrOutlineViewShell.Invalidate( SID_UNDO );
1569 mrOutlineViewShell.Invalidate( SID_REDO );
1572 /** updates all changes in the outliner model to the draw model */
1573 void OutlineView::UpdateDocument()
1575 const sal_uInt32 nPageCount = mrDoc.GetSdPageCount(PK_STANDARD);
1576 Paragraph* pPara = mrOutliner.GetParagraph( 0 );
1577 sal_uInt32 nPage;
1578 for (nPage = 0; nPage < nPageCount; nPage++)
1580 SdPage* pPage = mrDoc.GetSdPage( (sal_uInt16)nPage, PK_STANDARD);
1581 mrDoc.SetSelected(pPage, sal_False);
1583 mrOutlineViewShell.UpdateTitleObject( pPage, pPara );
1584 mrOutlineViewShell.UpdateOutlineObject( pPage, pPara );
1586 if( pPara )
1587 pPara = GetNextTitle(pPara);
1590 DBG_ASSERT( pPara == 0, "sd::OutlineView::UpdateDocument(), slides are out of sync, creating missing ones" );
1591 while( pPara )
1593 SdPage* pPage = InsertSlideForParagraph( pPara );
1594 mrDoc.SetSelected(pPage, sal_False);
1596 mrOutlineViewShell.UpdateTitleObject( pPage, pPara );
1597 mrOutlineViewShell.UpdateOutlineObject( pPage, pPara );
1599 if( pPara )
1600 pPara = GetNextTitle(pPara);
1604 /** merge edit engine undo actions if possible */
1605 void OutlineView::TryToMergeUndoActions()
1607 ::svl::IUndoManager& rOutlineUndo = mrOutliner.GetUndoManager();
1608 if( rOutlineUndo.GetUndoActionCount() > 1 )
1610 SfxListUndoAction* pListAction = dynamic_cast< SfxListUndoAction* >( rOutlineUndo.GetUndoAction(0) );
1611 SfxListUndoAction* pPrevListAction = dynamic_cast< SfxListUndoAction* >( rOutlineUndo.GetUndoAction(1) );
1612 if( pListAction && pPrevListAction )
1614 // find the top EditUndo action in the top undo action list
1615 size_t nAction = pListAction->aUndoActions.size();
1616 EditUndo* pEditUndo = 0;
1617 while( !pEditUndo && nAction )
1619 pEditUndo = dynamic_cast< EditUndo* >(pListAction->aUndoActions[--nAction].pAction);
1622 sal_uInt16 nEditPos = nAction; // we need this later to remove the merged undo actions
1624 // make sure it is the only EditUndo action in the top undo list
1625 while( pEditUndo && nAction )
1627 if( dynamic_cast< EditUndo* >(pListAction->aUndoActions[--nAction].pAction) )
1628 pEditUndo = 0;
1631 // do we have one and only one EditUndo action in the top undo list?
1632 if( pEditUndo )
1634 // yes, see if we can merge it with the prev undo list
1636 nAction = pPrevListAction->aUndoActions.size();
1637 EditUndo* pPrevEditUndo = 0;
1638 while( !pPrevEditUndo && nAction )
1639 pPrevEditUndo = dynamic_cast< EditUndo* >(pPrevListAction->aUndoActions[--nAction].pAction);
1641 if( pPrevEditUndo && pPrevEditUndo->Merge( pEditUndo ) )
1643 // ok we merged the only EditUndo of the top undo list with
1644 // the top EditUndo of the previous undo list
1646 // first remove the merged undo action
1647 DBG_ASSERT( pListAction->aUndoActions[nEditPos].pAction == pEditUndo,
1648 "sd::OutlineView::TryToMergeUndoActions(), wrong edit pos!" );
1649 pListAction->aUndoActions.Remove(nEditPos);
1650 delete pEditUndo;
1652 // now check if we also can merge the draw undo actions
1653 ::svl::IUndoManager* pDocUndoManager = mpDocSh->GetUndoManager();
1654 if( pDocUndoManager && ( pListAction->aUndoActions.size() == 1 ))
1656 SfxLinkUndoAction* pLinkAction = dynamic_cast< SfxLinkUndoAction* >( pListAction->aUndoActions[0].pAction );
1657 SfxLinkUndoAction* pPrevLinkAction = 0;
1659 if( pLinkAction )
1661 nAction = pPrevListAction->aUndoActions.size();
1662 while( !pPrevLinkAction && nAction )
1663 pPrevLinkAction = dynamic_cast< SfxLinkUndoAction* >(pPrevListAction->aUndoActions[--nAction].pAction);
1666 if( pLinkAction && pPrevLinkAction &&
1667 ( pLinkAction->GetAction() == pDocUndoManager->GetUndoAction(0) ) &&
1668 ( pPrevLinkAction->GetAction() == pDocUndoManager->GetUndoAction(1) ) )
1670 SfxListUndoAction* pSourceList = dynamic_cast< SfxListUndoAction* >(pLinkAction->GetAction());
1671 SfxListUndoAction* pDestinationList = dynamic_cast< SfxListUndoAction* >(pPrevLinkAction->GetAction());
1673 if( pSourceList && pDestinationList )
1675 sal_uInt16 nCount = pSourceList->aUndoActions.size();
1676 sal_uInt16 nDestAction = pDestinationList->aUndoActions.size();
1677 while( nCount-- )
1679 SfxUndoAction* pTemp = pSourceList->aUndoActions[0].pAction;
1680 pSourceList->aUndoActions.Remove(0);
1681 pDestinationList->aUndoActions.Insert( pTemp, nDestAction++ );
1683 pDestinationList->nCurUndoAction = pDestinationList->aUndoActions.size();
1685 pListAction->aUndoActions.Remove(0);
1686 delete pLinkAction;
1688 pDocUndoManager->RemoveLastUndoAction();
1693 if ( !pListAction->aUndoActions.empty() )
1695 // now we have to move all remaining doc undo actions from the top undo
1696 // list to the previous undo list and remove the top undo list
1698 size_t nCount = pListAction->aUndoActions.size();
1699 size_t nDestAction = pPrevListAction->aUndoActions.size();
1700 while( nCount-- )
1702 SfxUndoAction* pTemp = pListAction->aUndoActions[0].pAction;
1703 pListAction->aUndoActions.Remove(0);
1704 if( pTemp )
1705 pPrevListAction->aUndoActions.Insert( pTemp, nDestAction++ );
1707 pPrevListAction->nCurUndoAction = pPrevListAction->aUndoActions.size();
1710 rOutlineUndo.RemoveLastUndoAction();
1717 IMPL_LINK(OutlineView, PaintingFirstLineHdl, PaintFirstLineInfo*, pInfo)
1719 if( pInfo )
1721 Paragraph* pPara = mrOutliner.GetParagraph( pInfo->mnPara );
1722 EditEngine& rEditEngine = const_cast< EditEngine& >( mrOutliner.GetEditEngine() );
1724 Size aImageSize( pInfo->mpOutDev->PixelToLogic( maSlideImage.GetSizePixel() ) );
1725 Size aOffset( 100, 100 );
1727 // paint slide number
1728 if( pPara && mrOutliner.HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1730 long nPage = 0; // todo, printing??
1731 for ( sal_Int32 n = 0; n <= pInfo->mnPara; n++ )
1733 Paragraph* p = mrOutliner.GetParagraph( n );
1734 if ( mrOutliner.HasParaFlag(p,PARAFLAG_ISPAGE) )
1735 nPage++;
1738 long nBulletHeight = (long)mrOutliner.GetLineHeight( pInfo->mnPara );
1739 long nFontHeight = 0;
1740 if ( !rEditEngine.IsFlatMode() )
1742 nFontHeight = nBulletHeight / 5;
1744 else
1746 nFontHeight = (nBulletHeight * 10) / 25;
1749 Size aFontSz( 0, nFontHeight );
1751 Size aOutSize( 2000, nBulletHeight );
1753 const float fImageHeight = ((float)aOutSize.Height() * (float)4) / (float)7;
1754 const float fImageRatio = (float)aImageSize.Height() / (float)aImageSize.Width();
1755 aImageSize.Width() = (long)( fImageRatio * fImageHeight );
1756 aImageSize.Height() = (long)( fImageHeight );
1758 Point aImagePos( pInfo->mrStartPos );
1759 aImagePos.X() += aOutSize.Width() - aImageSize.Width() - aOffset.Width() ;
1760 aImagePos.Y() += (aOutSize.Height() - aImageSize.Height()) / 2;
1762 pInfo->mpOutDev->DrawImage( aImagePos, aImageSize, maSlideImage );
1764 const bool bVertical = mrOutliner.IsVertical();
1765 const bool bRightToLeftPara = rEditEngine.IsRightToLeft( pInfo->mnPara );
1767 LanguageType eLang = rEditEngine.GetDefaultLanguage();
1769 Point aTextPos( aImagePos.X() - aOffset.Width(), pInfo->mrStartPos.Y() );
1770 Font aNewFont( OutputDevice::GetDefaultFont( DEFAULTFONT_SANS_UNICODE, eLang, 0 ) );
1771 aNewFont.SetSize( aFontSz );
1772 aNewFont.SetVertical( bVertical );
1773 aNewFont.SetOrientation( bVertical ? 2700 : 0 );
1774 aNewFont.SetColor( COL_AUTO );
1775 pInfo->mpOutDev->SetFont( aNewFont );
1776 String aPageText = OUString::number( nPage );
1777 Size aTextSz;
1778 aTextSz.Width() = pInfo->mpOutDev->GetTextWidth( aPageText );
1779 aTextSz.Height() = pInfo->mpOutDev->GetTextHeight();
1780 if ( !bVertical )
1782 aTextPos.Y() += (aOutSize.Height() - aTextSz.Height()) / 2;
1783 if ( !bRightToLeftPara )
1785 aTextPos.X() -= aTextSz.Width();
1787 else
1789 aTextPos.X() += aTextSz.Width();
1792 else
1794 aTextPos.Y() -= aTextSz.Width();
1795 aTextPos.X() += nBulletHeight / 2;
1797 pInfo->mpOutDev->DrawText( aTextPos, aPageText );
1801 return 0;
1804 // --------------------------------------------------------------------
1806 void OutlineView::UpdateParagraph( sal_Int32 nPara )
1808 SfxItemSet aNewAttrs2( mrOutliner.GetParaAttribs( nPara ) );
1809 aNewAttrs2.Put( maLRSpaceItem );
1810 mrOutliner.SetParaAttribs( nPara, aNewAttrs2 );
1813 // --------------------------------------------------------------------
1815 void OutlineView::OnBeginPasteOrDrop( PasteOrDropInfos* /*pInfos*/ )
1819 /** this is called after a paste or drop operation, make sure that the newly inserted paragraphs
1820 get the correct style sheet and new slides are inserted. */
1821 void OutlineView::OnEndPasteOrDrop( PasteOrDropInfos* pInfos )
1823 SdPage* pPage = 0;
1824 SfxStyleSheetBasePool* pStylePool = GetDoc().GetStyleSheetPool();
1826 for( sal_Int32 nPara = pInfos->nStartPara; nPara <= pInfos->nEndPara; nPara++ )
1828 Paragraph* pPara = mrOutliner.GetParagraph( nPara );
1830 bool bPage = mrOutliner.HasParaFlag( pPara, PARAFLAG_ISPAGE );
1832 if( !bPage )
1834 SdStyleSheet* pStyleSheet = dynamic_cast< SdStyleSheet* >( mrOutliner.GetStyleSheet( nPara ) );
1835 if( pStyleSheet )
1837 const OUString aName( pStyleSheet->GetApiName() );
1838 if ( aName == "title" )
1839 bPage = true;
1843 if( !pPara )
1844 continue; // fatality!?
1846 if( bPage && (nPara != pInfos->nStartPara) )
1848 // insert new slide for this paragraph
1849 pPage = InsertSlideForParagraph( pPara );
1851 else
1853 // newly inserted non page paragraphs get the outline style
1854 if( !pPage )
1855 pPage = GetPageForParagraph( pPara );
1857 if( pPage )
1859 SfxStyleSheet* pStyle = pPage->GetStyleSheetForPresObj( bPage ? PRESOBJ_TITLE : PRESOBJ_OUTLINE );
1861 if( !bPage )
1863 const sal_Int16 nDepth = mrOutliner.GetDepth( nPara );
1864 if( nDepth > 0 )
1866 String aStyleSheetName( pStyle->GetName() );
1867 aStyleSheetName.Erase( aStyleSheetName.Len() - 1, 1 );
1868 aStyleSheetName += OUString::number( nDepth );
1869 pStyle = static_cast<SfxStyleSheet*>( pStylePool->Find( aStyleSheetName, pStyle->GetFamily() ) );
1870 DBG_ASSERT( pStyle, "sd::OutlineView::OnEndPasteOrDrop(), Style not found!" );
1874 mrOutliner.SetStyleSheet( nPara, pStyle );
1877 UpdateParagraph( nPara );
1882 // ====================================================================
1885 OutlineViewModelChangeGuard::OutlineViewModelChangeGuard( OutlineView& rView )
1886 : mrView( rView )
1888 mrView.BeginModelChange();
1891 OutlineViewModelChangeGuard::~OutlineViewModelChangeGuard()
1893 mrView.EndModelChange();
1896 OutlineViewPageChangesGuard::OutlineViewPageChangesGuard( OutlineView* pView )
1897 : mpView( pView )
1899 if( mpView )
1900 mpView->IgnoreCurrentPageChanges( true );
1903 OutlineViewPageChangesGuard::~OutlineViewPageChangesGuard()
1905 if( mpView )
1906 mpView->IgnoreCurrentPageChanges( false );
1910 } // end of namespace sd
1912 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */