tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / formula / source / ui / dlg / parawin.cxx
blob3c6d333a10f02016b3fbe6d0a468138dd59d317b
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 <vcl/svapp.hxx>
22 #include <sal/log.hxx>
24 #include "parawin.hxx"
25 #include <formula/IFunctionDescription.hxx>
26 #include <formula/funcvarargs.h>
27 #include <strings.hrc>
28 #include <bitmaps.hlst>
29 #include <core_resource.hxx>
30 #include <rtl/math.hxx>
32 namespace formula
35 // Formula token argument count is sal_uInt8, max 255, edit offset 254.
36 constexpr sal_uInt16 kMaxArgCount = 255;
37 constexpr sal_uInt16 kMaxArgOffset = kMaxArgCount - 1;
39 ParaWin::ParaWin(weld::Container* pParent,IControlReferenceHandler* _pDlg)
40 : pFuncDesc(nullptr)
41 , pMyParent(_pDlg)
42 , m_sOptional(ForResId(STR_OPTIONAL))
43 , m_sRequired(ForResId(STR_REQUIRED))
44 , m_xBuilder(Application::CreateBuilder(pParent, u"formula/ui/parameter.ui"_ustr))
45 , m_xContainer(m_xBuilder->weld_container(u"ParameterPage"_ustr))
46 , m_xSlider(m_xBuilder->weld_scrolled_window(u"scrollbar"_ustr, true))
47 , m_xParamGrid(m_xBuilder->weld_widget(u"paramgrid"_ustr))
48 , m_xGrid(m_xBuilder->weld_widget(u"grid"_ustr))
49 , m_xFtEditDesc(m_xBuilder->weld_label(u"editdesc"_ustr))
50 , m_xFtArgName(m_xBuilder->weld_label(u"parname"_ustr))
51 , m_xFtArgDesc(m_xBuilder->weld_label(u"pardesc"_ustr))
52 , m_xBtnFx1(m_xBuilder->weld_button(u"FX1"_ustr))
53 , m_xBtnFx2(m_xBuilder->weld_button(u"FX2"_ustr))
54 , m_xBtnFx3(m_xBuilder->weld_button(u"FX3"_ustr))
55 , m_xBtnFx4(m_xBuilder->weld_button(u"FX4"_ustr))
56 , m_xFtArg1(m_xBuilder->weld_label(u"FT_ARG1"_ustr))
57 , m_xFtArg2(m_xBuilder->weld_label(u"FT_ARG2"_ustr))
58 , m_xFtArg3(m_xBuilder->weld_label(u"FT_ARG3"_ustr))
59 , m_xFtArg4(m_xBuilder->weld_label(u"FT_ARG4"_ustr))
60 , m_xEdArg1(new ArgEdit(m_xBuilder->weld_entry(u"ED_ARG1"_ustr)))
61 , m_xEdArg2(new ArgEdit(m_xBuilder->weld_entry(u"ED_ARG2"_ustr)))
62 , m_xEdArg3(new ArgEdit(m_xBuilder->weld_entry(u"ED_ARG3"_ustr)))
63 , m_xEdArg4(new ArgEdit(m_xBuilder->weld_entry(u"ED_ARG4"_ustr)))
64 , m_xRefBtn1(new RefButton(m_xBuilder->weld_button(u"RB_ARG1"_ustr)))
65 , m_xRefBtn2(new RefButton(m_xBuilder->weld_button(u"RB_ARG2"_ustr)))
66 , m_xRefBtn3(new RefButton(m_xBuilder->weld_button(u"RB_ARG3"_ustr)))
67 , m_xRefBtn4(new RefButton(m_xBuilder->weld_button(u"RB_ARG4"_ustr)))
69 // Space for three lines of text in function description.
70 m_xFtEditDesc->set_label(u"X\nX\nX\n"_ustr);
71 auto nEditHeight = m_xFtEditDesc->get_preferred_size().Height();
72 m_xFtEditDesc->set_size_request(-1, nEditHeight);
73 m_xFtEditDesc->set_label(u""_ustr);
74 // Space for two lines of text in parameter description.
75 m_xFtArgDesc->set_label(u"X\nX\n"_ustr);
76 auto nArgHeight = m_xFtArgDesc->get_preferred_size().Height();
77 m_xFtArgDesc->set_size_request(-1, nArgHeight);
78 m_xFtArgDesc->set_label(u""_ustr);
80 m_xBtnFx1->set_from_icon_name(BMP_FX);
81 m_xBtnFx2->set_from_icon_name(BMP_FX);
82 m_xBtnFx3->set_from_icon_name(BMP_FX);
83 m_xBtnFx4->set_from_icon_name(BMP_FX);
85 //lock down initial preferences
86 m_xParamGrid->set_size_request(-1, m_xParamGrid->get_preferred_size().Height());
87 Size aSize(m_xContainer->get_preferred_size());
88 m_xContainer->set_size_request(aSize.Width(), aSize.Height());
90 aDefaultString = m_xFtEditDesc->get_label();
91 nEdFocus = NOT_FOUND;
92 nActiveLine = 0;
94 m_xSlider->connect_vadjustment_changed(LINK(this, ParaWin, ScrollHdl));
96 InitArgInput( 0, *m_xFtArg1, *m_xBtnFx1, *m_xEdArg1, *m_xRefBtn1);
97 InitArgInput( 1, *m_xFtArg2, *m_xBtnFx2, *m_xEdArg2, *m_xRefBtn2);
98 InitArgInput( 2, *m_xFtArg3, *m_xBtnFx3, *m_xEdArg3, *m_xRefBtn3);
99 InitArgInput( 3, *m_xFtArg4, *m_xBtnFx4, *m_xEdArg4, *m_xRefBtn4);
100 ClearAll();
103 void ParaWin::UpdateArgDesc( sal_uInt16 nArg )
105 if (nArg == NOT_FOUND)
106 return;
108 if (nMaxArgs > 4)
109 nArg = sal::static_int_cast<sal_uInt16>( nArg + GetSliderPos() );
111 if ((nMaxArgs <= 0) || (nArg >= nMaxArgs))
112 return;
114 OUString aArgDesc;
115 OUString aArgName;
117 SetArgumentDesc( OUString() );
118 SetArgumentText( OUString() );
120 if ( nArgs < VAR_ARGS )
122 sal_uInt16 nRealArg = (nArg < aVisibleArgMapping.size()) ? aVisibleArgMapping[nArg] : nArg;
123 aArgDesc = pFuncDesc->getParameterDescription(nRealArg);
124 aArgName = pFuncDesc->getParameterName(nRealArg) + " " +
125 ((pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired);
127 else if ( nArgs < PAIRED_VAR_ARGS )
129 sal_uInt16 nFix = nArgs - VAR_ARGS;
130 sal_uInt16 nPos = std::min( nArg, nFix );
131 sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ?
132 aVisibleArgMapping[nPos] : aVisibleArgMapping.back());
133 aArgDesc = pFuncDesc->getParameterDescription(nRealArg);
134 aArgName = pFuncDesc->getParameterName(nRealArg);
135 sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart();
136 if ( nArg >= nVarArgsStart )
137 aArgName += OUString::number( nArg-nVarArgsStart+1 );
138 aArgName += " " + ((nArg > nFix || pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired) ;
140 else
142 sal_uInt16 nFix = nArgs - PAIRED_VAR_ARGS;
143 sal_uInt16 nPos;
144 if ( nArg < nFix )
145 nPos = nArg;
146 else
147 nPos = nFix + ( (nArg-nFix) % 2);
148 sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ?
149 aVisibleArgMapping[nPos] : aVisibleArgMapping.back());
150 aArgDesc = pFuncDesc->getParameterDescription(nRealArg);
151 aArgName = pFuncDesc->getParameterName(nRealArg);
152 sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart();
153 if ( nArg >= nVarArgsStart )
155 sal_Int16 nShifted = pFuncDesc->getFunctionName().equalsIgnoreAsciiCase(u"LET") ? nPos / 2 : 0;
156 aArgName += OUString::number( (nArg-nVarArgsStart)/2 + 1 + nShifted );
158 aArgName += " " + ((nArg > (nFix+1) || pFuncDesc->isParameterOptional(nRealArg)) ? m_sOptional : m_sRequired) ;
161 SetArgumentDesc(aArgDesc);
162 SetArgumentText(aArgName);
165 void ParaWin::UpdateArgInput( sal_uInt16 nOffset, sal_uInt16 i )
167 sal_uInt16 nArg = nOffset + i;
168 if (nArg > kMaxArgOffset)
169 return;
171 if ( nArgs < VAR_ARGS)
173 if (nArg < nMaxArgs)
175 sal_uInt16 nRealArg = aVisibleArgMapping[nArg];
176 SetArgNameFont (i,(pFuncDesc->isParameterOptional(nRealArg))
177 ? aFntLight : aFntBold );
178 SetArgName (i,pFuncDesc->getParameterName(nRealArg));
181 else if ( nArgs < PAIRED_VAR_ARGS)
183 sal_uInt16 nFix = nArgs - VAR_ARGS;
184 sal_uInt16 nPos = std::min( nArg, nFix );
185 sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ?
186 aVisibleArgMapping[nPos] : aVisibleArgMapping.back());
187 SetArgNameFont( i,
188 (nArg > nFix || pFuncDesc->isParameterOptional(nRealArg)) ?
189 aFntLight : aFntBold );
190 sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart();
191 if ( nArg >= nVarArgsStart )
193 OUString aArgName = pFuncDesc->getParameterName(nRealArg) +
194 OUString::number(nArg-nVarArgsStart+1);
195 SetArgName( i, aArgName );
197 else
198 SetArgName( i, pFuncDesc->getParameterName(nRealArg) );
200 else
202 sal_uInt16 nFix = nArgs - PAIRED_VAR_ARGS;
203 sal_uInt16 nPos;
204 if ( nArg < nFix )
205 nPos = nArg;
206 else
207 nPos = nFix + ( (nArg-nFix) % 2);
208 sal_uInt16 nRealArg = (nPos < aVisibleArgMapping.size() ?
209 aVisibleArgMapping[nPos] : aVisibleArgMapping.back());
210 SetArgNameFont( i,
211 (nArg > (nFix+1) || pFuncDesc->isParameterOptional(nRealArg)) ?
212 aFntLight : aFntBold );
213 sal_uInt16 nVarArgsStart = pFuncDesc->getVarArgsStart();
214 if ( nArg >= nVarArgsStart )
216 sal_Int16 nShifted = pFuncDesc->getFunctionName().equalsIgnoreAsciiCase(u"LET") ? nPos / 2 : 0;
217 OUString aArgName = pFuncDesc->getParameterName(nRealArg) +
218 OUString::number( (nArg-nVarArgsStart)/2 + 1 + nShifted);
219 SetArgName( i, aArgName );
221 else
222 SetArgName( i, pFuncDesc->getParameterName(nRealArg) );
224 if (nArg < nMaxArgs)
225 aArgInput[i].SetArgVal(aParaArray[nArg]);
228 ParaWin::~ParaWin()
230 // #i66422# if the focus changes during destruction of the controls,
231 // don't call the focus handlers
232 Link<weld::Widget&,void> aEmptyLink;
233 m_xBtnFx1->connect_focus_in(aEmptyLink);
234 m_xBtnFx2->connect_focus_in(aEmptyLink);
235 m_xBtnFx3->connect_focus_in(aEmptyLink);
236 m_xBtnFx4->connect_focus_in(aEmptyLink);
239 void ParaWin::SetActiveLine(sal_uInt16 no)
241 if (no >= nMaxArgs)
242 return;
244 tools::Long nOffset = GetSliderPos();
245 nActiveLine=no;
246 tools::Long nNewEdPos=static_cast<tools::Long>(nActiveLine)-nOffset;
247 if(nNewEdPos<0 || nNewEdPos>3)
249 nOffset+=nNewEdPos;
250 SetSliderPos(static_cast<sal_uInt16>(nOffset));
251 nOffset=GetSliderPos();
253 nEdFocus=no-static_cast<sal_uInt16>(nOffset);
254 UpdateArgDesc( nEdFocus );
257 RefEdit* ParaWin::GetActiveEdit()
259 if (nMaxArgs > 0 && nEdFocus != NOT_FOUND)
261 return aArgInput[nEdFocus].GetArgEdPtr();
263 else
265 return nullptr;
270 OUString ParaWin::GetArgument(sal_uInt16 no)
272 OUString aStr;
273 if(no<aParaArray.size())
275 aStr=aParaArray[no];
276 if(no==nActiveLine && aStr.isEmpty())
277 aStr += " ";
279 return aStr;
282 OUString ParaWin::GetActiveArgName() const
284 OUString aStr;
285 if (nMaxArgs > 0 && nEdFocus != NOT_FOUND)
287 aStr=aArgInput[nEdFocus].GetArgName();
289 return aStr;
293 void ParaWin::SetArgument(sal_uInt16 no, std::u16string_view aString)
295 if (no < aParaArray.size())
296 aParaArray[no] = comphelper::string::stripStart(aString, ' ');
299 void ParaWin::SetArgumentFonts(const vcl::Font&aBoldFont,const vcl::Font&aLightFont)
301 aFntBold=aBoldFont;
302 aFntLight=aLightFont;
305 void ParaWin::SetFunctionDesc(const IFunctionDescription* pFDesc)
307 pFuncDesc=pFDesc;
309 SetArgumentDesc( OUString() );
310 SetArgumentText( OUString() );
311 SetEditDesc( OUString() );
312 nMaxArgs = nArgs = 0;
313 if ( pFuncDesc!=nullptr)
315 if ( !pFuncDesc->getDescription().isEmpty() )
317 SetEditDesc(pFuncDesc->getDescription());
319 else
321 SetEditDesc(aDefaultString);
323 nArgs = pFuncDesc->getSuppressedArgumentCount();
324 nMaxArgs = std::min( nArgs, kMaxArgCount);
325 if (sal_uInt16 nVarArgsLimit = pFuncDesc->getVarArgsLimit())
326 nMaxArgs = std::min( nVarArgsLimit, nMaxArgs);
327 pFuncDesc->fillVisibleArgumentMapping(aVisibleArgMapping);
328 m_xSlider->set_vpolicy(VclPolicyType::NEVER);
329 m_xSlider->set_size_request(-1, -1);
330 OUString sHelpId = pFuncDesc->getHelpId();
331 m_xContainer->set_help_id(sHelpId);
332 m_xEdArg1->GetWidget()->set_help_id(sHelpId);
333 m_xEdArg2->GetWidget()->set_help_id(sHelpId);
334 m_xEdArg3->GetWidget()->set_help_id(sHelpId);
335 m_xEdArg4->GetWidget()->set_help_id(sHelpId);
337 SetActiveLine(0);
339 else
341 nActiveLine=0;
346 void ParaWin::SetArgumentText(const OUString& aText)
348 m_xFtArgName->set_label(aText);
351 void ParaWin::SetArgumentDesc(const OUString& aText)
353 m_xFtArgDesc->set_label(aText);
356 void ParaWin::SetEditDesc(const OUString& aText)
358 m_xFtEditDesc->set_label(aText);
361 void ParaWin::SetArgName(sal_uInt16 no,const OUString& aText)
363 aArgInput[no].SetArgName(aText);
364 aArgInput[no].UpdateAccessibleNames();
367 void ParaWin::SetArgNameFont(sal_uInt16 no,const vcl::Font& aFont)
369 aArgInput[no].SetArgNameFont(aFont);
372 void ParaWin::SetEdFocus()
374 UpdateArgDesc(0);
375 if(!aParaArray.empty())
376 aArgInput[0].GetArgEdPtr()->GrabFocus();
379 void ParaWin::InitArgInput(sal_uInt16 nPos, weld::Label& rFtArg, weld::Button& rBtnFx,
380 ArgEdit& rEdArg, RefButton& rRefBtn)
383 rRefBtn.SetReferences(pMyParent, &rEdArg);
384 rEdArg.SetReferences(pMyParent, &rFtArg);
386 aArgInput[nPos].InitArgInput (&rFtArg,&rBtnFx,&rEdArg,&rRefBtn);
388 aArgInput[nPos].Hide();
390 aArgInput[nPos].SetFxClickHdl ( LINK( this, ParaWin, GetFxHdl ) );
391 aArgInput[nPos].SetFxFocusHdl ( LINK( this, ParaWin, GetFxFocusHdl ) );
392 aArgInput[nPos].SetEdFocusHdl ( LINK( this, ParaWin, GetEdFocusHdl ) );
393 aArgInput[nPos].SetEdModifyHdl ( LINK( this, ParaWin, ModifyHdl ) );
394 aArgInput[nPos].UpdateAccessibleNames();
397 void ParaWin::ClearAll()
399 SetFunctionDesc(nullptr);
400 SetArgumentOffset(0);
403 void ParaWin::SetArgumentOffset(sal_uInt16 nOffset)
405 aParaArray.clear();
406 m_xSlider->vadjustment_set_value(0);
408 aParaArray.resize(nMaxArgs);
410 if (nMaxArgs > 0)
412 for ( int i=0; i<4 && i<nMaxArgs; i++ )
414 aArgInput[i].SetArgVal(OUString());
415 aArgInput[i].GetArgEdPtr()->Init(
416 (i==0) ? nullptr : aArgInput[i-1].GetArgEdPtr(),
417 (i==3 || i==nMaxArgs-1) ? nullptr : aArgInput[i+1].GetArgEdPtr(),
418 *m_xSlider, *this, nMaxArgs );
422 UpdateParas();
424 if (nMaxArgs < 5)
426 m_xSlider->set_vpolicy(VclPolicyType::NEVER);
427 m_xSlider->set_size_request(-1, -1);
429 else
431 m_xSlider->vadjustment_configure(nOffset, 0, nMaxArgs, 1, 4, 4);
432 m_xSlider->set_vpolicy(VclPolicyType::ALWAYS);
433 Size aPrefSize(m_xGrid->get_preferred_size());
434 m_xSlider->set_size_request(aPrefSize.Width(), aPrefSize.Height());
438 void ParaWin::UpdateParas()
440 sal_uInt16 i;
441 sal_uInt16 nOffset = GetSliderPos();
443 if ( nMaxArgs > 0 )
445 for ( i=0; (i<nMaxArgs) && (i<4); i++ )
447 UpdateArgInput( nOffset, i );
448 aArgInput[i].Show();
452 for ( i=nMaxArgs; i<4; i++ )
453 aArgInput[i].Hide();
457 sal_uInt16 ParaWin::GetSliderPos() const
459 return static_cast<sal_uInt16>(m_xSlider->vadjustment_get_value());
462 void ParaWin::SetSliderPos(sal_uInt16 nSliderPos)
464 sal_uInt16 nOffset = GetSliderPos();
466 if(m_xSlider->get_visible() && nOffset!=nSliderPos)
468 m_xSlider->vadjustment_set_value(nSliderPos);
469 for ( sal_uInt16 i=0; i<4; i++ )
471 UpdateArgInput( nSliderPos, i );
476 void ParaWin::SliderMoved()
478 sal_uInt16 nOffset = GetSliderPos();
480 for ( sal_uInt16 i=0; i<4; i++ )
482 UpdateArgInput( nOffset, i );
484 if(nEdFocus!=NOT_FOUND)
486 UpdateArgDesc( nEdFocus );
487 aArgInput[nEdFocus].SelectAll();
488 nActiveLine=nEdFocus+nOffset;
489 ArgumentModified();
490 aArgInput[nEdFocus].SelectAll(); // ensure all is still selected
491 aArgInput[nEdFocus].UpdateAccessibleNames();
495 void ParaWin::ArgumentModified()
497 aArgModifiedLink.Call(*this);
500 IMPL_LINK( ParaWin, GetFxHdl, ArgInput&, rPtr, void )
502 sal_uInt16 nOffset = GetSliderPos();
503 nEdFocus=NOT_FOUND;
504 for (size_t nPos=0; nPos < std::size(aArgInput); ++nPos)
506 if(&rPtr == &aArgInput[nPos])
508 nEdFocus=nPos;
509 break;
513 if(nEdFocus!=NOT_FOUND)
515 aArgInput[nEdFocus].SelectAll();
516 nActiveLine=nEdFocus+nOffset;
517 aFxLink.Call(*this);
521 IMPL_LINK( ParaWin, GetFxFocusHdl, ArgInput&, rPtr, void )
523 sal_uInt16 nOffset = GetSliderPos();
524 nEdFocus=NOT_FOUND;
525 for (size_t nPos=0; nPos < SAL_N_ELEMENTS(aArgInput); ++nPos)
527 if(&rPtr == &aArgInput[nPos])
529 nEdFocus=nPos;
530 break;
534 if(nEdFocus!=NOT_FOUND)
536 aArgInput[nEdFocus].SelectAll();
537 UpdateArgDesc( nEdFocus );
538 nActiveLine=nEdFocus+nOffset;
542 IMPL_LINK( ParaWin, GetEdFocusHdl, ArgInput&, rPtr, void )
544 sal_uInt16 nOffset = GetSliderPos();
545 nEdFocus=NOT_FOUND;
546 for (size_t nPos=0; nPos < SAL_N_ELEMENTS(aArgInput); ++nPos)
548 if(&rPtr == &aArgInput[nPos])
550 nEdFocus=nPos;
551 break;
555 if(nEdFocus!=NOT_FOUND)
557 aArgInput[nEdFocus].SelectAll();
558 UpdateArgDesc( nEdFocus );
559 nActiveLine=nEdFocus+nOffset;
560 ArgumentModified();
561 aArgInput[nEdFocus].SelectAll(); // ensure all is still selected
562 aArgInput[nEdFocus].UpdateAccessibleNames();
566 IMPL_LINK_NOARG(ParaWin, ScrollHdl, weld::ScrolledWindow&, void)
568 SliderMoved();
571 IMPL_LINK( ParaWin, ModifyHdl, ArgInput&, rPtr, void )
573 sal_uInt16 nOffset = GetSliderPos();
574 nEdFocus=NOT_FOUND;
575 for (size_t nPos=0; nPos < SAL_N_ELEMENTS(aArgInput); ++nPos)
577 if(&rPtr == &aArgInput[nPos])
579 nEdFocus=nPos;
580 break;
583 if(nEdFocus!=NOT_FOUND)
585 size_t nPara = nEdFocus + nOffset;
586 if (nPara < aParaArray.size())
587 aParaArray[nPara] = aArgInput[nEdFocus].GetArgVal();
588 else
590 SAL_WARN("formula.ui","ParaWin::ModifyHdl - shot in foot: nPara " <<
591 nPara << " >= aParaArray.size() " << aParaArray.size() <<
592 " with nEdFocus " << nEdFocus <<
593 " and aArgInput[nEdFocus].GetArgVal() '" << aArgInput[nEdFocus].GetArgVal() << "'");
595 UpdateArgDesc( nEdFocus);
596 nActiveLine = static_cast<sal_uInt16>(nPara);
599 ArgumentModified();
603 } // formula
605 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */