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