Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / ui / formdlg / dwfunctr.cxx
blob8a36f6d64ca2f5a0e8094443c422a94733bb961f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <comphelper/string.hxx>
21 #include <editeng/editview.hxx>
22 #include <sfx2/bindings.hxx>
23 #include <sfx2/dispatch.hxx>
24 #include <sfx2/objsh.hxx>
25 #include <sfx2/viewsh.hxx>
27 #include "sc.hrc"
28 #include "global.hxx"
29 #include "scresid.hxx"
30 #include "reffact.hxx"
31 #include "document.hxx"
32 #include "formulacell.hxx"
33 #include "scmod.hxx"
34 #include "inputhdl.hxx"
35 #include "tabvwsh.hxx"
36 #include "appoptio.hxx"
37 #include "compiler.hxx"
39 #include "dwfunctr.hrc"
40 #include "dwfunctr.hxx"
42 /*************************************************************************
43 #* Member: ScFunctionWin
44 #*------------------------------------------------------------------------
46 #* Klasse: ScFunctionWin
48 #* Funktion: Konstruktor der Klasse ScFunctionWin
50 #* Input: Sfx- Verknuepfungen, Fenster, Resource
52 #* Output: ---
54 #************************************************************************/
56 ScFunctionWin::ScFunctionWin( SfxBindings* pBindingsP, vcl::Window* pParent, const ResId& rResId ) :
57 vcl::Window(pParent, rResId),
58 rBindings ( *pBindingsP ),
59 aIdle ( "sc formdlg ScFunctionWin" ),
60 aPrivatSplit ( VclPtr<ScPrivatSplit>::Create( this, ResId( FT_SPLIT, *rResId.GetResMgr() ) ) ),
61 aCatBox ( VclPtr<ListBox>::Create( this, ResId( CB_CAT, *rResId.GetResMgr() ) ) ),
62 aFuncList ( VclPtr<ListBox>::Create( this, ResId( LB_FUNC, *rResId.GetResMgr() ) ) ),
63 aDDFuncList ( VclPtr<ListBox>::Create( this, ResId( DDLB_FUNC, *rResId.GetResMgr() ) ) ),
64 aInsertButton ( VclPtr<ImageButton>::Create( this, ResId( IMB_INSERT, *rResId.GetResMgr() ) ) ),
65 aFiFuncDesc ( VclPtr<FixedText>::Create( this, ResId( FI_FUNCDESC, *rResId.GetResMgr() ) ) ),
66 aOldSize (0,0),
67 pFuncDesc (nullptr)
69 FreeResource();
70 InitLRUList();
71 SetStyle(GetStyle()|WB_CLIPCHILDREN);
73 aIdle.SetPriority(SchedulerPriority::LOWER);
74 aIdle.SetIdleHdl(LINK( this, ScFunctionWin, TimerHdl));
76 aFiFuncDesc->SetUpdateMode(true);
77 pAllFuncList=aFuncList;
78 aDDFuncList->Disable();
79 aDDFuncList->Hide();
80 nArgs=0;
81 bSizeFlag=false;
82 aCatBox->SetDropDownLineCount(9);
83 vcl::Font aFont=aFiFuncDesc->GetFont();
84 aFont.SetColor(Color(COL_BLACK));
85 aFiFuncDesc->SetFont(aFont);
86 aFiFuncDesc->SetBackground( GetBackground() ); //! never transparent?
88 Link<ListBox&,void> aLink=LINK( this, ScFunctionWin, SelHdl);
89 aCatBox->SetSelectHdl(aLink);
90 aFuncList->SetSelectHdl(aLink);
91 aDDFuncList->SetSelectHdl(aLink);
93 aFuncList->SetDoubleClickHdl(LINK( this, ScFunctionWin, SetSelectionHdl));
94 aDDFuncList->SetSelectHdl(aLink);
95 aInsertButton->SetClickHdl(LINK( this, ScFunctionWin, SetSelectionClickHdl));
97 Link<ScPrivatSplit&,void> a3Link=LINK( this, ScFunctionWin, SetSplitHdl);
98 aPrivatSplit->SetCtrModifiedHdl(a3Link);
99 StartListening( rBindings, true );
101 Point aTopLeft=aCatBox->GetPosPixel();
102 OUString aString("ww");
103 Size aTxtSize( aFiFuncDesc->GetTextWidth(aString), aFiFuncDesc->GetTextHeight() );
104 nMinWidth=aTxtSize.Width()+aTopLeft.X()
105 +2*aFuncList->GetPosPixel().X();
106 nMinHeight=19*aTxtSize.Height();
107 aCatBox->SelectEntryPos(0);
109 Range aYRange(3*aTxtSize.Height()+aFuncList->GetPosPixel().Y(),
110 GetOutputSizePixel().Height()-2*aTxtSize.Height());
111 aPrivatSplit->SetYRange(aYRange);
112 SelHdl(*aCatBox.get());
115 /*************************************************************************
116 #* Member: ScFunctionWin
117 #*------------------------------------------------------------------------
119 #* Klasse: ScFunctionWin
121 #* Funktion: Destruktor der Klasse ScFunctionWin
123 #* Input: ---
125 #* Output: ---
127 #************************************************************************/
129 ScFunctionWin::~ScFunctionWin()
131 disposeOnce();
134 void ScFunctionWin::dispose()
136 EndListening( rBindings );
137 aPrivatSplit.disposeAndClear();
138 aCatBox.disposeAndClear();
139 aFuncList.disposeAndClear();
140 aDDFuncList.disposeAndClear();
141 aInsertButton.disposeAndClear();
142 aFiFuncDesc.disposeAndClear();
143 pAllFuncList.clear();
144 vcl::Window::dispose();
147 /*************************************************************************
148 #* Member: UpdateFunctionList
149 #*------------------------------------------------------------------------
151 #* Klasse: ScFunctionWin
153 #* Funktion: Aktualisiert die Liste der Funktionen ab-
154 #* haengig von der eingestellten Kategorie.
156 #* Input: ---
158 #* Output: ---
160 #************************************************************************/
162 void ScFunctionWin::InitLRUList()
164 ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
165 pFuncMgr->fillLastRecentlyUsedFunctions(aLRUList);
167 sal_Int32 nSelPos = aCatBox->GetSelectEntryPos();
169 if(nSelPos == 0)
170 UpdateFunctionList();
173 /*************************************************************************
174 #* Member: UpdateFunctionList
175 #*------------------------------------------------------------------------
177 #* Klasse: ScFunctionWin
179 #* Funktion: Aktualisiert die Liste der zuletzt verwendeten Funktionen.
181 #* Input: ---
183 #* Output: ---
185 #************************************************************************/
187 void ScFunctionWin::UpdateLRUList()
189 if (pFuncDesc && pFuncDesc->nFIndex!=0)
191 ScModule* pScMod = SC_MOD();
192 pScMod->InsertEntryToLRUList(pFuncDesc->nFIndex);
196 /*************************************************************************
197 #* Member: SetSize
198 #*------------------------------------------------------------------------
200 #* Klasse: ScFunctionWin
202 #* Funktion: Groesse fuer die einzelnen Controls einzustellen.
204 #* Input: ---
206 #* Output: ---
208 #************************************************************************/
210 void ScFunctionWin::SetSize()
212 SetLeftRightSize();
215 /*************************************************************************
216 #* Member: SetLeftRightSize
217 #*------------------------------------------------------------------------
219 #* Klasse: ScFunctionWin
221 #* Funktion: Groesse fuer die einzelnen Controls einstellen,
222 #* wenn Links oder Rechts angedockt wird.
224 #* Input: ---
226 #* Output: ---
228 #************************************************************************/
230 void ScFunctionWin::SetLeftRightSize()
232 if(!bSizeFlag)
234 bSizeFlag = true;
236 Size aDiffSize=GetSizePixel();
237 Size aNewSize=GetOutputSizePixel();
238 aDiffSize.Width()-=aNewSize.Width();
239 aDiffSize.Height()-=aNewSize.Height();
241 OUString aString("ww");
242 Size aTxtSize( aFuncList->GetTextWidth(aString), aFuncList->GetTextHeight() );
244 Range aYRange(3*aTxtSize.Height()+aFuncList->GetPosPixel().Y(),
245 GetOutputSizePixel().Height()-2*aTxtSize.Height());
246 aPrivatSplit->SetYRange(aYRange);
248 if(aOldSize.Width()!=aNewSize.Width())
249 SetMyWidthLeRi(aNewSize);
251 if(aOldSize.Height()!=aNewSize.Height())
252 SetMyHeightLeRi(aNewSize);
254 aOldSize=aNewSize;
255 aNewSize.Width()+=aDiffSize.Width();
256 aNewSize.Height()+=aDiffSize.Height();
257 bSizeFlag=false;
262 /*************************************************************************
263 #* Member: SetMyWidthLeRi
264 #*------------------------------------------------------------------------
266 #* Klasse: ScFunctionWin
268 #* Funktion: Breite fuer die einzelnen Controls und
269 #* das Fenster einstellen,wenn Li oder Re
271 #* Input: neue Fenstergroesse
273 #* Output: ---
275 #************************************************************************/
277 void ScFunctionWin::SetMyWidthLeRi(Size &aNewSize)
279 if((sal_uLong)aNewSize.Width()<nMinWidth) aNewSize.Width()=nMinWidth;
281 Size aCDSize=aCatBox->GetSizePixel();
282 Size aFLSize=aFuncList->GetSizePixel();
283 Size aSplitterSize=aPrivatSplit->GetSizePixel();
284 Size aFDSize=aFiFuncDesc->GetSizePixel();
286 Point aCDTopLeft=aCatBox->GetPosPixel();
287 Point aFLTopLeft=aFuncList->GetPosPixel();
289 aCDSize.Width()=aNewSize.Width()-aCDTopLeft.X()-aFLTopLeft.X();
290 aFLSize.Width()=aNewSize.Width()-2*aFLTopLeft.X();
291 aFDSize.Width()=aFLSize.Width();
292 aSplitterSize.Width()=aFLSize.Width();
294 aCatBox->SetSizePixel(aCDSize);
295 aFuncList->SetSizePixel(aFLSize);
296 aPrivatSplit->SetSizePixel(aSplitterSize);
297 aFiFuncDesc->SetSizePixel(aFDSize);
300 /*************************************************************************
301 #* Member: SetHeight
302 #*------------------------------------------------------------------------
304 #* Klasse: ScFunctionWin
306 #* Funktion: Hoehe fuer die einzelnen Controls und
307 #* das Fenster einstellen bei Li oder Re
309 #* Input: neue Fenstergroesse
311 #* Output: ---
313 #************************************************************************/
315 void ScFunctionWin::SetMyHeightLeRi(Size &aNewSize)
317 if((sal_uLong)aNewSize.Height()<nMinHeight) aNewSize.Height()=nMinHeight;
319 Size aFLSize=aFuncList->GetSizePixel();
320 Size aSplitterSize=aPrivatSplit->GetSizePixel();
321 Size aFDSize=aFiFuncDesc->GetSizePixel();
323 Point aFLTopLeft=aFuncList->GetPosPixel();
324 Point aSplitterTopLeft=aPrivatSplit->GetPosPixel();
325 Point aFDTopLeft=aFiFuncDesc->GetPosPixel();
327 long nTxtHeight = aFuncList->GetTextHeight();
329 short nY=(short)(3*nTxtHeight+
330 aFuncList->GetPosPixel().Y()+aSplitterSize.Height());
332 aFDTopLeft.Y()=aNewSize.Height()-aFDSize.Height()-4;
333 if(nY>aFDTopLeft.Y())
335 aFDSize.Height()-=nY-aFDTopLeft.Y();
336 aFDTopLeft.Y()=nY;
338 aSplitterTopLeft.Y()=aFDTopLeft.Y()-aSplitterSize.Height()-1;
339 aFLSize.Height()=aSplitterTopLeft.Y()-aFLTopLeft.Y()-1;
341 aFuncList->SetSizePixel(aFLSize);
342 aPrivatSplit->SetPosPixel(aSplitterTopLeft);
343 aFiFuncDesc->SetPosPixel(aFDTopLeft);
344 aFiFuncDesc->SetSizePixel(aFDSize);
348 /*************************************************************************
349 #* Member: SetDescription
350 #*------------------------------------------------------------------------
352 #* Klasse: ScFunctionWin
354 #* Funktion: Erklaerungstext fuer die Funktion einstellen.
356 #* Input: ---
358 #* Output: ---
360 #************************************************************************/
362 void ScFunctionWin::SetDescription()
364 aFiFuncDesc->SetText( EMPTY_OUSTRING );
365 const ScFuncDesc* pDesc =
366 static_cast<const ScFuncDesc*>(pAllFuncList->GetEntryData(
367 pAllFuncList->GetSelectEntryPos() ));
368 if (pDesc)
370 pDesc->initArgumentInfo(); // full argument info is needed
372 OUStringBuffer aBuf(pAllFuncList->GetSelectEntry());
373 aBuf.append(":\n\n");
374 aBuf.append(pDesc->GetParamList());
375 aBuf.append("\n\n");
376 aBuf.append(*pDesc->pFuncDesc);
378 aFiFuncDesc->SetText(aBuf.makeStringAndClear());
379 aFiFuncDesc->StateChanged(StateChangedType::Text);
380 aFiFuncDesc->Invalidate();
381 aFiFuncDesc->Update();
386 /*************************************************************************
387 #* Member: Close
388 #*------------------------------------------------------------------------
390 #* Klasse: ScFunctionWin
392 #* Funktion: Aenderungen erkennen
394 #* Input: ---
396 #* Output: TRUE
398 #************************************************************************/
399 void ScFunctionWin::Notify( SfxBroadcaster&, const SfxHint& /* rHint */ )
403 /// override to set new size of the controls
404 void ScFunctionWin::Resize()
406 SetSize();
407 vcl::Window::Resize();
410 /*************************************************************************
411 #* Member: UpdateFunctionList
412 #*------------------------------------------------------------------------
414 #* Klasse: ScFunctionWin
416 #* Funktion: Aktualisiert die Liste der Funktionen ab-
417 #* haengig von der eingestellten Kategorie.
419 #* Input: ---
421 #* Output: ---
423 #************************************************************************/
425 void ScFunctionWin::UpdateFunctionList()
427 sal_Int32 nSelPos = aCatBox->GetSelectEntryPos();
428 sal_Int32 nCategory = ( LISTBOX_ENTRY_NOTFOUND != nSelPos )
429 ? (nSelPos-1) : 0;
431 pAllFuncList->Clear();
432 pAllFuncList->SetUpdateMode( false );
434 if ( nSelPos > 0 )
436 ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
438 const ScFuncDesc* pDesc = pFuncMgr->First( nCategory );
439 while ( pDesc )
441 pAllFuncList->SetEntryData(
442 pAllFuncList->InsertEntry( *(pDesc->pFuncName) ),
443 const_cast<ScFuncDesc *>(pDesc) );
444 pDesc = pFuncMgr->Next();
447 else // LRU-Liste
449 for (::std::vector<const formula::IFunctionDescription*>::iterator iter=aLRUList.begin();
450 iter != aLRUList.end(); ++iter)
452 const formula::IFunctionDescription* pDesc = *iter;
453 if (pDesc)
454 pAllFuncList->SetEntryData( pAllFuncList->InsertEntry( pDesc->getFunctionName()), const_cast<formula::IFunctionDescription *>(pDesc));
458 pAllFuncList->SetUpdateMode( true );
460 if ( pAllFuncList->GetEntryCount() > 0 )
462 pAllFuncList->Enable();
463 pAllFuncList->SelectEntryPos( 0 );
465 else
467 pAllFuncList->Disable();
471 /*************************************************************************
472 #* Member: DoEnter
473 #*------------------------------------------------------------------------
475 #* Klasse: ScFunctionWin
477 #* Funktion: Eingabe ins Dokument uebernehmen. Wird aufgerufen
478 #* nach betaetigen der Uebernehmen- Schaltflaeche
479 #* oder einem Doppelklick in die Funktionsliste.
481 #* Input: ---
483 #* Output: ---
485 #************************************************************************/
487 void ScFunctionWin::DoEnter()
489 OUString aFirstArgStr;
490 OUString aArgStr;
491 OUString aString=pAllFuncList->GetSelectEntry();
492 SfxViewShell* pCurSh = SfxViewShell::Current();
493 nArgs=0;
495 if(!aString.isEmpty())
498 ScModule* pScMod = SC_MOD();
499 ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( pCurSh );
500 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
501 if(!pScMod->IsEditMode())
503 pScMod->SetInputMode(SC_INPUT_TABLE);
504 // the above call can result in us being disposed
505 if (OutputDevice::isDisposed())
506 return;
507 aString = "=";
508 aString += pAllFuncList->GetSelectEntry();
509 if (pHdl)
510 pHdl->ClearText();
512 const ScFuncDesc* pDesc =
513 static_cast<const ScFuncDesc*>(pAllFuncList->GetEntryData(
514 pAllFuncList->GetSelectEntryPos() ));
515 if (pDesc)
517 pFuncDesc=pDesc;
518 UpdateLRUList();
519 nArgs = pDesc->nArgCount;
520 if(nArgs>0)
522 // NOTE: Theoretically the first parameter could have the
523 // suppress flag as well, but practically it doesn't.
524 aFirstArgStr = pDesc->maDefArgNames[0];
525 aFirstArgStr = comphelper::string::strip(aFirstArgStr, ' ');
526 aFirstArgStr = aFirstArgStr.replaceAll(" ", "_");
527 aArgStr = aFirstArgStr;
528 if ( nArgs != VAR_ARGS && nArgs != PAIRED_VAR_ARGS )
529 { // no VarArgs or Fix plus VarArgs, but not VarArgs only
530 OUString aArgSep("; ");
531 sal_uInt16 nFix;
532 if (nArgs >= PAIRED_VAR_ARGS)
533 nFix = nArgs - PAIRED_VAR_ARGS + 2;
534 else if (nArgs >= VAR_ARGS)
535 nFix = nArgs - VAR_ARGS + 1;
536 else
537 nFix = nArgs;
538 for ( sal_uInt16 nArg = 1;
539 nArg < nFix && !pDesc->pDefArgFlags[nArg].bOptional; nArg++ )
541 if (!pDesc->pDefArgFlags[nArg].bSuppress)
543 aArgStr += aArgSep;
544 OUString sTmp = pDesc->maDefArgNames[nArg];
545 sTmp = comphelper::string::strip(sTmp, ' ');
546 sTmp = sTmp.replaceAll(" ", "_");
547 aArgStr += sTmp;
553 if (pHdl)
555 if (pHdl->GetEditString().isEmpty())
557 aString = "=";
558 aString += pAllFuncList->GetSelectEntry();
560 EditView *pEdView=pHdl->GetActiveView();
561 if(pEdView!=nullptr) // @ Wegen Absturz bei Namen festlegen
563 if(nArgs>0)
565 pHdl->InsertFunction(aString);
566 pEdView->InsertText(aArgStr,true);
567 ESelection aESel=pEdView->GetSelection();
568 aESel.nEndPos = aESel.nStartPos + aFirstArgStr.getLength();
569 pEdView->SetSelection(aESel);
570 pHdl->DataChanged();
572 else
574 aString += "()";
575 pEdView->InsertText(aString);
576 pHdl->DataChanged();
580 InitLRUList();
582 if ( pCurSh )
584 vcl::Window* pShellWnd = pCurSh->GetWindow();
586 if ( pShellWnd )
587 pShellWnd->GrabFocus();
592 /*************************************************************************
593 #* Handle: SelHdl
594 #*------------------------------------------------------------------------
596 #* Klasse: ScFunctionWin
598 #* Funktion: Bei einer Aenderung der Kategorie wird die
599 #* die Liste der Funktionen aktualisiert.
601 #* Input: ---
603 #* Output: ---
605 #************************************************************************/
607 IMPL_LINK_TYPED( ScFunctionWin, SelHdl, ListBox&, rLb, void )
609 if ( &rLb == aCatBox.get() )
611 UpdateFunctionList();
612 SetDescription();
615 if ( &rLb == aFuncList.get() || &rLb == aDDFuncList.get() )
617 SetDescription();
621 /*************************************************************************
622 #* Handle: SelHdl
623 #*------------------------------------------------------------------------
625 #* Klasse: ScFunctionWin
627 #* Funktion: Bei einer Aenderung der Kategorie wird die
628 #* die Liste der Funktionen aktualisiert.
630 #* Input: ---
632 #* Output: ---
634 #************************************************************************/
636 IMPL_LINK_NOARG_TYPED( ScFunctionWin, SetSelectionClickHdl, Button*, void )
638 DoEnter(); // Uebernimmt die Eingabe
640 IMPL_LINK_NOARG_TYPED( ScFunctionWin, SetSelectionHdl, ListBox&, void )
642 DoEnter(); // Uebernimmt die Eingabe
645 /*************************************************************************
646 #* Handle: SetSplitHdl
647 #*------------------------------------------------------------------------
649 #* Klasse: ScFunctionWin
651 #* Funktion: Bei einer Aenderung des Split- Controls werden die
652 #* einzelnen Controls an die neue Groesse angepasst.
654 #* Input: Zeiger auf Control
656 #* Output: ---
658 #************************************************************************/
660 IMPL_LINK_TYPED( ScFunctionWin, SetSplitHdl, ScPrivatSplit&, rCtrl, void )
662 if (&rCtrl == aPrivatSplit.get())
664 short nDeltaY=aPrivatSplit->GetDeltaY();
665 Size aFLSize=aFuncList->GetSizePixel();
666 Size aFDSize=aFiFuncDesc->GetSizePixel();
667 Point aFDTopLeft=aFiFuncDesc->GetPosPixel();
669 aFLSize.Height()+=nDeltaY;
670 aFDSize.Height()-=nDeltaY;
671 aFDTopLeft.Y()+=nDeltaY;
672 aFuncList->SetSizePixel(aFLSize);
673 aFiFuncDesc->SetPosPixel(aFDTopLeft);
674 aFiFuncDesc->SetSizePixel(aFDSize);
678 IMPL_LINK_NOARG_TYPED(ScFunctionWin, TimerHdl, Idle *, void)
680 OUString aString("ww");
681 Size aTxtSize( aFiFuncDesc->GetTextWidth(aString), aFiFuncDesc->GetTextHeight() );
682 Point aTopLeft=aCatBox->GetPosPixel();
683 nMinWidth=aTxtSize.Width()+aTopLeft.X() +2*aFuncList->GetPosPixel().X();
684 nMinHeight=19*aTxtSize.Height();
685 SetSize();
688 void ScFunctionWin::UseSplitterInitPos()
690 if ( IsVisible() && aPrivatSplit->IsEnabled() && aSplitterInitPos != Point() )
692 aPrivatSplit->MoveSplitTo(aSplitterInitPos);
693 aSplitterInitPos = Point(); // use only once
697 void ScFunctionWin::StateChanged( StateChangedType nStateChange )
699 vcl::Window::StateChanged( nStateChange );
701 if (nStateChange == StateChangedType::InitShow)
703 UseSplitterInitPos(); // set initial splitter position if necessary
707 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */