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