1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <memory>
21 #include <com/sun/star/i18n/WordType.hpp>
22
23 #include <svl/itempool.hxx>
24 #include <editeng/editeng.hxx>
25 #include <editeng/editview.hxx>
26 #include <editeng/editdata.hxx>
27
28 #include <svl/style.hxx>
29 #include <svl/languageoptions.hxx>
30 #include <i18nlangtag/languagetag.hxx>
31
32 #include <editeng/outliner.hxx>
33 #include <outleeng.hxx>
34 #include "paralist.hxx"
35 #include "outlundo.hxx"
36 #include <editeng/outlobj.hxx>
37 #include <editeng/flditem.hxx>
38 #include <editeng/eeitem.hxx>
39 #include <editeng/numitem.hxx>
40 #include <vcl/window.hxx>
41 #include <vcl/event.hxx>
42 #include <vcl/ptrstyle.hxx>
43 #include <svl/itemset.hxx>
44 #include <svl/eitem.hxx>
45 #include <editeng/editstat.hxx>
46 #include <sal/log.hxx>
47 #include <osl/diagnose.h>
48 #include <tools/debug.hxx>
49
50 using namespace ::com::sun::star;
51
52
OutlinerView(Outliner * pOut,vcl::Window * pWin)53 OutlinerView::OutlinerView( Outliner* pOut, vcl::Window* pWin )
54 {
55 pOwner = pOut;
56 pEditView.reset( new EditView( pOut->pEditEngine.get(), pWin ) );
57 }
58
~OutlinerView()59 OutlinerView::~OutlinerView()
60 {
61 }
62
Paint(const tools::Rectangle & rRect,OutputDevice * pTargetDevice)63 void OutlinerView::Paint( const tools::Rectangle& rRect, OutputDevice* pTargetDevice )
64 {
65 // For the first Paint/KeyInput/Drop an empty Outliner is turned into
66 // an Outliner with exactly one paragraph.
67 if( pOwner->bFirstParaIsEmpty )
68 pOwner->Insert( OUString() );
69
70 pEditView->Paint( rRect, pTargetDevice );
71 }
72
PostKeyEvent(const KeyEvent & rKEvt,vcl::Window const * pFrameWin)73 bool OutlinerView::PostKeyEvent( const KeyEvent& rKEvt, vcl::Window const * pFrameWin )
74 {
75 // For the first Paint/KeyInput/Drop an empty Outliner is turned into
76 // an Outliner with exactly one paragraph.
77 if( pOwner->bFirstParaIsEmpty )
78 pOwner->Insert( OUString() );
79
80 bool bKeyProcessed = false;
81 ESelection aSel( pEditView->GetSelection() );
82 bool bSelection = aSel.HasRange();
83 vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
84 KeyFuncType eFunc = aKeyCode.GetFunction();
85 sal_uInt16 nCode = aKeyCode.GetCode();
86 bool bReadOnly = IsReadOnly();
87
88 if( bSelection && ( nCode != KEY_TAB ) && EditEngine::DoesKeyChangeText( rKEvt ) )
89 {
90 if ( ImpCalcSelectedPages( false ) && !pOwner->ImpCanDeleteSelectedPages( this ) )
91 return true;
92 }
93
94 if ( eFunc != KeyFuncType::DONTKNOW )
95 {
96 switch ( eFunc )
97 {
98 case KeyFuncType::CUT:
99 {
100 if ( !bReadOnly )
101 {
102 Cut();
103 bKeyProcessed = true;
104 }
105 }
106 break;
107 case KeyFuncType::COPY:
108 {
109 Copy();
110 bKeyProcessed = true;
111 }
112 break;
113 case KeyFuncType::PASTE:
114 {
115 if ( !bReadOnly )
116 {
117 PasteSpecial();
118 bKeyProcessed = true;
119 }
120 }
121 break;
122 case KeyFuncType::DELETE:
123 {
124 if( !bReadOnly && !bSelection && ( pOwner->GetOutlinerMode() != OutlinerMode::TextObject ) )
125 {
126 if( aSel.nEndPos == pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) )
127 {
128 Paragraph* pNext = pOwner->pParaList->GetParagraph( aSel.nEndPara+1 );
129 if( pNext && pNext->HasFlag(ParaFlag::ISPAGE) )
130 {
131 if( !pOwner->ImpCanDeleteSelectedPages( this, aSel.nEndPara, 1 ) )
132 return false;
133 }
134 }
135 }
136 }
137 break;
138 default: // is then possibly edited below.
139 eFunc = KeyFuncType::DONTKNOW;
140 }
141 }
142 if ( eFunc == KeyFuncType::DONTKNOW )
143 {
144 switch ( nCode )
145 {
146 case KEY_TAB:
147 {
148 if ( !bReadOnly && !aKeyCode.IsMod1() && !aKeyCode.IsMod2() )
149 {
150 if ( ( pOwner->GetOutlinerMode() != OutlinerMode::TextObject ) &&
151 ( pOwner->GetOutlinerMode() != OutlinerMode::TitleObject ) &&
152 ( bSelection || !aSel.nStartPos ) )
153 {
154 Indent( aKeyCode.IsShift() ? -1 : +1 );
155 bKeyProcessed = true;
156 }
157 else if ( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) &&
158 !bSelection && !aSel.nEndPos && pOwner->ImplHasNumberFormat( aSel.nEndPara ) )
159 {
160 Indent( aKeyCode.IsShift() ? -1 : +1 );
161 bKeyProcessed = true;
162 }
163 }
164 }
165 break;
166 case KEY_BACKSPACE:
167 {
168 if( !bReadOnly && !bSelection && aSel.nEndPara && !aSel.nEndPos )
169 {
170 Paragraph* pPara = pOwner->pParaList->GetParagraph( aSel.nEndPara );
171 Paragraph* pPrev = pOwner->pParaList->GetParagraph( aSel.nEndPara-1 );
172 if( !pPrev->IsVisible() )
173 return true;
174 if( !pPara->GetDepth() )
175 {
176 if(!pOwner->ImpCanDeleteSelectedPages(this, aSel.nEndPara , 1 ) )
177 return true;
178 }
179 }
180 }
181 break;
182 case KEY_RETURN:
183 {
184 if ( !bReadOnly )
185 {
186 // Special treatment: hard return at the end of a paragraph,
187 // which has collapsed subparagraphs.
188 Paragraph* pPara = pOwner->pParaList->GetParagraph( aSel.nEndPara );
189
190 if( !aKeyCode.IsShift() )
191 {
192 // Don't let insert empty paragraph with numbering. Instead end numbering.
193 if (pPara->GetDepth() > -1 &&
194 pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) == 0)
195 {
196 ToggleBullets();
197 return true;
198 }
199 // ImpGetCursor again???
200 if( !bSelection &&
201 aSel.nEndPos == pOwner->pEditEngine->GetTextLen( aSel.nEndPara ) )
202 {
203 sal_Int32 nChildren = pOwner->pParaList->GetChildCount(pPara);
204 if( nChildren && !pOwner->pParaList->HasVisibleChildren(pPara))
205 {
206 pOwner->UndoActionStart( OLUNDO_INSERT );
207 sal_Int32 nTemp = aSel.nEndPara;
208 nTemp += nChildren;
209 nTemp++; // insert above next Non-Child
210 SAL_WARN_IF( nTemp < 0, "editeng", "OutlinerView::PostKeyEvent - overflow");
211 if (nTemp >= 0)
212 {
213 pOwner->Insert( OUString(),nTemp,pPara->GetDepth());
214 // Position the cursor
215 ESelection aTmpSel(nTemp,0,nTemp,0);
216 pEditView->SetSelection( aTmpSel );
217 }
218 pEditView->ShowCursor();
219 pOwner->UndoActionEnd();
220 bKeyProcessed = true;
221 }
222 }
223 }
224 if( !bKeyProcessed && !bSelection &&
225 !aKeyCode.IsShift() && aKeyCode.IsMod1() &&
226 ( aSel.nEndPos == pOwner->pEditEngine->GetTextLen(aSel.nEndPara) ) )
227 {
228 pOwner->UndoActionStart( OLUNDO_INSERT );
229 sal_Int32 nTemp = aSel.nEndPara;
230 nTemp++;
231 pOwner->Insert( OUString(), nTemp, pPara->GetDepth()+1 );
232
233 // Position the cursor
234 ESelection aTmpSel(nTemp,0,nTemp,0);
235 pEditView->SetSelection( aTmpSel );
236 pEditView->ShowCursor();
237 pOwner->UndoActionEnd();
238 bKeyProcessed = true;
239 }
240 }
241 }
242 break;
243 }
244 }
245
246 return bKeyProcessed || pEditView->PostKeyEvent( rKEvt, pFrameWin );
247 }
248
ImpCheckMousePos(const Point & rPosPix,MouseTarget & reTarget)249 sal_Int32 OutlinerView::ImpCheckMousePos(const Point& rPosPix, MouseTarget& reTarget)
250 {
251 sal_Int32 nPara = EE_PARA_NOT_FOUND;
252
253 Point aMousePosWin = pEditView->GetOutputDevice().PixelToLogic( rPosPix );
254 if( !pEditView->GetOutputArea().Contains( aMousePosWin ) )
255 {
256 reTarget = MouseTarget::Outside;
257 }
258 else
259 {
260 reTarget = MouseTarget::Text;
261
262 Point aPaperPos( aMousePosWin );
263 tools::Rectangle aOutArea = pEditView->GetOutputArea();
264 tools::Rectangle aVisArea = pEditView->GetVisArea();
265 aPaperPos.AdjustX( -(aOutArea.Left()) );
266 aPaperPos.AdjustX(aVisArea.Left() );
267 aPaperPos.AdjustY( -(aOutArea.Top()) );
268 aPaperPos.AdjustY(aVisArea.Top() );
269
270 bool bBullet;
271 if ( pOwner->IsTextPos( aPaperPos, 0, &bBullet ) )
272 {
273 Point aDocPos = pOwner->GetDocPos( aPaperPos );
274 nPara = pOwner->pEditEngine->FindParagraph( aDocPos.Y() );
275
276 if ( bBullet )
277 {
278 reTarget = MouseTarget::Bullet;
279 }
280 else
281 {
282 // Check for hyperlink
283 const SvxFieldItem* pFieldItem = pEditView->GetField( aMousePosWin );
284 if ( pFieldItem && pFieldItem->GetField() && dynamic_cast< const SvxURLField* >(pFieldItem->GetField()) != nullptr )
285 reTarget = MouseTarget::Hypertext;
286 }
287 }
288 }
289 return nPara;
290 }
291
MouseMove(const MouseEvent & rMEvt)292 bool OutlinerView::MouseMove( const MouseEvent& rMEvt )
293 {
294 if( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->getEditEngine().IsInSelectionMode())
295 return pEditView->MouseMove( rMEvt );
296
297 Point aMousePosWin( pEditView->GetOutputDevice().PixelToLogic( rMEvt.GetPosPixel() ) );
298 if( !pEditView->GetOutputArea().Contains( aMousePosWin ) )
299 return false;
300
301 PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() );
302 pEditView->GetWindow()->SetPointer( aPointer );
303 return pEditView->MouseMove( rMEvt );
304 }
305
306
MouseButtonDown(const MouseEvent & rMEvt)307 bool OutlinerView::MouseButtonDown( const MouseEvent& rMEvt )
308 {
309 if ( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->getEditEngine().IsInSelectionMode() )
310 return pEditView->MouseButtonDown( rMEvt );
311
312 Point aMousePosWin( pEditView->GetOutputDevice().PixelToLogic( rMEvt.GetPosPixel() ) );
313 if( !pEditView->GetOutputArea().Contains( aMousePosWin ) )
314 return false;
315
316 PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() );
317 pEditView->GetWindow()->SetPointer( aPointer );
318
319 MouseTarget eTarget;
320 sal_Int32 nPara = ImpCheckMousePos( rMEvt.GetPosPixel(), eTarget );
321 if ( eTarget == MouseTarget::Bullet )
322 {
323 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
324 bool bHasChildren = (pPara && pOwner->pParaList->HasChildren(pPara));
325 if( rMEvt.GetClicks() == 1 )
326 {
327 sal_Int32 nEndPara = nPara;
328 if ( bHasChildren && pOwner->pParaList->HasVisibleChildren(pPara) )
329 nEndPara += pOwner->pParaList->GetChildCount( pPara );
330 // The selection is inverted, so that EditEngine does not scroll
331 ESelection aSel(nEndPara, EE_TEXTPOS_ALL, nPara, 0 );
332 pEditView->SetSelection( aSel );
333 }
334 else if( rMEvt.GetClicks() == 2 && bHasChildren )
335 ImpToggleExpand( pPara );
336
337 return true;
338 }
339
340 // special case for outliner view in impress, check if double click hits the page icon for toggle
341 if( (nPara == EE_PARA_NOT_FOUND) && (pOwner->GetOutlinerMode() == OutlinerMode::OutlineView) && (eTarget == MouseTarget::Text) && (rMEvt.GetClicks() == 2) )
342 {
343 ESelection aSel( pEditView->GetSelection() );
344 nPara = aSel.nStartPara;
345 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
346 if( (pPara && pOwner->pParaList->HasChildren(pPara)) && pPara->HasFlag(ParaFlag::ISPAGE) )
347 {
348 ImpToggleExpand( pPara );
349 }
350 }
351 return pEditView->MouseButtonDown( rMEvt );
352 }
353
354
MouseButtonUp(const MouseEvent & rMEvt)355 bool OutlinerView::MouseButtonUp( const MouseEvent& rMEvt )
356 {
357 if ( ( pOwner->GetOutlinerMode() == OutlinerMode::TextObject ) || pEditView->getEditEngine().IsInSelectionMode() )
358 return pEditView->MouseButtonUp( rMEvt );
359
360 Point aMousePosWin( pEditView->GetOutputDevice().PixelToLogic( rMEvt.GetPosPixel() ) );
361 if( !pEditView->GetOutputArea().Contains( aMousePosWin ) )
362 return false;
363
364 PointerStyle aPointer = GetPointer( rMEvt.GetPosPixel() );
365 pEditView->GetWindow()->SetPointer( aPointer );
366
367 return pEditView->MouseButtonUp( rMEvt );
368 }
369
ReleaseMouse()370 void OutlinerView::ReleaseMouse()
371 {
372 pEditView->ReleaseMouse();
373 }
374
ImpToggleExpand(Paragraph const * pPara)375 void OutlinerView::ImpToggleExpand( Paragraph const * pPara )
376 {
377 sal_Int32 nPara = pOwner->pParaList->GetAbsPos( pPara );
378 pEditView->SetSelection( ESelection( nPara, 0, nPara, 0 ) );
379 ImplExpandOrCollaps( nPara, nPara, !pOwner->pParaList->HasVisibleChildren( pPara ) );
380 pEditView->ShowCursor();
381 }
382
Select(Paragraph const * pParagraph,bool bSelect)383 void OutlinerView::Select( Paragraph const * pParagraph, bool bSelect )
384 {
385 sal_Int32 nPara = pOwner->pParaList->GetAbsPos( pParagraph );
386 sal_Int32 nEnd = 0;
387 if ( bSelect )
388 nEnd = SAL_MAX_INT32;
389
390 ESelection aSel( nPara, 0, nPara, nEnd );
391 pEditView->SetSelection( aSel );
392 }
393
SetDepth(sal_Int32 nParagraph,sal_Int16 nDepth)394 void OutlinerView::SetDepth(sal_Int32 nParagraph, sal_Int16 nDepth)
395 {
396 Paragraph* pParagraph = pOwner->GetParagraph(nParagraph);
397 pOwner->SetDepth(pParagraph, nDepth);
398 }
399
GetDepth() const400 sal_Int16 OutlinerView::GetDepth() const
401 {
402 ESelection aESelection = GetSelection();
403 aESelection.Adjust();
404 sal_Int16 nDepth = pOwner->GetDepth(aESelection.nStartPara);
405 for (sal_Int32 nPara = aESelection.nStartPara + 1; nPara <= aESelection.nEndPara; ++nPara)
406 {
407 if (nDepth != pOwner->GetDepth(nPara))
408 return -2;
409 }
410 return nDepth;
411 }
412
SetAttribs(const SfxItemSet & rAttrs)413 void OutlinerView::SetAttribs( const SfxItemSet& rAttrs )
414 {
415 bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false );
416
417 if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() )
418 pOwner->UndoActionStart( OLUNDO_ATTR );
419
420 ParaRange aSel = ImpGetSelectedParagraphs( false );
421
422 pEditView->SetAttribs( rAttrs );
423
424 // Update Bullet text
425 for( sal_Int32 nPara= aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ )
426 {
427 pOwner->ImplCheckNumBulletItem( nPara );
428 pOwner->ImplCalcBulletText( nPara, false, false );
429
430 if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() )
431 pOwner->InsertUndo( std::make_unique<OutlinerUndoCheckPara>( pOwner, nPara ) );
432 }
433
434 if( !pOwner->IsInUndo() && pOwner->IsUndoEnabled() )
435 pOwner->UndoActionEnd();
436
437 pEditView->SetEditEngineUpdateLayout( bUpdate );
438 }
439
ImpGetSelectedParagraphs(bool bIncludeHiddenChildren)440 ParaRange OutlinerView::ImpGetSelectedParagraphs( bool bIncludeHiddenChildren )
441 {
442 ESelection aSel = pEditView->GetSelection();
443 ParaRange aParas( aSel.nStartPara, aSel.nEndPara );
444 aParas.Adjust();
445
446 // Record the invisible Children of the last Parents in the selection
447 if ( bIncludeHiddenChildren )
448 {
449 Paragraph* pLast = pOwner->pParaList->GetParagraph( aParas.nEndPara );
450 if ( pOwner->pParaList->HasHiddenChildren( pLast ) )
451 aParas.nEndPara = aParas.nEndPara + pOwner->pParaList->GetChildCount( pLast );
452 }
453 return aParas;
454 }
455
456 // TODO: Name should be changed!
AdjustDepth(short nDX)457 void OutlinerView::AdjustDepth( short nDX )
458 {
459 Indent( nDX );
460 }
461
Indent(short nDiff)462 void OutlinerView::Indent( short nDiff )
463 {
464 if( !nDiff || ( ( nDiff > 0 ) && ImpCalcSelectedPages( true ) && !pOwner->ImpCanIndentSelectedPages( this ) ) )
465 return;
466
467 const bool bOutlinerView = bool(pOwner->pEditEngine->GetControlWord() & EEControlBits::OUTLINER);
468 bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false );
469
470 bool bUndo = !pOwner->IsInUndo() && pOwner->IsUndoEnabled();
471
472 if( bUndo )
473 pOwner->UndoActionStart( OLUNDO_DEPTH );
474
475 sal_Int16 nMinDepth = -1; // Optimization: avoid recalculate too many paragraphs if not really needed.
476
477 ParaRange aSel = ImpGetSelectedParagraphs( true );
478 for ( sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ )
479 {
480 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
481
482 sal_Int16 nOldDepth = pPara->GetDepth();
483 sal_Int16 nNewDepth = nOldDepth + nDiff;
484
485 if( bOutlinerView && nPara )
486 {
487 const bool bPage = pPara->HasFlag(ParaFlag::ISPAGE);
488 if( (bPage && (nDiff == +1)) || (!bPage && (nDiff == -1) && (nOldDepth <= 0)) )
489 {
490 // Notify App
491 pOwner->nDepthChangedHdlPrevDepth = nOldDepth;
492 ParaFlag nPrevFlags = pPara->nFlags;
493
494 if( bPage )
495 pPara->RemoveFlag( ParaFlag::ISPAGE );
496 else
497 pPara->SetFlag( ParaFlag::ISPAGE );
498
499 pOwner->DepthChangedHdl(pPara, nPrevFlags);
500 pOwner->pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) );
501
502 if( bUndo )
503 pOwner->InsertUndo( std::make_unique<OutlinerUndoChangeParaFlags>( pOwner, nPara, nPrevFlags, pPara->nFlags ) );
504
505 continue;
506 }
507 }
508
509 // do not switch off numeration with tab
510 if( (nOldDepth == 0) && (nNewDepth == -1) )
511 continue;
512
513 // do not indent if there is no numeration enabled
514 if( nOldDepth == -1 )
515 continue;
516
517 if ( nNewDepth < Outliner::gnMinDepth )
518 nNewDepth = Outliner::gnMinDepth;
519 if ( nNewDepth > pOwner->nMaxDepth )
520 nNewDepth = pOwner->nMaxDepth;
521
522 if( nOldDepth < nMinDepth )
523 nMinDepth = nOldDepth;
524 if( nNewDepth < nMinDepth )
525 nMinDepth = nNewDepth;
526
527 if( nOldDepth != nNewDepth )
528 {
529 if ( ( nPara == aSel.nStartPara ) && aSel.nStartPara && ( pOwner->GetOutlinerMode() != OutlinerMode::TextObject ))
530 {
531 // Special case: the predecessor of an indented paragraph is
532 // invisible and is now on the same level as the visible
533 // paragraph. In this case, the next visible paragraph is
534 // searched for and fluffed.
535 #ifdef DBG_UTIL
536 Paragraph* _pPara = pOwner->pParaList->GetParagraph( aSel.nStartPara );
537 DBG_ASSERT(_pPara->IsVisible(),"Selected Paragraph invisible ?!");
538 #endif
539 Paragraph* pPrev= pOwner->pParaList->GetParagraph( aSel.nStartPara-1 );
540
541 if( !pPrev->IsVisible() && ( pPrev->GetDepth() == nNewDepth ) )
542 {
543 // Predecessor is collapsed and is on the same level
544 // => find next visible paragraph and expand it
545 pPrev = pOwner->pParaList->GetParent( pPrev );
546 while( !pPrev->IsVisible() )
547 pPrev = pOwner->pParaList->GetParent( pPrev );
548
549 pOwner->Expand( pPrev );
550 pOwner->InvalidateBullet(pOwner->pParaList->GetAbsPos(pPrev));
551 }
552 }
553
554 pOwner->nDepthChangedHdlPrevDepth = nOldDepth;
555 ParaFlag nPrevFlags = pPara->nFlags;
556
557 pOwner->ImplInitDepth( nPara, nNewDepth, true );
558 pOwner->ImplCalcBulletText( nPara, false, false );
559
560 if ( pOwner->GetOutlinerMode() == OutlinerMode::OutlineObject )
561 pOwner->ImplSetLevelDependentStyleSheet( nPara );
562
563 // Notify App
564 pOwner->DepthChangedHdl(pPara, nPrevFlags);
565 }
566 else
567 {
568 // Needs at least a repaint...
569 pOwner->pEditEngine->QuickMarkInvalid( ESelection( nPara, 0, nPara, 0 ) );
570 }
571 }
572
573 sal_Int32 nParas = pOwner->pParaList->GetParagraphCount();
574 for ( sal_Int32 n = aSel.nEndPara+1; n < nParas; n++ )
575 {
576 Paragraph* pPara = pOwner->pParaList->GetParagraph( n );
577 if ( pPara->GetDepth() < nMinDepth )
578 break;
579 pOwner->ImplCalcBulletText( n, false, false );
580 }
581
582 if ( bUpdate )
583 {
584 pEditView->SetEditEngineUpdateLayout( true );
585 pEditView->ShowCursor();
586 }
587
588 if( bUndo )
589 pOwner->UndoActionEnd();
590 }
591
AdjustHeight(tools::Long nDY)592 void OutlinerView::AdjustHeight( tools::Long nDY )
593 {
594 pEditView->MoveParagraphs( nDY );
595 }
596
GetVisArea() const597 tools::Rectangle OutlinerView::GetVisArea() const
598 {
599 return pEditView->GetVisArea();
600 }
601
Expand()602 void OutlinerView::Expand()
603 {
604 ParaRange aParas = ImpGetSelectedParagraphs( false );
605 ImplExpandOrCollaps( aParas.nStartPara, aParas.nEndPara, true );
606 }
607
608
Collapse()609 void OutlinerView::Collapse()
610 {
611 ParaRange aParas = ImpGetSelectedParagraphs( false );
612 ImplExpandOrCollaps( aParas.nStartPara, aParas.nEndPara, false );
613 }
614
615
ExpandAll()616 void OutlinerView::ExpandAll()
617 {
618 ImplExpandOrCollaps( 0, pOwner->pParaList->GetParagraphCount()-1, true );
619 }
620
621
CollapseAll()622 void OutlinerView::CollapseAll()
623 {
624 ImplExpandOrCollaps( 0, pOwner->pParaList->GetParagraphCount()-1, false );
625 }
626
ImplExpandOrCollaps(sal_Int32 nStartPara,sal_Int32 nEndPara,bool bExpand)627 void OutlinerView::ImplExpandOrCollaps( sal_Int32 nStartPara, sal_Int32 nEndPara, bool bExpand )
628 {
629 bool bUpdate = pOwner->SetUpdateLayout( false );
630
631 bool bUndo = !pOwner->IsInUndo() && pOwner->IsUndoEnabled();
632 if( bUndo )
633 pOwner->UndoActionStart( bExpand ? OLUNDO_EXPAND : OLUNDO_COLLAPSE );
634
635 for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; nPara++ )
636 {
637 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
638 bool bDone = bExpand ? pOwner->Expand( pPara ) : pOwner->Collapse( pPara );
639 if( bDone )
640 {
641 // The line under the paragraph should disappear ...
642 pOwner->pEditEngine->QuickMarkToBeRepainted( nPara );
643 }
644 }
645
646 if( bUndo )
647 pOwner->UndoActionEnd();
648
649 if ( bUpdate )
650 {
651 pOwner->SetUpdateLayout( true );
652 pEditView->ShowCursor();
653 }
654 }
655
InsertText(const OutlinerParaObject & rParaObj)656 void OutlinerView::InsertText( const OutlinerParaObject& rParaObj )
657 {
658 // Like Paste, only EditView::Insert, instead of EditView::Paste.
659 // Actually not quite true that possible indentations must be corrected,
660 // but that comes later by a universal import. The indentation level is
661 // then determined right in the Inserted method.
662 // Possible structure:
663 // pImportInfo with DestPara, DestPos, nFormat, pParaObj...
664 // Possibly problematic:
665 // EditEngine, RTF => Splitting the area, later join together.
666
667 if ( ImpCalcSelectedPages( false ) && !pOwner->ImpCanDeleteSelectedPages( this ) )
668 return;
669
670 pOwner->UndoActionStart( OLUNDO_INSERT );
671
672 const bool bPrevUpdateLayout = pOwner->pEditEngine->SetUpdateLayout( false );
673 sal_Int32 nStart, nParaCount;
674 nParaCount = pOwner->pEditEngine->GetParagraphCount();
675 sal_uInt16 nSize = ImpInitPaste( nStart );
676 pEditView->InsertText( rParaObj.GetTextObject() );
677 ImpPasted( nStart, nParaCount, nSize);
678 pEditView->SetEditEngineUpdateLayout( bPrevUpdateLayout );
679
680 pOwner->UndoActionEnd();
681
682 pEditView->ShowCursor();
683 }
684
685
Cut()686 void OutlinerView::Cut()
687 {
688 if ( !ImpCalcSelectedPages( false ) || pOwner->ImpCanDeleteSelectedPages( this ) ) {
689 pEditView->Cut();
690 // Chaining handling
691 aEndCutPasteLink.Call(nullptr);
692 }
693 }
694
PasteSpecial(SotClipboardFormatId format)695 void OutlinerView::PasteSpecial(SotClipboardFormatId format)
696 {
697 Paste( true, format );
698 }
699
Paste(bool bUseSpecial,SotClipboardFormatId format)700 void OutlinerView::Paste( bool bUseSpecial, SotClipboardFormatId format)
701 {
702 if ( ImpCalcSelectedPages( false ) && !pOwner->ImpCanDeleteSelectedPages( this ) )
703 return;
704
705 pOwner->UndoActionStart( OLUNDO_INSERT );
706
707 const bool bPrevUpdateLayout = pOwner->pEditEngine->SetUpdateLayout( false );
708 pOwner->bPasting = true;
709
710 if ( bUseSpecial )
711 pEditView->PasteSpecial(format);
712 else
713 pEditView->Paste();
714
715 if ( pOwner->GetOutlinerMode() == OutlinerMode::OutlineObject )
716 {
717 const sal_Int32 nParaCount = pOwner->pEditEngine->GetParagraphCount();
718
719 for( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
720 pOwner->ImplSetLevelDependentStyleSheet( nPara );
721 }
722
723 pEditView->SetEditEngineUpdateLayout( bPrevUpdateLayout );
724 pOwner->UndoActionEnd();
725 pEditView->ShowCursor();
726
727 // Chaining handling
728 // NOTE: We need to do this last because it pEditView may be deleted if a switch of box occurs
729 aEndCutPasteLink.Call(nullptr);
730 }
731
CreateSelectionList(std::vector<Paragraph * > & aSelList)732 void OutlinerView::CreateSelectionList (std::vector<Paragraph*> &aSelList)
733 {
734 ParaRange aParas = ImpGetSelectedParagraphs( true );
735
736 for ( sal_Int32 nPara = aParas.nStartPara; nPara <= aParas.nEndPara; nPara++ )
737 {
738 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
739 aSelList.push_back(pPara);
740 }
741 }
742
SetStyleSheet(const OUString & rStyleName)743 void OutlinerView::SetStyleSheet(const OUString& rStyleName)
744 {
745 ParaRange aParas = ImpGetSelectedParagraphs(false);
746
747 auto pStyle = pOwner->GetStyleSheetPool()->Find(rStyleName, SfxStyleFamily::Para);
748 if (!pStyle)
749 return;
750
751 for (sal_Int32 nPara = aParas.nStartPara; nPara <= aParas.nEndPara; nPara++)
752 pOwner->SetStyleSheet(nPara, static_cast<SfxStyleSheet*>(pStyle));
753 }
754
GetStyleSheet() const755 const SfxStyleSheet* OutlinerView::GetStyleSheet() const
756 {
757 return pEditView->GetStyleSheet();
758 }
759
GetStyleSheet()760 SfxStyleSheet* OutlinerView::GetStyleSheet()
761 {
762 return pEditView->GetStyleSheet();
763 }
764
GetPointer(const Point & rPosPixel)765 PointerStyle OutlinerView::GetPointer( const Point& rPosPixel )
766 {
767 MouseTarget eTarget;
768 ImpCheckMousePos( rPosPixel, eTarget );
769
770 PointerStyle ePointerStyle = PointerStyle::Arrow;
771 if ( eTarget == MouseTarget::Text )
772 {
773 ePointerStyle = GetOutliner()->IsVertical() ? PointerStyle::TextVertical : PointerStyle::Text;
774 }
775 else if ( eTarget == MouseTarget::Hypertext )
776 {
777 ePointerStyle = PointerStyle::RefHand;
778 }
779 else if ( eTarget == MouseTarget::Bullet )
780 {
781 ePointerStyle = PointerStyle::Move;
782 }
783
784 return ePointerStyle;
785 }
786
787
ImpInitPaste(sal_Int32 & rStart)788 sal_Int32 OutlinerView::ImpInitPaste( sal_Int32& rStart )
789 {
790 pOwner->bPasting = true;
791 ESelection aSelection( pEditView->GetSelection() );
792 aSelection.Adjust();
793 rStart = aSelection.nStartPara;
794 sal_Int32 nSize = aSelection.nEndPara - aSelection.nStartPara + 1;
795 return nSize;
796 }
797
798
ImpPasted(sal_Int32 nStart,sal_Int32 nPrevParaCount,sal_Int32 nSize)799 void OutlinerView::ImpPasted( sal_Int32 nStart, sal_Int32 nPrevParaCount, sal_Int32 nSize)
800 {
801 pOwner->bPasting = false;
802 sal_Int32 nCurParaCount = pOwner->pEditEngine->GetParagraphCount();
803 if( nCurParaCount < nPrevParaCount )
804 nSize = nSize - ( nPrevParaCount - nCurParaCount );
805 else
806 nSize = nSize + ( nCurParaCount - nPrevParaCount );
807 pOwner->ImpTextPasted( nStart, nSize );
808 }
809
Command(const CommandEvent & rCEvt)810 bool OutlinerView::Command(const CommandEvent& rCEvt)
811 {
812 return pEditView->Command(rCEvt);
813 }
814
SelectRange(sal_Int32 nFirst,sal_Int32 nCount)815 void OutlinerView::SelectRange( sal_Int32 nFirst, sal_Int32 nCount )
816 {
817 sal_Int32 nLast = nFirst+nCount;
818 nCount = pOwner->pParaList->GetParagraphCount();
819 if( nLast <= nCount )
820 nLast = nCount - 1;
821 ESelection aSel( nFirst, 0, nLast, EE_TEXTPOS_ALL );
822 pEditView->SetSelection( aSel );
823 }
824
825
ImpCalcSelectedPages(bool bIncludeFirstSelected)826 sal_Int32 OutlinerView::ImpCalcSelectedPages( bool bIncludeFirstSelected )
827 {
828 ESelection aSel( pEditView->GetSelection() );
829 aSel.Adjust();
830
831 sal_Int32 nPages = 0;
832 sal_Int32 nFirstPage = EE_PARA_MAX_COUNT;
833 sal_Int32 nStartPara = aSel.nStartPara;
834 if ( !bIncludeFirstSelected )
835 nStartPara++; // All paragraphs after StartPara will be deleted
836 for ( sal_Int32 nPara = nStartPara; nPara <= aSel.nEndPara; nPara++ )
837 {
838 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
839 assert(pPara && "ImpCalcSelectedPages: invalid Selection?");
840 if( pPara->HasFlag(ParaFlag::ISPAGE) )
841 {
842 nPages++;
843 if( nFirstPage == EE_PARA_MAX_COUNT )
844 nFirstPage = nPara;
845 }
846 }
847
848 if( nPages )
849 {
850 pOwner->nDepthChangedHdlPrevDepth = nPages;
851 pOwner->mnFirstSelPage = nFirstPage;
852 }
853
854 return nPages;
855 }
856
857
ToggleBullets()858 void OutlinerView::ToggleBullets()
859 {
860 pOwner->UndoActionStart( OLUNDO_DEPTH );
861
862 ESelection aSel( pEditView->GetSelection() );
863 aSel.Adjust();
864
865 const bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false );
866
867 sal_Int16 nNewDepth = -2;
868 const SvxNumRule* pDefaultBulletNumRule = nullptr;
869
870 for ( sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ )
871 {
872 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
873 DBG_ASSERT(pPara, "OutlinerView::ToggleBullets(), illegal selection?");
874
875 if( pPara )
876 {
877 if( nNewDepth == -2 )
878 {
879 nNewDepth = (pOwner->GetDepth(nPara) == -1) ? 0 : -1;
880 if ( nNewDepth == 0 )
881 {
882 // determine default numbering rule for bullets
883 const ESelection aSelection(nPara, 0);
884 const SfxItemSet aTmpSet(pOwner->pEditEngine->GetAttribs(aSelection));
885 const SfxPoolItem& rPoolItem = aTmpSet.GetPool()->GetUserOrPoolDefaultItem( EE_PARA_NUMBULLET );
886 const SvxNumBulletItem* pNumBulletItem = dynamic_cast< const SvxNumBulletItem* >(&rPoolItem);
887 pDefaultBulletNumRule = pNumBulletItem ? &pNumBulletItem->GetNumRule() : nullptr;
888 }
889 }
890
891 pOwner->SetDepth( pPara, nNewDepth );
892
893 if( nNewDepth == -1 )
894 {
895 const SfxItemSet& rAttrs = pOwner->GetParaAttribs( nPara );
896 if ( rAttrs.GetItemState( EE_PARA_BULLETSTATE ) == SfxItemState::SET )
897 {
898 SfxItemSet aAttrs(rAttrs);
899 aAttrs.ClearItem( EE_PARA_BULLETSTATE );
900 pOwner->SetParaAttribs( nPara, aAttrs );
901 }
902 }
903 else
904 {
905 if ( pDefaultBulletNumRule )
906 {
907 const SvxNumberFormat* pFmt = pOwner ->GetNumberFormat( nPara );
908 if ( !pFmt
909 || ( pFmt->GetNumberingType() != SVX_NUM_BITMAP
910 && pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) )
911 {
912 SfxItemSet aAttrs( pOwner->GetParaAttribs( nPara ) );
913 SvxNumRule aNewNumRule( *pDefaultBulletNumRule );
914 aAttrs.Put( SvxNumBulletItem( std::move(aNewNumRule), EE_PARA_NUMBULLET ) );
915 pOwner->SetParaAttribs( nPara, aAttrs );
916 }
917 }
918 }
919 }
920 }
921
922 const sal_Int32 nParaCount = pOwner->pParaList->GetParagraphCount();
923 pOwner->ImplCheckParagraphs( aSel.nStartPara, nParaCount );
924
925 sal_Int32 nEndPara = (nParaCount > 0) ? nParaCount-1 : nParaCount;
926 pOwner->pEditEngine->QuickMarkInvalid( ESelection( aSel.nStartPara, 0, nEndPara, 0 ) );
927
928 pOwner->pEditEngine->SetUpdateLayout( bUpdate );
929
930 pOwner->UndoActionEnd();
931 }
932
933
ToggleBulletsNumbering(const bool bToggle,const bool bHandleBullets,const SvxNumRule * pNumRule)934 void OutlinerView::ToggleBulletsNumbering(
935 const bool bToggle,
936 const bool bHandleBullets,
937 const SvxNumRule* pNumRule )
938 {
939 ESelection aSel( pEditView->GetSelection() );
940 aSel.Adjust();
941
942 bool bToggleOn = true;
943 if ( bToggle )
944 {
945 bToggleOn = false;
946 const sal_Int16 nBulletNumberingStatus( pOwner->GetBulletsNumberingStatus( aSel.nStartPara, aSel.nEndPara ) );
947 if ( nBulletNumberingStatus != 0 && bHandleBullets )
948 {
949 // not all paragraphs have bullets and method called to toggle bullets --> bullets on
950 bToggleOn = true;
951 }
952 else if ( nBulletNumberingStatus != 1 && !bHandleBullets )
953 {
954 // not all paragraphs have numbering and method called to toggle numberings --> numberings on
955 bToggleOn = true;
956 }
957 }
958 if ( bToggleOn )
959 {
960 // apply bullets/numbering for selected paragraphs
961 ApplyBulletsNumbering( bHandleBullets, pNumRule, bToggle, true );
962 }
963 else
964 {
965 // switch off bullets/numbering for selected paragraphs
966 SwitchOffBulletsNumbering( true );
967 }
968 }
969
EnsureNumberingIsOn()970 void OutlinerView::EnsureNumberingIsOn()
971 {
972 pOwner->UndoActionStart(OLUNDO_DEPTH);
973
974 ESelection aSel(pEditView->GetSelection());
975 aSel.Adjust();
976
977 const bool bUpdate = pOwner->pEditEngine->IsUpdateLayout();
978 pOwner->pEditEngine->SetUpdateLayout(false);
979
980 for (sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++)
981 {
982 Paragraph* pPara = pOwner->pParaList->GetParagraph(nPara);
983 DBG_ASSERT(pPara, "OutlinerView::EnableBullets(), illegal selection?");
984
985 if (pPara && pOwner->GetDepth(nPara) == -1)
986 pOwner->SetDepth(pPara, 0);
987 }
988
989 sal_Int32 nParaCount = pOwner->pParaList->GetParagraphCount();
990 pOwner->ImplCheckParagraphs(aSel.nStartPara, nParaCount);
991
992 const sal_Int32 nEndPara = (nParaCount > 0) ? nParaCount-1 : nParaCount;
993 pOwner->pEditEngine->QuickMarkInvalid(ESelection(aSel.nStartPara, 0, nEndPara, 0));
994
995 pOwner->pEditEngine->SetUpdateLayout(bUpdate);
996
997 pOwner->UndoActionEnd();
998 }
999
ApplyBulletsNumbering(const bool bHandleBullets,const SvxNumRule * pNewNumRule,const bool bCheckCurrentNumRuleBeforeApplyingNewNumRule,const bool bAtSelection)1000 void OutlinerView::ApplyBulletsNumbering(
1001 const bool bHandleBullets,
1002 const SvxNumRule* pNewNumRule,
1003 const bool bCheckCurrentNumRuleBeforeApplyingNewNumRule,
1004 const bool bAtSelection )
1005 {
1006 if (!pOwner || !pOwner->pEditEngine || !pOwner->pParaList)
1007 {
1008 return;
1009 }
1010
1011 pOwner->UndoActionStart(OLUNDO_DEPTH);
1012 const bool bUpdate = pOwner->pEditEngine->SetUpdateLayout(false);
1013
1014 sal_Int32 nStartPara = 0;
1015 sal_Int32 nEndPara = 0;
1016 if ( bAtSelection )
1017 {
1018 ESelection aSel( pEditView->GetSelection() );
1019 aSel.Adjust();
1020 nStartPara = aSel.nStartPara;
1021 nEndPara = aSel.nEndPara;
1022 }
1023 else
1024 {
1025 nStartPara = 0;
1026 nEndPara = pOwner->pParaList->GetParagraphCount() - 1;
1027 }
1028
1029 for (sal_Int32 nPara = nStartPara; nPara <= nEndPara; ++nPara)
1030 {
1031 Paragraph* pPara = pOwner->pParaList->GetParagraph(nPara);
1032 DBG_ASSERT(pPara, "OutlinerView::ApplyBulletsNumbering(..), illegal selection?");
1033
1034 if (pPara)
1035 {
1036 const sal_Int16 nDepth = pOwner->GetDepth(nPara);
1037 if ( nDepth == -1 )
1038 {
1039 pOwner->SetDepth( pPara, 0 );
1040 }
1041
1042 const SfxItemSet& rAttrs = pOwner->GetParaAttribs(nPara);
1043 SfxItemSet aAttrs(rAttrs);
1044 aAttrs.Put(SfxBoolItem(EE_PARA_BULLETSTATE, true));
1045
1046 // apply new numbering rule
1047 if ( pNewNumRule )
1048 {
1049 bool bApplyNumRule = false;
1050 if ( !bCheckCurrentNumRuleBeforeApplyingNewNumRule )
1051 {
1052 bApplyNumRule = true;
1053 }
1054 else
1055 {
1056 const SvxNumberFormat* pFmt = pOwner ->GetNumberFormat(nPara);
1057 if (!pFmt)
1058 {
1059 bApplyNumRule = true;
1060 }
1061 else
1062 {
1063 sal_Int16 nNumType = pFmt->GetNumberingType();
1064 if ( bHandleBullets
1065 && nNumType != SVX_NUM_BITMAP && nNumType != SVX_NUM_CHAR_SPECIAL)
1066 {
1067 // Set to Normal bullet, old bullet type is Numbering bullet.
1068 bApplyNumRule = true;
1069 }
1070 else if ( !bHandleBullets
1071 && (nNumType == SVX_NUM_BITMAP || nNumType == SVX_NUM_CHAR_SPECIAL))
1072 {
1073 // Set to Numbering bullet, old bullet type is Normal bullet.
1074 bApplyNumRule = true;
1075 }
1076 }
1077 }
1078
1079 if ( bApplyNumRule )
1080 {
1081 SvxNumRule aNewRule(*pNewNumRule);
1082
1083 // Get old bullet space.
1084 {
1085 const SvxNumBulletItem* pNumBulletItem = rAttrs.GetItemIfSet(EE_PARA_NUMBULLET, false);
1086 if (pNumBulletItem)
1087 {
1088 // Use default value when has not contain bullet item.
1089 ESelection aSelection(nPara, 0);
1090 SfxItemSet aTmpSet(pOwner->pEditEngine->GetAttribs(aSelection));
1091 pNumBulletItem = aTmpSet.GetItem(EE_PARA_NUMBULLET);
1092 }
1093
1094 if (pNumBulletItem)
1095 {
1096 const sal_uInt16 nLevelCnt = std::min(pNumBulletItem->GetNumRule().GetLevelCount(), aNewRule.GetLevelCount());
1097 for ( sal_uInt16 nLevel = 0; nLevel < nLevelCnt; ++nLevel )
1098 {
1099 const SvxNumberFormat* pOldFmt = pNumBulletItem->GetNumRule().Get(nLevel);
1100 const SvxNumberFormat* pNewFmt = aNewRule.Get(nLevel);
1101 if (pOldFmt && pNewFmt && (pOldFmt->GetFirstLineOffset() != pNewFmt->GetFirstLineOffset() || pOldFmt->GetAbsLSpace() != pNewFmt->GetAbsLSpace()))
1102 {
1103 SvxNumberFormat aNewFmtClone(*pNewFmt);
1104 aNewFmtClone.SetFirstLineOffset(pOldFmt->GetFirstLineOffset());
1105 aNewFmtClone.SetAbsLSpace(pOldFmt->GetAbsLSpace());
1106 aNewRule.SetLevel(nLevel, &aNewFmtClone);
1107 }
1108 }
1109 }
1110 }
1111
1112 aAttrs.Put(SvxNumBulletItem(std::move(aNewRule), EE_PARA_NUMBULLET));
1113 }
1114 }
1115 pOwner->SetParaAttribs(nPara, aAttrs);
1116 }
1117 }
1118
1119 const sal_uInt16 nParaCount = static_cast<sal_uInt16>(pOwner->pParaList->GetParagraphCount());
1120 pOwner->ImplCheckParagraphs( nStartPara, nParaCount );
1121 pOwner->pEditEngine->QuickMarkInvalid( ESelection( nStartPara, 0, nParaCount, 0 ) );
1122
1123 pOwner->pEditEngine->SetUpdateLayout( bUpdate );
1124
1125 pOwner->UndoActionEnd();
1126 }
1127
1128
SwitchOffBulletsNumbering(const bool bAtSelection)1129 void OutlinerView::SwitchOffBulletsNumbering(
1130 const bool bAtSelection )
1131 {
1132 sal_Int32 nStartPara = 0;
1133 sal_Int32 nEndPara = 0;
1134 if ( bAtSelection )
1135 {
1136 ESelection aSel( pEditView->GetSelection() );
1137 aSel.Adjust();
1138 nStartPara = aSel.nStartPara;
1139 nEndPara = aSel.nEndPara;
1140 }
1141 else
1142 {
1143 nStartPara = 0;
1144 nEndPara = pOwner->pParaList->GetParagraphCount() - 1;
1145 }
1146
1147 pOwner->UndoActionStart( OLUNDO_DEPTH );
1148 const bool bUpdate = pOwner->pEditEngine->SetUpdateLayout( false );
1149
1150 for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; ++nPara )
1151 {
1152 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
1153 DBG_ASSERT(pPara, "OutlinerView::SwitchOffBulletsNumbering(...), illegal paragraph index?");
1154
1155 if( pPara )
1156 {
1157 pOwner->SetDepth( pPara, -1 );
1158
1159 const SfxItemSet& rAttrs = pOwner->GetParaAttribs( nPara );
1160 if (rAttrs.GetItemState( EE_PARA_BULLETSTATE ) == SfxItemState::SET)
1161 {
1162 SfxItemSet aAttrs(rAttrs);
1163 aAttrs.ClearItem( EE_PARA_BULLETSTATE );
1164 pOwner->SetParaAttribs( nPara, aAttrs );
1165 }
1166 }
1167 }
1168
1169 const sal_uInt16 nParaCount = static_cast<sal_uInt16>(pOwner->pParaList->GetParagraphCount());
1170 pOwner->ImplCheckParagraphs( nStartPara, nParaCount );
1171 pOwner->pEditEngine->QuickMarkInvalid( ESelection( nStartPara, 0, nParaCount, 0 ) );
1172
1173 pOwner->pEditEngine->SetUpdateLayout( bUpdate );
1174 pOwner->UndoActionEnd();
1175 }
1176
1177
RemoveAttribsKeepLanguages(bool bRemoveParaAttribs)1178 void OutlinerView::RemoveAttribsKeepLanguages( bool bRemoveParaAttribs )
1179 {
1180 RemoveAttribs( bRemoveParaAttribs, true /*keep language attribs*/ );
1181 }
1182
RemoveAttribs(bool bRemoveParaAttribs,bool bKeepLanguages)1183 void OutlinerView::RemoveAttribs( bool bRemoveParaAttribs, bool bKeepLanguages )
1184 {
1185 bool bUpdate = pOwner->SetUpdateLayout( false );
1186 pOwner->UndoActionStart( OLUNDO_ATTR );
1187 if (bKeepLanguages)
1188 pEditView->RemoveAttribsKeepLanguages( bRemoveParaAttribs );
1189 else
1190 pEditView->RemoveAttribs( bRemoveParaAttribs );
1191 if ( bRemoveParaAttribs )
1192 {
1193 // Loop through all paragraphs and set indentation and level
1194 ESelection aSel = pEditView->GetSelection();
1195 aSel.Adjust();
1196 for ( sal_Int32 nPara = aSel.nStartPara; nPara <= aSel.nEndPara; nPara++ )
1197 {
1198 Paragraph* pPara = pOwner->pParaList->GetParagraph( nPara );
1199 pOwner->ImplInitDepth( nPara, pPara->GetDepth(), false );
1200 }
1201 }
1202 pOwner->UndoActionEnd();
1203 pOwner->SetUpdateLayout( bUpdate );
1204 }
1205
1206
1207 // ====================== Simple pass-through =======================
1208
1209
InsertText(const OUString & rNew,bool bSelect)1210 void OutlinerView::InsertText( const OUString& rNew, bool bSelect )
1211 {
1212 if( pOwner->bFirstParaIsEmpty )
1213 pOwner->Insert( OUString() );
1214 pEditView->InsertText( rNew, bSelect );
1215 }
1216
SetVisArea(const tools::Rectangle & rRect)1217 void OutlinerView::SetVisArea( const tools::Rectangle& rRect )
1218 {
1219 pEditView->SetVisArea( rRect );
1220 }
1221
1222
SetSelection(const ESelection & rSel)1223 void OutlinerView::SetSelection( const ESelection& rSel )
1224 {
1225 pEditView->SetSelection( rSel );
1226 }
1227
GetSelectionRectangles(std::vector<tools::Rectangle> & rLogicRects) const1228 void OutlinerView::GetSelectionRectangles(std::vector<tools::Rectangle>& rLogicRects) const
1229 {
1230 pEditView->GetSelectionRectangles(rLogicRects);
1231 }
1232
SetReadOnly(bool bReadOnly)1233 void OutlinerView::SetReadOnly( bool bReadOnly )
1234 {
1235 pEditView->SetReadOnly( bReadOnly );
1236 }
1237
IsReadOnly() const1238 bool OutlinerView::IsReadOnly() const
1239 {
1240 return pEditView->IsReadOnly();
1241 }
1242
HasSelection() const1243 bool OutlinerView::HasSelection() const
1244 {
1245 return pEditView->HasSelection();
1246 }
1247
ShowCursor(bool bGotoCursor,bool bActivate)1248 void OutlinerView::ShowCursor( bool bGotoCursor, bool bActivate )
1249 {
1250 pEditView->ShowCursor( bGotoCursor, /*bForceVisCursor=*/true, bActivate );
1251 }
1252
HideCursor(bool bDeactivate)1253 void OutlinerView::HideCursor(bool bDeactivate)
1254 {
1255 pEditView->HideCursor(bDeactivate);
1256 }
1257
SetWindow(vcl::Window * pWin)1258 void OutlinerView::SetWindow( vcl::Window* pWin )
1259 {
1260 pEditView->SetWindow( pWin );
1261 }
1262
GetWindow() const1263 vcl::Window* OutlinerView::GetWindow() const
1264 {
1265 return pEditView->GetWindow();
1266 }
1267
SetOutputArea(const tools::Rectangle & rRect)1268 void OutlinerView::SetOutputArea( const tools::Rectangle& rRect )
1269 {
1270 pEditView->SetOutputArea( rRect );
1271 }
1272
GetOutputArea() const1273 tools::Rectangle const & OutlinerView::GetOutputArea() const
1274 {
1275 return pEditView->GetOutputArea();
1276 }
1277
GetSelected() const1278 OUString OutlinerView::GetSelected() const
1279 {
1280 return pEditView->GetSelected();
1281 }
1282
StartSpeller(weld::Widget * pDialogParent)1283 void OutlinerView::StartSpeller(weld::Widget* pDialogParent)
1284 {
1285 pEditView->StartSpeller(pDialogParent);
1286 }
1287
StartThesaurus(weld::Widget * pDialogParent)1288 EESpellState OutlinerView::StartThesaurus(weld::Widget* pDialogParent)
1289 {
1290 return pEditView->StartThesaurus(pDialogParent);
1291 }
1292
StartTextConversion(weld::Widget * pDialogParent,LanguageType nSrcLang,LanguageType nDestLang,const vcl::Font * pDestFont,sal_Int32 nOptions,bool bIsInteractive,bool bMultipleDoc)1293 void OutlinerView::StartTextConversion(weld::Widget* pDialogParent,
1294 LanguageType nSrcLang, LanguageType nDestLang, const vcl::Font *pDestFont,
1295 sal_Int32 nOptions, bool bIsInteractive, bool bMultipleDoc )
1296 {
1297 if (
1298 (LANGUAGE_KOREAN == nSrcLang && LANGUAGE_KOREAN == nDestLang) ||
1299 (LANGUAGE_CHINESE_SIMPLIFIED == nSrcLang && LANGUAGE_CHINESE_TRADITIONAL == nDestLang) ||
1300 (LANGUAGE_CHINESE_TRADITIONAL == nSrcLang && LANGUAGE_CHINESE_SIMPLIFIED == nDestLang)
1301 )
1302 {
1303 pEditView->StartTextConversion(pDialogParent, nSrcLang, nDestLang, pDestFont, nOptions, bIsInteractive, bMultipleDoc);
1304 }
1305 else
1306 {
1307 OSL_FAIL( "unexpected language" );
1308 }
1309 }
1310
1311
StartSearchAndReplace(const SvxSearchItem & rSearchItem)1312 sal_Int32 OutlinerView::StartSearchAndReplace( const SvxSearchItem& rSearchItem )
1313 {
1314 return pEditView->StartSearchAndReplace( rSearchItem );
1315 }
1316
TransliterateText(TransliterationFlags nTransliterationMode)1317 void OutlinerView::TransliterateText( TransliterationFlags nTransliterationMode )
1318 {
1319 pEditView->TransliterateText( nTransliterationMode );
1320 }
1321
GetSelection() const1322 ESelection OutlinerView::GetSelection() const
1323 {
1324 return pEditView->GetSelection();
1325 }
1326
1327
Scroll(tools::Long nHorzScroll,tools::Long nVertScroll)1328 void OutlinerView::Scroll( tools::Long nHorzScroll, tools::Long nVertScroll )
1329 {
1330 pEditView->Scroll( nHorzScroll, nVertScroll );
1331 }
1332
SetControlWord(EVControlBits nWord)1333 void OutlinerView::SetControlWord( EVControlBits nWord )
1334 {
1335 pEditView->SetControlWord( nWord );
1336 }
1337
GetControlWord() const1338 EVControlBits OutlinerView::GetControlWord() const
1339 {
1340 return pEditView->GetControlWord();
1341 }
1342
SetAnchorMode(EEAnchorMode eMode)1343 void OutlinerView::SetAnchorMode( EEAnchorMode eMode )
1344 {
1345 pEditView->SetAnchorMode( eMode );
1346 }
1347
GetAnchorMode() const1348 EEAnchorMode OutlinerView::GetAnchorMode() const
1349 {
1350 return pEditView->GetAnchorMode();
1351 }
1352
Copy()1353 void OutlinerView::Copy()
1354 {
1355 pEditView->Copy();
1356 }
1357
InsertField(const SvxFieldItem & rFld)1358 void OutlinerView::InsertField( const SvxFieldItem& rFld )
1359 {
1360 pEditView->InsertField( rFld );
1361 }
1362
GetFieldUnderMousePointer() const1363 const SvxFieldItem* OutlinerView::GetFieldUnderMousePointer() const
1364 {
1365 return pEditView->GetFieldUnderMousePointer();
1366 }
1367
GetFieldAtSelection(bool bAlsoCheckBeforeCursor) const1368 const SvxFieldItem* OutlinerView::GetFieldAtSelection(bool bAlsoCheckBeforeCursor) const
1369 {
1370 return pEditView->GetFieldAtSelection(bAlsoCheckBeforeCursor);
1371 }
1372
SelectFieldAtCursor()1373 void OutlinerView::SelectFieldAtCursor()
1374 {
1375 pEditView->SelectFieldAtCursor();
1376 }
1377
SetInvalidateMore(sal_uInt16 nPixel)1378 void OutlinerView::SetInvalidateMore( sal_uInt16 nPixel )
1379 {
1380 pEditView->SetInvalidateMore( nPixel );
1381 }
1382
1383
GetInvalidateMore() const1384 sal_uInt16 OutlinerView::GetInvalidateMore() const
1385 {
1386 return pEditView->GetInvalidateMore();
1387 }
1388
1389
IsCursorAtWrongSpelledWord()1390 bool OutlinerView::IsCursorAtWrongSpelledWord()
1391 {
1392 return pEditView->IsCursorAtWrongSpelledWord();
1393 }
1394
1395
IsWrongSpelledWordAtPos(const Point & rPosPixel)1396 bool OutlinerView::IsWrongSpelledWordAtPos( const Point& rPosPixel )
1397 {
1398 return pEditView->IsWrongSpelledWordAtPos( rPosPixel, /*bMarkIfWrong*/false );
1399 }
1400
ExecuteSpellPopup(const Point & rPosPixel,const Link<SpellCallbackInfo &,void> & rStartDlg)1401 void OutlinerView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbackInfo&,void>& rStartDlg)
1402 {
1403 pEditView->ExecuteSpellPopup(rPosPixel, rStartDlg);
1404 }
1405
Read(SvStream & rInput,EETextFormat eFormat,SvKeyValueIterator * pHTTPHeaderAttrs)1406 void OutlinerView::Read( SvStream& rInput, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs )
1407 {
1408 sal_Int32 nOldParaCount = pEditView->getEditEngine().GetParagraphCount();
1409 ESelection aOldSel = pEditView->GetSelection();
1410 aOldSel.Adjust();
1411
1412 pEditView->Read( rInput, eFormat, pHTTPHeaderAttrs );
1413
1414 tools::Long nParaDiff = pEditView->getEditEngine().GetParagraphCount() - nOldParaCount;
1415 sal_Int32 nChangesStart = aOldSel.nStartPara;
1416 sal_Int32 nChangesEnd = nChangesStart + nParaDiff + (aOldSel.nEndPara-aOldSel.nStartPara);
1417
1418 for ( sal_Int32 n = nChangesStart; n <= nChangesEnd; n++ )
1419 {
1420 if ( pOwner->GetOutlinerMode() == OutlinerMode::OutlineObject )
1421 pOwner->ImplSetLevelDependentStyleSheet( n );
1422 }
1423
1424 pOwner->ImpFilterIndents( nChangesStart, nChangesEnd );
1425 }
1426
SetBackgroundColor(const Color & rColor)1427 void OutlinerView::SetBackgroundColor( const Color& rColor )
1428 {
1429 pEditView->SetBackgroundColor( rColor );
1430 }
1431
RegisterViewShell(OutlinerViewShell * pViewShell)1432 void OutlinerView::RegisterViewShell(OutlinerViewShell* pViewShell)
1433 {
1434 pEditView->RegisterViewShell(pViewShell);
1435 }
1436
GetBackgroundColor() const1437 Color const & OutlinerView::GetBackgroundColor() const
1438 {
1439 return pEditView->GetBackgroundColor();
1440 }
1441
GetAttribs()1442 SfxItemSet OutlinerView::GetAttribs()
1443 {
1444 return pEditView->GetAttribs();
1445 }
1446
GetSelectedScriptType() const1447 SvtScriptType OutlinerView::GetSelectedScriptType() const
1448 {
1449 return pEditView->GetSelectedScriptType();
1450 }
1451
GetSurroundingText() const1452 OUString OutlinerView::GetSurroundingText() const
1453 {
1454 return pEditView->GetSurroundingText();
1455 }
1456
GetSurroundingTextSelection() const1457 Selection OutlinerView::GetSurroundingTextSelection() const
1458 {
1459 return pEditView->GetSurroundingTextSelection();
1460 }
1461
DeleteSurroundingText(const Selection & rSelection)1462 bool OutlinerView::DeleteSurroundingText(const Selection& rSelection)
1463 {
1464 return pEditView->DeleteSurroundingText(rSelection);
1465 }
1466
1467 // ===== some code for thesaurus sub menu within context menu
1468
1469 namespace {
1470
isSingleScriptType(SvtScriptType nScriptType)1471 bool isSingleScriptType( SvtScriptType nScriptType )
1472 {
1473 sal_uInt8 nScriptCount = 0;
1474
1475 if (nScriptType & SvtScriptType::LATIN)
1476 ++nScriptCount;
1477 if (nScriptType & SvtScriptType::ASIAN)
1478 ++nScriptCount;
1479 if (nScriptType & SvtScriptType::COMPLEX)
1480 ++nScriptCount;
1481
1482 return nScriptCount == 1;
1483 }
1484
1485 }
1486
1487 // returns: true if a word for thesaurus look-up was found at the current cursor position.
1488 // The status string will be word + iso language string (e.g. "light#en-US")
GetStatusValueForThesaurusFromContext(OUString & rStatusVal,LanguageType & rLang,const EditView & rEditView)1489 bool GetStatusValueForThesaurusFromContext(
1490 OUString &rStatusVal,
1491 LanguageType &rLang,
1492 const EditView &rEditView )
1493 {
1494 // get text and locale for thesaurus look up
1495 OUString aText;
1496 EditEngine& rEditEngine = rEditView.getEditEngine();
1497 ESelection aTextSel( rEditView.GetSelection() );
1498 if (!aTextSel.HasRange())
1499 aTextSel = rEditEngine.GetWord( aTextSel, i18n::WordType::DICTIONARY_WORD );
1500 aText = rEditEngine.GetText( aTextSel );
1501 aTextSel.Adjust();
1502
1503 if (!isSingleScriptType(rEditEngine.GetScriptType(aTextSel)))
1504 return false;
1505
1506 LanguageType nLang = rEditEngine.GetLanguage( aTextSel.nStartPara, aTextSel.nStartPos ).nLang;
1507 OUString aLangText( LanguageTag::convertToBcp47( nLang ) );
1508
1509 // set word and locale to look up as status value
1510 rStatusVal = aText + "#" + aLangText;
1511 rLang = nLang;
1512
1513 return aText.getLength() > 0;
1514 }
1515
1516
ReplaceTextWithSynonym(EditView & rEditView,const OUString & rSynonmText)1517 void ReplaceTextWithSynonym( EditView &rEditView, const OUString &rSynonmText )
1518 {
1519 // get selection to use
1520 ESelection aCurSel( rEditView.GetSelection() );
1521 if (!rEditView.HasSelection())
1522 {
1523 // select the same word that was used in GetStatusValueForThesaurusFromContext by calling GetWord.
1524 // (In the end both functions will call ImpEditEngine::SelectWord)
1525 rEditView.SelectCurrentWord( i18n::WordType::DICTIONARY_WORD );
1526 aCurSel = rEditView.GetSelection();
1527 }
1528
1529 // replace word ...
1530 rEditView.InsertText( rSynonmText );
1531 rEditView.ShowCursor( true, false );
1532 }
1533
1534
1535 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1536