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 "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
58 ParaLineSpacingControl::ParaLineSpacingControl(SvxLineSpacingToolBoxControl
* pControl
, weld::Widget
* pParent
)
59 : WeldToolbarPopup(pControl
->getFrameInterface(), pParent
, "svx/ui/paralinespacingcontrol.ui", "ParaLineSpacingControl")
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());
92 eUnit
= SfxModule::GetCurrentFieldUnit();
94 SetFieldUnit(*mxLineDistAtMetricBox
, eUnit
);
99 void ParaLineSpacingControl::GrabFocus()
101 switch (mxLineDist
->get_active())
104 mxSpacing1Button
->grab_focus();
107 mxSpacing115Button
->grab_focus();
110 mxSpacing15Button
->grab_focus();
113 mxSpacing2Button
->grab_focus();
116 mxLineDist
->grab_focus();
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();
155 case SvxInterLineSpaceRule::Off
:
156 SelectEntryPos(LLINESPACE_1
);
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
);
179 SelectEntryPos(LLINESPACE_PROP
);
180 mxLineDistAtPercentBox
->set_value(mxLineDistAtPercentBox
->normalize(currSPItem
->GetPropLineSpace()), FieldUnit::PERCENT
);
185 case SvxInterLineSpaceRule::Fix
:
187 SelectEntryPos(LLINESPACE_DURCH
);
188 SetMetricValue(*mxLineDistAtMetricBox
, currSPItem
->GetInterLineSpace(), eUnit
);
196 case SvxLineSpaceRule::Fix
:
198 SelectEntryPos(LLINESPACE_FIX
);
199 SetMetricValue(*mxLineDistAtMetricBox
, currSPItem
->GetLineHeight(), eUnit
);
203 case SvxLineSpaceRule::Min
:
205 SelectEntryPos(LLINESPACE_MIN
);
206 SetMetricValue(*mxLineDistAtMetricBox
, currSPItem
->GetLineHeight(), eUnit
);
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())
240 if (mpActLineDistFld
== mxLineDistAtPercentBox
.get())
241 mxLineDistAtMetricBox
->hide();
243 mxLineDistAtPercentBox
->hide();
245 mxLineDistLabel
->set_sensitive(false);
246 mpActLineDistFld
->show();
247 mpActLineDistFld
->set_sensitive(false);
248 mpActLineDistFld
->set_text("");
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);
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);
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);
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);
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();
321 IMPL_LINK_NOARG( ParaLineSpacingControl
, LineSPDistAtHdl_Impl
, weld::MetricSpinButton
&, void )
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();
339 SetLineSpace(aSpacing
, nPos
);
342 case LLINESPACE_PROP
:
343 SetLineSpace(aSpacing
, nPos
, mxLineDistAtPercentBox
->denormalize(static_cast<tools::Long
>(mxLineDistAtPercentBox
->get_value(FieldUnit::PERCENT
))));
347 case LLINESPACE_DURCH
:
349 SetLineSpace(aSpacing
, nPos
, GetCoreValue(*mxLineDistAtMetricBox
, meLNSpaceUnit
));
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
)
368 rLineSpace
.SetLineSpaceRule( SvxLineSpaceRule::Auto
);
369 rLineSpace
.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off
);
373 rLineSpace
.SetLineSpaceRule( SvxLineSpaceRule::Auto
);
374 rLineSpace
.SetPropLineSpace( LINESPACE_115
);
378 rLineSpace
.SetLineSpaceRule( SvxLineSpaceRule::Auto
);
379 rLineSpace
.SetPropLineSpace( LINESPACE_15
);
383 rLineSpace
.SetLineSpaceRule( SvxLineSpaceRule::Auto
);
384 rLineSpace
.SetPropLineSpace( LINESPACE_2
);
387 case LLINESPACE_PROP
:
388 rLineSpace
.SetLineSpaceRule( SvxLineSpaceRule::Auto
);
389 rLineSpace
.SetPropLineSpace( static_cast<sal_uInt16
>(lValue
) );
393 rLineSpace
.SetLineHeight( static_cast<sal_uInt16
>(lValue
) );
394 rLineSpace
.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off
);
397 case LLINESPACE_DURCH
:
398 rLineSpace
.SetLineSpaceRule( SvxLineSpaceRule::Auto
);
399 rLineSpace
.SetInterLineSpace( static_cast<sal_uInt16
>(lValue
) );
403 rLineSpace
.SetLineHeight(static_cast<sal_uInt16
>(lValue
));
404 rLineSpace
.SetLineSpaceRule( SvxLineSpaceRule::Fix
);
405 rLineSpace
.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off
);
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: */