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