xref: /AOO41X/main/sd/source/ui/view/outlview.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 
27 #include "OutlineView.hxx"
28 #include <memory>
29 #include <editeng/forbiddencharacterstable.hxx>
30 #include <sfx2/progress.hxx>
31 #include <vcl/wrkwin.hxx>
32 #include <svx/svxids.hrc>
33 #include "eetext.hxx"
34 #include <editeng/eeitem.hxx>
35 #include <editeng/editstat.hxx>
36 #include <editeng/lrspitem.hxx>
37 #include <svx/svdotext.hxx>
38 #include <sfx2/printer.hxx>
39 #include <sfx2/imagemgr.hxx>
40 #include <sfx2/app.hxx>
41 #include <sfx2/bindings.hxx>
42 #include <svl/itempool.hxx>
43 #include <svl/style.hxx>
44 #include <svx/svdorect.hxx>
45 #include <svx/svdundo.hxx>
46 #include <svl/brdcst.hxx>
47 #include <vcl/msgbox.hxx>
48 #include <editeng/adjitem.hxx>
49 #include <editeng/tstpitem.hxx>
50 #include <editeng/lspcitem.hxx>
51 #include <editeng/numitem.hxx>
52 #include <editeng/outlobj.hxx>
53 #include <editeng/numitem.hxx>
54 #include <editeng/editeng.hxx>
55 
56 // #97766#
57 #include <editeng/editobj.hxx>
58 #include <editeng/editund2.hxx>
59 
60 #include <editeng/editview.hxx>
61 #include <editeng/svxfont.hxx>
62 #include <editeng/fhgtitem.hxx>
63 
64 #include "DrawDocShell.hxx"
65 #include "drawdoc.hxx"
66 #include "Window.hxx"
67 #include "sdpage.hxx"
68 #include "pres.hxx"
69 #include "OutlineViewShell.hxx"
70 #include "app.hrc"
71 #include "glob.hrc"
72 #include "sdresid.hxx"
73 #include "Outliner.hxx"
74 #include "strings.hrc"
75 #include "EventMultiplexer.hxx"
76 #include "ViewShellBase.hxx"
77 #include "undo/undoobjects.hxx"
78 #include "undo/undomanager.hxx"
79 #include "stlsheet.hxx"
80 
81 using ::rtl::OUString;
82 using namespace ::com::sun::star::uno;
83 using namespace ::com::sun::star::frame;
84 
85 namespace sd {
86 
87 // Breite: DIN A 4,  zwei Raender zu je 1 cm
88 #define OUTLINE_PAPERWIDTH 19000
89 
90 // beim Seitenmanipulation Fortschrittsanzeige, wenn mehr Seiten betroffen
91 // sind als:
92 #define PROCESS_WITH_PROGRESS_THRESHOLD  5
93 
94 struct SdParaAndPos
95 {
96     Paragraph* pPara;
97     sal_uInt16     nPos;
98 };
99 
100 TYPEINIT1( OutlineView, ::sd::View );
101 
102 /*************************************************************************
103 |*
104 |* Konstruktor
105 |*
106 \************************************************************************/
107 
OutlineView(DrawDocShell * pDocSh,::Window * pWindow,OutlineViewShell * pOutlineViewSh)108 OutlineView::OutlineView( DrawDocShell* pDocSh, ::Window* pWindow, OutlineViewShell* pOutlineViewSh)
109 : ::sd::View(pDocSh->GetDoc(), pWindow, pOutlineViewSh)
110 , mpOutlineViewShell(pOutlineViewSh)
111 , mpOutliner( mpDoc->GetOutliner(sal_True) )
112 , mpOldParaOrder(NULL)
113 , mpSelectedParas(NULL)
114 , mnPagesToProcess(0)
115 , mnPagesProcessed(0)
116 , mbFirstPaint(sal_True)
117 , mpProgress(NULL)
118 , mbHighContrastMode( false )
119 , maDocColor( COL_WHITE )
120 , mnPageNumberWidthPixel( 0 )
121 , maLRSpaceItem( 0, 0, 2000, 0, EE_PARA_OUTLLRSPACE )
122 {
123     sal_Bool bInitOutliner = sal_False;
124 
125     if (mpOutliner->GetViewCount() == 0)
126     {
127         // Outliner initialisieren: Referenz-Device setzen
128         bInitOutliner = sal_True;
129         mpOutliner->Init( OUTLINERMODE_OUTLINEVIEW );
130 /*
131         SfxStyleSheet* pTitleSheet = mpDoc->GetSdPage( 0, PK_STANDARD )->GetStyleSheetForPresObj( PRESOBJ_TITLE );
132 
133         if ( pTitleSheet )
134         {
135             // set title symbol (level 0)
136             SvxNumBulletItem aNumBulletItem( (const SvxNumBulletItem&) pTitleSheet->GetItemSet().Get(EE_PARA_NUMBULLET) );
137             SvxNumRule aNumRule(* aNumBulletItem.GetNumRule());
138             SvxNumberFormat aFormat( aNumRule.GetLevel(0));
139             Font    aBulletFont;
140             const Font* pFont = aFormat.GetBulletFont();
141             if ( pFont )                                        // if available take font size and color from style
142                 aBulletFont = *pFont;
143             else
144             {
145                 aBulletFont.SetColor( COL_AUTO );
146                 aBulletFont.SetHeight( 1552 );
147             }
148             aBulletFont.SetCharSet(RTL_TEXTENCODING_MS_1252);   // and replacing other values by standard
149             aBulletFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "StarSymbol" )) );
150             aBulletFont.SetWeight(WEIGHT_NORMAL);
151             aBulletFont.SetUnderline(UNDERLINE_NONE);
152             aBulletFont.SetStrikeout(STRIKEOUT_NONE);
153             aBulletFont.SetItalic(ITALIC_NONE);
154             aBulletFont.SetOutline(sal_False);
155             aBulletFont.SetShadow(sal_False);
156             aFormat.SetBulletFont( &aBulletFont );
157             aFormat.SetBulletChar( 0xE011 );  // StarBats: 0xF000 + 114
158             mpOutliner->OverwriteLevel0Bullet( aFormat );
159         }
160 */
161         mpOutliner->SetRefDevice( SD_MOD()->GetRefDevice( *pDocSh ) );
162         sal_uLong nWidth = OUTLINE_PAPERWIDTH;
163         mpOutliner->SetPaperSize(Size(nWidth, 400000000));
164     }
165 
166     // View in Outliner einfuegen
167     for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
168     {
169         mpOutlinerView[nView] = NULL;
170     }
171 
172     mpOutlinerView[0] = new OutlinerView(mpOutliner, pWindow);
173     Rectangle aNullRect;
174     mpOutlinerView[0]->SetOutputArea(aNullRect);
175     mpOutliner->SetUpdateMode(sal_False);
176     mpOutliner->InsertView(mpOutlinerView[0], LIST_APPEND);
177 
178     onUpdateStyleSettings( true );
179 
180     if (bInitOutliner)
181     {
182         // Outliner mit Inhalt fuellen
183         FillOutliner();
184     }
185 
186     Link aLink( LINK(this,OutlineView,EventMultiplexerListener) );
187     mpOutlineViewShell->GetViewShellBase().GetEventMultiplexer()->AddEventListener(
188         aLink,
189         tools::EventMultiplexerEvent::EID_CURRENT_PAGE
190         | tools::EventMultiplexerEvent::EID_PAGE_ORDER);
191 
192     LanguageType eLang = mpOutliner->GetDefaultLanguage();
193     maPageNumberFont = OutputDevice::GetDefaultFont( DEFAULTFONT_SANS_UNICODE, eLang, 0 );
194     maPageNumberFont.SetHeight( 500 );
195 
196     maBulletFont.SetColor( COL_AUTO );
197     maBulletFont.SetHeight( 1000 );
198     maBulletFont.SetCharSet(RTL_TEXTENCODING_MS_1252);   // and replacing other values by standard
199     maBulletFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "StarSymbol" )) );
200     maBulletFont.SetWeight(WEIGHT_NORMAL);
201     maBulletFont.SetUnderline(UNDERLINE_NONE);
202     maBulletFont.SetStrikeout(STRIKEOUT_NONE);
203     maBulletFont.SetItalic(ITALIC_NONE);
204     maBulletFont.SetOutline(sal_False);
205     maBulletFont.SetShadow(sal_False);
206 
207 
208     Reference<XFrame> xFrame (mpOutlineViewShell->GetViewShellBase().GetFrame()->GetTopFrame().GetFrameInterface(), UNO_QUERY);
209 
210     const OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( ".uno:ShowSlide" ));
211     maSlideImage = GetImage( xFrame, aSlotURL, true, false /* todo, hc mode */ );
212 
213     // Tell undo manager of the document about the undo manager of the
214     // outliner, so that the former can synchronize with the later.
215     sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager());
216     if (pDocUndoMgr != NULL)
217         pDocUndoMgr->SetLinkedUndoManager(&mpOutliner->GetUndoManager());
218 }
219 
220 /*************************************************************************
221 |*
222 |* Destruktor, Links restaurieren, Outliner leeren
223 |*
224 \************************************************************************/
225 
~OutlineView()226 OutlineView::~OutlineView()
227 {
228     DBG_ASSERT(maDragAndDropModelGuard.get() == 0, "sd::OutlineView::~OutlineView(), prior drag operation not finished correctly!" );
229 
230     Link aLink( LINK(this,OutlineView,EventMultiplexerListener) );
231     mpOutlineViewShell->GetViewShellBase().GetEventMultiplexer()->RemoveEventListener( aLink );
232     DisconnectFromApplication();
233 
234     if( mpProgress )
235         delete mpProgress;
236 
237     // OutlinerViews abmelden und zerstoeren
238     for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
239     {
240         if (mpOutlinerView[nView] != NULL)
241         {
242             mpOutliner->RemoveView( mpOutlinerView[nView] );
243             delete mpOutlinerView[nView];
244             mpOutlinerView[nView] = NULL;
245         }
246     }
247 
248     if (mpOutliner->GetViewCount() == 0)
249     {
250         // Outliner deinitialisieren: Farbdarstellung einschalten
251         ResetLinks();
252         sal_uLong nCntrl = mpOutliner->GetControlWord();
253         mpOutliner->SetUpdateMode(sal_False); // sonst wird bei SetControlWord gezeichnet
254         mpOutliner->SetControlWord(nCntrl & ~EE_CNTRL_NOCOLORS);
255         SvtAccessibilityOptions aOptions;
256         mpOutliner->ForceAutoColor( aOptions.GetIsAutomaticFontColor() );
257         mpOutliner->Clear();
258     }
259 
260     DBG_ASSERT(!mpSelectedParas, "Absatzliste nicht geloescht");
261     DBG_ASSERT(!mpOldParaOrder, "Absatzliste nicht geloescht");
262 }
263 
264 
265 
266 
ConnectToApplication(void)267 void OutlineView::ConnectToApplication (void)
268 {
269     mpOutlineViewShell->GetActiveWindow()->GrabFocus();
270     Application::AddEventListener(LINK(this, OutlineView, AppEventListenerHdl));
271 }
272 
273 
274 
275 
DisconnectFromApplication(void)276 void OutlineView::DisconnectFromApplication (void)
277 {
278     Application::RemoveEventListener(LINK(this, OutlineView, AppEventListenerHdl));
279 }
280 
281 
282 
283 
284 /*************************************************************************
285 |*
286 |* Paint-Methode
287 |*
288 \************************************************************************/
289 
Paint(const Rectangle & rRect,::sd::Window * pWin)290 void OutlineView::Paint(const Rectangle& rRect, ::sd::Window* pWin)
291 {
292     OutlinerView* pOlView = GetViewByWindow(pWin);
293 
294     if (pOlView)
295     {
296         pOlView->HideCursor();
297         pOlView->Paint(rRect);
298 
299         pOlView->ShowCursor(mbFirstPaint);
300 
301 /*
302         if( mnPageNumberWidthPixel == 0 )
303             GetPageNumberWidthPixel();
304 
305         const sal_uLong nParaCount = pOlView->GetOutliner()->GetParagraphCount();
306         EditView& rEditView = pOlView->GetEditView();
307 
308         Font aOldFont( pWin->GetFont() );
309 
310         const String aBulletStr( sal_Unicode( 0xE011 ) );
311         pWin->SetFont( maBulletFont);
312         sal_Int32 nBulletWidth = pWin->GetTextWidth(aBulletStr);
313 
314         sal_Int32 nPage = 1;
315         for( sal_uLong nPara = 0; nPara < nParaCount; nPara++ )
316         {
317             Paragraph* pPara = pOlView->GetOutliner()->GetParagraph( nPara );
318             if( pPara->HasFlag( PARAFLAG_ISPAGE ) )
319             {
320                 pWin->SetFont( maPageNumberFont );
321                 const String aStr( String::CreateFromInt32( nPage++ ) );
322                 Point aPos( rEditView.GetWindowPosTopLeft( (sal_uInt16)nPara ) );
323 
324                 sal_Int32 nNumberOffset = pWin->PixelToLogic( Point(mnPageNumberWidthPixel, 0) ).X() - nBulletWidth;
325                 sal_Int32 nLineHeight = pOlView->GetOutliner()->GetLineHeight( nPara, 0 );
326 
327                 aPos.X() = nNumberOffset;
328 
329                 Point aPoint( aPos.X() - pWin->GetTextWidth( aStr ), aPos.Y() + ( nLineHeight - maPageNumberFont.GetHeight()) / 2 );
330                 pWin->DrawText( aPoint, aStr );
331 
332                 aPoint.X() = aPos.X();
333                 aPoint.Y() = aPos.Y() +( nLineHeight - maBulletFont.GetHeight()) / 2;
334                 pWin->SetFont( maBulletFont );
335                 pWin->DrawText( aPoint, aBulletStr );
336             }
337         }
338 
339         pWin->SetFont( aOldFont );
340 */
341         mbFirstPaint = sal_False;
342     }
343 }
344 
InvalidateSlideNumberArea()345 void OutlineView::InvalidateSlideNumberArea()
346 {
347 /*
348     for( sal_Int16 nView = 0; nView < MAX_OUTLINERVIEWS; ++nView )
349     {
350         if (mpOutlinerView[nView] != NULL)
351         {
352             ::Window* pWindow = mpOutlinerView[nView]->GetWindow();
353             if( pWindow )
354             {
355                 Rectangle aRect( Point(0,0), pWindow->GetOutputSize() );
356                 aRect.nRight = aRect.nLeft + pWindow->PixelToLogic( Point( mnPageNumberWidthPixel, 0 ) ).X() * 2;
357 
358                 pWindow->Invalidate(aRect);
359             }
360         }
361     }
362 */
363 }
364 
365 /*************************************************************************
366 |*
367 |* Fenster-Groesse hat sich geaendert
368 |*
369 \************************************************************************/
370 
AdjustPosSizePixel(const Point &,const Size &,::sd::Window *)371 void OutlineView::AdjustPosSizePixel(const Point &,const Size &,::sd::Window*)
372 {
373 }
374 
375 /*************************************************************************
376 |*
377 |* ein Fenster hinzufuegen
378 |*
379 \************************************************************************/
380 
AddWindowToPaintView(OutputDevice * pWin)381 void OutlineView::AddWindowToPaintView(OutputDevice* pWin)
382 {
383     sal_Bool bAdded = sal_False;
384     sal_Bool bValidArea = sal_False;
385     Rectangle aOutputArea;
386     const Color aWhiteColor( COL_WHITE );
387     sal_uInt16 nView = 0;
388 
389     while (nView < MAX_OUTLINERVIEWS && !bAdded)
390     {
391         if (mpOutlinerView[nView] == NULL)
392         {
393             mpOutlinerView[nView] = new OutlinerView(mpOutliner, dynamic_cast< ::sd::Window* >(pWin));
394             mpOutlinerView[nView]->SetBackgroundColor( aWhiteColor );
395             mpOutliner->InsertView(mpOutlinerView[nView], LIST_APPEND);
396             bAdded = sal_True;
397 
398             if (bValidArea)
399             {
400                 mpOutlinerView[nView]->SetOutputArea(aOutputArea);
401             }
402         }
403         else if (!bValidArea)
404         {
405             aOutputArea = mpOutlinerView[nView]->GetOutputArea();
406             bValidArea = sal_True;
407         }
408 
409         nView++;
410     }
411 
412     // weisser Hintergrund im Outliner
413     pWin->SetBackground( Wallpaper( aWhiteColor ) );
414 
415     ::sd::View::AddWindowToPaintView(pWin);
416 }
417 
418 /*************************************************************************
419 |*
420 |* ein Fenster entfernen
421 |*
422 \************************************************************************/
423 
DeleteWindowFromPaintView(OutputDevice * pWin)424 void OutlineView::DeleteWindowFromPaintView(OutputDevice* pWin)
425 {
426     sal_Bool bRemoved = sal_False;
427     sal_uInt16 nView = 0;
428     ::Window* pWindow;
429 
430     while (nView < MAX_OUTLINERVIEWS && !bRemoved)
431     {
432         if (mpOutlinerView[nView] != NULL)
433         {
434             pWindow = mpOutlinerView[nView]->GetWindow();
435 
436             if (pWindow == pWin)
437             {
438                 mpOutliner->RemoveView( mpOutlinerView[nView] );
439                 delete mpOutlinerView[nView];
440                 mpOutlinerView[nView] = NULL;
441                 bRemoved = sal_True;
442             }
443         }
444 
445         nView++;
446     }
447 
448     ::sd::View::DeleteWindowFromPaintView(pWin);
449 }
450 
451 /*************************************************************************
452 |*
453 |* Zeiger der dem Fenster entsprechenden OutlinerView zurueckgeben.
454 |*
455 \************************************************************************/
456 
GetViewByWindow(::Window * pWin) const457 OutlinerView* OutlineView::GetViewByWindow (::Window* pWin) const
458 {
459     OutlinerView* pOlView = NULL;
460     for (sal_uInt16 nView = 0; nView < MAX_OUTLINERVIEWS; nView++)
461     {
462         if (mpOutlinerView[nView] != NULL)
463         {
464             if ( pWin == mpOutlinerView[nView]->GetWindow() )
465             {
466                 pOlView = mpOutlinerView[nView];
467             }
468         }
469     }
470     return (pOlView);
471 }
472 
473 
474 /*************************************************************************
475 |*
476 |* Ermittelt den Titel vor einem beliebigen Absatz.
477 |*
478 \************************************************************************/
479 
GetPrevTitle(const Paragraph * pPara)480 Paragraph* OutlineView::GetPrevTitle(const Paragraph* pPara)
481 {
482     sal_Int32 nPos = mpOutliner->GetAbsPos(const_cast<Paragraph*>(pPara));
483 
484     if (nPos > 0)
485     {
486         while(nPos)
487         {
488             pPara = mpOutliner->GetParagraph(--nPos);
489             if( mpOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
490             {
491                 return const_cast< Paragraph* >( pPara );
492             }
493         }
494 
495     }
496     return NULL;
497 }
498 
499 /*************************************************************************
500 |*
501 |* Ermittelt den Titel nach einem beliebigen Absatz.
502 |*
503 \************************************************************************/
504 
GetNextTitle(const Paragraph * pPara)505 Paragraph* OutlineView::GetNextTitle(const Paragraph* pPara)
506 {
507     Paragraph* pResult = const_cast< Paragraph* >( pPara );
508 
509     sal_Int32 nPos = mpOutliner->GetAbsPos(pResult);
510 
511     do
512     {
513         pResult = mpOutliner->GetParagraph(++nPos);
514         if( pResult && mpOutliner->HasParaFlag(pResult, PARAFLAG_ISPAGE) )
515             return pResult;
516     }
517     while( pResult );
518 
519     return NULL;
520 }
521 
522 /*************************************************************************
523 |*
524 |* Handler fuer das Einfuegen von Seiten (Absaetzen)
525 |*
526 \************************************************************************/
527 
IMPL_LINK(OutlineView,ParagraphInsertedHdl,::Outliner *,pOutliner)528 IMPL_LINK( OutlineView, ParagraphInsertedHdl, ::Outliner *, pOutliner )
529 {
530 //  DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::ParagraphInsertedHdl(), model change without undo?!" );
531 
532     // we get calls to this handler during binary insert of drag and drop contents but
533     // we ignore it here and handle it later in OnEndPasteOrDrop()
534     if( maDragAndDropModelGuard.get() == 0 )
535     {
536         OutlineViewPageChangesGuard aGuard(this);
537 
538         Paragraph* pPara = pOutliner->GetHdlParagraph();
539 
540         sal_uInt16 nAbsPos = (sal_uInt16)mpOutliner->GetAbsPos( pPara );
541 
542         UpdateParagraph( nAbsPos );
543 
544         if( (nAbsPos == 0) || mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) || mpOutliner->HasParaFlag(mpOutliner->GetParagraph( nAbsPos-1 ), PARAFLAG_ISPAGE) )
545         {
546             InsertSlideForParagraph( pPara );
547             InvalidateSlideNumberArea();
548         }
549     }
550 
551     return 0;
552 }
553 
554 /** creates and inserts an empty slide for the given paragraph */
InsertSlideForParagraph(Paragraph * pPara)555 SdPage* OutlineView::InsertSlideForParagraph( Paragraph* pPara )
556 {
557     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::InsertSlideForParagraph(), model change without undo?!" );
558 
559     OutlineViewPageChangesGuard aGuard(this);
560 
561     mpOutliner->SetParaFlag( pPara, PARAFLAG_ISPAGE );
562     // wieviele Titel sind vor dem neuen Titelabsatz?
563     sal_uLong nExample = 0L;            // Position der "Vorbild"seite
564     sal_uLong nTarget  = 0L;            // Einfuegeposition
565     while(pPara)
566     {
567         pPara = GetPrevTitle(pPara);
568         if (pPara)
569             nTarget++;
570     }
571 
572 
573     // was der Outliner nicht kann, muss hier wieder wettgemacht werden:
574     // wenn VOR dem ersten Absatz ein neuer Absatz mit RETURN erzeugt wird,
575     // meldet der Outliner den bereits bestehenden (jetzt nach unten
576     // gerutschten) Absatz als neuen Absatz; nicht darauf reinfallen!
577     if (nTarget == 1)
578     {
579         String aTest(mpOutliner->GetText( mpOutliner->GetParagraph( 0 ) ));
580         if (aTest.Len() == 0)
581         {
582             nTarget = 0;
583         }
584     }
585 
586 
587     // "Vorbild"seite ist - wenn vorhanden - die Vorgaengerseite
588     if (nTarget > 0)
589     {
590         nExample = nTarget - 1;
591 
592         sal_uInt16 nPageCount = mpDoc->GetSdPageCount( PK_STANDARD );
593         if( nExample >= nPageCount )
594             nExample = nPageCount - 1;
595     }
596 
597     /**********************************************************************
598     * Es wird stets zuerst eine Standardseite und dann eine
599     * Notizseite erzeugt. Es ist sichergestellt, dass auf eine
600     * Standardseite stets die zugehoerige Notizseite folgt.
601     * Vorangestellt ist genau eine Handzettelseite
602     **********************************************************************/
603 
604     // diese Seite hat Vorbildfunktion
605     SdPage* pExample = (SdPage*)mpDoc->GetSdPage((sal_uInt16)nExample, PK_STANDARD);
606     SdPage* pPage = (SdPage*)mpDoc->AllocPage(sal_False);
607 
608     pPage->SetLayoutName(pExample->GetLayoutName());
609 
610     // einfuegen (Seite)
611     mpDoc->InsertPage(pPage, (sal_uInt16)(nTarget) * 2 + 1);
612     if( isRecordingUndo() )
613         AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pPage));
614 
615     // der Standardseite eine Masterpage zuweisen
616     pPage->TRG_SetMasterPage(pExample->TRG_GetMasterPage());
617 
618     // Seitengroesse setzen
619     pPage->SetSize(pExample->GetSize());
620     pPage->SetBorder( pExample->GetLftBorder(),
621                       pExample->GetUppBorder(),
622                       pExample->GetRgtBorder(),
623                       pExample->GetLwrBorder() );
624 
625     // neue Praesentationsobjekte anlegen (auf <Titel> oder
626     // <Titel mit Untertitel> folgt <Titel mit Gliederung>, ansonsten
627     // wird das Layout von der Vorgaengerseite uebernommen)
628     AutoLayout eAutoLayout = pExample->GetAutoLayout();
629     if (eAutoLayout == AUTOLAYOUT_TITLE ||
630         eAutoLayout == AUTOLAYOUT_ONLY_TITLE)
631     {
632         pPage->SetAutoLayout(AUTOLAYOUT_ENUM, sal_True);
633     }
634     else
635     {
636         pPage->SetAutoLayout(pExample->GetAutoLayout(), sal_True);
637     }
638 
639     /**********************************************************************
640     |* jetzt die Notizseite
641     \*********************************************************************/
642     pExample = (SdPage*)mpDoc->GetSdPage((sal_uInt16)nExample, PK_NOTES);
643     SdPage* pNotesPage = (SdPage*)mpDoc->AllocPage(sal_False);
644 
645     pNotesPage->SetLayoutName(pExample->GetLayoutName());
646 
647     pNotesPage->SetPageKind(PK_NOTES);
648 
649     // einfuegen (Notizseite)
650     mpDoc->InsertPage(pNotesPage, (sal_uInt16)(nTarget) * 2 + 2);
651     if( isRecordingUndo() )
652         AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoNewPage(*pNotesPage));
653 
654     // der Notizseite eine Masterpage zuweisen
655     pNotesPage->TRG_SetMasterPage(pExample->TRG_GetMasterPage());
656 
657     // Seitengroesse setzen, es muss bereits eine Seite vorhanden sein
658     pNotesPage->SetSize(pExample->GetSize());
659     pNotesPage->SetBorder( pExample->GetLftBorder(),
660                            pExample->GetUppBorder(),
661                            pExample->GetRgtBorder(),
662                            pExample->GetLwrBorder() );
663 
664     // neue Praesentationsobjekte anlegen
665     pNotesPage->SetAutoLayout(pExample->GetAutoLayout(), sal_True);
666 
667     mpOutliner->UpdateFields();
668 
669     return pPage;
670 }
671 
672 /*************************************************************************
673 |*
674 |* Handler fuer das Loeschen von Seiten (Absaetzen)
675 |*
676 \************************************************************************/
677 
IMPL_LINK(OutlineView,ParagraphRemovingHdl,::Outliner *,pOutliner)678 IMPL_LINK( OutlineView, ParagraphRemovingHdl, ::Outliner *, pOutliner )
679 {
680     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::ParagraphRemovingHdl(), model change without undo?!" );
681 
682     OutlineViewPageChangesGuard aGuard(this);
683 
684     Paragraph* pPara = pOutliner->GetHdlParagraph();
685     if( pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) )
686     {
687         // wieviele Titel sind vor dem fraglichen Titelabsatz?
688         sal_uLong nPos = 0L;
689         while(pPara)
690         {
691             pPara = GetPrevTitle(pPara);
692             if (pPara) nPos++;
693         }
694 
695         // Seite und Notizseite loeschen
696         sal_uInt16 nAbsPos = (sal_uInt16)nPos * 2 + 1;
697         SdrPage* pPage = mpDoc->GetPage(nAbsPos);
698         if( isRecordingUndo() )
699             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
700         mpDoc->RemovePage(nAbsPos);
701 
702         nAbsPos = (sal_uInt16)nPos * 2 + 1;
703         pPage = mpDoc->GetPage(nAbsPos);
704         if( isRecordingUndo() )
705             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
706         mpDoc->RemovePage(nAbsPos);
707 
708         // ggfs. Fortschrittsanzeige
709         if (mnPagesToProcess)
710         {
711             mnPagesProcessed++;
712 
713             if(mpProgress)
714                 mpProgress->SetState(mnPagesProcessed);
715 
716             if (mnPagesProcessed == mnPagesToProcess)
717             {
718                 if(mpProgress)
719                 {
720                     delete mpProgress;
721                     mpProgress = NULL;
722                 }
723                 mnPagesToProcess = 0;
724                 mnPagesProcessed = 0;
725             }
726         }
727         pOutliner->UpdateFields();
728     }
729 
730     InvalidateSlideNumberArea();
731 
732     return 0;
733 }
734 
735 /*************************************************************************
736 |*
737 |* Handler fuer das Aendern der Einruecktiefe von Absaetzen (macht ggfs.
738 |* das Einfuegen oder Loeschen von Seiten notwendig)
739 |*
740 \************************************************************************/
741 
IMPL_LINK(OutlineView,DepthChangedHdl,::Outliner *,pOutliner)742 IMPL_LINK( OutlineView, DepthChangedHdl, ::Outliner *, pOutliner )
743 {
744     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::DepthChangedHdl(), no undo for model change?!" );
745 
746     OutlineViewPageChangesGuard aGuard(this);
747 
748     Paragraph* pPara = pOutliner->GetHdlParagraph();
749     if( pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) && ((pOutliner->GetPrevFlags() & PARAFLAG_ISPAGE) == 0) )
750     {
751         // the current paragraph is transformed into a slide
752 
753         mpOutliner->SetDepth( pPara, -1 );
754 
755         // werden da etwa mehrere Level-1-Absaetze auf Level 0 gebracht und
756         // wir sollten eine Fortschrittsanzeige oder Eieruhr aufsetzen und
757         // haben es noch nicht getan?
758         if (mnPagesToProcess == 0)
759         {
760             Window*       pActWin = mpOutlineViewShell->GetActiveWindow();
761             OutlinerView* pOlView = GetViewByWindow(pActWin);
762             List*         pList   = pOlView->CreateSelectionList();
763 
764             Paragraph*    pParagraph   = (Paragraph*)pList->First();
765             while (pParagraph)
766             {
767                 if( !pOutliner->HasParaFlag( pParagraph, PARAFLAG_ISPAGE ) && (pOutliner->GetDepth( (sal_uInt16) pOutliner->GetAbsPos( pParagraph ) ) <= 0) )
768                     mnPagesToProcess++;
769                 pParagraph = (Paragraph*)pList->Next();
770             }
771 
772             mnPagesToProcess++; // der Absatz, der jetzt schon auf Level 0
773                                 // steht, gehoert auch dazu
774             mnPagesProcessed = 0;
775 
776             if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD)
777             {
778                 if( mpProgress )
779                     delete mpProgress;
780 
781                 const String aStr(SdResId(STR_CREATE_PAGES));
782                 mpProgress = new SfxProgress( GetDocSh(), aStr, mnPagesToProcess );
783             }
784             else
785             {
786                 mpDocSh->SetWaitCursor( sal_True );
787             }
788             delete pList;
789         }
790 
791         ParagraphInsertedHdl(pOutliner);
792 
793         mnPagesProcessed++;
794 
795         // muss eine Fortschrittsanzeige gepflegt werden?
796         if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD)
797         {
798             if (mpProgress)
799                 mpProgress->SetState(mnPagesProcessed);
800         }
801 
802         // war das die letzte Seite?
803         if (mnPagesProcessed == mnPagesToProcess)
804         {
805             if (mnPagesToProcess > PROCESS_WITH_PROGRESS_THRESHOLD && mpProgress)
806             {
807                 delete mpProgress;
808                 mpProgress = NULL;
809             }
810             else
811                 mpDocSh->SetWaitCursor( sal_False );
812 
813             mnPagesToProcess = 0;
814             mnPagesProcessed = 0;
815         }
816         pOutliner->UpdateFields();
817     }
818     else if( !pOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE ) && ((pOutliner->GetPrevFlags() & PARAFLAG_ISPAGE) != 0) )
819     {
820         // the paragraph was a page but now becomes a normal paragraph
821 
822         // how many titles are before the title paragraph in question?
823         sal_uLong nPos = 0L;
824         Paragraph* pParagraph = pPara;
825         while(pParagraph)
826         {
827             pParagraph = GetPrevTitle(pParagraph);
828             if (pParagraph)
829                 nPos++;
830         }
831         // Seite und Notizseite loeschen
832 
833         sal_uInt16 nAbsPos = (sal_uInt16)nPos * 2 + 1;
834         SdrPage* pPage = mpDoc->GetPage(nAbsPos);
835         if( isRecordingUndo() )
836             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
837         mpDoc->RemovePage(nAbsPos);
838 
839         nAbsPos = (sal_uInt16)nPos * 2 + 1;
840         pPage = mpDoc->GetPage(nAbsPos);
841         if( isRecordingUndo() )
842             AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoDeletePage(*pPage));
843         mpDoc->RemovePage(nAbsPos);
844 
845         pPage = GetPageForParagraph( pPara );
846 
847         mpOutliner->SetDepth( pPara, (pPage && (static_cast<SdPage*>(pPage)->GetAutoLayout() == AUTOLAYOUT_TITLE)) ?  -1 : 0 );
848 
849         // ggfs. Fortschrittsanzeige
850         if (mnPagesToProcess)
851         {
852             mnPagesProcessed++;
853             if (mpProgress)
854                 mpProgress->SetState(mnPagesProcessed);
855 
856             if (mnPagesProcessed == mnPagesToProcess)
857             {
858                 if(mpProgress)
859                 {
860                     delete mpProgress;
861                     mpProgress = NULL;
862                 }
863                 mnPagesToProcess = 0;
864                 mnPagesProcessed = 0;
865             }
866         }
867         pOutliner->UpdateFields();
868     }
869     else if ( (pOutliner->GetPrevDepth() == 1) && ( pOutliner->GetDepth( (sal_uInt16) pOutliner->GetAbsPos( pPara ) ) == 2 ) )
870     {
871         // wieviele Titel sind vor dem fraglichen Titelabsatz?
872         sal_Int32 nPos = -1L;
873 
874         Paragraph* pParagraph = pPara;
875         while(pParagraph)
876         {
877             pParagraph = GetPrevTitle(pParagraph);
878             if (pParagraph)
879                 nPos++;
880         }
881 
882         if(nPos >= 0)
883         {
884             SdPage*pPage = (SdPage*)mpDoc->GetSdPage( (sal_uInt16) nPos, PK_STANDARD);
885 
886             if(pPage && pPage->GetPresObj(PRESOBJ_TEXT))
887                 pOutliner->SetDepth( pPara, 0 );
888         }
889 
890     }
891     // wieviele Titel sind vor dem fraglichen Titelabsatz?
892     sal_Int32 nPos = -1L;
893 
894     Paragraph* pTempPara = pPara;
895     while(pTempPara)
896     {
897         pTempPara = GetPrevTitle(pTempPara);
898         if (pTempPara)
899             nPos++;
900     }
901 
902     if( nPos >= 0 )
903     {
904         SdPage* pPage = (SdPage*) mpDoc->GetSdPage( (sal_uInt16) nPos, PK_STANDARD );
905 
906         if( pPage )
907         {
908             SfxStyleSheet* pStyleSheet = NULL;
909             sal_uLong nPara = pOutliner->GetAbsPos( pPara );
910             sal_Int16 nDepth = pOutliner->GetDepth( (sal_uInt16) nPara );
911             bool bSubTitle = pPage->GetPresObj(PRESOBJ_TEXT) != NULL;
912 
913             if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
914             {
915                 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_TITLE );
916             }
917             else if( bSubTitle )
918             {
919                 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_TEXT );
920             }
921             else
922             {
923                 pStyleSheet = pPage->GetStyleSheetForPresObj( PRESOBJ_OUTLINE );
924 
925                 if( nDepth > 0 )
926                 {
927                     String aNewStyleSheetName( pStyleSheet->GetName() );
928                     aNewStyleSheetName.Erase( aNewStyleSheetName.Len()-1, 1 );
929                     aNewStyleSheetName += String::CreateFromInt32( nDepth+1 );
930                     SfxStyleSheetBasePool* pStylePool = mpDoc->GetStyleSheetPool();
931                     pStyleSheet = (SfxStyleSheet*) pStylePool->Find( aNewStyleSheetName, pStyleSheet->GetFamily() );
932                 }
933             }
934 
935             // before we set the style sheet we need to preserve the bullet item
936             // since all items will be deleted while setting a new style sheet
937             SfxItemSet aOldAttrs( pOutliner->GetParaAttribs( (sal_uInt16)nPara ) );
938 
939             pOutliner->SetStyleSheet( nPara, pStyleSheet );
940 
941             // restore the old bullet item but not if the style changed
942             if ( pOutliner->GetPrevDepth() != -1 && nDepth != -1 &&
943                  aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SFX_ITEM_ON )
944             {
945                 SfxItemSet aAttrs( pOutliner->GetParaAttribs( (sal_uInt16)nPara ) );
946                 aAttrs.Put( *aOldAttrs.GetItem( EE_PARA_NUMBULLET ) );
947                 pOutliner->SetParaAttribs( (sal_uInt16)nPara, aAttrs );
948             }
949         }
950     }
951 
952     InvalidateSlideNumberArea();
953 
954     return 0;
955 }
956 
957 /*************************************************************************
958 |*
959 |* Handler fuer StatusEvents
960 |*
961 \************************************************************************/
962 
IMPL_LINK(OutlineView,StatusEventHdl,EditStatus *,EMPTYARG)963 IMPL_LINK( OutlineView, StatusEventHdl, EditStatus *, EMPTYARG )
964 {
965     ::sd::Window*   pWin = mpOutlineViewShell->GetActiveWindow();
966     OutlinerView*   pOutlinerView = GetViewByWindow(pWin);
967     Rectangle     aVis          = pOutlinerView->GetVisArea();
968 
969 //    sal_uLong nWidth = ((SdPage*)mpDoc->GetSdPage(0, PK_STANDARD))->GetSize().Width();
970     sal_uLong nWidth = OUTLINE_PAPERWIDTH;
971     Rectangle aText = Rectangle(Point(0,0),
972                                    Size(nWidth,
973                                         mpOutliner->GetTextHeight()));
974     Rectangle aWin(Point(0,0), pWin->GetOutputSizePixel());
975     aWin = pWin->PixelToLogic(aWin);
976 
977     if (!aVis.IsEmpty())        // nicht beim Oeffnen
978     {
979         aText.Bottom() += aWin.GetHeight();
980 
981         mpOutlineViewShell->InitWindows(Point(0,0), aText.GetSize(),
982                                        Point(aVis.TopLeft()));
983         mpOutlineViewShell->UpdateScrollBars();
984     }
985 
986     InvalidateSlideNumberArea();
987     return 0;
988 }
989 
IMPL_LINK(OutlineView,BeginDropHdl,void *,EMPTYARG)990 IMPL_LINK( OutlineView, BeginDropHdl, void *, EMPTYARG )
991 {
992     DBG_ASSERT(maDragAndDropModelGuard.get() == 0, "sd::OutlineView::BeginDropHdl(), prior drag operation not finished correctly!" );
993 
994     maDragAndDropModelGuard.reset( new OutlineViewModelChangeGuard( *this ) );
995     return 0;
996 }
997 
IMPL_LINK(OutlineView,EndDropHdl,void *,EMPTYARG)998 IMPL_LINK( OutlineView, EndDropHdl, void *, EMPTYARG )
999 {
1000     maDragAndDropModelGuard.reset(0);
1001     InvalidateSlideNumberArea();
1002     return 0;
1003 }
1004 
1005 /*************************************************************************
1006 |*
1007 |* Handler fuer den Beginn einer Absatzverschiebung
1008 |*
1009 \************************************************************************/
1010 
IMPL_LINK(OutlineView,BeginMovingHdl,::Outliner *,pOutliner)1011 IMPL_LINK( OutlineView, BeginMovingHdl, ::Outliner *, pOutliner )
1012 {
1013     DBG_ASSERT(!mpSelectedParas, "Absatzliste nicht geloescht");
1014     DBG_ASSERT(!mpOldParaOrder, "Absatzliste nicht geloescht");
1015 
1016     OutlineViewPageChangesGuard aGuard(this);
1017 
1018     mpOldParaOrder = new List;
1019 
1020     // Liste der selektierten Titelabsaetze
1021     mpSelectedParas = mpOutlinerView[0]->CreateSelectionList();
1022     Paragraph* pPara = static_cast<Paragraph*>(mpSelectedParas->First());
1023     while (pPara)
1024     {
1025         if( !pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
1026         {
1027             mpSelectedParas->Remove();
1028             pPara = static_cast<Paragraph*>(mpSelectedParas->GetCurObject());
1029         }
1030         else
1031         {
1032             pPara = static_cast<Paragraph*>(mpSelectedParas->Next());
1033         }
1034     }
1035 
1036     // Die zu den selektierten Absaetzen auf Ebene 0 gehoerenden Seiten
1037     // selektieren
1038     sal_uInt16 nPos = 0;
1039     sal_uLong nParaPos = 0;
1040     pPara = pOutliner->GetParagraph( 0 );
1041 
1042     while(pPara)
1043     {
1044         if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )                     // eine Seite?
1045         {
1046             mpOldParaOrder->Insert(pPara, LIST_APPEND);
1047             SdPage* pPage = mpDoc->GetSdPage(nPos, PK_STANDARD);
1048             pPage->SetSelected(sal_False);
1049             if (mpSelectedParas->Seek(pPara))            // selektiert?
1050             {
1051                 pPage->SetSelected(sal_True);
1052             }
1053             nPos++;
1054         }
1055         pPara = pOutliner->GetParagraph( ++nParaPos );
1056     }
1057 
1058     return 0;
1059 }
1060 
1061 /*************************************************************************
1062 |*
1063 |* Handler fuer das Ende einer Absatzverschiebung
1064 |*
1065 \************************************************************************/
1066 
IMPL_LINK(OutlineView,EndMovingHdl,::Outliner *,pOutliner)1067 IMPL_LINK( OutlineView, EndMovingHdl, ::Outliner *, pOutliner )
1068 {
1069     OutlineViewPageChangesGuard aGuard(this);
1070 
1071     DBG_ASSERT(mpSelectedParas, "keine Absatzliste");
1072     DBG_ASSERT(mpOldParaOrder, "keine Absatzliste");
1073     DBG_ASSERT( isRecordingUndo(), "sd::OutlineView::EndMovingHdl(), model change without undo?!" );
1074 
1075     // Einfuegeposition anhand des ersten Absatzes suchen
1076     Paragraph* pSearchIt = (Paragraph*)mpSelectedParas->First();
1077 
1078     // den ersten der selektierten Paragraphen in der neuen Ordnung suchen
1079     sal_uInt16 nPosNewOrder = 0;
1080     sal_uLong nParaPos = 0;
1081     Paragraph*  pPara = pOutliner->GetParagraph( 0 );
1082     Paragraph*  pPrev = NULL;
1083     while (pPara && pPara != pSearchIt)
1084     {
1085         if( pOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
1086         {
1087             nPosNewOrder++;
1088             pPrev = pPara;
1089         }
1090         pPara = pOutliner->GetParagraph( ++nParaPos );
1091     }
1092 
1093     sal_uInt16 nPos = nPosNewOrder;     // nPosNewOrder nicht veraendern
1094     if (nPos == 0)
1095     {
1096         nPos = (sal_uInt16)-1;          // vor der ersten Seite einfuegen
1097     }
1098     else
1099     {
1100         // den Vorgaenger in der alten Ordnung suchen
1101         nPos = (sal_uInt16)mpOldParaOrder->GetPos(pPrev);
1102         DBG_ASSERT(nPos != 0xffff, "Absatz nicht gefunden");
1103     }
1104 
1105     mpDoc->MovePages(nPos);
1106 
1107     // die Seiten wieder deselektieren
1108     sal_uInt16 nPageCount = (sal_uInt16)mpSelectedParas->Count();
1109     while (nPageCount)
1110     {
1111         SdPage* pPage = mpDoc->GetSdPage(nPosNewOrder, PK_STANDARD);
1112         pPage->SetSelected(sal_False);
1113         nPosNewOrder++;
1114         nPageCount--;
1115     }
1116 
1117     pOutliner->UpdateFields();
1118 
1119     delete mpSelectedParas;
1120     mpSelectedParas = NULL;
1121     delete mpOldParaOrder;
1122     mpOldParaOrder = NULL;
1123 
1124     InvalidateSlideNumberArea();
1125 
1126     return 0;
1127 }
1128 
1129 /*************************************************************************
1130 |*
1131 |* Eine Seite des Models nach dem Titeltextobjekt durchsuchen
1132 |*
1133 \************************************************************************/
1134 
GetTitleTextObject(SdrPage * pPage)1135 SdrTextObj* OutlineView::GetTitleTextObject(SdrPage* pPage)
1136 {
1137     sal_uLong           nObjectCount = pPage->GetObjCount();
1138     SdrObject*      pObject      = NULL;
1139     SdrTextObj*     pResult      = NULL;
1140 
1141     for (sal_uLong nObject = 0; nObject < nObjectCount; nObject++)
1142     {
1143         pObject = pPage->GetObj(nObject);
1144         if (pObject->GetObjInventor() == SdrInventor &&
1145             pObject->GetObjIdentifier() == OBJ_TITLETEXT)
1146         {
1147             pResult = (SdrTextObj*)pObject;
1148             break;
1149         }
1150     }
1151     return pResult;
1152 }
1153 
1154 
1155 /*************************************************************************
1156 |*
1157 |* Eine Seite des Models nach dem Gliederungstextobjekt durchsuchen
1158 |*
1159 \************************************************************************/
1160 
GetOutlineTextObject(SdrPage * pPage)1161 SdrTextObj* OutlineView::GetOutlineTextObject(SdrPage* pPage)
1162 {
1163     sal_uLong           nObjectCount = pPage->GetObjCount();
1164     SdrObject*      pObject      = NULL;
1165     SdrTextObj*     pResult      = NULL;
1166 
1167     for (sal_uLong nObject = 0; nObject < nObjectCount; nObject++)
1168     {
1169         pObject = pPage->GetObj(nObject);
1170         if (pObject->GetObjInventor() == SdrInventor &&
1171             pObject->GetObjIdentifier() == OBJ_OUTLINETEXT)
1172         {
1173             pResult = (SdrTextObj*)pObject;
1174             break;
1175         }
1176     }
1177     return pResult;
1178 }
1179 
CreateTitleTextObject(SdPage * pPage)1180 SdrTextObj* OutlineView::CreateTitleTextObject(SdPage* pPage)
1181 {
1182     DBG_ASSERT( GetTitleTextObject(pPage) == 0, "sd::OutlineView::CreateTitleTextObject(), there is already a title text object!" );
1183 
1184     if( pPage->GetAutoLayout() == AUTOLAYOUT_NONE )
1185     {
1186         // simple case
1187         pPage->SetAutoLayout( AUTOLAYOUT_ONLY_TITLE, true );
1188     }
1189     else
1190     {
1191         // we already have a layout with a title but the title
1192         // object was deleted, create a new one
1193         pPage->InsertAutoLayoutShape( 0, PRESOBJ_TITLE, false, pPage->GetTitleRect(), true );
1194     }
1195 
1196     return GetTitleTextObject(pPage);
1197 }
1198 
CreateOutlineTextObject(SdPage * pPage)1199 SdrTextObj* OutlineView::CreateOutlineTextObject(SdPage* pPage)
1200 {
1201     DBG_ASSERT( GetOutlineTextObject(pPage) == 0, "sd::OutlineView::CreateOutlineTextObject(), there is already a layout text object!" );
1202 
1203     AutoLayout eNewLayout = pPage->GetAutoLayout();
1204     switch( eNewLayout )
1205     {
1206     case AUTOLAYOUT_NONE:
1207     case AUTOLAYOUT_ONLY_TITLE:
1208     case AUTOLAYOUT_TITLE:  eNewLayout = AUTOLAYOUT_ENUM; break;
1209 
1210     case AUTOLAYOUT_CHART:  eNewLayout = AUTOLAYOUT_CHARTTEXT; break;
1211 
1212     case AUTOLAYOUT_ORG:
1213     case AUTOLAYOUT_TAB:
1214     case AUTOLAYOUT_OBJ:    eNewLayout = AUTOLAYOUT_OBJTEXT; break;
1215     default:
1216         break;
1217     }
1218 
1219     if( eNewLayout != pPage->GetAutoLayout() )
1220     {
1221         pPage->SetAutoLayout( eNewLayout, true );
1222     }
1223     else
1224     {
1225         // we already have a layout with a text but the text
1226         // object was deleted, create a new one
1227         pPage->InsertAutoLayoutShape( 0,
1228                                       (eNewLayout == AUTOLAYOUT_TITLE) ? PRESOBJ_TEXT : PRESOBJ_OUTLINE,
1229                                       false, pPage->GetLayoutRect(), true );
1230     }
1231 
1232     return GetOutlineTextObject(pPage);
1233 }
1234 
1235 /** updates draw model with all changes from outliner model */
PrepareClose(sal_Bool)1236 sal_Bool OutlineView::PrepareClose(sal_Bool)
1237 {
1238     ::sd::UndoManager* pDocUndoMgr = dynamic_cast<sd::UndoManager*>(mpDocSh->GetUndoManager());
1239     if (pDocUndoMgr != NULL)
1240         pDocUndoMgr->SetLinkedUndoManager(NULL);
1241 
1242     mpOutliner->GetUndoManager().Clear();
1243 
1244     const String aUndoStr(SdResId(STR_UNDO_CHANGE_TITLE_AND_LAYOUT));
1245     BegUndo(aUndoStr);
1246     UpdateDocument();
1247     EndUndo();
1248     mpDoc->SetSelected(GetActualPage(), sal_True);
1249     return sal_True;
1250 }
1251 
1252 
1253 /*************************************************************************
1254 |*
1255 |* Attribute des selektierten Textes setzen
1256 |*
1257 \************************************************************************/
1258 
SetAttributes(const SfxItemSet & rSet,sal_Bool)1259 sal_Bool OutlineView::SetAttributes(const SfxItemSet& rSet, sal_Bool )
1260 {
1261     sal_Bool bOk = sal_False;
1262 
1263     OutlinerView* pOlView = GetViewByWindow(mpOutlineViewShell->GetActiveWindow());
1264 
1265     if (pOlView)
1266     {
1267         pOlView->SetAttribs(rSet);
1268         bOk = sal_True;
1269     }
1270 
1271     mpOutlineViewShell->Invalidate (SID_PREVIEW_STATE);
1272 
1273     return (bOk);
1274 }
1275 
1276 /*************************************************************************
1277 |*
1278 |* Attribute des selektierten Textes erfragen
1279 |*
1280 \************************************************************************/
1281 
GetAttributes(SfxItemSet & rTargetSet,sal_Bool) const1282 sal_Bool OutlineView::GetAttributes( SfxItemSet& rTargetSet, sal_Bool ) const
1283 {
1284     OutlinerView* pOlView = GetViewByWindow(
1285                                 mpOutlineViewShell->GetActiveWindow());
1286     DBG_ASSERT(pOlView, "keine OutlinerView gefunden");
1287 
1288     rTargetSet.Put( pOlView->GetAttribs(), sal_False );
1289     return sal_True;
1290 }
1291 
1292 /** creates outliner model from draw model */
FillOutliner()1293 void OutlineView::FillOutliner()
1294 {
1295     mpOutliner->GetUndoManager().Clear();
1296     mpOutliner->EnableUndo(sal_False);
1297     ResetLinks();
1298     mpOutliner->SetUpdateMode(false);
1299 
1300     Paragraph* pTitleToSelect = NULL;
1301     sal_uLong nPageCount = mpDoc->GetSdPageCount(PK_STANDARD);
1302 
1303     // fill outliner with paragraphs from slides title & (outlines|subtitles)
1304     for (sal_uInt16 nPage = 0; nPage < nPageCount; nPage++)
1305     {
1306         SdPage*     pPage = (SdPage*)mpDoc->GetSdPage(nPage, PK_STANDARD);
1307         Paragraph * pPara = NULL;
1308 
1309         // take text from title shape
1310         SdrTextObj* pTO = GetTitleTextObject(pPage);
1311         if(pTO && !(pTO->IsEmptyPresObj()))
1312         {
1313             OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1314             if (pOPO)
1315             {
1316                 sal_Bool bVertical = pOPO->IsVertical();
1317                 pOPO->SetVertical( sal_False );
1318                 mpOutliner->AddText(*pOPO);
1319                 pOPO->SetVertical( bVertical );
1320                 pPara = mpOutliner->GetParagraph( mpOutliner->GetParagraphCount()-1 );
1321             }
1322         }
1323 
1324         if( pPara == 0 ) // no title, insert an empty paragraph
1325         {
1326             pPara = mpOutliner->Insert(String());
1327             mpOutliner->SetDepth(pPara, -1);
1328 
1329             // Keine harten Attribute vom vorherigen Absatz uebernehmen
1330             mpOutliner->SetParaAttribs( (sal_uInt16)mpOutliner->GetAbsPos(pPara),
1331                                        mpOutliner->GetEmptyItemSet() );
1332 
1333             mpOutliner->SetStyleSheet( mpOutliner->GetAbsPos( pPara ), pPage->GetStyleSheetForPresObj( PRESOBJ_TITLE ) );
1334         }
1335 
1336         mpOutliner->SetParaFlag( pPara, PARAFLAG_ISPAGE );
1337 
1338         sal_uLong nPara = mpOutliner->GetAbsPos( pPara );
1339 
1340         UpdateParagraph( (sal_uInt16)nPara );
1341 
1342         // remember paragraph of currently selected page
1343         if (pPage->IsSelected())
1344             pTitleToSelect = pPara;
1345 
1346         // take text from subtitle or outline
1347         pTO = static_cast<SdrTextObj*>(pPage->GetPresObj(PRESOBJ_TEXT));
1348         const bool bSubTitle = pTO != 0;
1349 
1350         if (!pTO) // if no subtile found, try outline
1351             pTO = GetOutlineTextObject(pPage);
1352 
1353         if(pTO && !(pTO->IsEmptyPresObj())) // found some text
1354         {
1355             OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1356             if (pOPO)
1357             {
1358                 sal_uInt16 nParaCount1 = (sal_uInt16)mpOutliner->GetParagraphCount();
1359                 sal_Bool bVertical = pOPO->IsVertical();
1360                 pOPO->SetVertical( sal_False );
1361                 mpOutliner->AddText(*pOPO);
1362                 pOPO->SetVertical( bVertical );
1363 
1364                 sal_uInt16 nParaCount2 = (sal_uInt16)mpOutliner->GetParagraphCount();
1365                 for (sal_uInt16 n = nParaCount1; n < nParaCount2; n++)
1366                 {
1367                     if( bSubTitle )
1368                     {
1369                         Paragraph* p = mpOutliner->GetParagraph(n);
1370                         if(p && mpOutliner->GetDepth( n ) > 0 )
1371                             mpOutliner->SetDepth(p, 0);
1372                     }
1373 
1374                     UpdateParagraph( n );
1375                 }
1376             }
1377         }
1378     }
1379 
1380     // place cursor at the start
1381     Paragraph* pFirstPara = mpOutliner->GetParagraph( 0 );
1382     mpOutlinerView[0]->Select( pFirstPara, sal_True, sal_False );
1383     mpOutlinerView[0]->Select( pFirstPara, sal_False, sal_False );
1384 
1385     // select title of slide that was selected
1386     if (pTitleToSelect)
1387         mpOutlinerView[0]->Select(pTitleToSelect, sal_True, sal_False);
1388 
1389     SetLinks();
1390 
1391     mpOutliner->EnableUndo(sal_True);
1392 
1393     mpOutliner->SetUpdateMode(true);
1394 }
1395 
1396 /*************************************************************************
1397 |*
1398 |* Handler fuer das Loeschen von Level-0-Absaetzen (Seiten): Warnung
1399 |*
1400 \************************************************************************/
1401 
IMPL_LINK(OutlineView,RemovingPagesHdl,OutlinerView *,EMPTYARG)1402 IMPL_LINK( OutlineView, RemovingPagesHdl, OutlinerView *, EMPTYARG )
1403 {
1404     sal_uInt16 nNumOfPages = mpOutliner->GetSelPageCount();
1405 
1406     if (nNumOfPages > PROCESS_WITH_PROGRESS_THRESHOLD)
1407     {
1408         mnPagesToProcess = nNumOfPages;
1409         mnPagesProcessed  = 0;
1410     }
1411 
1412     if (mnPagesToProcess)
1413     {
1414         if( mpProgress )
1415             delete mpProgress;
1416 
1417         String aStr(SdResId(STR_DELETE_PAGES));
1418         mpProgress = new SfxProgress( GetDocSh(), aStr, mnPagesToProcess );
1419     }
1420     mpOutliner->UpdateFields();
1421 
1422     InvalidateSlideNumberArea();
1423 
1424     return 1;
1425 }
1426 
1427 /*************************************************************************
1428 |*
1429 |* Handler fuer das Einruecken von Level-0-Absaetzen (Seiten): Warnung
1430 |*
1431 \************************************************************************/
1432 
IMPL_LINK_INLINE_START(OutlineView,IndentingPagesHdl,OutlinerView *,pOutlinerView)1433 IMPL_LINK_INLINE_START( OutlineView, IndentingPagesHdl, OutlinerView *, pOutlinerView )
1434 {
1435     return RemovingPagesHdl(pOutlinerView);
1436 }
IMPL_LINK_INLINE_END(OutlineView,IndentingPagesHdl,OutlinerView *,pOutlinerView)1437 IMPL_LINK_INLINE_END( OutlineView, IndentingPagesHdl, OutlinerView *, pOutlinerView )
1438 
1439 
1440 /** returns the first slide that is selected in the outliner or where
1441     the cursor is located */
1442 SdPage* OutlineView::GetActualPage()
1443 {
1444     ::sd::Window* pWin = mpOutlineViewShell->GetActiveWindow();
1445     OutlinerView* pActiveView = GetViewByWindow(pWin);
1446     std::auto_ptr<List> pSelList( static_cast< List* >(pActiveView->CreateSelectionList()) );
1447 
1448     SdPage* pCurrent = GetPageForParagraph(static_cast<Paragraph*>(pSelList->First()) );
1449     DBG_ASSERT( pCurrent ||
1450                 (mpDocSh->GetUndoManager() && static_cast< sd::UndoManager *>(mpDocSh->GetUndoManager())->IsDoing()) ||
1451                 maDragAndDropModelGuard.get(),
1452                 "sd::OutlineView::GetActualPage(), no current page?" );
1453     if( pCurrent )
1454         return pCurrent;
1455     else
1456         return mpDoc->GetSdPage( 0, PK_STANDARD );
1457 }
1458 
GetPageForParagraph(Paragraph * pPara)1459 SdPage* OutlineView::GetPageForParagraph( Paragraph* pPara )
1460 {
1461     if( !mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1462         pPara = GetPrevTitle(pPara);
1463 
1464     sal_uInt32 nPageToSelect = 0;
1465     while(pPara)
1466     {
1467         pPara = GetPrevTitle(pPara);
1468         if(pPara)
1469             nPageToSelect++;
1470     }
1471 
1472     if( nPageToSelect < (sal_uInt32)mpDoc->GetSdPageCount( PK_STANDARD ) )
1473         return static_cast< SdPage* >( mpDoc->GetSdPage( (sal_uInt16)nPageToSelect, PK_STANDARD) );
1474     else
1475         return 0;
1476 }
1477 
GetParagraphForPage(::Outliner * pOutl,SdPage * pPage)1478 Paragraph* OutlineView::GetParagraphForPage( ::Outliner* pOutl, SdPage* pPage )
1479 {
1480     // get the number of paragraphs with ident 0 we need to skip before
1481     // we finde the actual page
1482     sal_uInt32 nPagesToSkip = (pPage->GetPageNum() - 1) >> 1;
1483 
1484     sal_uInt32 nParaPos = 0;
1485     Paragraph* pPara = pOutl->GetParagraph( 0 );
1486     while( pPara )
1487     {
1488         // if this paragraph is a page ...
1489         if( mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1490         {
1491             // see if we already skiped enough pages
1492             if( 0 == nPagesToSkip )
1493                 break;  // and if so, end the loop
1494 
1495             // we skiped another page
1496             nPagesToSkip--;
1497         }
1498 
1499         // get next paragraph
1500         pPara = mpOutliner->GetParagraph( ++nParaPos );
1501     }
1502 
1503     return pPara;
1504 }
1505 
1506 /** selects the paragraph for the given page at the outliner view*/
SetActualPage(SdPage * pActual)1507 void OutlineView::SetActualPage( SdPage* pActual )
1508 {
1509     if( pActual && mpOutliner && dynamic_cast<Outliner*> ( mpOutliner )->GetIgnoreCurrentPageChangesLevel()==0 && !mbFirstPaint)
1510     {
1511         // if we found a paragraph, select its text at the outliner view
1512         Paragraph* pPara = GetParagraphForPage( mpOutliner, pActual );
1513         if( pPara )
1514             mpOutlinerView[0]->Select( pPara, sal_True, sal_False );
1515     }
1516 }
1517 
1518 /*************************************************************************
1519 |*
1520 |* StyleSheet aus der Selektion besorgen
1521 |*
1522 \************************************************************************/
1523 
GetStyleSheet() const1524 SfxStyleSheet* OutlineView::GetStyleSheet() const
1525 {
1526     ::sd::Window* pActWin = mpOutlineViewShell->GetActiveWindow();
1527     OutlinerView* pOlView = GetViewByWindow(pActWin);
1528     SfxStyleSheet* pResult = pOlView->GetStyleSheet();
1529     return pResult;
1530 }
1531 
1532 
1533 
1534 /*************************************************************************
1535 |*
1536 |* Seiten als selektiert / nicht selektiert setzen
1537 |*
1538 \************************************************************************/
1539 
SetSelectedPages()1540 void OutlineView::SetSelectedPages()
1541 {
1542     // Liste der selektierten Titelabsaetze
1543     List* pSelParas = mpOutlinerView[0]->CreateSelectionList();
1544     Paragraph* pPara = (Paragraph*) pSelParas->First();
1545 
1546     while(pPara)
1547     {
1548         if( !mpOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )
1549         {
1550             pSelParas->Remove();
1551             pPara = (Paragraph*) pSelParas->GetCurObject();
1552         }
1553         else
1554         {
1555             pPara = (Paragraph*) pSelParas->Next();
1556         }
1557     }
1558 
1559     // Die zu den selektierten Absaetzen auf Ebene 0 gehoerenden Seiten
1560     // selektieren
1561     sal_uInt16 nPos = 0;
1562     sal_uLong nParaPos = 0;
1563     pPara = mpOutliner->GetParagraph( 0 );
1564 
1565     while(pPara)
1566     {
1567         if( mpOutliner->HasParaFlag(pPara, PARAFLAG_ISPAGE) )                     // eine Seite?
1568         {
1569             SdPage* pPage = mpDoc->GetSdPage(nPos, PK_STANDARD);
1570             DBG_ASSERT(pPage!=NULL,
1571                 "Trying to select non-existing page OutlineView::SetSelectedPages()");
1572             if (pPage != NULL)
1573             {
1574                 pPage->SetSelected(sal_False);
1575 
1576                 if (pSelParas->Seek(pPara))            // selektiert?
1577                     pPage->SetSelected(sal_True);
1578             }
1579 
1580             nPos++;
1581         }
1582 
1583         pPara = mpOutliner->GetParagraph( ++nParaPos );
1584     }
1585 }
1586 
1587 
1588 /*************************************************************************
1589 |*
1590 |* Neue Links setzen
1591 |*
1592 \************************************************************************/
1593 
SetLinks()1594 void OutlineView::SetLinks()
1595 {
1596     // Benachrichtigungs-Links setzen
1597     mpOutliner->SetParaInsertedHdl(LINK(this, OutlineView, ParagraphInsertedHdl));
1598     mpOutliner->SetParaRemovingHdl(LINK(this, OutlineView, ParagraphRemovingHdl));
1599     mpOutliner->SetDepthChangedHdl(LINK(this, OutlineView, DepthChangedHdl));
1600     mpOutliner->SetBeginMovingHdl(LINK(this, OutlineView, BeginMovingHdl));
1601     mpOutliner->SetEndMovingHdl(LINK(this, OutlineView, EndMovingHdl));
1602     mpOutliner->SetRemovingPagesHdl(LINK(this, OutlineView, RemovingPagesHdl));
1603     mpOutliner->SetIndentingPagesHdl(LINK(this, OutlineView, IndentingPagesHdl));
1604     mpOutliner->SetStatusEventHdl(LINK(this, OutlineView, StatusEventHdl));
1605     mpOutliner->SetBeginDropHdl(LINK(this,OutlineView, BeginDropHdl));
1606     mpOutliner->SetEndDropHdl(LINK(this,OutlineView, EndDropHdl));
1607     mpOutliner->SetPaintFirstLineHdl(LINK(this,OutlineView,PaintingFirstLineHdl));
1608     mpOutliner->SetBeginPasteOrDropHdl(LINK(this,OutlineView, BeginPasteOrDropHdl));
1609     mpOutliner->SetEndPasteOrDropHdl(LINK(this,OutlineView, EndPasteOrDropHdl));
1610 }
1611 
1612 
1613 
1614 /*************************************************************************
1615 |*
1616 |* Alte Links restaurieren
1617 |*
1618 \************************************************************************/
1619 
ResetLinks() const1620 void OutlineView::ResetLinks() const
1621 {
1622     // alte Links restaurieren
1623     Link aEmptyLink;
1624     mpOutliner->SetParaInsertedHdl(aEmptyLink);
1625     mpOutliner->SetParaRemovingHdl(aEmptyLink);
1626     mpOutliner->SetDepthChangedHdl(aEmptyLink);
1627     mpOutliner->SetBeginMovingHdl(aEmptyLink);
1628     mpOutliner->SetEndMovingHdl(aEmptyLink);
1629     mpOutliner->SetStatusEventHdl(aEmptyLink);
1630     mpOutliner->SetRemovingPagesHdl(aEmptyLink);
1631     mpOutliner->SetIndentingPagesHdl(aEmptyLink);
1632     mpOutliner->SetDrawPortionHdl(aEmptyLink);
1633     mpOutliner->SetBeginPasteOrDropHdl(aEmptyLink);
1634     mpOutliner->SetEndPasteOrDropHdl(aEmptyLink);
1635 }
1636 
1637 /*************************************************************************
1638 |*
1639 |* AcceptDrop
1640 |*
1641 \************************************************************************/
1642 
AcceptDrop(const AcceptDropEvent &,DropTargetHelper &,::sd::Window *,sal_uInt16,sal_uInt16)1643 sal_Int8 OutlineView::AcceptDrop( const AcceptDropEvent&, DropTargetHelper&, ::sd::Window*, sal_uInt16, sal_uInt16)
1644 {
1645     return DND_ACTION_NONE;
1646 }
1647 
1648 /*************************************************************************
1649 |*
1650 |* ExecuteDrop
1651 |*
1652 \************************************************************************/
1653 
ExecuteDrop(const ExecuteDropEvent &,DropTargetHelper &,::sd::Window *,sal_uInt16,sal_uInt16)1654 sal_Int8 OutlineView::ExecuteDrop( const ExecuteDropEvent&, DropTargetHelper&, ::sd::Window*, sal_uInt16, sal_uInt16)
1655 {
1656     return DND_ACTION_NONE;
1657 }
1658 
1659 // #97766# Re-implement GetScriptType for this view to get correct results
GetScriptType() const1660 sal_uInt16 OutlineView::GetScriptType() const
1661 {
1662     sal_uInt16 nScriptType = ::sd::View::GetScriptType();
1663 
1664     if(mpOutliner)
1665     {
1666         OutlinerParaObject* pTempOPObj = mpOutliner->CreateParaObject();
1667 
1668         if(pTempOPObj)
1669         {
1670             nScriptType = pTempOPObj->GetTextObject().GetScriptType();
1671             delete pTempOPObj;
1672         }
1673     }
1674 
1675     return nScriptType;
1676 }
1677 
onUpdateStyleSettings(bool bForceUpdate)1678 void OutlineView::onUpdateStyleSettings( bool bForceUpdate /* = false */ )
1679 {
1680     const bool bHighContrastMode = Application::GetSettings().GetStyleSettings().GetHighContrastMode() != 0;
1681     if( bForceUpdate || (mbHighContrastMode != bHighContrastMode) )
1682     {
1683         if( mpOutliner )
1684         {
1685             mpOutliner->ForceAutoColor( bHighContrastMode );
1686         }
1687         mbHighContrastMode = bHighContrastMode;
1688 
1689     }
1690 
1691     svtools::ColorConfig aColorConfig;
1692     const Color aDocColor( aColorConfig.GetColorValue( svtools::DOCCOLOR ).nColor );
1693     if( bForceUpdate || (maDocColor != aDocColor) )
1694     {
1695         sal_uInt16 nView;
1696         for( nView = 0; nView < MAX_OUTLINERVIEWS; nView++ )
1697         {
1698             if (mpOutlinerView[nView] != NULL)
1699             {
1700                 mpOutlinerView[nView]->SetBackgroundColor( aDocColor );
1701 
1702                 ::Window* pWindow = mpOutlinerView[nView]->GetWindow();
1703 
1704                 if( pWindow )
1705                     pWindow->SetBackground( Wallpaper( aDocColor ) );
1706 
1707             }
1708         }
1709 
1710         if( mpOutliner )
1711             mpOutliner->SetBackgroundColor( aDocColor );
1712 
1713         maDocColor = aDocColor;
1714     }
1715 }
1716 
IMPL_LINK(OutlineView,AppEventListenerHdl,void *,EMPTYARG)1717 IMPL_LINK( OutlineView, AppEventListenerHdl, void *, EMPTYARG )
1718 {
1719     onUpdateStyleSettings();
1720     return 0;
1721 }
1722 
1723 
1724 
1725 
IMPL_LINK(OutlineView,EventMultiplexerListener,::sd::tools::EventMultiplexerEvent *,pEvent)1726 IMPL_LINK(OutlineView, EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent*, pEvent)
1727 {
1728     if (pEvent != NULL)
1729     {
1730         switch (pEvent->meEventId)
1731         {
1732             case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
1733                 SetActualPage(mpOutlineViewShell->GetActualPage());
1734                 InvalidateSlideNumberArea();
1735                 break;
1736 
1737             case tools::EventMultiplexerEvent::EID_PAGE_ORDER:
1738                 if (mpOutliner != NULL && mpDoc!=NULL && mpOutliner != NULL && dynamic_cast<Outliner*> ( mpOutliner )->GetIgnoreCurrentPageChangesLevel()==0)
1739                 {
1740                     if (((mpDoc->GetPageCount()-1)%2) == 0)
1741                     {
1742                         mpOutliner->Clear();
1743                         FillOutliner();
1744                         ::sd::Window* pWindow = mpOutlineViewShell->GetActiveWindow();
1745                         if (pWindow != NULL)
1746                             pWindow->Invalidate();
1747                     }
1748                 }
1749                 break;
1750         }
1751     }
1752     return 0;
1753 }
1754 
IgnoreCurrentPageChanges(bool bIgnoreChanges)1755 void OutlineView::IgnoreCurrentPageChanges (bool bIgnoreChanges)
1756 {
1757     if ( mpOutliner )
1758     {
1759         if (bIgnoreChanges)
1760             dynamic_cast<Outliner*> ( mpOutliner )->IncreIgnoreCurrentPageChangesLevel();
1761         else
1762             dynamic_cast<Outliner*> ( mpOutliner )->DecreIgnoreCurrentPageChangesLevel();
1763     }
1764 }
1765 
1766 /** call this method before you do anything that can modify the outliner
1767     and or the drawing document model. It will create needed undo actions */
BeginModelChange()1768 void OutlineView::BeginModelChange()
1769 {
1770     const String aEmpty;
1771     mpOutliner->GetUndoManager().EnterListAction(aEmpty,aEmpty);
1772     const String aUndoStr(SdResId(STR_UNDO_CHANGE_TITLE_AND_LAYOUT));
1773     BegUndo(aUndoStr);
1774 }
1775 
1776 /** call this method after BeginModelChange(), when all possible model
1777     changes are done. */
EndModelChange()1778 void OutlineView::EndModelChange()
1779 {
1780     UpdateDocument();
1781 
1782     ::svl::IUndoManager* pDocUndoMgr = mpDocSh->GetUndoManager();
1783 
1784     bool bHasUndoActions = pDocUndoMgr->GetUndoActionCount() != 0;
1785 
1786     EndUndo();
1787 
1788     DBG_ASSERT( bHasUndoActions == (mpOutliner->GetUndoManager().GetUndoActionCount() != 0), "sd::OutlineView::EndModelChange(), undo actions not in sync!" );
1789 
1790     if( bHasUndoActions )
1791     {
1792         SfxLinkUndoAction* pLink = new SfxLinkUndoAction(pDocUndoMgr);
1793         mpOutliner->GetUndoManager().AddUndoAction(pLink);
1794     }
1795 
1796     mpOutliner->GetUndoManager().LeaveListAction();
1797 
1798     if( bHasUndoActions && mpOutliner->GetEditEngine().HasTriedMergeOnLastAddUndo() )
1799         TryToMergeUndoActions();
1800 
1801     mpOutlineViewShell->Invalidate( SID_UNDO );
1802     mpOutlineViewShell->Invalidate( SID_REDO );
1803 }
1804 
1805 /** updates all changes in the outliner model to the draw model */
UpdateDocument()1806 void OutlineView::UpdateDocument()
1807 {
1808     const sal_uInt32 nPageCount = mpDoc->GetSdPageCount(PK_STANDARD);
1809     Paragraph* pPara = mpOutliner->GetParagraph( 0 );
1810     sal_uInt32 nPage;
1811     for (nPage = 0; nPage < nPageCount; nPage++)
1812     {
1813         SdPage* pPage = mpDoc->GetSdPage( (sal_uInt16)nPage, PK_STANDARD);
1814         mpDoc->SetSelected(pPage, sal_False);
1815 
1816         mpOutlineViewShell->UpdateTitleObject( pPage, pPara );
1817         mpOutlineViewShell->UpdateOutlineObject( pPage, pPara );
1818 
1819         if( pPara )
1820             pPara = GetNextTitle(pPara);
1821     }
1822 
1823     DBG_ASSERT( pPara == 0, "sd::OutlineView::UpdateDocument(), slides are out of sync, creating missing ones" );
1824     while( pPara )
1825     {
1826         SdPage* pPage = InsertSlideForParagraph( pPara );
1827         mpDoc->SetSelected(pPage, sal_False);
1828 
1829         mpOutlineViewShell->UpdateTitleObject( pPage, pPara );
1830         mpOutlineViewShell->UpdateOutlineObject( pPage, pPara );
1831 
1832         if( pPara )
1833             pPara = GetNextTitle(pPara);
1834     }
1835 }
1836 
1837 /** merge edit engine undo actions if possible */
TryToMergeUndoActions()1838 void OutlineView::TryToMergeUndoActions()
1839 {
1840     ::svl::IUndoManager& rOutlineUndo = mpOutliner->GetUndoManager();
1841     if( rOutlineUndo.GetUndoActionCount() > 1 )
1842     {
1843         SfxListUndoAction* pListAction = dynamic_cast< SfxListUndoAction* >( rOutlineUndo.GetUndoAction(0) );
1844         SfxListUndoAction* pPrevListAction = dynamic_cast< SfxListUndoAction* >( rOutlineUndo.GetUndoAction(1) );
1845         if( pListAction && pPrevListAction )
1846         {
1847             // find the top EditUndo action in the top undo action list
1848             size_t nAction = pListAction->aUndoActions.size();
1849             EditUndo* pEditUndo = 0;
1850             while( !pEditUndo && nAction )
1851             {
1852                 pEditUndo = dynamic_cast< EditUndo* >(pListAction->aUndoActions[--nAction].pAction);
1853             }
1854 
1855             sal_uInt16 nEditPos = nAction; // we need this later to remove the merged undo actions
1856 
1857             // make sure it is the only EditUndo action in the top undo list
1858             while( pEditUndo && nAction )
1859             {
1860                 if( dynamic_cast< EditUndo* >(pListAction->aUndoActions[--nAction].pAction) )
1861                     pEditUndo = 0;
1862             }
1863 
1864             // do we have one and only one EditUndo action in the top undo list?
1865             if( pEditUndo )
1866             {
1867                 // yes, see if we can merge it with the prev undo list
1868 
1869                 nAction = pPrevListAction->aUndoActions.size();
1870                 EditUndo* pPrevEditUndo = 0;
1871                 while( !pPrevEditUndo && nAction )
1872                     pPrevEditUndo = dynamic_cast< EditUndo* >(pPrevListAction->aUndoActions[--nAction].pAction);
1873 
1874                 if( pPrevEditUndo && pPrevEditUndo->Merge( pEditUndo ) )
1875                 {
1876                     // ok we merged the only EditUndo of the top undo list with
1877                     // the top EditUndo of the previous undo list
1878 
1879                     // first remove the merged undo action
1880                     DBG_ASSERT( pListAction->aUndoActions[nEditPos].pAction == pEditUndo,
1881                         "sd::OutlineView::TryToMergeUndoActions(), wrong edit pos!" );
1882                     pListAction->aUndoActions.Remove(nEditPos);
1883                     delete pEditUndo;
1884 
1885                     // now check if we also can merge the draw undo actions
1886                     ::svl::IUndoManager* pDocUndoManager = mpDocSh->GetUndoManager();
1887                     if( pDocUndoManager && ( pListAction->aUndoActions.size() == 1 ))
1888                     {
1889                         SfxLinkUndoAction* pLinkAction = dynamic_cast< SfxLinkUndoAction* >( pListAction->aUndoActions[0].pAction );
1890                         SfxLinkUndoAction* pPrevLinkAction = 0;
1891 
1892                         if( pLinkAction )
1893                         {
1894                             nAction = pPrevListAction->aUndoActions.size();
1895                             while( !pPrevLinkAction && nAction )
1896                                 pPrevLinkAction = dynamic_cast< SfxLinkUndoAction* >(pPrevListAction->aUndoActions[--nAction].pAction);
1897                         }
1898 
1899                         if( pLinkAction && pPrevLinkAction &&
1900                             ( pLinkAction->GetAction() == pDocUndoManager->GetUndoAction(0) ) &&
1901                             ( pPrevLinkAction->GetAction() == pDocUndoManager->GetUndoAction(1) ) )
1902                         {
1903                             SfxListUndoAction* pSourceList = dynamic_cast< SfxListUndoAction* >(pLinkAction->GetAction());
1904                             SfxListUndoAction* pDestinationList = dynamic_cast< SfxListUndoAction* >(pPrevLinkAction->GetAction());
1905 
1906                             if( pSourceList && pDestinationList )
1907                             {
1908                                 sal_uInt16 nCount = pSourceList->aUndoActions.size();
1909                                 sal_uInt16 nDestAction = pDestinationList->aUndoActions.size();
1910                                 while( nCount-- )
1911                                 {
1912                                     SfxUndoAction* pTemp = pSourceList->aUndoActions[0].pAction;
1913                                     pSourceList->aUndoActions.Remove(0);
1914                                     pDestinationList->aUndoActions.Insert( pTemp, nDestAction++ );
1915                                 }
1916                                 pDestinationList->nCurUndoAction = pDestinationList->aUndoActions.size();
1917 
1918                                 pListAction->aUndoActions.Remove(0);
1919                                 delete pLinkAction;
1920 
1921                                 pDocUndoManager->RemoveLastUndoAction();
1922                             }
1923                         }
1924                     }
1925 
1926                     if ( !pListAction->aUndoActions.empty() )
1927                     {
1928                         // now we have to move all remaining doc undo actions from the top undo
1929                         // list to the previous undo list and remove the top undo list
1930 
1931                         size_t nCount = pListAction->aUndoActions.size();
1932                         size_t nDestAction = pPrevListAction->aUndoActions.size();
1933                         while( nCount-- )
1934                         {
1935                             SfxUndoAction* pTemp = pListAction->aUndoActions[0].pAction;
1936                             pListAction->aUndoActions.Remove(0);
1937                             if( pTemp )
1938                                 pPrevListAction->aUndoActions.Insert( pTemp, nDestAction++ );
1939                         }
1940                         pPrevListAction->nCurUndoAction = pPrevListAction->aUndoActions.size();
1941                     }
1942 
1943                     rOutlineUndo.RemoveLastUndoAction();
1944                 }
1945             }
1946         }
1947     }
1948 }
1949 
IMPL_LINK(OutlineView,PaintingFirstLineHdl,PaintFirstLineInfo *,pInfo)1950 IMPL_LINK(OutlineView, PaintingFirstLineHdl, PaintFirstLineInfo*, pInfo)
1951 {
1952     if( pInfo && mpOutliner )
1953     {
1954         Paragraph* pPara = mpOutliner->GetParagraph( pInfo->mnPara );
1955         EditEngine& rEditEngine = const_cast< EditEngine& >( mpOutliner->GetEditEngine() );
1956 
1957         Size aImageSize( pInfo->mpOutDev->PixelToLogic( maSlideImage.GetSizePixel()  ) );
1958         Size aOffset( 100, 100 );
1959 
1960         // paint slide number
1961         if( pPara && mpOutliner->HasParaFlag(pPara,PARAFLAG_ISPAGE) )
1962         {
1963             long nPage = 0; // todo, printing??
1964             for ( sal_uInt16 n = 0; n <= pInfo->mnPara; n++ )
1965             {
1966                 Paragraph* p = mpOutliner->GetParagraph( n );
1967                 if ( mpOutliner->HasParaFlag(p,PARAFLAG_ISPAGE) )
1968                     nPage++;
1969             }
1970 
1971             long nBulletHeight = (long)mpOutliner->GetLineHeight( pInfo->mnPara );
1972             long nFontHeight = 0;
1973             if ( !rEditEngine.IsFlatMode() )
1974             {
1975 //              const SvxFontHeightItem& rFH = (const SvxFontHeightItem&)rEditEngine.GetParaAttrib( pInfo->mnPara, EE_CHAR_FONTHEIGHT );
1976 //              nBulletHeight = rFH.GetHeight();
1977                 nFontHeight = nBulletHeight / 5;
1978             }
1979             else
1980             {
1981 //              const SvxFontHeightItem& rFH = (const SvxFontHeightItem&)rEditEngine.GetEmptyItemSet().Get( EE_CHAR_FONTHEIGHT );
1982  //               nBulletHeight = rFH.GetHeight();
1983                 nFontHeight = (nBulletHeight * 10) / 25;
1984             }
1985 
1986             Size aFontSz( 0, nFontHeight );
1987 
1988             Size aOutSize( 2000, nBulletHeight );
1989 
1990             const float fImageHeight = ((float)aOutSize.Height() * (float)4) / (float)7;
1991             const float fImageRatio  = (float)aImageSize.Height() / (float)aImageSize.Width();
1992             aImageSize.Width() = (long)( fImageRatio * fImageHeight );
1993             aImageSize.Height() = (long)( fImageHeight );
1994 
1995             Point aImagePos( pInfo->mrStartPos );
1996             aImagePos.X() += aOutSize.Width() - aImageSize.Width() - aOffset.Width() ;
1997             aImagePos.Y() += (aOutSize.Height() - aImageSize.Height()) / 2;
1998 
1999             pInfo->mpOutDev->DrawImage( aImagePos, aImageSize, maSlideImage );
2000 
2001             const bool bVertical = mpOutliner->IsVertical();
2002             const bool bRightToLeftPara = rEditEngine.IsRightToLeft( pInfo->mnPara );
2003 
2004             LanguageType eLang = rEditEngine.GetDefaultLanguage();
2005 
2006             Point aTextPos( aImagePos.X() - aOffset.Width(), pInfo->mrStartPos.Y() );
2007             Font aNewFont( OutputDevice::GetDefaultFont( DEFAULTFONT_SANS_UNICODE, eLang, 0 ) );
2008             aNewFont.SetSize( aFontSz );
2009 //          aNewFont.SetAlign( aBulletFont.GetAlign() );
2010             aNewFont.SetVertical( bVertical );
2011             aNewFont.SetOrientation( bVertical ? 2700 : 0 );
2012             aNewFont.SetColor( COL_AUTO );
2013             pInfo->mpOutDev->SetFont( aNewFont );
2014             String aPageText = String::CreateFromInt32( nPage );
2015             Size aTextSz;
2016             aTextSz.Width() = pInfo->mpOutDev->GetTextWidth( aPageText );
2017             aTextSz.Height() = pInfo->mpOutDev->GetTextHeight();
2018 //            long nBulletHeight = !bVertical ? aBulletArea.GetHeight() : aBulletArea.GetWidth();
2019             if ( !bVertical )
2020             {
2021                 aTextPos.Y() += (aOutSize.Height() - aTextSz.Height()) / 2;
2022                 if ( !bRightToLeftPara )
2023                 {
2024                     aTextPos.X() -= aTextSz.Width();
2025                 }
2026                 else
2027                 {
2028                     aTextPos.X() += aTextSz.Width();
2029                 }
2030             }
2031             else
2032             {
2033                 aTextPos.Y() -= aTextSz.Width();
2034                 aTextPos.X() += nBulletHeight / 2;
2035             }
2036             pInfo->mpOutDev->DrawText( aTextPos, aPageText );
2037         }
2038     }
2039 
2040     return 0;
2041 }
2042 
2043 #if 0
2044 sal_Int32 OutlineView::GetPageNumberWidthPixel()
2045 {
2046     Window* pActWin = mpOutlineViewShell->GetActiveWindow();
2047     if( pActWin )
2048     {
2049         Font aOldFont( pActWin->GetFont() );
2050         pActWin->SetFont( maPageNumberFont );
2051         Size aSize( pActWin->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM("X" ) ) ), 0 );
2052         sal_Int32 nWidth = pActWin->LogicToPixel( aSize ).Width() * 5;
2053 
2054         const String aBulletStr( sal_Unicode( 0xE011 ) );
2055         pActWin->SetFont( maBulletFont);
2056 
2057         aSize.Width() = pActWin->GetTextWidth(aBulletStr);
2058         nWidth += pActWin->LogicToPixel( aSize ).Width();
2059 
2060         pActWin->SetFont( aOldFont );
2061 
2062         mnPageNumberWidthPixel = nWidth;
2063     }
2064     return mnPageNumberWidthPixel;
2065 }
2066 #endif
2067 
2068 // --------------------------------------------------------------------
2069 
UpdateParagraph(sal_uInt16 nPara)2070 void OutlineView::UpdateParagraph( sal_uInt16 nPara )
2071 {
2072     if( mpOutliner )
2073     {
2074         SfxItemSet aNewAttrs2( mpOutliner->GetParaAttribs( nPara ) );
2075         aNewAttrs2.Put( maLRSpaceItem );
2076         mpOutliner->SetParaAttribs( nPara, aNewAttrs2 );
2077     }
2078 }
2079 
2080 // --------------------------------------------------------------------
2081 
OnBeginPasteOrDrop(PasteOrDropInfos *)2082 void OutlineView::OnBeginPasteOrDrop( PasteOrDropInfos* /*pInfos*/ )
2083 {
2084 }
2085 
2086 /** this is called after a paste or drop operation, make sure that the newly inserted paragraphs
2087     get the correct style sheet and new slides are inserted. */
OnEndPasteOrDrop(PasteOrDropInfos * pInfos)2088 void OutlineView::OnEndPasteOrDrop( PasteOrDropInfos* pInfos )
2089 {
2090     SdPage* pPage = 0;
2091     SfxStyleSheetBasePool* pStylePool = GetDoc()->GetStyleSheetPool();
2092 
2093     for( sal_uInt16 nPara = pInfos->nStartPara; nPara <= pInfos->nEndPara; nPara++ )
2094     {
2095         Paragraph* pPara = mpOutliner->GetParagraph( nPara );
2096 
2097         bool bPage = mpOutliner->HasParaFlag( pPara, PARAFLAG_ISPAGE  );
2098 
2099         if( !bPage )
2100         {
2101             SdStyleSheet* pStyleSheet = dynamic_cast< SdStyleSheet* >( mpOutliner->GetStyleSheet( nPara ) );
2102             if( pStyleSheet )
2103             {
2104                 const OUString aName( pStyleSheet->GetApiName() );
2105                 if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("title" ) ) )
2106                     bPage = true;
2107             }
2108         }
2109 
2110         if( !pPara )
2111             continue; // fatality!?
2112 
2113         if( bPage && (nPara != pInfos->nStartPara) )
2114         {
2115             // insert new slide for this paragraph
2116             pPage = InsertSlideForParagraph( pPara );
2117         }
2118         else
2119         {
2120             // newly inserted non page paragraphs get the outline style
2121             if( !pPage )
2122                 pPage = GetPageForParagraph( pPara );
2123 
2124             if( pPage )
2125             {
2126                 SfxStyleSheet* pStyle = pPage->GetStyleSheetForPresObj( bPage ? PRESOBJ_TITLE : PRESOBJ_OUTLINE );
2127 
2128                 if( !bPage )
2129                 {
2130                     const sal_Int16 nDepth = mpOutliner->GetDepth( nPara );
2131                     if( nDepth > 0 )
2132                     {
2133                         String aStyleSheetName( pStyle->GetName() );
2134                         aStyleSheetName.Erase( aStyleSheetName.Len() - 1, 1 );
2135                         aStyleSheetName += String::CreateFromInt32( nDepth );
2136                         pStyle = static_cast<SfxStyleSheet*>( pStylePool->Find( aStyleSheetName, pStyle->GetFamily() ) );
2137                         DBG_ASSERT( pStyle, "sd::OutlineView::OnEndPasteOrDrop(), Style not found!" );
2138                     }
2139                 }
2140 
2141                 mpOutliner->SetStyleSheet( nPara, pStyle );
2142             }
2143 
2144             UpdateParagraph( nPara );
2145         }
2146     }
2147 }
2148 
2149 // ====================================================================
2150 
2151 
OutlineViewModelChangeGuard(OutlineView & rView)2152 OutlineViewModelChangeGuard::OutlineViewModelChangeGuard( OutlineView& rView )
2153 : mrView( rView )
2154 {
2155     mrView.BeginModelChange();
2156 }
2157 
~OutlineViewModelChangeGuard()2158 OutlineViewModelChangeGuard::~OutlineViewModelChangeGuard()
2159 {
2160     mrView.EndModelChange();
2161 }
2162 
OutlineViewPageChangesGuard(OutlineView * pView)2163 OutlineViewPageChangesGuard::OutlineViewPageChangesGuard( OutlineView* pView )
2164 : mpView( pView )
2165 {
2166     if( mpView )
2167         mpView->IgnoreCurrentPageChanges( true );
2168 }
2169 
~OutlineViewPageChangesGuard()2170 OutlineViewPageChangesGuard::~OutlineViewPageChangesGuard()
2171 {
2172     if( mpView )
2173         mpView->IgnoreCurrentPageChanges( false );
2174 }
2175 
2176 
2177 } // end of namespace sd
2178