1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svdundo.hxx>
21 #include <sfx2/request.hxx>
22 #include <sfx2/objface.hxx>
23 #include <sfx2/viewsh.hxx>
24 #include <svx/unoapi.hxx>
25 #include <com/sun/star/drawing/XShape.hpp>
26 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
27 #include <sal/log.hxx>
28 #include <svx/dialmgr.hxx>
29 #include <svx/svdoashp.hxx>
30 #include <svx/strings.hrc>
31 #include <svx/svdpage.hxx>
32 #include <svx/svdview.hxx>
33 #include <svx/sdasitm.hxx>
34 #include <svx/gallery.hxx>
35 #include <svx/fmmodel.hxx>
36 #include <svx/sdtfsitm.hxx>
37 #include <svl/itempool.hxx>
38 #include <svl/stritem.hxx>
39 #include <sfx2/bindings.hxx>
40 #include <editeng/eeitem.hxx>
41 #include <editeng/charscaleitem.hxx>
42 #include <editeng/kernitem.hxx>
44 #include <svx/svxids.hrc>
45 #include <svx/fontworkbar.hxx>
46 #include <svx/fontworkgallery.hxx>
49 using namespace ::svx
;
50 using namespace ::com::sun::star
;
51 using namespace ::com::sun::star::beans
;
52 using namespace ::com::sun::star::uno
;
54 static void SetAlignmentState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
56 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
57 const size_t nCount
= rMarkList
.GetMarkCount();
59 sal_Int32 nAlignment
= -1;
60 for( size_t i
= 0; i
< nCount
; ++i
)
62 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
63 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
65 sal_Int32 nOldAlignment
= nAlignment
;
66 const SdrTextHorzAdjustItem
& rTextHorzAdjustItem
= pObj
->GetMergedItem( SDRATTR_TEXT_HORZADJUST
);
67 const SdrTextFitToSizeTypeItem
& rTextFitToSizeTypeItem
= pObj
->GetMergedItem( SDRATTR_TEXT_FITTOSIZE
);
68 switch ( rTextHorzAdjustItem
.GetValue() )
70 case SDRTEXTHORZADJUST_LEFT
: nAlignment
= 0; break;
71 case SDRTEXTHORZADJUST_CENTER
: nAlignment
= 1; break;
72 case SDRTEXTHORZADJUST_RIGHT
: nAlignment
= 2; break;
73 case SDRTEXTHORZADJUST_BLOCK
:
75 auto const fit(rTextFitToSizeTypeItem
.GetValue());
76 if (fit
== drawing::TextFitToSizeType_NONE
)
80 else if (fit
== drawing::TextFitToSizeType_ALLLINES
||
81 fit
== drawing::TextFitToSizeType_PROPORTIONAL
)
87 if ( ( nOldAlignment
!= -1 ) && ( nOldAlignment
!= nAlignment
) )
94 rSet
.Put( SfxInt32Item( SID_FONTWORK_ALIGNMENT
, nAlignment
) );
97 static void SetCharacterSpacingState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
99 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
100 const size_t nCount
= rMarkList
.GetMarkCount();
102 sal_Int32 nCharacterSpacing
= -1;
103 for( size_t i
= 0; i
< nCount
; ++i
)
105 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
106 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
108 sal_Int32 nOldCharacterSpacing
= nCharacterSpacing
;
109 const SvxCharScaleWidthItem
& rCharScaleWidthItem
= pObj
->GetMergedItem( EE_CHAR_FONTWIDTH
);
110 nCharacterSpacing
= rCharScaleWidthItem
.GetValue();
111 if ( ( nOldCharacterSpacing
!= -1 ) && ( nOldCharacterSpacing
!= nCharacterSpacing
) )
113 nCharacterSpacing
= -1;
118 rSet
.Put( SfxInt32Item( SID_FONTWORK_CHARACTER_SPACING
, nCharacterSpacing
) );
122 static void SetKernCharacterPairsState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
124 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
125 const size_t nCount
= rMarkList
.GetMarkCount();
127 bool bChecked
= false;
128 for( size_t i
= 0; i
< nCount
; ++i
)
130 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
131 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
133 const SvxKerningItem
& rKerningItem
= pObj
->GetMergedItem( EE_CHAR_KERNING
);
134 if ( rKerningItem
.GetValue() )
138 rSet
.Put( SfxBoolItem( SID_FONTWORK_KERN_CHARACTER_PAIRS
, bChecked
) );
141 static void SetFontWorkShapeTypeState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
143 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
144 const size_t nCount
= rMarkList
.GetMarkCount();
146 OUString aFontWorkShapeType
;
148 for( size_t i
= 0; i
< nCount
; ++i
)
150 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
151 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
153 const SdrCustomShapeGeometryItem
& rGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
154 const Any
* pAny
= rGeometryItem
.GetPropertyValueByName( u
"Type"_ustr
);
158 if ( *pAny
>>= aType
)
160 if ( !aFontWorkShapeType
.isEmpty() )
162 if ( aFontWorkShapeType
!= aType
) // different FontWorkShapeTypes selected ?
164 aFontWorkShapeType
.clear();
168 aFontWorkShapeType
= aType
;
173 rSet
.Put( SfxStringItem( SID_FONTWORK_SHAPE_TYPE
, aFontWorkShapeType
) );
176 // Declare the default interface. (The slotmap must not be empty, so
177 // we enter something which never occurs here (hopefully).)
178 static SfxSlot aFontworkBarSlots_Impl
[] =
180 { 0, SfxGroupId::NONE
, SfxSlotMode::NONE
, 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr, 0, SfxDisableFlags::NONE
, u
""_ustr
}
183 SFX_IMPL_INTERFACE(FontworkBar
, SfxShell
)
185 void FontworkBar::InitInterface_Impl()
187 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT
, SfxVisibilityFlags::Invisible
, ToolbarId::Svx_Fontwork_Bar
);
191 FontworkBar::FontworkBar(SfxViewShell
* pViewShell
)
192 : SfxShell(pViewShell
)
194 DBG_ASSERT( pViewShell
, "svx::FontworkBar::FontworkBar(), I need a viewshell!" );
196 SetPool(&pViewShell
->GetPool());
198 SetName( SvxResId( RID_SVX_FONTWORK_BAR
));
201 FontworkBar::~FontworkBar()
203 SetRepeatTarget(nullptr);
207 bool checkForFontWork( const SdrObject
* pObj
)
209 static constexpr OUString sTextPath
= u
"TextPath"_ustr
;
212 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
214 const SdrCustomShapeGeometryItem
& rGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
215 const Any
* pAny
= rGeometryItem
.GetPropertyValueByName( sTextPath
, sTextPath
);
223 bool checkForSelectedFontWork( SdrView
const * pSdrView
)
225 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
226 const size_t nCount
= rMarkList
.GetMarkCount();
228 for(size_t i
=0; (i
<nCount
) && !bFound
; ++i
)
230 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
231 bFound
= checkForFontWork(pObj
);
236 static void impl_execute( SfxRequest
const & rReq
, SdrCustomShapeGeometryItem
& rGeometryItem
, SdrObject
* pObj
)
238 sal_uInt16 nSID
= rReq
.GetSlot();
241 case SID_FONTWORK_SAME_LETTER_HEIGHTS
:
243 css::uno::Any
* pAny
= rGeometryItem
.GetPropertyValueByName( u
"TextPath"_ustr
, u
"SameLetterHeights"_ustr
);
249 css::beans::PropertyValue aPropValue
;
250 aPropValue
.Name
= "SameLetterHeights";
251 aPropValue
.Value
<<= bOn
;
252 rGeometryItem
.SetPropertyValue(u
"TextPath"_ustr
, aPropValue
);
256 case SID_FONTWORK_ALIGNMENT
:
258 const SfxInt32Item
* pAlignItem
= nullptr;
259 if( rReq
.GetArgs() && rReq
.GetArgs()->GetItemState( SID_FONTWORK_ALIGNMENT
, true, &pAlignItem
) == SfxItemState::SET
)
261 sal_Int32 nValue
= pAlignItem
->GetValue();
262 if ( ( nValue
>= 0 ) && ( nValue
< 5 ) )
264 drawing::TextFitToSizeType eFTS
= drawing::TextFitToSizeType_NONE
;
265 SdrTextHorzAdjust eHorzAdjust
;
268 case 4 : eFTS
= drawing::TextFitToSizeType_ALLLINES
; [[fallthrough
]];
269 case 3 : eHorzAdjust
= SDRTEXTHORZADJUST_BLOCK
; break;
270 default: eHorzAdjust
= SDRTEXTHORZADJUST_LEFT
; break;
271 case 1 : eHorzAdjust
= SDRTEXTHORZADJUST_CENTER
; break;
272 case 2 : eHorzAdjust
= SDRTEXTHORZADJUST_RIGHT
; break;
274 pObj
->SetMergedItem( SdrTextHorzAdjustItem( eHorzAdjust
) );
275 pObj
->SetMergedItem( SdrTextFitToSizeTypeItem( eFTS
) );
276 pObj
->BroadcastObjectChange();
282 case SID_FONTWORK_CHARACTER_SPACING
:
284 const SfxInt32Item
* pSpacingItem
= nullptr;
285 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_CHARACTER_SPACING
, true, &pSpacingItem
) == SfxItemState::SET
) )
287 sal_Int32 nCharSpacing
= pSpacingItem
->GetValue();
288 pObj
->SetMergedItem( SvxCharScaleWidthItem( static_cast<sal_uInt16
>(nCharSpacing
), EE_CHAR_FONTWIDTH
) );
289 pObj
->BroadcastObjectChange();
294 case SID_FONTWORK_KERN_CHARACTER_PAIRS
:
296 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_KERN_CHARACTER_PAIRS
) == SfxItemState::SET
) )
298 // sal_Bool bKernCharacterPairs = ((const SfxBoolItem*)rReq.GetArgs()->GetItem(SID_FONTWORK_KERN_CHARACTER_PAIRS))->GetValue();
299 //TODO: pObj->SetMergedItem( SvxCharScaleWidthItem( (sal_uInt16)nCharSpacing, EE_CHAR_FONTWIDTH ) );
300 pObj
->BroadcastObjectChange();
307 static void GetGeometryForCustomShape( SdrCustomShapeGeometryItem
& rGeometryItem
, const OUString
& rCustomShape
)
309 static constexpr OUString
sType( u
"Type"_ustr
);
311 css::beans::PropertyValue aPropVal
;
312 aPropVal
.Name
= sType
;
313 aPropVal
.Value
<<= rCustomShape
;
314 rGeometryItem
.SetPropertyValue( aPropVal
);
316 static constexpr OUString
sAdjustmentValues( u
"AdjustmentValues"_ustr
);
317 static constexpr OUString
sCoordinateOrigin( u
"CoordinateOrigin"_ustr
);
318 static constexpr OUString
sCoordinateSize( u
"CoordinateSize"_ustr
);
319 static constexpr OUString
sEquations( u
"Equations"_ustr
);
320 static constexpr OUString
sHandles( u
"Handles"_ustr
);
321 static constexpr OUString
sPath( u
"Path"_ustr
);
322 rGeometryItem
.ClearPropertyValue( sAdjustmentValues
);
323 rGeometryItem
.ClearPropertyValue( sCoordinateOrigin
);
324 rGeometryItem
.ClearPropertyValue( sCoordinateSize
);
325 rGeometryItem
.ClearPropertyValue( sEquations
);
326 rGeometryItem
.ClearPropertyValue( sHandles
);
327 rGeometryItem
.ClearPropertyValue( sPath
);
329 /* SJ: CustomShapes that are available in the gallery are having the highest
330 priority, so we will take a look there before taking the internal default */
332 if ( !GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT
) )
335 std::vector
< OUString
> aObjList
;
336 if ( !GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT
, aObjList
) )
339 for ( std::vector
<OUString
>::size_type i
= 0; i
< aObjList
.size(); i
++ )
341 if ( aObjList
[ i
].equalsIgnoreAsciiCase( rCustomShape
) )
343 FmFormModel aFormModel
;
345 if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT
, i
, &aFormModel
) )
347 const SdrObject
* pSourceObj
= nullptr;
348 if (aFormModel
.GetPageCount() > 0)
349 pSourceObj
= aFormModel
.GetPage( 0 )->GetObj( 0 );
350 SAL_WARN_IF(!pSourceObj
, "svx.form", "No content in gallery custom shape '" << rCustomShape
<< "'" );
353 PropertyValue aPropVal_
;
354 const SdrCustomShapeGeometryItem
& rSourceGeometry
= pSourceObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
);
355 const css::uno::Any
* pAny
= rSourceGeometry
.GetPropertyValueByName( sType
);
358 aPropVal_
.Name
= sType
;
359 aPropVal_
.Value
= *pAny
;
360 rGeometryItem
.SetPropertyValue( aPropVal_
);
362 pAny
= rSourceGeometry
.GetPropertyValueByName( sAdjustmentValues
);
365 aPropVal_
.Name
= sAdjustmentValues
;
366 aPropVal_
.Value
= *pAny
;
367 rGeometryItem
.SetPropertyValue( aPropVal_
);
369 pAny
= rSourceGeometry
.GetPropertyValueByName( sCoordinateOrigin
);
372 aPropVal_
.Name
= sCoordinateOrigin
;
373 aPropVal_
.Value
= *pAny
;
374 rGeometryItem
.SetPropertyValue( aPropVal_
);
376 pAny
= rSourceGeometry
.GetPropertyValueByName( sCoordinateSize
);
379 aPropVal_
.Name
= sCoordinateSize
;
380 aPropVal_
.Value
= *pAny
;
381 rGeometryItem
.SetPropertyValue( aPropVal_
);
383 pAny
= rSourceGeometry
.GetPropertyValueByName( sEquations
);
386 aPropVal_
.Name
= sEquations
;
387 aPropVal_
.Value
= *pAny
;
388 rGeometryItem
.SetPropertyValue( aPropVal_
);
390 pAny
= rSourceGeometry
.GetPropertyValueByName( sHandles
);
393 aPropVal_
.Name
= sHandles
;
394 aPropVal_
.Value
= *pAny
;
395 rGeometryItem
.SetPropertyValue( aPropVal_
);
397 pAny
= rSourceGeometry
.GetPropertyValueByName( sPath
);
400 aPropVal_
.Name
= sPath
;
401 aPropVal_
.Value
= *pAny
;
402 rGeometryItem
.SetPropertyValue( aPropVal_
);
411 void FontworkBar::execute( SdrView
& rSdrView
, SfxRequest
const & rReq
, SfxBindings
& rBindings
)
413 TranslateId pStrResId
;
415 sal_uInt16 nSID
= rReq
.GetSlot();
418 case SID_FONTWORK_GALLERY_FLOATER
:
420 std::shared_ptr
<FontWorkGalleryDialog
> pDlg
= std::make_shared
<FontWorkGalleryDialog
>(rReq
.GetFrameWeld(), rSdrView
, rBindings
.GetActiveFrame());
421 weld::DialogController::runAsync(pDlg
, [](int){});
425 case SID_FONTWORK_SHAPE_TYPE
:
427 OUString aCustomShape
;
428 const SfxItemSet
* pArgs
= rReq
.GetArgs();
431 const SfxStringItem
& rItm
= static_cast<const SfxStringItem
&>(pArgs
->Get( rReq
.GetSlot() ));
432 aCustomShape
= rItm
.GetValue();
434 if ( !aCustomShape
.isEmpty() )
436 const SdrMarkList
& rMarkList
= rSdrView
.GetMarkedObjectList();
437 const size_t nCount
= rMarkList
.GetMarkCount();
438 for( size_t i
= 0; i
< nCount
; ++i
)
440 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
441 if( auto pCustomShape
= dynamic_cast<SdrObjCustomShape
*>( pObj
) )
443 const bool bUndo
= rSdrView
.IsUndoEnabled();
447 OUString
aStr( SvxResId( RID_SVXSTR_UNDO_APPLY_FONTWORK_SHAPE
) );
448 rSdrView
.BegUndo(aStr
);
449 rSdrView
.AddUndo(rSdrView
.GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
451 SdrCustomShapeGeometryItem
aGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
452 GetGeometryForCustomShape( aGeometryItem
, aCustomShape
);
453 pObj
->SetMergedItem( aGeometryItem
);
455 Reference
< drawing::XShape
> aXShape
= GetXShapeForSdrObject( pCustomShape
);
458 Reference
< drawing::XEnhancedCustomShapeDefaulter
> xDefaulter( aXShape
, UNO_QUERY
);
459 if( xDefaulter
.is() )
460 xDefaulter
->createCustomShapeDefaults( aCustomShape
);
463 pObj
->BroadcastObjectChange();
466 rSdrView
.AdjustMarkHdl(); //HMH sal_True );
467 rBindings
.Invalidate( SID_FONTWORK_SHAPE_TYPE
);
474 case SID_FONTWORK_CHARACTER_SPACING_DIALOG
:
476 const SfxInt32Item
* pSpacingItem
= nullptr;
477 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_CHARACTER_SPACING
, true, &pSpacingItem
) == SfxItemState::SET
) )
479 sal_Int32 nCharSpacing
= pSpacingItem
->GetValue();
480 FontworkCharacterSpacingDialog
aDlg(rReq
.GetFrameWeld(), nCharSpacing
);
481 sal_uInt16 nRet
= aDlg
.run();
482 if (nRet
!= RET_CANCEL
)
484 SfxInt32Item
aItem(SID_FONTWORK_CHARACTER_SPACING
, aDlg
.getScale());
485 SfxPoolItem
* aItems
[] = { &aItem
, nullptr };
486 rBindings
.Execute( SID_FONTWORK_CHARACTER_SPACING
, const_cast<const SfxPoolItem
**>(aItems
) );
492 case SID_FONTWORK_SHAPE
:
493 case SID_FONTWORK_ALIGNMENT
:
496 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_ALIGNMENT
;
499 case SID_FONTWORK_CHARACTER_SPACING
:
502 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_CHARACTER_SPACING
;
505 case SID_FONTWORK_KERN_CHARACTER_PAIRS
:
508 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_CHARACTER_SPACING
;
511 case SID_FONTWORK_SAME_LETTER_HEIGHTS
:
514 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_SAME_LETTER_HEIGHT
;
516 const SdrMarkList
& rMarkList
= rSdrView
.GetMarkedObjectList();
517 const size_t nCount
= rMarkList
.GetMarkCount();
518 for( size_t i
= 0; i
< nCount
; ++i
)
520 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
521 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
523 const bool bUndo
= rSdrView
.IsUndoEnabled();
526 OUString
aStr( SvxResId( pStrResId
) );
527 rSdrView
.BegUndo(aStr
);
528 rSdrView
.AddUndo(rSdrView
.GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
530 SdrCustomShapeGeometryItem
aGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
531 impl_execute( rReq
, aGeometryItem
, pObj
);
532 pObj
->SetMergedItem( aGeometryItem
);
533 pObj
->BroadcastObjectChange();
543 void FontworkBar::getState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
545 if ( checkForSelectedFontWork( pSdrView
) )
547 SetAlignmentState( pSdrView
, rSet
);
548 SetCharacterSpacingState( pSdrView
, rSet
);
549 SetKernCharacterPairsState( pSdrView
, rSet
);
550 SetFontWorkShapeTypeState( pSdrView
, rSet
);
554 rSet
.DisableItem( SID_FONTWORK_ALIGNMENT_FLOATER
);
555 rSet
.DisableItem( SID_FONTWORK_ALIGNMENT
);
556 rSet
.DisableItem( SID_FONTWORK_CHARACTER_SPACING_FLOATER
);
557 rSet
.DisableItem( SID_FONTWORK_CHARACTER_SPACING
);
558 rSet
.DisableItem( SID_FONTWORK_KERN_CHARACTER_PAIRS
);
559 rSet
.DisableItem( SID_FONTWORK_SAME_LETTER_HEIGHTS
);
560 rSet
.DisableItem( SID_FONTWORK_SHAPE_TYPE
);
565 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */