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 <vcl/event.hxx>
21 #include <vcl/svapp.hxx>
22 #include <formula/IFunctionDescription.hxx>
24 #include "funcpage.hxx"
25 #include <unotools/syslocale.hxx>
26 #include <unotools/charclass.hxx>
30 IMPL_LINK(FuncPage
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
32 if (rKEvt
.GetCharCode() == ' ')
34 aDoubleClickLink
.Call(*this);
40 // tdf#104487 - remember last used function category - set default to All category
41 sal_Int32
FuncPage::m_nRememberedFunctionCategory
= 1;
43 FuncPage::FuncPage(weld::Container
* pParent
, const IFunctionManager
* _pFunctionManager
)
44 : m_xBuilder(Application::CreateBuilder(pParent
, "formula/ui/functionpage.ui"))
45 , m_xContainer(m_xBuilder
->weld_container("FunctionPage"))
46 , m_xLbCategory(m_xBuilder
->weld_combo_box("category"))
47 , m_xLbFunction(m_xBuilder
->weld_tree_view("function"))
48 , m_xLbFunctionSearchString(m_xBuilder
->weld_entry("search"))
49 , m_pFunctionManager(_pFunctionManager
)
51 m_xLbFunction
->make_sorted();
52 m_aHelpId
= m_xLbFunction
->get_help_id();
54 m_pFunctionManager
->fillLastRecentlyUsedFunctions(aLRUList
);
56 const sal_uInt32 nCategoryCount
= m_pFunctionManager
->getCount();
57 for (sal_uInt32 j
= 0; j
< nCategoryCount
; ++j
)
59 const IFunctionCategory
* pCategory
= m_pFunctionManager
->getCategory(j
);
60 OUString
sId(weld::toId(pCategory
));
61 m_xLbCategory
->append(sId
, pCategory
->getName());
64 // tdf#104487 - remember last used function category
65 m_xLbCategory
->set_active(m_nRememberedFunctionCategory
);
66 OUString searchStr
= m_xLbFunctionSearchString
->get_text();
67 UpdateFunctionList(searchStr
);
68 // lock to its initial size
69 m_xLbFunction
->set_size_request(m_xLbFunction
->get_preferred_size().Width(),
70 m_xLbFunction
->get_height_rows(15));
71 m_xLbCategory
->connect_changed(LINK(this, FuncPage
, SelComboBoxHdl
));
72 m_xLbFunction
->connect_changed(LINK(this, FuncPage
, SelTreeViewHdl
));
73 m_xLbFunction
->connect_row_activated(LINK(this, FuncPage
, DblClkHdl
));
74 m_xLbFunction
->connect_key_press(LINK(this, FuncPage
, KeyInputHdl
));
75 m_xLbFunctionSearchString
->connect_changed(LINK(this, FuncPage
, ModifyHdl
));
77 m_xLbFunctionSearchString
->grab_focus();
80 FuncPage::~FuncPage() {}
82 void FuncPage::impl_addFunctions(const IFunctionCategory
* _pCategory
)
84 const sal_uInt32 nCount
= _pCategory
->getCount();
85 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
87 TFunctionDesc
pDesc(_pCategory
->getFunction(i
));
88 if (!pDesc
->isHidden())
90 OUString
sId(weld::toId(pDesc
));
91 m_xLbFunction
->append(sId
, pDesc
->getFunctionName());
96 //aStr is non-empty when user types in the search box to search some function
97 void FuncPage::UpdateFunctionList(const OUString
& aStr
)
99 m_xLbFunction
->clear();
100 m_xLbFunction
->freeze();
102 const sal_Int32 nSelPos
= m_xLbCategory
->get_active();
103 // tdf#104487 - remember last used function category
104 m_nRememberedFunctionCategory
= nSelPos
;
106 if (aStr
.isEmpty() || nSelPos
== 0)
108 const IFunctionCategory
* pCategory
109 = weld::fromId
<const IFunctionCategory
*>(m_xLbCategory
->get_id(nSelPos
));
113 if (pCategory
== nullptr)
115 const sal_uInt32 nCount
= m_pFunctionManager
->getCount();
116 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
118 impl_addFunctions(m_pFunctionManager
->getCategory(i
));
123 impl_addFunctions(pCategory
);
128 for (auto const& elem
: aLRUList
)
130 if (elem
) // may be null if a function is no longer available
132 OUString
sId(weld::toId(elem
));
133 m_xLbFunction
->append(sId
, elem
->getFunctionName());
140 SvtSysLocale aSysLocale
;
141 const CharClass
& rCharClass
= aSysLocale
.GetCharClass();
142 const OUString
aSearchStr(rCharClass
.uppercase(aStr
));
144 const sal_uInt32 nCategoryCount
= m_pFunctionManager
->getCount();
145 // Category listbox holds additional entries for Last Used and All, so
146 // the offset should be two but hard coded numbers are ugly...
147 const sal_Int32 nCategoryOffset
= m_xLbCategory
->get_count() - nCategoryCount
;
148 // If a real category (not Last Used or All) is selected, list only
149 // functions of that category. Else list all, LRU is handled above.
150 sal_Int32 nCatBeg
= (nSelPos
== -1 ? -1 : nSelPos
- nCategoryOffset
);
155 nCatEnd
= nCategoryCount
;
159 nCatEnd
= nCatBeg
+ 1;
161 for (sal_uInt32 i
= nCatBeg
; i
< nCatEnd
; ++i
)
163 const IFunctionCategory
* pCategory
= m_pFunctionManager
->getCategory(i
);
164 const sal_uInt32 nFunctionCount
= pCategory
->getCount();
165 for (sal_uInt32 j
= 0; j
< nFunctionCount
; ++j
)
167 TFunctionDesc
pDesc(pCategory
->getFunction(j
));
168 // tdf#146781 - search for the desired function also in the description
169 if (rCharClass
.uppercase(pDesc
->getFunctionName()).indexOf(aSearchStr
) >= 0
170 || rCharClass
.uppercase(pDesc
->getDescription()).indexOf(aSearchStr
) >= 0)
172 if (!pDesc
->isHidden())
174 OUString
sId(weld::toId(pDesc
));
175 m_xLbFunction
->append(sId
, pDesc
->getFunctionName());
182 m_xLbFunction
->thaw();
183 // Ensure no function is selected so the Next button doesn't overwrite a
184 // function that is not in the list with an arbitrary selected one.
185 m_xLbFunction
->unselect_all();
188 SelTreeViewHdl(*m_xLbFunction
);
191 IMPL_LINK_NOARG(FuncPage
, SelComboBoxHdl
, weld::ComboBox
&, void)
193 OUString searchStr
= m_xLbFunctionSearchString
->get_text();
194 m_xLbFunction
->set_help_id(m_aHelpId
);
195 UpdateFunctionList(searchStr
);
198 IMPL_LINK_NOARG(FuncPage
, SelTreeViewHdl
, weld::TreeView
&, void)
200 const IFunctionDescription
* pDesc
= GetFuncDesc(GetFunction());
203 const OUString sHelpId
= pDesc
->getHelpId();
204 if (!sHelpId
.isEmpty())
205 m_xLbFunction
->set_help_id(sHelpId
);
207 aSelectionLink
.Call(*this);
210 IMPL_LINK_NOARG(FuncPage
, DblClkHdl
, weld::TreeView
&, bool)
212 aDoubleClickLink
.Call(*this);
216 IMPL_LINK_NOARG(FuncPage
, ModifyHdl
, weld::Entry
&, void)
218 // While typing select All category.
219 m_xLbCategory
->set_active(1);
220 OUString searchStr
= m_xLbFunctionSearchString
->get_text();
221 UpdateFunctionList(searchStr
);
224 void FuncPage::SetCategory(sal_Int32 nCat
)
226 // tdf#104487 - remember last used function category
227 m_nRememberedFunctionCategory
= nCat
;
228 m_xLbCategory
->set_active(nCat
);
229 UpdateFunctionList(OUString());
232 sal_Int32
FuncPage::GetFuncPos(const IFunctionDescription
* _pDesc
)
234 return m_xLbFunction
->find_id(weld::toId(_pDesc
));
237 void FuncPage::SetFunction(sal_Int32 nFunc
)
240 m_xLbFunction
->unselect_all();
242 m_xLbFunction
->select(nFunc
);
245 void FuncPage::SetFocus() { m_xLbFunction
->grab_focus(); }
247 sal_Int32
FuncPage::GetCategory() const { return m_xLbCategory
->get_active(); }
249 sal_Int32
FuncPage::GetCategoryEntryCount() const { return m_xLbCategory
->get_count(); }
251 sal_Int32
FuncPage::GetFunction() const { return m_xLbFunction
->get_selected_index(); }
253 sal_Int32
FuncPage::GetFunctionEntryCount() const { return m_xLbFunction
->n_children(); }
255 OUString
FuncPage::GetSelFunctionName() const { return m_xLbFunction
->get_selected_text(); }
257 const IFunctionDescription
* FuncPage::GetFuncDesc(sal_Int32 nPos
) const
261 // not pretty, but hopefully rare
262 return weld::fromId
<const IFunctionDescription
*>(m_xLbFunction
->get_id(nPos
));
267 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */