LibreOffice Module svx (master)  1
extrusionbar.cxx
Go to the documentation of this file.
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 
21 #include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
22 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
23 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
24 #include <com/sun/star/drawing/ShadeMode.hpp>
25 #include <com/sun/star/drawing/Position3D.hpp>
26 #include <com/sun/star/drawing/Direction3D.hpp>
27 #include <com/sun/star/drawing/ProjectionMode.hpp>
28 #include <svx/svxids.hrc>
29 #include <svx/svdundo.hxx>
30 #include <sfx2/request.hxx>
31 #include <sfx2/objface.hxx>
32 #include <sfx2/viewsh.hxx>
33 #include <sfx2/bindings.hxx>
34 #include <svx/xsflclit.hxx>
35 #include <svx/dialmgr.hxx>
36 #include <svx/svdoashp.hxx>
37 #include <svx/strings.hrc>
38 #include <svx/svdview.hxx>
39 #include <editeng/colritem.hxx>
40 #include <svx/chrtitem.hxx>
41 #include <svx/sdasitm.hxx>
42 #include <svl/intitem.hxx>
43 #include <rtl/math.hxx>
45 
46 #include <svx/extrusionbar.hxx>
47 #include <extrusiondepthdialog.hxx>
48 
49 using namespace ::svx;
50 using namespace ::cppu;
51 using namespace ::com::sun::star::beans;
52 using namespace ::com::sun::star::drawing;
53 using namespace ::com::sun::star::uno;
54 
55 // Declare the default interface. (The slotmap must not be empty, so
56 // we enter something which never occurs here (hopefully).)
58 {
59  { 0, SfxGroupId::NONE, SfxSlotMode::NONE, 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr, 0, SfxDisableFlags::NONE, nullptr }
60 };
61 
62 SFX_IMPL_INTERFACE(ExtrusionBar, SfxShell)
63 
64 void ExtrusionBar::InitInterface_Impl()
65 {
66  GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Invisible, ToolbarId::Svx_Extrusion_Bar);
67 }
68 
69 
70 ExtrusionBar::ExtrusionBar(SfxViewShell* pViewShell )
71 : SfxShell(pViewShell)
72 {
73  DBG_ASSERT( pViewShell, "svx::ExtrusionBar::ExtrusionBar(), I need a viewshell!" );
74  if( pViewShell )
75  SetPool(&pViewShell->GetPool());
76 
77  SetName(SvxResId(RID_SVX_EXTRUSION_BAR));
78 }
79 
81 {
82  SetRepeatTarget(nullptr);
83 }
84 
85 static void getLightingDirectionDefaults( const Direction3D **pLighting1Defaults, const Direction3D **pLighting2Defaults )
86 {
87 
88  static const Direction3D aLighting1Defaults[9] =
89  {
90  Direction3D( -50000, -50000, 10000 ),
91  Direction3D( 0, -50000, 10000 ),
92  Direction3D( 50000, -50000, 10000 ),
93  Direction3D( -50000, 0, 10000 ),
94  Direction3D( 0, 0, 10000 ),
95  Direction3D( 50000, 0, 10000 ),
96  Direction3D( -50000, 50000, 10000 ),
97  Direction3D( 0, 50000, 10000 ),
98  Direction3D( 50000, 50000, 10000 )
99  };
100 
101  static const Direction3D aLighting2Defaults[9] =
102  {
103  Direction3D( 50000,0, 10000 ),
104  Direction3D( 0, 50000, 10000 ),
105  Direction3D( -50000, 0, 10000 ),
106  Direction3D( 50000, 0, 10000 ),
107  Direction3D( 0, 0, 10000 ),
108  Direction3D( -50000, 0, 10000 ),
109  Direction3D( 50000, 0, 10000 ),
110  Direction3D( 0, -50000, 10000 ),
111  Direction3D( -50000, 0, 10000 )
112  };
113 
114  *pLighting1Defaults = aLighting1Defaults;
115  *pLighting2Defaults = aLighting2Defaults;
116 };
117 
118 static void impl_execute( SfxRequest const & rReq, SdrCustomShapeGeometryItem& rGeometryItem, SdrObject* pObj )
119 {
120  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
121  static constexpr OUStringLiteral sRotateAngle = u"RotateAngle";
122 
123  sal_uInt16 nSID = rReq.GetSlot();
124  switch( nSID )
125  {
126  case SID_EXTRUSION_TOGGLE:
127  {
128  bool bOn(false);
129  css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
130  if ( pAny )
131  {
132  (*pAny) >>= bOn;
133  bOn = !bOn;
134  css::beans::PropertyValue aPropValue;
135  aPropValue.Name = sExtrusion;
136  aPropValue.Value <<= bOn;
137  rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
138  }
139  else
140  {
141  css::beans::PropertyValue aPropValue;
142  aPropValue.Name = sExtrusion;
143  aPropValue.Value <<= true;
144  rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
145  bOn = true;
146  }
147 
148  // draw:extrusion-diffusion has default 0% and c3DDiffuseAmt has default 100%. We set property
149  // "Diffusion" with value 100% here if it does not exist already. This forces, that the
150  // property is written to file in case an extrusion is newly created, and users of old
151  // documents, which usually do not have this property, can force the value to 100% by toggling
152  // the extrusion off and on.
153  if (bOn)
154  {
155  pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"Diffusion");
156  if (!pAny)
157  {
158  css::beans::PropertyValue aPropValue;
159  aPropValue.Name = u"Diffusion";
160  aPropValue.Value <<= 100.0;
161  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
162  }
163  }
164  }
165  break;
166 
167  case SID_EXTRUSION_TILT_DOWN:
168  case SID_EXTRUSION_TILT_UP:
169  case SID_EXTRUSION_TILT_LEFT:
170  case SID_EXTRUSION_TILT_RIGHT:
171  {
172  bool bHorizontal = ( nSID == SID_EXTRUSION_TILT_DOWN ) || ( nSID == SID_EXTRUSION_TILT_UP );
173  sal_Int32 nDiff = ( nSID == SID_EXTRUSION_TILT_LEFT ) || ( nSID == SID_EXTRUSION_TILT_UP ) ? 5 : -5;
174  EnhancedCustomShapeParameterPair aRotateAnglePropPair;
175  double fX = 0.0;
176  double fY = 0.0;
177  aRotateAnglePropPair.First.Value <<= fX;
178  aRotateAnglePropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
179  aRotateAnglePropPair.Second.Value <<= fY;
180  aRotateAnglePropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
181  css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sRotateAngle );
182  if( pAny && ( *pAny >>= aRotateAnglePropPair ) )
183  {
184  aRotateAnglePropPair.First.Value >>= fX;
185  aRotateAnglePropPair.Second.Value >>= fY;
186  }
187  if ( bHorizontal )
188  fX += nDiff;
189  else
190  fY += nDiff;
191  aRotateAnglePropPair.First.Value <<= fX;
192  aRotateAnglePropPair.Second.Value <<= fY;
193  css::beans::PropertyValue aPropValue;
194  aPropValue.Name = sRotateAngle;
195  aPropValue.Value <<= aRotateAnglePropPair;
196  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
197  }
198  break;
199 
200  case SID_EXTRUSION_DIRECTION:
201  {
202  if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_DIRECTION ) == SfxItemState::SET )
203  {
204  sal_Int32 nSkew = rReq.GetArgs()->GetItem<SfxInt32Item>(SID_EXTRUSION_DIRECTION)->GetValue();
205 
206  Position3D aViewPoint( 3472, -3472, 25000 );
207  double fOriginX = 0.50;
208  double fOriginY = -0.50;
209  double fSkewAngle = nSkew;
210  double fSkew = 50.0;
211 
212  switch( nSkew )
213  {
214  case 135:
215  aViewPoint.PositionY = 3472;
216  fOriginY = 0.50;
217  break;
218  case 90:
219  aViewPoint.PositionX = 0;
220  aViewPoint.PositionY = 3472;
221  fOriginX = 0;
222  fOriginY = 0.50;
223  break;
224  case 45:
225  aViewPoint.PositionX = -3472;
226  aViewPoint.PositionY = 3472;
227  fOriginX = -0.50;
228  fOriginY = 0.50;
229  break;
230  case 180:
231  aViewPoint.PositionY = 0;
232  fOriginY = 0;
233  break;
234  case 0:
235  aViewPoint.PositionX = 0;
236  aViewPoint.PositionY = 0;
237  fOriginX = 0;
238  fOriginY = 0;
239  fSkew = 0.0;
240  break;
241  case -360:
242  aViewPoint.PositionX = -3472;
243  aViewPoint.PositionY = 0;
244  fOriginX = -0.50;
245  fOriginY = 0;
246  break;
247  case -90:
248  aViewPoint.PositionX = 0;
249  fOriginX = 0;
250  break;
251  case -45:
252  aViewPoint.PositionX = -3472;
253  fOriginX = -0.50;
254  break;
255  }
256 
257  css::beans::PropertyValue aPropValue;
258 
259  aPropValue.Name = "ViewPoint";
260  aPropValue.Value <<= aViewPoint;
261  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
262 
263 
264  EnhancedCustomShapeParameterPair aOriginPropPair;
265  aOriginPropPair.First.Value <<= fOriginX;
266  aOriginPropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
267  aOriginPropPair.Second.Value <<= fOriginY;
268  aOriginPropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
269  aPropValue.Name = "Origin";
270  aPropValue.Value <<= aOriginPropPair;
271  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
272 
273  EnhancedCustomShapeParameterPair aSkewPropPair;
274  aSkewPropPair.First.Value <<= fSkew;
275  aSkewPropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
276  aSkewPropPair.Second.Value <<= fSkewAngle;
277  aSkewPropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
278  aPropValue.Name = "Skew";
279  aPropValue.Value <<= aSkewPropPair;
280  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
281  }
282  }
283  break;
284  case SID_EXTRUSION_PROJECTION:
285  {
286  if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_PROJECTION ) == SfxItemState::SET )
287  {
288  sal_Int32 nProjection = rReq.GetArgs()->GetItem<SfxInt32Item>(SID_EXTRUSION_PROJECTION)->GetValue();
289  ProjectionMode eProjectionMode = nProjection == 1 ? ProjectionMode_PARALLEL : ProjectionMode_PERSPECTIVE;
290  css::beans::PropertyValue aPropValue;
291  aPropValue.Name = "ProjectionMode";
292  aPropValue.Value <<= eProjectionMode;
293  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
294  }
295  }
296  break;
297  case SID_EXTRUSION_DEPTH:
298  {
299  if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_DEPTH ) == SfxItemState::SET)
300  {
301  double fDepth = rReq.GetArgs()->GetItem<SvxDoubleItem>(SID_EXTRUSION_DEPTH)->GetValue();
302  EnhancedCustomShapeParameterPair aDepthPropPair;
303  aDepthPropPair.First.Value <<= fDepth;
304  aDepthPropPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
305  aDepthPropPair.Second.Value <<= 0.0; // fraction
306  aDepthPropPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
307 
308  css::beans::PropertyValue aPropValue;
309  aPropValue.Name = "Depth";
310  aPropValue.Value <<= aDepthPropPair;
311  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
312  }
313  }
314  break;
315  case SID_EXTRUSION_3D_COLOR:
316  {
317  if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_3D_COLOR ) == SfxItemState::SET)
318  {
319  Color aColor( static_cast<const SvxColorItem&>(rReq.GetArgs()->Get(SID_EXTRUSION_3D_COLOR)).GetValue() );
320 
321  const bool bAuto = aColor == COL_AUTO;
322 
323  css::beans::PropertyValue aPropValue;
324  aPropValue.Name = "Color";
325  aPropValue.Value <<= !bAuto;
326  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
327 
328  if( bAuto )
329  {
331  }
332  else
333  {
334  pObj->SetMergedItem( XSecondaryFillColorItem( "", aColor ) );
335  }
336  pObj->BroadcastObjectChange();
337  }
338  }
339  break;
340  case SID_EXTRUSION_SURFACE:
341  {
342  if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_SURFACE ) == SfxItemState::SET)
343  {
344  sal_Int32 nSurface = rReq.GetArgs()->GetItem<SfxInt32Item>(SID_EXTRUSION_SURFACE)->GetValue();
345 
346  // Set ShadeMode only when changing from or to wireframe, otherwise keep existing value.
347  ShadeMode eOldShadeMode(ShadeMode_FLAT);
348  css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"ShadeMode");
349  if (pAny)
350  *pAny >>= eOldShadeMode;
351  ShadeMode eShadeMode(eOldShadeMode);
352  switch (nSurface)
353  {
354  case 0: // wireframe
355  eShadeMode = ShadeMode_DRAFT;
356  break;
357  case 1: // matte
358  case 2: // plastic
359  case 3: // metal ODF
360  case 4: // metal MS Office
361  if (eOldShadeMode == ShadeMode_DRAFT)
362  eShadeMode = ShadeMode_FLAT; // ODF default
363  break;
364  }
365 
366  // ODF has no dedicated property for 'surface'. MS Office binary format uses attribute
367  // c3DSpecularAmt to distinguish between 'matte' (=0) and 'plastic'.
368  // We do the same.
369  double fOldSpecularity = 0.0;
370  pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"Specularity");
371  if (pAny)
372  *pAny >>= fOldSpecularity;
373  double fSpecularity = fOldSpecularity;
374  switch( nSurface )
375  {
376  case 0: // wireframe
377  break;
378  case 1: // matte
379  fSpecularity = 0.0;
380  break;
381  case 2: // plastic
382  case 3: // metal ODF
383  case 4: // metal MS Office
384  if (basegfx::fTools::equalZero(fOldSpecularity, 0.0001))
385  // MS Office uses 80000/65536. That is currently not allowed in ODF.
386  // But the ODF error will be caught in xmloff.
387  fSpecularity = 80000.0 / 655.36; // interpreted as %
388  break;
389  }
390 
391  // MS Office binary format uses attribute c3DDiffuseAmt with value =43712 (Fixed 16.16) in
392  // addition to the 'metal' flag. For other surface kinds default = 65536 is used.
393  // We toggle between 100 and 43712.0 / 655.36 here, to get better ODF -> MSO binary.
394  // We keep other values, those might be set outside regular UI, e.g by macro.
395  double fOldDiffusion = 100.0;
396  pAny = rGeometryItem.GetPropertyValueByName(sExtrusion, u"Diffusion");
397  if (pAny)
398  *pAny >>= fOldDiffusion;
399  double fDiffusion = fOldDiffusion;
400  if (nSurface == 4)
401  {
402  if (fOldDiffusion == 100.0)
403  fDiffusion = 43712.0 / 655.36; // interpreted as %
404  }
405  else
406  {
407  if (basegfx::fTools::equalZero(fOldDiffusion - 43712.0 / 655.36, 0.0001))
408  fDiffusion = 100.0;
409  }
410 
411  css::beans::PropertyValue aPropValue;
412  aPropValue.Name = "ShadeMode";
413  aPropValue.Value <<= eShadeMode;
414  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
415 
416  aPropValue.Name = "Metal";
417  aPropValue.Value <<= nSurface == 3 || nSurface == 4;
418  rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
419 
420  if (nSurface == 3 || nSurface == 4)
421  {
422  aPropValue.Name = "MetalType";
423  aPropValue.Value <<= nSurface == 4
424  ? EnhancedCustomShapeMetalType::MetalMSCompatible
425  : EnhancedCustomShapeMetalType::MetalODF;
426  rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
427  }
428 
429  if (!basegfx::fTools::equalZero(fOldSpecularity - fSpecularity, 0.0001))
430  {
431  aPropValue.Name = "Specularity";
432  aPropValue.Value <<= fSpecularity;
433  rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
434  }
435 
436  if (!basegfx::fTools::equalZero(fOldDiffusion - fDiffusion, 0.0001))
437  {
438  aPropValue.Name = "Diffusion";
439  aPropValue.Value <<= fDiffusion;
440  rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
441  }
442  }
443  }
444  break;
445  case SID_EXTRUSION_LIGHTING_INTENSITY:
446  {
447  if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_LIGHTING_INTENSITY ) == SfxItemState::SET)
448  {
449  sal_Int32 nLevel = rReq.GetArgs()->GetItem<SfxInt32Item>(SID_EXTRUSION_LIGHTING_INTENSITY)->GetValue();
450 
451  double fBrightness; // c3DAmbientIntensity in MS Office
452  double fLevel1; // c3DKeyIntensity in MS Office
453  double fLevel2; // c3DFillIntensity in MS Office
454 
455  // ToDo: "bright" values are different from MS Office. Should they be kept?
456  switch( nLevel )
457  {
458  case 0: // bright
459  fBrightness = 33.0; // ODF default.
460  fLevel1 = 66.0; // ODF default
461  fLevel2 = 66.0; // ODF default
462  break;
463  case 1: // normal
464  fBrightness = 15.0;
465  fLevel1 = 67.0;
466  fLevel2 = 37.0;
467  break;
468  case 2: // dim
469  fBrightness = 6.0;
470  fLevel1 = 79.0;
471  fLevel2 = 21.0;
472  break;
473  }
474 
475  css::beans::PropertyValue aPropValue;
476  aPropValue.Name = "Brightness";
477  aPropValue.Value <<= fBrightness;
478  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
479 
480  aPropValue.Name = "FirstLightLevel";
481  aPropValue.Value <<= fLevel1;
482  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
483 
484  aPropValue.Name = "SecondLightLevel";
485  aPropValue.Value <<= fLevel2;
486  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
487 
488  // If a user sets light preset 'Dim' in MS Office, MS Office sets second light to harsh.
489  // In other cases it is soft.
490  aPropValue.Name = "SecondLightHarsh";
491  aPropValue.Value <<= nLevel == 2;
492  rGeometryItem.SetPropertyValue(sExtrusion, aPropValue);
493  }
494  }
495  break;
496  case SID_EXTRUSION_LIGHTING_DIRECTION:
497  {
498  if( rReq.GetArgs() && rReq.GetArgs()->GetItemState( SID_EXTRUSION_LIGHTING_DIRECTION ) == SfxItemState::SET)
499  {
500  sal_Int32 nDirection = rReq.GetArgs()->GetItem<SfxInt32Item>(SID_EXTRUSION_LIGHTING_DIRECTION)->GetValue();
501 
502  if((nDirection >= 0) && (nDirection < 9))
503  {
504  const Direction3D * pLighting1Defaults;
505  const Direction3D * pLighting2Defaults;
506 
507  getLightingDirectionDefaults( &pLighting1Defaults, &pLighting2Defaults );
508 
509  css::beans::PropertyValue aPropValue;
510  aPropValue.Name = "FirstLightDirection";
511  aPropValue.Value <<= pLighting1Defaults[nDirection];
512  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
513 
514  aPropValue.Name = "SecondLightDirection";
515  aPropValue.Value <<= pLighting2Defaults[nDirection];
516  rGeometryItem.SetPropertyValue( sExtrusion, aPropValue );
517  }
518  }
519  }
520  break;
521 
522  }
523 }
524 
525 void ExtrusionBar::execute( SdrView* pSdrView, SfxRequest const & rReq, SfxBindings& rBindings )
526 {
527  sal_uInt16 nSID = rReq.GetSlot();
528  TranslateId pStrResId;
529 
530  const bool bUndo = pSdrView && pSdrView->IsUndoEnabled();
531 
532  switch( nSID )
533  {
534  case SID_EXTRUSION_TOGGLE:
535  {
536  if ( !pStrResId )
537  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ON_OFF;
538  [[fallthrough]];
539  }
540  case SID_EXTRUSION_TILT_DOWN:
541  {
542  if ( !pStrResId )
543  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_DOWN;
544  [[fallthrough]];
545  }
546  case SID_EXTRUSION_TILT_UP:
547  {
548  if ( !pStrResId )
549  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_UP;
550  [[fallthrough]];
551  }
552  case SID_EXTRUSION_TILT_LEFT:
553  {
554  if ( !pStrResId )
555  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_LEFT;
556  [[fallthrough]];
557  }
558  case SID_EXTRUSION_TILT_RIGHT:
559  {
560  if ( !pStrResId )
561  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ROTATE_RIGHT;
562  [[fallthrough]];
563  }
564  case SID_EXTRUSION_DIRECTION:
565  {
566  if ( !pStrResId )
567  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_ORIENTATION;
568  [[fallthrough]];
569  }
570  case SID_EXTRUSION_PROJECTION:
571  {
572  if ( !pStrResId )
573  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_PROJECTION;
574  [[fallthrough]];
575  }
576  case SID_EXTRUSION_DEPTH:
577  {
578  if ( !pStrResId )
579  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_DEPTH;
580  [[fallthrough]];
581  }
582  case SID_EXTRUSION_3D_COLOR:
583  {
584  if ( !pStrResId )
585  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_COLOR;
586  [[fallthrough]];
587  }
588  case SID_EXTRUSION_SURFACE:
589  {
590  if ( !pStrResId )
591  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_SURFACE;
592  [[fallthrough]];
593  }
594  case SID_EXTRUSION_LIGHTING_INTENSITY:
595  {
596  if ( !pStrResId )
597  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_BRIGHTNESS;
598  [[fallthrough]];
599  }
600  case SID_EXTRUSION_LIGHTING_DIRECTION:
601  {
602  if ( !pStrResId )
603  pStrResId = RID_SVXSTR_UNDO_APPLY_EXTRUSION_LIGHTING;
604 
605  if (pSdrView)
606  {
607  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
608  const size_t nCount = rMarkList.GetMarkCount();
609 
610  for(size_t i=0; i<nCount; ++i)
611  {
612  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
613  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
614  {
615  if( bUndo )
616  {
617  OUString aStr( SvxResId( pStrResId ) );
618  pSdrView->BegUndo( aStr );
619  pSdrView->AddUndo( pSdrView->GetModel()->GetSdrUndoFactory().CreateUndoAttrObject( *pObj ) );
620  }
622  impl_execute( rReq, aGeometryItem, pObj );
623  pObj->SetMergedItem( aGeometryItem );
624  pObj->BroadcastObjectChange();
625  if( bUndo )
626  pSdrView->EndUndo();
627 
628  // simulate a context change:
629  // force SelectionHasChanged() being called
630  // so that extrusion bar will be visible/hidden
631  pSdrView->MarkListHasChanged();
632  }
633  }
634  }
635  }
636  break;
637 
638  case SID_EXTRUSION_DEPTH_DIALOG:
639  if( rReq.GetArgs() &&
640  (rReq.GetArgs()->GetItemState( SID_EXTRUSION_DEPTH ) == SfxItemState::SET) &&
641  (rReq.GetArgs()->GetItemState( SID_ATTR_METRIC ) == SfxItemState::SET))
642  {
643  double fDepth = rReq.GetArgs()->GetItem<SvxDoubleItem>(SID_EXTRUSION_DEPTH)->GetValue();
644  FieldUnit eUnit = static_cast<FieldUnit>(rReq.GetArgs()->GetItem<SfxUInt16Item>(SID_ATTR_METRIC)->GetValue());
645 
646  ExtrusionDepthDialog aDlg(rReq.GetFrameWeld(), fDepth, eUnit);
647  sal_uInt16 nRet = aDlg.run();
648  if (nRet == RET_OK)
649  {
650  fDepth = aDlg.getDepth();
651 
652  SvxDoubleItem aItem( fDepth, SID_EXTRUSION_DEPTH );
653  SfxPoolItem* aItems[] = { &aItem, nullptr };
654  rBindings.Execute( SID_EXTRUSION_DEPTH, const_cast<const SfxPoolItem**>(aItems) );
655  }
656  }
657  break;
658  }
659 
660  if( nSID != SID_EXTRUSION_TOGGLE )
661  return;
662 
663  static const sal_uInt16 SidArray[] = {
664  SID_EXTRUSION_TILT_DOWN,
665  SID_EXTRUSION_TILT_UP,
666  SID_EXTRUSION_TILT_LEFT,
667  SID_EXTRUSION_TILT_RIGHT,
668  SID_EXTRUSION_DEPTH_FLOATER,
669  SID_EXTRUSION_DIRECTION_FLOATER,
670  SID_EXTRUSION_LIGHTING_FLOATER,
671  SID_EXTRUSION_SURFACE_FLOATER,
672  SID_EXTRUSION_3D_COLOR,
673  SID_EXTRUSION_DEPTH,
674  SID_EXTRUSION_DIRECTION,
675  SID_EXTRUSION_PROJECTION,
676  SID_EXTRUSION_LIGHTING_DIRECTION,
677  SID_EXTRUSION_LIGHTING_INTENSITY,
678  SID_EXTRUSION_SURFACE,
679  0 };
680 
681  rBindings.Invalidate( SidArray );
682 }
683 
684 static void getExtrusionDirectionState( SdrView const * pSdrView, SfxItemSet& rSet )
685 {
686  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
687  const size_t nCount = rMarkList.GetMarkCount();
688 
689  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
690 
691  const css::uno::Any* pAny;
692 
693  double fFinalSkewAngle = -1;
694  bool bHasCustomShape = false;
695 
696  for(size_t i=0; i<nCount; ++i)
697  {
698  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
699  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
700  {
702 
703  // see if this is an extruded customshape
704  if( !bHasCustomShape )
705  {
706  const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
707  if( pAny_ )
708  *pAny_ >>= bHasCustomShape;
709 
710  if( !bHasCustomShape )
711  continue;
712  }
713 
714  bool bParallel = true;
715  Position3D aViewPoint( 3472, -3472, 25000 ); // MSO default
716  double fSkewAngle = -135; // MSO default
717 
718  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "ProjectionMode" );
719  sal_Int16 nProjectionMode = sal_Int16();
720  if( pAny && ( *pAny >>= nProjectionMode ) )
721  bParallel = static_cast<ProjectionMode>(nProjectionMode) == ProjectionMode_PARALLEL;
722 
723  if( bParallel )
724  {
725  double fSkew = 50.0;
726  EnhancedCustomShapeParameterPair aSkewPropPair;
727  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "Skew" );
728  if( pAny && ( *pAny >>= aSkewPropPair ) )
729  {
730  aSkewPropPair.First.Value >>= fSkew;
731  aSkewPropPair.Second.Value >>= fSkewAngle;
732  }
733  if ( fSkew == 0.0 )
734  fSkewAngle = 0.0;
735  else if ( fSkewAngle == 0.0 )
736  fSkewAngle = -360.0;
737  }
738  else
739  {
740  double fOriginX = 0.50;
741  double fOriginY = -0.50;
742  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "ViewPoint" );
743  if( pAny )
744  *pAny >>= aViewPoint;
745 
746  EnhancedCustomShapeParameterPair aOriginPropPair;
747  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "Origin" );
748  if( pAny && ( *pAny >>= aOriginPropPair ) )
749  {
750  aOriginPropPair.First.Value >>= fOriginX;
751  aOriginPropPair.Second.Value >>= fOriginY;
752  }
753  fSkewAngle = -1;
754  const double e = 0.0001;
755  if( aViewPoint.PositionX > e )
756  {
757  if( aViewPoint.PositionY > e )
758  {
759  if( (fOriginX > e ) && ( fOriginY > e ) )
760  fSkewAngle = 135.0;
761  }
762  else if( aViewPoint.PositionY < -e )
763  {
764  if( ( fOriginX > e ) && ( fOriginY < -e ) )
765  fSkewAngle = -135.0;
766  }
767  else
768  {
769  if( ( fOriginX > e ) && ( fOriginY > -e ) && ( fOriginY < e ) )
770  fSkewAngle = 180.0;
771  }
772  }
773  else if( aViewPoint.PositionX < -e )
774  {
775  if( aViewPoint.PositionY < -e )
776  {
777  if( ( fOriginX < -e ) && ( fOriginY < -e ) )
778  fSkewAngle = -45.0;
779  }
780  else if( aViewPoint.PositionY > e )
781  {
782  if( ( fOriginX < -e ) && ( fOriginY > e ) )
783  fSkewAngle = 45.0;
784  }
785  else
786  {
787  if( ( fOriginX < e ) && ( fOriginY > -e ) && ( fOriginY < e ) )
788  fSkewAngle = -360.0;
789  }
790  }
791  else
792  {
793  if( aViewPoint.PositionY < -e )
794  {
795  if( ( fOriginX > -e ) && ( fOriginX < e ) && ( fOriginY < -e ) )
796  fSkewAngle = -90.0;
797  }
798  else if( aViewPoint.PositionY > e )
799  {
800  if( ( fOriginX > -e ) && ( fOriginX < e ) && ( fOriginY > e ) )
801  fSkewAngle = 90.0;
802  }
803  else
804  {
805  if( ( fOriginX > -e ) && ( fOriginX < e ) && ( fOriginY > -e ) && ( fOriginY < e ) )
806  fSkewAngle = 0.0;
807  }
808  }
809  }
810 
811  if( rtl::math::approxEqual(fFinalSkewAngle, -1.0) )
812  {
813  fFinalSkewAngle = fSkewAngle;
814  }
815  else if( !rtl::math::approxEqual(fSkewAngle, fFinalSkewAngle) )
816  {
817  fFinalSkewAngle = -1.0;
818  }
819 
820  if( rtl::math::approxEqual(fFinalSkewAngle, -1.0) )
821  break;
822  }
823  }
824 
825  if( bHasCustomShape )
826  rSet.Put( SfxInt32Item( SID_EXTRUSION_DIRECTION, static_cast<sal_Int32>(fFinalSkewAngle) ) );
827  else
828  rSet.DisableItem( SID_EXTRUSION_DIRECTION );
829 }
830 
831 static void getExtrusionProjectionState( SdrView const * pSdrView, SfxItemSet& rSet )
832 {
833  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
834  const size_t nCount = rMarkList.GetMarkCount();
835 
836  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
837 
838  const css::uno::Any* pAny;
839 
840  sal_Int32 nFinalProjection = -1;
841  bool bHasCustomShape = false;
842 
843  for(size_t i=0; i<nCount; ++i)
844  {
845  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
846  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
847  {
848  // see if this is an extruded customshape
849  if( !bHasCustomShape )
850  {
852  const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
853  if( pAny_ )
854  *pAny_ >>= bHasCustomShape;
855 
856  if( !bHasCustomShape )
857  continue;
858  }
859 
861 
862  bool bParallel = true;
863  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "ProjectionMode" );
864  ProjectionMode eProjectionMode;
865  if( pAny && ( *pAny >>= eProjectionMode ) )
866  bParallel = eProjectionMode == ProjectionMode_PARALLEL;
867 
868  if( nFinalProjection == -1 )
869  {
870  nFinalProjection = bParallel ? 1 : 0;
871  }
872  else if( nFinalProjection != (bParallel ? 1 : 0) )
873  {
874  nFinalProjection = -1;
875  break;
876  }
877  }
878  }
879 
880  if( bHasCustomShape )
881  rSet.Put( SfxInt32Item( SID_EXTRUSION_PROJECTION, nFinalProjection ) );
882  else
883  rSet.DisableItem( SID_EXTRUSION_PROJECTION );
884 }
885 
886 static void getExtrusionSurfaceState( SdrView const * pSdrView, SfxItemSet& rSet )
887 {
888  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
889  const size_t nCount = rMarkList.GetMarkCount();
890 
891  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
892 
893  const css::uno::Any* pAny;
894 
895  sal_Int32 nFinalSurface = -1;
896  bool bHasCustomShape = false;
897 
898  for(size_t i=0; i<nCount; ++i)
899  {
900  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
901  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
902  {
904 
905  // see if this is an extruded customshape
906  if( !bHasCustomShape )
907  {
908  const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
909  if( pAny_ )
910  *pAny_ >>= bHasCustomShape;
911 
912  if( !bHasCustomShape )
913  continue;
914  }
915 
916  sal_Int32 nSurface = 0; // wire frame
917 
918  ShadeMode eShadeMode( ShadeMode_FLAT );
919  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"ShadeMode" );
920  if( pAny )
921  *pAny >>= eShadeMode;
922 
923  if (eShadeMode != ShadeMode_DRAFT)
924  {
925  bool bMetal = false;
926  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Metal" );
927  if( pAny )
928  *pAny >>= bMetal;
929 
930  if( bMetal )
931  {
932  nSurface = 3; // metal ODF
933  sal_Int16 eMetalType = EnhancedCustomShapeMetalType::MetalODF;
934  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"MetalType" );
935  if (pAny)
936  {
937  *pAny >>= eMetalType;
938  if (eMetalType == EnhancedCustomShapeMetalType::MetalMSCompatible)
939  nSurface = 4; // metal MS Office
940  }
941  }
942  else
943  {
944  double fSpecularity = 0;
945  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, u"Specularity" );
946  if( pAny )
947  *pAny >>= fSpecularity;
948 
949  const double e = 0.0001;
950  if( (fSpecularity > -e) && (fSpecularity < e) )
951  {
952  nSurface = 1; // matte
953  }
954  else
955  {
956  nSurface = 2; // plastic
957  }
958  }
959  }
960 
961  if( nFinalSurface == -1 )
962  {
963  nFinalSurface = nSurface;
964  }
965  else if( nFinalSurface != nSurface )
966  {
967  nFinalSurface = -1;
968  break;
969  }
970  }
971  }
972 
973  if( bHasCustomShape )
974  rSet.Put( SfxInt32Item( SID_EXTRUSION_SURFACE, nFinalSurface ) );
975  else
976  rSet.DisableItem( SID_EXTRUSION_SURFACE );
977 }
978 
979 static void getExtrusionDepthState( SdrView const * pSdrView, SfxItemSet& rSet )
980 {
981  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
982  const size_t nCount = rMarkList.GetMarkCount();
983 
984  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
985 
986  const css::uno::Any* pAny;
987 
988  double fFinalDepth = -1;
989  bool bHasCustomShape = false;
990 
991  for(size_t i=0; i<nCount; ++i)
992  {
993  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
994  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
995  {
997 
998  // see if this is an extruded customshape
999  if( !bHasCustomShape )
1000  {
1001  const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
1002  if( pAny_ )
1003  *pAny_ >>= bHasCustomShape;
1004 
1005  if( !bHasCustomShape )
1006  continue;
1007  }
1008 
1009  double fDepth = 1270.0; // =36pt ODF default
1010  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "Depth" );
1011  if( pAny )
1012  {
1013  EnhancedCustomShapeParameterPair aDepthPropPair;
1014  if ( *pAny >>= aDepthPropPair )
1015  aDepthPropPair.First.Value >>= fDepth;
1016  }
1017 
1018  if( fFinalDepth == -1 )
1019  {
1020  fFinalDepth = fDepth;
1021  }
1022  else if( !rtl::math::approxEqual(fFinalDepth, fDepth) )
1023  {
1024  fFinalDepth = -1;
1025  break;
1026  }
1027  }
1028  }
1029 
1030  if( pSdrView->GetModel() )
1031  {
1032  FieldUnit eUnit = pSdrView->GetModel()->GetUIUnit();
1033  rSet.Put( SfxUInt16Item( SID_ATTR_METRIC, static_cast<sal_uInt16>(eUnit) ) );
1034  }
1035 
1036  if( bHasCustomShape )
1037  rSet.Put( SvxDoubleItem( fFinalDepth, SID_EXTRUSION_DEPTH ) );
1038  else
1039  rSet.DisableItem( SID_EXTRUSION_DEPTH );
1040 }
1041 
1042 static bool compare_direction( const Direction3D& d1, const Direction3D& d2 )
1043 {
1044  if( ((d1.DirectionX < 0) && (d2.DirectionX < 0)) || ((d1.DirectionX == 0) && (d2.DirectionX == 0)) || ((d1.DirectionX > 0) && (d2.DirectionX > 0)) )
1045  {
1046  if( ((d1.DirectionY < 0) && (d2.DirectionY < 0)) || ((d1.DirectionY == 0) && (d2.DirectionY == 0)) || ((d1.DirectionY > 0) && (d2.DirectionY > 0)) )
1047  {
1048  if( ((d1.DirectionZ < 0) && (d2.DirectionZ < 0)) || ((d1.DirectionZ == 0) && (d2.DirectionZ == 0)) || ((d1.DirectionZ > 0) && (d2.DirectionZ > 0)) )
1049  {
1050  return true;
1051  }
1052  }
1053  }
1054 
1055  return false;
1056 }
1057 
1058 static void getExtrusionLightingDirectionState( SdrView const * pSdrView, SfxItemSet& rSet )
1059 {
1060  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
1061  const size_t nCount = rMarkList.GetMarkCount();
1062 
1063  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
1064 
1065  const Direction3D * pLighting1Defaults;
1066  const Direction3D * pLighting2Defaults;
1067 
1068  getLightingDirectionDefaults( &pLighting1Defaults, &pLighting2Defaults );
1069 
1070  const css::uno::Any* pAny;
1071 
1072  int nFinalDirection = -1;
1073  bool bHasCustomShape = false;
1074 
1075  for(size_t i=0; i<nCount; ++i)
1076  {
1077  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1078  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
1079  {
1080  const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1081 
1082  // see if this is an extruded customshape
1083  if( !bHasCustomShape )
1084  {
1085  const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
1086  if( pAny_ )
1087  *pAny_ >>= bHasCustomShape;
1088 
1089  if( !bHasCustomShape )
1090  continue;
1091  }
1092 
1093  Direction3D aFirstLightDirection( 50000, 0, 10000 );
1094  Direction3D aSecondLightDirection( -50000, 0, 10000 );
1095 
1096  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "FirstLightDirection" );
1097  if( pAny )
1098  *pAny >>= aFirstLightDirection;
1099 
1100  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "SecondLightDirection" );
1101  if( pAny )
1102  *pAny >>= aSecondLightDirection;
1103 
1104  int nDirection = -1;
1105 
1106  int j;
1107  for( j = 0; j < 9; j++ )
1108  {
1109  if( compare_direction( aFirstLightDirection, pLighting1Defaults[j] ) &&
1110  compare_direction( aSecondLightDirection, pLighting2Defaults[j] ))
1111  {
1112  nDirection = j;
1113  break;
1114  }
1115  }
1116 
1117  if( nFinalDirection == -1 )
1118  {
1119  nFinalDirection = nDirection;
1120  }
1121  else if( nDirection != nFinalDirection )
1122  {
1123  nFinalDirection = -1;
1124  }
1125 
1126  if( nFinalDirection == -1 )
1127  break;
1128  }
1129  }
1130 
1131  if( bHasCustomShape )
1132  rSet.Put( SfxInt32Item( SID_EXTRUSION_LIGHTING_DIRECTION, static_cast<sal_Int32>(nFinalDirection) ) );
1133  else
1134  rSet.DisableItem( SID_EXTRUSION_LIGHTING_DIRECTION );
1135 }
1136 
1137 static void getExtrusionLightingIntensityState( SdrView const * pSdrView, SfxItemSet& rSet )
1138 {
1139  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
1140  const size_t nCount = rMarkList.GetMarkCount();
1141 
1142  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
1143 
1144  const css::uno::Any* pAny;
1145 
1146  int nFinalLevel = -1;
1147  bool bHasCustomShape = false;
1148 
1149  for(size_t i=0; i<nCount; ++i)
1150  {
1151  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1152  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
1153  {
1154  const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1155 
1156  // see if this is an extruded customshape
1157  if( !bHasCustomShape )
1158  {
1159  const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
1160  if( pAny_ )
1161  *pAny_ >>= bHasCustomShape;
1162 
1163  if( !bHasCustomShape )
1164  continue;
1165  }
1166 
1167  double fBrightness = 22178.0 / 655.36;
1168  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "Brightness" );
1169  if( pAny )
1170  *pAny >>= fBrightness;
1171 
1172  int nLevel;
1173  if( fBrightness >= 30.0 )
1174  {
1175  nLevel = 0; // Bright
1176  }
1177  else if( fBrightness >= 10.0 )
1178  {
1179  nLevel = 1; // Normal;
1180  }
1181  else
1182  {
1183  nLevel = 2; // Dim
1184  }
1185 
1186  if( nFinalLevel == -1 )
1187  {
1188  nFinalLevel = nLevel;
1189  }
1190  else if( nFinalLevel != nLevel )
1191  {
1192  nFinalLevel = -1;
1193  break;
1194  }
1195  }
1196  }
1197 
1198  if( bHasCustomShape )
1199  rSet.Put( SfxInt32Item( SID_EXTRUSION_LIGHTING_INTENSITY, nFinalLevel ) );
1200  else
1201  rSet.DisableItem( SID_EXTRUSION_LIGHTING_INTENSITY );
1202 }
1203 
1204 static void getExtrusionColorState( SdrView const * pSdrView, SfxItemSet& rSet )
1205 {
1206  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
1207  const size_t nCount = rMarkList.GetMarkCount();
1208 
1209  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
1210 
1211  const css::uno::Any* pAny;
1212 
1213  bool bInit = false;
1214  bool bAmbigius = false;
1215  Color aFinalColor;
1216  bool bHasCustomShape = false;
1217 
1218  for(size_t i=0; i<nCount; ++i)
1219  {
1220  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1221  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
1222  {
1223  const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1224 
1225  // see if this is an extruded customshape
1226  if( !bHasCustomShape )
1227  {
1228  const Any* pAny_ = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
1229  if( pAny_ )
1230  *pAny_ >>= bHasCustomShape;
1231 
1232  if( !bHasCustomShape )
1233  continue;
1234  }
1235 
1236  Color aColor;
1237 
1238  bool bUseColor = false;
1239  pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, "Color" );
1240  if( pAny )
1241  *pAny >>= bUseColor;
1242 
1243  if( bUseColor )
1244  {
1246  aColor = rItem.GetColorValue();
1247  }
1248  else
1249  {
1250  aColor = COL_AUTO;
1251  }
1252 
1253  if( !bInit )
1254  {
1255  aFinalColor = aColor;
1256  bInit = true;
1257  }
1258  else if( aFinalColor != aColor )
1259  {
1260  bAmbigius = true;
1261  break;
1262  }
1263  }
1264  }
1265 
1266  if( bAmbigius )
1267  aFinalColor = COL_AUTO;
1268 
1269  if( bHasCustomShape )
1270  rSet.Put( SvxColorItem( aFinalColor, SID_EXTRUSION_3D_COLOR ) );
1271  else
1272  rSet.DisableItem( SID_EXTRUSION_3D_COLOR );
1273 }
1274 
1275 namespace svx {
1276 bool checkForSelectedCustomShapes( SdrView const * pSdrView, bool bOnlyExtruded )
1277 {
1278  static constexpr OUStringLiteral sExtrusion = u"Extrusion";
1279 
1280  const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
1281  const size_t nCount = rMarkList.GetMarkCount();
1282  bool bFound = false;
1283 
1284  for(size_t i=0;(i<nCount) && !bFound ; ++i)
1285  {
1286  SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
1287  if( dynamic_cast<const SdrObjCustomShape*>( pObj) != nullptr )
1288  {
1289  if( bOnlyExtruded )
1290  {
1291  const SdrCustomShapeGeometryItem & rGeometryItem( pObj->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
1292  const Any* pAny = rGeometryItem.GetPropertyValueByName( sExtrusion, sExtrusion );
1293  if( pAny )
1294  *pAny >>= bFound;
1295  }
1296  else
1297  {
1298  bFound = true;
1299  }
1300  }
1301  }
1302 
1303  return bFound;
1304 }
1305 }
1306 
1307 void ExtrusionBar::getState( SdrView const * pSdrView, SfxItemSet& rSet )
1308 {
1309  getExtrusionDirectionState( pSdrView, rSet );
1310  getExtrusionProjectionState( pSdrView, rSet );
1311 
1312  const bool bOnlyExtrudedCustomShapes(checkForSelectedCustomShapes( pSdrView, true ));
1313 
1314  if (! bOnlyExtrudedCustomShapes)
1315  {
1316  rSet.DisableItem( SID_EXTRUSION_TILT_DOWN );
1317  rSet.DisableItem( SID_EXTRUSION_TILT_DOWN );
1318  rSet.DisableItem( SID_EXTRUSION_TILT_UP );
1319  rSet.DisableItem( SID_EXTRUSION_TILT_LEFT );
1320  rSet.DisableItem( SID_EXTRUSION_TILT_RIGHT );
1321  rSet.DisableItem( SID_EXTRUSION_3D_COLOR );
1322  rSet.DisableItem( SID_EXTRUSION_DEPTH_FLOATER );
1323  rSet.DisableItem( SID_EXTRUSION_DIRECTION_FLOATER );
1324  rSet.DisableItem( SID_EXTRUSION_LIGHTING_FLOATER );
1325  rSet.DisableItem( SID_EXTRUSION_SURFACE_FLOATER );
1326  }
1327 
1328  if( !checkForSelectedCustomShapes( pSdrView, false ) )
1329  rSet.DisableItem( SID_EXTRUSION_TOGGLE );
1330 
1331  getExtrusionDepthState( pSdrView, rSet );
1332  getExtrusionSurfaceState( pSdrView, rSet );
1333  getExtrusionLightingIntensityState( pSdrView, rSet );
1334  getExtrusionLightingDirectionState( pSdrView, rSet );
1335  getExtrusionColorState( pSdrView, rSet );
1336 }
1337 
1338 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static void getExtrusionSurfaceState(SdrView const *pSdrView, SfxItemSet &rSet)
void SetPropertyValue(const css::beans::PropertyValue &rPropVal)
FieldUnit
size_t GetMarkCount() const
Definition: svdmark.hxx:178
#define SFX_IMPL_INTERFACE(Class, SuperClass)
virtual ~ExtrusionBar() override
std::string GetValue
bool equalZero(const T &rfVal)
bool IsUndoEnabled() const
Definition: svdedtv.cxx:1073
constexpr::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
static void getExtrusionProjectionState(SdrView const *pSdrView, SfxItemSet &rSet)
void BegUndo()
Definition: svdedtv.hxx:178
SdrMark * GetMark(size_t nNum) const
Definition: svdmark.cxx:230
static SfxSlot aExtrusionBarSlots_Impl[]
const SfxItemSet * GetArgs() const
void Invalidate(sal_uInt16 nId)
const sal_uInt16 SidArray[]
virtual void MarkListHasChanged() override
Definition: svdedxv.cxx:2514
static void execute(SdrView *pSdrView, SfxRequest const &rReq, SfxBindings &rBindings)
void ClearMergedItem(const sal_uInt16 nWhich=0)
Definition: svdobj.cxx:1987
static void getLightingDirectionDefaults(const Direction3D **pLighting1Defaults, const Direction3D **pLighting2Defaults)
static void getState(SdrView const *pSdrView, SfxItemSet &rSet)
static bool compare_direction(const Direction3D &d1, const Direction3D &d2)
int nCount
OUString SvxResId(TranslateId aId)
Definition: dialmgr.cxx:24
static void getExtrusionColorState(SdrView const *pSdrView, SfxItemSet &rSet)
bool checkForSelectedCustomShapes(SdrView const *pSdrView, bool bOnlyExtruded)
bool Execute(sal_uInt16 nSlot, const SfxPoolItem **pArgs=nullptr, SfxCallMode nCall=SfxCallMode::SLOT)
const Color & GetColorValue() const
Definition: xattr.cxx:300
void EndUndo()
Definition: svdedtv.cxx:303
FieldUnit GetUIUnit() const
Definition: svdmodel.hxx:383
SfxItemPool & GetPool() const
SdrObject * GetMarkedSdrObj() const
Definition: svdmark.hxx:68
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: svdedtv.hxx:182
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
#define DBG_ASSERT(sCon, aError)
void SetRepeatTarget(SfxRepeatTarget *pTarget)
constexpr TypedWhichId< SdrCustomShapeGeometryItem > SDRATTR_CUSTOMSHAPE_GEOMETRY(SDRATTR_CUSTOMSHAPE_FIRST+2)
int i
static void getExtrusionDepthState(SdrView const *pSdrView, SfxItemSet &rSet)
static void getExtrusionDirectionState(SdrView const *pSdrView, SfxItemSet &rSet)
constexpr TypedWhichId< XSecondaryFillColorItem > XATTR_SECONDARYFILLCOLOR(XATTR_FILL_FIRST+12)
void BroadcastObjectChange() const
Definition: svdobj.cxx:1001
const SdrMarkList & GetMarkedObjectList() const
Definition: svdmrkv.hxx:258
void SetPool(SfxItemPool *pNewPool)
float u
void SetMergedItem(const SfxPoolItem &rItem)
Definition: svdobj.cxx:1982
static bool bInit
Definition: objfac3d.cxx:30
void SetName(const OUString &rName)
const SfxPoolItem & GetMergedItem(const sal_uInt16 nWhich) const
Definition: svdobj.cxx:2007
static void impl_execute(SfxRequest const &rReq, SdrCustomShapeGeometryItem &rGeometryItem, SdrObject *pObj)
Abstract DrawObject.
Definition: svdobj.hxx:259
SdrUndoFactory & GetSdrUndoFactory() const
returns the models undo factory.
Definition: svdmodel.cxx:1856
#define SFX_OBJECTBAR_OBJECT
static void getExtrusionLightingIntensityState(SdrView const *pSdrView, SfxItemSet &rSet)
weld::Window * GetFrameWeld() const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_uInt16 GetSlot() const
void DisableItem(sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
static void getExtrusionLightingDirectionState(SdrView const *pSdrView, SfxItemSet &rSet)
RET_OK
virtual short run()
css::uno::Any * GetPropertyValueByName(const OUString &rPropName)
virtual std::unique_ptr< SdrUndoAction > CreateUndoAttrObject(SdrObject &rObject, bool bStyleSheet1=false, bool bSaveText=false)
Definition: svdundo.cxx:1732
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
SdrModel * GetModel() const
Definition: svdpntv.hxx:260
aStr