1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
29 #include "scresid.hxx"
30 #include "reffact.hxx"
31 #include "document.hxx"
32 #include "formulacell.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
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() ) ) ),
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();
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
127 #************************************************************************/
129 ScFunctionWin::~ScFunctionWin()
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.
160 #************************************************************************/
162 void ScFunctionWin::InitLRUList()
164 ScFunctionMgr
* pFuncMgr
= ScGlobal::GetStarCalcFunctionMgr();
165 pFuncMgr
->fillLastRecentlyUsedFunctions(aLRUList
);
167 sal_Int32 nSelPos
= aCatBox
->GetSelectEntryPos();
170 UpdateFunctionList();
173 /*************************************************************************
174 #* Member: UpdateFunctionList
175 #*------------------------------------------------------------------------
177 #* Klasse: ScFunctionWin
179 #* Funktion: Aktualisiert die Liste der zuletzt verwendeten Funktionen.
185 #************************************************************************/
187 void ScFunctionWin::UpdateLRUList()
189 if (pFuncDesc
&& pFuncDesc
->nFIndex
!=0)
191 ScModule
* pScMod
= SC_MOD();
192 pScMod
->InsertEntryToLRUList(pFuncDesc
->nFIndex
);
196 /*************************************************************************
198 #*------------------------------------------------------------------------
200 #* Klasse: ScFunctionWin
202 #* Funktion: Groesse fuer die einzelnen Controls einzustellen.
208 #************************************************************************/
210 void ScFunctionWin::SetSize()
215 /*************************************************************************
216 #* Member: SetLeftRightSize
217 #*------------------------------------------------------------------------
219 #* Klasse: ScFunctionWin
221 #* Funktion: Groesse fuer die einzelnen Controls einstellen,
222 #* wenn Links oder Rechts angedockt wird.
228 #************************************************************************/
230 void ScFunctionWin::SetLeftRightSize()
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
);
255 aNewSize
.Width()+=aDiffSize
.Width();
256 aNewSize
.Height()+=aDiffSize
.Height();
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
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 /*************************************************************************
302 #*------------------------------------------------------------------------
304 #* Klasse: ScFunctionWin
306 #* Funktion: Hoehe fuer die einzelnen Controls und
307 #* das Fenster einstellen bei Li oder Re
309 #* Input: neue Fenstergroesse
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();
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.
360 #************************************************************************/
362 void ScFunctionWin::SetDescription()
364 aFiFuncDesc
->SetText( EMPTY_OUSTRING
);
365 const ScFuncDesc
* pDesc
=
366 static_cast<const ScFuncDesc
*>(pAllFuncList
->GetEntryData(
367 pAllFuncList
->GetSelectEntryPos() ));
370 pDesc
->initArgumentInfo(); // full argument info is needed
372 OUStringBuffer
aBuf(pAllFuncList
->GetSelectEntry());
373 aBuf
.append(":\n\n");
374 aBuf
.append(pDesc
->GetParamList());
376 aBuf
.append(*pDesc
->pFuncDesc
);
378 aFiFuncDesc
->SetText(aBuf
.makeStringAndClear());
379 aFiFuncDesc
->StateChanged(StateChangedType::Text
);
380 aFiFuncDesc
->Invalidate();
381 aFiFuncDesc
->Update();
386 /*************************************************************************
388 #*------------------------------------------------------------------------
390 #* Klasse: ScFunctionWin
392 #* Funktion: Aenderungen erkennen
398 #************************************************************************/
399 void ScFunctionWin::Notify( SfxBroadcaster
&, const SfxHint
& /* rHint */ )
403 /// override to set new size of the controls
404 void ScFunctionWin::Resize()
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.
423 #************************************************************************/
425 void ScFunctionWin::UpdateFunctionList()
427 sal_Int32 nSelPos
= aCatBox
->GetSelectEntryPos();
428 sal_Int32 nCategory
= ( LISTBOX_ENTRY_NOTFOUND
!= nSelPos
)
431 pAllFuncList
->Clear();
432 pAllFuncList
->SetUpdateMode( false );
436 ScFunctionMgr
* pFuncMgr
= ScGlobal::GetStarCalcFunctionMgr();
438 const ScFuncDesc
* pDesc
= pFuncMgr
->First( nCategory
);
441 pAllFuncList
->SetEntryData(
442 pAllFuncList
->InsertEntry( *(pDesc
->pFuncName
) ),
443 const_cast<ScFuncDesc
*>(pDesc
) );
444 pDesc
= pFuncMgr
->Next();
449 for (::std::vector
<const formula::IFunctionDescription
*>::iterator iter
=aLRUList
.begin();
450 iter
!= aLRUList
.end(); ++iter
)
452 const formula::IFunctionDescription
* pDesc
= *iter
;
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 );
467 pAllFuncList
->Disable();
471 /*************************************************************************
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.
485 #************************************************************************/
487 void ScFunctionWin::DoEnter()
489 OUString aFirstArgStr
;
491 OUString aString
=pAllFuncList
->GetSelectEntry();
492 SfxViewShell
* pCurSh
= SfxViewShell::Current();
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())
508 aString
+= pAllFuncList
->GetSelectEntry();
512 const ScFuncDesc
* pDesc
=
513 static_cast<const ScFuncDesc
*>(pAllFuncList
->GetEntryData(
514 pAllFuncList
->GetSelectEntryPos() ));
519 nArgs
= pDesc
->nArgCount
;
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("; ");
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;
538 for ( sal_uInt16 nArg
= 1;
539 nArg
< nFix
&& !pDesc
->pDefArgFlags
[nArg
].bOptional
; nArg
++ )
541 if (!pDesc
->pDefArgFlags
[nArg
].bSuppress
)
544 OUString sTmp
= pDesc
->maDefArgNames
[nArg
];
545 sTmp
= comphelper::string::strip(sTmp
, ' ');
546 sTmp
= sTmp
.replaceAll(" ", "_");
555 if (pHdl
->GetEditString().isEmpty())
558 aString
+= pAllFuncList
->GetSelectEntry();
560 EditView
*pEdView
=pHdl
->GetActiveView();
561 if(pEdView
!=nullptr) // @ Wegen Absturz bei Namen festlegen
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
);
575 pEdView
->InsertText(aString
);
584 vcl::Window
* pShellWnd
= pCurSh
->GetWindow();
587 pShellWnd
->GrabFocus();
592 /*************************************************************************
594 #*------------------------------------------------------------------------
596 #* Klasse: ScFunctionWin
598 #* Funktion: Bei einer Aenderung der Kategorie wird die
599 #* die Liste der Funktionen aktualisiert.
605 #************************************************************************/
607 IMPL_LINK_TYPED( ScFunctionWin
, SelHdl
, ListBox
&, rLb
, void )
609 if ( &rLb
== aCatBox
.get() )
611 UpdateFunctionList();
615 if ( &rLb
== aFuncList
.get() || &rLb
== aDDFuncList
.get() )
621 /*************************************************************************
623 #*------------------------------------------------------------------------
625 #* Klasse: ScFunctionWin
627 #* Funktion: Bei einer Aenderung der Kategorie wird die
628 #* die Liste der Funktionen aktualisiert.
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
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();
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: */