Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / sidebar / paragraph / ParaLineSpacingControl.cxx
blob4c756a5b1224cc27e22d5875d4db21c5506c34fc
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 "ParaLineSpacingControl.hxx"
22 #include <editeng/editids.hrc>
23 #include <editeng/lspcitem.hxx>
24 #include <sfx2/dispatch.hxx>
25 #include <sfx2/module.hxx>
26 #include <sfx2/sfxsids.hrc>
27 #include <sfx2/viewfrm.hxx>
28 #include <svtools/unitconv.hxx>
30 #include <svl/intitem.hxx>
31 #include <svl/itempool.hxx>
33 #include <ParaLineSpacingPopup.hxx>
35 #include <vcl/commandinfoprovider.hxx>
37 #define DEFAULT_LINE_SPACING 200
38 #define FIX_DIST_DEF 283
39 #define LINESPACE_1 100
40 #define LINESPACE_15 150
41 #define LINESPACE_2 200
42 #define LINESPACE_115 115
44 // values of the mxLineDist listbox
45 #define LLINESPACE_1 0
46 #define LLINESPACE_115 1
47 #define LLINESPACE_15 2
48 #define LLINESPACE_2 3
49 #define LLINESPACE_PROP 4
50 #define LLINESPACE_MIN 5
51 #define LLINESPACE_DURCH 6
52 #define LLINESPACE_FIX 7
54 #define MIN_FIXED_DISTANCE 28
56 using namespace svx;
58 ParaLineSpacingControl::ParaLineSpacingControl(SvxLineSpacingToolBoxControl* pControl, weld::Widget* pParent)
59 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/paralinespacingcontrol.ui", "ParaLineSpacingControl")
60 , mxControl(pControl)
61 , meLNSpaceUnit(MapUnit::Map100thMM)
62 , mxSpacing1Button(m_xBuilder->weld_button("spacing_1"))
63 , mxSpacing115Button(m_xBuilder->weld_button("spacing_115"))
64 , mxSpacing15Button(m_xBuilder->weld_button("spacing_15"))
65 , mxSpacing2Button(m_xBuilder->weld_button("spacing_2"))
66 , mxLineDist(m_xBuilder->weld_combo_box("line_dist"))
67 , mxLineDistLabel(m_xBuilder->weld_label("value_label"))
68 , mxLineDistAtPercentBox(m_xBuilder->weld_metric_spin_button("percent_box", FieldUnit::PERCENT))
69 , mxLineDistAtMetricBox(m_xBuilder->weld_metric_spin_button("metric_box", FieldUnit::CM))
70 , mpActLineDistFld(mxLineDistAtPercentBox.get())
72 Link<weld::Button&,void> aLink = LINK(this, ParaLineSpacingControl, PredefinedValuesHandler);
73 mxSpacing1Button->connect_clicked(aLink);
74 mxSpacing115Button->connect_clicked(aLink);
75 mxSpacing15Button->connect_clicked(aLink);
76 mxSpacing2Button->connect_clicked(aLink);
78 Link<weld::ComboBox&,void> aLink3 = LINK( this, ParaLineSpacingControl, LineSPDistHdl_Impl );
79 mxLineDist->connect_changed(aLink3);
80 SelectEntryPos(LLINESPACE_1);
82 Link<weld::MetricSpinButton&,void> aLink2 = LINK( this, ParaLineSpacingControl, LineSPDistAtHdl_Impl );
83 mxLineDistAtPercentBox->connect_value_changed( aLink2 );
84 mxLineDistAtMetricBox->connect_value_changed( aLink2 );
86 FieldUnit eUnit = FieldUnit::INCH;
87 const SfxUInt16Item* pItem = nullptr;
88 SfxViewFrame* pCurrent = SfxViewFrame::Current();
89 if (pCurrent && pCurrent->GetBindings().GetDispatcher()->QueryState(SID_ATTR_METRIC, pItem) >= SfxItemState::DEFAULT)
90 eUnit = static_cast<FieldUnit>(pItem->GetValue());
91 else
92 eUnit = SfxModule::GetCurrentFieldUnit();
94 SetFieldUnit(*mxLineDistAtMetricBox, eUnit);
96 Initialize();
99 void ParaLineSpacingControl::GrabFocus()
101 switch (mxLineDist->get_active())
103 case LLINESPACE_1:
104 mxSpacing1Button->grab_focus();
105 break;
106 case LLINESPACE_115:
107 mxSpacing115Button->grab_focus();
108 break;
109 case LLINESPACE_15:
110 mxSpacing15Button->grab_focus();
111 break;
112 case LLINESPACE_2:
113 mxSpacing2Button->grab_focus();
114 break;
115 default:
116 mxLineDist->grab_focus();
117 break;
121 ParaLineSpacingControl::~ParaLineSpacingControl()
125 void ParaLineSpacingControl::Initialize()
127 const SvxLineSpacingItem* pItem(nullptr);
128 SfxViewFrame* pCurrent = SfxViewFrame::Current();
129 const bool bItemStateSet(nullptr != pCurrent);
130 const SfxItemState eState(bItemStateSet
131 ? pCurrent->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PARA_LINESPACE, pItem)
132 : SfxItemState::DEFAULT);
134 mxLineDist->set_sensitive(true);
136 if( bItemStateSet && (eState == SfxItemState::DEFAULT || eState == SfxItemState::SET) )
138 const SvxLineSpacingItem* currSPItem = pItem;
139 // It seems draw/impress and writer require different MapUnit values for fixed line spacing
140 // metric values to be correctly calculated.
141 MapUnit eUnit = MapUnit::Map100thMM; // works for draw/impress
142 if (vcl::CommandInfoProvider::GetModuleIdentifier(pCurrent->GetFrame().GetFrameInterface())
143 == "com.sun.star.text.TextDocument")
144 eUnit = MapUnit::MapTwip; // works for writer
145 meLNSpaceUnit = eUnit;
147 switch( currSPItem->GetLineSpaceRule() )
149 case SvxLineSpaceRule::Auto:
151 SvxInterLineSpaceRule eInter = currSPItem->GetInterLineSpaceRule();
153 switch( eInter )
155 case SvxInterLineSpaceRule::Off:
156 SelectEntryPos(LLINESPACE_1);
157 break;
159 case SvxInterLineSpaceRule::Prop:
161 if ( LINESPACE_1 == currSPItem->GetPropLineSpace() )
163 SelectEntryPos(LLINESPACE_1);
165 else if ( LINESPACE_115 == currSPItem->GetPropLineSpace() )
167 SelectEntryPos(LLINESPACE_115);
169 else if ( LINESPACE_15 == currSPItem->GetPropLineSpace() )
171 SelectEntryPos(LLINESPACE_15);
173 else if ( LINESPACE_2 == currSPItem->GetPropLineSpace() )
175 SelectEntryPos(LLINESPACE_2);
177 else
179 SelectEntryPos(LLINESPACE_PROP);
180 mxLineDistAtPercentBox->set_value(mxLineDistAtPercentBox->normalize(currSPItem->GetPropLineSpace()), FieldUnit::PERCENT);
183 break;
185 case SvxInterLineSpaceRule::Fix:
187 SelectEntryPos(LLINESPACE_DURCH);
188 SetMetricValue(*mxLineDistAtMetricBox, currSPItem->GetInterLineSpace(), eUnit);
190 break;
191 default:
192 break;
195 break;
196 case SvxLineSpaceRule::Fix:
198 SelectEntryPos(LLINESPACE_FIX);
199 SetMetricValue(*mxLineDistAtMetricBox, currSPItem->GetLineHeight(), eUnit);
201 break;
203 case SvxLineSpaceRule::Min:
205 SelectEntryPos(LLINESPACE_MIN);
206 SetMetricValue(*mxLineDistAtMetricBox, currSPItem->GetLineHeight(), eUnit);
208 break;
209 default:
210 break;
213 else if( bItemStateSet && eState == SfxItemState::DISABLED )
215 mxLineDist->set_sensitive(false);
216 mxLineDistLabel->set_sensitive(false);
217 mpActLineDistFld->set_sensitive(false);
218 mpActLineDistFld->set_text("");
221 else // !bItemStateSet || eState == SfxItemState::DONTCARE || eState == SfxItemState::UNKNOWN
223 mxLineDistLabel->set_sensitive(false);
224 mpActLineDistFld->set_sensitive(false);
225 mpActLineDistFld->set_text("");
226 mxLineDist->set_active(-1);
229 mxLineDist->save_value();
232 void ParaLineSpacingControl::UpdateMetricFields()
234 switch (mxLineDist->get_active())
236 case LLINESPACE_1:
237 case LLINESPACE_115:
238 case LLINESPACE_15:
239 case LLINESPACE_2:
240 if (mpActLineDistFld == mxLineDistAtPercentBox.get())
241 mxLineDistAtMetricBox->hide();
242 else
243 mxLineDistAtPercentBox->hide();
245 mxLineDistLabel->set_sensitive(false);
246 mpActLineDistFld->show();
247 mpActLineDistFld->set_sensitive(false);
248 mpActLineDistFld->set_text("");
249 break;
251 case LLINESPACE_DURCH:
252 mxLineDistAtPercentBox->hide();
254 mpActLineDistFld = mxLineDistAtMetricBox.get();
255 mxLineDistAtMetricBox->set_min(0, FieldUnit::NONE);
257 if (mxLineDistAtMetricBox->get_text().isEmpty())
258 mxLineDistAtMetricBox->set_value(mxLineDistAtMetricBox->normalize(0), FieldUnit::NONE);
260 mxLineDistLabel->set_sensitive(true);
261 mpActLineDistFld->show();
262 mpActLineDistFld->set_sensitive(true);
263 break;
265 case LLINESPACE_MIN:
266 mxLineDistAtPercentBox->hide();
268 mpActLineDistFld = mxLineDistAtMetricBox.get();
269 mxLineDistAtMetricBox->set_min(0, FieldUnit::NONE);
271 if (mxLineDistAtMetricBox->get_text().isEmpty())
272 mxLineDistAtMetricBox->set_value(mxLineDistAtMetricBox->normalize(0), FieldUnit::TWIP);
274 mxLineDistLabel->set_sensitive(true);
275 mpActLineDistFld->show();
276 mpActLineDistFld->set_sensitive(true);
277 break;
279 case LLINESPACE_PROP:
280 mxLineDistAtMetricBox->hide();
282 mpActLineDistFld = mxLineDistAtPercentBox.get();
284 if (mxLineDistAtPercentBox->get_text().isEmpty())
285 mxLineDistAtPercentBox->set_value(mxLineDistAtPercentBox->normalize(100), FieldUnit::TWIP);
287 mxLineDistLabel->set_sensitive(true);
288 mpActLineDistFld->show();
289 mpActLineDistFld->set_sensitive(true);
290 break;
292 case LLINESPACE_FIX:
293 mxLineDistAtPercentBox->hide();
295 mpActLineDistFld = mxLineDistAtMetricBox.get();
296 sal_Int64 nTemp = mxLineDistAtMetricBox->get_value(FieldUnit::NONE);
297 mxLineDistAtMetricBox->set_min(mxLineDistAtMetricBox->normalize(MIN_FIXED_DISTANCE), FieldUnit::TWIP);
299 if (mxLineDistAtMetricBox->get_value(FieldUnit::NONE) != nTemp)
300 SetMetricValue(*mxLineDistAtMetricBox, FIX_DIST_DEF, MapUnit::MapTwip);
302 mxLineDistLabel->set_sensitive(true);
303 mpActLineDistFld->show();
304 mpActLineDistFld->set_sensitive(true);
305 break;
309 void ParaLineSpacingControl::SelectEntryPos(sal_Int32 nPos)
311 mxLineDist->set_active(nPos);
312 UpdateMetricFields();
315 IMPL_LINK_NOARG(ParaLineSpacingControl, LineSPDistHdl_Impl, weld::ComboBox&, void)
317 UpdateMetricFields();
318 ExecuteLineSpace();
321 IMPL_LINK_NOARG( ParaLineSpacingControl, LineSPDistAtHdl_Impl, weld::MetricSpinButton&, void )
323 ExecuteLineSpace();
326 void ParaLineSpacingControl::ExecuteLineSpace()
328 mxLineDist->save_value();
330 SvxLineSpacingItem aSpacing(DEFAULT_LINE_SPACING, SID_ATTR_PARA_LINESPACE);
331 const sal_Int32 nPos = mxLineDist->get_active();
333 switch ( nPos )
335 case LLINESPACE_1:
336 case LLINESPACE_115:
337 case LLINESPACE_15:
338 case LLINESPACE_2:
339 SetLineSpace(aSpacing, nPos);
340 break;
342 case LLINESPACE_PROP:
343 SetLineSpace(aSpacing, nPos, mxLineDistAtPercentBox->denormalize(static_cast<tools::Long>(mxLineDistAtPercentBox->get_value(FieldUnit::PERCENT))));
344 break;
346 case LLINESPACE_MIN:
347 case LLINESPACE_DURCH:
348 case LLINESPACE_FIX:
349 SetLineSpace(aSpacing, nPos, GetCoreValue(*mxLineDistAtMetricBox, meLNSpaceUnit));
350 break;
352 default:
353 break;
356 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
358 pViewFrm->GetBindings().GetDispatcher()->ExecuteList(
359 SID_ATTR_PARA_LINESPACE, SfxCallMode::RECORD, { &aSpacing });
363 void ParaLineSpacingControl::SetLineSpace(SvxLineSpacingItem& rLineSpace, sal_Int32 eSpace, tools::Long lValue)
365 switch ( eSpace )
367 case LLINESPACE_1:
368 rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto );
369 rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off );
370 break;
372 case LLINESPACE_115:
373 rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto );
374 rLineSpace.SetPropLineSpace( LINESPACE_115 );
375 break;
377 case LLINESPACE_15:
378 rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto );
379 rLineSpace.SetPropLineSpace( LINESPACE_15 );
380 break;
382 case LLINESPACE_2:
383 rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto );
384 rLineSpace.SetPropLineSpace( LINESPACE_2 );
385 break;
387 case LLINESPACE_PROP:
388 rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto );
389 rLineSpace.SetPropLineSpace( static_cast<sal_uInt16>(lValue) );
390 break;
392 case LLINESPACE_MIN:
393 rLineSpace.SetLineHeight( static_cast<sal_uInt16>(lValue) );
394 rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off );
395 break;
397 case LLINESPACE_DURCH:
398 rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Auto );
399 rLineSpace.SetInterLineSpace( static_cast<sal_uInt16>(lValue) );
400 break;
402 case LLINESPACE_FIX:
403 rLineSpace.SetLineHeight(static_cast<sal_uInt16>(lValue));
404 rLineSpace.SetLineSpaceRule( SvxLineSpaceRule::Fix );
405 rLineSpace.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off );
406 break;
410 IMPL_LINK(ParaLineSpacingControl, PredefinedValuesHandler, weld::Button&, rControl, void)
412 if (&rControl == mxSpacing1Button.get())
414 ExecuteLineSpacing(LLINESPACE_1);
416 else if (&rControl == mxSpacing115Button.get())
418 ExecuteLineSpacing(LLINESPACE_115);
420 else if (&rControl == mxSpacing15Button.get())
422 ExecuteLineSpacing(LLINESPACE_15);
424 else if (&rControl == mxSpacing2Button.get())
426 ExecuteLineSpacing(LLINESPACE_2);
430 void ParaLineSpacingControl::ExecuteLineSpacing(sal_Int32 nEntry)
432 SvxLineSpacingItem aSpacing(DEFAULT_LINE_SPACING, SID_ATTR_PARA_LINESPACE);
434 SetLineSpace(aSpacing, nEntry);
436 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
438 pViewFrm->GetBindings().GetDispatcher()->ExecuteList(
439 SID_ATTR_PARA_LINESPACE, SfxCallMode::RECORD, { &aSpacing });
442 // close when the user used the buttons
443 mxControl->EndPopupMode();
446 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */