xref: /aoo41x/main/sc/source/ui/miscdlgs/anyrefdg.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 
31 
32 
33 //----------------------------------------------------------------------------
34 
35 #include "rangelst.hxx"
36 #include <sfx2/app.hxx>
37 #include <sfx2/viewsh.hxx>
38 #include <vcl/wrkwin.hxx>
39 #include <vcl/mnemonic.hxx>
40 #include <tools/shl.hxx>
41 #include <svtools/taskbar.hxx>
42 #include <sfx2/bindings.hxx>
43 #include <sfx2/dispatch.hxx>
44 
45 
46 #define ANYREFDG_CXX
47 #include "anyrefdg.hxx"
48 #undef ANYREFDG_CXX
49 
50 #include "sc.hrc"
51 #include "inputhdl.hxx"
52 #include "scmod.hxx"
53 #include "scresid.hxx"
54 #include "inputwin.hxx"
55 #include "tabvwsh.hxx"
56 #include "docsh.hxx"
57 #include "rfindlst.hxx"
58 #include "compiler.hxx"
59 #include "cell.hxx"
60 #include "global.hxx"
61 #include "inputopt.hxx"
62 #include "rangeutl.hxx"
63 
64 
65 ScFormulaReferenceHelper::ScFormulaReferenceHelper(IAnyRefDialog* _pDlg,SfxBindings* _pBindings)
66  : m_pDlg(_pDlg)
67  , pRefEdit (NULL)
68  , m_pWindow(NULL)
69  , m_pBindings(_pBindings)
70  , pAccel( NULL )
71  , pHiddenMarks(NULL)
72  , nRefTab(0)
73  , bHighLightRef( sal_False )
74  , bAccInserted( sal_False )
75 {
76     ScInputOptions aInputOption=SC_MOD()->GetInputOptions();
77 	bEnableColorRef=aInputOption.GetRangeFinder();
78 }
79 // -----------------------------------------------------------------------------
80 ScFormulaReferenceHelper::~ScFormulaReferenceHelper()
81 {
82     if (bAccInserted)
83 		Application::RemoveAccel( pAccel.get() );
84 
85     // common cleanup for ScAnyRefDlg and ScFormulaDlg is done here
86 
87     HideReference();
88     enableInput( sal_True );
89 
90     ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
91     if ( pInputHdl )
92         pInputHdl->ResetDelayTimer();   // stop the timer for disabling the input line
93 }
94 // -----------------------------------------------------------------------------
95 void ScFormulaReferenceHelper::enableInput( sal_Bool bEnable )
96 {
97     TypeId aType(TYPE(ScDocShell));
98     ScDocShell* pDocShell = (ScDocShell*)SfxObjectShell::GetFirst(&aType);
99     while( pDocShell )
100     {
101 	    SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
102 	    while( pFrame )
103 	    {
104 		    //	#71577# enable everything except InPlace, including bean frames
105             if ( !pFrame->GetFrame().IsInPlace() )
106 		    {
107 			    SfxViewShell* p = pFrame->GetViewShell();
108 			    ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
109 			    if(pViewSh!=NULL)
110 			    {
111 				    Window *pWin=pViewSh->GetWindow();
112 				    if(pWin)
113 				    {
114 					    Window *pParent=pWin->GetParent();
115 					    if(pParent)
116 					    {
117 						    pParent->EnableInput(bEnable,sal_True /* sal_False */);
118 						    if(sal_True /*bChilds*/)
119 							    pViewSh->EnableRefInput(bEnable);
120 					    }
121 				    }
122 			    }
123 		    }
124 		    pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
125 	    }
126 
127 	    pDocShell = (ScDocShell*)SfxObjectShell::GetNext(*pDocShell, &aType);
128     }
129 }
130 // -----------------------------------------------------------------------------
131 void ScFormulaReferenceHelper::ShowSimpleReference( const XubString& rStr )
132 {
133     if( /*!pRefEdit &&*/ bEnableColorRef )
134 	{
135 		bHighLightRef=sal_True;
136 		ScViewData* pViewData=ScDocShell::GetViewData();
137 		if ( pViewData )
138 		{
139 			ScDocument* pDoc=pViewData->GetDocument();
140 			ScTabViewShell*	pTabViewShell=pViewData->GetViewShell();
141 
142 			ScRangeList aRangeList;
143 
144 			pTabViewShell->DoneRefMode( sal_False );
145 			pTabViewShell->ClearHighlightRanges();
146 
147 			if( ParseWithNames( aRangeList, rStr, pDoc ) )
148 			{
149 				ScRange* pRangeEntry = aRangeList.First();
150 
151 				sal_uInt16 nIndex=0;
152 				while(pRangeEntry != NULL)
153 				{
154 					ColorData aColName = ScRangeFindList::GetColorName(nIndex++);
155 					pTabViewShell->AddHighlightRange(*pRangeEntry, aColName);
156 
157 					pRangeEntry = aRangeList.Next();
158 				}
159 			}
160 		}
161 	}
162 }
163 // -----------------------------------------------------------------------------
164 bool ScFormulaReferenceHelper::ParseWithNames( ScRangeList& rRanges, const String& rStr, ScDocument* pDoc )
165 {
166     bool bError = false;
167     rRanges.RemoveAll();
168 
169     ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0);
170     ScRangeUtil aRangeUtil;
171     xub_StrLen nTokenCnt = rStr.GetTokenCount();
172     for( xub_StrLen nToken = 0; nToken < nTokenCnt; ++nToken )
173     {
174         ScRange aRange;
175         String aRangeStr( rStr.GetToken( nToken ) );
176 
177         sal_uInt16 nFlags = aRange.ParseAny( aRangeStr, pDoc, aDetails );
178         if ( nFlags & SCA_VALID )
179         {
180             if ( (nFlags & SCA_TAB_3D) == 0 )
181                 aRange.aStart.SetTab( nRefTab );
182             if ( (nFlags & SCA_TAB2_3D) == 0 )
183                 aRange.aEnd.SetTab( aRange.aStart.Tab() );
184             rRanges.Append( aRange );
185         }
186         else if ( aRangeUtil.MakeRangeFromName( aRangeStr, pDoc, nRefTab, aRange, RUTL_NAMES, aDetails ) )
187             rRanges.Append( aRange );
188         else
189             bError = true;
190     }
191 
192     return !bError;
193 }
194 // -----------------------------------------------------------------------------
195 void ScFormulaReferenceHelper::ShowFormulaReference( const XubString& rStr )
196 {
197     if( /*!pRefEdit &&*/ bEnableColorRef)
198 	{
199 		bHighLightRef=sal_True;
200 		ScViewData* pViewData=ScDocShell::GetViewData();
201 		if ( pViewData && pRefComp.get() )
202 		{
203 			ScTabViewShell*	pTabViewShell=pViewData->GetViewShell();
204 			SCCOL nCol = pViewData->GetCurX();
205 			SCROW nRow = pViewData->GetCurY();
206 			SCTAB nTab = pViewData->GetTabNo();
207 			ScAddress aPos( nCol, nRow, nTab );
208 
209 			ScTokenArray* pScTokA=pRefComp->CompileString(rStr);
210 			//pRefComp->CompileTokenArray();
211 
212 			if(pTabViewShell!=NULL && pScTokA!=NULL)
213 			{
214 				pTabViewShell->DoneRefMode( sal_False );
215 				pTabViewShell->ClearHighlightRanges();
216 
217 				pScTokA->Reset();
218 				const ScToken* pToken = static_cast<const ScToken*>(pScTokA->GetNextReference());
219 
220 				sal_uInt16 nIndex=0;
221 
222 				while(pToken!=NULL)
223 				{
224 					sal_Bool bDoubleRef=(pToken->GetType()==formula::svDoubleRef);
225 
226 
227 					if(pToken->GetType()==formula::svSingleRef || bDoubleRef)
228 					{
229 						ScRange aRange;
230 						if(bDoubleRef)
231 						{
232 							ScComplexRefData aRef( pToken->GetDoubleRef() );
233 							aRef.CalcAbsIfRel( aPos );
234 							aRange.aStart.Set( aRef.Ref1.nCol, aRef.Ref1.nRow, aRef.Ref1.nTab );
235 							aRange.aEnd.Set( aRef.Ref2.nCol, aRef.Ref2.nRow, aRef.Ref2.nTab );
236 						}
237 						else
238 						{
239 							ScSingleRefData aRef( pToken->GetSingleRef() );
240 							aRef.CalcAbsIfRel( aPos );
241 							aRange.aStart.Set( aRef.nCol, aRef.nRow, aRef.nTab );
242 							aRange.aEnd = aRange.aStart;
243 						}
244 						ColorData aColName=ScRangeFindList::GetColorName(nIndex++);
245 						pTabViewShell->AddHighlightRange(aRange, aColName);
246 					}
247 
248 					pToken = static_cast<const ScToken*>(pScTokA->GetNextReference());
249 				}
250 			}
251 			if(pScTokA!=NULL) delete pScTokA;
252 		}
253 	}
254 }
255 // -----------------------------------------------------------------------------
256 void ScFormulaReferenceHelper::HideReference( sal_Bool bDoneRefMode )
257 {
258 	ScViewData* pViewData=ScDocShell::GetViewData();
259 
260     if( pViewData && /*!pRefEdit &&*/ bHighLightRef && bEnableColorRef)
261 	{
262 		ScTabViewShell*	pTabViewShell=pViewData->GetViewShell();
263 
264 		if(pTabViewShell!=NULL)
265 		{
266 			//	bDoneRefMode is sal_False when called from before SetReference.
267 			//	In that case, RefMode was just started and must not be ended now.
268 
269 			if ( bDoneRefMode )
270 				pTabViewShell->DoneRefMode( sal_False );
271 			pTabViewShell->ClearHighlightRanges();
272 		}
273 		bHighLightRef=sal_False;
274 	}
275 }
276 // -----------------------------------------------------------------------------
277 void ScFormulaReferenceHelper::ShowReference( const XubString& rStr )
278 {
279     if( /*!pRefEdit &&*/ bEnableColorRef )
280 	{
281 		if(	rStr.Search('(')!=STRING_NOTFOUND ||
282 			rStr.Search('+')!=STRING_NOTFOUND ||
283 			rStr.Search('*')!=STRING_NOTFOUND ||
284 			rStr.Search('-')!=STRING_NOTFOUND ||
285 			rStr.Search('/')!=STRING_NOTFOUND ||
286 			rStr.Search('&')!=STRING_NOTFOUND ||
287 			rStr.Search('<')!=STRING_NOTFOUND ||
288 			rStr.Search('>')!=STRING_NOTFOUND ||
289 			rStr.Search('=')!=STRING_NOTFOUND ||
290 			rStr.Search('^')!=STRING_NOTFOUND)
291 		{
292 			ShowFormulaReference(rStr);
293 		}
294 		else
295 		{
296 			ShowSimpleReference(rStr);
297 		}
298 	}
299 }
300 // -----------------------------------------------------------------------------
301 void ScFormulaReferenceHelper::ReleaseFocus( formula::RefEdit* pEdit, formula::RefButton* pButton )
302 {
303     if( !pRefEdit && pEdit )
304     {
305         m_pDlg->RefInputStart( pEdit, pButton );
306 //        if( pRefEdit )
307 //            pRefEdit->SilentGrabFocus();
308     }
309 
310     ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
311     if( pViewShell )
312     {
313         pViewShell->ActiveGrabFocus();
314         if( pRefEdit )
315         {
316             const ScViewData* pViewData = pViewShell->GetViewData();
317             ScDocument* pDoc = pViewData->GetDocument();
318 			ScRangeList aRangeList;
319             if( ParseWithNames( aRangeList, pRefEdit->GetText(), pDoc ) )
320 			{
321                 const ScRange* pRange = aRangeList.GetObject( 0 );
322                 if( pRange )
323                 {
324                     pViewShell->SetTabNo( pRange->aStart.Tab() );
325                     pViewShell->MoveCursorAbs(  pRange->aStart.Col(),
326                         pRange->aStart.Row(), SC_FOLLOW_JUMP, sal_False, sal_False );
327                     pViewShell->MoveCursorAbs( pRange->aEnd.Col(),
328                         pRange->aEnd.Row(), SC_FOLLOW_JUMP, sal_True, sal_False );
329                     m_pDlg->SetReference( *pRange, pDoc );
330                 }
331             }
332         }
333     }
334 }
335 // -----------------------------------------------------------------------------
336 void ScFormulaReferenceHelper::Init()
337 {
338     ScViewData* pViewData=ScDocShell::GetViewData();    //! use pScViewShell?
339 	if ( pViewData )
340 	{
341 		ScDocument* pDoc = pViewData->GetDocument();
342 		SCCOL nCol = pViewData->GetCurX();
343 		SCROW nRow = pViewData->GetCurY();
344 		SCTAB nTab = pViewData->GetTabNo();
345 		ScAddress aCursorPos( nCol, nRow, nTab );
346 
347 		String rStrExp;
348 		pRefCell.reset( new ScFormulaCell( pDoc, aCursorPos, rStrExp ) );
349 		pRefComp.reset( new ScCompiler( pDoc, aCursorPos) );
350         pRefComp->SetGrammar( pDoc->GetGrammar() );
351 		pRefComp->SetCompileForFAP(sal_True);
352 
353         nRefTab = nTab;
354 	} // if ( pViewData )
355 }
356 // -----------------------------------------------------------------------------
357 IMPL_LINK( ScFormulaReferenceHelper, AccelSelectHdl, Accelerator *, pSelAccel )
358 {
359     if ( !pSelAccel )
360 		return 0;
361 
362     switch ( pSelAccel->GetCurKeyCode().GetCode() )
363 	{
364 		case KEY_RETURN:
365 		case KEY_ESCAPE:
366             if( pRefEdit )
367                 pRefEdit->GrabFocus();
368             m_pDlg->RefInputDone( sal_True );
369         break;
370 	}
371 	return sal_True;
372 }
373 //----------------------------------------------------------------------------
374 void ScFormulaReferenceHelper::RefInputDone( sal_Bool bForced )
375 {
376 	//<!--Modified by PengYunQuan for Validity Cell Range Picker
377 	//if (pRefEdit && (bForced || !pRefBtn))
378 	if ( CanInputDone( bForced ) )//if (pRefEdit && (bForced || !pRefBtn))
379 	//-->Modified by PengYunQuan for Validity Cell Range Picker
380 	{
381 		if (bAccInserted)			// Accelerator wieder abschalten
382 		{
383 			Application::RemoveAccel( pAccel.get() );
384 			bAccInserted = sal_False;
385 		}
386 
387 		// Fenstertitel anpassen
388 		m_pWindow->SetText(sOldDialogText);
389 
390 		// Fenster wieder gross
391 		m_pWindow->SetOutputSizePixel(aOldDialogSize);
392 
393 		// pEditCell an alte Position
394 		pRefEdit->SetPosSizePixel(aOldEditPos, aOldEditSize);
395 
396         // set button position and image
397         if( pRefBtn )
398         {
399             pRefBtn->SetPosPixel( aOldButtonPos );
400             pRefBtn->SetStartImage();
401         }
402 
403 		// Alle anderen: Show();
404 		sal_uInt16 nChildren = m_pWindow->GetChildCount();
405 		for ( sal_uInt16 i = 0; i < nChildren; i++ )
406 			if (pHiddenMarks[i])
407 			{
408 				m_pWindow->GetChild(i)->GetWindow( WINDOW_CLIENT )->Show();
409 			}
410 		delete [] pHiddenMarks;
411 
412 		pRefEdit = NULL;
413         pRefBtn = NULL;
414 	}
415 }
416 // -----------------------------------------------------------------------------
417 void ScFormulaReferenceHelper::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
418 {
419 	if (!pRefEdit)
420 	{
421 		pRefEdit = pEdit;
422 		pRefBtn  = pButton;
423 
424 		// Neuen Fenstertitel basteln
425 		String sNewDialogText;
426 		sOldDialogText = m_pWindow->GetText();
427 		sNewDialogText  = sOldDialogText;
428 		sNewDialogText.AppendAscii(RTL_CONSTASCII_STRINGPARAM( ": " ));
429 
430 		// Alle Elemente ausser EditCell und Button verstecken
431 		sal_uInt16 nChildren = m_pWindow->GetChildCount();
432 		pHiddenMarks = new sal_Bool [nChildren];
433 		for (sal_uInt16 i = 0; i < nChildren; i++)
434 		{
435 			pHiddenMarks[i] = sal_False;
436 			Window* pWin = m_pWindow->GetChild(i);
437 			pWin = pWin->GetWindow( WINDOW_CLIENT );
438 			if (pWin == (Window*)pRefEdit)
439 			{
440 				sNewDialogText += m_pWindow->GetChild(i-1)->GetWindow( WINDOW_CLIENT )->GetText();
441 			}
442 			else if (pWin == (Window*)pRefBtn)
443 				;	// do nothing
444 			else if (pWin->IsVisible())
445 			{
446 				pHiddenMarks[i] = sal_True;
447 				pWin->Hide();
448 			}
449 		}
450 
451 		// Alte Daten merken
452 		aOldDialogSize = m_pWindow->GetOutputSizePixel();
453 		aOldEditPos = pRefEdit->GetPosPixel();
454 		aOldEditSize = pRefEdit->GetSizePixel();
455 		if (pRefBtn)
456 			aOldButtonPos = pRefBtn->GetPosPixel();
457 
458 		// Edit-Feld verschieben und anpassen
459 		Size aNewDlgSize(aOldDialogSize.Width(), aOldEditSize.Height());
460 		Size aNewEditSize(aNewDlgSize);
461         long nOffset = 0;
462 		if (pRefBtn)
463 		{
464 			aNewEditSize.Width() -= pRefBtn->GetSizePixel().Width();
465 			aNewEditSize.Width() -= aOldButtonPos.X() - (aOldEditPos.X()+aOldEditSize.Width());
466 
467             long nHeight = pRefBtn->GetSizePixel().Height();
468             if ( nHeight > aOldEditSize.Height() )
469             {
470                 aNewDlgSize.Height() = nHeight;
471                 nOffset = (nHeight-aOldEditSize.Height()) / 2;
472             }
473             aNewEditSize.Width() -= nOffset;
474 		}
475 		pRefEdit->SetPosSizePixel(Point(nOffset, nOffset), aNewEditSize);
476 
477         // set button position and image
478         if( pRefBtn )
479         {
480             pRefBtn->SetPosPixel( Point( aOldDialogSize.Width() - pRefBtn->GetSizePixel().Width(), 0 ) );
481             pRefBtn->SetEndImage();
482         }
483 
484 		// Fenster verkleinern
485 		m_pWindow->SetOutputSizePixel(aNewDlgSize);
486 
487 		// Fenstertitel anpassen
488 		m_pWindow->SetText( MnemonicGenerator::EraseAllMnemonicChars( sNewDialogText ) );
489 
490 //        if ( pButton )      // ueber den Button: Enter und Escape abfangen
491 //        {
492 			if (!pAccel.get())
493 			{
494 				pAccel.reset( new Accelerator );
495 				pAccel->InsertItem( 1, KeyCode( KEY_RETURN ) );
496 				pAccel->InsertItem( 2, KeyCode( KEY_ESCAPE ) );
497 				pAccel->SetSelectHdl( LINK( this, ScFormulaReferenceHelper, AccelSelectHdl ) );
498 			}
499 			Application::InsertAccel( pAccel.get() );
500 			bAccInserted = sal_True;
501 //        }
502 	}
503 }
504 // -----------------------------------------------------------------------------
505 void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
506 {
507     if( pEdit )
508     {
509         if( pRefEdit == pEdit )                 // is this the active ref edit field?
510         {
511             pRefEdit->GrabFocus();              // before RefInputDone()
512             m_pDlg->RefInputDone( sal_True );               // finish ref input
513         }
514         else
515         {
516             m_pDlg->RefInputDone( sal_True );               // another active ref edit?
517             m_pDlg->RefInputStart( pEdit, pButton );    // start ref input
518             // pRefEdit might differ from pEdit after RefInputStart() (i.e. ScFormulaDlg)
519             if( pRefEdit )
520                 pRefEdit->GrabFocus();
521         }
522     }
523 }
524 // -----------------------------------------------------------------------------
525 sal_Bool ScFormulaReferenceHelper::DoClose( sal_uInt16 nId )
526 {
527 	SfxApplication* pSfxApp = SFX_APP();
528 
529 	SetDispatcherLock( sal_False );			//! here and in dtor ?
530 
531 	SfxViewFrame* pViewFrm = SfxViewFrame::Current();
532 	if ( pViewFrm && pViewFrm->HasChildWindow(FID_INPUTLINE_STATUS) )
533 	{
534 		//	Die Eingabezeile wird per ToolBox::Disable disabled, muss darum auch
535 		//	per ToolBox::Enable wieder aktiviert werden (vor dem Enable des AppWindow),
536 		//	damit die Buttons auch wieder enabled gezeichnet werden.
537 		SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_INPUTLINE_STATUS);
538 		if (pChild)
539 		{
540 			ScInputWindow* pWin = (ScInputWindow*)pChild->GetWindow();
541 			pWin->Enable();
542 		}
543 	}
544 
545 	// find parent view frame to close dialog
546 	SfxViewFrame* pMyViewFrm = NULL;
547 	if ( m_pBindings )
548 	{
549 		SfxDispatcher* pMyDisp = m_pBindings->GetDispatcher();
550 		if (pMyDisp)
551 			pMyViewFrm = pMyDisp->GetFrame();
552 	}
553 	SC_MOD()->SetRefDialog( nId, sal_False, pMyViewFrm );
554 
555 	pSfxApp->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );
556 
557     ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
558 	if ( pScViewShell )
559 		pScViewShell->UpdateInputHandler(sal_True);
560 
561 	return sal_True;
562 }
563 void ScFormulaReferenceHelper::SetDispatcherLock( sal_Bool bLock )
564 {
565 	//	lock / unlock only the dispatchers of Calc documents
566 
567 	TypeId aType(TYPE(ScDocShell));
568 	ScDocShell* pDocShell = (ScDocShell*)SfxObjectShell::GetFirst(&aType);
569 	while( pDocShell )
570 	{
571 		SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
572 		while( pFrame )
573 		{
574 			SfxDispatcher* pDisp = pFrame->GetDispatcher();
575 			if (pDisp)
576 				pDisp->Lock( bLock );
577 
578 			pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
579 		}
580 		pDocShell = (ScDocShell*)SfxObjectShell::GetNext(*pDocShell, &aType);
581 	}
582 
583 	//	if a new view is created while the dialog is open,
584 	//	that view's dispatcher is locked when trying to create the dialog
585 	//	for that view (ScTabViewShell::CreateRefDialog)
586 }
587 // -----------------------------------------------------------------------------
588 void ScFormulaReferenceHelper::ViewShellChanged(ScTabViewShell* /* pScViewShell */)
589 {
590 	enableInput( sal_False );
591 
592 	EnableSpreadsheets();
593 }
594 void ScFormulaReferenceHelper::EnableSpreadsheets(sal_Bool bFlag, sal_Bool bChilds)
595 {
596 	TypeId aType(TYPE(ScDocShell));
597 	ScDocShell* pDocShell = (ScDocShell*)SfxObjectShell::GetFirst(&aType);
598 	while( pDocShell )
599 	{
600 		SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
601 		while( pFrame )
602 		{
603 			//	#71577# enable everything except InPlace, including bean frames
604             if ( !pFrame->GetFrame().IsInPlace() )
605 			{
606 				SfxViewShell* p = pFrame->GetViewShell();
607 				ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
608 				if(pViewSh!=NULL)
609 				{
610 					Window *pWin=pViewSh->GetWindow();
611 					if(pWin)
612 					{
613 						Window *pParent=pWin->GetParent();
614 						if(pParent)
615 						{
616 							pParent->EnableInput(bFlag,sal_False);
617 							if(bChilds)
618 								pViewSh->EnableRefInput(bFlag);
619 						}
620 					}
621 				}
622 			}
623 			pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
624 		}
625 
626 		pDocShell = (ScDocShell*)SfxObjectShell::GetNext(*pDocShell, &aType);
627 	}
628 }
629 
630 //----------------------------------------------------------------------------
631 
632 
633 
634 void lcl_InvalidateWindows()
635 {
636 	TypeId aType(TYPE(ScDocShell));
637 	ScDocShell* pDocShell = (ScDocShell*)SfxObjectShell::GetFirst(&aType);
638 	while( pDocShell )
639 	{
640 		SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
641 		while( pFrame )
642 		{
643 			//	#71577# enable everything except InPlace, including bean frames
644             if ( !pFrame->GetFrame().IsInPlace() )
645 			{
646 				SfxViewShell* p = pFrame->GetViewShell();
647 				ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
648 				if(pViewSh!=NULL)
649 				{
650 					Window *pWin=pViewSh->GetWindow();
651 					if(pWin)
652 					{
653 						Window *pParent=pWin->GetParent();
654 						if(pParent)
655 							pParent->Invalidate();
656 					}
657 				}
658 			}
659 			pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
660 		}
661 
662 		pDocShell = (ScDocShell*)SfxObjectShell::GetNext(*pDocShell, &aType);
663 	}
664 }
665 //----------------------------------------------------------------------------
666 
667 void lcl_HideAllReferences()
668 {
669 	TypeId aScType = TYPE(ScTabViewShell);
670 	SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
671 	while ( pSh )
672 	{
673 		((ScTabViewShell*)pSh)->ClearHighlightRanges();
674 		pSh = SfxViewShell::GetNext( *pSh, &aScType );
675 	}
676 }
677 
678 //============================================================================
679 //The class of ScAnyRefDlg is rewritten by PengYunQuan for Validity Cell Range Picker
680 //	class ScRefHandler
681 //----------------------------------------------------------------------------
682 
683 ScRefHandler::ScRefHandler( Window &rWindow, SfxBindings* pB/*, SfxChildWindow* pCW,
684 						  Window* pParent, sal_uInt16 nResId*/, bool bBindRef )
685 	:	//SfxModelessDialog ( pB, pCW, pParent, ScResId( nResId ) ),
686 		m_rWindow( rWindow ),
687 		m_bInRefMode( false ),
688         m_aHelper(this,pB),
689 		pMyBindings( pB ),
690         pActiveWin(NULL)
691 {
692 	m_aHelper.SetWindow(/*this*/&m_rWindow);
693 	if(m_rWindow.GetHelpId().getLength()==0)				//Hack, da im SfxModelessDialog die HelpId
694 		m_rWindow.SetHelpId(m_rWindow.GetUniqueId());	//fuer einen ModelessDialog entfernt und
695 									//in eine UniqueId gewandelt wird, machen
696 									//wir das an dieser Stelle rueckgaengig.
697 	aTimer.SetTimeout(200);
698 	aTimer.SetTimeoutHdl(LINK( this, ScRefHandler, UpdateFocusHdl));
699 
700 	if( bBindRef ) EnterRefMode();
701 }
702 
703 bool ScRefHandler::EnterRefMode()
704 {
705 	if( m_bInRefMode ) return false;
706 
707 	SC_MOD()->InputEnterHandler();
708 //    ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
709 
710     ScTabViewShell* pScViewShell = NULL;
711 
712 	// title has to be from the view that opened the dialog,
713 	// even if it's not the current view
714 
715 	SfxObjectShell* pParentDoc = NULL;
716 	if ( pMyBindings )
717 	{
718 		SfxDispatcher* pMyDisp = pMyBindings->GetDispatcher();
719 		if (pMyDisp)
720 		{
721 			SfxViewFrame* pMyViewFrm = pMyDisp->GetFrame();
722 			if (pMyViewFrm)
723             {
724                 pScViewShell = PTR_CAST( ScTabViewShell, pMyViewFrm->GetViewShell() );
725                 if( pScViewShell )
726 		            pScViewShell->UpdateInputHandler(sal_True);
727 				pParentDoc = pMyViewFrm->GetObjectShell();
728             }
729 		}
730 	}
731 	if ( !pParentDoc && pScViewShell )					// use current only if above fails
732 		pParentDoc = pScViewShell->GetObjectShell();
733 	if ( pParentDoc )
734 		aDocName = pParentDoc->GetTitle();
735 
736     ScInputHandler*	pInputHdl = SC_MOD()->GetInputHdl(pScViewShell);
737 
738 	DBG_ASSERT( pInputHdl, "Missing input handler :-/" );
739 
740 	if ( pInputHdl )
741 		pInputHdl->NotifyChange( NULL );
742 
743 	m_aHelper.enableInput( sal_False );
744 
745 	m_aHelper.EnableSpreadsheets();
746 
747     m_aHelper.Init();
748 
749 	m_aHelper.SetDispatcherLock( sal_True );
750 	//@Test
751 	//SFX_APPWINDOW->Disable(sal_True);	  //@BugID 54702
752 
753 	return m_bInRefMode = true;
754 }
755 
756 //----------------------------------------------------------------------------
757 
758 ScRefHandler::~ScRefHandler()
759 {
760 	LeaveRefMode();
761 }
762 
763 bool ScRefHandler::LeaveRefMode()
764 {
765 	if( !m_bInRefMode ) return false;
766 
767 	lcl_HideAllReferences();
768 
769 	if( Dialog *pDlg = dynamic_cast<Dialog*>( static_cast<Window*>(*this) ) )
770 		pDlg->SetModalInputMode(sal_False);
771 	SetDispatcherLock( sal_False );			//! here and in DoClose ?
772 
773     ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
774     if( pScViewShell )
775 		pScViewShell->UpdateInputHandler(sal_True);
776 
777 	//SFX_APPWINDOW->Enable(sal_True,sal_True);
778 	lcl_InvalidateWindows();
779 
780 	m_bInRefMode = false;
781 	return true;
782 }
783 
784 //----------------------------------------------------------------------------
785 
786 //SfxBindings& ScRefHandler::GetBindings()
787 //{
788 //	//!	SfxModelessDialog should allow access to pBindings pointer
789 //
790 //	return *pMyBindings;
791 //}
792 
793 //----------------------------------------------------------------------------
794 
795 void ScRefHandler::SwitchToDocument()
796 {
797 	ScTabViewShell* pCurrent = ScTabViewShell::GetActiveViewShell();
798 	if (pCurrent)
799 	{
800 		SfxObjectShell* pObjSh = pCurrent->GetObjectShell();
801 		if ( pObjSh && pObjSh->GetTitle() == aDocName )
802 		{
803 			//	right document already visible -> nothing to do
804 			return;
805 		}
806 	}
807 
808 	TypeId aScType = TYPE(ScTabViewShell);
809 	SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
810 	while ( pSh )
811 	{
812 		SfxObjectShell* pObjSh = pSh->GetObjectShell();
813 		if ( pObjSh && pObjSh->GetTitle() == aDocName )
814 		{
815 			//	switch to first TabViewShell for document
816 			((ScTabViewShell*)pSh)->SetActive();
817 			return;
818 		}
819 		pSh = SfxViewShell::GetNext( *pSh, &aScType );
820 	}
821 }
822 
823 //----------------------------------------------------------------------------
824 
825 sal_Bool ScRefHandler::IsDocAllowed(SfxObjectShell* pDocSh) const	// pDocSh may be 0
826 {
827 	//	default: allow only same document (overridden in function dialog)
828 	String aCmpName;
829 	if ( pDocSh )
830 		aCmpName = pDocSh->GetTitle();
831 
832 	//	if aDocName isn't initialized, allow
833 	return ( aDocName.Len() == 0 || aDocName == aCmpName );
834 }
835 
836 //----------------------------------------------------------------------------
837 
838 sal_Bool __EXPORT ScRefHandler::IsRefInputMode() const
839 {
840 	return m_rWindow.IsVisible(); // nur wer sichtbar ist kann auch Referenzen bekommen
841 }
842 
843 //----------------------------------------------------------------------------
844 
845 sal_Bool __EXPORT ScRefHandler::DoClose( sal_uInt16 nId )
846 {
847     m_aHelper.DoClose(nId);
848 	return sal_True;
849 }
850 
851 void ScRefHandler::SetDispatcherLock( sal_Bool bLock )
852 {
853 	m_aHelper.SetDispatcherLock( bLock );
854 }
855 
856 //----------------------------------------------------------------------------
857 
858 void ScRefHandler::ViewShellChanged(ScTabViewShell*  pScViewShell )
859 {
860 	m_aHelper.ViewShellChanged(pScViewShell);
861 }
862 
863 //----------------------------------------------------------------------------
864 
865 void ScRefHandler::AddRefEntry()
866 {
867 	//	wenn nicht ueberladen, gibt es keine Mehrfach-Referenzen
868 }
869 
870 //----------------------------------------------------------------------------
871 
872 sal_Bool __EXPORT ScRefHandler::IsTableLocked() const
873 {
874 	// per Default kann bei Referenzeingabe auch die Tabelle umgeschaltet werden
875 
876 	return sal_False;
877 }
878 
879 //----------------------------------------------------------------------------
880 //
881 //	RefInputStart/Done: Zoom-In (AutoHide) auf einzelnes Feld
882 //	(per Button oder Bewegung)
883 //
884 //----------------------------------------------------------------------------
885 
886 void ScRefHandler::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
887 {
888     m_aHelper.RefInputStart( pEdit, pButton );
889 }
890 
891 
892 void ScRefHandler::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
893 {
894     m_aHelper.ToggleCollapsed( pEdit, pButton );
895 }
896 
897 //The two following function is commentted out by PengYunQuan for Validity Cell Range Picker
898 //long ScAnyRefDlg::PreNotify( NotifyEvent& rNEvt )
899 //{
900 //	sal_uInt16 nSwitch=rNEvt.GetType();
901 //	if(nSwitch==EVENT_GETFOCUS)
902 //	{
903 //		pActiveWin=rNEvt.GetWindow();
904 //	}
905 //	return SfxModelessDialog::PreNotify(rNEvt);
906 //}
907 //
908 //void ScAnyRefDlg::StateChanged( StateChangedType nStateChange )
909 //{
910 //	SfxModelessDialog::StateChanged( nStateChange );
911 //
912 //	if(nStateChange == STATE_CHANGE_VISIBLE)
913 //	{
914 //		if(IsVisible())
915 //		{
916 //			m_aHelper.enableInput( sal_False );
917 //			m_aHelper.EnableSpreadsheets();
918 //			m_aHelper.SetDispatcherLock( sal_True );
919 //			aTimer.Start();
920 //		}
921 //		else
922 //		{
923 //			m_aHelper.enableInput( sal_True );
924 //			m_aHelper.SetDispatcherLock( sal_False );			//! here and in DoClose ?
925 //		}
926 //	}
927 //}
928 
929 #if defined( _MSC_VER )
930 #define INTRODUCE_TEMPLATE
931 #else
932 #define INTRODUCE_TEMPLATE	template <>
933 #endif
934 
935 #define IMPL_TWINDOW_PRENOTIFY( TWindow,bBindRef )	\
936 INTRODUCE_TEMPLATE long ScRefHdlrImplBase<TWindow,bBindRef>::PreNotify( NotifyEvent& rNEvt )\
937 {\
938 	if( bBindRef || m_bInRefMode )\
939 	{\
940 		sal_uInt16 nSwitch=rNEvt.GetType();\
941 		if(nSwitch==EVENT_GETFOCUS)\
942 		{\
943 			pActiveWin=rNEvt.GetWindow();\
944 		}\
945 	}\
946 	return TWindow::PreNotify(rNEvt);\
947 }
948 
949 #define IMPL_TWINDOW_STATECHANGED( TWindow,bBindRef )	\
950 INTRODUCE_TEMPLATE void ScRefHdlrImplBase<TWindow,bBindRef>::StateChanged( StateChangedType nStateChange )\
951 {\
952 	TWindow::StateChanged( nStateChange );\
953 \
954 	if( !bBindRef && !m_bInRefMode ) return;\
955 	\
956 	if(nStateChange == STATE_CHANGE_VISIBLE)\
957 	{\
958 		if(m_rWindow.IsVisible())\
959 		{\
960 			m_aHelper.enableInput( sal_False );\
961 			m_aHelper.EnableSpreadsheets();\
962 			m_aHelper.SetDispatcherLock( sal_True );\
963 			aTimer.Start();\
964 		}\
965 		else\
966 		{\
967 			m_aHelper.enableInput( sal_True );\
968 			m_aHelper.SetDispatcherLock( sal_False );			/*//! here and in DoClose ?*/\
969 		}\
970 	}\
971 }
972 
973 IMPL_TWINDOW_PRENOTIFY( SfxModelessDialog, true )
974 IMPL_TWINDOW_PRENOTIFY( SfxTabDialog, false )
975 IMPL_TWINDOW_STATECHANGED( SfxModelessDialog, true )
976 IMPL_TWINDOW_STATECHANGED( SfxTabDialog, false )
977 
978 IMPL_LINK( ScRefHandler, UpdateFocusHdl, Timer*, EMPTYARG )
979 {
980 	if (pActiveWin)
981 	{
982 		pActiveWin->GrabFocus();
983 	}
984 	return 0;
985 }
986 // -----------------------------------------------------------------------------
987 bool ScRefHandler::ParseWithNames( ScRangeList& rRanges, const String& rStr, ScDocument* pDoc )
988 {
989     return m_aHelper.ParseWithNames( rRanges, rStr, pDoc );
990 }
991 // -----------------------------------------------------------------------------
992 void ScRefHandler::HideReference( sal_Bool bDoneRefMode )
993 {
994     m_aHelper.HideReference( bDoneRefMode );
995 }
996 // -----------------------------------------------------------------------------
997 void ScRefHandler::ShowReference( const XubString& rStr )
998 {
999     m_aHelper.ShowReference( rStr );
1000 }
1001 // -----------------------------------------------------------------------------
1002 void ScRefHandler::ReleaseFocus( formula::RefEdit* pEdit, formula::RefButton* pButton )
1003 {
1004     m_aHelper.ReleaseFocus( pEdit,pButton );
1005 }
1006 //----------------------------------------------------------------------------
1007 void ScRefHandler::RefInputDone( sal_Bool bForced )
1008 {
1009     m_aHelper.RefInputDone( bForced );
1010 }
1011 
1012