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 "NumberFormatPropertyPanel.hxx"
21 #include <sc.hrc>
22 #include <sfx2/bindings.hxx>
23 #include <sfx2/dispatch.hxx>
24 #include <svl/intitem.hxx>
25 #include <svl/stritem.hxx>
26 #include <svl/itemset.hxx>
27 #include <svx/numfmtsh.hxx>
28 #include <o3tl/string_view.hxx>
29 #include <com/sun/star/lang/IllegalArgumentException.hpp>
30
31 using namespace css;
32 using namespace css::uno;
33
34 namespace sc::sidebar {
35
NumberFormatPropertyPanel(weld::Widget * pParent,const css::uno::Reference<css::frame::XFrame> & rxFrame,SfxBindings * pBindings)36 NumberFormatPropertyPanel::NumberFormatPropertyPanel(
37 weld::Widget* pParent,
38 const css::uno::Reference<css::frame::XFrame>& rxFrame,
39 SfxBindings* pBindings)
40 : PanelLayout(pParent,u"NumberFormatPropertyPanel"_ustr, u"modules/scalc/ui/sidebarnumberformat.ui"_ustr)
41 , mxLbCategory(m_xBuilder->weld_combo_box(u"numberformatcombobox"_ustr))
42 , mxTBCategory(m_xBuilder->weld_toolbar(u"numberformat"_ustr))
43 , mxCategoryDispatch(new ToolbarUnoDispatcher(*mxTBCategory, *m_xBuilder, rxFrame))
44 , mxFtDecimals(m_xBuilder->weld_label(u"decimalplaceslabel"_ustr))
45 , mxEdDecimals(m_xBuilder->weld_spin_button(u"decimalplaces"_ustr))
46 , mxFtDenominator(m_xBuilder->weld_label(u"denominatorplaceslabel"_ustr))
47 , mxEdDenominator(m_xBuilder->weld_spin_button(u"denominatorplaces"_ustr))
48 , mxFtLeadZeroes(m_xBuilder->weld_label(u"leadingzeroeslabel"_ustr))
49 , mxEdLeadZeroes(m_xBuilder->weld_spin_button(u"leadingzeroes"_ustr))
50 , mxBtnNegRed(m_xBuilder->weld_check_button(u"negativenumbersred"_ustr))
51 , mxBtnThousand(m_xBuilder->weld_check_button(u"thousandseparator"_ustr))
52 , mxBtnEngineering(m_xBuilder->weld_check_button(u"engineeringnotation"_ustr))
53 , maNumFormatControl(SID_NUMBER_TYPE_FORMAT, *pBindings, *this)
54 , maFormatControl(SID_NUMBER_FORMAT, *pBindings, *this)
55 , mnCategorySelected(0)
56 , mpBindings(pBindings)
57 {
58 Initialize();
59 }
60
~NumberFormatPropertyPanel()61 NumberFormatPropertyPanel::~NumberFormatPropertyPanel()
62 {
63 mxLbCategory.reset();
64 mxCategoryDispatch.reset();
65 mxTBCategory.reset();
66 mxFtDecimals.reset();
67 mxEdDecimals.reset();
68 mxFtDenominator.reset();
69 mxEdDenominator.reset();
70 mxFtLeadZeroes.reset();
71 mxEdLeadZeroes.reset();
72 mxBtnNegRed.reset();
73 mxBtnThousand.reset();
74 mxBtnEngineering.reset();
75
76 maNumFormatControl.dispose();
77 maFormatControl.dispose();
78 }
79
Initialize()80 void NumberFormatPropertyPanel::Initialize()
81 {
82 mxLbCategory->connect_changed( LINK(this, NumberFormatPropertyPanel, NumFormatSelectHdl) );
83 mxLbCategory->set_active(0);
84
85 Link<weld::SpinButton&,void> aLink = LINK(this, NumberFormatPropertyPanel, NumFormatValueHdl);
86
87 mxEdDecimals->connect_value_changed( aLink );
88 mxEdDenominator->connect_value_changed( aLink );
89 mxEdLeadZeroes->connect_value_changed( aLink );
90
91 mxBtnNegRed->connect_toggled( LINK(this, NumberFormatPropertyPanel, NumFormatValueClickHdl) );
92 mxBtnThousand->connect_toggled( LINK(this, NumberFormatPropertyPanel, NumFormatValueClickHdl) );
93 mxBtnEngineering->connect_toggled( LINK(this, NumberFormatPropertyPanel, NumFormatValueClickHdl) );
94 }
95
IMPL_LINK(NumberFormatPropertyPanel,NumFormatSelectHdl,weld::ComboBox &,rBox,void)96 IMPL_LINK( NumberFormatPropertyPanel, NumFormatSelectHdl, weld::ComboBox&, rBox, void )
97 {
98 const sal_Int32 nVal = rBox.get_active();
99 if( nVal != mnCategorySelected )
100 {
101 SfxUInt16Item aItem( SID_NUMBER_TYPE_FORMAT, nVal );
102 GetBindings()->GetDispatcher()->ExecuteList(SID_NUMBER_TYPE_FORMAT,
103 SfxCallMode::RECORD, { &aItem });
104 mnCategorySelected = nVal;
105 }
106 }
107
IMPL_LINK_NOARG(NumberFormatPropertyPanel,NumFormatValueClickHdl,weld::Toggleable &,void)108 IMPL_LINK_NOARG( NumberFormatPropertyPanel, NumFormatValueClickHdl, weld::Toggleable&, void )
109 {
110 NumFormatValueHdl(*mxEdDecimals);
111 }
112
IMPL_LINK_NOARG(NumberFormatPropertyPanel,NumFormatValueHdl,weld::SpinButton &,void)113 IMPL_LINK_NOARG( NumberFormatPropertyPanel, NumFormatValueHdl, weld::SpinButton&, void )
114 {
115 OUString aFormat;
116 OUString sBreak = u","_ustr;
117 bool bThousand = ( mxBtnThousand->get_visible() && mxBtnThousand->get_sensitive() && mxBtnThousand->get_active() )
118 || ( mxBtnEngineering->get_visible() && mxBtnEngineering->get_sensitive() && mxBtnEngineering->get_active() );
119 bool bNegRed = mxBtnNegRed->get_sensitive() && mxBtnNegRed->get_active();
120 sal_uInt16 nPrecision = (mxEdDecimals->get_sensitive() && mxEdDecimals->get_visible())
121 ? static_cast<sal_uInt16>(mxEdDecimals->get_value())
122 : (mxEdDenominator->get_sensitive() && mxEdDenominator->get_visible())
123 ? static_cast<sal_uInt16>(mxEdDenominator->get_value())
124 : sal_uInt16(0);
125 sal_uInt16 nLeadZeroes = (mxEdLeadZeroes->get_sensitive())
126 ? static_cast<sal_uInt16>(mxEdLeadZeroes->get_value())
127 : sal_uInt16(0);
128
129 OUString sThousand = OUString::number(static_cast<sal_Int32>(bThousand));
130 OUString sNegRed = OUString::number(static_cast<sal_Int32>(bNegRed));
131 OUString sPrecision = OUString::number(nPrecision);
132 OUString sLeadZeroes = OUString::number(nLeadZeroes);
133
134 aFormat += sThousand +
135 sBreak +
136 sNegRed +
137 sBreak +
138 sPrecision +
139 sBreak +
140 sLeadZeroes +
141 sBreak;
142
143 SfxStringItem aItem( SID_NUMBER_FORMAT, aFormat );
144 GetBindings()->GetDispatcher()->ExecuteList(SID_NUMBER_FORMAT,
145 SfxCallMode::RECORD, { &aItem });
146 }
147
Create(weld::Widget * pParent,const css::uno::Reference<css::frame::XFrame> & rxFrame,SfxBindings * pBindings)148 std::unique_ptr<PanelLayout> NumberFormatPropertyPanel::Create (
149 weld::Widget* pParent,
150 const css::uno::Reference<css::frame::XFrame>& rxFrame,
151 SfxBindings* pBindings)
152 {
153 if (pParent == nullptr)
154 throw lang::IllegalArgumentException(u"no parent Window given to NumberFormatPropertyPanel::Create"_ustr, nullptr, 0);
155 if ( ! rxFrame.is())
156 throw lang::IllegalArgumentException(u"no XFrame given to NumberFormatPropertyPanel::Create"_ustr, nullptr, 1);
157 if (pBindings == nullptr)
158 throw lang::IllegalArgumentException(u"no SfxBindings given to NumberFormatPropertyPanel::Create"_ustr, nullptr, 2);
159
160 return std::make_unique<NumberFormatPropertyPanel>(pParent, rxFrame, pBindings);
161 }
162
HandleContextChange(const vcl::EnumContext & rContext)163 void NumberFormatPropertyPanel::HandleContextChange(
164 const vcl::EnumContext& rContext)
165 {
166 if(maContext == rContext)
167 {
168 // Nothing to do.
169 return;
170 }
171
172 maContext = rContext;
173 }
174
NotifyItemUpdate(sal_uInt16 nSID,SfxItemState eState,const SfxPoolItem * pState)175 void NumberFormatPropertyPanel::NotifyItemUpdate(
176 sal_uInt16 nSID,
177 SfxItemState eState,
178 const SfxPoolItem* pState)
179 {
180 switch(nSID)
181 {
182 case SID_NUMBER_TYPE_FORMAT:
183 {
184 if( eState >= SfxItemState::DEFAULT)
185 {
186 const SfxUInt16Item* pItem = static_cast<const SfxUInt16Item*>(pState);
187 sal_uInt16 nVal = pItem->GetValue();
188 mnCategorySelected = nVal;
189 mxLbCategory->set_active(nVal);
190 // There is an offset between category list enum and listbox in side panel
191 SvxNumberFormatCategory nCategory = static_cast< SvxNumberFormatCategory >( nVal + 1 );
192 if (nCategory <= CAT_FRACTION && // General, Number, Percent, Currency, Time, Scientific, Fraction
193 nCategory != CAT_DATE ) // not Date
194 {
195 // For scientific, Thousand separator is replaced by Engineering notation
196 bool bIsScientific ( nCategory == CAT_SCIENTIFIC );
197 // For fraction, Decimal places is replaced by Denominator places
198 bool bIsFraction ( nCategory == CAT_FRACTION );
199 // For Time, Decimal places and NegRed available
200 bool bIsTime ( nCategory == CAT_TIME );
201 mxBtnThousand->set_visible( !bIsScientific );
202 mxBtnThousand->set_sensitive( !bIsScientific && !bIsTime );
203 mxBtnThousand->set_active(false);
204 mxBtnEngineering->set_visible(bIsScientific);
205 mxBtnEngineering->set_sensitive(bIsScientific);
206 mxBtnEngineering->set_active(false);
207 mxBtnNegRed->set_sensitive(true);
208 mxFtDenominator->set_visible(bIsFraction);
209 mxEdDenominator->set_visible(bIsFraction);
210 mxFtDenominator->set_sensitive(bIsFraction);
211 mxEdDenominator->set_sensitive(bIsFraction);
212 mxFtDecimals->set_visible(!bIsFraction);
213 mxEdDecimals->set_visible(!bIsFraction);
214 mxFtDecimals->set_sensitive(!bIsFraction);
215 mxEdDecimals->set_sensitive(!bIsFraction);
216 mxFtLeadZeroes->set_sensitive( !bIsTime );
217 mxEdLeadZeroes->set_sensitive( !bIsTime );
218 }
219 else
220 DisableControls();
221 }
222 else
223 {
224 DisableControls();
225 mxLbCategory->set_active(-1);
226 mnCategorySelected = 0;
227 }
228 }
229 break;
230 case SID_NUMBER_FORMAT:
231 {
232 bool bThousand = false;
233 bool bNegRed = false;
234 sal_uInt16 nPrecision = 0;
235 sal_uInt16 nLeadZeroes = 0;
236 bool bNatNum12 = false;
237 SvxNumberFormatCategory nCategory = static_cast< SvxNumberFormatCategory >( mnCategorySelected + 1 );
238 if( eState >= SfxItemState::DEFAULT)
239 {
240 const SfxStringItem* pItem = static_cast<const SfxStringItem*>(pState);
241 const OUString& aCode = pItem->GetValue();
242 sal_Int32 nIndex = 0;
243 sal_Int32 aFormat[5] = {0};
244 for (sal_Int32 & rn : aFormat)
245 {
246 rn = o3tl::toInt32(o3tl::getToken(aCode, 0, ',', nIndex));
247 if (nIndex<0)
248 break;
249 }
250 bThousand = static_cast<bool>(aFormat[0]);
251 bNegRed = static_cast<bool>(aFormat[1]);
252 nPrecision = static_cast<sal_uInt16>(aFormat[2]);
253 nLeadZeroes = static_cast<sal_uInt16>(aFormat[3]);
254 bNatNum12 = static_cast< bool >( aFormat[4] );
255 }
256 else
257 {
258 bThousand = false;
259 bNegRed = false;
260 nPrecision = 0;
261 nLeadZeroes = 1;
262 }
263 if ( nCategory == CAT_NUMBER ||
264 nCategory == CAT_PERCENT ||
265 nCategory == CAT_CURRENCY ||
266 nCategory == CAT_FRACTION )
267 mxBtnThousand->set_sensitive( !bNatNum12 );
268 if ( mxBtnThousand->get_visible() )
269 mxBtnThousand->set_active(bThousand);
270 else if ( mxBtnEngineering->get_visible() )
271 mxBtnEngineering->set_active(bThousand);
272 mxBtnNegRed->set_active(bNegRed);
273 if ( mxLbCategory->get_active() == 0 )
274 mxEdDecimals->set_text(u""_ustr); // tdf#44399
275 else if ( mxEdDecimals->get_visible() )
276 mxEdDecimals->set_value(nPrecision);
277 else if ( mxEdDenominator->get_visible() )
278 mxEdDenominator->set_value(nPrecision);
279 mxEdLeadZeroes->set_value(nLeadZeroes);
280 }
281 break;
282 default:
283 break;
284 }
285 }
286
DisableControls()287 void NumberFormatPropertyPanel::DisableControls()
288 {
289 mxBtnEngineering->hide();
290 mxBtnThousand->show();
291 mxBtnThousand->set_sensitive(false);
292 mxBtnNegRed->set_sensitive(false);
293 mxFtDenominator->hide();
294 mxEdDenominator->hide();
295 mxFtDecimals->show();
296 mxEdDecimals->show();
297 mxFtDecimals->set_sensitive(false);
298 mxEdDecimals->set_sensitive(false);
299 mxFtLeadZeroes->set_sensitive(false);
300 mxEdLeadZeroes->set_sensitive(false);
301 }
302
303 } // end of namespace ::sc::sidebar
304
305 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
306