xref: /trunk/main/sd/source/ui/view/outlview.cxx (revision cd9c0841)
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( 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( 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( 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( 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( nPara ) );
946 				aAttrs.Put( *aOldAttrs.GetItem( EE_PARA_NUMBULLET ) );
947 				pOutliner->SetParaAttribs( 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( 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_uInt32 nParaCount1 = mpOutliner->GetParagraphCount();
1359 				sal_Bool bVertical = pOPO->IsVertical();
1360 				pOPO->SetVertical( sal_False );
1361 				mpOutliner->AddText(*pOPO);
1362 				pOPO->SetVertical( bVertical );
1363 
1364                 sal_uInt32 nParaCount2 = mpOutliner->GetParagraphCount();
1365 				for (sal_uInt32 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