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 <memory>
21 #include <comphelper/servicehelper.hxx>
22 #include <svx/sidebar/LinePropertyPanelBase.hxx>
23 #include <sfx2/weldutils.hxx>
24 #include <svx/linectrl.hxx>
25 #include <svx/xlnwtit.hxx>
26 #include <svx/xlntrit.hxx>
27 #include <svx/xlncapit.hxx>
28 #include <svx/xlinjoit.hxx>
29 #include <bitmaps.hlst>
30 
31 using namespace css;
32 using namespace css::uno;
33 
34 constexpr OStringLiteral SELECTWIDTH = "SelectWidth";
35 
36 namespace svx::sidebar {
37 
38 // trigger disabling the arrows if the none line style is selected
39 class LineStyleNoneChange
40 {
41 private:
42     LinePropertyPanelBase& m_rPanel;
43 
44 public:
45     LineStyleNoneChange(LinePropertyPanelBase& rPanel)
46         : m_rPanel(rPanel)
47     {
48     }
49 
50     void operator()(bool bLineStyleNone)
51     {
52         m_rPanel.SetNoneLineStyle(bLineStyleNone);
53     }
54 };
55 
56 namespace
57 {
58     SvxLineStyleToolBoxControl* getLineStyleToolBoxControl(const ToolbarUnoDispatcher& rToolBoxColor)
59     {
60         css::uno::Reference<css::frame::XToolbarController> xController = rToolBoxColor.GetControllerForCommand(".uno:XLineStyle");
61         SvxLineStyleToolBoxControl* pToolBoxLineStyleControl = comphelper::getFromUnoTunnel<SvxLineStyleToolBoxControl>(xController);
62         return pToolBoxLineStyleControl;
63     }
64 }
65 
66 
67 LinePropertyPanelBase::LinePropertyPanelBase(
68     weld::Widget* pParent,
69     const uno::Reference<css::frame::XFrame>& rxFrame)
70 :   PanelLayout(pParent, "LinePropertyPanel", "svx/ui/sidebarline.ui"),
71     mxTBColor(m_xBuilder->weld_toolbar("color")),
72     mxColorDispatch(new ToolbarUnoDispatcher(*mxTBColor, *m_xBuilder, rxFrame)),
73     mxLineStyleTB(m_xBuilder->weld_toolbar("linestyle")),
74     mxLineStyleDispatch(new ToolbarUnoDispatcher(*mxLineStyleTB, *m_xBuilder, rxFrame)),
75     mnWidthCoreValue(0),
76     mxFTWidth(m_xBuilder->weld_label("widthlabel")),
77     mxTBWidth(m_xBuilder->weld_toolbar("width")),
78     mxFTTransparency(m_xBuilder->weld_label("translabel")),
79     mxMFTransparent(m_xBuilder->weld_metric_spin_button("linetransparency", FieldUnit::PERCENT)),
80     mxFTEdgeStyle(m_xBuilder->weld_label("cornerlabel")),
81     mxLBEdgeStyle(m_xBuilder->weld_combo_box("edgestyle")),
82     mxFTCapStyle(m_xBuilder->weld_label("caplabel")),
83     mxLBCapStyle(m_xBuilder->weld_combo_box("linecapstyle")),
84     mxGridLineProps(m_xBuilder->weld_widget("lineproperties")),
85     mxBoxArrowProps(m_xBuilder->weld_widget("arrowproperties")),
86     mxLineWidthPopup(new LineWidthPopup(mxTBWidth.get(), *this)),
87     mxLineStyleNoneChange(new LineStyleNoneChange(*this)),
88     mnTrans(0),
89     meMapUnit(MapUnit::MapMM),
90     maIMGNone(BMP_NONE_ICON),
91     mbWidthValuable(true),
92     mbArrowSupported(true),
93     mbNoneLineStyle(false)
94 {
95     Initialize();
96 }
97 
98 LinePropertyPanelBase::~LinePropertyPanelBase()
99 {
100     mxLineWidthPopup.reset();
101     mxFTWidth.reset();
102     mxTBWidth.reset();
103     mxColorDispatch.reset();
104     mxTBColor.reset();
105     mxFTTransparency.reset();
106     mxMFTransparent.reset();
107     mxLineStyleDispatch.reset();
108     mxLineStyleTB.reset();
109     mxFTEdgeStyle.reset();
110     mxLBEdgeStyle.reset();
111     mxFTCapStyle.reset();
112     mxLBCapStyle.reset();
113     mxGridLineProps.reset();
114     mxBoxArrowProps.reset();
115 }
116 
117 void LinePropertyPanelBase::Initialize()
118 {
119     mxTBWidth->set_item_popover(SELECTWIDTH, mxLineWidthPopup->getTopLevel());
120 
121     maIMGWidthIcon[0] = BMP_WIDTH1_ICON;
122     maIMGWidthIcon[1] = BMP_WIDTH2_ICON;
123     maIMGWidthIcon[2] = BMP_WIDTH3_ICON;
124     maIMGWidthIcon[3] = BMP_WIDTH4_ICON;
125     maIMGWidthIcon[4] = BMP_WIDTH5_ICON;
126     maIMGWidthIcon[5] = BMP_WIDTH6_ICON;
127     maIMGWidthIcon[6] = BMP_WIDTH7_ICON;
128     maIMGWidthIcon[7] = BMP_WIDTH8_ICON;
129 
130     mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[0]);
131     mxTBWidth->connect_clicked(LINK(this, LinePropertyPanelBase, ToolboxWidthSelectHdl));
132 
133     mxMFTransparent->connect_value_changed(LINK(this, LinePropertyPanelBase, ChangeTransparentHdl));
134 
135     mxLBEdgeStyle->connect_changed( LINK( this, LinePropertyPanelBase, ChangeEdgeStyleHdl ) );
136 
137     mxLBCapStyle->connect_changed( LINK( this, LinePropertyPanelBase, ChangeCapStyleHdl ) );
138 
139     SvxLineStyleToolBoxControl* pLineStyleControl = getLineStyleToolBoxControl(*mxLineStyleDispatch);
140     pLineStyleControl->setLineStyleIsNoneFunction(*mxLineStyleNoneChange);
141 }
142 
143 void LinePropertyPanelBase::updateLineTransparence(bool bDisabled, bool bSetOrDefault,
144         const SfxPoolItem* pState)
145 {
146     if(bDisabled)
147     {
148         mxFTTransparency->set_sensitive(false);
149         mxMFTransparent->set_sensitive(false);
150     }
151     else
152     {
153         mxFTTransparency->set_sensitive(true);
154         mxMFTransparent->set_sensitive(true);
155     }
156 
157     if(bSetOrDefault)
158     {
159         if (const XLineTransparenceItem* pItem = dynamic_cast<const XLineTransparenceItem*>(pState))
160         {
161             mnTrans = pItem->GetValue();
162             mxMFTransparent->set_value(mnTrans, FieldUnit::PERCENT);
163             return;
164         }
165     }
166 
167     mxMFTransparent->set_value(0, FieldUnit::PERCENT);//add
168     mxMFTransparent->set_text(OUString());
169 }
170 
171 void LinePropertyPanelBase::updateLineWidth(bool bDisabled, bool bSetOrDefault,
172         const SfxPoolItem* pState)
173 {
174     if(bDisabled)
175     {
176         mxTBWidth->set_sensitive(false);
177         mxFTWidth->set_sensitive(false);
178     }
179     else
180     {
181         mxTBWidth->set_sensitive(true);
182         mxFTWidth->set_sensitive(true);
183     }
184 
185     if(bSetOrDefault)
186     {
187         if (const XLineWidthItem* pItem = dynamic_cast<const XLineWidthItem*>(pState))
188         {
189             mnWidthCoreValue = pItem->GetValue();
190             mbWidthValuable = true;
191             SetWidthIcon();
192             return;
193         }
194     }
195 
196     mbWidthValuable = false;
197     SetWidthIcon();
198 }
199 
200 void LinePropertyPanelBase::updateLineJoint(bool bDisabled, bool bSetOrDefault,
201         const SfxPoolItem* pState)
202 {
203     if(bDisabled)
204     {
205         mxLBEdgeStyle->set_sensitive(false);
206         mxFTEdgeStyle->set_sensitive(false);
207     }
208     else
209     {
210         mxLBEdgeStyle->set_sensitive(true);
211         mxFTEdgeStyle->set_sensitive(true);
212     }
213 
214     if(bSetOrDefault)
215     {
216         if (const XLineJointItem* pItem = dynamic_cast<const XLineJointItem*>(pState))
217         {
218             sal_Int32 nEntryPos(0);
219 
220             switch(pItem->GetValue())
221             {
222                 case drawing::LineJoint_ROUND:
223                 {
224                     nEntryPos = 1;
225                     break;
226                 }
227                 case drawing::LineJoint_NONE:
228                 {
229                     nEntryPos = 2;
230                     break;
231                 }
232                 case drawing::LineJoint_MIDDLE:
233                 case drawing::LineJoint_MITER:
234                 {
235                     nEntryPos = 3;
236                     break;
237                 }
238                 case drawing::LineJoint_BEVEL:
239                 {
240                     nEntryPos = 4;
241                     break;
242                 }
243 
244                 default:
245                 break;
246             }
247 
248             if(nEntryPos)
249             {
250                 mxLBEdgeStyle->set_active(nEntryPos - 1);
251                 return;
252             }
253         }
254     }
255 
256     mxLBEdgeStyle->set_active(-1);
257 }
258 
259 void LinePropertyPanelBase::updateLineCap(bool bDisabled, bool bSetOrDefault,
260         const SfxPoolItem* pState)
261 {
262     if(bDisabled)
263     {
264         mxLBCapStyle->set_sensitive(false);
265         mxFTCapStyle->set_sensitive(false);
266     }
267     else
268     {
269         mxLBCapStyle->set_sensitive(true);
270         mxLBCapStyle->set_sensitive(true);
271     }
272 
273     if(bSetOrDefault)
274     {
275         if (const XLineCapItem* pItem = dynamic_cast<const XLineCapItem*>(pState))
276         {
277             sal_Int32 nEntryPos(0);
278 
279             switch(pItem->GetValue())
280             {
281                 case drawing::LineCap_BUTT:
282                 {
283                     nEntryPos = 1;
284                     break;
285                 }
286                 case drawing::LineCap_ROUND:
287                 {
288                     nEntryPos = 2;
289                     break;
290                 }
291                 case drawing::LineCap_SQUARE:
292                 {
293                     nEntryPos = 3;
294                     break;
295                 }
296 
297                 default:
298                 break;
299             }
300 
301             if(nEntryPos)
302             {
303                 mxLBCapStyle->set_active(nEntryPos - 1);
304                 return;
305             }
306         }
307     }
308 
309     mxLBCapStyle->set_active(-1);
310 }
311 
312 IMPL_LINK_NOARG(LinePropertyPanelBase, ChangeEdgeStyleHdl, weld::ComboBox&, void)
313 {
314     const sal_Int32 nPos(mxLBEdgeStyle->get_active());
315 
316     if (nPos == -1 || !mxLBEdgeStyle->get_value_changed_from_saved())
317         return;
318 
319     std::unique_ptr<XLineJointItem> pItem;
320 
321     switch(nPos)
322     {
323         case 0: // rounded
324         {
325             pItem.reset(new XLineJointItem(drawing::LineJoint_ROUND));
326             break;
327         }
328         case 1: // none
329         {
330             pItem.reset(new XLineJointItem(drawing::LineJoint_NONE));
331             break;
332         }
333         case 2: // mitered
334         {
335             pItem.reset(new XLineJointItem(drawing::LineJoint_MITER));
336             break;
337         }
338         case 3: // beveled
339         {
340             pItem.reset(new XLineJointItem(drawing::LineJoint_BEVEL));
341             break;
342         }
343     }
344 
345     setLineJoint(pItem.get());
346 }
347 
348 IMPL_LINK_NOARG(LinePropertyPanelBase, ChangeCapStyleHdl, weld::ComboBox&, void)
349 {
350     const sal_Int32 nPos(mxLBCapStyle->get_active());
351 
352     if (!(nPos != -1 && mxLBCapStyle->get_value_changed_from_saved()))
353         return;
354 
355     std::unique_ptr<XLineCapItem> pItem;
356 
357     switch(nPos)
358     {
359         case 0: // flat
360         {
361             pItem.reset(new XLineCapItem(drawing::LineCap_BUTT));
362             break;
363         }
364         case 1: // round
365         {
366             pItem.reset(new XLineCapItem(drawing::LineCap_ROUND));
367             break;
368         }
369         case 2: // square
370         {
371             pItem.reset(new XLineCapItem(drawing::LineCap_SQUARE));
372             break;
373         }
374     }
375 
376     setLineCap(pItem.get());
377 }
378 
379 IMPL_LINK_NOARG(LinePropertyPanelBase, ToolboxWidthSelectHdl, const OString&, void)
380 {
381     mxTBWidth->set_menu_item_active(SELECTWIDTH, !mxTBWidth->get_menu_item_active(SELECTWIDTH));
382 }
383 
384 void LinePropertyPanelBase::EndLineWidthPopup()
385 {
386     mxTBWidth->set_menu_item_active(SELECTWIDTH, false);
387 }
388 
389 IMPL_LINK_NOARG( LinePropertyPanelBase, ChangeTransparentHdl, weld::MetricSpinButton&, void )
390 {
391     sal_uInt16 nVal = static_cast<sal_uInt16>(mxMFTransparent->get_value(FieldUnit::PERCENT));
392     XLineTransparenceItem aItem( nVal );
393 
394     setLineTransparency(aItem);
395 }
396 
397 void LinePropertyPanelBase::SetWidthIcon(int n)
398 {
399     if (n == 0)
400         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGNone);
401     else
402         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[n-1]);
403 }
404 
405 void LinePropertyPanelBase::SetWidthIcon()
406 {
407     if(!mbWidthValuable)
408     {
409         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGNone);
410         return;
411     }
412 
413     tools::Long nVal = OutputDevice::LogicToLogic(mnWidthCoreValue * 10, meMapUnit, MapUnit::MapPoint);
414 
415     if(nVal <= 6)
416         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[0]);
417     else if (nVal <= 9)
418         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[1]);
419     else if (nVal <= 12)
420         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[2]);
421     else if (nVal <= 19)
422         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[3]);
423     else if (nVal <= 26)
424         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[4]);
425     else if (nVal <= 37)
426         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[5]);
427     else if (nVal <= 52)
428         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[6]);
429     else
430         mxTBWidth->set_item_icon_name(SELECTWIDTH, maIMGWidthIcon[7]);
431 
432 }
433 
434 void LinePropertyPanelBase::SetWidth(tools::Long nWidth)
435 {
436     mnWidthCoreValue = nWidth;
437     mbWidthValuable = true;
438     mxLineWidthPopup->SetWidthSelect(mnWidthCoreValue, mbWidthValuable, meMapUnit);
439 }
440 
441 void LinePropertyPanelBase::ActivateControls()
442 {
443     mxGridLineProps->set_sensitive(!mbNoneLineStyle);
444     mxBoxArrowProps->set_sensitive(!mbNoneLineStyle);
445     mxLineStyleTB->set_item_sensitive(".uno:LineEndStyle", !mbNoneLineStyle);
446 
447     mxBoxArrowProps->set_visible(mbArrowSupported);
448     mxLineStyleTB->set_item_visible(".uno:LineEndStyle", mbArrowSupported);
449 }
450 
451 void LinePropertyPanelBase::setMapUnit(MapUnit eMapUnit)
452 {
453     meMapUnit = eMapUnit;
454     mxLineWidthPopup->SetWidthSelect(mnWidthCoreValue, mbWidthValuable, meMapUnit);
455 }
456 
457 void LinePropertyPanelBase::disableArrowHead()
458 {
459     mbArrowSupported = false;
460     ActivateControls();
461 }
462 
463 void LinePropertyPanelBase::enableArrowHead()
464 {
465     mbArrowSupported = true;
466     ActivateControls();
467 }
468 
469 } // end of namespace svx::sidebar
470 
471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
472