1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <spelldialog.hxx>
22 #include <sfx2/bindings.hxx>
23 #include <svx/svxids.hrc>
24 #include <editeng/editstat.hxx>
25 #include <editeng/editview.hxx>
26 #include <editeng/unolingu.hxx>
27 #include <selectionstate.hxx>
28 #include <osl/diagnose.h>
30 #include <spelleng.hxx>
31 #include <tabvwsh.hxx>
34 #include <editable.hxx>
35 #include <undoblk.hxx>
36 #include <gridwin.hxx>
37 #include <refupdatecontext.hxx>
38 #include <vcl/svapp.hxx>
40 SFX_IMPL_CHILDWINDOW_WITHID( ScSpellDialogChildWindow
, SID_SPELL_DIALOG
)
42 ScSpellDialogChildWindow::ScSpellDialogChildWindow( vcl::Window
* pParentP
, sal_uInt16 nId
,
43 SfxBindings
* pBindings
, SAL_UNUSED_PARAMETER SfxChildWinInfo
* /*pInfo*/ ) :
44 svx::SpellDialogChildWindow( pParentP
, nId
, pBindings
),
45 mpViewShell( nullptr ),
46 mpViewData( nullptr ),
47 mpDocShell( nullptr ),
49 mbNeedNextObj( false ),
50 mbOldIdleEnabled(true)
55 ScSpellDialogChildWindow::~ScSpellDialogChildWindow()
60 SfxChildWinInfo
ScSpellDialogChildWindow::GetInfo() const
62 return svx::SpellDialogChildWindow::GetInfo();
65 void ScSpellDialogChildWindow::InvalidateSpellDialog()
67 svx::SpellDialogChildWindow::InvalidateSpellDialog();
70 // protected ------------------------------------------------------------------
72 svx::SpellPortions
ScSpellDialogChildWindow::GetNextWrongSentence( bool /*bRecheck*/ )
74 svx::SpellPortions aPortions
;
75 if( mxEngine
&& mpViewData
)
77 if( EditView
* pEditView
= mpViewData
->GetSpellingView() )
79 // edit engine handles cell iteration internally
83 mxEngine
->SpellNextDocument();
84 mbNeedNextObj
= !mxEngine
->IsFinished() && !mxEngine
->SpellSentence( *pEditView
, aPortions
);
86 while( mbNeedNextObj
);
92 void ScSpellDialogChildWindow::ApplyChangedSentence( const svx::SpellPortions
& rChanged
, bool bRecheck
)
94 if( mxEngine
&& mpViewData
)
95 if( EditView
* pEditView
= mpViewData
->GetSpellingView() )
97 mxEngine
->ApplyChangedSentence( *pEditView
, rChanged
, bRecheck
);
99 // Reset the spell checking results to clear the markers.
100 mpViewData
->GetActiveWin()->ResetAutoSpell();
104 void ScSpellDialogChildWindow::GetFocus()
106 SolarMutexGuard aGuard
;
108 if( IsSelectionChanged() )
111 InvalidateSpellDialog();
116 void ScSpellDialogChildWindow::LoseFocus()
120 // private --------------------------------------------------------------------
122 void ScSpellDialogChildWindow::Reset()
124 if( mpViewShell
&& (mpViewShell
== dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() )) )
126 if( mxEngine
&& mxEngine
->IsAnyModified() )
128 const ScAddress
& rCursor
= mxOldSel
->GetCellCursor();
129 SCTAB nTab
= rCursor
.Tab();
130 SCCOL nOldCol
= rCursor
.Col();
131 SCROW nOldRow
= rCursor
.Row();
132 SCCOL nNewCol
= mpViewData
->GetCurX();
133 SCROW nNewRow
= mpViewData
->GetCurY();
134 mpDocShell
->GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoConversion
>(
135 mpDocShell
, mpViewData
->GetMarkData(),
136 nOldCol
, nOldRow
, nTab
, std::move(mxUndoDoc
),
137 nNewCol
, nNewRow
, nTab
, std::move(mxRedoDoc
),
138 ScConversionParam( SC_CONVERSION_SPELLCHECK
) ) );
140 sc::SetFormulaDirtyContext aCxt
;
141 mpDoc
->SetAllFormulasDirty(aCxt
);
143 mpDocShell
->SetDocumentModified();
146 mpViewData
->SetSpellingView( nullptr );
147 mpViewShell
->KillEditView( true );
148 mpDocShell
->PostPaintGridAll();
149 mpViewShell
->UpdateInputHandler();
150 mpDoc
->EnableIdle(mbOldIdleEnabled
);
156 mxOldRangeList
.clear();
157 mpViewShell
= nullptr;
158 mpViewData
= nullptr;
159 mpDocShell
= nullptr;
161 mbNeedNextObj
= false;
162 mbOldIdleEnabled
= true;
165 void ScSpellDialogChildWindow::Init()
169 if( (mpViewShell
= dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() )) == nullptr )
172 mpViewData
= &mpViewShell
->GetViewData();
174 // exit edit mode - TODO support spelling in edit mode
175 if( mpViewData
->HasEditView( mpViewData
->GetActivePart() ) )
176 ScModule::get()->InputEnterHandler();
178 mxOldSel
.reset( new ScSelectionState( *mpViewData
) );
180 mpDocShell
= mpViewData
->GetDocShell();
181 mpDoc
= &mpDocShell
->GetDocument();
183 const ScAddress
& rCursor
= mxOldSel
->GetCellCursor();
184 SCCOL nCol
= rCursor
.Col();
185 SCROW nRow
= rCursor
.Row();
186 SCTAB nTab
= rCursor
.Tab();
188 ScMarkData
& rMarkData
= mpViewData
->GetMarkData();
190 mxOldRangeList
= new ScRangeList
;
191 rMarkData
.FillRangeListWithMarks(mxOldRangeList
.get(), true);
193 rMarkData
.MarkToMulti();
195 switch( mxOldSel
->GetSelectionType() )
197 case SC_SELECTTYPE_NONE
:
198 case SC_SELECTTYPE_SHEET
:
200 // test if there is something editable
201 ScEditableTester
aTester( *mpDoc
, rMarkData
);
202 if( !aTester
.IsEditable() )
204 // #i85751# Don't show an ErrorMessage here, because the vcl
205 // parent of the InfoBox is not fully initialized yet.
206 // This leads to problems in the modality behaviour of the
207 // ScSpellDialogChildWindow.
209 //mpViewShell->ErrorMessage( aTester.GetMessageId() );
215 // edit mode exited, see TODO above
216 // case SC_SELECTTYPE_EDITCELL:
220 OSL_FAIL( "ScSpellDialogChildWindow::Init - unknown selection type" );
223 mbOldIdleEnabled
= mpDoc
->IsIdleEnabled();
224 mpDoc
->EnableIdle(false); // stop online spelling
226 // *** create Undo/Redo documents *** -------------------------------------
228 mxUndoDoc
.reset( new ScDocument( SCDOCMODE_UNDO
) );
229 mxUndoDoc
->InitUndo( *mpDoc
, nTab
, nTab
);
230 mxRedoDoc
.reset( new ScDocument( SCDOCMODE_UNDO
) );
231 mxRedoDoc
->InitUndo( *mpDoc
, nTab
, nTab
);
233 if ( rMarkData
.GetSelectCount() > 1 )
235 for (const auto& rTab
: rMarkData
)
239 mxUndoDoc
->AddUndoTab( rTab
, rTab
);
240 mxRedoDoc
->AddUndoTab( rTab
, rTab
);
245 // *** create and init the edit engine *** --------------------------------
247 mxEngine
.reset( new ScSpellingEngine(
248 mpDoc
->GetEnginePool(), *mpViewData
, mxUndoDoc
.get(), mxRedoDoc
.get(), LinguMgr::GetSpellChecker() ) );
249 mxEngine
->SetRefDevice( mpViewData
->GetActiveWin()->GetOutDev() );
251 mpViewShell
->MakeEditView( mxEngine
.get(), nCol
, nRow
);
252 EditView
* pEditView
= mpViewData
->GetEditView( mpViewData
->GetActivePart() );
253 mpViewData
->SetSpellingView( pEditView
);
254 tools::Rectangle
aRect( Point( 0, 0 ), Point( 0, 0 ) );
255 pEditView
->SetOutputArea( aRect
);
256 mxEngine
->SetControlWord( EEControlBits::USECHARATTRIBS
);
257 mxEngine
->EnableUndo( false );
258 mxEngine
->SetPaperSize( aRect
.GetSize() );
259 mxEngine
->SetTextCurrentDefaults( OUString() );
260 mxEngine
->ClearModifyFlag();
262 mbNeedNextObj
= true;
265 bool ScSpellDialogChildWindow::IsSelectionChanged()
267 if (!mxOldRangeList
|| !mpViewShell
268 || (mpViewShell
!= dynamic_cast<ScTabViewShell
*>(SfxViewShell::Current())))
271 if( EditView
* pEditView
= mpViewData
->GetSpellingView() )
272 if (&pEditView
->getEditEngine() != mxEngine
.get())
275 ScRangeList aCurrentRangeList
;
276 mpViewData
->GetMarkData().FillRangeListWithMarks(&aCurrentRangeList
, true);
278 return (*mxOldRangeList
!= aCurrentRangeList
);
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */