Bump version to 5.0-14
[LibreOffice.git] / editeng / source / outliner / outliner.cxx
blobb573ea1ebd5e86ccc1ec5480029ef31627d63db0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/string.hxx>
21 #include <svl/intitem.hxx>
22 #include <editeng/editeng.hxx>
23 #include <editeng/editview.hxx>
24 #include <editeng/editdata.hxx>
25 #include <editeng/eerdll.hxx>
26 #include <editeng/lrspitem.hxx>
27 #include <editeng/fhgtitem.hxx>
29 #include <math.h>
30 #include <svl/style.hxx>
31 #include <vcl/wrkwin.hxx>
32 #include <editeng/outliner.hxx>
33 #include <paralist.hxx>
34 #include <editeng/outlobj.hxx>
35 #include <outleeng.hxx>
36 #include <outlundo.hxx>
37 #include <editeng/eeitem.hxx>
38 #include <editeng/editstat.hxx>
39 #include <editeng/scripttypeitem.hxx>
40 #include <editeng/editobj.hxx>
41 #include <svl/itemset.hxx>
42 #include <svl/whiter.hxx>
43 #include <vcl/metric.hxx>
44 #include <editeng/numitem.hxx>
45 #include <editeng/adjustitem.hxx>
46 #include <vcl/graph.hxx>
47 #include <vcl/gdimtf.hxx>
48 #include <vcl/metaact.hxx>
49 #include <svtools/grfmgr.hxx>
50 #include <editeng/svxfont.hxx>
51 #include <editeng/brushitem.hxx>
52 #include <svl/itempool.hxx>
54 // calculate if it's RTL or not
55 #include <unicode/ubidi.h>
56 #include <cassert>
57 #include <boost/scoped_array.hpp>
58 using ::std::advance;
61 // Outliner
64 void Outliner::ImplCheckDepth( sal_Int16& rnDepth ) const
66 if( rnDepth < nMinDepth )
67 rnDepth = nMinDepth;
68 else if( rnDepth > nMaxDepth )
69 rnDepth = nMaxDepth;
72 Paragraph* Outliner::Insert(const OUString& rText, sal_Int32 nAbsPos, sal_Int16 nDepth)
74 DBG_ASSERT(pParaList->GetParagraphCount(),"Insert:No Paras");
76 Paragraph* pPara;
78 ImplCheckDepth( nDepth );
80 sal_Int32 nParagraphCount = pParaList->GetParagraphCount();
81 if( nAbsPos > nParagraphCount )
82 nAbsPos = nParagraphCount;
84 if( bFirstParaIsEmpty )
86 pPara = pParaList->GetParagraph( 0 );
87 if( pPara->GetDepth() != nDepth )
89 nDepthChangedHdlPrevDepth = pPara->GetDepth();
90 mnDepthChangeHdlPrevFlags = pPara->nFlags;
91 pPara->SetDepth( nDepth );
92 pHdlParagraph = pPara;
93 DepthChangedHdl();
95 pPara->nFlags |= ParaFlag::HOLDDEPTH;
96 SetText( rText, pPara );
98 else
100 bool bUpdate = pEditEngine->GetUpdateMode();
101 pEditEngine->SetUpdateMode( false );
102 ImplBlockInsertionCallbacks( true );
103 pPara = new Paragraph( nDepth );
104 pParaList->Insert( pPara, nAbsPos );
105 pEditEngine->InsertParagraph( nAbsPos, OUString() );
106 DBG_ASSERT(pPara==pParaList->GetParagraph(nAbsPos),"Insert:Failed");
107 ImplInitDepth( nAbsPos, nDepth, false );
108 pHdlParagraph = pPara;
109 ParagraphInsertedHdl();
110 pPara->nFlags |= ParaFlag::HOLDDEPTH;
111 SetText( rText, pPara );
112 ImplBlockInsertionCallbacks( false );
113 pEditEngine->SetUpdateMode( bUpdate );
115 bFirstParaIsEmpty = false;
116 DBG_ASSERT(pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(),"SetText failed");
117 return pPara;
121 void Outliner::ParagraphInserted( sal_Int32 nPara )
124 if ( nBlockInsCallback )
125 return;
127 if( bPasting || pEditEngine->IsInUndo() )
129 Paragraph* pPara = new Paragraph( -1 );
130 pParaList->Insert( pPara, nPara );
131 if( pEditEngine->IsInUndo() )
133 pPara->nFlags = ParaFlag::SETBULLETTEXT;
134 pPara->bVisible = true;
135 const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ) );
136 pPara->SetDepth( rLevel.GetValue() );
139 else
141 sal_Int16 nDepth = -1;
142 Paragraph* pParaBefore = pParaList->GetParagraph( nPara-1 );
143 if ( pParaBefore )
144 nDepth = pParaBefore->GetDepth();
146 Paragraph* pPara = new Paragraph( nDepth );
147 pParaList->Insert( pPara, nPara );
149 if( !pEditEngine->IsInUndo() )
151 ImplCalcBulletText( nPara, true, false );
152 pHdlParagraph = pPara;
153 ParagraphInsertedHdl();
158 void Outliner::ParagraphDeleted( sal_Int32 nPara )
161 if ( nBlockInsCallback || ( nPara == EE_PARA_ALL ) )
162 return;
164 Paragraph* pPara = pParaList->GetParagraph( nPara );
165 if (!pPara)
166 return;
168 sal_Int16 nDepth = pPara->GetDepth();
170 if( !pEditEngine->IsInUndo() )
172 pHdlParagraph = pPara;
173 ParagraphRemovingHdl();
176 pParaList->Remove( nPara );
177 delete pPara;
179 if( !pEditEngine->IsInUndo() && !bPasting )
181 pPara = pParaList->GetParagraph( nPara );
182 if ( pPara && ( pPara->GetDepth() > nDepth ) )
184 ImplCalcBulletText( nPara, true, false );
185 // Search for next on the this level ...
186 while ( pPara && pPara->GetDepth() > nDepth )
187 pPara = pParaList->GetParagraph( ++nPara );
190 if ( pPara && ( pPara->GetDepth() == nDepth ) )
191 ImplCalcBulletText( nPara, true, false );
195 void Outliner::Init( sal_uInt16 nMode )
197 nOutlinerMode = nMode;
199 Clear();
201 EEControlBits nCtrl = pEditEngine->GetControlWord();
202 nCtrl &= ~EEControlBits(EEControlBits::OUTLINER|EEControlBits::OUTLINER2);
204 SetMaxDepth( 9 );
206 switch ( ImplGetOutlinerMode() )
208 case OUTLINERMODE_TEXTOBJECT:
209 case OUTLINERMODE_TITLEOBJECT:
210 break;
212 case OUTLINERMODE_OUTLINEOBJECT:
213 nCtrl |= EEControlBits::OUTLINER2;
214 break;
215 case OUTLINERMODE_OUTLINEVIEW:
216 nCtrl |= EEControlBits::OUTLINER;
217 break;
219 default: OSL_FAIL( "Outliner::Init - Invalid Mode!" );
222 pEditEngine->SetControlWord( nCtrl );
224 const bool bWasUndoEnabled(IsUndoEnabled());
225 EnableUndo(false);
226 ImplInitDepth( 0, -1, false );
227 GetUndoManager().Clear();
228 EnableUndo(bWasUndoEnabled);
231 void Outliner::SetMaxDepth( sal_Int16 nDepth, bool bCheckParagraphs )
233 if( nMaxDepth != nDepth )
235 nMaxDepth = std::min( nDepth, (sal_Int16)(SVX_MAX_NUM-1) );
237 if( bCheckParagraphs )
239 sal_Int32 nParagraphs = pParaList->GetParagraphCount();
240 for ( sal_Int32 nPara = 0; nPara < nParagraphs; nPara++ )
242 Paragraph* pPara = pParaList->GetParagraph( nPara );
243 if( pPara && pPara->GetDepth() > nMaxDepth )
245 SetDepth( pPara, nMaxDepth );
252 sal_Int16 Outliner::GetDepth( sal_Int32 nPara ) const
254 Paragraph* pPara = pParaList->GetParagraph( nPara );
255 DBG_ASSERT( pPara, "Outliner::GetDepth - Paragraph not found!" );
256 return pPara ? pPara->GetDepth() : -1;
259 void Outliner::SetDepth( Paragraph* pPara, sal_Int16 nNewDepth )
262 ImplCheckDepth( nNewDepth );
264 if ( nNewDepth != pPara->GetDepth() )
266 nDepthChangedHdlPrevDepth = pPara->GetDepth();
267 mnDepthChangeHdlPrevFlags = pPara->nFlags;
268 pHdlParagraph = pPara;
270 sal_Int32 nPara = GetAbsPos( pPara );
271 ImplInitDepth( nPara, nNewDepth, true );
272 ImplCalcBulletText( nPara, false, false );
274 if ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT )
275 ImplSetLevelDependendStyleSheet( nPara );
277 DepthChangedHdl();
281 sal_Int16 Outliner::GetNumberingStartValue( sal_Int32 nPara )
283 Paragraph* pPara = pParaList->GetParagraph( nPara );
284 DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" );
285 return pPara ? pPara->GetNumberingStartValue() : -1;
288 void Outliner::SetNumberingStartValue( sal_Int32 nPara, sal_Int16 nNumberingStartValue )
290 Paragraph* pPara = pParaList->GetParagraph( nPara );
291 DBG_ASSERT( pPara, "Outliner::GetNumberingStartValue - Paragraph not found!" );
292 if( pPara && pPara->GetNumberingStartValue() != nNumberingStartValue )
294 if( IsUndoEnabled() && !IsInUndo() )
295 InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara,
296 pPara->GetNumberingStartValue(), nNumberingStartValue,
297 pPara->IsParaIsNumberingRestart(), pPara->IsParaIsNumberingRestart() ) );
299 pPara->SetNumberingStartValue( nNumberingStartValue );
300 ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() );
301 pEditEngine->SetModified();
305 bool Outliner::IsParaIsNumberingRestart( sal_Int32 nPara )
307 Paragraph* pPara = pParaList->GetParagraph( nPara );
308 DBG_ASSERT( pPara, "Outliner::IsParaIsNumberingRestart - Paragraph not found!" );
309 return pPara && pPara->IsParaIsNumberingRestart();
312 void Outliner::SetParaIsNumberingRestart( sal_Int32 nPara, bool bParaIsNumberingRestart )
314 Paragraph* pPara = pParaList->GetParagraph( nPara );
315 DBG_ASSERT( pPara, "Outliner::SetParaIsNumberingRestart - Paragraph not found!" );
316 if( pPara && (pPara->IsParaIsNumberingRestart() != bParaIsNumberingRestart) )
318 if( IsUndoEnabled() && !IsInUndo() )
319 InsertUndo( new OutlinerUndoChangeParaNumberingRestart( this, nPara,
320 pPara->GetNumberingStartValue(), pPara->GetNumberingStartValue(),
321 pPara->IsParaIsNumberingRestart(), bParaIsNumberingRestart ) );
323 pPara->SetParaIsNumberingRestart( bParaIsNumberingRestart );
324 ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() );
325 pEditEngine->SetModified();
329 sal_Int32 Outliner::GetBulletsNumberingStatus(
330 const sal_Int32 nParaStart,
331 const sal_Int32 nParaEnd ) const
333 if ( nParaStart > nParaEnd
334 || nParaEnd >= pParaList->GetParagraphCount() )
336 DBG_ASSERT( false,"<Outliner::GetBulletsNumberingStatus> - unexpected parameter values" );
337 return 2;
340 sal_Int32 nBulletsCount = 0;
341 sal_Int32 nNumberingCount = 0;
342 for (sal_Int32 nPara = nParaStart; nPara <= nParaEnd; ++nPara)
344 if ( !pParaList->GetParagraph(nPara) )
346 break;
348 const SvxNumberFormat* pFmt = GetNumberFormat(nPara);
349 if (!pFmt)
351 // At least, exists one paragraph that has no Bullets/Numbering.
352 break;
354 else if ((pFmt->GetNumberingType() == SVX_NUM_BITMAP) || (pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL))
356 // Having Bullets in this paragraph.
357 nBulletsCount++;
359 else
361 // Having Numbering in this paragraph.
362 nNumberingCount++;
366 const sal_Int32 nParaCount = nParaEnd - nParaStart + 1;
367 if ( nBulletsCount == nParaCount )
369 return 0;
371 else if ( nNumberingCount == nParaCount )
373 return 1;
375 return 2;
378 sal_Int32 Outliner::GetBulletsNumberingStatus() const
380 return pParaList->GetParagraphCount() > 0
381 ? GetBulletsNumberingStatus( 0, pParaList->GetParagraphCount()-1 )
382 : 2;
385 OutlinerParaObject* Outliner::CreateParaObject( sal_Int32 nStartPara, sal_Int32 nCount ) const
387 if ( static_cast<sal_uLong>(nStartPara) + nCount >
388 static_cast<sal_uLong>(pParaList->GetParagraphCount()) )
389 nCount = pParaList->GetParagraphCount() - nStartPara;
391 // When a new OutlinerParaObject is created because a paragraph is just being deleted,
392 // it can happen that the ParaList is not updated yet...
393 if ( ( nStartPara + nCount ) > pEditEngine->GetParagraphCount() )
394 nCount = pEditEngine->GetParagraphCount() - nStartPara;
396 if (nCount <= 0)
397 return NULL;
399 EditTextObject* pText = pEditEngine->CreateTextObject( nStartPara, nCount );
400 const bool bIsEditDoc(OUTLINERMODE_TEXTOBJECT == ImplGetOutlinerMode());
401 ParagraphDataVector aParagraphDataVector(nCount);
402 const sal_Int32 nLastPara(nStartPara + nCount - 1);
404 for(sal_Int32 nPara(nStartPara); nPara <= nLastPara; nPara++)
406 aParagraphDataVector[nPara-nStartPara] = *GetParagraph(nPara);
409 OutlinerParaObject* pPObj = new OutlinerParaObject(*pText, aParagraphDataVector, bIsEditDoc);
410 pPObj->SetOutlinerMode(GetMode());
411 delete pText;
413 return pPObj;
416 void Outliner::SetText( const OUString& rText, Paragraph* pPara )
418 DBG_ASSERT(pPara,"SetText:No Para");
420 bool bUpdate = pEditEngine->GetUpdateMode();
421 pEditEngine->SetUpdateMode( false );
422 ImplBlockInsertionCallbacks( true );
424 sal_Int32 nPara = pParaList->GetAbsPos( pPara );
426 if (rText.isEmpty())
428 pEditEngine->SetText( nPara, rText );
429 ImplInitDepth( nPara, pPara->GetDepth(), false );
431 else
433 OUString aText(convertLineEnd(rText, LINEEND_LF));
435 if (aText.endsWith("\x0A"))
436 aText = aText.copy(0, aText.getLength()-1); // Delete the last break
438 sal_Int32 nCount = comphelper::string::getTokenCount(aText, '\x0A');
439 sal_Int32 nPos = 0;
440 sal_Int32 nInsPos = nPara+1;
441 while( nCount > nPos )
443 OUString aStr = aText.getToken( nPos, '\x0A' );
445 sal_Int16 nCurDepth;
446 if( nPos )
448 pPara = new Paragraph( -1 );
449 nCurDepth = -1;
451 else
452 nCurDepth = pPara->GetDepth();
454 // In the outliner mode, filter the tabs and set the indentation
455 // about a LRSpaceItem. In EditEngine mode intend over old tabs
456 if( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) ||
457 ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ) )
459 // Extract Tabs
460 sal_uInt16 nTabs = 0;
461 while ( ( nTabs < aStr.getLength() ) && ( aStr[nTabs] == '\t' ) )
462 nTabs++;
463 if ( nTabs )
464 aStr = aStr.copy(nTabs);
466 // Keep depth? (see Outliner::Insert)
467 if( !(pPara->nFlags & ParaFlag::HOLDDEPTH) )
469 nCurDepth = nTabs-1;
470 ImplCheckDepth( nCurDepth );
471 pPara->SetDepth( nCurDepth );
472 pPara->nFlags &= (~ParaFlag::HOLDDEPTH);
475 if( nPos ) // not with the first paragraph
477 pParaList->Insert( pPara, nInsPos );
478 pEditEngine->InsertParagraph( nInsPos, aStr );
479 pHdlParagraph = pPara;
480 ParagraphInsertedHdl();
482 else
484 nInsPos--;
485 pEditEngine->SetText( nInsPos, aStr );
487 ImplInitDepth( nInsPos, nCurDepth, false );
488 nInsPos++;
489 nPos++;
493 DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"SetText failed!");
494 bFirstParaIsEmpty = false;
495 ImplBlockInsertionCallbacks( false );
496 pEditEngine->SetUpdateMode( bUpdate );
499 // pView == 0 -> Ignore tabs
501 bool Outliner::ImpConvertEdtToOut( sal_Int32 nPara,EditView* pView)
504 bool bConverted = false;
505 sal_Int32 nTabs = 0;
506 ESelection aDelSel;
508 OUString aName;
509 OUString aHeading_US( "heading" );
510 OUString aNumber_US( "Numbering" );
512 OUString aStr( pEditEngine->GetText( nPara ) );
513 const sal_Unicode* pPtr = aStr.getStr();
515 sal_Int32 nHeadingNumberStart = 0;
516 sal_Int32 nNumberingNumberStart = 0;
517 SfxStyleSheet* pStyle= pEditEngine->GetStyleSheet( nPara );
518 if( pStyle )
520 aName = pStyle->GetName();
521 sal_Int32 nSearch;
522 if ( ( nSearch = aName.indexOf( aHeading_US ) ) != -1 )
523 nHeadingNumberStart = nSearch + aHeading_US.getLength();
524 else if ( ( nSearch = aName.indexOf( aNumber_US ) ) != -1 )
525 nNumberingNumberStart = nSearch + aNumber_US.getLength();
528 if ( nHeadingNumberStart || nNumberingNumberStart )
530 // PowerPoint import ?
531 if( nHeadingNumberStart && ( aStr.getLength() >= 2 ) &&
532 ( pPtr[0] != '\t' ) && ( pPtr[1] == '\t' ) )
534 // Extract Bullet and Tab
535 aDelSel = ESelection( nPara, 0, nPara, 2 );
538 sal_Int32 nPos = nHeadingNumberStart ? nHeadingNumberStart : nNumberingNumberStart;
539 OUString aLevel = comphelper::string::stripStart(aName.copy(nPos), ' ');
540 nTabs = aLevel.toInt32();
541 if( nTabs )
542 nTabs--; // Level 0 = "heading 1"
543 bConverted = true;
545 else
547 // filter leading tabs
548 while( *pPtr == '\t' )
550 pPtr++;
551 nTabs++;
553 // Remove tabs from the text
554 if( nTabs )
555 aDelSel = ESelection( nPara, 0, nPara, nTabs );
558 if ( aDelSel.HasRange() )
560 if ( pView )
562 pView->SetSelection( aDelSel );
563 pView->DeleteSelected();
565 else
566 pEditEngine->QuickDelete( aDelSel );
569 const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ) );
570 sal_Int16 nOutlLevel = rLevel.GetValue();
572 ImplCheckDepth( nOutlLevel );
573 ImplInitDepth( nPara, nOutlLevel, false );
575 return bConverted;
578 void Outliner::SetText( const OutlinerParaObject& rPObj )
581 bool bUpdate = pEditEngine->GetUpdateMode();
582 pEditEngine->SetUpdateMode( false );
584 bool bUndo = pEditEngine->IsUndoEnabled();
585 EnableUndo( false );
587 Init( rPObj.GetOutlinerMode() );
589 ImplBlockInsertionCallbacks( true );
590 pEditEngine->SetText(rPObj.GetTextObject());
592 bFirstParaIsEmpty = false;
594 pParaList->Clear( true );
595 for( sal_Int32 nCurPara = 0; nCurPara < rPObj.Count(); nCurPara++ )
597 Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(nCurPara));
598 ImplCheckDepth( pPara->nDepth );
600 pParaList->Append(pPara);
601 ImplCheckNumBulletItem( nCurPara );
604 ImplCheckParagraphs( 0, pParaList->GetParagraphCount() );
606 EnableUndo( bUndo );
607 ImplBlockInsertionCallbacks( false );
608 pEditEngine->SetUpdateMode( bUpdate );
610 DBG_ASSERT( pParaList->GetParagraphCount()==rPObj.Count(),"SetText failed");
611 DBG_ASSERT( pEditEngine->GetParagraphCount()==rPObj.Count(),"SetText failed");
614 void Outliner::AddText( const OutlinerParaObject& rPObj )
617 bool bUpdate = pEditEngine->GetUpdateMode();
618 pEditEngine->SetUpdateMode( false );
620 ImplBlockInsertionCallbacks( true );
621 sal_Int32 nPara;
622 if( bFirstParaIsEmpty )
624 pParaList->Clear( true );
625 pEditEngine->SetText(rPObj.GetTextObject());
626 nPara = 0;
628 else
630 nPara = pParaList->GetParagraphCount();
631 pEditEngine->InsertParagraph( EE_PARA_APPEND, rPObj.GetTextObject() );
633 bFirstParaIsEmpty = false;
635 for( sal_Int32 n = 0; n < rPObj.Count(); n++ )
637 Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(n) );
638 pParaList->Append(pPara);
639 sal_Int32 nP = nPara+n;
640 DBG_ASSERT(pParaList->GetAbsPos(pPara)==nP,"AddText:Out of sync");
641 ImplInitDepth( nP, pPara->GetDepth(), false );
643 DBG_ASSERT( pEditEngine->GetParagraphCount()==pParaList->GetParagraphCount(), "SetText: OutOfSync" );
645 ImplCheckParagraphs( nPara, pParaList->GetParagraphCount() );
647 ImplBlockInsertionCallbacks( false );
648 pEditEngine->SetUpdateMode( bUpdate );
651 void Outliner::FieldClicked( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos )
654 if ( aFieldClickedHdl.IsSet() )
656 EditFieldInfo aFldInfo( this, rField, nPara, nPos );
657 aFldInfo.SetSimpleClick( true );
658 aFieldClickedHdl.Call( &aFldInfo );
663 void Outliner::FieldSelected( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos )
665 if ( !aFieldClickedHdl.IsSet() )
666 return;
668 EditFieldInfo aFldInfo( this, rField, nPara, nPos );
669 aFldInfo.SetSimpleClick( false );
670 aFieldClickedHdl.Call( &aFldInfo );
674 OUString Outliner::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, Color*& rpTxtColor, Color*& rpFldColor )
676 if ( !aCalcFieldValueHdl.IsSet() )
677 return OUString( ' ' );
679 EditFieldInfo aFldInfo( this, rField, nPara, nPos );
680 // The FldColor is preset with COL_LIGHTGRAY.
681 if ( rpFldColor )
682 aFldInfo.SetFieldColor( *rpFldColor );
684 aCalcFieldValueHdl.Call( &aFldInfo );
685 if ( aFldInfo.GetTextColor() )
687 delete rpTxtColor;
688 rpTxtColor = new Color( *aFldInfo.GetTextColor() );
691 delete rpFldColor;
692 rpFldColor = aFldInfo.GetFieldColor() ? new Color( *aFldInfo.GetFieldColor() ) : 0;
694 return aFldInfo.GetRepresentation();
697 void Outliner::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle )
699 Paragraph* pPara = pParaList->GetParagraph( nPara );
700 if (pPara)
702 pEditEngine->SetStyleSheet( nPara, pStyle );
703 pPara->nFlags |= ParaFlag::SETBULLETTEXT;
704 ImplCheckNumBulletItem( nPara );
708 void Outliner::ImplCheckNumBulletItem( sal_Int32 nPara )
710 Paragraph* pPara = pParaList->GetParagraph( nPara );
711 if (pPara)
712 pPara->aBulSize.Width() = -1;
715 void Outliner::ImplSetLevelDependendStyleSheet( sal_Int32 nPara, SfxStyleSheet* pLevelStyle )
718 DBG_ASSERT( ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEOBJECT ) || ( ImplGetOutlinerMode() == OUTLINERMODE_OUTLINEVIEW ), "SetLevelDependendStyleSheet: Wrong Mode!" );
720 SfxStyleSheet* pStyle = pLevelStyle;
721 if ( !pStyle )
722 pStyle = GetStyleSheet( nPara );
724 if ( pStyle )
726 sal_Int16 nDepth = GetDepth( nPara );
727 if( nDepth < 0 )
728 nDepth = 0;
730 OUString aNewStyleSheetName( pStyle->GetName() );
731 aNewStyleSheetName = aNewStyleSheetName.copy( 0, aNewStyleSheetName.getLength()-1 );
732 aNewStyleSheetName += OUString::number( nDepth+1 );
733 SfxStyleSheet* pNewStyle = static_cast<SfxStyleSheet*>(GetStyleSheetPool()->Find( aNewStyleSheetName, pStyle->GetFamily() ));
734 DBG_ASSERT( pNewStyle, "AutoStyleSheetName - Style not found!" );
735 if ( pNewStyle && ( pNewStyle != GetStyleSheet( nPara ) ) )
737 SfxItemSet aOldAttrs( GetParaAttribs( nPara ) );
738 SetStyleSheet( nPara, pNewStyle );
739 if ( aOldAttrs.GetItemState( EE_PARA_NUMBULLET ) == SfxItemState::SET )
741 SfxItemSet aAttrs( GetParaAttribs( nPara ) );
742 aAttrs.Put( aOldAttrs.Get( EE_PARA_NUMBULLET ) );
743 SetParaAttribs( nPara, aAttrs );
749 void Outliner::ImplInitDepth( sal_Int32 nPara, sal_Int16 nDepth, bool bCreateUndo, bool bUndoAction )
752 DBG_ASSERT( ( nDepth >= nMinDepth ) && ( nDepth <= nMaxDepth ), "ImplInitDepth - Depth is invalid!" );
754 Paragraph* pPara = pParaList->GetParagraph( nPara );
755 if (!pPara)
756 return;
757 sal_Int16 nOldDepth = pPara->GetDepth();
758 pPara->SetDepth( nDepth );
760 // For IsInUndo attributes and style do not have to be set, there
761 // the old values are restored by the EditEngine.
762 if( !IsInUndo() )
764 bool bUpdate = pEditEngine->GetUpdateMode();
765 pEditEngine->SetUpdateMode( false );
767 bool bUndo = bCreateUndo && IsUndoEnabled();
768 if ( bUndo && bUndoAction )
769 UndoActionStart( OLUNDO_DEPTH );
771 SfxItemSet aAttrs( pEditEngine->GetParaAttribs( nPara ) );
772 aAttrs.Put( SfxInt16Item( EE_PARA_OUTLLEVEL, nDepth ) );
773 pEditEngine->SetParaAttribs( nPara, aAttrs );
774 ImplCheckNumBulletItem( nPara );
775 ImplCalcBulletText( nPara, false, false );
777 if ( bUndo )
779 InsertUndo( new OutlinerUndoChangeDepth( this, nPara, nOldDepth, nDepth ) );
780 if ( bUndoAction )
781 UndoActionEnd( OLUNDO_DEPTH );
784 pEditEngine->SetUpdateMode( bUpdate );
788 void Outliner::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
791 pEditEngine->SetParaAttribs( nPara, rSet );
794 bool Outliner::Expand( Paragraph* pPara )
796 if ( pParaList->HasHiddenChildren( pPara ) )
798 OLUndoExpand* pUndo = 0;
799 bool bUndo = IsUndoEnabled() && !IsInUndo();
800 if( bUndo )
802 UndoActionStart( OLUNDO_EXPAND );
803 pUndo = new OLUndoExpand( this, OLUNDO_EXPAND );
804 pUndo->pParas = 0;
805 pUndo->nCount = pParaList->GetAbsPos( pPara );
807 pHdlParagraph = pPara;
808 bIsExpanding = true;
809 pParaList->Expand( pPara );
810 ExpandHdl();
811 InvalidateBullet(pParaList->GetAbsPos(pPara));
812 if( bUndo )
814 InsertUndo( pUndo );
815 UndoActionEnd( OLUNDO_EXPAND );
817 return true;
819 return false;
822 bool Outliner::Collapse( Paragraph* pPara )
824 if ( pParaList->HasVisibleChildren( pPara ) ) // expanded
826 OLUndoExpand* pUndo = 0;
827 bool bUndo = false;
829 if( !IsInUndo() && IsUndoEnabled() )
830 bUndo = true;
831 if( bUndo )
833 UndoActionStart( OLUNDO_COLLAPSE );
834 pUndo = new OLUndoExpand( this, OLUNDO_COLLAPSE );
835 pUndo->pParas = 0;
836 pUndo->nCount = pParaList->GetAbsPos( pPara );
839 pHdlParagraph = pPara;
840 bIsExpanding = false;
841 pParaList->Collapse( pPara );
842 ExpandHdl();
843 InvalidateBullet(pParaList->GetAbsPos(pPara));
844 if( bUndo )
846 InsertUndo( pUndo );
847 UndoActionEnd( OLUNDO_COLLAPSE );
849 return true;
851 return false;
855 vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const
857 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
858 DBG_ASSERT( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ), "ImpCalcBulletFont: Missing or BitmapBullet!" );
860 vcl::Font aStdFont;
861 if ( !pEditEngine->IsFlatMode() )
863 ESelection aSel( nPara, 0, nPara, 0 );
864 aStdFont = EditEngine::CreateFontFromItemSet( pEditEngine->GetAttribs( aSel ), GetScriptType( aSel ) );
866 else
868 aStdFont = pEditEngine->GetStandardFont( nPara );
871 vcl::Font aBulletFont;
872 const vcl::Font *pSourceFont = 0;
873 if ( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL )
875 pSourceFont = pFmt->GetBulletFont();
878 if (pSourceFont)
880 aBulletFont = *pSourceFont;
882 else
884 aBulletFont = aStdFont;
885 aBulletFont.SetUnderline( UNDERLINE_NONE );
886 aBulletFont.SetOverline( UNDERLINE_NONE );
887 aBulletFont.SetStrikeout( STRIKEOUT_NONE );
888 aBulletFont.SetEmphasisMark( EMPHASISMARK_NONE );
889 aBulletFont.SetRelief( RELIEF_NONE );
892 // Use original scale...
893 sal_uInt16 nStretchX, nStretchY;
894 GetGlobalCharStretching(nStretchX, nStretchY);
896 sal_uInt16 nScale = pFmt->GetBulletRelSize() * nStretchY / 100;
897 sal_uLong nScaledLineHeight = aStdFont.GetSize().Height();
898 nScaledLineHeight *= nScale*10;
899 nScaledLineHeight /= 1000;
901 aBulletFont.SetAlign( ALIGN_BOTTOM );
902 aBulletFont.SetSize( Size( 0, nScaledLineHeight ) );
903 bool bVertical = IsVertical();
904 aBulletFont.SetVertical( bVertical );
905 aBulletFont.SetOrientation( bVertical ? 2700 : 0 );
907 Color aColor( COL_AUTO );
908 if( !pEditEngine->IsFlatMode() && !( pEditEngine->GetControlWord() & EEControlBits::NOCOLORS ) )
910 aColor = pFmt->GetBulletColor();
913 if ( ( aColor == COL_AUTO ) || ( IsForceAutoColor() ) )
914 aColor = pEditEngine->GetAutoColor();
916 aBulletFont.SetColor( aColor );
917 return aBulletFont;
920 void Outliner::PaintBullet( sal_Int32 nPara, const Point& rStartPos,
921 const Point& rOrigin, short nOrientation, OutputDevice* pOutDev )
924 bool bDrawBullet = false;
925 if (pEditEngine)
927 const SfxBoolItem& rBulletState = static_cast<const SfxBoolItem&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) );
928 bDrawBullet = rBulletState.GetValue();
931 if (bDrawBullet && ImplHasNumberFormat(nPara))
933 bool bVertical = IsVertical();
935 bool bRightToLeftPara = pEditEngine->IsRightToLeft( nPara );
937 Rectangle aBulletArea( ImpCalcBulletArea( nPara, true, false ) );
938 sal_uInt16 nStretchX, nStretchY;
939 GetGlobalCharStretching(nStretchX, nStretchY);
940 aBulletArea = Rectangle( Point(aBulletArea.Left()*nStretchX/100,
941 aBulletArea.Top()),
942 Size(aBulletArea.GetWidth()*nStretchX/100,
943 aBulletArea.GetHeight()) );
945 Paragraph* pPara = pParaList->GetParagraph( nPara );
946 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
947 if ( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) )
949 if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
951 vcl::Font aBulletFont( ImpCalcBulletFont( nPara ) );
952 // Use baseline
953 bool bSymbol = pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL;
954 aBulletFont.SetAlign( bSymbol ? ALIGN_BOTTOM : ALIGN_BASELINE );
955 vcl::Font aOldFont = pOutDev->GetFont();
956 pOutDev->SetFont( aBulletFont );
958 ParagraphInfos aParaInfos = pEditEngine->GetParagraphInfos( nPara );
959 Point aTextPos;
960 if ( !bVertical )
962 // aTextPos.Y() = rStartPos.Y() + aBulletArea.Bottom();
963 aTextPos.Y() = rStartPos.Y() + ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent );
964 if ( !bRightToLeftPara )
965 aTextPos.X() = rStartPos.X() + aBulletArea.Left();
966 else
967 aTextPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Right();
969 else
971 // aTextPos.X() = rStartPos.X() - aBulletArea.Bottom();
972 aTextPos.X() = rStartPos.X() - ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent );
973 aTextPos.Y() = rStartPos.Y() + aBulletArea.Left();
976 if ( nOrientation )
978 // Both TopLeft and bottom left is not quite correct,
979 // since in EditEngine baseline ...
980 double nRealOrientation = nOrientation*F_PI1800;
981 double nCos = cos( nRealOrientation );
982 double nSin = sin( nRealOrientation );
983 Point aRotatedPos;
984 // Translation...
985 aTextPos -= rOrigin;
986 // Rotation...
987 aRotatedPos.X()=(long) (nCos*aTextPos.X() + nSin*aTextPos.Y());
988 aRotatedPos.Y()=(long) - (nSin*aTextPos.X() - nCos*aTextPos.Y());
989 aTextPos = aRotatedPos;
990 // Translation...
991 aTextPos += rOrigin;
992 vcl::Font aRotatedFont( aBulletFont );
993 aRotatedFont.SetOrientation( nOrientation );
994 pOutDev->SetFont( aRotatedFont );
997 // VCL will take care of brackets and so on...
998 ComplexTextLayoutMode nLayoutMode = pOutDev->GetLayoutMode();
999 nLayoutMode &= ~(TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG);
1000 if ( bRightToLeftPara )
1001 nLayoutMode |= TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT | TEXT_LAYOUT_BIDI_STRONG;
1002 pOutDev->SetLayoutMode( nLayoutMode );
1004 if(bStrippingPortions)
1006 const vcl::Font aSvxFont(pOutDev->GetFont());
1007 boost::scoped_array<long> pBuf(new long[ pPara->GetText().getLength() ]);
1008 pOutDev->GetTextArray( pPara->GetText(), pBuf.get() );
1010 if(bSymbol)
1012 // aTextPos is Bottom, go to Baseline
1013 FontMetric aMetric(pOutDev->GetFontMetric());
1014 aTextPos.Y() -= aMetric.GetDescent();
1017 DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), pBuf.get(),
1018 aSvxFont, nPara, -1, bRightToLeftPara ? 1 : 0, 0, 0, false, false, true, 0, Color(), Color());
1020 else
1022 pOutDev->DrawText( aTextPos, pPara->GetText() );
1025 pOutDev->SetFont( aOldFont );
1027 else
1029 if ( pFmt->GetBrush()->GetGraphicObject() )
1031 Point aBulletPos;
1032 if ( !bVertical )
1034 aBulletPos.Y() = rStartPos.Y() + aBulletArea.Top();
1035 if ( !bRightToLeftPara )
1036 aBulletPos.X() = rStartPos.X() + aBulletArea.Left();
1037 else
1038 aBulletPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Right();
1040 else
1042 aBulletPos.X() = rStartPos.X() - aBulletArea.Bottom();
1043 aBulletPos.Y() = rStartPos.Y() + aBulletArea.Left();
1046 if(bStrippingPortions)
1048 if(aDrawBulletHdl.IsSet())
1050 // call something analog to aDrawPortionHdl (if set) and feed it something
1051 // analog to DrawPortionInfo...
1052 // created aDrawBulletHdl, Set/GetDrawBulletHdl.
1053 // created DrawBulletInfo and added handling to sdrtextdecomposition.cxx
1054 DrawBulletInfo aDrawBulletInfo(
1055 *pFmt->GetBrush()->GetGraphicObject(),
1056 aBulletPos,
1057 pPara->aBulSize);
1059 aDrawBulletHdl.Call(&aDrawBulletInfo);
1062 else
1064 // Remove CAST when KA made the Draw-Method const
1065 const_cast<GraphicObject*>(pFmt->GetBrush()->GetGraphicObject())->Draw( pOutDev, aBulletPos, pPara->aBulSize );
1071 // In case of collapsed subparagraphs paint a line before the text.
1072 if( pParaList->HasChildren(pPara) && !pParaList->HasVisibleChildren(pPara) &&
1073 !bStrippingPortions && !nOrientation )
1075 long nWidth = pOutDev->PixelToLogic( Size( 10, 0 ) ).Width();
1077 Point aStartPos, aEndPos;
1078 if ( !bVertical )
1080 aStartPos.Y() = rStartPos.Y() + aBulletArea.Bottom();
1081 if ( !bRightToLeftPara )
1082 aStartPos.X() = rStartPos.X() + aBulletArea.Right();
1083 else
1084 aStartPos.X() = rStartPos.X() + GetPaperSize().Width() - aBulletArea.Left();
1085 aEndPos = aStartPos;
1086 aEndPos.X() += nWidth;
1088 else
1090 aStartPos.X() = rStartPos.X() - aBulletArea.Bottom();
1091 aStartPos.Y() = rStartPos.Y() + aBulletArea.Right();
1092 aEndPos = aStartPos;
1093 aEndPos.Y() += nWidth;
1096 const Color& rOldLineColor = pOutDev->GetLineColor();
1097 pOutDev->SetLineColor( Color( COL_BLACK ) );
1098 pOutDev->DrawLine( aStartPos, aEndPos );
1099 pOutDev->SetLineColor( rOldLineColor );
1104 void Outliner::InvalidateBullet(sal_Int32 nPara)
1106 long nLineHeight = (long)pEditEngine->GetLineHeight(nPara );
1107 for ( size_t i = 0, n = aViewList.size(); i < n; ++i )
1109 OutlinerView* pView = aViewList[ i ];
1110 Point aPos( pView->pEditView->GetWindowPosTopLeft(nPara ) );
1111 Rectangle aRect( pView->GetOutputArea() );
1112 aRect.Right() = aPos.X();
1113 aRect.Top() = aPos.Y();
1114 aRect.Bottom() = aPos.Y();
1115 aRect.Bottom() += nLineHeight;
1117 pView->GetWindow()->Invalidate( aRect );
1121 sal_uLong Outliner::Read( SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat, SvKeyValueIterator* pHTTPHeaderAttrs )
1124 bool bOldUndo = pEditEngine->IsUndoEnabled();
1125 EnableUndo( false );
1127 bool bUpdate = pEditEngine->GetUpdateMode();
1128 pEditEngine->SetUpdateMode( false );
1130 Clear();
1132 ImplBlockInsertionCallbacks( true );
1133 sal_uLong nRet = pEditEngine->Read( rInput, rBaseURL, (EETextFormat)eFormat, pHTTPHeaderAttrs );
1135 bFirstParaIsEmpty = false;
1137 sal_Int32 nParas = pEditEngine->GetParagraphCount();
1138 pParaList->Clear( true );
1139 for ( sal_Int32 n = 0; n < nParas; n++ )
1141 Paragraph* pPara = new Paragraph( 0 );
1142 pParaList->Append(pPara);
1144 if ( eFormat == EE_FORMAT_BIN )
1146 const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( n );
1147 const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( rAttrs.Get( EE_PARA_OUTLLEVEL ));
1148 sal_Int16 nDepth = rLevel.GetValue();
1149 ImplInitDepth( n, nDepth, false );
1153 if ( eFormat != EE_FORMAT_BIN )
1155 ImpFilterIndents( 0, nParas-1 );
1158 ImplBlockInsertionCallbacks( false );
1159 pEditEngine->SetUpdateMode( bUpdate );
1160 EnableUndo( bOldUndo );
1162 return nRet;
1166 void Outliner::ImpFilterIndents( sal_Int32 nFirstPara, sal_Int32 nLastPara )
1169 bool bUpdate = pEditEngine->GetUpdateMode();
1170 pEditEngine->SetUpdateMode( false );
1172 Paragraph* pLastConverted = NULL;
1173 for( sal_Int32 nPara = nFirstPara; nPara <= nLastPara; nPara++ )
1175 Paragraph* pPara = pParaList->GetParagraph( nPara );
1176 if (pPara)
1178 if( ImpConvertEdtToOut( nPara ) )
1180 pLastConverted = pPara;
1182 else if ( pLastConverted )
1184 // Arrange normal paragraphs below the heading ...
1185 pPara->SetDepth( pLastConverted->GetDepth() );
1188 ImplInitDepth( nPara, pPara->GetDepth(), false );
1192 pEditEngine->SetUpdateMode( bUpdate );
1195 ::svl::IUndoManager& Outliner::GetUndoManager()
1197 return pEditEngine->GetUndoManager();
1200 ::svl::IUndoManager* Outliner::SetUndoManager(::svl::IUndoManager* pNew)
1202 return pEditEngine->SetUndoManager(pNew);
1205 void Outliner::ImpTextPasted( sal_Int32 nStartPara, sal_Int32 nCount )
1208 bool bUpdate = pEditEngine->GetUpdateMode();
1209 pEditEngine->SetUpdateMode( false );
1211 const sal_Int32 nStart = nStartPara;
1213 Paragraph* pPara = pParaList->GetParagraph( nStartPara );
1215 while( nCount && pPara )
1217 if( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT )
1219 nDepthChangedHdlPrevDepth = pPara->GetDepth();
1220 mnDepthChangeHdlPrevFlags = pPara->nFlags;
1222 ImpConvertEdtToOut( nStartPara );
1224 pHdlParagraph = pPara;
1226 if( nStartPara == nStart )
1228 // the existing paragraph has changed depth or flags
1229 if( (pPara->GetDepth() != nDepthChangedHdlPrevDepth) || (pPara->nFlags != mnDepthChangeHdlPrevFlags) )
1230 DepthChangedHdl();
1233 else // EditEngine mode
1235 sal_Int16 nDepth = -1;
1236 const SfxItemSet& rAttrs = pEditEngine->GetParaAttribs( nStartPara );
1237 if ( rAttrs.GetItemState( EE_PARA_OUTLLEVEL ) == SfxItemState::SET )
1239 const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( rAttrs.Get( EE_PARA_OUTLLEVEL ) );
1240 nDepth = rLevel.GetValue();
1242 if ( nDepth != GetDepth( nStartPara ) )
1243 ImplInitDepth( nStartPara, nDepth, false );
1246 nCount--;
1247 nStartPara++;
1248 pPara = pParaList->GetParagraph( nStartPara );
1251 pEditEngine->SetUpdateMode( bUpdate );
1253 DBG_ASSERT(pParaList->GetParagraphCount()==pEditEngine->GetParagraphCount(),"ImpTextPasted failed");
1256 long Outliner::IndentingPagesHdl( OutlinerView* pView )
1258 if( !aIndentingPagesHdl.IsSet() )
1259 return 1;
1260 return aIndentingPagesHdl.Call( pView );
1263 bool Outliner::ImpCanIndentSelectedPages( OutlinerView* pCurView )
1265 // The selected pages must already be set in advance through
1266 // ImpCalcSelectedPages
1268 // If the first paragraph is on level 0 it can not indented in any case,
1269 // possible there might be indentations in the following on the 0 level.
1270 if ( ( mnFirstSelPage == 0 ) && ( ImplGetOutlinerMode() != OUTLINERMODE_TEXTOBJECT ) )
1272 if ( nDepthChangedHdlPrevDepth == 1 ) // is the only page
1273 return false;
1274 else
1275 (void)pCurView->ImpCalcSelectedPages( false ); // without the first
1277 return IndentingPagesHdl( pCurView );
1281 bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView )
1283 // The selected pages must already be set in advance through
1284 // ImpCalcSelectedPages
1285 return RemovingPagesHdl( pCurView );
1288 Outliner::Outliner( SfxItemPool* pPool, sal_uInt16 nMode )
1289 : nMinDepth( -1 )
1292 bStrippingPortions = false;
1293 bPasting = false;
1295 nFirstPage = 1;
1296 nBlockInsCallback = 0;
1298 nMaxDepth = 9;
1300 pParaList = new ParagraphList;
1301 pParaList->SetVisibleStateChangedHdl( LINK( this, Outliner, ParaVisibleStateChangedHdl ) );
1302 Paragraph* pPara = new Paragraph( 0 );
1303 pParaList->Append(pPara);
1304 bFirstParaIsEmpty = true;
1306 pEditEngine = new OutlinerEditEng( this, pPool );
1307 pEditEngine->SetBeginMovingParagraphsHdl( LINK( this, Outliner, BeginMovingParagraphsHdl ) );
1308 pEditEngine->SetEndMovingParagraphsHdl( LINK( this, Outliner, EndMovingParagraphsHdl ) );
1309 pEditEngine->SetBeginPasteOrDropHdl( LINK( this, Outliner, BeginPasteOrDropHdl ) );
1310 pEditEngine->SetEndPasteOrDropHdl( LINK( this, Outliner, EndPasteOrDropHdl ) );
1312 Init( nMode );
1315 Outliner::~Outliner()
1318 pParaList->Clear( true );
1319 delete pParaList;
1320 delete pEditEngine;
1323 size_t Outliner::InsertView( OutlinerView* pView, size_t nIndex )
1325 size_t ActualIndex;
1327 if ( nIndex >= aViewList.size() )
1329 aViewList.push_back( pView );
1330 ActualIndex = aViewList.size() - 1;
1332 else
1334 ViewList::iterator it = aViewList.begin();
1335 advance( it, nIndex );
1336 ActualIndex = nIndex;
1338 pEditEngine->InsertView( pView->pEditView, nIndex );
1339 return ActualIndex;
1342 OutlinerView* Outliner::RemoveView( OutlinerView* pView )
1345 for ( ViewList::iterator it = aViewList.begin(); it != aViewList.end(); ++it )
1347 if ( *it == pView )
1349 pView->pEditView->HideCursor(); // HACK
1350 pEditEngine->RemoveView( pView->pEditView );
1351 aViewList.erase( it );
1352 break;
1355 return NULL; // return superfluous
1358 OutlinerView* Outliner::RemoveView( size_t nIndex )
1361 EditView* pEditView = pEditEngine->GetView( nIndex );
1362 pEditView->HideCursor(); // HACK
1364 pEditEngine->RemoveView( nIndex );
1367 ViewList::iterator it = aViewList.begin();
1368 advance( it, nIndex );
1369 aViewList.erase( it );
1372 return NULL; // return superfluous
1376 OutlinerView* Outliner::GetView( size_t nIndex ) const
1378 return ( nIndex >= aViewList.size() ) ? NULL : aViewList[ nIndex ];
1381 size_t Outliner::GetViewCount() const
1383 return aViewList.size();
1386 void Outliner::ParagraphInsertedHdl()
1388 if( !IsInUndo() )
1389 aParaInsertedHdl.Call( this );
1393 void Outliner::ParagraphRemovingHdl()
1395 if( !IsInUndo() )
1396 aParaRemovingHdl.Call( this );
1400 void Outliner::DepthChangedHdl()
1402 if( !IsInUndo() )
1403 aDepthChangedHdl.Call( this );
1407 sal_Int32 Outliner::GetAbsPos( Paragraph* pPara )
1409 DBG_ASSERT(pPara,"GetAbsPos:No Para");
1410 return pParaList->GetAbsPos( pPara );
1413 sal_Int32 Outliner::GetParagraphCount() const
1415 return pParaList->GetParagraphCount();
1418 Paragraph* Outliner::GetParagraph( sal_Int32 nAbsPos ) const
1420 return pParaList->GetParagraph( nAbsPos );
1423 bool Outliner::HasChildren( Paragraph* pParagraph ) const
1425 return pParaList->HasChildren( pParagraph );
1428 bool Outliner::ImplHasNumberFormat( sal_Int32 nPara ) const
1430 return GetNumberFormat(nPara) != 0;
1431 #if 0 // The below code is obviously unreachable
1432 if ( GetNumberFormat(nPara) )
1434 const SfxBoolItem& rBulletState = (const SfxBoolItem&) pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE );
1435 return rBulletState.GetValue();
1437 else
1438 return false;
1439 #endif
1442 const SvxNumberFormat* Outliner::GetNumberFormat( sal_Int32 nPara ) const
1444 const SvxNumberFormat* pFmt = NULL;
1446 Paragraph* pPara = pParaList->GetParagraph( nPara );
1447 if (!pPara)
1448 return NULL;
1450 sal_Int16 nDepth = pPara->GetDepth();
1452 if( nDepth >= 0 )
1454 const SvxNumBulletItem& rNumBullet = static_cast<const SvxNumBulletItem&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_NUMBULLET ) );
1455 if ( rNumBullet.GetNumRule()->GetLevelCount() > nDepth )
1456 pFmt = rNumBullet.GetNumRule()->Get( nDepth );
1459 return pFmt;
1462 Size Outliner::ImplGetBulletSize( sal_Int32 nPara )
1464 Paragraph* pPara = pParaList->GetParagraph( nPara );
1465 if (!pPara)
1466 return Size();
1468 if( pPara->aBulSize.Width() == -1 )
1470 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1471 DBG_ASSERT( pFmt, "ImplGetBulletSize - no Bullet!" );
1473 if ( pFmt->GetNumberingType() == SVX_NUM_NUMBER_NONE )
1475 pPara->aBulSize = Size( 0, 0 );
1477 else if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
1479 OUString aBulletText = ImplGetBulletText( nPara );
1480 OutputDevice* pRefDev = pEditEngine->GetRefDevice();
1481 vcl::Font aBulletFont( ImpCalcBulletFont( nPara ) );
1482 vcl::Font aRefFont( pRefDev->GetFont());
1483 pRefDev->SetFont( aBulletFont );
1484 pPara->aBulSize.Width() = pRefDev->GetTextWidth( aBulletText );
1485 pPara->aBulSize.Height() = pRefDev->GetTextHeight();
1486 pRefDev->SetFont( aRefFont );
1488 else
1490 pPara->aBulSize = OutputDevice::LogicToLogic( pFmt->GetGraphicSize(), MAP_100TH_MM, pEditEngine->GetRefDevice()->GetMapMode() );
1494 return pPara->aBulSize;
1497 void Outliner::ImplCheckParagraphs( sal_Int32 nStart, sal_Int32 nEnd )
1500 for ( sal_Int32 n = nStart; n < nEnd; n++ )
1502 Paragraph* pPara = pParaList->GetParagraph( n );
1503 if (pPara)
1505 pPara->Invalidate();
1506 ImplCalcBulletText( n, false, false );
1511 void Outliner::SetRefDevice( OutputDevice* pRefDev )
1513 pEditEngine->SetRefDevice( pRefDev );
1514 for ( sal_Int32 n = pParaList->GetParagraphCount(); n; )
1516 Paragraph* pPara = pParaList->GetParagraph( --n );
1517 pPara->Invalidate();
1521 void Outliner::ParaAttribsChanged( sal_Int32 nPara )
1524 // The Outliner does not have an undo of its own, when paragraphs are
1525 // separated/merged. When ParagraphInserted the attribute EE_PARA_OUTLLEVEL
1526 // may not be set, this is however needed when the depth of the paragraph
1527 // is to be determined.
1528 if( pEditEngine->IsInUndo() )
1530 if ( pParaList->GetParagraphCount() == pEditEngine->GetParagraphCount() )
1532 Paragraph* pPara = pParaList->GetParagraph( nPara );
1533 const SfxInt16Item& rLevel = static_cast<const SfxInt16Item&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ) );
1534 if ( pPara && pPara->GetDepth() != rLevel.GetValue() )
1536 pPara->SetDepth( rLevel.GetValue() );
1537 ImplCalcBulletText( nPara, true, true );
1543 void Outliner::StyleSheetChanged( SfxStyleSheet* pStyle )
1546 // The EditEngine calls StyleSheetChanged also for derived styles.
1547 // Here all the paragraphs, which had the said template, used to be
1548 // hunted by a ImpRecalcParaAttribs, why?
1549 // => only the Bullet-representation can really change...
1550 sal_Int32 nParas = pParaList->GetParagraphCount();
1551 for( sal_Int32 nPara = 0; nPara < nParas; nPara++ )
1553 if ( pEditEngine->GetStyleSheet( nPara ) == pStyle )
1555 ImplCheckNumBulletItem( nPara );
1556 ImplCalcBulletText( nPara, false, false );
1557 // EditEngine formats changed paragraphs before calling this method,
1558 // so they are not reformatted now and use wrong bullet indent
1559 pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) );
1564 Rectangle Outliner::ImpCalcBulletArea( sal_Int32 nPara, bool bAdjust, bool bReturnPaperPos )
1566 // Bullet area within the paragraph ...
1567 Rectangle aBulletArea;
1569 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1570 if ( pFmt )
1572 Point aTopLeft;
1573 Size aBulletSize( ImplGetBulletSize( nPara ) );
1575 bool bOutlineMode = bool( pEditEngine->GetControlWord() & EEControlBits::OUTLINER );
1577 // the ODF attribute text:space-before which holds the spacing to add to the left of the label
1578 const short nSpaceBefore = pFmt->GetAbsLSpace() + pFmt->GetFirstLineOffset();
1580 const SvxLRSpaceItem& rLR = static_cast<const SvxLRSpaceItem&>( pEditEngine->GetParaAttrib( nPara, bOutlineMode ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ) );
1581 aTopLeft.X() = rLR.GetTextLeft() + rLR.GetTextFirstLineOfst() + nSpaceBefore;
1583 long nBulletWidth = std::max( (long) -rLR.GetTextFirstLineOfst(), (long) ((-pFmt->GetFirstLineOffset()) + pFmt->GetCharTextDistance()) );
1584 if ( nBulletWidth < aBulletSize.Width() ) // The Bullet creates its space
1585 nBulletWidth = aBulletSize.Width();
1587 if ( bAdjust && !bOutlineMode )
1589 // Adjust when centered or align right
1590 const SvxAdjustItem& rItem = static_cast<const SvxAdjustItem&>(pEditEngine->GetParaAttrib( nPara, EE_PARA_JUST ));
1591 if ( ( !pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_LEFT ) ) ||
1592 ( pEditEngine->IsRightToLeft( nPara ) && ( rItem.GetAdjust() != SVX_ADJUST_RIGHT ) ) )
1594 aTopLeft.X() = pEditEngine->GetFirstLineStartX( nPara ) - nBulletWidth;
1598 // Vertical:
1599 ParagraphInfos aInfos = pEditEngine->GetParagraphInfos( nPara );
1600 if ( aInfos.bValid )
1602 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ // nFirstLineOffset is already added to the StartPos (PaintBullet) from the EditEngine
1603 aInfos.nFirstLineHeight - aInfos.nFirstLineTextHeight
1604 + aInfos.nFirstLineTextHeight / 2
1605 - aBulletSize.Height() / 2;
1606 // may prefer to print out on the baseline ...
1607 if( ( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE ) && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) && ( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) )
1609 vcl::Font aBulletFont( ImpCalcBulletFont( nPara ) );
1610 if ( aBulletFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL )
1612 OutputDevice* pRefDev = pEditEngine->GetRefDevice();
1613 vcl::Font aOldFont = pRefDev->GetFont();
1614 pRefDev->SetFont( aBulletFont );
1615 FontMetric aMetric( pRefDev->GetFontMetric() );
1616 // Leading on the first line ...
1617 aTopLeft.Y() = /* aInfos.nFirstLineOffset + */ aInfos.nFirstLineMaxAscent;
1618 aTopLeft.Y() -= aMetric.GetAscent();
1619 pRefDev->SetFont( aOldFont );
1624 // Horizontal:
1625 if( pFmt->GetNumAdjust() == SVX_ADJUST_RIGHT )
1627 aTopLeft.X() += nBulletWidth - aBulletSize.Width();
1629 else if( pFmt->GetNumAdjust() == SVX_ADJUST_CENTER )
1631 aTopLeft.X() += ( nBulletWidth - aBulletSize.Width() ) / 2;
1634 if ( aTopLeft.X() < 0 ) // then push
1635 aTopLeft.X() = 0;
1637 aBulletArea = Rectangle( aTopLeft, aBulletSize );
1639 if ( bReturnPaperPos )
1641 Size aBulletSize( aBulletArea.GetSize() );
1642 Point aBulletDocPos( aBulletArea.TopLeft() );
1643 aBulletDocPos.Y() += pEditEngine->GetDocPosTopLeft( nPara ).Y();
1644 Point aBulletPos( aBulletDocPos );
1646 if ( IsVertical() )
1648 aBulletPos.Y() = aBulletDocPos.X();
1649 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.Y();
1650 // Rotate:
1651 aBulletPos.X() -= aBulletSize.Height();
1652 Size aSz( aBulletSize );
1653 aBulletSize.Width() = aSz.Height();
1654 aBulletSize.Height() = aSz.Width();
1656 else if ( pEditEngine->IsRightToLeft( nPara ) )
1658 aBulletPos.X() = GetPaperSize().Width() - aBulletDocPos.X() - aBulletSize.Width();
1661 aBulletArea = Rectangle( aBulletPos, aBulletSize );
1663 return aBulletArea;
1666 void Outliner::ExpandHdl()
1668 aExpandHdl.Call( this );
1671 EBulletInfo Outliner::GetBulletInfo( sal_Int32 nPara )
1673 EBulletInfo aInfo;
1675 aInfo.nParagraph = nPara;
1676 aInfo.bVisible = ImplHasNumberFormat( nPara );
1678 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1679 aInfo.nType = pFmt ? pFmt->GetNumberingType() : 0;
1681 if( pFmt )
1683 if( pFmt->GetNumberingType() != SVX_NUM_BITMAP )
1685 aInfo.aText = ImplGetBulletText( nPara );
1687 if( pFmt->GetBulletFont() )
1688 aInfo.aFont = *pFmt->GetBulletFont();
1690 else if ( pFmt->GetBrush()->GetGraphicObject() )
1692 aInfo.aGraphic = pFmt->GetBrush()->GetGraphicObject()->GetGraphic();
1696 if ( aInfo.bVisible )
1698 aInfo.aBounds = ImpCalcBulletArea( nPara, true, true );
1701 return aInfo;
1704 OUString Outliner::GetText( Paragraph* pParagraph, sal_Int32 nCount ) const
1707 OUString aText;
1708 sal_Int32 nStartPara = pParaList->GetAbsPos( pParagraph );
1709 for ( sal_Int32 n = 0; n < nCount; n++ )
1711 aText += pEditEngine->GetText( nStartPara + n );
1712 if ( (n+1) < nCount )
1713 aText += "\n";
1715 return aText;
1718 void Outliner::Remove( Paragraph* pPara, sal_Int32 nParaCount )
1721 sal_Int32 nPos = pParaList->GetAbsPos( pPara );
1722 if( !nPos && ( nParaCount >= pParaList->GetParagraphCount() ) )
1724 Clear();
1726 else
1728 for( sal_Int32 n = 0; n < nParaCount; n++ )
1729 pEditEngine->RemoveParagraph( nPos );
1733 void Outliner::StripPortions()
1735 bStrippingPortions = true;
1736 pEditEngine->StripPortions();
1737 bStrippingPortions = false;
1740 void Outliner::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart,
1741 sal_Int32 nTextLen, const long* pDXArray,const SvxFont& rFont,
1742 sal_Int32 nPara, sal_Int32 nIndex, sal_uInt8 nRightToLeft,
1743 const EEngineData::WrongSpellVector* pWrongSpellVector,
1744 const SvxFieldData* pFieldData,
1745 bool bEndOfLine,
1746 bool bEndOfParagraph,
1747 bool bEndOfBullet,
1748 const ::com::sun::star::lang::Locale* pLocale,
1749 const Color& rOverlineColor,
1750 const Color& rTextLineColor)
1752 if(aDrawPortionHdl.IsSet())
1754 DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, nIndex, pDXArray, pWrongSpellVector,
1755 pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, false, 0, bEndOfLine, bEndOfParagraph, bEndOfBullet);
1757 aDrawPortionHdl.Call( &aInfo );
1761 void Outliner::DrawingTab( const Point& rStartPos, long nWidth, const OUString& rChar, const SvxFont& rFont,
1762 sal_Int32 nPara, sal_Int32 nIndex, sal_uInt8 nRightToLeft, bool bEndOfLine, bool bEndOfParagraph,
1763 const Color& rOverlineColor, const Color& rTextLineColor)
1765 if(aDrawPortionHdl.IsSet())
1767 DrawPortionInfo aInfo( rStartPos, rChar, 0, rChar.getLength(), rFont, nPara, nIndex, NULL, NULL,
1768 NULL, NULL, rOverlineColor, rTextLineColor, nRightToLeft, true, nWidth, bEndOfLine, bEndOfParagraph, false);
1770 aDrawPortionHdl.Call( &aInfo );
1774 bool Outliner::RemovingPagesHdl( OutlinerView* pView )
1776 return !aRemovingPagesHdl.IsSet() || aRemovingPagesHdl.Call( pView );
1779 bool Outliner::ImpCanDeleteSelectedPages( OutlinerView* pCurView, sal_Int32 _nFirstPage, sal_Int32 nPages )
1782 nDepthChangedHdlPrevDepth = nPages;
1783 mnFirstSelPage = _nFirstPage;
1784 pHdlParagraph = 0;
1785 return RemovingPagesHdl( pCurView );
1788 SfxItemSet Outliner::GetParaAttribs( sal_Int32 nPara )
1790 return pEditEngine->GetParaAttribs( nPara );
1793 IMPL_LINK( Outliner, ParaVisibleStateChangedHdl, Paragraph*, pPara )
1796 sal_Int32 nPara = pParaList->GetAbsPos( pPara );
1797 pEditEngine->ShowParagraph( nPara, pPara->IsVisible() );
1799 return 0;
1802 IMPL_LINK_NOARG(Outliner, BeginMovingParagraphsHdl)
1805 if( !IsInUndo() )
1806 GetBeginMovingHdl().Call( this );
1808 return 0;
1811 IMPL_LINK( Outliner, BeginPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1813 UndoActionStart( EDITUNDO_DRAGANDDROP );
1814 maBeginPasteOrDropHdl.Call(pInfos);
1815 return 0;
1818 IMPL_LINK( Outliner, EndPasteOrDropHdl, PasteOrDropInfos*, pInfos )
1820 bPasting = false;
1821 ImpTextPasted( pInfos->nStartPara, pInfos->nEndPara - pInfos->nStartPara + 1 );
1822 maEndPasteOrDropHdl.Call( pInfos );
1823 UndoActionEnd( EDITUNDO_DRAGANDDROP );
1824 return 0;
1827 IMPL_LINK( Outliner, EndMovingParagraphsHdl, MoveParagraphsInfo*, pInfos )
1830 pParaList->MoveParagraphs( pInfos->nStartPara, pInfos->nDestPara, pInfos->nEndPara - pInfos->nStartPara + 1 );
1831 sal_Int32 nChangesStart = std::min( pInfos->nStartPara, pInfos->nDestPara );
1832 sal_Int32 nParas = pParaList->GetParagraphCount();
1833 for ( sal_Int32 n = nChangesStart; n < nParas; n++ )
1834 ImplCalcBulletText( n, false, false );
1836 if( !IsInUndo() )
1837 aEndMovingHdl.Call( this );
1839 return 0;
1842 static bool isSameNumbering( const SvxNumberFormat& rN1, const SvxNumberFormat& rN2 )
1844 if( rN1.GetNumberingType() != rN2.GetNumberingType() )
1845 return false;
1847 if( rN1.GetNumStr(1) != rN2.GetNumStr(1) )
1848 return false;
1850 if( (rN1.GetPrefix() != rN2.GetPrefix()) || (rN1.GetSuffix() != rN2.GetSuffix()) )
1851 return false;
1853 return true;
1856 sal_uInt16 Outliner::ImplGetNumbering( sal_Int32 nPara, const SvxNumberFormat* pParaFmt )
1858 sal_uInt16 nNumber = pParaFmt->GetStart() - 1;
1860 Paragraph* pPara = pParaList->GetParagraph( nPara );
1861 const sal_Int16 nParaDepth = pPara->GetDepth();
1865 pPara = pParaList->GetParagraph( nPara );
1866 const sal_Int16 nDepth = pPara->GetDepth();
1868 // ignore paragraphs that are below our paragraph or have no numbering
1869 if( (nDepth > nParaDepth) || (nDepth == -1) )
1870 continue;
1872 // stop on paragraphs that are above our paragraph
1873 if( nDepth < nParaDepth )
1874 break;
1876 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1878 if( pFmt == 0 )
1879 continue; // ignore paragraphs without bullets
1881 // check if numbering less than or equal to pParaFmt
1882 if( !isSameNumbering( *pFmt, *pParaFmt ) || ( pFmt->GetStart() < pParaFmt->GetStart() ) )
1883 break;
1885 if ( pFmt->GetStart() > pParaFmt->GetStart() )
1887 nNumber += pFmt->GetStart() - pParaFmt->GetStart();
1888 pParaFmt = pFmt;
1891 const SfxBoolItem& rBulletState = static_cast<const SfxBoolItem&>( pEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) );
1893 if( rBulletState.GetValue() )
1894 nNumber += 1;
1896 // same depth, same number format, check for restart
1897 const sal_Int16 nNumberingStartValue = pPara->GetNumberingStartValue();
1898 if( (nNumberingStartValue != -1) || pPara->IsParaIsNumberingRestart() )
1900 if( nNumberingStartValue != -1 )
1901 nNumber += nNumberingStartValue - 1;
1902 break;
1905 while( nPara-- );
1907 return nNumber;
1910 void Outliner::ImplCalcBulletText( sal_Int32 nPara, bool bRecalcLevel, bool bRecalcChildren )
1913 Paragraph* pPara = pParaList->GetParagraph( nPara );
1915 while ( pPara )
1917 OUString aBulletText;
1918 const SvxNumberFormat* pFmt = GetNumberFormat( nPara );
1919 if( pFmt && ( pFmt->GetNumberingType() != SVX_NUM_BITMAP ) )
1921 aBulletText += pFmt->GetPrefix();
1922 if( pFmt->GetNumberingType() == SVX_NUM_CHAR_SPECIAL )
1924 aBulletText += OUString(pFmt->GetBulletChar());
1926 else if( pFmt->GetNumberingType() != SVX_NUM_NUMBER_NONE )
1928 aBulletText += pFmt->GetNumStr( ImplGetNumbering( nPara, pFmt ) );
1930 aBulletText += pFmt->GetSuffix();
1933 if (!pPara->GetText().equals(aBulletText))
1934 pPara->SetText( aBulletText );
1936 pPara->nFlags &= (~ParaFlag::SETBULLETTEXT);
1938 if ( bRecalcLevel )
1940 sal_Int16 nDepth = pPara->GetDepth();
1941 pPara = pParaList->GetParagraph( ++nPara );
1942 if ( !bRecalcChildren )
1944 while ( pPara && ( pPara->GetDepth() > nDepth ) )
1945 pPara = pParaList->GetParagraph( ++nPara );
1948 if ( pPara && ( pPara->GetDepth() < nDepth ) )
1949 pPara = NULL;
1951 else
1953 pPara = NULL;
1958 void Outliner::Clear()
1961 if( !bFirstParaIsEmpty )
1963 ImplBlockInsertionCallbacks( true );
1964 pEditEngine->Clear();
1965 pParaList->Clear( true );
1966 pParaList->Append( new Paragraph( nMinDepth ));
1967 bFirstParaIsEmpty = true;
1968 ImplBlockInsertionCallbacks( false );
1970 else
1972 Paragraph* pPara = pParaList->GetParagraph( 0 );
1973 if(pPara)
1974 pPara->SetDepth( nMinDepth );
1978 void Outliner::SetFlatMode( bool bFlat )
1981 if( bFlat != pEditEngine->IsFlatMode() )
1983 for ( sal_Int32 nPara = pParaList->GetParagraphCount(); nPara; )
1984 pParaList->GetParagraph( --nPara )->aBulSize.Width() = -1;
1986 pEditEngine->SetFlatMode( bFlat );
1990 OUString Outliner::ImplGetBulletText( sal_Int32 nPara )
1992 OUString aRes;
1993 Paragraph* pPara = pParaList->GetParagraph( nPara );
1994 if (pPara)
1996 // Enable optimization again ...
1997 // if( pPara->nFlags & ParaFlag::SETBULLETTEXT )
1998 ImplCalcBulletText( nPara, false, false );
1999 aRes = pPara->GetText();
2001 return aRes;
2004 // this is needed for StarOffice Api
2005 void Outliner::SetLevelDependendStyleSheet( sal_Int32 nPara )
2007 SfxItemSet aOldAttrs( pEditEngine->GetParaAttribs( nPara ) );
2008 ImplSetLevelDependendStyleSheet( nPara );
2009 pEditEngine->SetParaAttribs( nPara, aOldAttrs );
2012 void Outliner::ImplBlockInsertionCallbacks( bool b )
2014 if ( b )
2016 nBlockInsCallback++;
2018 else
2020 DBG_ASSERT( nBlockInsCallback, "ImplBlockInsertionCallbacks ?!" );
2021 nBlockInsCallback--;
2022 if ( !nBlockInsCallback )
2024 // Call blocked notify events...
2025 while(!pEditEngine->aNotifyCache.empty())
2027 EENotify aNotify(pEditEngine->aNotifyCache.front());
2028 // Remove from list before calling, maybe we enter LeaveBlockNotifications while calling the handler...
2029 pEditEngine->aNotifyCache.erase(pEditEngine->aNotifyCache.begin());
2030 pEditEngine->aOutlinerNotifyHdl.Call( &aNotify );
2036 IMPL_LINK( Outliner, EditEngineNotifyHdl, EENotify*, pNotify )
2038 if ( !nBlockInsCallback )
2039 pEditEngine->aOutlinerNotifyHdl.Call( pNotify );
2040 else
2041 pEditEngine->aNotifyCache.push_back(*pNotify);
2043 return 0;
2046 /** sets a link that is called at the beginning of a drag operation at an edit view */
2047 void Outliner::SetBeginDropHdl( const Link<>& rLink )
2049 pEditEngine->SetBeginDropHdl( rLink );
2052 /** sets a link that is called at the end of a drag operation at an edit view */
2053 void Outliner::SetEndDropHdl( const Link<>& rLink )
2055 pEditEngine->SetEndDropHdl( rLink );
2058 /** sets a link that is called before a drop or paste operation. */
2059 void Outliner::SetBeginPasteOrDropHdl( const Link<>& rLink )
2061 maBeginPasteOrDropHdl = rLink;
2064 /** sets a link that is called after a drop or paste operation. */
2065 void Outliner::SetEndPasteOrDropHdl( const Link<>& rLink )
2067 maEndPasteOrDropHdl = rLink;
2070 void Outliner::SetParaFlag( Paragraph* pPara, ParaFlag nFlag )
2072 if( pPara && !pPara->HasFlag( nFlag ) )
2074 if( IsUndoEnabled() && !IsInUndo() )
2075 InsertUndo( new OutlinerUndoChangeParaFlags( this, GetAbsPos( pPara ), pPara->nFlags, pPara->nFlags|nFlag ) );
2077 pPara->SetFlag( nFlag );
2081 bool Outliner::HasParaFlag( const Paragraph* pPara, ParaFlag nFlag )
2083 return pPara && pPara->HasFlag( nFlag );
2086 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */