Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / sw / source / uibase / dialog / SwSpellDialogChildWindow.cxx
blob52aeec2e47a398663011cd4f60b8bb26889277fd
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 <memory>
21 #include <SwSpellDialogChildWindow.hxx>
22 #include <vcl/layout.hxx>
23 #include <editeng/svxacorr.hxx>
24 #include <editeng/acorrcfg.hxx>
25 #include <svx/svxids.hrc>
26 #include <sfx2/app.hxx>
27 #include <sfx2/bindings.hxx>
28 #include <sfx2/dispatch.hxx>
29 #include <editeng/unolingu.hxx>
30 #include <editeng/editeng.hxx>
31 #include <editeng/editview.hxx>
32 #include <wrtsh.hxx>
33 #include <sfx2/printer.hxx>
34 #include <svx/svdoutl.hxx>
35 #include <svx/svdview.hxx>
36 #include <svx/svditer.hxx>
37 #include <svx/svdogrp.hxx>
38 #include <unotools/linguprops.hxx>
39 #include <unotools/lingucfg.hxx>
40 #include <doc.hxx>
41 #include <IDocumentDeviceAccess.hxx>
42 #include <IDocumentDrawModelAccess.hxx>
43 #include <docsh.hxx>
44 #include <docary.hxx>
45 #include <drawdoc.hxx>
46 #include <frmfmt.hxx>
47 #include <dcontact.hxx>
48 #include <edtwin.hxx>
49 #include <pam.hxx>
50 #include <drawbase.hxx>
51 #include <unotextrange.hxx>
52 #include <dialog.hrc>
53 #include <cmdid.h>
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::text;
58 using namespace ::com::sun::star::linguistic2;
59 using namespace ::com::sun::star::beans;
61 SFX_IMPL_CHILDWINDOW_WITHID(SwSpellDialogChildWindow, FN_SPELL_GRAMMAR_DIALOG)
63 #define SPELL_START_BODY 0 // body text area
64 #define SPELL_START_OTHER 1 // frame, footnote, header, footer
65 #define SPELL_START_DRAWTEXT 2 // started in a draw text object
67 struct SpellState
69 bool m_bInitialCall;
70 bool m_bLockFocus; // lock the focus notification while a modal dialog is active
71 bool m_bLostFocus;
73 // restart and progress information
74 sal_uInt16 m_SpellStartPosition;
75 bool m_bBodySpelled; // body already spelled
76 bool m_bOtherSpelled; // frames, footnotes, headers and footers spelled
77 bool m_bStartedInOther; // started the spelling inside of the _other_ area
78 bool m_bStartedInSelection; // there was an initial text selection
79 std::unique_ptr<SwPaM>
80 pOtherCursor; // position where the spelling inside the _other_ area started
81 bool m_bDrawingsSpelled; // all drawings spelled
82 Reference<XTextRange> m_xStartRange; // text range that marks the start of spelling
83 const SdrObject* m_pStartDrawing; // draw text object spelling started in
84 ESelection m_aStartDrawingSelection; // draw text start selection
85 bool m_bRestartDrawing; // the first selected drawing object is found again
87 // lose/get focus information to decide if spelling can be continued
88 ShellMode m_eSelMode;
89 const SwNode* m_pPointNode;
90 const SwNode* m_pMarkNode;
91 sal_Int32 m_nPointPos;
92 sal_Int32 m_nMarkPos;
93 const SdrOutliner* m_pOutliner;
94 ESelection m_aESelection;
96 // iterating over draw text objects
97 std::list<SdrTextObj*> m_aTextObjects;
98 bool m_bTextObjectsCollected;
100 SpellState() :
101 m_bInitialCall(true),
102 m_bLockFocus(false),
103 m_bLostFocus(false),
104 m_SpellStartPosition(SPELL_START_BODY),
105 m_bBodySpelled(false),
106 m_bOtherSpelled(false),
107 m_bStartedInOther(false),
108 m_bStartedInSelection(false),
109 pOtherCursor(nullptr),
110 m_bDrawingsSpelled(false),
111 m_pStartDrawing(nullptr),
112 m_bRestartDrawing(false),
114 m_eSelMode(ShellMode::Object), // initially invalid
115 m_pPointNode(nullptr),
116 m_pMarkNode(nullptr),
117 m_nPointPos(0),
118 m_nMarkPos(0),
119 m_pOutliner(nullptr),
120 m_bTextObjectsCollected(false)
123 // reset state in ::InvalidateSpellDialog
124 void Reset()
125 { m_bInitialCall = true;
126 m_bBodySpelled = m_bOtherSpelled = m_bDrawingsSpelled = false;
127 m_xStartRange = nullptr;
128 m_pStartDrawing = nullptr;
129 m_bRestartDrawing = false;
130 m_bTextObjectsCollected = false;
131 m_aTextObjects.clear();
132 m_bStartedInOther = false;
133 pOtherCursor.reset();
137 static void lcl_LeaveDrawText(SwWrtShell& rSh)
139 if(rSh.GetDrawView())
141 rSh.GetDrawView()->SdrEndTextEdit( true );
142 Point aPt(LONG_MIN, LONG_MIN);
143 // go out of the frame
144 rSh.SelectObj(aPt, SW_LEAVE_FRAME);
145 rSh.EnterStdMode();
146 rSh.GetView().AttrChangedNotify(&rSh);
150 SwSpellDialogChildWindow::SwSpellDialogChildWindow (
151 vcl::Window* _pParent,
152 sal_uInt16 nId,
153 SfxBindings* pBindings,
154 SfxChildWinInfo* /*pInfo*/)
155 : svx::SpellDialogChildWindow (
156 _pParent, nId, pBindings)
157 , m_bIsGrammarCheckingOn(false)
158 , m_pSpellState(new SpellState)
160 OUString aPropName(UPN_IS_GRAMMAR_INTERACTIVE);
161 SvtLinguConfig().GetProperty( aPropName ) >>= m_bIsGrammarCheckingOn;
164 SwSpellDialogChildWindow::~SwSpellDialogChildWindow ()
166 SwWrtShell* pWrtShell = GetWrtShell_Impl();
167 if(!m_pSpellState->m_bInitialCall && pWrtShell)
168 pWrtShell->SpellEnd();
169 delete m_pSpellState;
172 SfxChildWinInfo SwSpellDialogChildWindow::GetInfo() const
174 SfxChildWinInfo aInfo = svx::SpellDialogChildWindow::GetInfo();
175 aInfo.bVisible = false;
176 return aInfo;
179 svx::SpellPortions SwSpellDialogChildWindow::GetNextWrongSentence(bool bRecheck)
181 svx::SpellPortions aRet;
182 SwWrtShell* pWrtShell = GetWrtShell_Impl();
183 if(pWrtShell)
185 if (!bRecheck)
187 // first set continuation point for spell/grammar check to the
188 // end of the current sentence
189 SwEditShell::MoveContinuationPosToEndOfCheckedSentence();
192 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
193 bool bDrawText = ShellMode::DrawText == eSelMode;
194 bool bNormalText =
195 ShellMode::TableText == eSelMode ||
196 ShellMode::ListText == eSelMode ||
197 ShellMode::TableListText == eSelMode ||
198 ShellMode::Text == eSelMode;
199 // Writer text outside of the body
200 bool bOtherText = false;
202 if( m_pSpellState->m_bInitialCall )
204 // if no text selection exists the cursor has to be set into the text
205 if(!bDrawText && !bNormalText)
207 if(!MakeTextSelection_Impl(*pWrtShell, eSelMode))
208 return aRet;
209 else
211 // the selection type has to be checked again - both text types are possible
212 if(pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
213 bDrawText = true;
214 bNormalText = !bDrawText;
217 if(bNormalText)
219 // set cursor to the start of the sentence
220 if(!pWrtShell->HasSelection())
221 pWrtShell->GoStartSentence();
222 else
224 pWrtShell->ExpandToSentenceBorders();
225 m_pSpellState->m_bStartedInSelection = true;
227 // determine if the selection is outside of the body text
228 bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
229 m_pSpellState->m_SpellStartPosition = bOtherText ? SPELL_START_OTHER : SPELL_START_BODY;
230 if(bOtherText)
232 m_pSpellState->pOtherCursor.reset( new SwPaM(*pWrtShell->GetCursor()->GetPoint()) );
233 m_pSpellState->m_bStartedInOther = true;
234 pWrtShell->SpellStart( SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::Curr );
236 else
238 SwPaM* pCursor = pWrtShell->GetCursor();
239 // mark the start position only if not at start of doc
240 if(!pWrtShell->IsStartOfDoc())
242 m_pSpellState->m_xStartRange =
243 SwXTextRange::CreateXTextRange(
244 *pWrtShell->GetDoc(),
245 *pCursor->Start(), pCursor->End());
247 pWrtShell->SpellStart( SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Curr );
250 else
252 SdrView* pSdrView = pWrtShell->GetDrawView();
253 m_pSpellState->m_SpellStartPosition = SPELL_START_DRAWTEXT;
254 m_pSpellState->m_pStartDrawing = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
255 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
256 // start checking at the top of the drawing object
257 pOLV->SetSelection( ESelection() );
258 m_pSpellState->m_aStartDrawingSelection = ESelection();
260 Note: spelling in a selection only, or starting in a mid of a drawing object requires
261 further changes elsewhere. (Especially if it should work in sc and sd as well.)
262 The code below would only be part of the solution.
263 (Keeping it a as a comment for the time being)
264 ESelection aCurSel( pOLV->GetSelection() );
265 ESelection aSentenceSel( pOLV->GetEditView().GetEditEngine()->SelectSentence( aCurSel ) );
266 if (!aCurSel.HasRange())
268 aSentenceSel.nEndPara = aSentenceSel.nStartPara;
269 aSentenceSel.nEndPos = aSentenceSel.nStartPos;
271 pOLV->SetSelection( aSentenceSel );
272 m_pSpellState->m_aStartDrawingSelection = aSentenceSel;
276 m_pSpellState->m_bInitialCall = false;
278 if( bDrawText )
280 // spell inside of the current draw text
281 if(!SpellDrawText_Impl(*pWrtShell, aRet))
283 if(!FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet))
285 lcl_LeaveDrawText(*pWrtShell);
286 // now the drawings have been spelled
287 m_pSpellState->m_bDrawingsSpelled = true;
288 // the spelling continues at the other content
289 // if there's any that has not been spelled yet
290 if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
292 pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::OtherStart );
293 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
295 pWrtShell->SpellEnd();
296 m_pSpellState->m_bOtherSpelled = true;
299 else
300 m_pSpellState->m_bOtherSpelled = true;
301 // if no result has been found try at the body text - completely
302 if(!m_pSpellState->m_bBodySpelled && aRet.empty())
304 pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Start );
305 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
307 m_pSpellState->m_bBodySpelled = true;
308 pWrtShell->SpellEnd();
315 else
317 // spell inside of the Writer text
318 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
320 // if there is a selection (within body or header/footer text)
321 // then spell/grammar checking should not move outside of it.
322 if (!m_pSpellState->m_bStartedInSelection)
324 // find out which text has been spelled body or other
325 bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
326 if(bOtherText && m_pSpellState->m_bStartedInOther && m_pSpellState->pOtherCursor)
328 m_pSpellState->m_bStartedInOther = false;
329 pWrtShell->SetSelection(*m_pSpellState->pOtherCursor);
330 pWrtShell->SpellEnd();
331 m_pSpellState->pOtherCursor.reset();
332 pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::Curr, SwDocPositions::OtherStart );
333 (void)pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn);
335 if(aRet.empty())
337 // end spelling
338 pWrtShell->SpellEnd();
339 if(bOtherText)
341 m_pSpellState->m_bOtherSpelled = true;
342 // has the body been spelled?
343 if(!m_pSpellState->m_bBodySpelled)
345 pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Start );
346 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
348 m_pSpellState->m_bBodySpelled = true;
349 pWrtShell->SpellEnd();
353 else
355 m_pSpellState->m_bBodySpelled = true;
356 if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
358 pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::OtherStart );
359 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
361 pWrtShell->SpellEnd();
362 m_pSpellState->m_bOtherSpelled = true;
365 else
366 m_pSpellState->m_bOtherSpelled = true;
370 // search for a draw text object that contains error and spell it
371 if(aRet.empty() &&
372 (m_pSpellState->m_bDrawingsSpelled ||
373 !FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet)))
375 lcl_LeaveDrawText(*pWrtShell);
376 m_pSpellState->m_bDrawingsSpelled = true;
381 // now only the rest of the body text can be spelled -
382 // if the spelling started inside of the body
383 bool bCloseMessage = true;
384 if(aRet.empty() && !m_pSpellState->m_bStartedInSelection)
386 OSL_ENSURE(m_pSpellState->m_bDrawingsSpelled &&
387 m_pSpellState->m_bOtherSpelled && m_pSpellState->m_bBodySpelled,
388 "not all parts of the document are already spelled");
389 if(m_pSpellState->m_xStartRange.is())
391 LockFocusNotification( true );
392 sal_uInt16 nRet = ScopedVclPtrInstance<MessageDialog>(GetWindow(), SwResId(STR_QUERY_SPELL_CONTINUE),
393 VclMessageType::Question, VclButtonsType::YesNo)->Execute();
394 if(RET_YES == nRet)
396 SwUnoInternalPaM aPam(*pWrtShell->GetDoc());
397 if (::sw::XTextRangeToSwPaM(aPam,
398 m_pSpellState->m_xStartRange))
400 pWrtShell->SetSelection(aPam);
401 pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::Curr, SwDocPositions::Start);
402 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
403 pWrtShell->SpellEnd();
405 m_pSpellState->m_xStartRange = nullptr;
406 LockFocusNotification( false );
407 // take care that the now valid selection is stored
408 LoseFocus();
410 else
411 bCloseMessage = false; // no closing message if a wrap around has been denied
414 if(aRet.empty())
416 if(bCloseMessage)
418 LockFocusNotification( true );
419 OUString sInfo(SwResId(STR_SPELLING_COMPLETED));
420 // #i84610#
421 vcl::Window* pTemp = GetWindow(); // temporary needed for g++ 3.3.5
422 ScopedVclPtrInstance<MessageDialog>(pTemp, sInfo, VclMessageType::Info)->Execute();
423 LockFocusNotification( false );
424 // take care that the now valid selection is stored
425 LoseFocus();
429 return aRet;
432 void SwSpellDialogChildWindow::ApplyChangedSentence(const svx::SpellPortions& rChanged, bool bRecheck)
434 SwWrtShell* pWrtShell = GetWrtShell_Impl();
435 OSL_ENSURE(!m_pSpellState->m_bInitialCall, "ApplyChangedSentence in initial call or after resume");
436 if(pWrtShell && !m_pSpellState->m_bInitialCall)
438 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
439 bool bDrawText = ShellMode::DrawText == eSelMode;
440 bool bNormalText =
441 ShellMode::TableText == eSelMode ||
442 ShellMode::ListText == eSelMode ||
443 ShellMode::TableListText == eSelMode ||
444 ShellMode::Text == eSelMode;
446 // evaluate if the same sentence should be rechecked or not.
447 // Sentences that got grammar checked should always be rechecked in order
448 // to detect possible errors that get introduced with the changes
449 bRecheck |= SwEditShell::HasLastSentenceGotGrammarChecked();
451 if(bNormalText)
452 pWrtShell->ApplyChangedSentence(rChanged, bRecheck);
453 else if(bDrawText )
455 SdrView* pDrView = pWrtShell->GetDrawView();
456 SdrOutliner *pOutliner = pDrView->GetTextEditOutliner();
457 pOutliner->ApplyChangedSentence(pDrView->GetTextEditOutlinerView()->GetEditView(), rChanged, bRecheck);
462 void SwSpellDialogChildWindow::AddAutoCorrection(
463 const OUString& rOld, const OUString& rNew, LanguageType eLanguage)
465 SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
466 pACorr->PutText( rOld, rNew, eLanguage );
469 bool SwSpellDialogChildWindow::HasAutoCorrection()
471 return true;
474 bool SwSpellDialogChildWindow::HasGrammarChecking()
476 return SvtLinguConfig().HasGrammarChecker();
479 bool SwSpellDialogChildWindow::IsGrammarChecking()
481 return m_bIsGrammarCheckingOn;
484 void SwSpellDialogChildWindow::SetGrammarChecking(bool bOn)
486 uno::Any aVal;
487 aVal <<= bOn;
488 m_bIsGrammarCheckingOn = bOn;
489 OUString aPropName(UPN_IS_GRAMMAR_INTERACTIVE);
490 SvtLinguConfig().SetProperty( aPropName, aVal );
491 // set current spell position to the start of the current sentence to
492 // continue with this sentence after grammar checking state has been changed
493 SwWrtShell* pWrtShell = GetWrtShell_Impl();
494 if(pWrtShell)
496 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
497 bool bDrawText = ShellMode::DrawText == eSelMode;
498 bool bNormalText =
499 ShellMode::TableText == eSelMode ||
500 ShellMode::ListText == eSelMode ||
501 ShellMode::TableListText == eSelMode ||
502 ShellMode::Text == eSelMode;
503 if( bNormalText )
504 SwEditShell::PutSpellingToSentenceStart();
505 else if( bDrawText )
507 SdrView* pSdrView = pWrtShell->GetDrawView();
508 SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
509 OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SetGrammarChecking");
510 if(pOutliner)
512 pOutliner->PutSpellingToSentenceStart( pSdrView->GetTextEditOutlinerView()->GetEditView() );
518 void SwSpellDialogChildWindow::GetFocus()
520 if(m_pSpellState->m_bLockFocus)
521 return;
522 bool bInvalidate = false;
523 SwWrtShell* pWrtShell = GetWrtShell_Impl();
524 if(pWrtShell && !m_pSpellState->m_bInitialCall)
526 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
527 if(eSelMode != m_pSpellState->m_eSelMode)
529 // prevent initial invalidation
530 if(m_pSpellState->m_bLostFocus)
531 bInvalidate = true;
533 else
535 switch(m_pSpellState->m_eSelMode)
537 case ShellMode::Text:
538 case ShellMode::ListText:
539 case ShellMode::TableText:
540 case ShellMode::TableListText:
542 SwPaM* pCursor = pWrtShell->GetCursor();
543 if(m_pSpellState->m_pPointNode != &pCursor->GetNode() ||
544 m_pSpellState->m_pMarkNode != &pCursor->GetNode(false)||
545 m_pSpellState->m_nPointPos != pCursor->GetPoint()->nContent.GetIndex()||
546 m_pSpellState->m_nMarkPos != pCursor->GetMark()->nContent.GetIndex())
547 bInvalidate = true;
549 break;
550 case ShellMode::DrawText:
552 SdrView* pSdrView = pWrtShell->GetDrawView();
553 SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
554 if(!pOutliner || m_pSpellState->m_pOutliner != pOutliner)
555 bInvalidate = true;
556 else
558 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
559 OSL_ENSURE(pOLV, "no OutlinerView in SwSpellDialogChildWindow::GetFocus()");
560 if(!pOLV || !m_pSpellState->m_aESelection.IsEqual(pOLV->GetSelection()))
561 bInvalidate = true;
564 break;
565 default: bInvalidate = true;
569 else
571 bInvalidate = true;
573 if(bInvalidate)
574 InvalidateSpellDialog();
577 void SwSpellDialogChildWindow::LoseFocus()
579 // prevent initial invalidation
580 m_pSpellState->m_bLostFocus = true;
581 if(m_pSpellState->m_bLockFocus)
582 return;
583 SwWrtShell* pWrtShell = GetWrtShell_Impl();
584 if(pWrtShell)
586 m_pSpellState->m_eSelMode = pWrtShell->GetView().GetShellMode();
587 m_pSpellState->m_pPointNode = m_pSpellState->m_pMarkNode = nullptr;
588 m_pSpellState->m_nPointPos = m_pSpellState->m_nMarkPos = 0;
589 m_pSpellState->m_pOutliner = nullptr;
591 switch(m_pSpellState->m_eSelMode)
593 case ShellMode::Text:
594 case ShellMode::ListText:
595 case ShellMode::TableText:
596 case ShellMode::TableListText:
598 // store a node pointer and a pam-position to be able to check on next GetFocus();
599 SwPaM* pCursor = pWrtShell->GetCursor();
600 m_pSpellState->m_pPointNode = &pCursor->GetNode();
601 m_pSpellState->m_pMarkNode = &pCursor->GetNode(false);
602 m_pSpellState->m_nPointPos = pCursor->GetPoint()->nContent.GetIndex();
603 m_pSpellState->m_nMarkPos = pCursor->GetMark()->nContent.GetIndex();
606 break;
607 case ShellMode::DrawText:
609 SdrView* pSdrView = pWrtShell->GetDrawView();
610 SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
611 m_pSpellState->m_pOutliner = pOutliner;
612 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
613 OSL_ENSURE(pOutliner && pOLV, "no Outliner/OutlinerView in SwSpellDialogChildWindow::LoseFocus()");
614 if(pOLV)
616 m_pSpellState->m_aESelection = pOLV->GetSelection();
619 break;
620 default:;// prevent warning
623 else
624 m_pSpellState->m_eSelMode = ShellMode::Object;
627 void SwSpellDialogChildWindow::InvalidateSpellDialog()
629 SwWrtShell* pWrtShell = GetWrtShell_Impl();
630 if(!m_pSpellState->m_bInitialCall && pWrtShell)
631 pWrtShell->SpellEnd(nullptr, false);
632 m_pSpellState->Reset();
633 svx::SpellDialogChildWindow::InvalidateSpellDialog();
636 SwWrtShell* SwSpellDialogChildWindow::GetWrtShell_Impl()
638 SfxDispatcher* pDispatch = GetBindings().GetDispatcher();
639 SwView* pView = nullptr;
640 if(pDispatch)
642 sal_uInt16 nShellIdx = 0;
643 SfxShell* pShell;
644 while(nullptr != (pShell = pDispatch->GetShell(nShellIdx++)))
645 if(dynamic_cast< const SwView *>( pShell ) != nullptr)
647 pView = static_cast<SwView* >(pShell);
648 break;
651 return pView ? pView->GetWrtShellPtr(): nullptr;
654 // set the cursor into the body text - necessary if any object is selected
655 // on start of the spelling dialog
656 bool SwSpellDialogChildWindow::MakeTextSelection_Impl(SwWrtShell& rShell, ShellMode eSelMode)
658 SwView& rView = rShell.GetView();
659 switch(eSelMode)
661 case ShellMode::Text:
662 case ShellMode::ListText:
663 case ShellMode::TableText:
664 case ShellMode::TableListText:
665 case ShellMode::DrawText:
666 OSL_FAIL("text already active in SwSpellDialogChildWindow::MakeTextSelection_Impl()");
667 break;
669 case ShellMode::Frame:
671 rShell.UnSelectFrame();
672 rShell.LeaveSelFrameMode();
673 rView.AttrChangedNotify(&rShell);
675 break;
677 case ShellMode::Draw:
678 case ShellMode::DrawForm:
679 case ShellMode::Bezier:
680 if(FindNextDrawTextError_Impl(rShell))
682 rView.AttrChangedNotify(&rShell);
683 break;
685 SAL_FALLTHROUGH; // to deselect the object
686 case ShellMode::Graphic:
687 case ShellMode::Object:
689 if ( rShell.IsDrawCreate() )
691 rView.GetDrawFuncPtr()->BreakCreate();
692 rView.AttrChangedNotify(&rShell);
694 else if ( rShell.HasSelection() || rView.IsDrawMode() )
696 SdrView *pSdrView = rShell.GetDrawView();
697 if(pSdrView && pSdrView->AreObjectsMarked() &&
698 pSdrView->GetHdlList().GetFocusHdl())
700 const_cast<SdrHdlList&>(pSdrView->GetHdlList()).ResetFocusHdl();
702 else
704 rView.LeaveDrawCreate();
705 Point aPt(LONG_MIN, LONG_MIN);
706 // go out of the frame
707 rShell.SelectObj(aPt, SW_LEAVE_FRAME);
708 SfxBindings& rBind = rView.GetViewFrame()->GetBindings();
709 rBind.Invalidate( SID_ATTR_SIZE );
710 rShell.EnterStdMode();
711 rView.AttrChangedNotify(&rShell);
715 break;
716 default:; // prevent warning
718 return true;
721 // select the next draw text object that has a spelling error
722 bool SwSpellDialogChildWindow::FindNextDrawTextError_Impl(SwWrtShell& rSh)
724 bool bNextDoc = false;
725 SdrView* pDrView = rSh.GetDrawView();
726 if(!pDrView)
727 return bNextDoc;
728 SwView& rView = rSh.GetView();
729 SwDoc* pDoc = rView.GetDocShell()->GetDoc();
730 const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
731 // start at the current draw object - if there is any selected
732 SdrTextObj* pCurrentTextObj = nullptr;
733 if ( rMarkList.GetMarkCount() == 1 )
735 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
736 if( pObj && dynamic_cast< const SdrTextObj *>( pObj ) != nullptr )
737 pCurrentTextObj = static_cast<SdrTextObj*>(pObj);
739 // at first fill the list of drawing objects
740 if(!m_pSpellState->m_bTextObjectsCollected )
742 m_pSpellState->m_bTextObjectsCollected = true;
743 std::list<SdrTextObj*> aTextObjs;
744 SwDrawContact::GetTextObjectsFromFormat( aTextObjs, pDoc );
745 if(pCurrentTextObj)
747 m_pSpellState->m_aTextObjects.remove(pCurrentTextObj);
748 m_pSpellState->m_aTextObjects.push_back(pCurrentTextObj);
751 if(!m_pSpellState->m_aTextObjects.empty())
753 Reference< XSpellChecker1 > xSpell( GetSpellChecker() );
754 while(!bNextDoc && !m_pSpellState->m_aTextObjects.empty())
756 std::list<SdrTextObj*>::iterator aStart = m_pSpellState->m_aTextObjects.begin();
757 SdrTextObj* pTextObj = *aStart;
758 if(m_pSpellState->m_pStartDrawing == pTextObj)
759 m_pSpellState->m_bRestartDrawing = true;
760 m_pSpellState->m_aTextObjects.erase(aStart);
761 OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
762 if ( pParaObj )
764 bool bHasSpellError = false;
766 SdrOutliner aTmpOutliner(pDoc->getIDocumentDrawModelAccess().GetDrawModel()->
767 GetDrawOutliner().GetEmptyItemSet().GetPool(),
768 OutlinerMode::TextObject );
769 aTmpOutliner.SetRefDevice( pDoc->getIDocumentDeviceAccess().getPrinter( false ) );
770 MapMode aMapMode (MapUnit::MapTwip);
771 aTmpOutliner.SetRefMapMode(aMapMode);
772 aTmpOutliner.SetPaperSize( pTextObj->GetLogicRect().GetSize() );
773 aTmpOutliner.SetSpeller( xSpell );
775 std::unique_ptr<OutlinerView> pOutlView( new OutlinerView( &aTmpOutliner, &(rView.GetEditWin()) ) );
776 pOutlView->GetOutliner()->SetRefDevice( rSh.getIDocumentDeviceAccess().getPrinter( false ) );
777 aTmpOutliner.InsertView( pOutlView.get() );
778 Point aPt;
779 Size aSize(1,1);
780 tools::Rectangle aRect( aPt, aSize );
781 pOutlView->SetOutputArea( aRect );
782 aTmpOutliner.SetText( *pParaObj );
783 aTmpOutliner.ClearModifyFlag();
784 bHasSpellError = EESpellState::Ok != aTmpOutliner.HasSpellErrors();
785 aTmpOutliner.RemoveView( pOutlView.get() );
787 if(bHasSpellError)
789 // now the current one has to be deselected
790 if(pCurrentTextObj)
791 pDrView->SdrEndTextEdit( true );
792 // and the found one should be activated
793 rSh.MakeVisible(pTextObj->GetLogicRect());
794 Point aTmp( 0,0 );
795 rSh.SelectObj( aTmp, 0, pTextObj );
796 SdrPageView* pPV = pDrView->GetSdrPageView();
797 rView.BeginTextEdit( pTextObj, pPV, &rView.GetEditWin(), false, true );
798 rView.AttrChangedNotify(&rSh);
799 bNextDoc = true;
804 return bNextDoc;
807 bool SwSpellDialogChildWindow::SpellDrawText_Impl(SwWrtShell& rSh, svx::SpellPortions& rPortions)
809 bool bRet = false;
810 SdrView* pSdrView = rSh.GetDrawView();
811 SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
812 OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SpellDrawText_Impl");
813 if(pOutliner)
815 bRet = pOutliner->SpellSentence(pSdrView->GetTextEditOutlinerView()->GetEditView(), rPortions);
816 // find out if the current selection is in the first spelled drawing object
817 // and behind the initial selection
818 if(bRet && m_pSpellState->m_bRestartDrawing)
820 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
821 ESelection aCurrentSelection = pOLV->GetSelection();
822 if(m_pSpellState->m_aStartDrawingSelection.nEndPara < aCurrentSelection.nEndPara ||
823 (m_pSpellState->m_aStartDrawingSelection.nEndPara == aCurrentSelection.nEndPara &&
824 m_pSpellState->m_aStartDrawingSelection.nEndPos < aCurrentSelection.nEndPos))
826 bRet = false;
827 rPortions.clear();
831 return bRet;
834 void SwSpellDialogChildWindow::LockFocusNotification(bool bLock)
836 OSL_ENSURE(m_pSpellState->m_bLockFocus != bLock, "invalid locking - no change of state");
837 m_pSpellState->m_bLockFocus = bLock;
840 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */