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
, nullptr }
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( 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" );
255 case SID_FONTWORK_ALIGNMENT
:
257 if( rReq
.GetArgs() && rReq
.GetArgs()->GetItemState( SID_FONTWORK_ALIGNMENT
) == SfxItemState::SET
)
259 sal_Int32 nValue
= rReq
.GetArgs()->GetItem
<SfxInt32Item
>(SID_FONTWORK_ALIGNMENT
)->GetValue();
260 if ( ( nValue
>= 0 ) && ( nValue
< 5 ) )
262 drawing::TextFitToSizeType eFTS
= drawing::TextFitToSizeType_NONE
;
263 SdrTextHorzAdjust eHorzAdjust
;
266 case 4 : eFTS
= drawing::TextFitToSizeType_ALLLINES
; [[fallthrough
]];
267 case 3 : eHorzAdjust
= SDRTEXTHORZADJUST_BLOCK
; break;
268 default: eHorzAdjust
= SDRTEXTHORZADJUST_LEFT
; break;
269 case 1 : eHorzAdjust
= SDRTEXTHORZADJUST_CENTER
; break;
270 case 2 : eHorzAdjust
= SDRTEXTHORZADJUST_RIGHT
; break;
272 pObj
->SetMergedItem( SdrTextHorzAdjustItem( eHorzAdjust
) );
273 pObj
->SetMergedItem( SdrTextFitToSizeTypeItem( eFTS
) );
274 pObj
->BroadcastObjectChange();
280 case SID_FONTWORK_CHARACTER_SPACING
:
282 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_CHARACTER_SPACING
) == SfxItemState::SET
) )
284 sal_Int32 nCharSpacing
= rReq
.GetArgs()->GetItem
<SfxInt32Item
>(SID_FONTWORK_CHARACTER_SPACING
)->GetValue();
285 pObj
->SetMergedItem( SvxCharScaleWidthItem( static_cast<sal_uInt16
>(nCharSpacing
), EE_CHAR_FONTWIDTH
) );
286 pObj
->BroadcastObjectChange();
291 case SID_FONTWORK_KERN_CHARACTER_PAIRS
:
293 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_KERN_CHARACTER_PAIRS
) == SfxItemState::SET
) )
295 // sal_Bool bKernCharacterPairs = ((const SfxBoolItem*)rReq.GetArgs()->GetItem(SID_FONTWORK_KERN_CHARACTER_PAIRS))->GetValue();
296 //TODO: pObj->SetMergedItem( SvxCharScaleWidthItem( (sal_uInt16)nCharSpacing, EE_CHAR_FONTWIDTH ) );
297 pObj
->BroadcastObjectChange();
304 static void GetGeometryForCustomShape( SdrCustomShapeGeometryItem
& rGeometryItem
, const OUString
& rCustomShape
)
306 static const OUStringLiteral
sType( u
"Type" );
308 css::beans::PropertyValue aPropVal
;
309 aPropVal
.Name
= sType
;
310 aPropVal
.Value
<<= rCustomShape
;
311 rGeometryItem
.SetPropertyValue( aPropVal
);
313 static const OUStringLiteral
sAdjustmentValues( u
"AdjustmentValues" );
314 static const OUStringLiteral
sCoordinateOrigin( u
"CoordinateOrigin" );
315 static const OUStringLiteral
sCoordinateSize( u
"CoordinateSize" );
316 static const OUStringLiteral
sEquations( u
"Equations" );
317 static const OUStringLiteral
sHandles( u
"Handles" );
318 static const OUStringLiteral
sPath( u
"Path" );
319 rGeometryItem
.ClearPropertyValue( sAdjustmentValues
);
320 rGeometryItem
.ClearPropertyValue( sCoordinateOrigin
);
321 rGeometryItem
.ClearPropertyValue( sCoordinateSize
);
322 rGeometryItem
.ClearPropertyValue( sEquations
);
323 rGeometryItem
.ClearPropertyValue( sHandles
);
324 rGeometryItem
.ClearPropertyValue( sPath
);
326 /* SJ: CustomShapes that are available in the gallery are having the highest
327 priority, so we will take a look there before taking the internal default */
329 if ( !GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT
) )
332 std::vector
< OUString
> aObjList
;
333 if ( !GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT
, aObjList
) )
336 for ( std::vector
<OUString
>::size_type i
= 0; i
< aObjList
.size(); i
++ )
338 if ( aObjList
[ i
].equalsIgnoreAsciiCase( rCustomShape
) )
340 FmFormModel aFormModel
;
341 SfxItemPool
& rPool(aFormModel
.GetItemPool());
342 rPool
.FreezeIdRanges();
344 if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT
, i
, &aFormModel
) )
346 const SdrObject
* pSourceObj
= nullptr;
347 if (aFormModel
.GetPageCount() > 0)
348 pSourceObj
= aFormModel
.GetPage( 0 )->GetObj( 0 );
349 SAL_WARN_IF(!pSourceObj
, "svx.form", "No content in gallery custom shape '" << rCustomShape
<< "'" );
352 PropertyValue aPropVal_
;
353 const SdrCustomShapeGeometryItem
& rSourceGeometry
= pSourceObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
);
354 const css::uno::Any
* pAny
= rSourceGeometry
.GetPropertyValueByName( sType
);
357 aPropVal_
.Name
= sType
;
358 aPropVal_
.Value
= *pAny
;
359 rGeometryItem
.SetPropertyValue( aPropVal_
);
361 pAny
= rSourceGeometry
.GetPropertyValueByName( sAdjustmentValues
);
364 aPropVal_
.Name
= sAdjustmentValues
;
365 aPropVal_
.Value
= *pAny
;
366 rGeometryItem
.SetPropertyValue( aPropVal_
);
368 pAny
= rSourceGeometry
.GetPropertyValueByName( sCoordinateOrigin
);
371 aPropVal_
.Name
= sCoordinateOrigin
;
372 aPropVal_
.Value
= *pAny
;
373 rGeometryItem
.SetPropertyValue( aPropVal_
);
375 pAny
= rSourceGeometry
.GetPropertyValueByName( sCoordinateSize
);
378 aPropVal_
.Name
= sCoordinateSize
;
379 aPropVal_
.Value
= *pAny
;
380 rGeometryItem
.SetPropertyValue( aPropVal_
);
382 pAny
= rSourceGeometry
.GetPropertyValueByName( sEquations
);
385 aPropVal_
.Name
= sEquations
;
386 aPropVal_
.Value
= *pAny
;
387 rGeometryItem
.SetPropertyValue( aPropVal_
);
389 pAny
= rSourceGeometry
.GetPropertyValueByName( sHandles
);
392 aPropVal_
.Name
= sHandles
;
393 aPropVal_
.Value
= *pAny
;
394 rGeometryItem
.SetPropertyValue( aPropVal_
);
396 pAny
= rSourceGeometry
.GetPropertyValueByName( sPath
);
399 aPropVal_
.Name
= sPath
;
400 aPropVal_
.Value
= *pAny
;
401 rGeometryItem
.SetPropertyValue( aPropVal_
);
410 void FontworkBar::execute( SdrView
& rSdrView
, SfxRequest
const & rReq
, SfxBindings
& rBindings
)
412 const char* pStrResId
= nullptr;
414 sal_uInt16 nSID
= rReq
.GetSlot();
417 case SID_FONTWORK_GALLERY_FLOATER
:
419 std::shared_ptr
<FontWorkGalleryDialog
> pDlg
= std::make_shared
<FontWorkGalleryDialog
>(rReq
.GetFrameWeld(), rSdrView
);
420 weld::DialogController::runAsync(pDlg
, [](int){});
424 case SID_FONTWORK_SHAPE_TYPE
:
426 OUString aCustomShape
;
427 const SfxItemSet
* pArgs
= rReq
.GetArgs();
430 const SfxStringItem
& rItm
= static_cast<const SfxStringItem
&>(pArgs
->Get( rReq
.GetSlot() ));
431 aCustomShape
= rItm
.GetValue();
433 if ( !aCustomShape
.isEmpty() )
435 const SdrMarkList
& rMarkList
= rSdrView
.GetMarkedObjectList();
436 const size_t nCount
= rMarkList
.GetMarkCount();
437 for( size_t i
= 0; i
< nCount
; ++i
)
439 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
440 if( auto pCustomShape
= dynamic_cast<SdrObjCustomShape
*>( pObj
) )
442 const bool bUndo
= rSdrView
.IsUndoEnabled();
446 OUString
aStr( SvxResId( RID_SVXSTR_UNDO_APPLY_FONTWORK_SHAPE
) );
447 rSdrView
.BegUndo(aStr
);
448 rSdrView
.AddUndo(rSdrView
.GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
450 SdrCustomShapeGeometryItem
aGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
451 GetGeometryForCustomShape( aGeometryItem
, aCustomShape
);
452 pObj
->SetMergedItem( aGeometryItem
);
454 Reference
< drawing::XShape
> aXShape
= GetXShapeForSdrObject( pCustomShape
);
457 Reference
< drawing::XEnhancedCustomShapeDefaulter
> xDefaulter( aXShape
, UNO_QUERY
);
458 if( xDefaulter
.is() )
459 xDefaulter
->createCustomShapeDefaults( aCustomShape
);
462 pObj
->BroadcastObjectChange();
465 rSdrView
.AdjustMarkHdl(); //HMH sal_True );
466 rBindings
.Invalidate( SID_FONTWORK_SHAPE_TYPE
);
473 case SID_FONTWORK_CHARACTER_SPACING_DIALOG
:
475 if( rReq
.GetArgs() && ( rReq
.GetArgs()->GetItemState( SID_FONTWORK_CHARACTER_SPACING
) == SfxItemState::SET
) )
477 sal_Int32 nCharSpacing
= rReq
.GetArgs()->GetItem
<SfxInt32Item
>(SID_FONTWORK_CHARACTER_SPACING
)->GetValue();
478 FontworkCharacterSpacingDialog
aDlg(rReq
.GetFrameWeld(), nCharSpacing
);
479 sal_uInt16 nRet
= aDlg
.run();
480 if (nRet
!= RET_CANCEL
)
482 SfxInt32Item
aItem(SID_FONTWORK_CHARACTER_SPACING
, aDlg
.getScale());
483 SfxPoolItem
* aItems
[] = { &aItem
, nullptr };
484 rBindings
.Execute( SID_FONTWORK_CHARACTER_SPACING
, const_cast<const SfxPoolItem
**>(aItems
) );
490 case SID_FONTWORK_SHAPE
:
491 case SID_FONTWORK_ALIGNMENT
:
494 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_ALIGNMENT
;
497 case SID_FONTWORK_CHARACTER_SPACING
:
500 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_CHARACTER_SPACING
;
503 case SID_FONTWORK_KERN_CHARACTER_PAIRS
:
506 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_CHARACTER_SPACING
;
509 case SID_FONTWORK_SAME_LETTER_HEIGHTS
:
512 pStrResId
= RID_SVXSTR_UNDO_APPLY_FONTWORK_SAME_LETTER_HEIGHT
;
514 const SdrMarkList
& rMarkList
= rSdrView
.GetMarkedObjectList();
515 const size_t nCount
= rMarkList
.GetMarkCount();
516 for( size_t i
= 0; i
< nCount
; ++i
)
518 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
519 if( dynamic_cast<const SdrObjCustomShape
*>( pObj
) != nullptr )
521 const bool bUndo
= rSdrView
.IsUndoEnabled();
524 OUString
aStr( SvxResId( pStrResId
) );
525 rSdrView
.BegUndo(aStr
);
526 rSdrView
.AddUndo(rSdrView
.GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj
));
528 SdrCustomShapeGeometryItem
aGeometryItem( pObj
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
529 impl_execute( rReq
, aGeometryItem
, pObj
);
530 pObj
->SetMergedItem( aGeometryItem
);
531 pObj
->BroadcastObjectChange();
541 void FontworkBar::getState( SdrView
const * pSdrView
, SfxItemSet
& rSet
)
543 if ( checkForSelectedFontWork( pSdrView
) )
545 SetAlignmentState( pSdrView
, rSet
);
546 SetCharacterSpacingState( pSdrView
, rSet
);
547 SetKernCharacterPairsState( pSdrView
, rSet
);
548 SetFontWorkShapeTypeState( pSdrView
, rSet
);
552 rSet
.DisableItem( SID_FONTWORK_ALIGNMENT_FLOATER
);
553 rSet
.DisableItem( SID_FONTWORK_ALIGNMENT
);
554 rSet
.DisableItem( SID_FONTWORK_CHARACTER_SPACING_FLOATER
);
555 rSet
.DisableItem( SID_FONTWORK_CHARACTER_SPACING
);
556 rSet
.DisableItem( SID_FONTWORK_KERN_CHARACTER_PAIRS
);
557 rSet
.DisableItem( SID_FONTWORK_SAME_LETTER_HEIGHTS
);
558 rSet
.DisableItem( SID_FONTWORK_SHAPE_TYPE
);
563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */