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 <sal/config.h>
22 #include <string_view>
24 #include "res_DataLabel.hxx"
26 #include <TextDirectionListBox.hxx>
27 #include <chartview/ChartSfxItemIds.hxx>
28 #include "dlg_NumberFormat.hxx"
30 #include <svx/numinf.hxx>
31 #include <svl/eitem.hxx>
32 #include <svl/intitem.hxx>
33 #include <svl/stritem.hxx>
34 #include <svl/ilstitem.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <editeng/frmdiritem.hxx>
37 #include <svx/sdangitm.hxx>
38 #include <svx/svxids.hrc>
39 #include <osl/diagnose.h>
47 const std::u16string_view our_aLBEntryMap
[] = {u
" ", u
", ", u
"; ", u
"\n", u
". "};
49 bool lcl_ReadNumberFormatFromItemSet( const SfxItemSet
& rSet
, TypedWhichId
<SfxUInt32Item
> nValueWhich
, TypedWhichId
<SfxBoolItem
> nSourceFormatWhich
, sal_uInt32
& rnFormatKeyOut
, bool& rbSourceFormatOut
, bool& rbSourceFormatMixedStateOut
)
52 if( const SfxUInt32Item
* pNumItem
= rSet
.GetItemIfSet( nValueWhich
) )
54 rnFormatKeyOut
= pNumItem
->GetValue();
58 rbSourceFormatMixedStateOut
=true;
59 if( const SfxBoolItem
* pBoolItem
= rSet
.GetItemIfSet( nSourceFormatWhich
) )
61 rbSourceFormatOut
= pBoolItem
->GetValue();
62 rbSourceFormatMixedStateOut
=false;
67 void lcl_setBoolItemToCheckBox(const SfxItemSet
& rInAttrs
, TypedWhichId
<SfxBoolItem
> nWhichId
, weld::CheckButton
& rCheckbox
, weld::TriStateEnabled
& rTriState
)
69 if( const SfxBoolItem
* pPoolItem
= rInAttrs
.GetItemIfSet(nWhichId
) )
71 rCheckbox
.set_active(pPoolItem
->GetValue());
72 rTriState
.bTriStateEnabled
= false;
76 rCheckbox
.set_state(TRISTATE_INDET
);
77 rTriState
.bTriStateEnabled
= true;
81 }//end anonymous namespace
83 DataLabelResources::DataLabelResources(weld::Builder
* pBuilder
, weld::Window
* pParent
, const SfxItemSet
& rInAttrs
)
84 : m_pNumberFormatter(nullptr)
85 , m_bNumberFormatMixedState(true)
86 , m_bPercentFormatMixedState(true)
87 , m_nNumberFormatForValue(0)
88 , m_nNumberFormatForPercent(11)
89 , m_bSourceFormatMixedState(true)
90 , m_bPercentSourceMixedState(true)
91 , m_bSourceFormatForValue(true)
92 , m_bSourceFormatForPercent(true)
94 , m_pPool(rInAttrs
.GetPool())
95 , m_xCBNumber(pBuilder
->weld_check_button(u
"CB_VALUE_AS_NUMBER"_ustr
))
96 , m_xPB_NumberFormatForValue(pBuilder
->weld_button(u
"PB_NUMBERFORMAT"_ustr
))
97 , m_xCBPercent(pBuilder
->weld_check_button(u
"CB_VALUE_AS_PERCENTAGE"_ustr
))
98 , m_xPB_NumberFormatForPercent(pBuilder
->weld_button(u
"PB_PERCENT_NUMBERFORMAT"_ustr
))
99 , m_xFT_NumberFormatForPercent(pBuilder
->weld_label(u
"STR_DLG_NUMBERFORMAT_FOR_PERCENTAGE_VALUE"_ustr
))
100 , m_xCBCategory(pBuilder
->weld_check_button(u
"CB_CATEGORY"_ustr
))
101 , m_xCBSymbol(pBuilder
->weld_check_button(u
"CB_SYMBOL"_ustr
))
102 , m_xCBDataSeries(pBuilder
->weld_check_button(u
"CB_DATA_SERIES_NAME"_ustr
))
103 , m_xCBWrapText(pBuilder
->weld_check_button(u
"CB_WRAP_TEXT"_ustr
))
104 , m_xLB_Separator(pBuilder
->weld_combo_box(u
"LB_TEXT_SEPARATOR"_ustr
))
105 , m_xLB_LabelPlacement(pBuilder
->weld_combo_box(u
"LB_LABEL_PLACEMENT"_ustr
))
106 , m_xBxOrientation(pBuilder
->weld_widget(u
"boxORIENTATION"_ustr
))
107 , m_xFT_Dial(pBuilder
->weld_label(u
"CT_LABEL_DIAL"_ustr
))
108 , m_xNF_Degrees(pBuilder
->weld_metric_spin_button(u
"NF_LABEL_DEGREES"_ustr
, FieldUnit::DEGREE
))
109 , m_xBxTextDirection(pBuilder
->weld_widget(u
"boxTXT_DIRECTION"_ustr
))
110 , m_aLB_TextDirection(pBuilder
->weld_combo_box(u
"LB_LABEL_TEXTDIR"_ustr
))
111 , m_xDC_Dial(new svx::DialControl
)
112 , m_xDC_DialWin(new weld::CustomWeld(*pBuilder
, u
"CT_DIAL"_ustr
, *m_xDC_Dial
))
113 , m_xCBCustomLeaderLines(pBuilder
->weld_check_button(u
"CB_CUSTOM_LEADER_LINES"_ustr
))
115 m_xDC_Dial
->SetText(m_xFT_Dial
->get_label());
117 //fill label placement list
118 std::map
< sal_Int32
, OUString
> aPlacementToStringMap
;
119 for( sal_Int32 nEnum
=0; nEnum
<m_xLB_LabelPlacement
->get_count(); ++nEnum
)
120 aPlacementToStringMap
[nEnum
] = m_xLB_LabelPlacement
->get_text(static_cast<sal_uInt16
>(nEnum
));
123 std::vector
< sal_Int32
> aAvailablePlacementList
;
124 if( const SfxIntegerListItem
* pPlacementsItem
= rInAttrs
.GetItemIfSet(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS
) )
125 aAvailablePlacementList
= pPlacementsItem
->GetList();
127 m_xLB_LabelPlacement
->clear();
128 for( size_t nN
=0; nN
<aAvailablePlacementList
.size(); ++nN
)
130 sal_uInt16 nListBoxPos
= static_cast<sal_uInt16
>( nN
);
131 sal_Int32 nPlacement
= aAvailablePlacementList
[nN
];
132 m_aPlacementToListBoxMap
[nPlacement
]=nListBoxPos
;
133 m_aListBoxToPlacementMap
[nListBoxPos
]=nPlacement
;
134 m_xLB_LabelPlacement
->append_text( aPlacementToStringMap
[nPlacement
] );
138 m_xPB_NumberFormatForValue
->connect_clicked( LINK( this, DataLabelResources
, NumberFormatDialogHdl
) );
139 m_xPB_NumberFormatForPercent
->connect_clicked( LINK( this, DataLabelResources
, NumberFormatDialogHdl
) );
140 m_xCBNumber
->connect_toggled( LINK( this, DataLabelResources
, CheckHdl
));
141 m_xCBPercent
->connect_toggled( LINK( this, DataLabelResources
, CheckHdl
));
142 m_xCBCategory
->connect_toggled( LINK( this, DataLabelResources
, CheckHdl
));
143 m_xCBSymbol
->connect_toggled( LINK( this, DataLabelResources
, CheckHdl
));
144 m_xCBDataSeries
->connect_toggled( LINK( this, DataLabelResources
, CheckHdl
));
145 m_xCBWrapText
->connect_toggled( LINK( this, DataLabelResources
, CheckHdl
));
146 m_xCBCustomLeaderLines
->connect_toggled( LINK( this, DataLabelResources
, CheckHdl
));
148 m_bNumberFormatMixedState
= !lcl_ReadNumberFormatFromItemSet( rInAttrs
, SID_ATTR_NUMBERFORMAT_VALUE
, SID_ATTR_NUMBERFORMAT_SOURCE
, m_nNumberFormatForValue
, m_bSourceFormatForValue
, m_bSourceFormatMixedState
);
149 m_bPercentFormatMixedState
= !lcl_ReadNumberFormatFromItemSet( rInAttrs
, SCHATTR_PERCENT_NUMBERFORMAT_VALUE
, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE
, m_nNumberFormatForPercent
, m_bSourceFormatForPercent
, m_bPercentSourceMixedState
);
151 if( const SfxBoolItem
* pNoPercentValueItem
= rInAttrs
.GetItemIfSet(SCHATTR_DATADESCR_NO_PERCENTVALUE
) )
153 bool bForbidPercentValue
= pNoPercentValueItem
->GetValue();
154 if( bForbidPercentValue
)
155 m_xCBPercent
->set_sensitive(false);
158 m_xDC_Dial
->SetLinkedField(m_xNF_Degrees
.get());
161 DataLabelResources::~DataLabelResources()
165 void DataLabelResources::SetNumberFormatter( SvNumberFormatter
* pFormatter
)
167 m_pNumberFormatter
= pFormatter
;
170 IMPL_LINK(DataLabelResources
, NumberFormatDialogHdl
, weld::Button
&, rButton
, void)
172 if( !m_pPool
|| !m_pNumberFormatter
)
174 OSL_FAIL("Missing item pool or number formatter");
178 if (&rButton
== m_xPB_NumberFormatForValue
.get() && !m_xCBNumber
->get_active())
180 m_xCBNumber
->set_active(true);
181 m_aNumberState
.bTriStateEnabled
= false;
183 else if (&rButton
== m_xPB_NumberFormatForPercent
.get() && !m_xCBPercent
->get_active())
185 m_xCBPercent
->set_active(true);
186 m_aPercentState
.bTriStateEnabled
= false;
189 SfxItemSet aNumberSet
= NumberFormatDialog::CreateEmptyItemSetForNumberFormatDialog( *m_pPool
);
190 aNumberSet
.Put (SvxNumberInfoItem( m_pNumberFormatter
, SID_ATTR_NUMBERFORMAT_INFO
));
192 bool bPercent
= (&rButton
== m_xPB_NumberFormatForPercent
.get());
194 sal_uInt32
& rnFormatKey
= bPercent
? m_nNumberFormatForPercent
: m_nNumberFormatForValue
;
195 bool& rUseSourceFormat
= bPercent
? m_bSourceFormatForPercent
: m_bSourceFormatForValue
;
196 bool& rbMixedState
= bPercent
? m_bPercentFormatMixedState
: m_bNumberFormatMixedState
;
197 bool& rbSourceMixedState
= bPercent
? m_bPercentSourceMixedState
: m_bSourceFormatMixedState
;
200 aNumberSet
.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE
, rnFormatKey
));
201 aNumberSet
.Put( SfxBoolItem( SID_ATTR_NUMBERFORMAT_SOURCE
, rUseSourceFormat
));
203 NumberFormatDialog
aDlg(m_pWindow
, aNumberSet
);
205 aDlg
.set_title(m_xFT_NumberFormatForPercent
->get_label());
206 if (aDlg
.run() != RET_OK
)
209 const SfxItemSet
* pResult
= aDlg
.GetOutputItemSet();
212 bool bOldSource
= rUseSourceFormat
;
213 sal_uInt32 nOldFormat
= rnFormatKey
;
214 bool bOldMixedState
= rbMixedState
|| rbSourceMixedState
;
216 rbMixedState
= !lcl_ReadNumberFormatFromItemSet( *pResult
, SID_ATTR_NUMBERFORMAT_VALUE
, SID_ATTR_NUMBERFORMAT_SOURCE
, rnFormatKey
, rUseSourceFormat
, rbSourceMixedState
);
218 //todo this maybe can be removed when the numberformatter dialog does handle mixed state for source format correctly
219 if( bOldMixedState
&& bOldSource
== rUseSourceFormat
&& nOldFormat
== rnFormatKey
)
220 rbMixedState
= rbSourceMixedState
= true;
224 IMPL_LINK(DataLabelResources
, CheckHdl
, weld::Toggleable
&, rToggle
, void)
226 if (&rToggle
== m_xCBNumber
.get())
227 m_aNumberState
.ButtonToggled(rToggle
);
228 else if (&rToggle
== m_xCBPercent
.get())
229 m_aPercentState
.ButtonToggled(rToggle
);
230 else if (&rToggle
== m_xCBCategory
.get())
231 m_aCategoryState
.ButtonToggled(rToggle
);
232 else if (&rToggle
== m_xCBSymbol
.get())
233 m_aSymbolState
.ButtonToggled(rToggle
);
234 else if (&rToggle
== m_xCBDataSeries
.get())
235 m_aDataSeriesState
.ButtonToggled(rToggle
);
236 else if (&rToggle
== m_xCBWrapText
.get())
237 m_aWrapTextState
.ButtonToggled(rToggle
);
238 else if (&rToggle
== m_xCBCustomLeaderLines
.get())
239 m_aCustomLeaderLinesState
.ButtonToggled(rToggle
);
243 void DataLabelResources::EnableControls()
245 m_xCBSymbol
->set_sensitive( m_xCBNumber
->get_active() || (m_xCBPercent
->get_active() && m_xCBPercent
->get_sensitive())
246 || m_xCBCategory
->get_active() || m_xCBDataSeries
->get_active());
248 m_xCBWrapText
->set_sensitive( m_xCBNumber
->get_active() || (m_xCBPercent
->get_active() && m_xCBPercent
->get_sensitive())
249 || m_xCBCategory
->get_active() || m_xCBDataSeries
->get_active() );
251 // Enable or disable separator, placement and direction based on the check
252 // box states. Note that the check boxes are tri-state.
254 tools::Long nNumberOfCheckedLabelParts
= 0;
255 if (m_xCBNumber
->get_state() != TRISTATE_FALSE
)
256 ++nNumberOfCheckedLabelParts
;
257 if (m_xCBPercent
->get_state() != TRISTATE_FALSE
&& m_xCBPercent
->get_sensitive())
258 ++nNumberOfCheckedLabelParts
;
259 if (m_xCBCategory
->get_state() != TRISTATE_FALSE
)
260 ++nNumberOfCheckedLabelParts
;
261 if (m_xCBDataSeries
->get_state() != TRISTATE_FALSE
)
262 ++nNumberOfCheckedLabelParts
;
264 m_xLB_Separator
->set_sensitive( nNumberOfCheckedLabelParts
> 1 );
266 bool bEnableTextDir
= nNumberOfCheckedLabelParts
> 0;
267 m_xBxTextDirection
->set_sensitive( bEnableTextDir
);
268 bool bEnablePlacement
= nNumberOfCheckedLabelParts
> 0 && m_xLB_LabelPlacement
->get_count()>1;
269 m_xLB_LabelPlacement
->set_sensitive( bEnablePlacement
);
272 m_xPB_NumberFormatForValue
->set_sensitive( m_pNumberFormatter
&& m_xCBNumber
->get_active() );
273 m_xPB_NumberFormatForPercent
->set_sensitive( m_pNumberFormatter
&& m_xCBPercent
->get_active() && m_xCBPercent
->get_sensitive() );
275 bool bEnableRotation
= (m_xCBNumber
->get_active() || m_xCBPercent
->get_active()
276 || m_xCBCategory
->get_active() || m_xCBDataSeries
->get_active());
277 m_xBxOrientation
->set_sensitive(bEnableRotation
);
280 void DataLabelResources::FillItemSet( SfxItemSet
* rOutAttrs
) const
282 if( m_xCBNumber
->get_active() )
284 if( !m_bNumberFormatMixedState
)
285 rOutAttrs
->Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE
, m_nNumberFormatForValue
));
286 if( !m_bSourceFormatMixedState
)
287 rOutAttrs
->Put( SfxBoolItem( SID_ATTR_NUMBERFORMAT_SOURCE
, m_bSourceFormatForValue
));
289 if( m_xCBPercent
->get_active() )
291 if( !m_bPercentFormatMixedState
)
292 rOutAttrs
->Put( SfxUInt32Item( SCHATTR_PERCENT_NUMBERFORMAT_VALUE
, m_nNumberFormatForPercent
));
293 if( !m_bPercentSourceMixedState
)
294 rOutAttrs
->Put( SfxBoolItem( SCHATTR_PERCENT_NUMBERFORMAT_SOURCE
, m_bSourceFormatForPercent
));
297 if( m_xCBNumber
->get_state()!= TRISTATE_INDET
)
298 rOutAttrs
->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_NUMBER
, m_xCBNumber
->get_active() ) );
299 if( m_xCBPercent
->get_state()!= TRISTATE_INDET
)
300 rOutAttrs
->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_PERCENTAGE
, m_xCBPercent
->get_active() ) );
301 if( m_xCBCategory
->get_state()!= TRISTATE_INDET
)
302 rOutAttrs
->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_CATEGORY
, m_xCBCategory
->get_active() ) );
303 if( m_xCBSymbol
->get_state()!= TRISTATE_INDET
)
304 rOutAttrs
->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_SYMBOL
, m_xCBSymbol
->get_active()) );
305 if( m_xCBDataSeries
->get_state()!= TRISTATE_INDET
)
306 rOutAttrs
->Put( SfxBoolItem( SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME
, m_xCBDataSeries
->get_active()) );
307 if( m_xCBWrapText
->get_state()!= TRISTATE_INDET
)
308 rOutAttrs
->Put( SfxBoolItem( SCHATTR_DATADESCR_WRAP_TEXT
, m_xCBWrapText
->get_active()) );
309 if( m_xCBCustomLeaderLines
->get_state() != TRISTATE_INDET
)
310 rOutAttrs
->Put(SfxBoolItem( SCHATTR_DATADESCR_CUSTOM_LEADER_LINES
, m_xCBCustomLeaderLines
->get_active()) );
312 auto const aSep
= our_aLBEntryMap
[m_xLB_Separator
->get_active()];
313 rOutAttrs
->Put( SfxStringItem( SCHATTR_DATADESCR_SEPARATOR
, OUString(aSep
)) );
315 std::map
< sal_uInt16
, sal_Int32
>::const_iterator
aIt( m_aListBoxToPlacementMap
.find(m_xLB_LabelPlacement
->get_active()) );
316 if(aIt
!=m_aListBoxToPlacementMap
.end())
318 sal_Int32 nValue
= aIt
->second
;
319 rOutAttrs
->Put( SfxInt32Item( SCHATTR_DATADESCR_PLACEMENT
, nValue
) );
322 if (m_aLB_TextDirection
.get_active() != -1)
323 rOutAttrs
->Put( SvxFrameDirectionItem( m_aLB_TextDirection
.get_active_id(), EE_PARA_WRITINGDIR
) );
325 if( m_xDC_Dial
->IsVisible() )
327 Degree100 nDegrees
= m_xDC_Dial
->GetRotation();
328 rOutAttrs
->Put(SdrAngleItem( SCHATTR_TEXT_DEGREES
, nDegrees
) );
332 void DataLabelResources::Reset(const SfxItemSet
& rInAttrs
)
335 m_xCBSymbol
->set_sensitive( false );
337 lcl_setBoolItemToCheckBox( rInAttrs
, SCHATTR_DATADESCR_SHOW_NUMBER
, *m_xCBNumber
, m_aNumberState
);
338 lcl_setBoolItemToCheckBox( rInAttrs
, SCHATTR_DATADESCR_SHOW_PERCENTAGE
, *m_xCBPercent
, m_aPercentState
);
339 lcl_setBoolItemToCheckBox( rInAttrs
, SCHATTR_DATADESCR_SHOW_CATEGORY
, *m_xCBCategory
, m_aCategoryState
);
340 lcl_setBoolItemToCheckBox( rInAttrs
, SCHATTR_DATADESCR_SHOW_SYMBOL
, *m_xCBSymbol
, m_aSymbolState
);
341 lcl_setBoolItemToCheckBox( rInAttrs
, SCHATTR_DATADESCR_SHOW_DATA_SERIES_NAME
, *m_xCBDataSeries
, m_aDataSeriesState
);
342 lcl_setBoolItemToCheckBox( rInAttrs
, SCHATTR_DATADESCR_WRAP_TEXT
, *m_xCBWrapText
, m_aWrapTextState
);
343 lcl_setBoolItemToCheckBox( rInAttrs
, SCHATTR_DATADESCR_CUSTOM_LEADER_LINES
, *m_xCBCustomLeaderLines
, m_aCustomLeaderLinesState
);
345 m_bNumberFormatMixedState
= !lcl_ReadNumberFormatFromItemSet( rInAttrs
, SID_ATTR_NUMBERFORMAT_VALUE
, SID_ATTR_NUMBERFORMAT_SOURCE
, m_nNumberFormatForValue
, m_bSourceFormatForValue
, m_bSourceFormatMixedState
);
346 m_bPercentFormatMixedState
= !lcl_ReadNumberFormatFromItemSet( rInAttrs
, SCHATTR_PERCENT_NUMBERFORMAT_VALUE
, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE
, m_nNumberFormatForPercent
, m_bSourceFormatForPercent
, m_bPercentSourceMixedState
);
348 if( const SfxStringItem
* pSeparatorItem
= rInAttrs
.GetItemIfSet(SCHATTR_DATADESCR_SEPARATOR
) )
349 for(size_t i
=0; i
< std::size(our_aLBEntryMap
); ++i
)
351 if( our_aLBEntryMap
[i
] == pSeparatorItem
->GetValue())
352 m_xLB_Separator
->set_active( i
);
355 m_xLB_Separator
->set_active( 0 );
357 if( const SfxInt32Item
* pPlacementItem
= rInAttrs
.GetItemIfSet(SCHATTR_DATADESCR_PLACEMENT
) )
359 sal_Int32 nPlacement
= pPlacementItem
->GetValue();
360 std::map
< sal_Int32
, sal_uInt16
>::const_iterator
aIt( m_aPlacementToListBoxMap
.find(nPlacement
) );
361 if(aIt
!=m_aPlacementToListBoxMap
.end())
363 sal_uInt16 nPos
= aIt
->second
;
364 m_xLB_LabelPlacement
->set_active( nPos
);
367 m_xLB_LabelPlacement
->set_active(-1);
370 m_xLB_LabelPlacement
->set_active(-1);
372 if( const SvxFrameDirectionItem
* pDirectionItem
= rInAttrs
.GetItemIfSet(EE_PARA_WRITINGDIR
) )
373 m_aLB_TextDirection
.set_active_id( pDirectionItem
->GetValue() );
375 if( const SdrAngleItem
* pAngleItem
= rInAttrs
.GetItemIfSet( SCHATTR_TEXT_DEGREES
) )
377 Degree100 nDegrees
= pAngleItem
->GetValue();
378 m_xDC_Dial
->SetRotation( nDegrees
);
381 m_xDC_Dial
->SetRotation( 0_deg100
);
388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */