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 ( aRangeUtil.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 : typedef std::vector<vcl::Window*> winvec;
348 :
349 0 : void ScFormulaReferenceHelper::RefInputDone( bool bForced )
350 : {
351 0 : if ( CanInputDone( bForced ) )
352 : {
353 0 : if (bAccInserted) // disable accelerator
354 : {
355 0 : Application::RemoveAccel( pAccel.get() );
356 0 : bAccInserted = false;
357 : }
358 :
359 : //get rid of all this junk when we can
360 0 : if (!mbOldDlgLayoutEnabled)
361 : {
362 0 : m_pWindow->SetOutputSizePixel(aOldDialogSize);
363 :
364 : // restore the parent of the edit field
365 0 : pRefEdit->SetParent(mpOldEditParent);
366 :
367 : // the window is at the old size again
368 0 : m_pWindow->SetOutputSizePixel(aOldDialogSize);
369 :
370 : // set button parent
371 0 : if( pRefBtn )
372 : {
373 0 : pRefBtn->SetParent(m_pWindow);
374 : }
375 : }
376 :
377 0 : if (!mbOldEditParentLayoutEnabled)
378 : {
379 : // set pEditCell to old position
380 0 : pRefEdit->SetPosSizePixel(aOldEditPos, aOldEditSize);
381 :
382 : // set button position
383 0 : if( pRefBtn )
384 : {
385 0 : pRefBtn->SetPosPixel( aOldButtonPos );
386 : }
387 : }
388 :
389 : // Adjust window title
390 0 : m_pWindow->SetText(sOldDialogText);
391 :
392 : // set button image
393 0 : if( pRefBtn )
394 0 : pRefBtn->SetStartImage();
395 :
396 : // All others: Show();
397 0 : for (winvec::iterator aI = m_aHiddenWidgets.begin(); aI != m_aHiddenWidgets.end(); ++aI)
398 : {
399 0 : vcl::Window *pWindow = *aI;
400 0 : pWindow->Show();
401 : }
402 0 : m_aHiddenWidgets.clear();
403 :
404 0 : if (mbOldDlgLayoutEnabled)
405 : {
406 0 : pRefEdit->set_width_request(mnOldEditWidthReq);
407 0 : Dialog* pResizeDialog = pRefEdit->GetParentDialog();
408 0 : pResizeDialog->set_border_width(m_nOldBorderWidth);
409 0 : if (vcl::Window *pActionArea = pResizeDialog->get_action_area())
410 0 : pActionArea->Show();
411 0 : pResizeDialog->setOptimalLayoutSize();
412 : }
413 :
414 0 : pRefEdit = NULL;
415 0 : pRefBtn = NULL;
416 : }
417 0 : }
418 :
419 : typedef std::set<vcl::Window*> winset;
420 :
421 : namespace
422 : {
423 0 : void hideUnless(vcl::Window *pTop, const winset& rVisibleWidgets,
424 : winvec &rWasVisibleWidgets)
425 : {
426 0 : for (vcl::Window* pChild = pTop->GetWindow(WINDOW_FIRSTCHILD); pChild;
427 0 : pChild = pChild->GetWindow(WINDOW_NEXT))
428 : {
429 0 : if (!pChild->IsVisible())
430 0 : continue;
431 0 : if (rVisibleWidgets.find(pChild) == rVisibleWidgets.end())
432 : {
433 0 : rWasVisibleWidgets.push_back(pChild);
434 0 : pChild->Hide();
435 : }
436 0 : else if (isContainerWindow(pChild))
437 : {
438 0 : hideUnless(pChild, rVisibleWidgets, rWasVisibleWidgets);
439 : }
440 : }
441 0 : }
442 : }
443 :
444 0 : void ScFormulaReferenceHelper::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
445 : {
446 0 : if (!pRefEdit)
447 : {
448 0 : pRefEdit = pEdit;
449 0 : pRefBtn = pButton;
450 :
451 0 : mbOldDlgLayoutEnabled = isLayoutEnabled(m_pWindow);
452 0 : aOldEditSize = pRefEdit->GetSizePixel();
453 0 : mnOldEditWidthReq = pRefEdit->get_width_request();
454 0 : mpOldEditParent = pRefEdit->GetParent();
455 0 : mbOldEditParentLayoutEnabled = isContainerWindow(mpOldEditParent);
456 :
457 : //get rid of all the !mbOldDlgLayoutEnabled and
458 : //mbOldEditParentLayoutEnabled junk when we can after the last user of
459 : //this is widget-layout-ified
460 0 : if (!mbOldEditParentLayoutEnabled)
461 : {
462 : // Save current state
463 0 : aOldDialogSize = m_pWindow->GetOutputSizePixel();
464 0 : aOldEditPos = pRefEdit->GetPosPixel();
465 0 : if (pRefBtn)
466 0 : aOldButtonPos = pRefBtn->GetPosPixel();
467 : }
468 :
469 0 : if (!mbOldDlgLayoutEnabled)
470 : {
471 0 : pRefEdit->SetParent(m_pWindow);
472 0 : if(pRefBtn)
473 0 : pRefBtn->SetParent(m_pWindow);
474 : }
475 :
476 : // Save and adjust window title
477 0 : sOldDialogText = m_pWindow->GetText();
478 0 : if (vcl::Window *pLabel = pRefEdit->GetLabelWidgetForShrinkMode())
479 : {
480 0 : OUString sLabel = pLabel->GetText();
481 0 : if (!sLabel.isEmpty())
482 : {
483 0 : OUString sNewDialogText = sOldDialogText;
484 0 : sNewDialogText += ": ";
485 0 : sNewDialogText += comphelper::string::stripEnd(sLabel, ':');
486 0 : m_pWindow->SetText( MnemonicGenerator::EraseAllMnemonicChars( sNewDialogText ) );
487 0 : }
488 : }
489 :
490 0 : Dialog* pResizeDialog = NULL;
491 :
492 0 : if (!mbOldDlgLayoutEnabled)
493 : {
494 0 : for (vcl::Window* pChild = m_pWindow->GetWindow(WINDOW_FIRSTCHILD); pChild;
495 0 : pChild = pChild->GetWindow(WINDOW_NEXT))
496 : {
497 0 : vcl::Window *pWin = pChild->GetWindow(WINDOW_CLIENT);
498 0 : if (pWin == (vcl::Window*)pRefEdit || pWin == (vcl::Window*)pRefBtn)
499 0 : continue; // do nothing
500 0 : else if (pWin->IsVisible())
501 : {
502 0 : m_aHiddenWidgets.push_back(pChild);
503 0 : pChild->Hide();
504 : }
505 : }
506 : }
507 : else
508 : {
509 : //We want just pRefBtn and pRefEdit to be shown
510 : //mark widgets we want to be visible, starting with pRefEdit
511 : //and all its direct parents.
512 0 : winset m_aVisibleWidgets;
513 0 : pResizeDialog = pRefEdit->GetParentDialog();
514 0 : vcl::Window *pContentArea = pResizeDialog->get_content_area();
515 0 : for (vcl::Window *pCandidate = pRefEdit;
516 0 : pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
517 0 : pCandidate = pCandidate->GetWindow(WINDOW_REALPARENT))
518 : {
519 0 : m_aVisibleWidgets.insert(pCandidate);
520 : }
521 : //same again with pRefBtn, except stop if there's a
522 : //shared parent in the existing widgets
523 0 : for (vcl::Window *pCandidate = pRefBtn;
524 0 : pCandidate && (pCandidate != pContentArea && pCandidate->IsVisible());
525 0 : pCandidate = pCandidate->GetWindow(WINDOW_REALPARENT))
526 : {
527 0 : if (m_aVisibleWidgets.insert(pCandidate).second)
528 0 : break;
529 : }
530 :
531 : //hide everything except the m_aVisibleWidgets
532 0 : hideUnless(pContentArea, m_aVisibleWidgets, m_aHiddenWidgets);
533 : }
534 :
535 0 : if (!mbOldDlgLayoutEnabled)
536 : {
537 : // move and adapt edit field
538 0 : Size aNewDlgSize(aOldDialogSize.Width(), aOldEditSize.Height());
539 0 : Size aNewEditSize(aNewDlgSize);
540 0 : long nOffset = 0;
541 0 : if (pRefBtn)
542 : {
543 0 : aNewEditSize.Width() -= pRefBtn->GetSizePixel().Width();
544 0 : aNewEditSize.Width() -= aOldButtonPos.X() - (aOldEditPos.X()+aOldEditSize.Width());
545 :
546 0 : long nHeight = pRefBtn->GetSizePixel().Height();
547 0 : if ( nHeight > aOldEditSize.Height() )
548 : {
549 0 : aNewDlgSize.Height() = nHeight;
550 0 : nOffset = (nHeight-aOldEditSize.Height()) / 2;
551 : }
552 0 : aNewEditSize.Width() -= nOffset;
553 : }
554 0 : pRefEdit->SetPosSizePixel(Point(nOffset, nOffset), aNewEditSize);
555 :
556 : // set button position
557 0 : if( pRefBtn )
558 0 : pRefBtn->SetPosPixel( Point( aOldDialogSize.Width() - pRefBtn->GetSizePixel().Width(), 0 ) );
559 :
560 : // shrink window
561 0 : m_pWindow->SetOutputSizePixel(aNewDlgSize);
562 : }
563 :
564 : // set button image
565 0 : if( pRefBtn )
566 0 : pRefBtn->SetEndImage();
567 :
568 0 : if (!pAccel.get())
569 : {
570 0 : pAccel.reset( new Accelerator );
571 0 : pAccel->InsertItem( 1, vcl::KeyCode( KEY_RETURN ) );
572 0 : pAccel->InsertItem( 2, vcl::KeyCode( KEY_ESCAPE ) );
573 0 : pAccel->SetSelectHdl( LINK( this, ScFormulaReferenceHelper, AccelSelectHdl ) );
574 : }
575 0 : Application::InsertAccel( pAccel.get() );
576 0 : bAccInserted = true;
577 :
578 0 : if (mbOldDlgLayoutEnabled)
579 : {
580 0 : pRefEdit->set_width_request(aOldEditSize.Width());
581 0 : m_nOldBorderWidth = pResizeDialog->get_border_width();
582 0 : pResizeDialog->set_border_width(0);
583 0 : if (vcl::Window *pActionArea = pResizeDialog->get_action_area())
584 0 : pActionArea->Hide();
585 0 : pResizeDialog->setOptimalLayoutSize();
586 : }
587 : }
588 0 : }
589 :
590 0 : void ScFormulaReferenceHelper::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
591 : {
592 0 : if( pEdit )
593 : {
594 0 : if( pRefEdit == pEdit ) // is this the active ref edit field?
595 : {
596 0 : pRefEdit->GrabFocus(); // before RefInputDone()
597 0 : m_pDlg->RefInputDone( true ); // finish ref input
598 : }
599 : else
600 : {
601 0 : m_pDlg->RefInputDone( true ); // another active ref edit?
602 0 : m_pDlg->RefInputStart( pEdit, pButton ); // start ref input
603 : // pRefEdit might differ from pEdit after RefInputStart() (i.e. ScFormulaDlg)
604 0 : if( pRefEdit )
605 0 : pRefEdit->GrabFocus();
606 : }
607 : }
608 0 : }
609 :
610 0 : bool ScFormulaReferenceHelper::DoClose( sal_uInt16 nId )
611 : {
612 0 : SfxApplication* pSfxApp = SfxGetpApp();
613 :
614 0 : SetDispatcherLock( false ); //! here and in dtor ?
615 :
616 0 : SfxViewFrame* pViewFrm = SfxViewFrame::Current();
617 0 : if ( pViewFrm && pViewFrm->HasChildWindow(FID_INPUTLINE_STATUS) )
618 : {
619 : // The input row is disabled with ToolBox::Disable disabled, thus it must be
620 : // reenabled with ToolBox::Enable (before the AppWindow is enabled)
621 : // for the buttons to be drawn as enabled.
622 0 : SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_INPUTLINE_STATUS);
623 0 : if (pChild)
624 : {
625 0 : ScInputWindow* pWin = static_cast<ScInputWindow*>(pChild->GetWindow());
626 0 : pWin->Enable();
627 : }
628 : }
629 :
630 : // find parent view frame to close dialog
631 0 : SfxViewFrame* pMyViewFrm = NULL;
632 0 : if ( m_pBindings )
633 : {
634 0 : SfxDispatcher* pMyDisp = m_pBindings->GetDispatcher();
635 0 : if (pMyDisp)
636 0 : pMyViewFrm = pMyDisp->GetFrame();
637 : }
638 0 : SC_MOD()->SetRefDialog( nId, false, pMyViewFrm );
639 :
640 0 : pSfxApp->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) );
641 :
642 0 : ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
643 0 : if ( pScViewShell )
644 0 : pScViewShell->UpdateInputHandler(true);
645 :
646 0 : return true;
647 : }
648 0 : void ScFormulaReferenceHelper::SetDispatcherLock( bool bLock )
649 : {
650 : // lock / unlock only the dispatchers of Calc documents
651 :
652 0 : TypeId aType(TYPE(ScDocShell));
653 0 : ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType));
654 0 : while( pDocShell )
655 : {
656 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
657 0 : while( pFrame )
658 : {
659 0 : SfxDispatcher* pDisp = pFrame->GetDispatcher();
660 0 : if (pDisp)
661 0 : pDisp->Lock( bLock );
662 :
663 0 : pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
664 : }
665 0 : pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, &aType));
666 : }
667 :
668 : // if a new view is created while the dialog is open,
669 : // that view's dispatcher is locked when trying to create the dialog
670 : // for that view (ScTabViewShell::CreateRefDialog)
671 0 : }
672 :
673 0 : void ScFormulaReferenceHelper::ViewShellChanged()
674 : {
675 0 : enableInput( false );
676 :
677 0 : EnableSpreadsheets();
678 0 : }
679 0 : void ScFormulaReferenceHelper::EnableSpreadsheets(bool bFlag, bool bChildren)
680 : {
681 0 : TypeId aType(TYPE(ScDocShell));
682 0 : ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType));
683 0 : while( pDocShell )
684 : {
685 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
686 0 : while( pFrame )
687 : {
688 : // enable everything except InPlace, including bean frames
689 0 : if ( !pFrame->GetFrame().IsInPlace() )
690 : {
691 0 : SfxViewShell* p = pFrame->GetViewShell();
692 0 : ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
693 0 : if(pViewSh!=NULL)
694 : {
695 0 : vcl::Window *pWin=pViewSh->GetWindow();
696 0 : if(pWin)
697 : {
698 0 : vcl::Window *pParent=pWin->GetParent();
699 0 : if(pParent)
700 : {
701 0 : pParent->EnableInput(bFlag,false);
702 0 : if(bChildren)
703 0 : pViewSh->EnableRefInput(bFlag);
704 : }
705 : }
706 : }
707 : }
708 0 : pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
709 : }
710 :
711 0 : pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, &aType));
712 : }
713 0 : }
714 :
715 0 : static void lcl_InvalidateWindows()
716 : {
717 0 : TypeId aType(TYPE(ScDocShell));
718 0 : ScDocShell* pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType));
719 0 : while( pDocShell )
720 : {
721 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
722 0 : while( pFrame )
723 : {
724 : // enable everything except InPlace, including bean frames
725 0 : if ( !pFrame->GetFrame().IsInPlace() )
726 : {
727 0 : SfxViewShell* p = pFrame->GetViewShell();
728 0 : ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
729 0 : if(pViewSh!=NULL)
730 : {
731 0 : vcl::Window *pWin=pViewSh->GetWindow();
732 0 : if(pWin)
733 : {
734 0 : vcl::Window *pParent=pWin->GetParent();
735 0 : if(pParent)
736 0 : pParent->Invalidate();
737 : }
738 : }
739 : }
740 0 : pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
741 : }
742 :
743 0 : pDocShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pDocShell, &aType));
744 : }
745 0 : }
746 :
747 0 : static void lcl_HideAllReferences()
748 : {
749 0 : TypeId aScType = TYPE(ScTabViewShell);
750 0 : SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
751 0 : while ( pSh )
752 : {
753 0 : static_cast<ScTabViewShell*>(pSh)->ClearHighlightRanges();
754 0 : pSh = SfxViewShell::GetNext( *pSh, &aScType );
755 : }
756 0 : }
757 :
758 : //The class of ScAnyRefDlg is rewritten by PengYunQuan for Validity Cell Range Picker
759 : // class ScRefHandler
760 :
761 0 : ScRefHandler::ScRefHandler( vcl::Window &rWindow, SfxBindings* pB, bool bBindRef ):
762 : m_rWindow( rWindow ),
763 : m_bInRefMode( false ),
764 : m_aHelper(this,pB),
765 : pMyBindings( pB ),
766 0 : pActiveWin(NULL)
767 : {
768 0 : m_aHelper.SetWindow(&m_rWindow);
769 0 : reverseUniqueHelpIdHack(m_rWindow);
770 0 : aTimer.SetTimeout(200);
771 0 : aTimer.SetTimeoutHdl(LINK( this, ScRefHandler, UpdateFocusHdl));
772 :
773 0 : if( bBindRef ) EnterRefMode();
774 0 : }
775 :
776 0 : bool ScRefHandler::EnterRefMode()
777 : {
778 0 : if( m_bInRefMode ) return false;
779 :
780 0 : SC_MOD()->InputEnterHandler();
781 :
782 0 : ScTabViewShell* pScViewShell = NULL;
783 :
784 : // title has to be from the view that opened the dialog,
785 : // even if it's not the current view
786 :
787 0 : SfxObjectShell* pParentDoc = NULL;
788 0 : if ( pMyBindings )
789 : {
790 0 : SfxDispatcher* pMyDisp = pMyBindings->GetDispatcher();
791 0 : if (pMyDisp)
792 : {
793 0 : SfxViewFrame* pMyViewFrm = pMyDisp->GetFrame();
794 0 : if (pMyViewFrm)
795 : {
796 0 : pScViewShell = PTR_CAST( ScTabViewShell, pMyViewFrm->GetViewShell() );
797 0 : if( pScViewShell )
798 0 : pScViewShell->UpdateInputHandler(true);
799 0 : pParentDoc = pMyViewFrm->GetObjectShell();
800 : }
801 : }
802 : }
803 0 : if ( !pParentDoc && pScViewShell ) // use current only if above fails
804 0 : pParentDoc = pScViewShell->GetObjectShell();
805 0 : if ( pParentDoc )
806 0 : aDocName = pParentDoc->GetTitle();
807 :
808 0 : ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(pScViewShell);
809 :
810 : OSL_ENSURE( pInputHdl, "Missing input handler :-/" );
811 :
812 0 : if ( pInputHdl )
813 0 : pInputHdl->NotifyChange( NULL );
814 :
815 0 : ScFormulaReferenceHelper::enableInput( false );
816 :
817 0 : m_aHelper.EnableSpreadsheets();
818 :
819 0 : m_aHelper.Init();
820 :
821 0 : m_aHelper.SetDispatcherLock( true );
822 :
823 0 : return m_bInRefMode = true;
824 : }
825 :
826 0 : ScRefHandler::~ScRefHandler()
827 : {
828 0 : LeaveRefMode();
829 0 : }
830 :
831 0 : bool ScRefHandler::LeaveRefMode()
832 : {
833 0 : if( !m_bInRefMode ) return false;
834 :
835 0 : lcl_HideAllReferences();
836 :
837 0 : if( Dialog *pDlg = dynamic_cast<Dialog*>( static_cast<vcl::Window*>(*this) ) )
838 0 : pDlg->SetModalInputMode(false);
839 0 : SetDispatcherLock( false ); //! here and in DoClose ?
840 :
841 0 : ScTabViewShell* pScViewShell = ScTabViewShell::GetActiveViewShell();
842 0 : if( pScViewShell )
843 0 : pScViewShell->UpdateInputHandler(true);
844 :
845 0 : lcl_InvalidateWindows();
846 :
847 0 : m_bInRefMode = false;
848 0 : return true;
849 : }
850 :
851 0 : void ScRefHandler::SwitchToDocument()
852 : {
853 0 : ScTabViewShell* pCurrent = ScTabViewShell::GetActiveViewShell();
854 0 : if (pCurrent)
855 : {
856 0 : SfxObjectShell* pObjSh = pCurrent->GetObjectShell();
857 0 : if ( pObjSh && pObjSh->GetTitle() == aDocName )
858 : {
859 : // right document already visible -> nothing to do
860 0 : return;
861 : }
862 : }
863 :
864 0 : TypeId aScType = TYPE(ScTabViewShell);
865 0 : SfxViewShell* pSh = SfxViewShell::GetFirst( &aScType );
866 0 : while ( pSh )
867 : {
868 0 : SfxObjectShell* pObjSh = pSh->GetObjectShell();
869 0 : if ( pObjSh && pObjSh->GetTitle() == aDocName )
870 : {
871 : // switch to first TabViewShell for document
872 0 : static_cast<ScTabViewShell*>(pSh)->SetActive();
873 0 : return;
874 : }
875 0 : pSh = SfxViewShell::GetNext( *pSh, &aScType );
876 : }
877 : }
878 :
879 0 : bool ScRefHandler::IsDocAllowed(SfxObjectShell* pDocSh) const // pDocSh may be 0
880 : {
881 : // default: allow only same document (overridden in function dialog)
882 0 : OUString aCmpName;
883 0 : if ( pDocSh )
884 0 : aCmpName = pDocSh->GetTitle();
885 :
886 : // if aDocName isn't initialized, allow
887 0 : return ( aDocName.isEmpty() || aDocName == aCmpName );
888 : }
889 :
890 0 : bool ScRefHandler::IsRefInputMode() const
891 : {
892 0 : return m_rWindow.IsVisible(); // references can only be input to visible windows
893 : }
894 :
895 0 : bool ScRefHandler::DoClose( sal_uInt16 nId )
896 : {
897 0 : m_aHelper.DoClose(nId);
898 0 : return true;
899 : }
900 :
901 0 : void ScRefHandler::SetDispatcherLock( bool bLock )
902 : {
903 0 : m_aHelper.SetDispatcherLock( bLock );
904 0 : }
905 :
906 0 : void ScRefHandler::ViewShellChanged()
907 : {
908 0 : m_aHelper.ViewShellChanged();
909 0 : }
910 :
911 0 : void ScRefHandler::AddRefEntry()
912 : {
913 : // needs to be overloaded for multi-references
914 0 : }
915 :
916 0 : bool ScRefHandler::IsTableLocked() const
917 : {
918 : // the default is that the sheet can be switched during while the reference is edited
919 :
920 0 : return false;
921 : }
922 :
923 : // RefInputStart/Done: Zoom-In (AutoHide) on single field
924 : // (using button oder movement)
925 :
926 0 : void ScRefHandler::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
927 : {
928 0 : m_aHelper.RefInputStart( pEdit, pButton );
929 0 : }
930 :
931 0 : void ScRefHandler::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton )
932 : {
933 0 : m_aHelper.ToggleCollapsed( pEdit, pButton );
934 0 : }
935 :
936 0 : void ScRefHandler::preNotify(const NotifyEvent& rNEvt, const bool bBindRef)
937 : {
938 0 : if( bBindRef || m_bInRefMode )
939 : {
940 0 : sal_uInt16 nSwitch=rNEvt.GetType();
941 0 : if(nSwitch==EVENT_GETFOCUS)
942 : {
943 0 : pActiveWin=rNEvt.GetWindow();
944 : }
945 : }
946 0 : }
947 :
948 0 : void ScRefHandler::stateChanged(const StateChangedType nStateChange, const bool bBindRef)
949 : {
950 0 : if( !bBindRef && !m_bInRefMode ) return;
951 :
952 0 : if(nStateChange == StateChangedType::VISIBLE)
953 : {
954 0 : if(m_rWindow.IsVisible())
955 : {
956 0 : ScFormulaReferenceHelper::enableInput( false );
957 0 : m_aHelper.EnableSpreadsheets();
958 0 : m_aHelper.SetDispatcherLock( true );
959 0 : aTimer.Start();
960 : }
961 : else
962 : {
963 0 : ScFormulaReferenceHelper::enableInput( true );
964 0 : m_aHelper.SetDispatcherLock( false ); /*//! here and in DoClose ?*/
965 : }
966 : }
967 : }
968 :
969 0 : IMPL_LINK_NOARG(ScRefHandler, UpdateFocusHdl)
970 : {
971 0 : if (pActiveWin)
972 : {
973 0 : pActiveWin->GrabFocus();
974 : }
975 0 : return 0;
976 : }
977 :
978 0 : bool ScRefHandler::ParseWithNames( ScRangeList& rRanges, const OUString& rStr, ScDocument* pDoc )
979 : {
980 0 : return m_aHelper.ParseWithNames( rRanges, rStr, pDoc );
981 : }
982 :
983 0 : void ScRefHandler::HideReference( bool bDoneRefMode )
984 : {
985 0 : m_aHelper.HideReference( bDoneRefMode );
986 0 : }
987 :
988 0 : void ScRefHandler::ShowReference(const OUString& rStr)
989 : {
990 0 : m_aHelper.ShowReference(rStr);
991 0 : }
992 :
993 0 : void ScRefHandler::ReleaseFocus( formula::RefEdit* pEdit, formula::RefButton* pButton )
994 : {
995 0 : m_aHelper.ReleaseFocus( pEdit,pButton );
996 0 : }
997 :
998 0 : void ScRefHandler::RefInputDone( bool bForced )
999 : {
1000 0 : m_aHelper.RefInputDone( bForced );
1001 0 : }
1002 :
1003 0 : ScRefHdlModalImpl::ScRefHdlModalImpl(vcl::Window* pParent, const OString& rID,
1004 : const OUString& rUIXMLDescription)
1005 : : ModalDialog( pParent, rID, rUIXMLDescription)
1006 0 : , ScRefHandler(dynamic_cast<Window&>(*this), NULL, true)
1007 : {
1008 0 : }
1009 :
1010 0 : bool ScRefHdlModalImpl::PreNotify( NotifyEvent& rNEvt )
1011 : {
1012 0 : ScRefHandler::preNotify( rNEvt, true );
1013 0 : return ModalDialog::PreNotify( rNEvt );
1014 : }
1015 :
1016 0 : void ScRefHdlModalImpl::StateChanged( StateChangedType nStateChange )
1017 : {
1018 0 : ModalDialog::StateChanged( nStateChange );
1019 0 : ScRefHandler::stateChanged( nStateChange, true );
1020 0 : }
1021 :
1022 0 : ScAnyRefModalDlg::ScAnyRefModalDlg(vcl::Window* pParent, const OString& rID,
1023 : const OUString& rUIXMLDescription)
1024 0 : : ScRefHdlModalImpl(pParent, rID, rUIXMLDescription)
1025 : {
1026 228 : }
1027 :
1028 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|