Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "rangelst.hxx"
21 : #include <comphelper/string.hxx>
22 : #include <sfx2/app.hxx>
23 : #include <sfx2/viewsh.hxx>
24 : #include <vcl/wrkwin.hxx>
25 : #include <vcl/mnemonic.hxx>
26 : #include <sfx2/bindings.hxx>
27 : #include <sfx2/dispatch.hxx>
28 :
29 : #include "anyrefdg.hxx"
30 : #include "sc.hrc"
31 : #include "inputhdl.hxx"
32 : #include "scmod.hxx"
33 : #include "scresid.hxx"
34 : #include "inputwin.hxx"
35 : #include "tabvwsh.hxx"
36 : #include "docsh.hxx"
37 : #include "rfindlst.hxx"
38 : #include "compiler.hxx"
39 : #include "formulacell.hxx"
40 : #include "global.hxx"
41 : #include "inputopt.hxx"
42 : #include "rangeutl.hxx"
43 : #include "tokenarray.hxx"
44 :
45 : #include <boost/scoped_ptr.hpp>
46 :
47 0 : ScFormulaReferenceHelper::ScFormulaReferenceHelper(IAnyRefDialog* _pDlg,SfxBindings* _pBindings)
48 : : m_pDlg(_pDlg)
49 : , pRefEdit (NULL)
50 : , pRefBtn (NULL)
51 : , m_pWindow(NULL)
52 : , m_pBindings(_pBindings)
53 : , m_nOldBorderWidth (0)
54 : , nRefTab(0)
55 : , mnOldEditWidthReq( -1 )
56 : , mpOldEditParent( NULL )
57 : , mbOldDlgLayoutEnabled( false )
58 : , mbOldEditParentLayoutEnabled( false )
59 : , bHighlightRef( false )
60 0 : , bAccInserted( false )
61 : {
62 0 : ScInputOptions aInputOption=SC_MOD()->GetInputOptions();
63 0 : bEnableColorRef=aInputOption.GetRangeFinder();
64 0 : }
65 :
66 0 : ScFormulaReferenceHelper::~ScFormulaReferenceHelper()
67 : {
68 0 : if (bAccInserted)
69 0 : Application::RemoveAccel( pAccel.get() );
70 :
71 : // common cleanup for ScAnyRefDlg and ScFormulaDlg is done here
72 :
73 0 : HideReference();
74 0 : enableInput( true );
75 :
76 0 : ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
77 0 : if ( pInputHdl )
78 0 : pInputHdl->ResetDelayTimer(); // stop the timer for disabling the input line
79 0 : }
80 :
81 0 : void ScFormulaReferenceHelper::enableInput( bool bEnable )
82 : {
83 0 : TypeId aType(TYPE(ScDocShell));
84 0 : ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType));
85 0 : while( pDocShell )
86 : {
87 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
88 0 : while( pFrame )
89 : {
90 : // enable everything except InPlace, including bean frames
91 0 : if ( !pFrame->GetFrame().IsInPlace() )
92 : {
93 0 : SfxViewShell* p = pFrame->GetViewShell();
94 0 : ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
95 0 : if(pViewSh!=NULL)
96 : {
97 0 : vcl::Window *pWin=pViewSh->GetWindow();
98 0 : if(pWin)
99 : {
100 0 : vcl::Window *pParent=pWin->GetParent();
101 0 : if(pParent)
102 : {
103 0 : pParent->EnableInput(bEnable,true);
104 : if(true)
105 0 : pViewSh->EnableRefInput(bEnable);
106 : }
107 : }
108 : }
109 : }
110 0 : pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
111 : }
112 :
113 0 : pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, &aType));
114 : }
115 0 : }
116 :
117 0 : void ScFormulaReferenceHelper::ShowSimpleReference(const OUString& rStr)
118 : {
119 0 : if( bEnableColorRef )
120 : {
121 0 : bHighlightRef=true;
122 0 : ScViewData* pViewData=ScDocShell::GetViewData();
123 0 : if ( pViewData )
124 : {
125 0 : ScDocument* pDoc=pViewData->GetDocument();
126 0 : ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
127 :
128 0 : ScRangeList aRangeList;
129 :
130 0 : pTabViewShell->DoneRefMode( false );
131 0 : pTabViewShell->ClearHighlightRanges();
132 :
133 0 : if( ParseWithNames( aRangeList, rStr, pDoc ) )
134 : {
135 0 : for ( size_t i = 0, nRanges = aRangeList.size(); i < nRanges; ++i )
136 : {
137 0 : ScRange* pRangeEntry = aRangeList[ i ];
138 0 : ColorData aColName = ScRangeFindList::GetColorName( i );
139 0 : pTabViewShell->AddHighlightRange( *pRangeEntry, aColName );
140 : }
141 0 : }
142 : }
143 : }
144 0 : }
145 :
146 0 : bool ScFormulaReferenceHelper::ParseWithNames( ScRangeList& rRanges, const OUString& rStr, ScDocument* pDoc )
147 : {
148 0 : bool bError = false;
149 0 : rRanges.RemoveAll();
150 :
151 0 : ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0);
152 0 : ScRangeUtil aRangeUtil;
153 0 : sal_Int32 nTokenCnt = comphelper::string::getTokenCount(rStr, ';');
154 0 : for( sal_Int32 nToken = 0; nToken < nTokenCnt; ++nToken )
155 : {
156 0 : ScRange aRange;
157 0 : OUString aRangeStr( rStr.getToken( nToken, ';' ) );
158 :
159 0 : sal_uInt16 nFlags = aRange.ParseAny( aRangeStr, pDoc, aDetails );
160 0 : if ( nFlags & SCA_VALID )
161 : {
162 0 : if ( (nFlags & SCA_TAB_3D) == 0 )
163 0 : aRange.aStart.SetTab( nRefTab );
164 0 : if ( (nFlags & SCA_TAB2_3D) == 0 )
165 0 : aRange.aEnd.SetTab( aRange.aStart.Tab() );
166 0 : rRanges.Append( aRange );
167 : }
168 0 : else if ( ScRangeUtil::MakeRangeFromName( aRangeStr, pDoc, nRefTab, aRange, RUTL_NAMES, aDetails ) )
169 0 : rRanges.Append( aRange );
170 : else
171 0 : bError = true;
172 0 : }
173 :
174 0 : return !bError;
175 : }
176 :
177 0 : void ScFormulaReferenceHelper::ShowFormulaReference(const OUString& rStr)
178 : {
179 0 : if( bEnableColorRef)
180 : {
181 0 : bHighlightRef=true;
182 0 : ScViewData* pViewData=ScDocShell::GetViewData();
183 0 : if ( pViewData && pRefComp.get() )
184 : {
185 0 : ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
186 0 : SCCOL nCol = pViewData->GetCurX();
187 0 : SCROW nRow = pViewData->GetCurY();
188 0 : SCTAB nTab = pViewData->GetTabNo();
189 0 : ScAddress aPos( nCol, nRow, nTab );
190 :
191 0 : boost::scoped_ptr<ScTokenArray> pScTokA(pRefComp->CompileString(rStr));
192 :
193 0 : if (pTabViewShell && pScTokA)
194 : {
195 0 : pTabViewShell->DoneRefMode( false );
196 0 : pTabViewShell->ClearHighlightRanges();
197 :
198 0 : pScTokA->Reset();
199 0 : const formula::FormulaToken* pToken = pScTokA->GetNextReference();
200 :
201 0 : sal_uInt16 nIndex=0;
202 :
203 0 : while(pToken!=NULL)
204 : {
205 0 : bool bDoubleRef=(pToken->GetType()==formula::svDoubleRef);
206 :
207 0 : if(pToken->GetType()==formula::svSingleRef || bDoubleRef)
208 : {
209 0 : ScRange aRange;
210 0 : if(bDoubleRef)
211 : {
212 0 : ScComplexRefData aRef( *pToken->GetDoubleRef() );
213 0 : aRange = aRef.toAbs(aPos);
214 : }
215 : else
216 : {
217 0 : ScSingleRefData aRef( *pToken->GetSingleRef() );
218 0 : aRange.aStart = aRef.toAbs(aPos);
219 0 : aRange.aEnd = aRange.aStart;
220 : }
221 0 : ColorData aColName=ScRangeFindList::GetColorName(nIndex++);
222 0 : pTabViewShell->AddHighlightRange(aRange, aColName);
223 : }
224 :
225 0 : pToken = pScTokA->GetNextReference();
226 : }
227 0 : }
228 : }
229 : }
230 0 : }
231 :
232 0 : void ScFormulaReferenceHelper::HideReference( bool bDoneRefMode )
233 : {
234 0 : ScViewData* pViewData=ScDocShell::GetViewData();
235 :
236 0 : if( pViewData && bHighlightRef && bEnableColorRef)
237 : {
238 0 : ScTabViewShell* pTabViewShell=pViewData->GetViewShell();
239 :
240 0 : if(pTabViewShell!=NULL)
241 : {
242 : // bDoneRefMode is sal_False when called from before SetReference.
243 : // In that case, RefMode was just started and must not be ended now.
244 :
245 0 : if ( bDoneRefMode )
246 0 : pTabViewShell->DoneRefMode( false );
247 0 : pTabViewShell->ClearHighlightRanges();
248 : }
249 0 : bHighlightRef=false;
250 : }
251 0 : }
252 :
253 0 : void ScFormulaReferenceHelper::ShowReference(const OUString& rStr)
254 : {
255 0 : if( bEnableColorRef )
256 : {
257 0 : if( rStr.indexOf('(') != -1 ||
258 0 : rStr.indexOf('+') != -1 ||
259 0 : rStr.indexOf('*') != -1 ||
260 0 : rStr.indexOf('-') != -1 ||
261 0 : rStr.indexOf('/') != -1 ||
262 0 : rStr.indexOf('&') != -1 ||
263 0 : rStr.indexOf('<') != -1 ||
264 0 : rStr.indexOf('>') != -1 ||
265 0 : rStr.indexOf('=') != -1 ||
266 0 : rStr.indexOf('^') != -1 )
267 : {
268 0 : ShowFormulaReference(rStr);
269 : }
270 : else
271 : {
272 0 : ShowSimpleReference(rStr);
273 : }
274 : }
275 0 : }
276 :
277 0 : void ScFormulaReferenceHelper::ReleaseFocus( formula::RefEdit* pEdit, formula::RefButton* pButton )
278 : {
279 0 : if( !pRefEdit && pEdit )
280 : {
281 0 : m_pDlg->RefInputStart( pEdit, pButton );
282 : }
283 :
284 0 : ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
285 0 : if( pViewShell )
286 : {
287 0 : pViewShell->ActiveGrabFocus();
288 0 : if( pRefEdit )
289 : {
290 0 : const ScViewData& rViewData = pViewShell->GetViewData();
291 0 : ScDocument* pDoc = rViewData.GetDocument();
292 0 : ScRangeList aRangeList;
293 0 : if( ParseWithNames( aRangeList, pRefEdit->GetText(), pDoc ) )
294 : {
295 0 : if ( !aRangeList.empty() )
296 : {
297 0 : const ScRange* pRange = aRangeList.front();
298 0 : pViewShell->SetTabNo( pRange->aStart.Tab() );
299 0 : pViewShell->MoveCursorAbs( pRange->aStart.Col(),
300 0 : pRange->aStart.Row(), SC_FOLLOW_JUMP, false, false );
301 0 : pViewShell->MoveCursorAbs( pRange->aEnd.Col(),
302 0 : pRange->aEnd.Row(), SC_FOLLOW_JUMP, true, false );
303 0 : m_pDlg->SetReference( *pRange, pDoc );
304 : }
305 0 : }
306 : }
307 : }
308 0 : }
309 :
310 0 : void ScFormulaReferenceHelper::Init()
311 : {
312 0 : ScViewData* pViewData=ScDocShell::GetViewData(); //! use pScViewShell?
313 0 : if ( pViewData )
314 : {
315 0 : ScDocument* pDoc = pViewData->GetDocument();
316 0 : SCCOL nCol = pViewData->GetCurX();
317 0 : SCROW nRow = pViewData->GetCurY();
318 0 : SCTAB nTab = pViewData->GetTabNo();
319 0 : ScAddress aCursorPos( nCol, nRow, nTab );
320 :
321 0 : pRefComp.reset( new ScCompiler( pDoc, aCursorPos) );
322 0 : pRefComp->SetGrammar( pDoc->GetGrammar() );
323 0 : pRefComp->EnableJumpCommandReorder(false);
324 0 : pRefComp->EnableStopOnError(false);
325 :
326 0 : nRefTab = nTab;
327 : }
328 0 : }
329 :
330 0 : IMPL_LINK( ScFormulaReferenceHelper, AccelSelectHdl, Accelerator *, pSelAccel )
331 : {
332 0 : if ( !pSelAccel )
333 0 : return long(false);
334 :
335 0 : switch ( pSelAccel->GetCurKeyCode().GetCode() )
336 : {
337 : case KEY_RETURN:
338 : case KEY_ESCAPE:
339 0 : if( pRefEdit )
340 0 : pRefEdit->GrabFocus();
341 0 : m_pDlg->RefInputDone( true );
342 0 : break;
343 : }
344 0 : return long(true);
345 : }
346 :
347 0 : void ScFormulaReferenceHelper::RefInputDone( bool bForced )
348 : {
349 0 : if ( CanInputDone( bForced ) )
350 : {
351 0 : if (bAccInserted) // disable accelerator
352 : {
353 0 : Application::RemoveAccel( pAccel.get() );
354 0 : bAccInserted = false;
355 : }
356 :
357 : //get rid of all this junk when we can
358 0 : if (!mbOldDlgLayoutEnabled)
359 : {
360 0 : m_pWindow->SetOutputSizePixel(aOldDialogSize);
361 :
362 : // restore the parent of the edit field
363 0 : pRefEdit->SetParent(mpOldEditParent);
364 :
365 : // the window is at the old size again
366 0 : m_pWindow->SetOutputSizePixel(aOldDialogSize);
367 :
368 : // set button parent
369 0 : if( pRefBtn )
370 : {
371 0 : pRefBtn->SetParent(m_pWindow);
372 : }
373 : }
374 :
375 0 : if (!mbOldEditParentLayoutEnabled)
376 : {
377 : // set pEditCell to old position
378 0 : pRefEdit->SetPosSizePixel(aOldEditPos, aOldEditSize);
379 :
380 : // set button position
381 0 : if( pRefBtn )
382 : {
383 0 : pRefBtn->SetPosPixel( aOldButtonPos );
384 : }
385 : }
386 :
387 : // Adjust window title
388 0 : m_pWindow->SetText(sOldDialogText);
389 :
390 : // set button image
391 0 : if( pRefBtn )
392 0 : pRefBtn->SetStartImage();
393 :
394 : // All others: Show();
395 0 : for (auto aI = m_aHiddenWidgets.begin(); aI != m_aHiddenWidgets.end(); ++aI)
396 : {
397 0 : vcl::Window *pWindow = *aI;
398 0 : pWindow->Show();
399 : }
400 0 : m_aHiddenWidgets.clear();
401 :
402 0 : if (mbOldDlgLayoutEnabled)
403 : {
404 0 : pRefEdit->set_width_request(mnOldEditWidthReq);
405 0 : Dialog* pResizeDialog = pRefEdit->GetParentDialog();
406 0 : pResizeDialog->set_border_width(m_nOldBorderWidth);
407 0 : if (vcl::Window *pActionArea = pResizeDialog->get_action_area())
408 0 : pActionArea->Show();
409 0 : pResizeDialog->setOptimalLayoutSize();
410 : }
411 :
412 0 : pRefEdit = NULL;
413 0 : pRefBtn = NULL;
414 : }
415 0 : }
416 :
417 : typedef std::set<VclPtr<vcl::Window> > winset;
418 :
419 : namespace
420 : {
421 0 : void hideUnless(vcl::Window *pTop, const winset& rVisibleWidgets,
422 : std::vector<VclPtr<vcl::Window> > &rWasVisibleWidgets)
423 : {
424 0 : for (vcl::Window* pChild = pTop->GetWindow(GetWindowType::FirstChild); pChild;
425 : pChild = pChild->GetWindow(GetWindowType::Next))
426 : {
427 0 : if (!pChild->IsVisible())
428 0 : continue;
429 0 : if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
430 : {
431 0 : rWasVisibleWidgets.push_back(pChild);
432 0 : pChild->Hide();
433 : }
434 0 : else if (isContainerWindow(pChild))
435 : {
436 0 : hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets);
437 : }
438 : }
439 0 : }
440 : }
441 :
442 0 : void ScFormulaReferenceHelper::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
443 : {
444 0 : if (!pRefEdit)
445 : {
446 0 : pRefEdit = pEdit;
447 0 : pRefBtn = pButton;
448 :
449 0 : mbOldDlgLayoutEnabled = isLayoutEnabled(m_pWindow);
450 0 : aOldEditSize = pRefEdit->GetSizePixel();
451 0 : mnOldEditWidthReq = pRefEdit->get_width_request();
452 0 : mpOldEditParent = pRefEdit->GetParent();
453 0 : mbOldEditParentLayoutEnabled = isContainerWindow(mpOldEditParent);
454 :
455 : //get rid of all the !mbOldDlgLayoutEnabled and
456 : //mbOldEditParentLayoutEnabled junk when we can after the last user of
457 : //this is widget-layout-ified
458 0 : if (!mbOldEditParentLayoutEnabled)
459 : {
460 : // Save current state
461 0 : aOldDialogSize = m_pWindow->GetOutputSizePixel();
462 0 : aOldEditPos = pRefEdit->GetPosPixel();
463 0 : if (pRefBtn)
464 0 : aOldButtonPos = pRefBtn->GetPosPixel();
465 : }
466 :
467 0 : if (!mbOldDlgLayoutEnabled)
468 : {
469 0 : pRefEdit->SetParent(m_pWindow);
470 0 : if(pRefBtn)
471 0 : pRefBtn->SetParent(m_pWindow);
472 : }
473 :
474 : // Save and adjust window title
475 0 : sOldDialogText = m_pWindow->GetText();
476 0 : if (vcl::Window *pLabel = pRefEdit->GetLabelWidgetForShrinkMode())
477 : {
478 0 : OUString sLabel = pLabel->GetText();
479 0 : if (!sLabel.isEmpty())
480 : {
481 0 : OUString sNewDialogText = sOldDialogText;
482 0 : sNewDialogText += ": ";
483 0 : sNewDialogText += comphelper::string::stripEnd(sLabel, ':');
484 0 : m_pWindow->SetText( MnemonicGenerator::EraseAllMnemonicChars( sNewDialogText ) );
485 0 : }
486 : }
487 :
488 0 : Dialog* pResizeDialog = NULL;
489 :
490 0 : if (!mbOldDlgLayoutEnabled)
491 : {
492 0 : for (vcl::Window* pChild = m_pWindow->GetWindow(GetWindowType::FirstChild); pChild;
493 : pChild = pChild->GetWindow(GetWindowType::Next))
494 : {
495 0 : vcl::Window *pWin = pChild->GetWindow(GetWindowType::Client);
496 0 : if (pWin == static_cast<vcl::Window*>(pRefEdit) || pWin == static_cast<vcl::Window*>(pRefBtn))
497 0 : continue; // do nothing
498 0 : else if (pWin->IsVisible())
499 : {
500 0 : m_aHiddenWidgets.push_back(pChild);
501 0 : pChild->Hide();
502 : }
503 : }
504 : }
505 : else
506 : {
507 : //We want just pRefBtn and pRefEdit to be shown
508 : //mark widgets we want to be visible, starting with pRefEdit
509 : //and all its direct parents.
510 0 : winset m_aVisibleWidgets;
511 0 : pResizeDialog = pRefEdit->GetParentDialog();
512 0 : vcl::Window *pContentArea = pResizeDialog->get_content_area();
513 0 : for (vcl::Window *pCandidate = pRefEdit;
514 0 : pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
515 : pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
516 : {
517 0 : m_aVisibleWidgets.insert(pCandidate);
518 : }
519 : //same again with pRefBtn, except stop if there's a
520 : //shared parent in the existing widgets
521 0 : for (vcl::Window *pCandidate = pRefBtn;
522 0 : pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
523 : pCandidate = pCandidate->GetWindow(GetWindowType::RealParent))
524 : {
525 0 : if (m_aVisibleWidgets.insert(pCandidate).second)
526 0 : break;
527 : }
528 :
529 : //hide everything except the m_aVisibleWidgets
530 0 : hideUnless(pContentArea, m_aVisibleWidgets, m_aHiddenWidgets);
531 : }
532 :
533 0 : if (!mbOldDlgLayoutEnabled)
534 : {
535 : // move and adapt edit field
536 0 : Size aNewDlgSize(aOldDialogSize.Width(), aOldEditSize.Height());
537 0 : Size aNewEditSize(aNewDlgSize);
538 0 : long nOffset = 0;
539 0 : if (pRefBtn)
540 : {
541 0 : aNewEditSize.Width() -= pRefBtn->GetSizePixel().Width();
542 0 : aNewEditSize.Width() -= aOldButtonPos.X() - (aOldEditPos.X()+aOldEditSize.Width());
543 :
544 0 : long nHeight = pRefBtn->GetSizePixel().Height();
545 0 : if ( nHeight > aOldEditSize.Height() )
546 : {
547 0 : aNewDlgSize.Height() = nHeight;
548 0 : nOffset = (nHeight-aOldEditSize.Height()) / 2;
549 : }
550 0 : aNewEditSize.Width() -= nOffset;
551 : }
552 0 : pRefEdit->SetPosSizePixel(Point(nOffset, nOffset), aNewEditSize);
553 :
554 : // set button position
555 0 : if( pRefBtn )
556 0 : pRefBtn->SetPosPixel( Point( aOldDialogSize.Width() - pRefBtn->GetSizePixel().Width(), 0 ) );
557 :
558 : // shrink window
559 0 : m_pWindow->SetOutputSizePixel(aNewDlgSize);
560 : }
561 :
562 : // set button image
563 0 : if( pRefBtn )
564 0 : pRefBtn->SetEndImage();
565 :
566 0 : if (!pAccel.get())
567 : {
568 0 : pAccel.reset( new Accelerator );
569 0 : pAccel->InsertItem( 1, vcl::KeyCode( KEY_RETURN ) );
570 0 : pAccel->InsertItem( 2, vcl::KeyCode( KEY_ESCAPE ) );
571 0 : pAccel->SetSelectHdl( LINK( this, ScFormulaReferenceHelper, AccelSelectHdl ) );
572 : }
573 0 : Application::InsertAccel( pAccel.get() );
574 0 : bAccInserted = true;
575 :
576 0 : if (mbOldDlgLayoutEnabled)
577 : {
578 0 : pRefEdit->set_width_request(aOldEditSize.Width());
579 0 : m_nOldBorderWidth = pResizeDialog->get_border_width();
580 0 : pResizeDialog->set_border_width(0);
581 0 : if (vcl::Window *pActionArea = pResizeDialog->get_action_area())
582 0 : pActionArea->Hide();
583 0 : pResizeDialog->setOptimalLayoutSize();
584 : }
585 : }
586 0 : }
587 :
588 0 : void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
589 : {
590 0 : if( pEdit )
591 : {
592 0 : if( pRefEdit == pEdit ) // is this the active ref edit field?
593 : {
594 0 : pRefEdit->GrabFocus(); // before RefInputDone()
595 0 : m_pDlg->RefInputDone( true ); // finish ref input
596 : }
597 : else
598 : {
599 0 : m_pDlg->RefInputDone( true ); // another active ref edit?
600 0 : m_pDlg->RefInputStart( pEdit, pButton ); // start ref input
601 : // pRefEdit might differ from pEdit after RefInputStart() (i.e. ScFormulaDlg)
602 0 : if( pRefEdit )
603 0 : pRefEdit->GrabFocus();
604 : }
605 : }
606 0 : }
607 :
608 0 : bool ScFormulaReferenceHelper::DoClose( sal_uInt16 nId )
609 : {
610 0 : SfxApplication* pSfxApp = SfxGetpApp();
611 :
612 0 : SetDispatcherLock( false ); //! here and in dtor ?
613 :
614 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
615 0 : if ( pViewFrm && pViewFrm->HasChildWindow(FID_INPUTLINE_STATUS) )
616 : {
617 : // The input row is disabled with ToolBox::Disable disabled, thus it must be
618 : // reenabled with ToolBox::Enable (before the AppWindow is enabled)
619 : // for the buttons to be drawn as enabled.
620 0 : SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_INPUTLINE_STATUS);
621 0 : if (pChild)
622 : {
623 0 : ScInputWindow* pWin = static_cast<ScInputWindow*>(pChild->GetWindow());
624 0 : pWin->Enable();
625 : }
626 : }
627 :
628 : // find parent view frame to close dialog
629 0 : SfxViewFrame* pMyViewFrm = NULL;
630 0 : if ( m_pBindings )
631 : {
632 0 : SfxDispatcher* pMyDisp = m_pBindings->GetDispatcher();
633 0 : if (pMyDisp)
634 0 : pMyViewFrm = pMyDisp->GetFrame();
635 : }
636 0 : SC_MOD()->SetRefDialog( nId, false, pMyViewFrm );
637 :
638 0 : pSfxApp->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );
639 :
640 0 : ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
641 0 : if ( pScViewShell )
642 0 : pScViewShell->UpdateInputHandler(true);
643 :
644 0 : return true;
645 : }
646 0 : void ScFormulaReferenceHelper::SetDispatcherLock( bool bLock )
647 : {
648 : // lock / unlock only the dispatchers of Calc documents
649 :
650 0 : TypeId aType(TYPE(ScDocShell));
651 0 : ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType));
652 0 : while( pDocShell )
653 : {
654 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
655 0 : while( pFrame )
656 : {
657 0 : SfxDispatcher* pDisp = pFrame->GetDispatcher();
658 0 : if (pDisp)
659 0 : pDisp->Lock( bLock );
660 :
661 0 : pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
662 : }
663 0 : pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, &aType));
664 : }
665 :
666 : // if a new view is created while the dialog is open,
667 : // that view's dispatcher is locked when trying to create the dialog
668 : // for that view (ScTabViewShell::CreateRefDialog)
669 0 : }
670 :
671 0 : void ScFormulaReferenceHelper::ViewShellChanged()
672 : {
673 0 : enableInput( false );
674 :
675 0 : EnableSpreadsheets();
676 0 : }
677 0 : void ScFormulaReferenceHelper::EnableSpreadsheets(bool bFlag, bool bChildren)
678 : {
679 0 : TypeId aType(TYPE(ScDocShell));
680 0 : ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType));
681 0 : while( pDocShell )
682 : {
683 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
684 0 : while( pFrame )
685 : {
686 : // enable everything except InPlace, including bean frames
687 0 : if ( !pFrame->GetFrame().IsInPlace() )
688 : {
689 0 : SfxViewShell* p = pFrame->GetViewShell();
690 0 : ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
691 0 : if(pViewSh!=NULL)
692 : {
693 0 : vcl::Window *pWin=pViewSh->GetWindow();
694 0 : if(pWin)
695 : {
696 0 : vcl::Window *pParent=pWin->GetParent();
697 0 : if(pParent)
698 : {
699 0 : pParent->EnableInput(bFlag,false);
700 0 : if(bChildren)
701 0 : pViewSh->EnableRefInput(bFlag);
702 : }
703 : }
704 : }
705 : }
706 0 : pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
707 : }
708 :
709 0 : pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, &aType));
710 : }
711 0 : }
712 :
713 0 : static void lcl_InvalidateWindows()
714 : {
715 0 : TypeId aType(TYPE(ScDocShell));
716 0 : ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType));
717 0 : while( pDocShell )
718 : {
719 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
720 0 : while( pFrame )
721 : {
722 : // enable everything except InPlace, including bean frames
723 0 : if ( !pFrame->GetFrame().IsInPlace() )
724 : {
725 0 : SfxViewShell* p = pFrame->GetViewShell();
726 0 : ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
727 0 : if(pViewSh!=NULL)
728 : {
729 0 : vcl::Window *pWin=pViewSh->GetWindow();
730 0 : if(pWin)
731 : {
732 0 : vcl::Window *pParent=pWin->GetParent();
733 0 : if(pParent)
734 0 : pParent->Invalidate();
735 : }
736 : }
737 : }
738 0 : pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
739 : }
740 :
741 0 : pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, &aType));
742 : }
743 0 : }
744 :
745 0 : static void lcl_HideAllReferences()
746 : {
747 0 : TypeId aScType = TYPE(ScTabViewShell);
748 0 : SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
749 0 : while ( pSh )
750 : {
751 0 : static_cast<ScTabViewShell*>(pSh)->ClearHighlightRanges();
752 0 : pSh = SfxViewShell::GetNext( *pSh, &aScType );
753 : }
754 0 : }
755 :
756 : //The class of ScAnyRefDlg is rewritten by PengYunQuan for Validity Cell Range Picker
757 : // class ScRefHandler
758 :
759 0 : ScRefHandler::ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef ):
760 : m_rWindow( &rWindow ),
761 : m_bInRefMode( false ),
762 : m_aHelper(this,pB),
763 : pMyBindings( pB ),
764 0 : pActiveWin(NULL)
765 : {
766 0 : m_aHelper.SetWindow(m_rWindow.get());
767 0 : reverseUniqueHelpIdHack(*m_rWindow.get());
768 0 : aIdle.SetPriority(SchedulerPriority::LOWER);
769 0 : aIdle.SetIdleHdl(LINK( this, ScRefHandler, UpdateFocusHdl));
770 :
771 0 : if( bBindRef ) EnterRefMode();
772 0 : }
773 :
774 0 : bool ScRefHandler::EnterRefMode()
775 : {
776 0 : if( m_bInRefMode ) return false;
777 :
778 0 : SC_MOD()->InputEnterHandler();
779 :
780 0 : ScTabViewShell* pScViewShell = NULL;
781 :
782 : // title has to be from the view that opened the dialog,
783 : // even if it's not the current view
784 :
785 0 : SfxObjectShell* pParentDoc = NULL;
786 0 : if ( pMyBindings )
787 : {
788 0 : SfxDispatcher* pMyDisp = pMyBindings->GetDispatcher();
789 0 : if (pMyDisp)
790 : {
791 0 : SfxViewFrame* pMyViewFrm = pMyDisp->GetFrame();
792 0 : if (pMyViewFrm)
793 : {
794 0 : pScViewShell = PTR_CAST( ScTabViewShell, pMyViewFrm->GetViewShell() );
795 0 : if( pScViewShell )
796 0 : pScViewShell->UpdateInputHandler(true);
797 0 : pParentDoc = pMyViewFrm->GetObjectShell();
798 : }
799 : }
800 : }
801 0 : if ( !pParentDoc && pScViewShell ) // use current only if above fails
802 0 : pParentDoc = pScViewShell->GetObjectShell();
803 0 : if ( pParentDoc )
804 0 : aDocName = pParentDoc->GetTitle();
805 :
806 0 : ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(pScViewShell);
807 :
808 : OSL_ENSURE( pInputHdl, "Missing input handler :-/" );
809 :
810 0 : if ( pInputHdl )
811 0 : pInputHdl->NotifyChange( NULL );
812 :
813 0 : ScFormulaReferenceHelper::enableInput( false );
814 :
815 0 : ScFormulaReferenceHelper::EnableSpreadsheets();
816 :
817 0 : m_aHelper.Init();
818 :
819 0 : ScFormulaReferenceHelper::SetDispatcherLock( true );
820 :
821 0 : return m_bInRefMode = true;
822 : }
823 :
824 0 : ScRefHandler::~ScRefHandler()
825 : {
826 0 : disposeRefHandler();
827 0 : }
828 :
829 0 : void ScRefHandler::disposeRefHandler()
830 : {
831 0 : m_rWindow.clear();
832 0 : pActiveWin.clear();
833 0 : LeaveRefMode();
834 0 : }
835 :
836 0 : bool ScRefHandler::LeaveRefMode()
837 : {
838 0 : if( !m_bInRefMode ) return false;
839 :
840 0 : lcl_HideAllReferences();
841 :
842 0 : if( Dialog *pDlg = dynamic_cast<Dialog*>( static_cast<vcl::Window*>(*this) ) )
843 0 : pDlg->SetModalInputMode(false);
844 0 : SetDispatcherLock( false ); //! here and in DoClose ?
845 :
846 0 : ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
847 0 : if( pScViewShell )
848 0 : pScViewShell->UpdateInputHandler(true);
849 :
850 0 : lcl_InvalidateWindows();
851 :
852 0 : m_bInRefMode = false;
853 0 : return true;
854 : }
855 :
856 0 : void ScRefHandler::SwitchToDocument()
857 : {
858 0 : ScTabViewShell* pCurrent = ScTabViewShell::GetActiveViewShell();
859 0 : if (pCurrent)
860 : {
861 0 : SfxObjectShell* pObjSh = pCurrent->GetObjectShell();
862 0 : if ( pObjSh && pObjSh->GetTitle() == aDocName )
863 : {
864 : // right document already visible -> nothing to do
865 0 : return;
866 : }
867 : }
868 :
869 0 : TypeId aScType = TYPE(ScTabViewShell);
870 0 : SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
871 0 : while ( pSh )
872 : {
873 0 : SfxObjectShell* pObjSh = pSh->GetObjectShell();
874 0 : if ( pObjSh && pObjSh->GetTitle() == aDocName )
875 : {
876 : // switch to first TabViewShell for document
877 0 : static_cast<ScTabViewShell*>(pSh)->SetActive();
878 0 : return;
879 : }
880 0 : pSh = SfxViewShell::GetNext( *pSh, &aScType );
881 : }
882 : }
883 :
884 0 : bool ScRefHandler::IsDocAllowed(SfxObjectShell* pDocSh) const // pDocSh may be 0
885 : {
886 : // default: allow only same document (overridden in function dialog)
887 0 : OUString aCmpName;
888 0 : if ( pDocSh )
889 0 : aCmpName = pDocSh->GetTitle();
890 :
891 : // if aDocName isn't initialized, allow
892 0 : return ( aDocName.isEmpty() || aDocName == aCmpName );
893 : }
894 :
895 0 : bool ScRefHandler::IsRefInputMode() const
896 : {
897 0 : return m_rWindow->IsVisible(); // references can only be input to visible windows
898 : }
899 :
900 0 : bool ScRefHandler::DoClose( sal_uInt16 nId )
901 : {
902 0 : m_aHelper.DoClose(nId);
903 0 : return true;
904 : }
905 :
906 0 : void ScRefHandler::SetDispatcherLock( bool bLock )
907 : {
908 0 : ScFormulaReferenceHelper::SetDispatcherLock( bLock );
909 0 : }
910 :
911 0 : void ScRefHandler::ViewShellChanged()
912 : {
913 0 : ScFormulaReferenceHelper::ViewShellChanged();
914 0 : }
915 :
916 0 : void ScRefHandler::AddRefEntry()
917 : {
918 : // override this for multi-references
919 0 : }
920 :
921 0 : bool ScRefHandler::IsTableLocked() const
922 : {
923 : // the default is that the sheet can be switched during while the reference is edited
924 :
925 0 : return false;
926 : }
927 :
928 : // RefInputStart/Done: Zoom-In (AutoHide) on single field
929 : // (using button oder movement)
930 :
931 0 : void ScRefHandler::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
932 : {
933 0 : m_aHelper.RefInputStart( pEdit, pButton );
934 0 : }
935 :
936 0 : void ScRefHandler::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
937 : {
938 0 : m_aHelper.ToggleCollapsed( pEdit, pButton );
939 0 : }
940 :
941 0 : void ScRefHandler::preNotify(const NotifyEvent& rNEvt, const bool bBindRef)
942 : {
943 0 : if( bBindRef || m_bInRefMode )
944 : {
945 0 : MouseNotifyEvent nSwitch=rNEvt.GetType();
946 0 : if(nSwitch==MouseNotifyEvent::GETFOCUS)
947 : {
948 0 : pActiveWin=rNEvt.GetWindow();
949 : }
950 : }
951 0 : }
952 :
953 0 : void ScRefHandler::stateChanged(const StateChangedType nStateChange, const bool bBindRef)
954 : {
955 0 : if( !bBindRef && !m_bInRefMode ) return;
956 :
957 0 : if(nStateChange == StateChangedType::Visible)
958 : {
959 0 : if(m_rWindow->IsVisible())
960 : {
961 0 : ScFormulaReferenceHelper::enableInput( false );
962 0 : ScFormulaReferenceHelper::EnableSpreadsheets();
963 0 : ScFormulaReferenceHelper::SetDispatcherLock( true );
964 0 : aIdle.Start();
965 : }
966 : else
967 : {
968 0 : ScFormulaReferenceHelper::enableInput( true );
969 0 : ScFormulaReferenceHelper::SetDispatcherLock( false ); /*//! here and in DoClose ?*/
970 : }
971 : }
972 : }
973 :
974 0 : IMPL_LINK_NOARG_TYPED(ScRefHandler, UpdateFocusHdl, Idle *, void)
975 : {
976 0 : if (pActiveWin)
977 : {
978 0 : pActiveWin->GrabFocus();
979 : }
980 0 : }
981 :
982 0 : bool ScRefHandler::ParseWithNames( ScRangeList& rRanges, const OUString& rStr, ScDocument* pDoc )
983 : {
984 0 : return m_aHelper.ParseWithNames( rRanges, rStr, pDoc );
985 : }
986 :
987 0 : void ScRefHandler::HideReference( bool bDoneRefMode )
988 : {
989 0 : m_aHelper.HideReference( bDoneRefMode );
990 0 : }
991 :
992 0 : void ScRefHandler::ShowReference(const OUString& rStr)
993 : {
994 0 : m_aHelper.ShowReference(rStr);
995 0 : }
996 :
997 0 : void ScRefHandler::ReleaseFocus( formula::RefEdit* pEdit, formula::RefButton* pButton )
998 : {
999 0 : m_aHelper.ReleaseFocus( pEdit,pButton );
1000 0 : }
1001 :
1002 0 : void ScRefHandler::RefInputDone( bool bForced )
1003 : {
1004 0 : m_aHelper.RefInputDone( bForced );
1005 156 : }
1006 :
1007 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|