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 <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <svtools/toolbarmenu.hxx>
25 #include <vcl/toolbox.hxx>
26 
27 #include <svx/strings.hrc>
28 #include <svx/svdtrans.hxx>
29 #include <svx/dialmgr.hxx>
30 
31 #include <helpids.h>
32 #include "extrusioncontrols.hxx"
33 #include <extrusiondepthdialog.hxx>
34 
35 #include <bitmaps.hlst>
36 
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::lang;
39 using namespace ::com::sun::star::beans;
40 using namespace ::com::sun::star::util;
41 using namespace ::com::sun::star::graphic;
42 
43 namespace svx
44 {
45 
46 const sal_Int32 gSkewList[] = { 135, 90, 45, 180, 0, -360, -135, -90, -45 };
47 constexpr OUStringLiteral g_sExtrusionDirection = u".uno:ExtrusionDirection";
48 constexpr OUStringLiteral g_sExtrusionProjection = u".uno:ExtrusionProjection";
49 
50 const std::u16string_view aLightOffBmps[] =
51 {
52     u"" RID_SVXBMP_LIGHT_OFF_FROM_TOP_LEFT,
53     u"" RID_SVXBMP_LIGHT_OFF_FROM_TOP,
54     u"" RID_SVXBMP_LIGHT_OFF_FROM_TOP_RIGHT,
55     u"" RID_SVXBMP_LIGHT_OFF_FROM_LEFT,
56     u"",
57     u"" RID_SVXBMP_LIGHT_OFF_FROM_RIGHT,
58     u"" RID_SVXBMP_LIGHT_OFF_FROM_BOTTOM_LEFT,
59     u"" RID_SVXBMP_LIGHT_OFF_FROM_BOTTOM,
60     u"" RID_SVXBMP_LIGHT_OFF_FROM_BOTTOM_RIGHT
61 };
62 
63 const std::u16string_view aLightOnBmps[] =
64 {
65     u"" RID_SVXBMP_LIGHT_ON_FROM_TOP_LEFT,
66     u"" RID_SVXBMP_LIGHT_ON_FROM_TOP,
67     u"" RID_SVXBMP_LIGHT_ON_FROM_TOP_RIGHT,
68     u"" RID_SVXBMP_LIGHT_ON_FROM_LEFT,
69     u"",
70     u"" RID_SVXBMP_LIGHT_ON_FROM_RIGHT,
71     u"" RID_SVXBMP_LIGHT_ON_FROM_BOTTOM_LEFT,
72     u"" RID_SVXBMP_LIGHT_ON_FROM_BOTTOM,
73     u"" RID_SVXBMP_LIGHT_ON_FROM_BOTTOM_RIGHT
74 };
75 
76 const std::u16string_view aLightPreviewBmps[] =
77 {
78     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_TOP_LEFT,
79     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_TOP,
80     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_TOP_RIGHT,
81     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_LEFT,
82     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_RIGHT,
83     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_FRONT,
84     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_BOTTOM_LEFT,
85     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_BOTTOM,
86     u"" RID_SVXBMP_LIGHT_PREVIEW_FROM_BOTTOM_RIGHT
87 };
88 
89 const std::u16string_view aDirectionBmps[] =
90 {
91     u"" RID_SVXBMP_DIRECTION_DIRECTION_NW,
92     u"" RID_SVXBMP_DIRECTION_DIRECTION_N,
93     u"" RID_SVXBMP_DIRECTION_DIRECTION_NE,
94     u"" RID_SVXBMP_DIRECTION_DIRECTION_W,
95     u"" RID_SVXBMP_DIRECTION_DIRECTION_NONE,
96     u"" RID_SVXBMP_DIRECTION_DIRECTION_E,
97     u"" RID_SVXBMP_DIRECTION_DIRECTION_SW,
98     u"" RID_SVXBMP_DIRECTION_DIRECTION_S,
99     u"" RID_SVXBMP_DIRECTION_DIRECTION_SE
100 };
101 
102 static const char* aDirectionStrs[] =
103 {
104     RID_SVXSTR_DIRECTION_NW,
105     RID_SVXSTR_DIRECTION_N,
106     RID_SVXSTR_DIRECTION_NE,
107     RID_SVXSTR_DIRECTION_W,
108     RID_SVXSTR_DIRECTION_NONE,
109     RID_SVXSTR_DIRECTION_E,
110     RID_SVXSTR_DIRECTION_SW,
111     RID_SVXSTR_DIRECTION_S,
112     RID_SVXSTR_DIRECTION_SE
113 };
114 
ExtrusionDirectionWindow(svt::PopupWindowController * pControl,weld::Widget * pParent)115 ExtrusionDirectionWindow::ExtrusionDirectionWindow(
116     svt::PopupWindowController* pControl,
117     weld::Widget* pParent)
118     : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/directionwindow.ui", "DirectionWindow")
119     , mxControl(pControl)
120     , mxDirectionSet(new ValueSet(nullptr))
121     , mxDirectionSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxDirectionSet))
122     , mxPerspective(m_xBuilder->weld_radio_button("perspective"))
123     , mxParallel(m_xBuilder->weld_radio_button("parallel"))
124 {
125     mxDirectionSet->SetStyle(WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT);
126 
127     for (sal_uInt16 i = DIRECTION_NW; i <= DIRECTION_SE; ++i)
128     {
129         maImgDirection[i] = Image(StockImage::Yes, OUString(aDirectionBmps[i]));
130     }
131 
132     mxDirectionSet->SetSelectHdl( LINK( this, ExtrusionDirectionWindow, SelectValueSetHdl ) );
133     mxDirectionSet->SetColCount( 3 );
134     mxDirectionSet->EnableFullItemMode( false );
135 
136     for (sal_uInt16 i = DIRECTION_NW; i <= DIRECTION_SE; ++i)
137     {
138         mxDirectionSet->InsertItem(i + 1, maImgDirection[i], SvxResId(aDirectionStrs[i]));
139     }
140 
141     Size aSize(72, 72);
142     mxDirectionSet->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height());
143     mxDirectionSet->SetOutputSizePixel(aSize);
144 
145     mxPerspective->connect_toggled(LINK(this, ExtrusionDirectionWindow, SelectToolbarMenuHdl));
146 
147     AddStatusListener( g_sExtrusionDirection );
148     AddStatusListener( g_sExtrusionProjection );
149 }
150 
GrabFocus()151 void ExtrusionDirectionWindow::GrabFocus()
152 {
153     mxDirectionSet->GrabFocus();
154 }
155 
~ExtrusionDirectionWindow()156 ExtrusionDirectionWindow::~ExtrusionDirectionWindow()
157 {
158 }
159 
implSetDirection(sal_Int32 nSkew,bool bEnabled)160 void ExtrusionDirectionWindow::implSetDirection( sal_Int32 nSkew, bool bEnabled )
161 {
162     sal_uInt16 nItemId;
163     for( nItemId = DIRECTION_NW; nItemId <= DIRECTION_SE; nItemId++ )
164     {
165         if( gSkewList[nItemId] == nSkew )
166             break;
167     }
168 
169     if( nItemId <= DIRECTION_SE )
170     {
171         mxDirectionSet->SelectItem( nItemId+1 );
172     }
173     else
174     {
175         mxDirectionSet->SetNoSelection();
176     }
177 
178     if (bEnabled)
179         mxDirectionSet->Enable();
180     else
181         mxDirectionSet->Disable();
182 }
183 
implSetProjection(sal_Int32 nProjection,bool bEnabled)184 void ExtrusionDirectionWindow::implSetProjection( sal_Int32 nProjection, bool bEnabled )
185 {
186     mxPerspective->set_active(nProjection == 0 && bEnabled);
187     mxParallel->set_active(nProjection == 1 && bEnabled);
188     mxPerspective->set_sensitive(bEnabled);
189     mxParallel->set_sensitive(bEnabled);
190 }
191 
statusChanged(const css::frame::FeatureStateEvent & Event)192 void ExtrusionDirectionWindow::statusChanged(
193     const css::frame::FeatureStateEvent& Event
194 )
195 {
196     if( Event.FeatureURL.Main == g_sExtrusionDirection )
197     {
198         if( !Event.IsEnabled )
199         {
200             implSetDirection( -1, false );
201         }
202         else
203         {
204             sal_Int32 nValue = 0;
205             if( Event.State >>= nValue )
206                 implSetDirection( nValue, true );
207         }
208     }
209     else if( Event.FeatureURL.Main == g_sExtrusionProjection )
210     {
211         if( !Event.IsEnabled )
212         {
213             implSetProjection( -1, false );
214         }
215         else
216         {
217             sal_Int32 nValue = 0;
218             if( Event.State >>= nValue )
219                 implSetProjection( nValue, true );
220         }
221     }
222 }
223 
IMPL_LINK_NOARG(ExtrusionDirectionWindow,SelectValueSetHdl,ValueSet *,void)224 IMPL_LINK_NOARG(ExtrusionDirectionWindow, SelectValueSetHdl, ValueSet*, void)
225 {
226     Sequence< PropertyValue > aArgs( 1 );
227     aArgs[0].Name = OUString(g_sExtrusionDirection).copy(5);
228     aArgs[0].Value <<= gSkewList[mxDirectionSet->GetSelectedItemId()-1];
229 
230     mxControl->dispatchCommand( g_sExtrusionDirection, aArgs );
231 
232     mxControl->EndPopupMode();
233 }
234 
IMPL_LINK_NOARG(ExtrusionDirectionWindow,SelectToolbarMenuHdl,weld::Toggleable &,void)235 IMPL_LINK_NOARG(ExtrusionDirectionWindow, SelectToolbarMenuHdl, weld::Toggleable&, void)
236 {
237     int nProjection = mxPerspective->get_active() ? 0 : 1;
238 
239     Sequence< PropertyValue > aArgs( 1 );
240     aArgs[0].Name = OUString(g_sExtrusionProjection).copy(5);
241     aArgs[0].Value <<= static_cast<sal_Int32>(nProjection);
242 
243     mxControl->dispatchCommand( g_sExtrusionProjection, aArgs );
244     implSetProjection( nProjection, true );
245 
246     mxControl->EndPopupMode();
247 }
248 
ExtrusionDirectionControl(const Reference<XComponentContext> & rxContext)249 ExtrusionDirectionControl::ExtrusionDirectionControl(
250     const Reference< XComponentContext >& rxContext
251 )   : svt::PopupWindowController(
252         rxContext,
253         Reference< css::frame::XFrame >(),
254         ".uno:ExtrusionDirectionFloater"
255     )
256 {
257 }
258 
weldPopupWindow()259 std::unique_ptr<WeldToolbarPopup> ExtrusionDirectionControl::weldPopupWindow()
260 {
261     return std::make_unique<ExtrusionDirectionWindow>(this, m_pToolbar);
262 }
263 
createVclPopupWindow(vcl::Window * pParent)264 VclPtr<vcl::Window> ExtrusionDirectionControl::createVclPopupWindow( vcl::Window* pParent )
265 {
266     mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
267         std::make_unique<ExtrusionDirectionWindow>(this, pParent->GetFrameWeld()));
268 
269     mxInterimPopover->Show();
270 
271     return mxInterimPopover;
272 }
273 
274 // XInitialization
initialize(const css::uno::Sequence<css::uno::Any> & aArguments)275 void SAL_CALL ExtrusionDirectionControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
276 {
277     svt::PopupWindowController::initialize( aArguments );
278 
279     ToolBox* pToolBox = nullptr;
280     ToolBoxItemId nId;
281     if ( getToolboxId( nId, &pToolBox ) )
282         pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
283 }
284 
285 // XServiceInfo
286 
287 
getImplementationName()288 OUString ExtrusionDirectionControl::getImplementationName()
289 {
290     return "com.sun.star.comp.svx.ExtrusionDirectionController";
291 }
292 
293 
getSupportedServiceNames()294 Sequence< OUString > ExtrusionDirectionControl::getSupportedServiceNames()
295 {
296     return { "com.sun.star.frame.ToolbarController" };
297 }
298 
299 
300 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_svx_ExtrusionDirectionControl_get_implementation(css::uno::XComponentContext * xContext,css::uno::Sequence<css::uno::Any> const &)301 com_sun_star_comp_svx_ExtrusionDirectionControl_get_implementation(
302     css::uno::XComponentContext* xContext,
303     css::uno::Sequence<css::uno::Any> const &)
304 {
305     return cppu::acquire(new ExtrusionDirectionControl(xContext));
306 }
307 
308 
ExtrusionDepthDialog(weld::Window * pParent,double fDepth,FieldUnit eDefaultUnit)309 ExtrusionDepthDialog::ExtrusionDepthDialog(weld::Window* pParent, double fDepth, FieldUnit eDefaultUnit)
310     : GenericDialogController(pParent, "svx/ui/extrustiondepthdialog.ui", "ExtrustionDepthDialog")
311     , m_xMtrDepth(m_xBuilder->weld_metric_spin_button("depth", eDefaultUnit))
312 {
313     m_xMtrDepth->set_value(static_cast<int>(fDepth) * 100, FieldUnit::MM_100TH);
314 }
315 
~ExtrusionDepthDialog()316 ExtrusionDepthDialog::~ExtrusionDepthDialog()
317 {
318 }
319 
getDepth() const320 double ExtrusionDepthDialog::getDepth() const
321 {
322     return static_cast<double>(m_xMtrDepth->get_value(FieldUnit::MM_100TH)) / 100.0;
323 }
324 
325 double const aDepthListInch[] = { 0, 1270,2540,5080,10160 };
326 double const aDepthListMM[] = { 0, 1000, 2500, 5000, 10000 };
327 
328 constexpr OUStringLiteral gsExtrusionDepth( u".uno:ExtrusionDepth" );
329 constexpr OUStringLiteral gsMetricUnit(     u".uno:MetricUnit"     );
330 
ExtrusionDepthWindow(svt::PopupWindowController * pControl,weld::Widget * pParent)331 ExtrusionDepthWindow::ExtrusionDepthWindow(svt::PopupWindowController* pControl, weld::Widget* pParent)
332     : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/depthwindow.ui", "DepthWindow")
333     , mxControl(pControl)
334     , mxDepth0(m_xBuilder->weld_radio_button("depth0"))
335     , mxDepth1(m_xBuilder->weld_radio_button("depth1"))
336     , mxDepth2(m_xBuilder->weld_radio_button("depth2"))
337     , mxDepth3(m_xBuilder->weld_radio_button("depth3"))
338     , mxDepth4(m_xBuilder->weld_radio_button("depth4"))
339     , mxInfinity(m_xBuilder->weld_radio_button("infinity"))
340     , mxCustom(m_xBuilder->weld_radio_button("custom"))
341     , meUnit(FieldUnit::NONE)
342     , mfDepth( -1.0 )
343     , mbSettingValue(false)
344     , mbCommandDispatched(false)
345 {
346     mxDepth0->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl));
347     mxDepth1->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl));
348     mxDepth2->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl));
349     mxDepth3->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl));
350     mxDepth4->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl));
351     mxInfinity->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl));
352     mxCustom->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl));
353     mxCustom->connect_mouse_release(LINK(this, ExtrusionDepthWindow, MouseReleaseHdl));
354 
355     AddStatusListener( gsExtrusionDepth );
356     AddStatusListener( gsMetricUnit );
357 }
358 
GrabFocus()359 void ExtrusionDepthWindow::GrabFocus()
360 {
361     mxDepth0->grab_focus();
362 }
363 
implSetDepth(double fDepth)364 void ExtrusionDepthWindow::implSetDepth( double fDepth )
365 {
366     mfDepth = fDepth;
367 
368     bool bSettingValue = mbSettingValue;
369     mbSettingValue = true;
370 
371     mxCustom->set_active(true);
372     bool bIsMetric = IsMetric(meUnit);
373     mxDepth0->set_active(fDepth == (bIsMetric ? aDepthListMM[0] : aDepthListInch[0]));
374     mxDepth1->set_active(fDepth == (bIsMetric ? aDepthListMM[1] : aDepthListInch[1]));
375     mxDepth2->set_active(fDepth == (bIsMetric ? aDepthListMM[2] : aDepthListInch[2]));
376     mxDepth3->set_active(fDepth == (bIsMetric ? aDepthListMM[3] : aDepthListInch[3]));
377     mxDepth4->set_active(fDepth == (bIsMetric ? aDepthListMM[4] : aDepthListInch[4]));
378     mxInfinity->set_active(fDepth >= 338666);
379 
380     mbSettingValue = bSettingValue;
381 }
382 
implFillStrings(FieldUnit eUnit)383 void ExtrusionDepthWindow::implFillStrings( FieldUnit eUnit )
384 {
385     meUnit = eUnit;
386 
387     const char* aDepths[] =
388     {
389         RID_SVXSTR_DEPTH_0,
390         RID_SVXSTR_DEPTH_1,
391         RID_SVXSTR_DEPTH_2,
392         RID_SVXSTR_DEPTH_3,
393         RID_SVXSTR_DEPTH_4
394     };
395 
396     const char* aDepthsInch[] =
397     {
398         RID_SVXSTR_DEPTH_0_INCH,
399         RID_SVXSTR_DEPTH_1_INCH,
400         RID_SVXSTR_DEPTH_2_INCH,
401         RID_SVXSTR_DEPTH_3_INCH,
402         RID_SVXSTR_DEPTH_4_INCH
403     };
404 
405     assert(SAL_N_ELEMENTS(aDepths) == SAL_N_ELEMENTS(aDepthsInch));
406 
407     const char** pResource = IsMetric(eUnit) ? aDepths : aDepthsInch;
408 
409     mxDepth0->set_label(SvxResId(pResource[0]));
410     mxDepth1->set_label(SvxResId(pResource[1]));
411     mxDepth2->set_label(SvxResId(pResource[2]));
412     mxDepth3->set_label(SvxResId(pResource[3]));
413     mxDepth4->set_label(SvxResId(pResource[4]));
414 }
415 
statusChanged(const css::frame::FeatureStateEvent & Event)416 void ExtrusionDepthWindow::statusChanged(
417     const css::frame::FeatureStateEvent& Event
418 )
419 {
420     if( Event.FeatureURL.Main == gsExtrusionDepth )
421     {
422         if( !Event.IsEnabled )
423         {
424             implSetDepth( 0 );
425         }
426         else
427         {
428             double fValue = 0.0;
429             if( Event.State >>= fValue )
430                 implSetDepth( fValue );
431         }
432     }
433     else if( Event.FeatureURL.Main == gsMetricUnit )
434     {
435         if( Event.IsEnabled )
436         {
437             sal_Int32 nValue = 0;
438             if( Event.State >>= nValue )
439             {
440                 implFillStrings( static_cast<FieldUnit>(nValue) );
441                 if( mfDepth >= 0.0 )
442                     implSetDepth( mfDepth );
443             }
444         }
445     }
446 }
447 
DispatchDepthDialog()448 void ExtrusionDepthWindow::DispatchDepthDialog()
449 {
450     Sequence< PropertyValue > aArgs( 2 );
451     aArgs[0].Name = "Depth";
452     aArgs[0].Value <<= mfDepth;
453     aArgs[1].Name = "Metric";
454     aArgs[1].Value <<= static_cast<sal_Int32>( meUnit );
455 
456     rtl::Reference<svt::PopupWindowController> xControl(mxControl);
457     xControl->EndPopupMode();
458     xControl->dispatchCommand(".uno:ExtrusionDepthDialog", aArgs);
459     mbCommandDispatched = true;
460 }
461 
IMPL_LINK(ExtrusionDepthWindow,SelectHdl,weld::Toggleable &,rButton,void)462 IMPL_LINK(ExtrusionDepthWindow, SelectHdl, weld::Toggleable&, rButton, void)
463 {
464     if (mbSettingValue || !rButton.get_active())
465         return;
466 
467     // see MouseReleaseHdl for mbCommandDispatched check, there's no guarantee
468     // this toggle will happen before that mouse release though it does in
469     // practice for vcl and gtk
470     if (mbCommandDispatched)
471         return;
472 
473     if (mxCustom->get_active())
474         DispatchDepthDialog();
475     else
476     {
477         double fDepth;
478 
479         if (mxInfinity->get_active())
480         {
481             fDepth = 338666.6;
482         }
483         else
484         {
485             int nSelected;
486             if (mxDepth0->get_active())
487                 nSelected = 0;
488             else if (mxDepth1->get_active())
489                 nSelected = 1;
490             else if (mxDepth2->get_active())
491                 nSelected = 2;
492             else if (mxDepth3->get_active())
493                 nSelected = 3;
494             else
495                 nSelected = 4;
496 
497             fDepth = IsMetric( meUnit ) ? aDepthListMM[nSelected] : aDepthListInch[nSelected];
498         }
499 
500         Sequence< PropertyValue > aArgs( 1 );
501         aArgs[0].Name = OUString(gsExtrusionDepth).copy(5);
502         aArgs[0].Value <<= fDepth;
503 
504         mxControl->dispatchCommand( gsExtrusionDepth,  aArgs );
505         mbCommandDispatched = true;
506         implSetDepth( fDepth );
507 
508         mxControl->EndPopupMode();
509     }
510 }
511 
IMPL_LINK_NOARG(ExtrusionDepthWindow,MouseReleaseHdl,const MouseEvent &,bool)512 IMPL_LINK_NOARG(ExtrusionDepthWindow, MouseReleaseHdl, const MouseEvent&, bool)
513 {
514     /*
515      tdf#145296 if the "custom" radiobutton was presented preselected as
516      toggled on and the user clicked on it then there's no toggled signal sent
517      because the item was already toggled on and didn't change state.
518 
519      So if that happens launch the custom spacing dialog explicitly here on
520      mouse release.
521     */
522     if (mxCustom->get_active() && !mbCommandDispatched)
523     {
524         DispatchDepthDialog();
525         return true;
526     }
527     return false;
528 }
529 
530 // ExtrusionDirectionControl
ExtrusionDepthController(const Reference<XComponentContext> & rxContext)531 ExtrusionDepthController::ExtrusionDepthController(
532     const Reference< XComponentContext >& rxContext
533 )   : svt::PopupWindowController(
534         rxContext,
535         Reference< css::frame::XFrame >(),
536         ".uno:ExtrusionDepthFloater"
537     )
538 {
539 }
540 
weldPopupWindow()541 std::unique_ptr<WeldToolbarPopup> ExtrusionDepthController::weldPopupWindow()
542 {
543     return std::make_unique<ExtrusionDepthWindow>(this, m_pToolbar);
544 }
545 
createVclPopupWindow(vcl::Window * pParent)546 VclPtr<vcl::Window> ExtrusionDepthController::createVclPopupWindow( vcl::Window* pParent )
547 {
548     mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
549         std::make_unique<ExtrusionDepthWindow>(this, pParent->GetFrameWeld()));
550 
551     mxInterimPopover->Show();
552 
553     return mxInterimPopover;
554 }
555 
556 // XInitialization
initialize(const css::uno::Sequence<css::uno::Any> & aArguments)557 void SAL_CALL ExtrusionDepthController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
558 {
559     svt::PopupWindowController::initialize( aArguments );
560 
561     ToolBox* pToolBox = nullptr;
562     ToolBoxItemId nId;
563     if ( getToolboxId( nId, &pToolBox ) )
564         pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
565 }
566 
567 // XServiceInfo
568 
569 
getImplementationName()570 OUString ExtrusionDepthController::getImplementationName()
571 {
572     return "com.sun.star.comp.svx.ExtrusionDepthController";
573 }
574 
575 
getSupportedServiceNames()576 Sequence< OUString > ExtrusionDepthController::getSupportedServiceNames()
577 {
578     return { "com.sun.star.frame.ToolbarController" };
579 }
580 
581 
582 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_svx_ExtrusionDepthController_get_implementation(css::uno::XComponentContext * xContext,css::uno::Sequence<css::uno::Any> const &)583 com_sun_star_comp_svx_ExtrusionDepthController_get_implementation(
584     css::uno::XComponentContext* xContext,
585     css::uno::Sequence<css::uno::Any> const &)
586 {
587     return cppu::acquire(new ExtrusionDepthController(xContext));
588 }
589 
590 
591 constexpr OUStringLiteral g_sExtrusionLightingDirection = u".uno:ExtrusionLightingDirection";
592 constexpr OUStringLiteral g_sExtrusionLightingIntensity = u".uno:ExtrusionLightingIntensity";
593 
ExtrusionLightingWindow(svt::PopupWindowController * pControl,weld::Widget * pParent)594 ExtrusionLightingWindow::ExtrusionLightingWindow(svt::PopupWindowController* pControl,
595                                                  weld::Widget* pParent)
596     : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/lightingwindow.ui", "LightingWindow")
597     , mxControl(pControl)
598     , mxLightingSet(new ValueSet(nullptr))
599     , mxLightingSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxLightingSet))
600     , mxBright(m_xBuilder->weld_radio_button("bright"))
601     , mxNormal(m_xBuilder->weld_radio_button("normal"))
602     , mxDim(m_xBuilder->weld_radio_button("dim"))
603 {
604     mxLightingSet->SetStyle(WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT);
605 
606     for (sal_uInt16 i = FROM_TOP_LEFT; i <= FROM_BOTTOM_RIGHT; ++i)
607     {
608         if( i != FROM_FRONT )
609         {
610             maImgLightingOff[i] = Image(StockImage::Yes, OUString(aLightOffBmps[i]));
611             maImgLightingOn[i] = Image(StockImage::Yes, OUString(aLightOnBmps[i]));
612         }
613         maImgLightingPreview[i] = Image(StockImage::Yes, OUString(aLightPreviewBmps[i]));
614     }
615 
616     mxLightingSet->SetHelpId( HID_VALUESET_EXTRUSION_LIGHTING );
617 
618     mxLightingSet->SetSelectHdl( LINK( this, ExtrusionLightingWindow, SelectValueSetHdl ) );
619     mxLightingSet->SetColCount( 3 );
620     mxLightingSet->EnableFullItemMode( false );
621 
622     for (sal_uInt16 i = FROM_TOP_LEFT; i <= FROM_BOTTOM_RIGHT; ++i)
623     {
624         if( i != FROM_FRONT )
625         {
626             mxLightingSet->InsertItem( i+1, maImgLightingOff[i] );
627         }
628         else
629         {
630             mxLightingSet->InsertItem( 5, maImgLightingPreview[FROM_FRONT] );
631         }
632     }
633     Size aSize(72, 72);
634     mxLightingSet->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height());
635     mxLightingSet->SetOutputSizePixel(aSize);
636 
637     mxBright->connect_toggled(LINK(this, ExtrusionLightingWindow, SelectToolbarMenuHdl));
638     mxNormal->connect_toggled(LINK(this, ExtrusionLightingWindow, SelectToolbarMenuHdl));
639     mxDim->connect_toggled(LINK(this, ExtrusionLightingWindow, SelectToolbarMenuHdl));
640 
641     AddStatusListener( g_sExtrusionLightingDirection );
642     AddStatusListener( g_sExtrusionLightingIntensity );
643 }
644 
GrabFocus()645 void ExtrusionLightingWindow::GrabFocus()
646 {
647     mxLightingSet->GrabFocus();
648 }
649 
~ExtrusionLightingWindow()650 ExtrusionLightingWindow::~ExtrusionLightingWindow()
651 {
652 }
653 
implSetIntensity(int nLevel,bool bEnabled)654 void ExtrusionLightingWindow::implSetIntensity( int nLevel, bool bEnabled )
655 {
656     mxBright->set_sensitive(bEnabled);
657     mxBright->set_active(nLevel == 0 && bEnabled);
658     mxNormal->set_sensitive(bEnabled);
659     mxNormal->set_active(nLevel == 1 && bEnabled);
660     mxDim->set_sensitive(bEnabled);
661     mxDim->set_active(nLevel == 2 && bEnabled);
662 }
663 
implSetDirection(int nDirection,bool bEnabled)664 void ExtrusionLightingWindow::implSetDirection( int nDirection, bool bEnabled )
665 {
666     if( !bEnabled )
667         nDirection = FROM_FRONT;
668 
669     sal_uInt16 nItemId;
670     for( nItemId = FROM_TOP_LEFT; nItemId <= FROM_BOTTOM_RIGHT; nItemId++ )
671     {
672         if( nItemId == FROM_FRONT )
673         {
674             mxLightingSet->SetItemImage( nItemId + 1, maImgLightingPreview[ nDirection ] );
675         }
676         else
677         {
678             mxLightingSet->SetItemImage(
679                 nItemId + 1,
680                 static_cast<sal_uInt16>(nDirection) == nItemId ? maImgLightingOn[nItemId] : maImgLightingOff[nItemId]
681             );
682         }
683     }
684 
685     if (bEnabled)
686         mxLightingSet->Enable();
687     else
688         mxLightingSet->Disable();
689 }
690 
statusChanged(const css::frame::FeatureStateEvent & Event)691 void ExtrusionLightingWindow::statusChanged(
692     const css::frame::FeatureStateEvent& Event
693 )
694 {
695     if( Event.FeatureURL.Main == g_sExtrusionLightingIntensity )
696     {
697         if( !Event.IsEnabled )
698         {
699             implSetIntensity( 0, false );
700         }
701         else
702         {
703             sal_Int32 nValue = 0;
704             if( Event.State >>= nValue )
705                 implSetIntensity( nValue, true );
706         }
707     }
708     else if( Event.FeatureURL.Main == g_sExtrusionLightingDirection )
709     {
710         if( !Event.IsEnabled )
711         {
712             implSetDirection( 0, false );
713         }
714         else
715         {
716             sal_Int32 nValue = 0;
717             if( Event.State >>= nValue )
718                 implSetDirection( nValue, true );
719         }
720     }
721 }
722 
IMPL_LINK_NOARG(ExtrusionLightingWindow,SelectValueSetHdl,ValueSet *,void)723 IMPL_LINK_NOARG(ExtrusionLightingWindow, SelectValueSetHdl, ValueSet*, void)
724 {
725     sal_Int32 nDirection = mxLightingSet->GetSelectedItemId();
726 
727     if( (nDirection > 0) && (nDirection < 10) )
728     {
729         nDirection--;
730 
731         Sequence< PropertyValue > aArgs( 1 );
732         aArgs[0].Name = OUString(g_sExtrusionLightingDirection).copy(5);
733         aArgs[0].Value <<= nDirection;
734 
735         mxControl->dispatchCommand( g_sExtrusionLightingDirection, aArgs );
736 
737         implSetDirection( nDirection, true );
738     }
739 
740     mxControl->EndPopupMode();
741 }
742 
IMPL_LINK(ExtrusionLightingWindow,SelectToolbarMenuHdl,weld::Toggleable &,rButton,void)743 IMPL_LINK(ExtrusionLightingWindow, SelectToolbarMenuHdl, weld::Toggleable&, rButton, void)
744 {
745     if (!rButton.get_active())
746         return;
747 
748     int nLevel;
749     if (mxBright->get_active())
750         nLevel = 0;
751     else if (mxNormal->get_active())
752         nLevel = 1;
753     else
754         nLevel = 2;
755 
756     Sequence< PropertyValue > aArgs( 1 );
757     aArgs[0].Name = OUString(g_sExtrusionLightingIntensity).copy(5);
758     aArgs[0].Value <<= static_cast<sal_Int32>(nLevel);
759 
760     mxControl->dispatchCommand( g_sExtrusionLightingIntensity, aArgs );
761 
762     implSetIntensity( nLevel, true );
763 
764     mxControl->EndPopupMode();
765 }
766 
ExtrusionLightingControl(const Reference<XComponentContext> & rxContext)767 ExtrusionLightingControl::ExtrusionLightingControl(
768     const Reference< XComponentContext >& rxContext
769 )   : svt::PopupWindowController( rxContext,
770                 Reference< css::frame::XFrame >(),
771                 ".uno:ExtrusionDirectionFloater"
772     )
773 {
774 }
775 
weldPopupWindow()776 std::unique_ptr<WeldToolbarPopup> ExtrusionLightingControl::weldPopupWindow()
777 {
778     return std::make_unique<ExtrusionLightingWindow>(this, m_pToolbar);
779 }
780 
createVclPopupWindow(vcl::Window * pParent)781 VclPtr<vcl::Window> ExtrusionLightingControl::createVclPopupWindow( vcl::Window* pParent )
782 {
783     mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
784         std::make_unique<ExtrusionLightingWindow>(this, pParent->GetFrameWeld()));
785 
786     mxInterimPopover->Show();
787 
788     return mxInterimPopover;
789 }
790 
791 // XInitialization
initialize(const css::uno::Sequence<css::uno::Any> & aArguments)792 void SAL_CALL ExtrusionLightingControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
793 {
794     svt::PopupWindowController::initialize( aArguments );
795 
796     ToolBox* pToolBox = nullptr;
797     ToolBoxItemId nId;
798     if ( getToolboxId( nId, &pToolBox ) )
799         pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
800 }
801 
802 // XServiceInfo
803 
804 
getImplementationName()805 OUString ExtrusionLightingControl::getImplementationName()
806 {
807     return "com.sun.star.comp.svx.ExtrusionLightingController";
808 }
809 
810 
getSupportedServiceNames()811 Sequence< OUString > ExtrusionLightingControl::getSupportedServiceNames()
812 {
813     return { "com.sun.star.frame.ToolbarController" };
814 }
815 
816 
817 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_svx_ExtrusionLightingControl_get_implementation(css::uno::XComponentContext * xContext,css::uno::Sequence<css::uno::Any> const &)818 com_sun_star_comp_svx_ExtrusionLightingControl_get_implementation(
819     css::uno::XComponentContext* xContext,
820     css::uno::Sequence<css::uno::Any> const &)
821 {
822     return cppu::acquire(new ExtrusionLightingControl(xContext));
823 }
824 
825 
826 constexpr OUStringLiteral g_sExtrusionSurface = u".uno:ExtrusionSurface";
827 
ExtrusionSurfaceWindow(svt::PopupWindowController * pControl,weld::Widget * pParent)828 ExtrusionSurfaceWindow::ExtrusionSurfaceWindow(svt::PopupWindowController* pControl, weld::Widget* pParent)
829     : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/surfacewindow.ui", "SurfaceWindow")
830     , mxControl(pControl)
831     , mxWireFrame(m_xBuilder->weld_radio_button("wireframe"))
832     , mxMatt(m_xBuilder->weld_radio_button("matt"))
833     , mxPlastic(m_xBuilder->weld_radio_button("plastic"))
834     , mxMetal(m_xBuilder->weld_radio_button("metal"))
835 {
836     mxWireFrame->connect_toggled(LINK(this, ExtrusionSurfaceWindow, SelectHdl));
837     mxMatt->connect_toggled(LINK(this, ExtrusionSurfaceWindow, SelectHdl));
838     mxPlastic->connect_toggled(LINK(this, ExtrusionSurfaceWindow, SelectHdl));
839     mxMetal->connect_toggled(LINK(this, ExtrusionSurfaceWindow, SelectHdl));
840 
841     AddStatusListener( g_sExtrusionSurface );
842 }
843 
GrabFocus()844 void ExtrusionSurfaceWindow::GrabFocus()
845 {
846     mxWireFrame->grab_focus();
847 }
848 
implSetSurface(int nSurface,bool bEnabled)849 void ExtrusionSurfaceWindow::implSetSurface( int nSurface, bool bEnabled )
850 {
851     mxWireFrame->set_active(nSurface == 0 && bEnabled);
852     mxWireFrame->set_sensitive(bEnabled);
853     mxMatt->set_active(nSurface == 1 && bEnabled);
854     mxMatt->set_sensitive(bEnabled);
855     mxPlastic->set_active(nSurface == 2 && bEnabled);
856     mxPlastic->set_sensitive(bEnabled);
857     mxMetal->set_active(nSurface == 3 && bEnabled);
858     mxMetal->set_sensitive(bEnabled);
859 }
860 
statusChanged(const css::frame::FeatureStateEvent & Event)861 void ExtrusionSurfaceWindow::statusChanged(
862     const css::frame::FeatureStateEvent& Event
863 )
864 {
865     if( Event.FeatureURL.Main != g_sExtrusionSurface )
866         return;
867 
868     if( !Event.IsEnabled )
869     {
870         implSetSurface( 0, false );
871     }
872     else
873     {
874         sal_Int32 nValue = 0;
875         if( Event.State >>= nValue )
876             implSetSurface( nValue, true );
877     }
878 }
879 
IMPL_LINK(ExtrusionSurfaceWindow,SelectHdl,weld::Toggleable &,rButton,void)880 IMPL_LINK(ExtrusionSurfaceWindow, SelectHdl, weld::Toggleable&, rButton, void)
881 {
882     if (!rButton.get_active())
883         return;
884 
885     sal_Int32 nSurface;
886     if (mxWireFrame->get_active())
887         nSurface = 0;
888     else if (mxMatt->get_active())
889         nSurface = 1;
890     else if (mxPlastic->get_active())
891         nSurface = 2;
892     else
893         nSurface = 3;
894 
895     Sequence< PropertyValue > aArgs( 1 );
896     aArgs[0].Name = OUString(g_sExtrusionSurface).copy(5);
897     aArgs[0].Value <<= nSurface;
898 
899     mxControl->dispatchCommand( g_sExtrusionSurface, aArgs );
900 
901     implSetSurface( nSurface, true );
902 
903     mxControl->EndPopupMode();
904 }
905 
ExtrusionSurfaceControl(const Reference<XComponentContext> & rxContext)906 ExtrusionSurfaceControl::ExtrusionSurfaceControl(
907     const Reference< XComponentContext >& rxContext
908 )
909 :   svt::PopupWindowController(
910         rxContext,
911         Reference< css::frame::XFrame >(),
912         ".uno:ExtrusionSurfaceFloater"
913     )
914 {
915 }
916 
weldPopupWindow()917 std::unique_ptr<WeldToolbarPopup> ExtrusionSurfaceControl::weldPopupWindow()
918 {
919     return std::make_unique<ExtrusionSurfaceWindow>(this, m_pToolbar);
920 }
921 
createVclPopupWindow(vcl::Window * pParent)922 VclPtr<vcl::Window> ExtrusionSurfaceControl::createVclPopupWindow( vcl::Window* pParent )
923 {
924     mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent,
925         std::make_unique<ExtrusionSurfaceWindow>(this, pParent->GetFrameWeld()));
926 
927     mxInterimPopover->Show();
928 
929     return mxInterimPopover;
930 }
931 
932 // XInitialization
initialize(const css::uno::Sequence<css::uno::Any> & aArguments)933 void SAL_CALL ExtrusionSurfaceControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments )
934 {
935     svt::PopupWindowController::initialize( aArguments );
936 
937     ToolBox* pToolBox = nullptr;
938     ToolBoxItemId nId;
939     if ( getToolboxId( nId, &pToolBox ) )
940         pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY );
941 }
942 
943 // XServiceInfo
944 
945 
getImplementationName()946 OUString ExtrusionSurfaceControl::getImplementationName()
947 {
948     return "com.sun.star.comp.svx.ExtrusionSurfaceController";
949 }
950 
951 
getSupportedServiceNames()952 Sequence< OUString > ExtrusionSurfaceControl::getSupportedServiceNames()
953 {
954     return { "com.sun.star.frame.ToolbarController" };
955 }
956 
957 
958 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_svx_ExtrusionSurfaceControl_get_implementation(css::uno::XComponentContext * xContext,css::uno::Sequence<css::uno::Any> const &)959 com_sun_star_comp_svx_ExtrusionSurfaceControl_get_implementation(
960     css::uno::XComponentContext* xContext,
961     css::uno::Sequence<css::uno::Any> const &)
962 {
963     return cppu::acquire(new ExtrusionSurfaceControl(xContext));
964 }
965 
966 }
967 
968 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
969