1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 #include "spelldialog.hxx" 27 28 #include <sfx2/app.hxx> 29 #include <sfx2/bindings.hxx> 30 #include <sfx2/dispatch.hxx> 31 #include <svx/svxids.hrc> 32 #include <editeng/editstat.hxx> 33 #include <editeng/editview.hxx> 34 #include <editeng/unolingu.hxx> 35 #include "selectionstate.hxx" 36 37 #include "spelleng.hxx" 38 #include "tabvwsh.hxx" 39 #include "docsh.hxx" 40 #include "scmod.hxx" 41 #include "editable.hxx" 42 #include "undoblk.hxx" 43 44 // ============================================================================ 45 46 SFX_IMPL_CHILDWINDOW( ScSpellDialogChildWindow, SID_SPELL_DIALOG ) 47 48 ScSpellDialogChildWindow::ScSpellDialogChildWindow( Window* pParentP, sal_uInt16 nId, 49 SfxBindings* pBindings, SfxChildWinInfo* pInfo ) : 50 ::svx::SpellDialogChildWindow( pParentP, nId, pBindings, pInfo ), 51 mpViewShell( 0 ), 52 mpViewData( 0 ), 53 mpDocShell( 0 ), 54 mpDoc( 0 ), 55 mbNeedNextObj( false ), 56 mbOldIdleDisabled( false ) 57 { 58 Init(); 59 } 60 61 ScSpellDialogChildWindow::~ScSpellDialogChildWindow() 62 { 63 Reset(); 64 } 65 66 SfxChildWinInfo ScSpellDialogChildWindow::GetInfo() const 67 { 68 return ::svx::SpellDialogChildWindow::GetInfo(); 69 } 70 71 void ScSpellDialogChildWindow::InvalidateSpellDialog() 72 { 73 ::svx::SpellDialogChildWindow::InvalidateSpellDialog(); 74 } 75 76 // protected ------------------------------------------------------------------ 77 78 ::svx::SpellPortions ScSpellDialogChildWindow::GetNextWrongSentence( bool /*bRecheck*/ ) 79 { 80 ::svx::SpellPortions aPortions; 81 if( mxEngine.get() && mpViewData ) 82 { 83 if( EditView* pEditView = mpViewData->GetSpellingView() ) 84 { 85 // edit engine handles cell iteration internally 86 do 87 { 88 if( mbNeedNextObj ) 89 mxEngine->SpellNextDocument(); 90 mbNeedNextObj = !mxEngine->IsFinished() && !mxEngine->SpellSentence( *pEditView, aPortions, false ); 91 } 92 while( mbNeedNextObj ); 93 } 94 95 // finished? - close the spelling dialog 96 if( mxEngine->IsFinished() ) 97 GetBindings().GetDispatcher()->Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON ); 98 } 99 return aPortions; 100 } 101 102 void ScSpellDialogChildWindow::ApplyChangedSentence( const ::svx::SpellPortions& rChanged, bool bRecheck ) 103 { 104 if( mxEngine.get() && mpViewData ) 105 if( EditView* pEditView = mpViewData->GetSpellingView() ) 106 mxEngine->ApplyChangedSentence( *pEditView, rChanged, bRecheck ); 107 } 108 109 void ScSpellDialogChildWindow::GetFocus() 110 { 111 if( IsSelectionChanged() ) 112 { 113 Reset(); 114 InvalidateSpellDialog(); 115 Init(); 116 } 117 } 118 119 void ScSpellDialogChildWindow::LoseFocus() 120 { 121 } 122 123 // private -------------------------------------------------------------------- 124 125 void ScSpellDialogChildWindow::Reset() 126 { 127 if( mpViewShell && (mpViewShell == PTR_CAST( ScTabViewShell, SfxViewShell::Current() )) ) 128 { 129 if( mxEngine.get() && mxEngine->IsAnyModified() ) 130 { 131 const ScAddress& rCursor = mxOldSel->GetCellCursor(); 132 SCTAB nTab = rCursor.Tab(); 133 SCCOL nOldCol = rCursor.Col(); 134 SCROW nOldRow = rCursor.Row(); 135 SCCOL nNewCol = mpViewData->GetCurX(); 136 SCROW nNewRow = mpViewData->GetCurY(); 137 mpDocShell->GetUndoManager()->AddUndoAction( new ScUndoConversion( 138 mpDocShell, mpViewData->GetMarkData(), 139 nOldCol, nOldRow, nTab, mxUndoDoc.release(), 140 nNewCol, nNewRow, nTab, mxRedoDoc.release(), 141 ScConversionParam( SC_CONVERSION_SPELLCHECK ) ) ); 142 mpDoc->SetDirty(); 143 mpDocShell->SetDocumentModified(); 144 } 145 146 mpViewData->SetSpellingView( 0 ); 147 mpViewShell->KillEditView( sal_True ); 148 mpDocShell->PostPaintGridAll(); 149 mpViewShell->UpdateInputHandler(); 150 mpDoc->DisableIdle( mbOldIdleDisabled ); 151 } 152 mxEngine.reset(); 153 mxUndoDoc.reset(); 154 mxRedoDoc.reset(); 155 mxOldSel.reset(); 156 mpViewShell = 0; 157 mpViewData = 0; 158 mpDocShell = 0; 159 mpDoc = 0; 160 mbNeedNextObj = false; 161 mbOldIdleDisabled = false; 162 } 163 164 void ScSpellDialogChildWindow::Init() 165 { 166 if( mpViewShell ) 167 return; 168 if( (mpViewShell = PTR_CAST( ScTabViewShell, SfxViewShell::Current() )) == 0 ) 169 return; 170 171 mpViewData = mpViewShell->GetViewData(); 172 173 // exit edit mode - TODO support spelling in edit mode 174 if( mpViewData->HasEditView( mpViewData->GetActivePart() ) ) 175 SC_MOD()->InputEnterHandler(); 176 177 mxOldSel.reset( new ScSelectionState( *mpViewData ) ); 178 179 mpDocShell = mpViewData->GetDocShell(); 180 mpDoc = mpDocShell->GetDocument(); 181 182 const ScAddress& rCursor = mxOldSel->GetCellCursor(); 183 SCCOL nCol = rCursor.Col(); 184 SCROW nRow = rCursor.Row(); 185 SCTAB nTab = rCursor.Tab(); 186 187 ScMarkData& rMarkData = mpViewData->GetMarkData(); 188 rMarkData.MarkToMulti(); 189 190 switch( mxOldSel->GetSelectionType() ) 191 { 192 case SC_SELECTTYPE_NONE: 193 case SC_SELECTTYPE_SHEET: 194 { 195 // test if there is something editable 196 ScEditableTester aTester( mpDoc, rMarkData ); 197 if( !aTester.IsEditable() ) 198 { 199 // #i85751# Don't show a ErrorMessage here, because the vcl 200 // parent of the InfoBox is not fully initialized yet. 201 // This leads to problems in the modality behaviour of the 202 // ScSpellDialogChildWindow. 203 204 //mpViewShell->ErrorMessage( aTester.GetMessageId() ); 205 return; 206 } 207 } 208 break; 209 210 // edit mode exited, see TODO above 211 // case SC_SELECTTYPE_EDITCELL: 212 // break; 213 214 default: 215 DBG_ERRORFILE( "ScSpellDialogChildWindow::Init - unknown selection type" ); 216 } 217 218 mbOldIdleDisabled = mpDoc->IsIdleDisabled(); 219 mpDoc->DisableIdle( sal_True ); // #42726# stop online spelling 220 221 // *** create Undo/Redo documents *** ------------------------------------- 222 223 mxUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) ); 224 mxUndoDoc->InitUndo( mpDoc, nTab, nTab ); 225 mxRedoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) ); 226 mxRedoDoc->InitUndo( mpDoc, nTab, nTab ); 227 228 if ( rMarkData.GetSelectCount() > 1 ) 229 { 230 SCTAB nTabCount = mpDoc->GetTableCount(); 231 for( SCTAB nOtherTab = 0; nOtherTab < nTabCount; ++nOtherTab ) 232 { 233 if( rMarkData.GetTableSelect( nOtherTab ) && (nOtherTab != nTab) ) 234 { 235 mxUndoDoc->AddUndoTab( nOtherTab, nOtherTab ); 236 mxRedoDoc->AddUndoTab( nOtherTab, nOtherTab ); 237 } 238 } 239 } 240 241 // *** create and init the edit engine *** -------------------------------- 242 243 mxEngine.reset( new ScSpellingEngine( 244 mpDoc->GetEnginePool(), *mpViewData, mxUndoDoc.get(), mxRedoDoc.get(), LinguMgr::GetSpellChecker() ) ); 245 mxEngine->SetRefDevice( mpViewData->GetActiveWin() ); 246 247 mpViewShell->MakeEditView( mxEngine.get(), nCol, nRow ); 248 EditView* pEditView = mpViewData->GetEditView( mpViewData->GetActivePart() ); 249 mpViewData->SetSpellingView( pEditView ); 250 Rectangle aRect( Point( 0, 0 ), Point( 0, 0 ) ); 251 pEditView->SetOutputArea( aRect ); 252 mxEngine->SetControlWord( EE_CNTRL_USECHARATTRIBS ); 253 mxEngine->EnableUndo( sal_False ); 254 mxEngine->SetPaperSize( aRect.GetSize() ); 255 mxEngine->SetText( EMPTY_STRING ); 256 mxEngine->ClearModifyFlag(); 257 258 mbNeedNextObj = true; 259 } 260 261 bool ScSpellDialogChildWindow::IsSelectionChanged() 262 { 263 if( !mxOldSel.get() || !mpViewShell || (mpViewShell != PTR_CAST( ScTabViewShell, SfxViewShell::Current() )) ) 264 return true; 265 266 if( EditView* pEditView = mpViewData->GetSpellingView() ) 267 if( pEditView->GetEditEngine() != mxEngine.get() ) 268 return true; 269 270 ScSelectionState aNewSel( *mpViewData ); 271 return mxOldSel->GetSheetSelection() != aNewSel.GetSheetSelection(); 272 } 273 274 // ============================================================================ 275 276