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
10*efeef26fSAndrew Rist  *
11*efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*efeef26fSAndrew Rist  *
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.
19*efeef26fSAndrew Rist  *
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