Revert "tdf#158280 Replace usage of InputDialog with SvxNameDialog"
[LibreOffice.git] / sw / source / uibase / dialog / SwSpellDialogChildWindow.cxx
blob65c96385f0e60ddf52ec54fa73a503d96618410c
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/svapp.hxx>
23 #include <vcl/weld.hxx>
24 #include <editeng/svxacorr.hxx>
25 #include <editeng/acorrcfg.hxx>
26 #include <sfx2/bindings.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <wrtsh.hxx>
30 #include <sfx2/printer.hxx>
31 #include <svx/svdoutl.hxx>
32 #include <svx/svdview.hxx>
33 #include <unotools/linguprops.hxx>
34 #include <unotools/lingucfg.hxx>
35 #include <osl/diagnose.h>
36 #include <doc.hxx>
37 #include <IDocumentDeviceAccess.hxx>
38 #include <IDocumentDrawModelAccess.hxx>
39 #include <docsh.hxx>
40 #include <drawdoc.hxx>
41 #include <dcontact.hxx>
42 #include <edtwin.hxx>
43 #include <pam.hxx>
44 #include <drawbase.hxx>
45 #include <unotextrange.hxx>
46 #include <strings.hrc>
47 #include <cmdid.h>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::linguistic2;
53 SFX_IMPL_CHILDWINDOW_WITHID(SwSpellDialogChildWindow, FN_SPELL_GRAMMAR_DIALOG)
55 struct SpellState
57 bool m_bInitialCall;
58 bool m_bLockFocus; // lock the focus notification while a modal dialog is active
59 bool m_bLostFocus;
61 // restart and progress information
62 bool m_bBodySpelled; // body already spelled
63 bool m_bOtherSpelled; // frames, footnotes, headers and footers spelled
64 bool m_bStartedInOther; // started the spelling inside of the _other_ area
65 bool m_bStartedInSelection; // there was an initial text selection
66 std::unique_ptr<SwPaM>
67 pOtherCursor; // position where the spelling inside the _other_ area started
68 bool m_bDrawingsSpelled; // all drawings spelled
69 rtl::Reference<SwXTextRange> m_xStartRange; // text range that marks the start of spelling
70 const SdrObject* m_pStartDrawing; // draw text object spelling started in
71 ESelection m_aStartDrawingSelection; // draw text start selection
72 bool m_bRestartDrawing; // the first selected drawing object is found again
74 // lose/get focus information to decide if spelling can be continued
75 ShellMode m_eSelMode;
76 const SwNode* m_pPointNode;
77 const SwNode* m_pMarkNode;
78 sal_Int32 m_nPointPos;
79 sal_Int32 m_nMarkPos;
80 const SdrOutliner* m_pOutliner;
81 ESelection m_aESelection;
83 // iterating over draw text objects
84 std::list<SdrTextObj*> m_aTextObjects;
85 bool m_bTextObjectsCollected;
87 SpellState() :
88 m_bInitialCall(true),
89 m_bLockFocus(false),
90 m_bLostFocus(false),
91 m_bBodySpelled(false),
92 m_bOtherSpelled(false),
93 m_bStartedInOther(false),
94 m_bStartedInSelection(false),
95 m_bDrawingsSpelled(false),
96 m_pStartDrawing(nullptr),
97 m_bRestartDrawing(false),
99 m_eSelMode(ShellMode::Object), // initially invalid
100 m_pPointNode(nullptr),
101 m_pMarkNode(nullptr),
102 m_nPointPos(0),
103 m_nMarkPos(0),
104 m_pOutliner(nullptr),
105 m_bTextObjectsCollected(false)
108 // reset state in ::InvalidateSpellDialog
109 void Reset()
110 { m_bInitialCall = true;
111 m_bBodySpelled = m_bOtherSpelled = m_bDrawingsSpelled = false;
112 m_xStartRange = nullptr;
113 m_pStartDrawing = nullptr;
114 m_bRestartDrawing = false;
115 m_bTextObjectsCollected = false;
116 m_aTextObjects.clear();
117 m_bStartedInOther = false;
118 pOtherCursor.reset();
122 static void lcl_LeaveDrawText(SwWrtShell& rSh)
124 if(rSh.GetDrawView())
126 rSh.GetDrawView()->SdrEndTextEdit( true );
127 Point aPt(LONG_MIN, LONG_MIN);
128 // go out of the frame
129 rSh.SelectObj(aPt, SW_LEAVE_FRAME);
130 rSh.EnterStdMode();
131 rSh.GetView().AttrChangedNotify(nullptr);
135 SwSpellDialogChildWindow::SwSpellDialogChildWindow (
136 vcl::Window* _pParent,
137 sal_uInt16 nId,
138 SfxBindings* pBindings,
139 SfxChildWinInfo* /*pInfo*/)
140 : svx::SpellDialogChildWindow (
141 _pParent, nId, pBindings)
142 , m_bIsGrammarCheckingOn(false)
143 , m_pSpellState(new SpellState)
145 SvtLinguConfig().GetProperty( UPN_IS_GRAMMAR_INTERACTIVE ) >>= m_bIsGrammarCheckingOn;
148 SwSpellDialogChildWindow::~SwSpellDialogChildWindow ()
150 SwWrtShell* pWrtShell = GetWrtShell_Impl();
151 if(!m_pSpellState->m_bInitialCall && pWrtShell)
152 pWrtShell->SpellEnd();
153 m_pSpellState.reset();
156 SfxChildWinInfo SwSpellDialogChildWindow::GetInfo() const
158 SfxChildWinInfo aInfo = svx::SpellDialogChildWindow::GetInfo();
159 aInfo.bVisible = false;
160 return aInfo;
163 svx::SpellPortions SwSpellDialogChildWindow::GetNextWrongSentence(bool bRecheck)
165 svx::SpellPortions aRet;
166 SwWrtShell* pWrtShell = GetWrtShell_Impl();
167 if(pWrtShell)
169 bool bNoDictionaryAvailable = pWrtShell->GetDoc()->IsDictionaryMissing();
171 if (!bRecheck)
173 // first set continuation point for spell/grammar check to the
174 // end of the current sentence
175 SwEditShell::MoveContinuationPosToEndOfCheckedSentence();
178 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
179 bool bDrawText = ShellMode::DrawText == eSelMode;
180 bool bNormalText =
181 ShellMode::TableText == eSelMode ||
182 ShellMode::ListText == eSelMode ||
183 ShellMode::TableListText == eSelMode ||
184 ShellMode::Text == eSelMode;
185 // Writer text outside of the body
186 bool bOtherText = false;
188 if( m_pSpellState->m_bInitialCall )
190 // if no text selection exists the cursor has to be set into the text
191 if(!bDrawText && !bNormalText)
193 MakeTextSelection_Impl(*pWrtShell, eSelMode);
194 // the selection type has to be checked again - both text types are possible
195 if(pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
196 bDrawText = true;
197 bNormalText = !bDrawText;
199 if(bNormalText)
201 // set cursor to the start of the sentence
202 if(!pWrtShell->HasSelection())
203 pWrtShell->GoStartSentence();
204 else
206 pWrtShell->ExpandToSentenceBorders();
207 m_pSpellState->m_bStartedInSelection = true;
209 // determine if the selection is outside of the body text
210 bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
211 if(bOtherText)
213 m_pSpellState->pOtherCursor.reset( new SwPaM(*pWrtShell->GetCursor()->GetPoint()) );
214 m_pSpellState->m_bStartedInOther = true;
215 pWrtShell->SpellStart( SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::Curr );
217 else
219 // mark the start position only if not at start of doc
220 if(!pWrtShell->IsStartOfDoc())
222 // Record the position *before* the current cursor, as
223 // the word at the current cursor can possibly be
224 // replaced by a spellcheck correction which invalidates
225 // an XTextRange at this position.
226 SwDoc *pDoc = pWrtShell->GetDoc();
227 auto pStart = pWrtShell->GetCursor()->Start();
228 auto pUnoCursor = pDoc->CreateUnoCursor(*pStart);
229 pUnoCursor->Left( 1 );
230 pStart = pUnoCursor->Start();
231 m_pSpellState->m_xStartRange
232 = SwXTextRange::CreateXTextRange(*pDoc, *pStart, nullptr);
234 pWrtShell->SpellStart( SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Curr );
237 else
239 SdrView* pSdrView = pWrtShell->GetDrawView();
240 m_pSpellState->m_pStartDrawing = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
241 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
242 // start checking at the top of the drawing object
243 pOLV->SetSelection( ESelection() );
244 m_pSpellState->m_aStartDrawingSelection = ESelection();
246 Note: spelling in a selection only, or starting in a mid of a drawing object requires
247 further changes elsewhere. (Especially if it should work in sc and sd as well.)
248 The code below would only be part of the solution.
249 (Keeping it as a comment for the time being)
250 ESelection aCurSel( pOLV->GetSelection() );
251 ESelection aSentenceSel( pOLV->GetEditView().GetEditEngine()->SelectSentence( aCurSel ) );
252 if (!aCurSel.HasRange())
254 aSentenceSel.nEndPara = aSentenceSel.nStartPara;
255 aSentenceSel.nEndPos = aSentenceSel.nStartPos;
257 pOLV->SetSelection( aSentenceSel );
258 m_pSpellState->m_aStartDrawingSelection = aSentenceSel;
262 m_pSpellState->m_bInitialCall = false;
264 if( bDrawText )
266 // spell inside of the current draw text
267 if(!SpellDrawText_Impl(*pWrtShell, aRet))
269 if(!FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet))
271 lcl_LeaveDrawText(*pWrtShell);
272 // now the drawings have been spelled
273 m_pSpellState->m_bDrawingsSpelled = true;
274 // the spelling continues at the other content
275 // if there's any that has not been spelled yet
276 if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
278 pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::OtherStart );
279 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
281 pWrtShell->SpellEnd();
282 m_pSpellState->m_bOtherSpelled = true;
285 else
286 m_pSpellState->m_bOtherSpelled = true;
287 // if no result has been found try at the body text - completely
288 if(!m_pSpellState->m_bBodySpelled && aRet.empty())
290 pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Start );
291 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
293 m_pSpellState->m_bBodySpelled = true;
294 pWrtShell->SpellEnd();
301 else
303 // spell inside of the Writer text
304 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
306 // if there is a selection (within body or header/footer text)
307 // then spell/grammar checking should not move outside of it.
308 if (!m_pSpellState->m_bStartedInSelection)
310 // find out which text has been spelled body or other
311 bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
312 if(bOtherText && m_pSpellState->m_bStartedInOther && m_pSpellState->pOtherCursor)
314 m_pSpellState->m_bStartedInOther = false;
315 pWrtShell->SetSelection(*m_pSpellState->pOtherCursor);
316 pWrtShell->SpellEnd();
317 m_pSpellState->pOtherCursor.reset();
318 pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::Curr, SwDocPositions::OtherStart );
319 (void)pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn);
321 if(aRet.empty())
323 // end spelling
324 pWrtShell->SpellEnd();
325 if(bOtherText)
327 m_pSpellState->m_bOtherSpelled = true;
328 // has the body been spelled?
329 if(!m_pSpellState->m_bBodySpelled)
331 pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::End, SwDocPositions::Start );
332 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
334 m_pSpellState->m_bBodySpelled = true;
335 pWrtShell->SpellEnd();
339 else
341 m_pSpellState->m_bBodySpelled = true;
342 if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
344 pWrtShell->SpellStart(SwDocPositions::OtherStart, SwDocPositions::OtherEnd, SwDocPositions::OtherStart );
345 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
347 pWrtShell->SpellEnd();
348 m_pSpellState->m_bOtherSpelled = true;
351 else
352 m_pSpellState->m_bOtherSpelled = true;
356 // search for a draw text object that contains error and spell it
357 if(aRet.empty() &&
358 (m_pSpellState->m_bDrawingsSpelled ||
359 !FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet)))
361 lcl_LeaveDrawText(*pWrtShell);
362 m_pSpellState->m_bDrawingsSpelled = true;
367 // now only the rest of the body text can be spelled -
368 // if the spelling started inside of the body
369 bool bCloseMessage = true;
370 if(aRet.empty() && !m_pSpellState->m_bStartedInSelection)
372 OSL_ENSURE(m_pSpellState->m_bDrawingsSpelled &&
373 m_pSpellState->m_bOtherSpelled && m_pSpellState->m_bBodySpelled,
374 "not all parts of the document are already spelled");
375 if( m_pSpellState->m_xStartRange.is() && !bNoDictionaryAvailable )
377 LockFocusNotification( true );
378 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetController()->getDialog(),
379 VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_QUERY_SPELL_CONTINUE)));
380 sal_uInt16 nRet = xBox->run();
381 if (RET_YES == nRet)
383 SwUnoInternalPaM aPam(*pWrtShell->GetDoc());
384 if (::sw::XTextRangeToSwPaM(aPam,
385 m_pSpellState->m_xStartRange))
387 pWrtShell->SetSelection(aPam);
388 pWrtShell->SpellStart(SwDocPositions::Start, SwDocPositions::Curr, SwDocPositions::Start);
389 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
390 pWrtShell->SpellEnd();
392 m_pSpellState->m_xStartRange = nullptr;
393 LockFocusNotification( false );
394 // take care that the now valid selection is stored
395 LoseFocus();
397 else
398 bCloseMessage = false; // no closing message if a wrap around has been denied
401 if( aRet.empty() && bCloseMessage )
403 LockFocusNotification( true );
404 OUString sInfo( SwResId( bNoDictionaryAvailable ? STR_DICTIONARY_UNAVAILABLE : STR_SPELLING_COMPLETED ) );
405 auto xSpellController = GetController();
406 // #i84610#
407 std::unique_ptr<weld::MessageDialog> xBox(
408 Application::CreateMessageDialog( xSpellController->getDialog(),
409 VclMessageType::Info,
410 VclButtonsType::Ok,
411 sInfo ) );
412 xBox->run();
413 LockFocusNotification( false );
414 // take care that the now valid selection is stored
415 LoseFocus();
416 xSpellController->getDialog()->grab_focus();
419 return aRet;
422 void SwSpellDialogChildWindow::ApplyChangedSentence(const svx::SpellPortions& rChanged, bool bRecheck)
424 SwWrtShell* pWrtShell = GetWrtShell_Impl();
425 OSL_ENSURE(!m_pSpellState->m_bInitialCall, "ApplyChangedSentence in initial call or after resume");
426 if(!pWrtShell || m_pSpellState->m_bInitialCall)
427 return;
429 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
430 bool bDrawText = ShellMode::DrawText == eSelMode;
431 bool bNormalText =
432 ShellMode::TableText == eSelMode ||
433 ShellMode::ListText == eSelMode ||
434 ShellMode::TableListText == eSelMode ||
435 ShellMode::Text == eSelMode;
437 // evaluate if the same sentence should be rechecked or not.
438 // Sentences that got grammar checked should always be rechecked in order
439 // to detect possible errors that get introduced with the changes
440 bRecheck |= SwEditShell::HasLastSentenceGotGrammarChecked();
442 if(bNormalText)
443 pWrtShell->ApplyChangedSentence(rChanged, bRecheck);
444 else if(bDrawText )
446 SdrView* pDrView = pWrtShell->GetDrawView();
447 SdrOutliner *pOutliner = pDrView->GetTextEditOutliner();
448 pOutliner->ApplyChangedSentence(pDrView->GetTextEditOutlinerView()->GetEditView(), rChanged, bRecheck);
452 void SwSpellDialogChildWindow::AddAutoCorrection(
453 const OUString& rOld, const OUString& rNew, LanguageType eLanguage)
455 SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
456 pACorr->PutText( rOld, rNew, eLanguage );
459 bool SwSpellDialogChildWindow::HasAutoCorrection()
461 return true;
464 bool SwSpellDialogChildWindow::HasGrammarChecking()
466 return SvtLinguConfig().HasGrammarChecker();
469 bool SwSpellDialogChildWindow::IsGrammarChecking()
471 return m_bIsGrammarCheckingOn;
474 void SwSpellDialogChildWindow::SetGrammarChecking(bool bOn)
476 uno::Any aVal;
477 aVal <<= bOn;
478 m_bIsGrammarCheckingOn = bOn;
479 SvtLinguConfig().SetProperty( UPN_IS_GRAMMAR_INTERACTIVE, aVal );
480 // set current spell position to the start of the current sentence to
481 // continue with this sentence after grammar checking state has been changed
482 SwWrtShell* pWrtShell = GetWrtShell_Impl();
483 if(!pWrtShell)
484 return;
486 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
487 bool bDrawText = ShellMode::DrawText == eSelMode;
488 bool bNormalText =
489 ShellMode::TableText == eSelMode ||
490 ShellMode::ListText == eSelMode ||
491 ShellMode::TableListText == eSelMode ||
492 ShellMode::Text == eSelMode;
493 if( bNormalText )
494 SwEditShell::PutSpellingToSentenceStart();
495 else if( bDrawText )
497 SdrView* pSdrView = pWrtShell->GetDrawView();
498 SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
499 OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SetGrammarChecking");
500 if(pOutliner)
502 pOutliner->PutSpellingToSentenceStart( pSdrView->GetTextEditOutlinerView()->GetEditView() );
507 void SwSpellDialogChildWindow::GetFocus()
509 if(m_pSpellState->m_bLockFocus)
510 return;
511 bool bInvalidate = false;
512 SwWrtShell* pWrtShell = GetWrtShell_Impl();
513 if(pWrtShell && !m_pSpellState->m_bInitialCall)
515 ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
516 if(eSelMode != m_pSpellState->m_eSelMode)
518 // prevent initial invalidation
519 if(m_pSpellState->m_bLostFocus)
520 bInvalidate = true;
522 else
524 switch(m_pSpellState->m_eSelMode)
526 case ShellMode::Text:
527 case ShellMode::ListText:
528 case ShellMode::TableText:
529 case ShellMode::TableListText:
531 SwPaM* pCursor = pWrtShell->GetCursor();
532 if(m_pSpellState->m_pPointNode != &pCursor->GetPointNode() ||
533 m_pSpellState->m_pMarkNode != &pCursor->GetMarkNode()||
534 m_pSpellState->m_nPointPos != pCursor->GetPoint()->GetContentIndex()||
535 m_pSpellState->m_nMarkPos != pCursor->GetMark()->GetContentIndex())
536 bInvalidate = true;
538 break;
539 case ShellMode::DrawText:
541 SdrView* pSdrView = pWrtShell->GetDrawView();
542 SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
543 if(!pOutliner || m_pSpellState->m_pOutliner != pOutliner)
544 bInvalidate = true;
545 else
547 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
548 OSL_ENSURE(pOLV, "no OutlinerView in SwSpellDialogChildWindow::GetFocus()");
549 if(!pOLV || m_pSpellState->m_aESelection != pOLV->GetSelection())
550 bInvalidate = true;
553 break;
554 default: bInvalidate = true;
558 else
560 bInvalidate = true;
562 if(bInvalidate)
563 InvalidateSpellDialog();
566 void SwSpellDialogChildWindow::LoseFocus()
568 // prevent initial invalidation
569 m_pSpellState->m_bLostFocus = true;
570 if(m_pSpellState->m_bLockFocus)
571 return;
572 SwWrtShell* pWrtShell = GetWrtShell_Impl();
573 if(pWrtShell)
575 m_pSpellState->m_eSelMode = pWrtShell->GetView().GetShellMode();
576 m_pSpellState->m_pPointNode = m_pSpellState->m_pMarkNode = nullptr;
577 m_pSpellState->m_nPointPos = m_pSpellState->m_nMarkPos = 0;
578 m_pSpellState->m_pOutliner = nullptr;
580 switch(m_pSpellState->m_eSelMode)
582 case ShellMode::Text:
583 case ShellMode::ListText:
584 case ShellMode::TableText:
585 case ShellMode::TableListText:
587 // store a node pointer and a pam-position to be able to check on next GetFocus();
588 SwPaM* pCursor = pWrtShell->GetCursor();
589 m_pSpellState->m_pPointNode = &pCursor->GetPointNode();
590 m_pSpellState->m_pMarkNode = &pCursor->GetMarkNode();
591 m_pSpellState->m_nPointPos = pCursor->GetPoint()->GetContentIndex();
592 m_pSpellState->m_nMarkPos = pCursor->GetMark()->GetContentIndex();
595 break;
596 case ShellMode::DrawText:
598 SdrView* pSdrView = pWrtShell->GetDrawView();
599 SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
600 m_pSpellState->m_pOutliner = pOutliner;
601 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
602 OSL_ENSURE(pOutliner && pOLV, "no Outliner/OutlinerView in SwSpellDialogChildWindow::LoseFocus()");
603 if(pOLV)
605 m_pSpellState->m_aESelection = pOLV->GetSelection();
608 break;
609 default:;// prevent warning
612 else
613 m_pSpellState->m_eSelMode = ShellMode::Object;
616 void SwSpellDialogChildWindow::InvalidateSpellDialog()
618 SwWrtShell* pWrtShell = GetWrtShell_Impl();
619 if(!m_pSpellState->m_bInitialCall && pWrtShell)
620 pWrtShell->SpellEnd(nullptr, false);
621 m_pSpellState->Reset();
622 svx::SpellDialogChildWindow::InvalidateSpellDialog();
625 SwWrtShell* SwSpellDialogChildWindow::GetWrtShell_Impl()
627 SfxDispatcher* pDispatch = GetBindings().GetDispatcher();
628 SwView* pView = nullptr;
629 if(pDispatch)
631 sal_uInt16 nShellIdx = 0;
632 SfxShell* pShell;
633 while(nullptr != (pShell = pDispatch->GetShell(nShellIdx++)))
634 if(auto pSwView = dynamic_cast< SwView *>( pShell ))
636 pView = pSwView;
637 break;
640 return pView ? pView->GetWrtShellPtr(): nullptr;
643 // set the cursor into the body text - necessary if any object is selected
644 // on start of the spelling dialog
645 void SwSpellDialogChildWindow::MakeTextSelection_Impl(SwWrtShell& rShell, ShellMode eSelMode)
647 SwView& rView = rShell.GetView();
648 switch(eSelMode)
650 case ShellMode::Text:
651 case ShellMode::ListText:
652 case ShellMode::TableText:
653 case ShellMode::TableListText:
654 case ShellMode::DrawText:
655 OSL_FAIL("text already active in SwSpellDialogChildWindow::MakeTextSelection_Impl()");
656 break;
658 case ShellMode::Frame:
660 rShell.UnSelectFrame();
661 rShell.LeaveSelFrameMode();
662 rView.AttrChangedNotify(nullptr);
664 break;
666 case ShellMode::Draw:
667 case ShellMode::DrawForm:
668 case ShellMode::Bezier:
669 if(FindNextDrawTextError_Impl(rShell))
671 rView.AttrChangedNotify(nullptr);
672 break;
674 [[fallthrough]]; // to deselect the object
675 case ShellMode::Graphic:
676 case ShellMode::Object:
678 if ( rShell.IsDrawCreate() )
680 rView.GetDrawFuncPtr()->BreakCreate();
681 rView.AttrChangedNotify(nullptr);
683 else if ( rShell.HasSelection() || rView.IsDrawMode() )
685 SdrView *pSdrView = rShell.GetDrawView();
686 if(pSdrView && pSdrView->GetMarkedObjectList().GetMarkCount() != 0 &&
687 pSdrView->GetHdlList().GetFocusHdl())
689 const_cast<SdrHdlList&>(pSdrView->GetHdlList()).ResetFocusHdl();
691 else
693 rView.LeaveDrawCreate();
694 Point aPt(LONG_MIN, LONG_MIN);
695 // go out of the frame
696 rShell.SelectObj(aPt, SW_LEAVE_FRAME);
697 SfxBindings& rBind = rView.GetViewFrame().GetBindings();
698 rBind.Invalidate( SID_ATTR_SIZE );
699 rShell.EnterStdMode();
700 rView.AttrChangedNotify(nullptr);
704 break;
705 default:; // prevent warning
709 // select the next draw text object that has a spelling error
710 bool SwSpellDialogChildWindow::FindNextDrawTextError_Impl(SwWrtShell& rSh)
712 bool bNextDoc = false;
713 SdrView* pDrView = rSh.GetDrawView();
714 if(!pDrView)
715 return bNextDoc;
716 SwView& rView = rSh.GetView();
717 SwDoc* pDoc = rView.GetDocShell()->GetDoc();
718 const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
719 // start at the current draw object - if there is any selected
720 SdrTextObj* pCurrentTextObj = nullptr;
721 if ( rMarkList.GetMarkCount() == 1 )
723 SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
724 if( auto pSdrTextObj = DynCastSdrTextObj( pObj ) )
725 pCurrentTextObj = pSdrTextObj;
727 // at first fill the list of drawing objects
728 if(!m_pSpellState->m_bTextObjectsCollected )
730 m_pSpellState->m_bTextObjectsCollected = true;
731 SwDrawContact::GetTextObjectsFromFormat(m_pSpellState->m_aTextObjects, *pDoc);
732 if(pCurrentTextObj)
734 m_pSpellState->m_aTextObjects.remove(pCurrentTextObj);
735 m_pSpellState->m_aTextObjects.push_back(pCurrentTextObj);
738 if(!m_pSpellState->m_aTextObjects.empty())
740 Reference< XSpellChecker1 > xSpell( GetSpellChecker() );
741 while(!bNextDoc && !m_pSpellState->m_aTextObjects.empty())
743 std::list<SdrTextObj*>::iterator aStart = m_pSpellState->m_aTextObjects.begin();
744 SdrTextObj* pTextObj = *aStart;
745 if(m_pSpellState->m_pStartDrawing == pTextObj)
746 m_pSpellState->m_bRestartDrawing = true;
747 m_pSpellState->m_aTextObjects.erase(aStart);
748 OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
749 if ( pParaObj )
751 bool bHasSpellError = false;
753 SdrOutliner aTmpOutliner(pDoc->getIDocumentDrawModelAccess().GetDrawModel()->
754 GetDrawOutliner().GetEmptyItemSet().GetPool(),
755 OutlinerMode::TextObject );
756 aTmpOutliner.SetRefDevice( pDoc->getIDocumentDeviceAccess().getPrinter( false ) );
757 MapMode aMapMode (MapUnit::MapTwip);
758 aTmpOutliner.SetRefMapMode(aMapMode);
759 aTmpOutliner.SetPaperSize( pTextObj->GetLogicRect().GetSize() );
760 aTmpOutliner.SetSpeller( xSpell );
762 OutlinerView aOutlView( &aTmpOutliner, &(rView.GetEditWin()) );
763 aOutlView.GetOutliner()->SetRefDevice( rSh.getIDocumentDeviceAccess().getPrinter( false ) );
764 aTmpOutliner.InsertView( &aOutlView );
765 Size aSize(1,1);
766 tools::Rectangle aRect( Point(), aSize );
767 aOutlView.SetOutputArea( aRect );
768 aTmpOutliner.SetText( *pParaObj );
769 aTmpOutliner.ClearModifyFlag();
770 bHasSpellError = EESpellState::Ok != aTmpOutliner.HasSpellErrors();
771 aTmpOutliner.RemoveView( &aOutlView );
773 if(bHasSpellError)
775 // now the current one has to be deselected
776 if(pCurrentTextObj)
777 pDrView->SdrEndTextEdit( true );
778 // and the found one should be activated
779 rSh.MakeVisible(SwRect(pTextObj->GetLogicRect()));
780 Point aTmp( 0,0 );
781 rSh.SelectObj( aTmp, 0, pTextObj );
782 SdrPageView* pPV = pDrView->GetSdrPageView();
783 rView.BeginTextEdit( pTextObj, pPV, &rView.GetEditWin(), false, true );
784 rView.AttrChangedNotify(nullptr);
785 bNextDoc = true;
790 return bNextDoc;
793 bool SwSpellDialogChildWindow::SpellDrawText_Impl(SwWrtShell& rSh, svx::SpellPortions& rPortions)
795 bool bRet = false;
796 SdrView* pSdrView = rSh.GetDrawView();
797 SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
798 OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SpellDrawText_Impl");
799 if(pOutliner)
801 bRet = pOutliner->SpellSentence(pSdrView->GetTextEditOutlinerView()->GetEditView(), rPortions);
802 // find out if the current selection is in the first spelled drawing object
803 // and behind the initial selection
804 if(bRet && m_pSpellState->m_bRestartDrawing)
806 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
807 ESelection aCurrentSelection = pOLV->GetSelection();
808 if (m_pSpellState->m_aStartDrawingSelection.end < aCurrentSelection.end)
810 bRet = false;
811 rPortions.clear();
815 return bRet;
818 void SwSpellDialogChildWindow::LockFocusNotification(bool bLock)
820 if (!m_pSpellState)
822 return;
825 OSL_ENSURE(m_pSpellState->m_bLockFocus != bLock, "invalid locking - no change of state");
826 m_pSpellState->m_bLockFocus = bLock;
829 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */