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 "DrawCommandDispatch.hxx"
21 #include <ChartController.hxx>
22 #include <DrawViewWrapper.hxx>
23 #include <chartview/DrawModelWrapper.hxx>
25 #include <com/sun/star/frame/CommandGroup.hpp>
26 #include <o3tl/unsafe_downcast.hxx>
27 #include <o3tl/string_view.hxx>
28 #include <vcl/svapp.hxx>
29 #include <editeng/eeitem.hxx>
30 #include <svx/strings.hrc>
31 #include <svx/dialmgr.hxx>
32 #include <svx/fmmodel.hxx>
33 #include <svx/gallery.hxx>
34 #include <svx/svdoashp.hxx>
35 #include <svx/svdocapt.hxx>
36 #include <svx/svdopath.hxx>
37 #include <svx/svdpage.hxx>
38 #include <svx/unoapi.hxx>
39 #include <svx/xlnedit.hxx>
40 #include <svx/xlnedwit.hxx>
41 #include <svx/xlnwtit.hxx>
42 #include <svx/xtable.hxx>
43 #include <svx/sdtagitm.hxx>
44 #include <basegfx/polygon/b2dpolygon.hxx>
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::frame
;
49 using ::com::sun::star::uno::Reference
;
50 using ::com::sun::star::uno::Sequence
;
56 DrawCommandDispatch::DrawCommandDispatch( const Reference
< uno::XComponentContext
>& rxContext
,
57 ChartController
* pController
)
58 :FeatureCommandDispatchBase( rxContext
)
59 ,m_pChartController( pController
)
63 DrawCommandDispatch::~DrawCommandDispatch()
67 bool DrawCommandDispatch::isFeatureSupported( const OUString
& rCommandURL
)
69 ChartCommandID nFeatureId
= ChartCommandID::NONE
;
70 OUString aBaseCommand
;
71 OUString aCustomShapeType
;
72 return parseCommandURL( rCommandURL
, &nFeatureId
, &aBaseCommand
, &aCustomShapeType
);
75 static ::basegfx::B2DPolyPolygon
getPolygon(TranslateId pResId
, const SdrModel
& rModel
)
77 ::basegfx::B2DPolyPolygon aReturn
;
78 XLineEndListRef pLineEndList
= rModel
.GetLineEndList();
79 if ( pLineEndList
.is() )
81 OUString
aName(SvxResId(pResId
));
82 tools::Long nCount
= pLineEndList
->Count();
83 for ( tools::Long nIndex
= 0; nIndex
< nCount
; ++nIndex
)
85 const XLineEndEntry
* pEntry
= pLineEndList
->GetLineEnd(nIndex
);
86 if ( pEntry
->GetName() == aName
)
88 aReturn
= pEntry
->GetLineEnd();
96 void DrawCommandDispatch::setAttributes( SdrObject
* pObj
)
98 if ( !m_pChartController
)
101 DrawModelWrapper
* pDrawModelWrapper
= m_pChartController
->GetDrawModelWrapper();
102 DrawViewWrapper
* pDrawViewWrapper
= m_pChartController
->GetDrawViewWrapper();
103 if ( !(pDrawModelWrapper
&& pDrawViewWrapper
&& pDrawViewWrapper
->GetCurrentObjIdentifier() == SdrObjKind::CustomShape
) )
106 bool bAttributesAppliedFromGallery
= false;
107 if ( GalleryExplorer::GetSdrObjCount( GALLERY_THEME_POWERPOINT
) )
109 std::vector
< OUString
> aObjList
;
110 if ( GalleryExplorer::FillObjListTitle( GALLERY_THEME_POWERPOINT
, aObjList
) )
112 for ( size_t i
= 0; i
< aObjList
.size(); ++i
)
114 if ( aObjList
[ i
].equalsIgnoreAsciiCase( m_aCustomShapeType
) )
118 if ( GalleryExplorer::GetSdrObj( GALLERY_THEME_POWERPOINT
, i
, &aModel
) )
120 const SdrObject
* pSourceObj
= aModel
.GetPage( 0 )->GetObj( 0 );
123 const SfxItemSet
& rSource
= pSourceObj
->GetMergedItemSet();
125 // Ranges from SdrAttrObj:
126 SDRATTR_START
, SDRATTR_SHADOW_LAST
,
129 SDRATTR_TEXTDIRECTION
,
130 SDRATTR_TEXTDIRECTION
,
131 // Graphic attributes, 3D
132 // properties, CustomShape
135 SDRATTR_CUSTOMSHAPE_LAST
,
136 // Range from SdrTextObj:
137 EE_ITEMS_START
, EE_ITEMS_END
>
138 aDest(pObj
->getSdrModelFromSdrObject().GetItemPool());
139 aDest
.Set( rSource
);
140 pObj
->SetMergedItemSet( aDest
);
141 Degree100 nAngle
= pSourceObj
->GetRotateAngle();
143 pObj
->NbcRotate( pObj
->GetSnapRect().Center(), nAngle
);
144 bAttributesAppliedFromGallery
= true;
152 if ( !bAttributesAppliedFromGallery
)
154 pObj
->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER
) );
155 pObj
->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK
) );
156 pObj
->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
158 o3tl::unsafe_downcast
< SdrObjCustomShape
* >( pObj
)->MergeDefaultAttributes( &m_aCustomShapeType
);
162 void DrawCommandDispatch::setLineEnds( SfxItemSet
& rAttr
)
164 if ( !(m_nFeatureId
== ChartCommandID::DrawLineArrowEnd
&& m_pChartController
) )
167 DrawModelWrapper
* pDrawModelWrapper
= m_pChartController
->GetDrawModelWrapper();
168 DrawViewWrapper
* pDrawViewWrapper
= m_pChartController
->GetDrawViewWrapper();
169 if ( !(pDrawModelWrapper
&& pDrawViewWrapper
) )
172 ::basegfx::B2DPolyPolygon
aArrow( getPolygon( RID_SVXSTR_ARROW
, pDrawModelWrapper
->getSdrModel() ) );
173 if ( !aArrow
.count() )
175 ::basegfx::B2DPolygon aNewArrow
;
176 aNewArrow
.append( ::basegfx::B2DPoint( 10.0, 0.0 ) );
177 aNewArrow
.append( ::basegfx::B2DPoint( 0.0, 30.0) );
178 aNewArrow
.append( ::basegfx::B2DPoint( 20.0, 30.0 ) );
179 aNewArrow
.setClosed( true );
180 aArrow
.append( aNewArrow
);
183 SfxItemSet
aSet(pDrawViewWrapper
->GetModel().GetItemPool());
184 pDrawViewWrapper
->GetAttributes( aSet
);
186 tools::Long nWidth
= 300; // (1/100th mm)
187 if ( aSet
.GetItemState( XATTR_LINEWIDTH
) != SfxItemState::INVALID
)
189 tools::Long nValue
= aSet
.Get( XATTR_LINEWIDTH
).GetValue();
196 rAttr
.Put( XLineEndItem( SvxResId( RID_SVXSTR_ARROW
), std::move(aArrow
) ) );
197 rAttr
.Put( XLineEndWidthItem( nWidth
) );
200 // WeakComponentImplHelperBase
201 void DrawCommandDispatch::disposing(std::unique_lock
<std::mutex
>& /*rGuard*/)
206 void DrawCommandDispatch::disposing( const lang::EventObject
& /* Source */ )
210 FeatureState
DrawCommandDispatch::getState( const OUString
& rCommand
)
212 FeatureState aReturn
;
213 aReturn
.bEnabled
= false;
214 aReturn
.aState
<<= false;
216 ChartCommandID nFeatureId
= ChartCommandID::NONE
;
217 OUString aBaseCommand
;
218 OUString aCustomShapeType
;
219 if ( parseCommandURL( rCommand
, &nFeatureId
, &aBaseCommand
, &aCustomShapeType
) )
221 switch ( nFeatureId
)
223 case ChartCommandID::DrawObjectSelect
:
224 case ChartCommandID::DrawLine
:
225 case ChartCommandID::DrawLineArrowEnd
:
226 case ChartCommandID::DrawRect
:
227 case ChartCommandID::DrawEllipse
:
228 case ChartCommandID::DrawFreelineNoFill
:
229 case ChartCommandID::DrawText
:
230 case ChartCommandID::DrawCaption
:
231 case ChartCommandID::DrawToolboxCsBasic
:
232 case ChartCommandID::DrawToolboxCsSymbol
:
233 case ChartCommandID::DrawToolboxCsArrow
:
234 case ChartCommandID::DrawToolboxCsFlowchart
:
235 case ChartCommandID::DrawToolboxCsCallout
:
236 case ChartCommandID::DrawToolboxCsStar
:
238 aReturn
.bEnabled
= true;
239 aReturn
.aState
<<= false;
244 aReturn
.bEnabled
= false;
245 aReturn
.aState
<<= false;
254 void DrawCommandDispatch::execute( const OUString
& rCommand
, const Sequence
< beans::PropertyValue
>& rArgs
)
256 ChartDrawMode eDrawMode
= CHARTDRAW_SELECT
;
257 SdrObjKind eKind
= SdrObjKind::NONE
;
259 ChartCommandID nFeatureId
= ChartCommandID::NONE
;
260 OUString aBaseCommand
;
261 OUString aCustomShapeType
;
262 if ( !parseCommandURL( rCommand
, &nFeatureId
, &aBaseCommand
, &aCustomShapeType
) )
265 bool bCreate
= false;
266 m_nFeatureId
= nFeatureId
;
267 m_aCustomShapeType
= aCustomShapeType
;
269 switch ( nFeatureId
)
271 case ChartCommandID::DrawObjectSelect
:
273 eDrawMode
= CHARTDRAW_SELECT
;
274 eKind
= SdrObjKind::NONE
;
277 case ChartCommandID::DrawLine
:
278 case ChartCommandID::DrawLineArrowEnd
:
280 eDrawMode
= CHARTDRAW_INSERT
;
281 eKind
= SdrObjKind::Line
;
284 case ChartCommandID::DrawRect
:
286 eDrawMode
= CHARTDRAW_INSERT
;
287 eKind
= SdrObjKind::Rectangle
;
290 case ChartCommandID::DrawEllipse
:
292 eDrawMode
= CHARTDRAW_INSERT
;
293 eKind
= SdrObjKind::CircleOrEllipse
;
296 case ChartCommandID::DrawFreelineNoFill
:
298 eDrawMode
= CHARTDRAW_INSERT
;
299 eKind
= SdrObjKind::FreehandLine
;
302 case ChartCommandID::DrawText
:
304 eDrawMode
= CHARTDRAW_INSERT
;
305 eKind
= SdrObjKind::Text
;
309 case ChartCommandID::DrawCaption
:
311 eDrawMode
= CHARTDRAW_INSERT
;
312 eKind
= SdrObjKind::Caption
;
315 case ChartCommandID::DrawToolboxCsBasic
:
316 case ChartCommandID::DrawToolboxCsSymbol
:
317 case ChartCommandID::DrawToolboxCsArrow
:
318 case ChartCommandID::DrawToolboxCsFlowchart
:
319 case ChartCommandID::DrawToolboxCsCallout
:
320 case ChartCommandID::DrawToolboxCsStar
:
322 eDrawMode
= CHARTDRAW_INSERT
;
323 eKind
= SdrObjKind::CustomShape
;
328 eDrawMode
= CHARTDRAW_SELECT
;
329 eKind
= SdrObjKind::NONE
;
334 if ( !m_pChartController
)
337 DrawViewWrapper
* pDrawViewWrapper
= m_pChartController
->GetDrawViewWrapper();
338 if ( !pDrawViewWrapper
)
341 SolarMutexGuard aGuard
;
342 m_pChartController
->setDrawMode( eDrawMode
);
346 pDrawViewWrapper
->SetCreateMode();
349 const beans::PropertyValue
* pKeyModifier
= std::find_if(rArgs
.begin(), rArgs
.end(),
350 [](const beans::PropertyValue
& lhs
)
351 {return lhs
.Name
== "KeyModifier";} );
352 sal_Int16 nKeyModifier
= 0;
353 if ( !(pKeyModifier
!= rArgs
.end() && ( pKeyModifier
->Value
>>= nKeyModifier
) && nKeyModifier
== KEY_MOD1
) )
356 if ( eDrawMode
!= CHARTDRAW_INSERT
)
359 rtl::Reference
<SdrObject
> pObj
= createDefaultObject( nFeatureId
);
362 SdrPageView
* pPageView
= pDrawViewWrapper
->GetSdrPageView();
363 if (pDrawViewWrapper
->InsertObjectAtView(pObj
.get(), *pPageView
))
364 m_pChartController
->SetAndApplySelection(Reference
<drawing::XShape
>(pObj
->getUnoShape(), uno::UNO_QUERY
));
365 if ( nFeatureId
== ChartCommandID::DrawText
)
367 m_pChartController
->StartTextEdit();
372 void DrawCommandDispatch::describeSupportedFeatures()
374 implDescribeSupportedFeature( ".uno:SelectObject", ChartCommandID::DrawObjectSelect
, CommandGroup::INSERT
);
375 implDescribeSupportedFeature( ".uno:Line", ChartCommandID::DrawLine
, CommandGroup::INSERT
);
376 implDescribeSupportedFeature( ".uno:LineArrowEnd", ChartCommandID::DrawLineArrowEnd
, CommandGroup::INSERT
);
377 implDescribeSupportedFeature( ".uno:Rect", ChartCommandID::DrawRect
, CommandGroup::INSERT
);
378 implDescribeSupportedFeature( ".uno:Ellipse", ChartCommandID::DrawEllipse
, CommandGroup::INSERT
);
379 implDescribeSupportedFeature( ".uno:Freeline_Unfilled", ChartCommandID::DrawFreelineNoFill
, CommandGroup::INSERT
);
380 implDescribeSupportedFeature( ".uno:DrawText", ChartCommandID::DrawText
, CommandGroup::INSERT
);
381 implDescribeSupportedFeature( ".uno:DrawCaption", ChartCommandID::DrawCaption
, CommandGroup::INSERT
);
382 implDescribeSupportedFeature( ".uno:BasicShapes", ChartCommandID::DrawToolboxCsBasic
, CommandGroup::INSERT
);
383 implDescribeSupportedFeature( ".uno:SymbolShapes", ChartCommandID::DrawToolboxCsSymbol
, CommandGroup::INSERT
);
384 implDescribeSupportedFeature( ".uno:ArrowShapes", ChartCommandID::DrawToolboxCsArrow
, CommandGroup::INSERT
);
385 implDescribeSupportedFeature( ".uno:FlowChartShapes", ChartCommandID::DrawToolboxCsFlowchart
, CommandGroup::INSERT
);
386 implDescribeSupportedFeature( ".uno:CalloutShapes", ChartCommandID::DrawToolboxCsCallout
, CommandGroup::INSERT
);
387 implDescribeSupportedFeature( ".uno:StarShapes", ChartCommandID::DrawToolboxCsStar
, CommandGroup::INSERT
);
390 void DrawCommandDispatch::setInsertObj(SdrObjKind eObj
)
392 DrawViewWrapper
* pDrawViewWrapper
= ( m_pChartController
? m_pChartController
->GetDrawViewWrapper() : nullptr );
393 if ( pDrawViewWrapper
)
395 pDrawViewWrapper
->SetCurrentObj( eObj
/*, Inventor */);
399 rtl::Reference
<SdrObject
> DrawCommandDispatch::createDefaultObject( const ChartCommandID nID
)
401 rtl::Reference
<SdrObject
> pObj
;
402 DrawViewWrapper
* pDrawViewWrapper
= ( m_pChartController
? m_pChartController
->GetDrawViewWrapper() : nullptr );
403 DrawModelWrapper
* pDrawModelWrapper
= ( m_pChartController
? m_pChartController
->GetDrawModelWrapper() : nullptr );
405 if ( pDrawViewWrapper
&& pDrawModelWrapper
)
407 Reference
< drawing::XDrawPage
> xDrawPage( pDrawModelWrapper
->getMainDrawPage() );
408 SdrPage
* pPage
= GetSdrPageFromXDrawPage( xDrawPage
);
411 SolarMutexGuard aGuard
;
413 pObj
= SdrObjFactory::MakeNewObject(
414 pDrawModelWrapper
->getSdrModel(),
415 pDrawViewWrapper
->GetCurrentObjInventor(),
416 pDrawViewWrapper
->GetCurrentObjIdentifier());
420 Size
aObjectSize( 4000, 2500 );
421 tools::Rectangle
aPageRect( tools::Rectangle( Point( 0, 0 ), pPage
->GetSize() ) );
422 Point aObjectPos
= aPageRect
.Center();
423 aObjectPos
.AdjustX( -(aObjectSize
.Width() / 2) );
424 aObjectPos
.AdjustY( -(aObjectSize
.Height() / 2) );
425 tools::Rectangle
aRect( aObjectPos
, aObjectSize
);
429 case ChartCommandID::DrawLine
:
430 case ChartCommandID::DrawLineArrowEnd
:
432 if ( auto const pathObj
= dynamic_cast<SdrPathObj
*>( pObj
.get()) )
434 Point aStart
= aRect
.TopLeft();
435 Point aEnd
= aRect
.BottomRight();
436 sal_Int32
nYMiddle( ( aRect
.Top() + aRect
.Bottom() ) / 2 );
437 basegfx::B2DPolygon aPoly
;
438 aPoly
.append( basegfx::B2DPoint( aStart
.X(), nYMiddle
) );
439 aPoly
.append( basegfx::B2DPoint( aEnd
.X(), nYMiddle
) );
440 pathObj
->SetPathPoly(basegfx::B2DPolyPolygon(aPoly
));
441 SfxItemSet
aSet( pDrawModelWrapper
->GetItemPool() );
443 pObj
->SetMergedItemSet( aSet
);
447 case ChartCommandID::DrawFreelineNoFill
:
449 if ( auto const pathObj
= dynamic_cast<SdrPathObj
*>( pObj
.get()) )
451 basegfx::B2DPolygon aInnerPoly
;
452 aInnerPoly
.append( basegfx::B2DPoint( aRect
.Left(), aRect
.Bottom() ) );
453 aInnerPoly
.appendBezierSegment(
454 basegfx::B2DPoint( aRect
.Left(), aRect
.Top() ),
455 basegfx::B2DPoint( aRect
.Center().X(), aRect
.Top() ),
456 basegfx::B2DPoint( aRect
.Center().X(), aRect
.Center().Y() ) );
457 aInnerPoly
.appendBezierSegment(
458 basegfx::B2DPoint( aRect
.Center().X(), aRect
.Bottom() ),
459 basegfx::B2DPoint( aRect
.Right(), aRect
.Bottom() ),
460 basegfx::B2DPoint( aRect
.Right(), aRect
.Top() ) );
461 basegfx::B2DPolyPolygon aPoly
;
462 aPoly
.append( aInnerPoly
);
463 pathObj
->SetPathPoly(aPoly
);
467 case ChartCommandID::DrawText
:
468 case ChartCommandID::DrawTextVertical
:
470 if ( SdrTextObj
* pTextObj
= DynCastSdrTextObj( pObj
.get()) )
472 pTextObj
->SetLogicRect( aRect
);
473 bool bVertical
= ( nID
== ChartCommandID::DrawTextVertical
);
474 pTextObj
->SetVerticalWriting( bVertical
);
477 SfxItemSet
aSet( pDrawModelWrapper
->GetItemPool() );
478 aSet
.Put( makeSdrTextAutoGrowWidthItem( true ) );
479 aSet
.Put( makeSdrTextAutoGrowHeightItem( false ) );
480 aSet
.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_TOP
) );
481 aSet
.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_RIGHT
) );
482 pTextObj
->SetMergedItemSet( aSet
);
487 case ChartCommandID::DrawCaption
:
488 case ChartCommandID::DrawCaptionVertical
:
490 if ( SdrCaptionObj
* pCaptionObj
= dynamic_cast<SdrCaptionObj
*>( pObj
.get()) )
492 bool bIsVertical( nID
== ChartCommandID::DrawCaptionVertical
);
493 pCaptionObj
->SetVerticalWriting( bIsVertical
);
496 SfxItemSet
aSet( pObj
->GetMergedItemSet() );
497 aSet
.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER
) );
498 aSet
.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_RIGHT
) );
499 pObj
->SetMergedItemSet( aSet
);
501 pCaptionObj
->SetLogicRect( aRect
);
502 pCaptionObj
->SetTailPos(
503 aRect
.TopLeft() - Point( aRect
.GetWidth() / 2, aRect
.GetHeight() / 2 ) );
509 pObj
->SetLogicRect( aRect
);
510 SfxItemSet
aSet( pDrawModelWrapper
->GetItemPool() );
511 setAttributes( pObj
.get() );
512 pObj
->SetMergedItemSet( aSet
);
523 bool DrawCommandDispatch::parseCommandURL( const OUString
& rCommandURL
, ChartCommandID
* pnFeatureId
,
524 OUString
* pBaseCommand
, OUString
* pCustomShapeType
)
527 ChartCommandID nFeatureId
= ChartCommandID::NONE
;
528 OUString aBaseCommand
;
531 sal_Int32 nIndex
= std::min(sal_Int32(1), rCommandURL
.getLength());
532 std::u16string_view aToken
= o3tl::getToken(rCommandURL
, 0, '.', nIndex
);
533 if ( nIndex
== -1 || aToken
.empty() )
535 aBaseCommand
= rCommandURL
;
536 SupportedFeatures::const_iterator aIter
= m_aSupportedFeatures
.find( aBaseCommand
);
537 if ( aIter
!= m_aSupportedFeatures
.end() )
539 nFeatureId
= aIter
->second
.nFeatureId
;
541 switch ( nFeatureId
)
543 case ChartCommandID::DrawToolboxCsBasic
:
548 case ChartCommandID::DrawToolboxCsSymbol
:
553 case ChartCommandID::DrawToolboxCsArrow
:
555 aType
= "left-right-arrow";
558 case ChartCommandID::DrawToolboxCsFlowchart
:
560 aType
= "flowchart-internal-storage";
563 case ChartCommandID::DrawToolboxCsCallout
:
565 aType
= "round-rectangular-callout";
568 case ChartCommandID::DrawToolboxCsStar
:
586 aBaseCommand
= rCommandURL
.copy( 0, nIndex
- 1 );
587 SupportedFeatures::const_iterator aIter
= m_aSupportedFeatures
.find( aBaseCommand
);
588 if ( aIter
!= m_aSupportedFeatures
.end() )
590 nFeatureId
= aIter
->second
.nFeatureId
;
591 aType
= rCommandURL
.getToken( 0, '.', nIndex
);
599 *pnFeatureId
= nFeatureId
;
600 *pBaseCommand
= aBaseCommand
;
601 *pCustomShapeType
= aType
;
608 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */