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