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