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 ::cppu
;
51 using namespace ::com::sun::star
;
52 using namespace ::com::sun::star::beans
;
53 using namespace ::com::sun::star::uno
;
55 static void SetAlignmentState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
57 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
58 const size_t nCount
= rMarkList
.GetMarkCount();
60 sal_Int32 nAlignment
= -1;
61 for( size_t i
= 0; i
< nCount
; ++i
)
63 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
64 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
66 sal_Int32 nOldAlignment
= nAlignment
;
67 const SdrTextHorzAdjustItem
& rTextHorzAdjustItem
= pObj
->GetMergedItem( SDRATTR_TEXT_HORZADJUST
);
68 const SdrTextFitToSizeTypeItem
& rTextFitToSizeTypeItem
= pObj
->GetMergedItem( SDRATTR_TEXT_FITTOSIZE
);
69 switch ( rTextHorzAdjustItem
.GetValue() )
71 case SDRTEXTHORZADJUST_LEFT
: nAlignment
= 0; break;
72 case SDRTEXTHORZADJUST_CENTER
: nAlignment
= 1; break;
73 case SDRTEXTHORZADJUST_RIGHT
: nAlignment
= 2; break;
74 case SDRTEXTHORZADJUST_BLOCK
:
76 auto const fit(rTextFitToSizeTypeItem
.GetValue());
77 if (fit
== drawing::TextFitToSizeType_NONE
)
81 else if (fit
== drawing::TextFitToSizeType_ALLLINES
||
82 fit
== drawing::TextFitToSizeType_PROPORTIONAL
)
88 if ( ( nOldAlignment
!= -1 ) && ( nOldAlignment
!= nAlignment
) )
95 rSet
.Put( SfxInt32Item( SID_FONTWORK_ALIGNMENT
, nAlignment
) );
98 static void SetCharacterSpacingState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
100 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
101 const size_t nCount
= rMarkList
.GetMarkCount();
103 sal_Int32 nCharacterSpacing
= -1;
104 for( size_t i
= 0; i
< nCount
; ++i
)
106 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
107 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
109 sal_Int32 nOldCharacterSpacing
= nCharacterSpacing
;
110 const SvxCharScaleWidthItem
& rCharScaleWidthItem
= pObj
->GetMergedItem( EE_CHAR_FONTWIDTH
);
111 nCharacterSpacing
= rCharScaleWidthItem
.GetValue();
112 if ( ( nOldCharacterSpacing
!= -1 ) && ( nOldCharacterSpacing
!= nCharacterSpacing
) )
114 nCharacterSpacing
= -1;
119 rSet
.Put( SfxInt32Item( SID_FONTWORK_CHARACTER_SPACING
, nCharacterSpacing
) );
123 static void SetKernCharacterPairsState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
125 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
126 const size_t nCount
= rMarkList
.GetMarkCount();
128 bool bChecked
= false;
129 for( size_t i
= 0; i
< nCount
; ++i
)
131 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
132 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
134 const SvxKerningItem
& rKerningItem
= pObj
->GetMergedItem( EE_CHAR_KERNING
);
135 if ( rKerningItem
.GetValue() )
139 rSet
.Put( SfxBoolItem( SID_FONTWORK_KERN_CHARACTER_PAIRS
, bChecked
) );
142 static void SetFontWorkShapeTypeState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
144 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
145 const size_t nCount
= rMarkList
.GetMarkCount();
147 OUString aFontWorkShapeType
;
149 for( size_t i
= 0; i
< nCount
; ++i
)
151 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
152 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
154 const SdrCustomShapeGeometryItem
& rGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
155 const Any
* pAny
= rGeometryItem
.GetPropertyValueByName( "Type" );
159 if ( *pAny
>>= aType
)
161 if ( !aFontWorkShapeType
.isEmpty() )
163 if ( aFontWorkShapeType
!= aType
) // different FontWorkShapeTypes selected ?
165 aFontWorkShapeType
.clear();
169 aFontWorkShapeType
= aType
;
174 rSet
.Put( SfxStringItem( SID_FONTWORK_SHAPE_TYPE
, aFontWorkShapeType
) );
177 // Declare the default interface. (The slotmap must not be empty, so
178 // we enter something which never occurs here (hopefully).)
179 static SfxSlot aFontworkBarSlots_Impl
[] =
181 { 0, SfxGroupId::NONE
, SfxSlotMode::NONE
, 0, 0, nullptr, nullptr, nullptr, nullptr, nullptr, 0, SfxDisableFlags::NONE
, "" }
184 SFX_IMPL_INTERFACE(FontworkBar
, SfxShell
)
186 void FontworkBar::InitInterface_Impl()
188 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT
, SfxVisibilityFlags::Invisible
, ToolbarId::Svx_Fontwork_Bar
);
192 FontworkBar::FontworkBar(SfxViewShell
* pViewShell
)
193 : SfxShell(pViewShell
)
195 DBG_ASSERT( pViewShell
, "svx::FontworkBar::FontworkBar(), I need a viewshell!" );
197 SetPool(&pViewShell
->GetPool());
199 SetName( SvxResId( RID_SVX_FONTWORK_BAR
));
202 FontworkBar::~FontworkBar()
204 SetRepeatTarget(nullptr);
208 bool checkForFontWork( const SdrObject
* pObj
)
210 static constexpr OUStringLiteral sTextPath
= u
"TextPath";
213 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
215 const SdrCustomShapeGeometryItem
& rGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
216 const Any
* pAny
= rGeometryItem
.GetPropertyValueByName( sTextPath
, sTextPath
);
224 bool checkForSelectedFontWork( SdrView
const * pSdrView
)
226 const SdrMarkList
& rMarkList
= pSdrView
->GetMarkedObjectList();
227 const size_t nCount
= rMarkList
.GetMarkCount();
229 for(size_t i
=0; (i
<nCount
) && !bFound
; ++i
)
231 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
232 bFound
= checkForFontWork(pObj
);
237 static void impl_execute( SfxRequest
const & rReq
, SdrCustomShapeGeometryItem
& rGeometryItem
, SdrObject
* pObj
)
239 sal_uInt16 nSID
= rReq
.GetSlot();
242 case SID_FONTWORK_SAME_LETTER_HEIGHTS
:
244 css::uno::Any
* pAny
= rGeometryItem
.GetPropertyValueByName( "TextPath", "SameLetterHeights" );
250 css::beans::PropertyValue aPropValue
;
251 aPropValue
.Name
= "SameLetterHeights";
252 aPropValue
.Value
<<= bOn
;
253 rGeometryItem
.SetPropertyValue("TextPath", aPropValue
);
258 case SID_FONTWORK_ALIGNMENT
:
260 if( rReq
.GetArgs() && rReq
.GetArgs()->GetItemState( SID_FONTWORK_ALIGNMENT
) == SfxItemState::SET
)
262 sal_Int32 nValue
= rReq
.GetArgs()->GetItem
<SfxInt32Item
>(SID_FONTWORK_ALIGNMENT
)->GetValue();
263 if ( ( nValue
>= 0 ) && ( nValue
< 5 ) )
265 drawing::TextFitToSizeType eFTS
= drawing::TextFitToSizeType_NONE
;
266 SdrTextHorzAdjust eHorzAdjust
;
269 case 4 : eFTS
= drawing::TextFitToSizeType_ALLLINES
; [[fallthrough
]];
270 case 3 : eHorzAdjust
= SDRTEXTHORZADJUST_BLOCK
; break;
271 default: eHorzAdjust
= SDRTEXTHORZADJUST_LEFT
; break;
272 case 1 : eHorzAdjust
= SDRTEXTHORZADJUST_CENTER
; break;
273 case 2 : eHorzAdjust
= SDRTEXTHORZADJUST_RIGHT
; break;
275 pObj
->SetMergedItem( SdrTextHorzAdjustItem( eHorzAdjust
) );
276 pObj
->SetMergedItem( SdrTextFitToSizeTypeItem( eFTS
) );
277 pObj
->BroadcastObjectChange();
283 case SID_FONTWORK_CHARACTER_SPACING
:
285 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_CHARACTER_SPACING
) == SfxItemState::SET
) )
287 sal_Int32 nCharSpacing
= rReq
.GetArgs()->GetItem
<SfxInt32Item
>(SID_FONTWORK_CHARACTER_SPACING
)->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 const OUStringLiteral
sType( u
"Type" );
311 css::beans::PropertyValue aPropVal
;
312 aPropVal
.Name
= sType
;
313 aPropVal
.Value
<<= rCustomShape
;
314 rGeometryItem
.SetPropertyValue( aPropVal
);
316 static const OUStringLiteral
sAdjustmentValues( u
"AdjustmentValues" );
317 static const OUStringLiteral
sCoordinateOrigin( u
"CoordinateOrigin" );
318 static const OUStringLiteral
sCoordinateSize( u
"CoordinateSize" );
319 static const OUStringLiteral
sEquations( u
"Equations" );
320 static const OUStringLiteral
sHandles( u
"Handles" );
321 static const OUStringLiteral
sPath( u
"Path" );
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
;
344 SfxItemPool
& rPool(aFormModel
.GetItemPool());
345 rPool
.FreezeIdRanges();
347 if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT
, i
, &aFormModel
) )
349 const SdrObject
* pSourceObj
= nullptr;
350 if (aFormModel
.GetPageCount() > 0)
351 pSourceObj
= aFormModel
.GetPage( 0 )->GetObj( 0 );
352 SAL_WARN_IF(!pSourceObj
, "svx.form", "No content in gallery custom shape '" << rCustomShape
<< "'" );
355 PropertyValue aPropVal_
;
356 const SdrCustomShapeGeometryItem
& rSourceGeometry
= pSourceObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
);
357 const css::uno::Any
* pAny
= rSourceGeometry
.GetPropertyValueByName( sType
);
360 aPropVal_
.Name
= sType
;
361 aPropVal_
.Value
= *pAny
;
362 rGeometryItem
.SetPropertyValue( aPropVal_
);
364 pAny
= rSourceGeometry
.GetPropertyValueByName( sAdjustmentValues
);
367 aPropVal_
.Name
= sAdjustmentValues
;
368 aPropVal_
.Value
= *pAny
;
369 rGeometryItem
.SetPropertyValue( aPropVal_
);
371 pAny
= rSourceGeometry
.GetPropertyValueByName( sCoordinateOrigin
);
374 aPropVal_
.Name
= sCoordinateOrigin
;
375 aPropVal_
.Value
= *pAny
;
376 rGeometryItem
.SetPropertyValue( aPropVal_
);
378 pAny
= rSourceGeometry
.GetPropertyValueByName( sCoordinateSize
);
381 aPropVal_
.Name
= sCoordinateSize
;
382 aPropVal_
.Value
= *pAny
;
383 rGeometryItem
.SetPropertyValue( aPropVal_
);
385 pAny
= rSourceGeometry
.GetPropertyValueByName( sEquations
);
388 aPropVal_
.Name
= sEquations
;
389 aPropVal_
.Value
= *pAny
;
390 rGeometryItem
.SetPropertyValue( aPropVal_
);
392 pAny
= rSourceGeometry
.GetPropertyValueByName( sHandles
);
395 aPropVal_
.Name
= sHandles
;
396 aPropVal_
.Value
= *pAny
;
397 rGeometryItem
.SetPropertyValue( aPropVal_
);
399 pAny
= rSourceGeometry
.GetPropertyValueByName( sPath
);
402 aPropVal_
.Name
= sPath
;
403 aPropVal_
.Value
= *pAny
;
404 rGeometryItem
.SetPropertyValue( aPropVal_
);
413 void FontworkBar::execute( SdrView
& rSdrView
, SfxRequest
const & rReq
, SfxBindings
& rBindings
)
415 TranslateId pStrResId
;
417 sal_uInt16 nSID
= rReq
.GetSlot();
420 case SID_FONTWORK_GALLERY_FLOATER
:
422 std::shared_ptr
<FontWorkGalleryDialog
> pDlg
= std::make_shared
<FontWorkGalleryDialog
>(rReq
.GetFrameWeld(), rSdrView
);
423 weld::DialogController::runAsync(pDlg
, [](int){});
427 case SID_FONTWORK_SHAPE_TYPE
:
429 OUString aCustomShape
;
430 const SfxItemSet
* pArgs
= rReq
.GetArgs();
433 const SfxStringItem
& rItm
= static_cast<const SfxStringItem
&>(pArgs
->Get( rReq
.GetSlot() ));
434 aCustomShape
= rItm
.GetValue();
436 if ( !aCustomShape
.isEmpty() )
438 const SdrMarkList
& rMarkList
= rSdrView
.GetMarkedObjectList();
439 const size_t nCount
= rMarkList
.GetMarkCount();
440 for( size_t i
= 0; i
< nCount
; ++i
)
442 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
443 if( auto pCustomShape
= dynamic_cast<SdrObjCustomShape
*>( pObj
) )
445 const bool bUndo
= rSdrView
.IsUndoEnabled();
449 OUString
aStr( SvxResId( RID_SVXSTR_UNDO_APPLY_FONTWORK_SHAPE
) );
450 rSdrView
.BegUndo(aStr
);
451 rSdrView
.AddUndo(rSdrView
.GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
453 SdrCustomShapeGeometryItem
aGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
454 GetGeometryForCustomShape( aGeometryItem
, aCustomShape
);
455 pObj
->SetMergedItem( aGeometryItem
);
457 Reference
< drawing::XShape
> aXShape
= GetXShapeForSdrObject( pCustomShape
);
460 Reference
< drawing::XEnhancedCustomShapeDefaulter
> xDefaulter( aXShape
, UNO_QUERY
);
461 if( xDefaulter
.is() )
462 xDefaulter
->createCustomShapeDefaults( aCustomShape
);
465 pObj
->BroadcastObjectChange();
468 rSdrView
.AdjustMarkHdl(); //HMH sal_True );
469 rBindings
.Invalidate( SID_FONTWORK_SHAPE_TYPE
);
476 case SID_FONTWORK_CHARACTER_SPACING_DIALOG
:
478 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_CHARACTER_SPACING
) == SfxItemState::SET
) )
480 sal_Int32 nCharSpacing
= rReq
.GetArgs()->GetItem
<SfxInt32Item
>(SID_FONTWORK_CHARACTER_SPACING
)->GetValue();
481 FontworkCharacterSpacingDialog
aDlg(rReq
.GetFrameWeld(), nCharSpacing
);
482 sal_uInt16 nRet
= aDlg
.run();
483 if (nRet
!= RET_CANCEL
)
485 SfxInt32Item
aItem(SID_FONTWORK_CHARACTER_SPACING
, aDlg
.getScale());
486 SfxPoolItem
* aItems
[] = { &aItem
, nullptr };
487 rBindings
.Execute( SID_FONTWORK_CHARACTER_SPACING
, const_cast<const SfxPoolItem
**>(aItems
) );
493 case SID_FONTWORK_SHAPE
:
494 case SID_FONTWORK_ALIGNMENT
:
497 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_ALIGNMENT
;
500 case SID_FONTWORK_CHARACTER_SPACING
:
503 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_CHARACTER_SPACING
;
506 case SID_FONTWORK_KERN_CHARACTER_PAIRS
:
509 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_CHARACTER_SPACING
;
512 case SID_FONTWORK_SAME_LETTER_HEIGHTS
:
515 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_SAME_LETTER_HEIGHT
;
517 const SdrMarkList
& rMarkList
= rSdrView
.GetMarkedObjectList();
518 const size_t nCount
= rMarkList
.GetMarkCount();
519 for( size_t i
= 0; i
< nCount
; ++i
)
521 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
522 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
524 const bool bUndo
= rSdrView
.IsUndoEnabled();
527 OUString
aStr( SvxResId( pStrResId
) );
528 rSdrView
.BegUndo(aStr
);
529 rSdrView
.AddUndo(rSdrView
.GetModel().GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
531 SdrCustomShapeGeometryItem
aGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
532 impl_execute( rReq
, aGeometryItem
, pObj
);
533 pObj
->SetMergedItem( aGeometryItem
);
534 pObj
->BroadcastObjectChange();
544 void FontworkBar::getState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
546 if ( checkForSelectedFontWork( pSdrView
) )
548 SetAlignmentState( pSdrView
, rSet
);
549 SetCharacterSpacingState( pSdrView
, rSet
);
550 SetKernCharacterPairsState( pSdrView
, rSet
);
551 SetFontWorkShapeTypeState( pSdrView
, rSet
);
555 rSet
.DisableItem( SID_FONTWORK_ALIGNMENT_FLOATER
);
556 rSet
.DisableItem( SID_FONTWORK_ALIGNMENT
);
557 rSet
.DisableItem( SID_FONTWORK_CHARACTER_SPACING_FLOATER
);
558 rSet
.DisableItem( SID_FONTWORK_CHARACTER_SPACING
);
559 rSet
.DisableItem( SID_FONTWORK_KERN_CHARACTER_PAIRS
);
560 rSet
.DisableItem( SID_FONTWORK_SAME_LETTER_HEIGHTS
);
561 rSet
.DisableItem( SID_FONTWORK_SHAPE_TYPE
);
566 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */