bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / view / Outliner.cxx
blob8d88518c931f2f38f7a8cb1117df820d25090014
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "Outliner.hxx"
21 #include <vcl/wrkwin.hxx>
22 #include <vcl/settings.hxx>
24 #include <svl/srchitem.hxx>
25 #include <editeng/colritem.hxx>
26 #include <editeng/eeitem.hxx>
27 #include <editeng/editstat.hxx>
28 #include <vcl/outdev.hxx>
29 #include <svx/dlgutil.hxx>
30 #include <svx/xtable.hxx>
31 #include <vcl/layout.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <sfx2/printer.hxx>
35 #include <svx/svxerr.hxx>
36 #include <svx/svdotext.hxx>
37 #include <editeng/unolingu.hxx>
38 #include <svx/svditer.hxx>
39 #include <comphelper/extract.hxx>
40 #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <comphelper/processfactory.hxx>
43 #include <editeng/forbiddencharacterstable.hxx>
44 #include <svx/srchdlg.hxx>
45 #include <unotools/linguprops.hxx>
46 #include <unotools/lingucfg.hxx>
47 #include <editeng/editeng.hxx>
48 #include <vcl/metric.hxx>
49 #include <sfx2/viewfrm.hxx>
50 #include <svtools/langtab.hxx>
51 #include <tools/diagnose_ex.h>
53 #include "strings.hrc"
54 #include "sdstring.hrc"
55 #include <editeng/outliner.hxx>
56 #include "sdpage.hxx"
57 #include "sdmod.hxx"
58 #include "Window.hxx"
59 #include "sdresid.hxx"
60 #include "DrawViewShell.hxx"
61 #include "OutlineViewShell.hxx"
62 #include "drawdoc.hxx"
63 #include "DrawDocShell.hxx"
64 #include "FrameView.hxx"
65 #include "optsitem.hxx"
66 #include "drawview.hxx"
67 #include "ViewShellBase.hxx"
68 #include "SpellDialogChildWindow.hxx"
69 #include "ToolBarManager.hxx"
70 #include "framework/FrameworkHelper.hxx"
71 #include <svx/svxids.hrc>
72 #include <editeng/editerr.hxx>
73 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
75 using namespace ::com::sun::star;
76 using namespace ::com::sun::star::uno;
77 using namespace ::com::sun::star::lang;
78 using namespace ::com::sun::star::linguistic2;
80 class SfxStyleSheetPool;
82 namespace sd {
84 class Outliner::Implementation
86 public:
87 /** The original edit mode directly after switching to a different view
88 mode. Used for restoring the edit mode when leaving that view mode
89 again.
91 EditMode meOriginalEditMode;
93 Implementation();
94 ~Implementation();
96 /** Return the OutlinerView that was provided by the last call to
97 ProvideOutlinerView() (or NULL when there was no such call.)
99 OutlinerView* GetOutlinerView() { return mpOutlineView;}
101 /** Provide in the member mpOutlineView an instance of OutlinerView that
102 is either taken from the ViewShell, when it is an OutlineViewShell,
103 or is created. When an OutlinerView already exists it is initialied.
105 void ProvideOutlinerView (
106 Outliner& rOutliner,
107 const ::boost::shared_ptr<ViewShell>& rpViewShell,
108 vcl::Window* pWindow);
110 /** This method is called when the OutlinerView is no longer used.
112 void ReleaseOutlinerView();
114 private:
115 /** Flag that specifies whether we own the outline view pointed to by
116 <member>mpOutlineView</member> and thus have to
117 delete it in <member>EndSpelling()</member>.
119 bool mbOwnOutlineView;
121 /** The outline view used for searching and spelling. If searching or
122 spell checking an outline view this data member points to that view.
123 For all other views an instance is created. The
124 <member>mbOwnOutlineView</member> distinguishes between both cases.
126 OutlinerView* mpOutlineView;
129 Outliner::Outliner( SdDrawDocument* pDoc, sal_uInt16 nMode )
130 : SdrOutliner( &pDoc->GetItemPool(), nMode ),
131 mpImpl(new Implementation()),
132 meMode(SEARCH),
133 mpView(NULL),
134 mpWeakViewShell(),
135 mpWindow(NULL),
136 mpDrawDocument(pDoc),
137 mnConversionLanguage(LANGUAGE_NONE),
138 mnIgnoreCurrentPageChangesLevel(0),
139 mbStringFound(false),
140 mbMatchMayExist(false),
141 mnPageCount(0),
142 mnObjectCount(0),
143 mbEndOfSearch(false),
144 mbFoundObject(false),
145 mbError(false),
146 mbDirectionIsForward(true),
147 mbRestrictSearchToSelection(false),
148 maMarkListCopy(),
149 mbProcessCurrentViewOnly(false),
150 mpObj(NULL),
151 mpFirstObj(NULL),
152 mpTextObj(NULL),
153 mnText(0),
154 mpParaObj(NULL),
155 meStartViewMode(PK_STANDARD),
156 meStartEditMode(EM_PAGE),
157 mnStartPageIndex((sal_uInt16)-1),
158 mpStartEditedObject(NULL),
159 maStartSelection(),
160 mpSearchItem(NULL),
161 maObjectIterator(),
162 maCurrentPosition(),
163 maSearchStartPosition(),
164 maLastValidPosition(),
165 mbSelectionHasChanged(false),
166 mbExpectingSelectionChangeEvent(false),
167 mbWholeDocumentProcessed(false),
168 mbPrepareSpellingPending(true)
170 SetStyleSheetPool(static_cast<SfxStyleSheetPool*>( mpDrawDocument->GetStyleSheetPool() ));
171 SetEditTextObjectPool( &pDoc->GetItemPool() );
172 SetCalcFieldValueHdl(LINK(SD_MOD(), SdModule, CalcFieldValueHdl));
173 SetForbiddenCharsTable( pDoc->GetForbiddenCharsTable() );
175 EEControlBits nCntrl = GetControlWord();
176 nCntrl |= EEControlBits::ALLOWBIGOBJS;
177 nCntrl |= EEControlBits::MARKFIELDS;
178 nCntrl |= EEControlBits::AUTOCORRECT;
180 bool bOnlineSpell = false;
182 DrawDocShell* pDocSh = mpDrawDocument->GetDocSh();
184 if (pDocSh)
186 bOnlineSpell = mpDrawDocument->GetOnlineSpell();
188 else
190 bOnlineSpell = false;
194 const SvtLinguConfig aLinguConfig;
195 Any aAny;
197 aAny = aLinguConfig.GetProperty( UPN_IS_SPELL_AUTO );
198 aAny >>= bOnlineSpell;
200 catch( ... )
202 OSL_FAIL( "Ill. type in linguistic property" );
206 if (bOnlineSpell)
207 nCntrl |= EEControlBits::ONLINESPELLING;
208 else
209 nCntrl &= ~EEControlBits::ONLINESPELLING;
211 SetControlWord(nCntrl);
213 Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() );
214 if ( xSpellChecker.is() )
215 SetSpeller( xSpellChecker );
217 Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() );
218 if( xHyphenator.is() )
219 SetHyphenator( xHyphenator );
221 SetDefaultLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
224 /// Nothing spectecular in the destructor.
225 Outliner::~Outliner()
227 mpImpl.reset();
230 /** Prepare find&replace or spellchecking. This distinguishes between three
231 cases:
232 <ol>
233 <li>The current shell is a <type>DrawViewShell</type>: Create a
234 <type>OutlinerView</type> object and search all objects of (i) the
235 current mark list, (ii) of the current view, or (iii) of all the view
236 combinations:
237 <ol>
238 <li>Draw view, slide view</li>
239 <li>Draw view, background view</li>
240 <li>Notes view, slide view</li>
241 <li>Notes view, background view</li>
242 <li>Handout view, slide view</li>
243 <li>Handout view, background view</li>
244 </ol>
246 <li>When the current shell is a <type>SdOutlineViewShell</type> then
247 directly operate on it. No switching into other views takes place.</li>
248 </ol>
250 void Outliner::PrepareSpelling()
252 mbPrepareSpellingPending = false;
254 ViewShellBase* pBase = PTR_CAST(ViewShellBase,SfxViewShell::Current());
255 if (pBase != NULL)
256 SetViewShell (pBase->GetMainViewShell());
257 SetRefDevice( SD_MOD()->GetRefDevice( *mpDrawDocument->GetDocSh() ) );
259 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
260 if (pViewShell)
262 mbStringFound = false;
264 mbWholeDocumentProcessed = false;
265 // Supposed that we are not located at the very beginning/end of
266 // the document then there may be a match in the document
267 // prior/after the current position.
268 mbMatchMayExist = true;
270 maObjectIterator = ::sd::outliner::Iterator();
271 maSearchStartPosition = ::sd::outliner::Iterator();
272 RememberStartPosition();
274 mpImpl->ProvideOutlinerView(*this, pViewShell, mpWindow);
276 HandleChangedSelection ();
278 ClearModifyFlag();
281 void Outliner::StartSpelling()
283 meMode = SPELL;
284 mbDirectionIsForward = true;
285 mpSearchItem = NULL;
288 /** Proxy for method from base class to avoid compiler warning */
289 void Outliner::StartSpelling(EditView& rView, unsigned char c)
291 SdrOutliner::StartSpelling( rView, c );
294 /** Free all resources acquired during the search/spell check. After a
295 spell check the start position is restored here.
297 void Outliner::EndSpelling()
299 // Keep old view shell alive until we release the outliner view.
300 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
301 ::boost::shared_ptr<ViewShell> pOldViewShell (pViewShell);
303 ViewShellBase* pBase = PTR_CAST(ViewShellBase,SfxViewShell::Current());
304 if (pBase != NULL)
305 pViewShell = pBase->GetMainViewShell();
306 else
307 pViewShell.reset();
308 mpWeakViewShell = pViewShell;
310 // When in <member>PrepareSpelling()</member> a new outline view has
311 // been created then delete it here.
312 bool bViewIsDrawViewShell(pViewShell && pViewShell->ISA(DrawViewShell));
313 if (bViewIsDrawViewShell)
315 SetStatusEventHdl(Link<>());
316 mpView = pViewShell->GetView();
317 mpView->UnmarkAllObj (mpView->GetSdrPageView());
318 mpView->SdrEndTextEdit();
319 // Make FuSelection the current function.
320 pViewShell->GetDispatcher()->Execute(
321 SID_OBJECT_SELECT,
322 SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
324 // Remove and, if previously created by us, delete the outline
325 // view.
326 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
327 if (pOutlinerView != NULL)
329 RemoveView(pOutlinerView);
330 mpImpl->ReleaseOutlinerView();
333 SetUpdateMode(true);
336 // Before clearing the modify flag use it as a hint that
337 // changes were done at SpellCheck
338 if(IsModified())
340 if(mpView && mpView->ISA(OutlineView))
341 static_cast<OutlineView*>(mpView)->PrepareClose(false);
342 if(mpDrawDocument && !mpDrawDocument->IsChanged())
343 mpDrawDocument->SetChanged(true);
346 // Now clear the modify flag to have a specified state of
347 // Outliner
348 ClearModifyFlag();
350 // When spell checking then restore the start position.
351 if (meMode==SPELL || meMode==TEXT_CONVERSION)
352 RestoreStartPosition ();
354 mpWeakViewShell.reset();
355 mpView = NULL;
356 mpWindow = NULL;
357 mnStartPageIndex = (sal_uInt16) -1;
360 bool Outliner::SpellNextDocument()
362 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
363 if (pViewShell->ISA(OutlineViewShell))
365 // When doing a spell check in the outline view then there is
366 // only one document.
367 mbEndOfSearch = true;
368 EndOfSearch ();
370 else
372 if (mpView->ISA(OutlineView))
373 static_cast<OutlineView*>(mpView)->PrepareClose(false);
374 mpDrawDocument->GetDocSh()->SetWaitCursor( true );
376 Initialize (true);
378 mpWindow = pViewShell->GetActiveWindow();
379 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
380 if (pOutlinerView != NULL)
381 pOutlinerView->SetWindow(mpWindow);
382 ProvideNextTextObject ();
384 mpDrawDocument->GetDocSh()->SetWaitCursor( false );
385 ClearModifyFlag();
388 return !mbEndOfSearch;
392 * check next text object
394 svx::SpellPortions Outliner::GetNextSpellSentence()
396 svx::SpellPortions aResult;
398 DetectChange();
399 // Iterate over sentences and text shapes until a sentence with a
400 // spelling error has been found. If no such sentence can be
401 // found the loop is left through a break.
402 // It is the responsibility of the sd outliner object to correctly
403 // iterate over all text shapes, i.e. switch between views, wrap
404 // around at the end of the document, stop when all text shapes
405 // have been examined exactly once.
406 bool bFoundNextSentence = false;
407 while ( ! bFoundNextSentence)
409 OutlinerView* pOutlinerView = GetView(0);
410 if (pOutlinerView != NULL)
412 ESelection aCurrentSelection (pOutlinerView->GetSelection());
413 if ( ! mbMatchMayExist
414 && maStartSelection.IsLess(aCurrentSelection))
415 EndOfSearch();
417 // Advance to the next sentence.
418 bFoundNextSentence = SpellSentence (
419 pOutlinerView->GetEditView(),
420 aResult, false);
423 // When no sentence with spelling errors has been found in the
424 // currently selected text shape or there is no selected text
425 // shape then advance to the next text shape.
426 if ( ! bFoundNextSentence)
427 if ( ! SpellNextDocument())
428 // All text objects have been processed so exit the
429 // loop and return an empty portions list.
430 break;
433 return aResult;
436 /** Go to next match.
438 bool Outliner::StartSearchAndReplace (const SvxSearchItem* pSearchItem)
440 bool bEndOfSearch = true;
442 // clear the search toolbar entry
443 SvxSearchDialogWrapper::SetSearchLabel(SL_Empty);
445 mpDrawDocument->GetDocSh()->SetWaitCursor( true );
446 if (mbPrepareSpellingPending)
447 PrepareSpelling();
448 ViewShellBase* pBase = PTR_CAST(ViewShellBase,SfxViewShell::Current());
449 // Determine whether we have to abort the search. This is necessary
450 // when the main view shell does not support searching.
451 bool bAbort = false;
452 if (pBase != NULL)
454 ::boost::shared_ptr<ViewShell> pShell (pBase->GetMainViewShell());
455 SetViewShell(pShell);
456 if (pShell.get() == NULL)
457 bAbort = true;
458 else
459 switch (pShell->GetShellType())
461 case ViewShell::ST_DRAW:
462 case ViewShell::ST_IMPRESS:
463 case ViewShell::ST_NOTES:
464 case ViewShell::ST_HANDOUT:
465 case ViewShell::ST_OUTLINE:
466 bAbort = false;
467 break;
468 default:
469 bAbort = true;
470 break;
474 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
475 if ( ! pViewShell)
477 OSL_ASSERT(pViewShell);
478 return true;
481 if ( ! bAbort)
483 meMode = SEARCH;
484 mpSearchItem = pSearchItem;
486 mbFoundObject = false;
488 Initialize ( ! mpSearchItem->GetBackward());
490 const SvxSearchCmd nCommand (mpSearchItem->GetCommand());
491 if (nCommand == SvxSearchCmd::REPLACE_ALL)
492 bEndOfSearch = SearchAndReplaceAll ();
493 else
495 RememberStartPosition ();
496 bEndOfSearch = SearchAndReplaceOnce ();
497 // restore start position if nothing was found
498 if(!mbStringFound)
499 RestoreStartPosition ();
500 mnStartPageIndex = (sal_uInt16)-1;
503 SfxChildWindow *pChildWin =
504 SfxViewFrame::Current()->GetChildWindow(
505 SvxSearchDialogWrapper::GetChildWindowId());
506 if (pChildWin)
508 SvxSearchDialog* pSearchDlg =
509 static_cast<SvxSearchDialog*>(pChildWin->GetWindow());
510 pSearchDlg->SetDocWin( pViewShell->GetActiveWindow() );
511 pSearchDlg->SetSrchFlag();
514 else
515 mpDrawDocument->GetDocSh()->SetWaitCursor( false );
517 return bEndOfSearch;
520 void Outliner::Initialize (bool bDirectionIsForward)
522 const bool bIsAtEnd (maObjectIterator == ::sd::outliner::OutlinerContainer(this).end());
523 const bool bOldDirectionIsForward = mbDirectionIsForward;
524 mbDirectionIsForward = bDirectionIsForward;
526 if (maObjectIterator == ::sd::outliner::Iterator())
528 // Initialize a new search.
529 maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
530 maCurrentPosition = *maObjectIterator;
532 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
533 if ( ! pViewShell)
535 OSL_ASSERT(pViewShell);
536 return;
539 // In case we are searching in an outline view then first remove the
540 // current selection and place cursor at its start or end.
541 if (pViewShell->ISA(OutlineViewShell))
543 ESelection aSelection = mpImpl->GetOutlinerView()->GetSelection ();
544 if (mbDirectionIsForward)
546 aSelection.nEndPara = aSelection.nStartPara;
547 aSelection.nEndPos = aSelection.nStartPos;
549 else
551 aSelection.nStartPara = aSelection.nEndPara;
552 aSelection.nStartPos = aSelection.nEndPos;
554 mpImpl->GetOutlinerView()->SetSelection (aSelection);
557 // When not beginning the search at the beginning of the search area
558 // then there may be matches before the current position.
559 mbMatchMayExist = (maObjectIterator!=::sd::outliner::OutlinerContainer(this).begin());
561 else if (bOldDirectionIsForward != mbDirectionIsForward)
563 // Requested iteration direction has changed. Turn around the iterator.
564 maObjectIterator.Reverse();
565 if (bIsAtEnd)
567 // The iterator has pointed to end(), which after the search
568 // direction is reversed, becomes begin().
569 maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin();
571 else
573 // The iterator has pointed to the object one ahead/before the current
574 // one. Now move it to the one before/ahead the current one.
575 ++maObjectIterator;
576 ++maObjectIterator;
579 mbMatchMayExist = true;
582 // Initialize the last valid position with where the search starts so
583 // that it always points to a valid position.
584 maLastValidPosition = *::sd::outliner::OutlinerContainer(this).current();
587 bool Outliner::SearchAndReplaceAll()
589 // Save the current position to be restored after having replaced all
590 // matches.
591 RememberStartPosition ();
593 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
594 if ( ! pViewShell)
596 OSL_ASSERT(pViewShell);
597 return true;
600 if (pViewShell->ISA(OutlineViewShell))
602 // Put the cursor to the beginning/end of the outliner.
603 mpImpl->GetOutlinerView()->SetSelection (GetSearchStartPosition ());
605 // The outliner does all the work for us when we are in this mode.
606 SearchAndReplaceOnce();
608 else if (pViewShell->ISA(DrawViewShell))
610 // Go to beginning/end of document.
611 maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin();
612 // Switch to the current object only if it is a valid text object.
613 ::sd::outliner::IteratorPosition aNewPosition (*maObjectIterator);
614 if (IsValidTextObject (aNewPosition))
616 maCurrentPosition = aNewPosition;
617 SetObject (maCurrentPosition);
620 // Search/replace until the end of the document is reached.
621 bool bFoundMatch;
624 bFoundMatch = ! SearchAndReplaceOnce();
626 while (bFoundMatch);
629 RestoreStartPosition ();
630 mnStartPageIndex = (sal_uInt16)-1;
632 return true;
635 bool Outliner::SearchAndReplaceOnce()
637 DetectChange ();
639 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
640 DBG_ASSERT(pOutlinerView!=NULL && GetEditEngine().HasView( &pOutlinerView->GetEditView() ),
641 "SearchAndReplace without valid view!" );
643 if( NULL == pOutlinerView || !GetEditEngine().HasView( &pOutlinerView->GetEditView() ) )
644 return true;
646 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
647 if (pViewShell != 0)
649 mpView = pViewShell->GetView();
650 mpWindow = pViewShell->GetActiveWindow();
651 pOutlinerView->SetWindow(mpWindow);
653 if (pViewShell->ISA(DrawViewShell) )
655 // When replacing we first check if there is a selection
656 // indicating a match. If there is then replace it. The
657 // following call to StartSearchAndReplace will then search for
658 // the next match.
659 if (meMode == SEARCH
660 && mpSearchItem->GetCommand() == SvxSearchCmd::REPLACE)
661 if (pOutlinerView->GetSelection().HasRange())
662 pOutlinerView->StartSearchAndReplace(*mpSearchItem);
664 // Search for the next match.
665 sal_uLong nMatchCount = 0;
666 if (mpSearchItem->GetCommand() != SvxSearchCmd::REPLACE_ALL)
667 nMatchCount = pOutlinerView->StartSearchAndReplace(*mpSearchItem);
669 // Go to the next text object when there have been no matches in
670 // the current object or the whole object has already been
671 // processed.
672 if (nMatchCount==0 || mpSearchItem->GetCommand()==SvxSearchCmd::REPLACE_ALL)
674 ProvideNextTextObject ();
676 if ( ! mbEndOfSearch)
678 // Remember the current position as the last one with a
679 // text object.
680 maLastValidPosition = maCurrentPosition;
682 // Now that the mbEndOfSearch flag guards this block the
683 // following assertion and return should not be
684 // necessary anymore.
685 DBG_ASSERT(GetEditEngine().HasView(&pOutlinerView->GetEditView() ),
686 "SearchAndReplace without valid view!" );
687 if ( ! GetEditEngine().HasView( &pOutlinerView->GetEditView() ) )
689 mpDrawDocument->GetDocSh()->SetWaitCursor( false );
690 return true;
693 if (meMode == SEARCH)
694 nMatchCount = pOutlinerView->StartSearchAndReplace(*mpSearchItem);
698 else if (pViewShell->ISA(OutlineViewShell))
700 mpDrawDocument->GetDocSh()->SetWaitCursor(false);
701 // The following loop is executed more than once only when a
702 // wrap around search is done.
703 while (true)
705 int nResult = pOutlinerView->StartSearchAndReplace(*mpSearchItem);
706 if (nResult == 0)
708 if (HandleFailedSearch ())
710 pOutlinerView->SetSelection (GetSearchStartPosition ());
711 continue;
714 else
715 mbStringFound = true;
716 break;
721 mpDrawDocument->GetDocSh()->SetWaitCursor( false );
723 // notify LibreOfficeKit about changed page
724 if (pViewShell && pViewShell->GetDoc()->isTiledRendering() && mbStringFound)
726 OString aPayload = OString::number(maCurrentPosition.mnPageIndex);
727 pViewShell->GetDoc()->libreOfficeKitCallback(LOK_CALLBACK_SET_PART, aPayload.getStr());
730 return mbEndOfSearch;
733 /** Try to detect whether the document or the view (shell) has changed since
734 the last time <member>StartSearchAndReplace()</member> has been called.
736 void Outliner::DetectChange()
738 ::sd::outliner::IteratorPosition aPosition (maCurrentPosition);
740 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
741 ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
742 ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
744 // Detect whether the view has been switched from the outside.
745 if (pDrawViewShell.get() != NULL
746 && (aPosition.meEditMode != pDrawViewShell->GetEditMode()
747 || aPosition.mePageKind != pDrawViewShell->GetPageKind()))
749 // Either the edit mode or the page kind has changed.
750 SetStatusEventHdl(Link<>());
752 SdrPageView* pPageView = mpView->GetSdrPageView();
753 if (pPageView != NULL)
754 mpView->UnmarkAllObj (pPageView);
755 mpView->SdrEndTextEdit();
756 SetUpdateMode(false);
757 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
758 if (pOutlinerView != NULL)
759 pOutlinerView->SetOutputArea( Rectangle( Point(), Size(1, 1) ) );
760 if (meMode == SPELL)
761 SetPaperSize( Size(1, 1) );
762 SetText(OUString(), GetParagraph(0));
764 RememberStartPosition ();
766 mnPageCount = mpDrawDocument->GetSdPageCount(pDrawViewShell->GetPageKind());
767 maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
770 // Detect change of the set of selected objects. If their number has
771 // changed start again with the first selected object.
772 else if (DetectSelectionChange())
774 HandleChangedSelection ();
775 maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
778 // Detect change of page count. Restart search at first/last page in
779 // that case.
780 else if (aPosition.meEditMode == EM_PAGE
781 && mpDrawDocument->GetSdPageCount(aPosition.mePageKind) != mnPageCount)
783 // The number of pages has changed.
784 mnPageCount = mpDrawDocument->GetSdPageCount(aPosition.mePageKind);
785 maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
787 else if (aPosition.meEditMode == EM_MASTERPAGE
788 && mpDrawDocument->GetSdPageCount(aPosition.mePageKind) != mnPageCount)
790 // The number of master pages has changed.
791 mnPageCount = mpDrawDocument->GetSdPageCount(aPosition.mePageKind);
792 maObjectIterator = ::sd::outliner::OutlinerContainer(this).current();
796 bool Outliner::DetectSelectionChange()
798 bool bSelectionHasChanged = false;
800 // If mpObj is NULL then we have not yet found our first match.
801 // Detecting a change makes no sense.
802 if (mpObj != NULL)
804 const size_t nMarkCount = mpView ? mpView->GetMarkedObjectList().GetMarkCount() : 0;
805 switch (nMarkCount)
807 case 0:
808 // The selection has changed when previously there have been
809 // selected objects.
810 bSelectionHasChanged = mbRestrictSearchToSelection;
811 break;
812 case 1:
813 // Check if the only selected object is not the one that we
814 // had selected.
815 if (mpView != NULL)
817 SdrMark* pMark = mpView->GetMarkedObjectList().GetMark(0);
818 if (pMark != NULL)
819 bSelectionHasChanged = (mpObj != pMark->GetMarkedSdrObj ());
821 break;
822 default:
823 // We had selected exactly one object.
824 bSelectionHasChanged = true;
825 break;
829 return bSelectionHasChanged;
832 void Outliner::RememberStartPosition()
834 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
835 if ( ! pViewShell)
837 OSL_ASSERT(pViewShell);
838 return;
841 if ( mnStartPageIndex != (sal_uInt16) -1 )
842 return;
844 if (pViewShell->ISA(DrawViewShell))
846 ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
847 ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
848 if (pDrawViewShell.get() != NULL)
850 meStartViewMode = pDrawViewShell->GetPageKind();
851 meStartEditMode = pDrawViewShell->GetEditMode();
852 mnStartPageIndex = pDrawViewShell->GetCurPageId() - 1;
855 if (mpView != NULL)
857 mpStartEditedObject = mpView->GetTextEditObject();
858 if (mpStartEditedObject != NULL)
860 // Try to retrieve current caret position only when there is an
861 // edited object.
862 ::Outliner* pOutliner =
863 static_cast<DrawView*>(mpView)->GetTextEditOutliner();
864 if (pOutliner!=NULL && pOutliner->GetViewCount()>0)
866 OutlinerView* pOutlinerView = pOutliner->GetView(0);
867 maStartSelection = pOutlinerView->GetSelection();
872 else if (pViewShell->ISA(OutlineViewShell))
874 // Remember the current cursor position.
875 OutlinerView* pView = GetView(0);
876 if (pView != NULL)
877 pView->GetSelection();
879 else
881 mnStartPageIndex = (sal_uInt16)-1;
885 void Outliner::RestoreStartPosition()
887 bool bRestore = true;
888 // Take a negative start page index as inidicator that restoring the
889 // start position is not requested.
890 if (mnStartPageIndex == (sal_uInt16)-1 )
891 bRestore = false;
892 // Dont't restore when the view shell is not valid.
893 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
894 if (pViewShell == 0)
895 bRestore = false;
897 if (bRestore)
899 if (pViewShell->ISA(DrawViewShell))
901 ::boost::shared_ptr<DrawViewShell> pDrawViewShell (
902 ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
903 SetViewMode (meStartViewMode);
904 if (pDrawViewShell.get() != NULL)
905 SetPage (meStartEditMode, mnStartPageIndex);
907 else if (pViewShell->ISA(OutlineViewShell))
909 // Set cursor to its old position.
910 OutlinerView* pView = GetView(0);
911 if (pView != NULL)
912 pView->SetSelection (maStartSelection);
917 /** The main purpose of this method is to iterate over all shape objects of
918 the search area (current selection, current view, or whole document)
919 until a text object has been found that contains at least one match or
920 until no such object can be found anymore. These two conditions are
921 expressed by setting one of the flags <member>mbFoundObject</member> or
922 <member>mbEndOfSearch</member> to <TRUE/>.
924 void Outliner::ProvideNextTextObject()
926 mbEndOfSearch = false;
927 mbFoundObject = false;
929 mpView->UnmarkAllObj (mpView->GetSdrPageView());
932 mpView->SdrEndTextEdit();
934 catch (const ::com::sun::star::uno::Exception&)
936 DBG_UNHANDLED_EXCEPTION();
938 SetUpdateMode(false);
939 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
940 if (pOutlinerView != NULL)
941 pOutlinerView->SetOutputArea( Rectangle( Point(), Size(1, 1) ) );
942 if (meMode == SPELL)
943 SetPaperSize( Size(1, 1) );
944 SetText(OUString(), GetParagraph(0));
946 mpTextObj = NULL;
948 // Iterate until a valid text object has been found or the search ends.
951 mpObj = NULL;
952 mpParaObj = NULL;
954 if (maObjectIterator != ::sd::outliner::OutlinerContainer(this).end())
956 maCurrentPosition = *maObjectIterator;
957 // Switch to the current object only if it is a valid text object.
958 if (IsValidTextObject (maCurrentPosition))
960 mpObj = SetObject (maCurrentPosition);
962 ++maObjectIterator;
964 if (mpObj != NULL)
966 PutTextIntoOutliner ();
968 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
969 if (pViewShell != 0)
970 switch (meMode)
972 case SEARCH:
973 PrepareSearchAndReplace ();
974 break;
975 case SPELL:
976 PrepareSpellCheck ();
977 break;
978 case TEXT_CONVERSION:
979 PrepareConversion();
980 break;
984 else
986 mbEndOfSearch = true;
987 EndOfSearch ();
990 while ( ! (mbFoundObject || mbEndOfSearch));
993 void Outliner::EndOfSearch()
995 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
996 if ( ! pViewShell)
998 OSL_ASSERT(pViewShell);
999 return;
1002 // Before we display a dialog we first jump to where the last valid text
1003 // object was found. All page and view mode switching since then was
1004 // temporary and should not be visible to the user.
1005 if ( ! pViewShell->ISA(OutlineViewShell))
1006 SetObject (maLastValidPosition);
1008 if (mbRestrictSearchToSelection)
1009 ShowEndOfSearchDialog ();
1010 else
1012 // When no match has been found so far then terminate the search.
1013 if ( ! mbMatchMayExist)
1015 ShowEndOfSearchDialog ();
1016 mbEndOfSearch = true;
1018 // Ask the user whether to wrap around and continue the search or
1019 // to terminate.
1020 else if (meMode==TEXT_CONVERSION || ShowWrapArroundDialog ())
1022 mbMatchMayExist = false;
1023 // Everything back to beginning (or end?) of the document.
1024 maObjectIterator = ::sd::outliner::OutlinerContainer(this).begin();
1025 if (pViewShell->ISA(OutlineViewShell))
1027 // Set cursor to first character of the document.
1028 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1029 if (pOutlinerView != NULL)
1030 pOutlinerView->SetSelection (GetSearchStartPosition ());
1033 mbEndOfSearch = false;
1035 else
1037 // No wrap around.
1038 mbEndOfSearch = true;
1043 void Outliner::ShowEndOfSearchDialog()
1045 mbWholeDocumentProcessed = true;
1047 if (meMode == SEARCH)
1049 if (!mbStringFound)
1051 SvxSearchDialogWrapper::SetSearchLabel(SL_NotFound);
1052 mpDrawDocument->libreOfficeKitCallback(LOK_CALLBACK_SEARCH_NOT_FOUND,
1053 mpSearchItem->GetSearchString().toUtf8().getStr());
1056 // don't do anything else for search
1057 return;
1060 OUString aString;
1061 if (mpView->AreObjectsMarked())
1062 aString = SD_RESSTR(STR_END_SPELLING_OBJ);
1063 else
1064 aString = SD_RESSTR(STR_END_SPELLING);
1066 // Show the message in an info box that is modal with respect to the
1067 // whole application.
1068 ScopedVclPtrInstance< MessageDialog > aInfoBox(nullptr, aString, VCL_MESSAGE_INFO);
1069 ShowModalMessageBox (*aInfoBox.get());
1072 bool Outliner::ShowWrapArroundDialog()
1074 // Determine whether to show the dialog.
1075 if (mpSearchItem)
1077 // When searching display the dialog only for single find&replace.
1078 const SvxSearchCmd nCommand(mpSearchItem->GetCommand());
1079 if (nCommand == SvxSearchCmd::REPLACE || nCommand == SvxSearchCmd::FIND)
1081 if (mbDirectionIsForward)
1082 SvxSearchDialogWrapper::SetSearchLabel(SL_End);
1083 else
1084 SvxSearchDialogWrapper::SetSearchLabel(SL_Start);
1086 return true;
1088 else
1089 return false;
1092 // show dialog only for spelling
1093 if (meMode != SPELL)
1094 return false;
1096 // The question text depends on the search direction.
1097 bool bImpress = mpDrawDocument && mpDrawDocument->GetDocumentType() == DOCUMENT_TYPE_IMPRESS;
1099 sal_uInt16 nStringId;
1100 if (mbDirectionIsForward)
1101 nStringId = bImpress ? STR_SAR_WRAP_FORWARD : STR_SAR_WRAP_FORWARD_DRAW;
1102 else
1103 nStringId = bImpress ? STR_SAR_WRAP_BACKWARD : STR_SAR_WRAP_BACKWARD_DRAW;
1105 // Pop up question box that asks the user whether to wrap around.
1106 // The dialog is made modal with respect to the whole application.
1107 ScopedVclPtrInstance<QueryBox> aQuestionBox(nullptr, WB_YES_NO | WB_DEF_YES, SD_RESSTR(nStringId));
1108 aQuestionBox->SetImage(QueryBox::GetStandardImage());
1109 sal_uInt16 nBoxResult = ShowModalMessageBox(*aQuestionBox.get());
1111 return (nBoxResult == RET_YES);
1114 bool Outliner::IsValidTextObject (const ::sd::outliner::IteratorPosition& rPosition)
1116 SdrTextObj* pObject = dynamic_cast< SdrTextObj* >( rPosition.mxObject.get() );
1117 return (pObject != NULL) && pObject->HasText() && ! pObject->IsEmptyPresObj();
1120 void Outliner::PutTextIntoOutliner()
1122 mpTextObj = dynamic_cast<SdrTextObj*>( mpObj );
1123 if ( mpTextObj && mpTextObj->HasText() && !mpTextObj->IsEmptyPresObj() )
1125 SdrText* pText = mpTextObj->getText( mnText );
1126 mpParaObj = pText ? pText->GetOutlinerParaObject() : NULL;
1128 if (mpParaObj != NULL)
1130 SetText(*mpParaObj);
1132 ClearModifyFlag();
1135 else
1137 mpTextObj = NULL;
1141 void Outliner::PrepareSpellCheck()
1143 EESpellState eState = HasSpellErrors();
1144 DBG_ASSERT(eState != EE_SPELL_NOSPELLER, "No SpellChecker");
1146 if (eState == EE_SPELL_NOLANGUAGE)
1148 mbError = true;
1149 mbEndOfSearch = true;
1150 ScopedVclPtrInstance<MessageDialog> aErrorBox (
1151 nullptr, SD_RESSTR(STR_NOLANGUAGE));
1152 ShowModalMessageBox (*aErrorBox.get());
1154 else if (eState != EE_SPELL_OK)
1156 // When spell checking we have to test whether we have processed the
1157 // whole document and have reached the start page again.
1158 if (meMode == SPELL)
1160 if (maSearchStartPosition == ::sd::outliner::Iterator())
1161 // Remember the position of the first text object so that we
1162 // know when we have processed the whole document.
1163 maSearchStartPosition = maObjectIterator;
1164 else if (maSearchStartPosition == maObjectIterator)
1166 mbEndOfSearch = true;
1170 EnterEditMode( false );
1174 void Outliner::PrepareSearchAndReplace()
1176 if (HasText( *mpSearchItem ))
1178 mbStringFound = true;
1179 mbMatchMayExist = true;
1181 EnterEditMode(false);
1183 mpDrawDocument->GetDocSh()->SetWaitCursor( false );
1184 // Start search at the right end of the current object's text
1185 // depending on the search direction.
1186 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1187 if (pOutlinerView != NULL)
1188 pOutlinerView->SetSelection (GetSearchStartPosition ());
1192 void Outliner::SetViewMode (PageKind ePageKind)
1194 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1195 ::boost::shared_ptr<DrawViewShell> pDrawViewShell(
1196 ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
1197 if (pDrawViewShell.get()!=NULL && ePageKind != pDrawViewShell->GetPageKind())
1199 // Restore old edit mode.
1200 pDrawViewShell->ChangeEditMode(mpImpl->meOriginalEditMode, false);
1202 SetStatusEventHdl(Link<>());
1203 OUString sViewURL;
1204 switch (ePageKind)
1206 case PK_STANDARD:
1207 default:
1208 sViewURL = framework::FrameworkHelper::msImpressViewURL;
1209 break;
1210 case PK_NOTES:
1211 sViewURL = framework::FrameworkHelper::msNotesViewURL;
1212 break;
1213 case PK_HANDOUT:
1214 sViewURL = framework::FrameworkHelper::msHandoutViewURL;
1215 break;
1217 // The text object iterator is destroyed when the shells are
1218 // switched but we need it so save it and restore it afterwards.
1219 ::sd::outliner::Iterator aIterator (maObjectIterator);
1220 bool bMatchMayExist = mbMatchMayExist;
1222 ViewShellBase& rBase = pViewShell->GetViewShellBase();
1223 SetViewShell(::boost::shared_ptr<ViewShell>());
1224 framework::FrameworkHelper::Instance(rBase)->RequestView(
1225 sViewURL,
1226 framework::FrameworkHelper::msCenterPaneURL);
1228 // Force (well, request) a synchronous update of the configuration.
1229 // In a better world we would handle the asynchronous view update
1230 // instead. But that would involve major restucturing of the
1231 // Outliner code.
1232 framework::FrameworkHelper::Instance(rBase)->RequestSynchronousUpdate();
1233 SetViewShell(rBase.GetMainViewShell());
1235 // Switching to another view shell has intermediatly called
1236 // EndSpelling(). A PrepareSpelling() is pending, so call that now.
1237 PrepareSpelling();
1239 // Update the number of pages so that
1240 // <member>DetectChange()</member> has the correct value to compare
1241 // to.
1242 mnPageCount = mpDrawDocument->GetSdPageCount(ePageKind);
1244 maObjectIterator = aIterator;
1245 mbMatchMayExist = bMatchMayExist;
1247 // Save edit mode so that it can be restored when switching the view
1248 // shell again.
1249 pDrawViewShell = ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell);
1250 OSL_ASSERT(pDrawViewShell.get()!=NULL);
1251 if (pDrawViewShell.get() != NULL)
1252 mpImpl->meOriginalEditMode = pDrawViewShell->GetEditMode();
1256 void Outliner::SetPage (EditMode eEditMode, sal_uInt16 nPageIndex)
1258 if ( ! mbRestrictSearchToSelection)
1260 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1261 ::boost::shared_ptr<DrawViewShell> pDrawViewShell(
1262 ::boost::dynamic_pointer_cast<DrawViewShell>(pViewShell));
1263 OSL_ASSERT(pDrawViewShell.get()!=NULL);
1264 if (pDrawViewShell.get() != NULL)
1266 pDrawViewShell->ChangeEditMode(eEditMode, false);
1267 pDrawViewShell->SwitchPage(nPageIndex);
1272 void Outliner::EnterEditMode (bool bGrabFocus)
1274 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1275 if (pOutlinerView && mpTextObj)
1277 pOutlinerView->SetOutputArea( Rectangle( Point(), Size(1, 1)));
1278 SetPaperSize( mpTextObj->GetLogicRect().GetSize() );
1279 SdrPageView* pPV = mpView->GetSdrPageView();
1281 // Make FuText the current function.
1282 SfxUInt16Item aItem (SID_TEXTEDIT, 1);
1283 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1284 pViewShell->GetDispatcher()->
1285 Execute(SID_TEXTEDIT, SfxCallMode::SYNCHRON |
1286 SfxCallMode::RECORD, &aItem, 0L);
1288 // To be consistent with the usual behaviour in the Office the text
1289 // object that is put into edit mode would have also to be selected.
1290 // Starting the text edit mode is not enough so we do it here by
1291 // hand.
1292 mbExpectingSelectionChangeEvent = true;
1293 mpView->UnmarkAllObj (pPV);
1294 mpView->MarkObj (mpTextObj, pPV);
1296 mpTextObj->setActiveText( mnText );
1298 // Turn on the edit mode for the text object.
1299 mpView->SdrBeginTextEdit(mpTextObj, pPV, mpWindow, true, this, pOutlinerView, true, true, bGrabFocus);
1301 SetUpdateMode(true);
1302 mbFoundObject = true;
1307 * SpellChecker: Error link handler
1309 IMPL_LINK( Outliner, SpellError, void *, nLang )
1311 mbError = true;
1312 OUString aError( SvtLanguageTable::GetLanguageString( (LanguageType)reinterpret_cast<sal_uLong>(nLang) ) );
1313 ErrorHandler::HandleError(* new StringErrorInfo(
1314 ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aError) );
1315 return 0;
1318 ESelection Outliner::GetSearchStartPosition()
1320 ESelection aPosition;
1321 if (mbDirectionIsForward)
1323 // The default constructor uses the beginning of the text as default.
1324 aPosition = ESelection ();
1326 else
1328 // Retrieve the position after the last character in the last
1329 // paragraph.
1330 sal_Int32 nParagraphCount = GetParagraphCount();
1331 if (nParagraphCount == 0)
1332 aPosition = ESelection();
1333 else
1335 sal_Int32 nLastParagraphLength = GetEditEngine().GetTextLen (
1336 nParagraphCount-1);
1337 aPosition = ESelection (nParagraphCount-1, nLastParagraphLength);
1341 return aPosition;
1344 bool Outliner::HasNoPreviousMatch()
1346 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1348 DBG_ASSERT (pOutlinerView!=NULL, "outline view in Outliner::HasNoPreviousMatch is NULL");
1350 // Detect whether the cursor stands at the beginning
1351 // resp. at the end of the text.
1352 return pOutlinerView->GetSelection().IsEqual(GetSearchStartPosition ());
1355 bool Outliner::HandleFailedSearch()
1357 bool bContinueSearch = false;
1359 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1360 if (pOutlinerView != NULL && mpSearchItem != NULL)
1362 // Detect whether there is/may be a prior match. If there is then
1363 // ask the user whether to wrap around. Otherwise tell the user
1364 // that there is no match.
1365 if (HasNoPreviousMatch ())
1367 // No match found in the whole presentation.
1368 SvxSearchDialogWrapper::SetSearchLabel(SL_NotFound);
1371 else
1373 // No further matches found. Ask the user whether to wrap
1374 // around and start again.
1375 bContinueSearch = ShowWrapArroundDialog();
1379 return bContinueSearch;
1382 SdrObject* Outliner::SetObject (
1383 const ::sd::outliner::IteratorPosition& rPosition)
1385 SetViewMode (rPosition.mePageKind);
1386 SetPage (rPosition.meEditMode, (sal_uInt16)rPosition.mnPageIndex);
1387 mnText = rPosition.mnText;
1388 return rPosition.mxObject.get();
1391 void Outliner::SetViewShell (const ::boost::shared_ptr<ViewShell>& rpViewShell)
1393 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1394 if (pViewShell != rpViewShell)
1396 // Set the new view shell.
1397 mpWeakViewShell = rpViewShell;
1398 // When the outline view is not owned by us then we have to clear
1399 // that pointer so that the current one for the new view shell will
1400 // be used (in ProvideOutlinerView).
1401 if (rpViewShell)
1403 mpView = rpViewShell->GetView();
1405 mpWindow = rpViewShell->GetActiveWindow();
1407 mpImpl->ProvideOutlinerView(*this, rpViewShell, mpWindow);
1408 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1409 if (pOutlinerView != NULL)
1410 pOutlinerView->SetWindow(mpWindow);
1412 else
1414 mpView = NULL;
1415 mpWindow = NULL;
1420 void Outliner::HandleChangedSelection()
1422 maMarkListCopy.clear();
1423 mbRestrictSearchToSelection = mpView->AreObjectsMarked();
1424 if (mbRestrictSearchToSelection)
1426 // Make a copy of the current mark list.
1427 const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
1428 const size_t nCount = rMarkList.GetMarkCount();
1429 if (nCount > 0)
1431 maMarkListCopy.clear();
1432 maMarkListCopy.reserve (nCount);
1433 for (size_t i=0; i<nCount; ++i)
1434 maMarkListCopy.push_back (rMarkList.GetMark(i)->GetMarkedSdrObj ());
1436 else
1437 // No marked object. Is this case possible?
1438 mbRestrictSearchToSelection = false;
1442 void Outliner::StartConversion( sal_Int16 nSourceLanguage, sal_Int16 nTargetLanguage,
1443 const vcl::Font *pTargetFont, sal_Int32 nOptions, bool bIsInteractive )
1445 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1446 bool bMultiDoc = pViewShell->ISA(DrawViewShell);
1448 meMode = TEXT_CONVERSION;
1449 mbDirectionIsForward = true;
1450 mpSearchItem = NULL;
1451 mnConversionLanguage = nSourceLanguage;
1453 BeginConversion();
1455 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1456 if (pOutlinerView != NULL)
1458 pOutlinerView->StartTextConversion(
1459 nSourceLanguage,
1460 nTargetLanguage,
1461 pTargetFont,
1462 nOptions,
1463 bIsInteractive,
1464 bMultiDoc);
1467 EndConversion();
1470 /** Prepare to do a text conversion on the current text object. This
1471 includes putting it into edit mode.
1473 void Outliner::PrepareConversion()
1475 SetUpdateMode(true);
1476 if( HasConvertibleTextPortion( mnConversionLanguage ) )
1478 SetUpdateMode(false);
1479 mbStringFound = true;
1480 mbMatchMayExist = true;
1482 EnterEditMode ();
1484 mpDrawDocument->GetDocSh()->SetWaitCursor( false );
1485 // Start search at the right end of the current object's text
1486 // depending on the search direction.
1488 else
1490 SetUpdateMode(false);
1494 void Outliner::BeginConversion()
1496 SetRefDevice( SD_MOD()->GetRefDevice( *mpDrawDocument->GetDocSh() ) );
1498 ViewShellBase* pBase = PTR_CAST(ViewShellBase, SfxViewShell::Current());
1499 if (pBase != NULL)
1500 SetViewShell (pBase->GetMainViewShell());
1502 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1503 if (pViewShell)
1505 mbStringFound = false;
1507 // Supposed that we are not located at the very beginning/end of the
1508 // document then there may be a match in the document prior/after
1509 // the current position.
1510 mbMatchMayExist = true;
1512 maObjectIterator = ::sd::outliner::Iterator();
1513 maSearchStartPosition = ::sd::outliner::Iterator();
1514 RememberStartPosition();
1516 mpImpl->ProvideOutlinerView(*this, pViewShell, mpWindow);
1518 HandleChangedSelection ();
1520 ClearModifyFlag();
1523 void Outliner::EndConversion()
1525 EndSpelling();
1528 bool Outliner::ConvertNextDocument()
1530 ::boost::shared_ptr<ViewShell> pViewShell (mpWeakViewShell.lock());
1531 if (pViewShell && pViewShell->ISA(OutlineViewShell) )
1532 return false;
1534 mpDrawDocument->GetDocSh()->SetWaitCursor( true );
1536 Initialize ( true );
1538 OutlinerView* pOutlinerView = mpImpl->GetOutlinerView();
1539 if (pOutlinerView != NULL)
1541 mpWindow = pViewShell->GetActiveWindow();
1542 pOutlinerView->SetWindow(mpWindow);
1544 ProvideNextTextObject ();
1546 mpDrawDocument->GetDocSh()->SetWaitCursor( false );
1547 ClearModifyFlag();
1549 // for text conversion we automatically wrap around one
1550 // time and stop at the start shape
1551 if( mpFirstObj )
1553 if( (mnText == 0) && (mpFirstObj == mpObj) )
1554 return false;
1556 else
1558 mpFirstObj = mpObj;
1561 return !mbEndOfSearch;
1564 sal_uInt16 Outliner::ShowModalMessageBox (Dialog& rMessageBox)
1566 // We assume that the parent of the given messge box is NULL, i.e. it is
1567 // modal with respect to the top application window. However, this
1568 // does not affect the search dialog. Therefore we have to lock it here
1569 // while the message box is being shown. We also have to take into
1570 // account that we are called during a spell check and the search dialog
1571 // is not available.
1572 vcl::Window* pSearchDialog = NULL;
1573 SfxChildWindow* pChildWindow = NULL;
1574 switch (meMode)
1576 case SEARCH:
1577 pChildWindow = SfxViewFrame::Current()->GetChildWindow(
1578 SvxSearchDialogWrapper::GetChildWindowId());
1579 break;
1581 case SPELL:
1582 pChildWindow = SfxViewFrame::Current()->GetChildWindow(
1583 SpellDialogChildWindow::GetChildWindowId());
1584 break;
1586 case TEXT_CONVERSION:
1587 // There should no messages boxes be displayed while doing the
1588 // hangul hanja conversion.
1589 break;
1592 if (pChildWindow != NULL)
1593 pSearchDialog = pChildWindow->GetWindow();
1594 if (pSearchDialog != NULL)
1595 pSearchDialog->EnableInput(false,true);
1597 sal_uInt16 nResult = rMessageBox.Execute();
1599 // Unlock the search dialog.
1600 if (pSearchDialog != NULL)
1601 pSearchDialog->EnableInput(true,true);
1603 return nResult;
1606 //===== Outliner::Implementation ==============================================
1608 Outliner::Implementation::Implementation()
1609 : meOriginalEditMode(EM_PAGE),
1610 mbOwnOutlineView(false),
1611 mpOutlineView(NULL)
1615 Outliner::Implementation::~Implementation()
1617 if (mbOwnOutlineView && mpOutlineView!=NULL)
1619 mpOutlineView->SetWindow(NULL);
1620 delete mpOutlineView;
1621 mpOutlineView = NULL;
1625 /** We try to create a new OutlinerView only when there is none available,
1626 either from an OutlinerViewShell or a previous call to
1627 ProvideOutlinerView(). This is necessary to support the spell checker
1628 which can not cope with exchanging the OutlinerView.
1630 void Outliner::Implementation::ProvideOutlinerView (
1631 Outliner& rOutliner,
1632 const ::boost::shared_ptr<ViewShell>& rpViewShell,
1633 vcl::Window* pWindow)
1635 if (rpViewShell.get() != NULL)
1637 switch (rpViewShell->GetShellType())
1639 case ViewShell::ST_DRAW:
1640 case ViewShell::ST_IMPRESS:
1641 case ViewShell::ST_NOTES:
1642 case ViewShell::ST_HANDOUT:
1644 // Create a new outline view to do the search on.
1645 bool bInsert = false;
1646 if (mpOutlineView!=NULL && !mbOwnOutlineView)
1647 mpOutlineView = NULL;
1648 if (mpOutlineView == NULL)
1650 mpOutlineView = new OutlinerView(&rOutliner, pWindow);
1651 mbOwnOutlineView = true;
1652 bInsert = true;
1654 else
1655 mpOutlineView->SetWindow(pWindow);
1656 EVControlBits nStat = mpOutlineView->GetControlWord();
1657 nStat &= ~EVControlBits::AUTOSCROLL;
1658 mpOutlineView->SetControlWord(nStat);
1659 if (bInsert)
1660 rOutliner.InsertView( mpOutlineView );
1661 rOutliner.SetUpdateMode(false);
1662 mpOutlineView->SetOutputArea (Rectangle (Point(), Size(1, 1)));
1663 rOutliner.SetPaperSize( Size(1, 1) );
1664 rOutliner.SetText(OUString(), rOutliner.GetParagraph(0));
1666 meOriginalEditMode =
1667 ::boost::static_pointer_cast<DrawViewShell>(rpViewShell)->GetEditMode();
1669 break;
1671 case ViewShell::ST_OUTLINE:
1673 if (mpOutlineView!=NULL && mbOwnOutlineView)
1674 delete mpOutlineView;
1675 mpOutlineView = rOutliner.GetView(0);
1676 mbOwnOutlineView = false;
1678 break;
1680 default:
1681 case ViewShell::ST_NONE:
1682 case ViewShell::ST_PRESENTATION:
1683 // Ignored
1684 break;
1689 void Outliner::Implementation::ReleaseOutlinerView()
1691 if (mbOwnOutlineView)
1693 OutlinerView* pView = mpOutlineView;
1694 mpOutlineView = NULL;
1695 mbOwnOutlineView = false;
1696 if (pView != NULL)
1698 pView->SetWindow(NULL);
1699 delete pView;
1702 else
1704 mpOutlineView = NULL;
1708 } // end of namespace sd
1710 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */