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/app.hxx>
23 #include <sfx2/bindings.hxx>
24 #include <sfx2/dispatch.hxx>
25 #include <svx/svxids.hrc>
26 #include <editeng/editstat.hxx>
27 #include <editeng/editview.hxx>
28 #include <editeng/unolingu.hxx>
29 #include "selectionstate.hxx"
31 #include "spelleng.hxx"
32 #include "tabvwsh.hxx"
35 #include "editable.hxx"
36 #include "undoblk.hxx"
37 #include <gridwin.hxx>
38 #include <refupdatecontext.hxx>
40 SFX_IMPL_CHILDWINDOW_WITHID( ScSpellDialogChildWindow
, SID_SPELL_DIALOG
)
42 ScSpellDialogChildWindow::ScSpellDialogChildWindow( vcl::Window
* pParentP
, sal_uInt16 nId
,
43 SfxBindings
* pBindings
, SfxChildWinInfo
* pInfo
) :
44 svx::SpellDialogChildWindow( pParentP
, nId
, pBindings
, pInfo
),
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
.get() && 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
, false );
86 while( mbNeedNextObj
);
92 void ScSpellDialogChildWindow::ApplyChangedSentence( const svx::SpellPortions
& rChanged
, bool bRecheck
)
94 if( mxEngine
.get() && mpViewData
)
95 if( EditView
* pEditView
= mpViewData
->GetSpellingView() )
96 mxEngine
->ApplyChangedSentence( *pEditView
, rChanged
, bRecheck
);
99 void ScSpellDialogChildWindow::GetFocus()
101 if( IsSelectionChanged() )
104 InvalidateSpellDialog();
109 void ScSpellDialogChildWindow::LoseFocus()
113 // private --------------------------------------------------------------------
115 void ScSpellDialogChildWindow::Reset()
117 if( mpViewShell
&& (mpViewShell
== dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() )) )
119 if( mxEngine
.get() && mxEngine
->IsAnyModified() )
121 const ScAddress
& rCursor
= mxOldSel
->GetCellCursor();
122 SCTAB nTab
= rCursor
.Tab();
123 SCCOL nOldCol
= rCursor
.Col();
124 SCROW nOldRow
= rCursor
.Row();
125 SCCOL nNewCol
= mpViewData
->GetCurX();
126 SCROW nNewRow
= mpViewData
->GetCurY();
127 mpDocShell
->GetUndoManager()->AddUndoAction( new ScUndoConversion(
128 mpDocShell
, mpViewData
->GetMarkData(),
129 nOldCol
, nOldRow
, nTab
, mxUndoDoc
.release(),
130 nNewCol
, nNewRow
, nTab
, mxRedoDoc
.release(),
131 ScConversionParam( SC_CONVERSION_SPELLCHECK
) ) );
133 sc::SetFormulaDirtyContext aCxt
;
134 mpDoc
->SetAllFormulasDirty(aCxt
);
136 mpDocShell
->SetDocumentModified();
139 mpViewData
->SetSpellingView( nullptr );
140 mpViewShell
->KillEditView( true );
141 mpDocShell
->PostPaintGridAll();
142 mpViewShell
->UpdateInputHandler();
143 mpDoc
->EnableIdle(mbOldIdleEnabled
);
149 mxOldRangeList
.reset();
150 mpViewShell
= nullptr;
151 mpViewData
= nullptr;
152 mpDocShell
= nullptr;
154 mbNeedNextObj
= false;
155 mbOldIdleEnabled
= true;
158 void ScSpellDialogChildWindow::Init()
162 if( (mpViewShell
= dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() )) == nullptr )
165 mpViewData
= &mpViewShell
->GetViewData();
167 // exit edit mode - TODO support spelling in edit mode
168 if( mpViewData
->HasEditView( mpViewData
->GetActivePart() ) )
169 SC_MOD()->InputEnterHandler();
171 mxOldSel
.reset( new ScSelectionState( *mpViewData
) );
173 mpDocShell
= mpViewData
->GetDocShell();
174 mpDoc
= &mpDocShell
->GetDocument();
176 const ScAddress
& rCursor
= mxOldSel
->GetCellCursor();
177 SCCOL nCol
= rCursor
.Col();
178 SCROW nRow
= rCursor
.Row();
179 SCTAB nTab
= rCursor
.Tab();
181 ScMarkData
& rMarkData
= mpViewData
->GetMarkData();
183 mxOldRangeList
.reset(new ScRangeList
);
184 rMarkData
.FillRangeListWithMarks(mxOldRangeList
.get(), true);
186 rMarkData
.MarkToMulti();
188 switch( mxOldSel
->GetSelectionType() )
190 case SC_SELECTTYPE_NONE
:
191 case SC_SELECTTYPE_SHEET
:
193 // test if there is something editable
194 ScEditableTester
aTester( mpDoc
, rMarkData
);
195 if( !aTester
.IsEditable() )
197 // #i85751# Don't show a ErrorMessage here, because the vcl
198 // parent of the InfoBox is not fully initialized yet.
199 // This leads to problems in the modality behaviour of the
200 // ScSpellDialogChildWindow.
202 //mpViewShell->ErrorMessage( aTester.GetMessageId() );
208 // edit mode exited, see TODO above
209 // case SC_SELECTTYPE_EDITCELL:
213 OSL_FAIL( "ScSpellDialogChildWindow::Init - unknown selection type" );
216 mbOldIdleEnabled
= mpDoc
->IsIdleEnabled();
217 mpDoc
->EnableIdle(false); // stop online spelling
219 // *** create Undo/Redo documents *** -------------------------------------
221 mxUndoDoc
.reset( new ScDocument( SCDOCMODE_UNDO
) );
222 mxUndoDoc
->InitUndo( mpDoc
, nTab
, nTab
);
223 mxRedoDoc
.reset( new ScDocument( SCDOCMODE_UNDO
) );
224 mxRedoDoc
->InitUndo( mpDoc
, nTab
, nTab
);
226 if ( rMarkData
.GetSelectCount() > 1 )
228 ScMarkData::iterator itr
= rMarkData
.begin(), itrEnd
= rMarkData
.end();
229 for (; itr
!= itrEnd
; ++itr
)
233 mxUndoDoc
->AddUndoTab( *itr
, *itr
);
234 mxRedoDoc
->AddUndoTab( *itr
, *itr
);
239 // *** create and init the edit engine *** --------------------------------
241 mxEngine
.reset( new ScSpellingEngine(
242 mpDoc
->GetEnginePool(), *mpViewData
, mxUndoDoc
.get(), mxRedoDoc
.get(), LinguMgr::GetSpellChecker() ) );
243 mxEngine
->SetRefDevice( mpViewData
->GetActiveWin() );
245 mpViewShell
->MakeEditView( mxEngine
.get(), nCol
, nRow
);
246 EditView
* pEditView
= mpViewData
->GetEditView( mpViewData
->GetActivePart() );
247 mpViewData
->SetSpellingView( pEditView
);
248 Rectangle
aRect( Point( 0, 0 ), Point( 0, 0 ) );
249 pEditView
->SetOutputArea( aRect
);
250 mxEngine
->SetControlWord( EEControlBits::USECHARATTRIBS
);
251 mxEngine
->EnableUndo( false );
252 mxEngine
->SetPaperSize( aRect
.GetSize() );
253 mxEngine
->SetText( EMPTY_OUSTRING
);
254 mxEngine
->ClearModifyFlag();
256 mbNeedNextObj
= true;
259 bool ScSpellDialogChildWindow::IsSelectionChanged()
261 if( !mxOldRangeList
.get() || !mpViewShell
|| (mpViewShell
!= dynamic_cast<ScTabViewShell
*>( SfxViewShell::Current() )) )
264 if( EditView
* pEditView
= mpViewData
->GetSpellingView() )
265 if( pEditView
->GetEditEngine() != mxEngine
.get() )
268 ScRangeList aCurrentRangeList
;
269 mpViewData
->GetMarkData().FillRangeListWithMarks(&aCurrentRangeList
, true);
271 return (*mxOldRangeList
!= aCurrentRangeList
);
274 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */