1*efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*efeef26fSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*efeef26fSAndrew Rist * or more contributor license agreements. See the NOTICE file
5*efeef26fSAndrew Rist * distributed with this work for additional information
6*efeef26fSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*efeef26fSAndrew Rist * to you under the Apache License, Version 2.0 (the
8*efeef26fSAndrew Rist * "License"); you may not use this file except in compliance
9*efeef26fSAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*efeef26fSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*efeef26fSAndrew Rist * Unless required by applicable law or agreed to in writing,
14*efeef26fSAndrew Rist * software distributed under the License is distributed on an
15*efeef26fSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*efeef26fSAndrew Rist * KIND, either express or implied. See the License for the
17*efeef26fSAndrew Rist * specific language governing permissions and limitations
18*efeef26fSAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*efeef26fSAndrew Rist *************************************************************/
21*efeef26fSAndrew Rist
22*efeef26fSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <vcl/timer.hxx>
28cdf0e10cSrcweir #include <hints.hxx>
29cdf0e10cSrcweir #include <IGrammarContact.hxx>
30cdf0e10cSrcweir #include <pam.hxx>
31cdf0e10cSrcweir #include <ndtxt.hxx>
32cdf0e10cSrcweir #include <SwGrammarMarkUp.hxx>
33cdf0e10cSrcweir #include <txtfrm.hxx>
34cdf0e10cSrcweir #include <rootfrm.hxx>
35cdf0e10cSrcweir #include <viewsh.hxx>
36cdf0e10cSrcweir
37cdf0e10cSrcweir /* SwGrammarContact
38cdf0e10cSrcweir This class is responsible for the delayed display of grammar checks when a paragraph is edited
39cdf0e10cSrcweir It's a client of the paragraph the cursor points to.
40cdf0e10cSrcweir If the cursor position changes, updateCursorPosition has to be called
41cdf0e10cSrcweir If the grammar checker wants to set a grammar marker at a paragraph, he has to request
42cdf0e10cSrcweir the grammar list from this class. If the requested paragraph is not edited, it returns
43cdf0e10cSrcweir the normal grammar list. But if the paragraph is the active one, a proxy list will be returned and
44cdf0e10cSrcweir all changes are set in this proxy list. If the cursor leaves the paragraph the proxy list
45cdf0e10cSrcweir will replace the old list. If the grammar checker has completed the paragraph ('setChecked')
46cdf0e10cSrcweir then a timer is setup which replaces the old list as well.
47cdf0e10cSrcweir */
48cdf0e10cSrcweir
49cdf0e10cSrcweir class SwGrammarContact : public IGrammarContact, public SwClient
50cdf0e10cSrcweir {
51cdf0e10cSrcweir Timer aTimer;
52cdf0e10cSrcweir SwGrammarMarkUp *mpProxyList;
53cdf0e10cSrcweir bool mbFinished;
getMyTxtNode()54cdf0e10cSrcweir SwTxtNode* getMyTxtNode() { return (SwTxtNode*)GetRegisteredIn(); }
55cdf0e10cSrcweir DECL_LINK( TimerRepaint, Timer * );
56cdf0e10cSrcweir
57cdf0e10cSrcweir public:
58cdf0e10cSrcweir SwGrammarContact();
~SwGrammarContact()59cdf0e10cSrcweir ~SwGrammarContact() { aTimer.Stop(); delete mpProxyList; }
60cdf0e10cSrcweir
61cdf0e10cSrcweir // (pure) virtual functions of IGrammarContact
62cdf0e10cSrcweir virtual void updateCursorPosition( const SwPosition& rNewPos );
63cdf0e10cSrcweir virtual SwGrammarMarkUp* getGrammarCheck( SwTxtNode& rTxtNode, bool bCreate );
64cdf0e10cSrcweir virtual void finishGrammarCheck( SwTxtNode& rTxtNode );
65cdf0e10cSrcweir protected:
66cdf0e10cSrcweir // virtual function of SwClient
67cdf0e10cSrcweir virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew);
68cdf0e10cSrcweir };
69cdf0e10cSrcweir
SwGrammarContact()70cdf0e10cSrcweir SwGrammarContact::SwGrammarContact() : mpProxyList(0), mbFinished( false )
71cdf0e10cSrcweir {
72cdf0e10cSrcweir aTimer.SetTimeout( 2000 ); // Repaint of grammar check after 'setChecked'
73cdf0e10cSrcweir aTimer.SetTimeoutHdl( LINK(this, SwGrammarContact, TimerRepaint) );
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
IMPL_LINK(SwGrammarContact,TimerRepaint,Timer *,pTimer)76cdf0e10cSrcweir IMPL_LINK( SwGrammarContact, TimerRepaint, Timer *, pTimer )
77cdf0e10cSrcweir {
78cdf0e10cSrcweir if( pTimer )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir pTimer->Stop();
81cdf0e10cSrcweir if( GetRegisteredIn() )
82cdf0e10cSrcweir { //Replace the old wrong list by the proxy list and repaint all frames
83cdf0e10cSrcweir getMyTxtNode()->SetGrammarCheck( mpProxyList, true );
84cdf0e10cSrcweir mpProxyList = 0;
85cdf0e10cSrcweir SwTxtFrm::repaintTextFrames( *getMyTxtNode() );
86cdf0e10cSrcweir }
87cdf0e10cSrcweir }
88cdf0e10cSrcweir return 0;
89cdf0e10cSrcweir }
90cdf0e10cSrcweir
91cdf0e10cSrcweir /* I'm always a client of the current paragraph */
updateCursorPosition(const SwPosition & rNewPos)92cdf0e10cSrcweir void SwGrammarContact::updateCursorPosition( const SwPosition& rNewPos )
93cdf0e10cSrcweir {
94cdf0e10cSrcweir SwTxtNode* pTxtNode = rNewPos.nNode.GetNode().GetTxtNode();
95cdf0e10cSrcweir if( pTxtNode != GetRegisteredIn() ) // paragraph has been changed
96cdf0e10cSrcweir {
97cdf0e10cSrcweir aTimer.Stop();
98cdf0e10cSrcweir if( GetRegisteredIn() ) // My last paragraph has been left
99cdf0e10cSrcweir {
100cdf0e10cSrcweir if( mpProxyList )
101cdf0e10cSrcweir { // replace old list by the proxy list and repaint
102cdf0e10cSrcweir getMyTxtNode()->SetGrammarCheck( mpProxyList, true );
103cdf0e10cSrcweir SwTxtFrm::repaintTextFrames( *getMyTxtNode() );
104cdf0e10cSrcweir }
105cdf0e10cSrcweir GetRegisteredInNonConst()->Remove( this ); // good bye old paragraph
106cdf0e10cSrcweir mpProxyList = 0;
107cdf0e10cSrcweir }
108cdf0e10cSrcweir if( pTxtNode )
109cdf0e10cSrcweir pTxtNode->Add( this ); // welcome new paragraph
110cdf0e10cSrcweir }
111cdf0e10cSrcweir }
112cdf0e10cSrcweir
113cdf0e10cSrcweir /* deliver a grammar check list for the given text node */
getGrammarCheck(SwTxtNode & rTxtNode,bool bCreate)114cdf0e10cSrcweir SwGrammarMarkUp* SwGrammarContact::getGrammarCheck( SwTxtNode& rTxtNode, bool bCreate )
115cdf0e10cSrcweir {
116cdf0e10cSrcweir SwGrammarMarkUp *pRet = 0;
117cdf0e10cSrcweir if( GetRegisteredIn() == &rTxtNode ) // hey, that's my current paragraph!
118cdf0e10cSrcweir { // so you will get a proxy list...
119cdf0e10cSrcweir if( bCreate )
120cdf0e10cSrcweir {
121cdf0e10cSrcweir if( mbFinished )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir delete mpProxyList;
124cdf0e10cSrcweir mpProxyList = 0;
125cdf0e10cSrcweir }
126cdf0e10cSrcweir if( !mpProxyList )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir if( rTxtNode.GetGrammarCheck() )
129cdf0e10cSrcweir mpProxyList = (SwGrammarMarkUp*)rTxtNode.GetGrammarCheck()->Clone();
130cdf0e10cSrcweir else
131cdf0e10cSrcweir {
132cdf0e10cSrcweir mpProxyList = new SwGrammarMarkUp();
133cdf0e10cSrcweir mpProxyList->SetInvalid( 0, STRING_LEN );
134cdf0e10cSrcweir }
135cdf0e10cSrcweir }
136cdf0e10cSrcweir mbFinished = false;
137cdf0e10cSrcweir }
138cdf0e10cSrcweir pRet = mpProxyList;
139cdf0e10cSrcweir }
140cdf0e10cSrcweir else
141cdf0e10cSrcweir {
142cdf0e10cSrcweir pRet = rTxtNode.GetGrammarCheck(); // do you have already a list?
143cdf0e10cSrcweir if( bCreate && !pRet ) // do you want to create a list?
144cdf0e10cSrcweir {
145cdf0e10cSrcweir pRet = new SwGrammarMarkUp();
146cdf0e10cSrcweir pRet->SetInvalid( 0, STRING_LEN );
147cdf0e10cSrcweir rTxtNode.SetGrammarCheck( pRet );
148cdf0e10cSrcweir rTxtNode.SetGrammarCheckDirty( true );
149cdf0e10cSrcweir }
150cdf0e10cSrcweir }
151cdf0e10cSrcweir return pRet;
152cdf0e10cSrcweir }
153cdf0e10cSrcweir
Modify(const SfxPoolItem * pOld,const SfxPoolItem *)154cdf0e10cSrcweir void SwGrammarContact::Modify( const SfxPoolItem* pOld, const SfxPoolItem * )
155cdf0e10cSrcweir {
156cdf0e10cSrcweir if( !pOld || pOld->Which() != RES_OBJECTDYING )
157cdf0e10cSrcweir return;
158cdf0e10cSrcweir
159cdf0e10cSrcweir SwPtrMsgPoolItem *pDead = (SwPtrMsgPoolItem *)pOld;
160cdf0e10cSrcweir if( pDead->pObject == GetRegisteredIn() )
161cdf0e10cSrcweir { // if my current paragraph dies, I throw the proxy list away
162cdf0e10cSrcweir aTimer.Stop();
163cdf0e10cSrcweir GetRegisteredInNonConst()->Remove( this );
164cdf0e10cSrcweir delete mpProxyList;
165cdf0e10cSrcweir mpProxyList = 0;
166cdf0e10cSrcweir }
167cdf0e10cSrcweir }
168cdf0e10cSrcweir
finishGrammarCheck(SwTxtNode & rTxtNode)169cdf0e10cSrcweir void SwGrammarContact::finishGrammarCheck( SwTxtNode& rTxtNode )
170cdf0e10cSrcweir {
171cdf0e10cSrcweir if( &rTxtNode != GetRegisteredIn() ) // not my paragraph
172cdf0e10cSrcweir SwTxtFrm::repaintTextFrames( rTxtNode ); // can be repainted directly
173cdf0e10cSrcweir else
174cdf0e10cSrcweir {
175cdf0e10cSrcweir if( mpProxyList )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir mbFinished = true;
178cdf0e10cSrcweir aTimer.Start(); // will replace old list and repaint with delay
179cdf0e10cSrcweir }
180cdf0e10cSrcweir else if( getMyTxtNode()->GetGrammarCheck() )
181cdf0e10cSrcweir { // all grammar problems seems to be gone, no delay needed
182cdf0e10cSrcweir getMyTxtNode()->SetGrammarCheck( 0, true );
183cdf0e10cSrcweir SwTxtFrm::repaintTextFrames( *getMyTxtNode() );
184cdf0e10cSrcweir }
185cdf0e10cSrcweir }
186cdf0e10cSrcweir }
187cdf0e10cSrcweir
createGrammarContact()188cdf0e10cSrcweir IGrammarContact* createGrammarContact()
189cdf0e10cSrcweir {
190cdf0e10cSrcweir return new SwGrammarContact();
191cdf0e10cSrcweir }
192cdf0e10cSrcweir
finishGrammarCheck(SwTxtNode & rTxtNode)193cdf0e10cSrcweir void finishGrammarCheck( SwTxtNode& rTxtNode )
194cdf0e10cSrcweir {
195cdf0e10cSrcweir IGrammarContact* pGrammarContact = getGrammarContact( rTxtNode );
196cdf0e10cSrcweir if( pGrammarContact )
197cdf0e10cSrcweir pGrammarContact->finishGrammarCheck( rTxtNode );
198cdf0e10cSrcweir }
199cdf0e10cSrcweir
200