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 "drawingfragment.hxx"
22 #include <basegfx/matrix/b2dhommatrix.hxx>
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/container/XNameReplace.hpp>
26 #include <com/sun/star/document/XEventsSupplier.hpp>
27 #include <com/sun/star/drawing/XControlShape.hpp>
28 #include <com/sun/star/drawing/XShapes.hpp>
29 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
30 #include <com/sun/star/script/XEventAttacherManager.hpp>
31 #include <rtl/strbuf.hxx>
32 #include <svx/svdobj.hxx>
33 #include "drwlayer.hxx"
34 #include "userdat.hxx"
35 #include <oox/core/filterbase.hxx>
36 #include <oox/drawingml/connectorshapecontext.hxx>
37 #include <oox/drawingml/graphicshapecontext.hxx>
38 #include <oox/helper/attributelist.hxx>
39 #include <oox/helper/propertyset.hxx>
40 #include <oox/token/namespaces.hxx>
41 #include <oox/token/properties.hxx>
42 #include <oox/token/tokens.hxx>
43 #include <oox/vml/vmlshape.hxx>
44 #include <oox/vml/vmlshapecontainer.hxx>
45 #include "formulaparser.hxx"
46 #include "stylesbuffer.hxx"
47 #include "themebuffer.hxx"
48 #include "unitconverter.hxx"
49 #include "worksheetbuffer.hxx"
53 using namespace ::com::sun::star::beans
;
54 using namespace ::com::sun::star::container
;
55 using namespace ::com::sun::star::document
;
56 using namespace ::com::sun::star::drawing
;
57 using namespace ::com::sun::star::script
;
58 using namespace ::com::sun::star::table
;
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::xml::sax
;
61 using namespace ::oox::core
;
62 using namespace ::oox::drawingml
;
63 using namespace ::oox::ole
;
65 using ::com::sun::star::awt::Size
;
66 using ::com::sun::star::awt::Point
;
67 using ::com::sun::star::awt::Rectangle
;
68 using ::com::sun::star::awt::XControlModel
;
69 // no using's for ::oox::vml, that may clash with ::oox::drawingml types
71 ShapeMacroAttacher::ShapeMacroAttacher( const OUString
& rMacroName
, const Reference
< XShape
>& rxShape
) :
72 VbaMacroAttacherBase( rMacroName
),
77 void ShapeMacroAttacher::attachMacro( const OUString
& rMacroUrl
)
81 Reference
< XEventsSupplier
> xSupplier( mxShape
, UNO_QUERY_THROW
);
82 Reference
< XNameReplace
> xEvents( xSupplier
->getEvents(), UNO_SET_THROW
);
83 Sequence
< PropertyValue
> aEventProps( 2 );
84 aEventProps
[ 0 ].Name
= "EventType";
85 aEventProps
[ 0 ].Value
<<= OUString( "Script" );
86 aEventProps
[ 1 ].Name
= "Script";
87 aEventProps
[ 1 ].Value
<<= rMacroUrl
;
88 xEvents
->replaceByName( "OnClick", Any( aEventProps
) );
95 Shape::Shape( const WorksheetHelper
& rHelper
, const AttributeList
& rAttribs
, const sal_Char
* pcServiceName
) :
96 ::oox::drawingml::Shape( pcServiceName
),
97 WorksheetHelper( rHelper
)
99 OUString aMacro
= rAttribs
.getXString( XML_macro
, OUString() );
100 if( !aMacro
.isEmpty() )
101 maMacroName
= getFormulaParser().importMacroName( aMacro
);
104 void Shape::finalizeXShape( XmlFilterBase
& rFilter
, const Reference
< XShapes
>& rxShapes
)
107 getShapeProperties().getProperty( PROP_URL
) >>= sURL
;
108 getWorksheets().convertSheetNameRef( sURL
);
109 if( !maMacroName
.isEmpty() && mxShape
.is() )
111 VbaMacroAttacherRef
xAttacher( new ShapeMacroAttacher( maMacroName
, mxShape
) );
112 getBaseFilter().getVbaProject().registerMacroAttacher( xAttacher
);
114 ::oox::drawingml::Shape::finalizeXShape( rFilter
, rxShapes
);
115 if ( !sURL
.isEmpty() )
117 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape( mxShape
);
120 if ( ScMacroInfo
* pInfo
= ScDrawLayer::GetMacroInfo( pObj
, true ) )
121 pInfo
->SetHlink( sURL
);
126 GroupShapeContext::GroupShapeContext( ContextHandler2Helper
& rParent
,
127 const WorksheetHelper
& rHelper
, const ShapePtr
& rxParentShape
, const ShapePtr
& rxShape
) :
128 ShapeGroupContext( rParent
, rxParentShape
, rxShape
),
129 WorksheetHelper( rHelper
)
133 /*static*/ ContextHandlerRef
GroupShapeContext::createShapeContext( ContextHandler2Helper
& rParent
,
134 const WorksheetHelper
& rHelper
, sal_Int32 nElement
, const AttributeList
& rAttribs
,
135 const ShapePtr
& rxParentShape
, ShapePtr
* pxShape
)
139 case XDR_TOKEN( sp
):
141 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.CustomShape" ) );
142 if( pxShape
) *pxShape
= xShape
;
143 return new ShapeContext( rParent
, rxParentShape
, xShape
);
145 case XDR_TOKEN( cxnSp
):
147 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.ConnectorShape" ) );
148 if( pxShape
) *pxShape
= xShape
;
149 return new ConnectorShapeContext( rParent
, rxParentShape
, xShape
);
151 case XDR_TOKEN( pic
):
153 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.GraphicObjectShape" ) );
154 if( pxShape
) *pxShape
= xShape
;
155 return new GraphicShapeContext( rParent
, rxParentShape
, xShape
);
157 case XDR_TOKEN( graphicFrame
):
159 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.GraphicObjectShape" ) );
160 if( pxShape
) *pxShape
= xShape
;
161 return new GraphicalObjectFrameContext( rParent
, rxParentShape
, xShape
, rHelper
.getSheetType() != SHEETTYPE_CHARTSHEET
);
163 case XDR_TOKEN( grpSp
):
165 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.GroupShape" ) );
166 if( pxShape
) *pxShape
= xShape
;
167 return new GroupShapeContext( rParent
, rHelper
, rxParentShape
, xShape
);
173 ContextHandlerRef
GroupShapeContext::onCreateContext(
174 sal_Int32 nElement
, const AttributeList
& rAttribs
)
176 ContextHandlerRef xContext
= createShapeContext( *this, *this, nElement
, rAttribs
, mpGroupShapePtr
);
177 return xContext
.get() ? xContext
.get() : ShapeGroupContext::onCreateContext( nElement
, rAttribs
);
180 DrawingFragment::DrawingFragment( const WorksheetHelper
& rHelper
, const OUString
& rFragmentPath
) :
181 WorksheetFragmentBase( rHelper
, rFragmentPath
),
182 mxDrawPage( rHelper
.getDrawPage(), UNO_QUERY
)
184 OSL_ENSURE( mxDrawPage
.is(), "DrawingFragment::DrawingFragment - missing drawing page" );
187 ContextHandlerRef
DrawingFragment::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
189 switch( getCurrentElement() )
191 case XML_ROOT_CONTEXT
:
192 if( nElement
== XDR_TOKEN( wsDr
) ) return this;
195 case XDR_TOKEN( wsDr
):
198 case XDR_TOKEN( absoluteAnchor
):
199 case XDR_TOKEN( oneCellAnchor
):
200 case XDR_TOKEN( twoCellAnchor
):
201 mxAnchor
.reset( new ShapeAnchor( *this ) );
202 mxAnchor
->importAnchor( nElement
, rAttribs
);
207 case XDR_TOKEN( absoluteAnchor
):
208 case XDR_TOKEN( oneCellAnchor
):
209 case XDR_TOKEN( twoCellAnchor
):
213 case XDR_TOKEN( from
):
214 case XDR_TOKEN( to
): return this;
216 case XDR_TOKEN( pos
): if( mxAnchor
.get() ) mxAnchor
->importPos( rAttribs
); break;
217 case XDR_TOKEN( ext
): if( mxAnchor
.get() ) mxAnchor
->importExt( rAttribs
); break;
218 case XDR_TOKEN( clientData
): if( mxAnchor
.get() ) mxAnchor
->importClientData( rAttribs
); break;
220 default: return GroupShapeContext::createShapeContext( *this, *this, nElement
, rAttribs
, ShapePtr(), &mxShape
);
225 case XDR_TOKEN( from
):
226 case XDR_TOKEN( to
):
229 case XDR_TOKEN( col
):
230 case XDR_TOKEN( row
):
231 case XDR_TOKEN( colOff
):
232 case XDR_TOKEN( rowOff
): return this; // collect index in onCharacters()
239 void DrawingFragment::onCharacters( const OUString
& rChars
)
241 switch( getCurrentElement() )
243 case XDR_TOKEN( col
):
244 case XDR_TOKEN( row
):
245 case XDR_TOKEN( colOff
):
246 case XDR_TOKEN( rowOff
):
247 if( mxAnchor
.get() ) mxAnchor
->setCellPos( getCurrentElement(), getParentElement(), rChars
);
252 void DrawingFragment::onEndElement()
254 switch( getCurrentElement() )
256 case XDR_TOKEN( absoluteAnchor
):
257 case XDR_TOKEN( oneCellAnchor
):
258 case XDR_TOKEN( twoCellAnchor
):
259 if( mxDrawPage
.is() && mxShape
.get() && mxAnchor
.get() )
261 // Rotation is decided by orientation of shape determined
262 // by the anchor position given by 'twoCellAnchor'
263 if ( getCurrentElement() == XDR_TOKEN( twoCellAnchor
) )
264 mxShape
->setRotation(0);
265 EmuRectangle aShapeRectEmu
= mxAnchor
->calcAnchorRectEmu( getDrawPageSize() );
266 const bool bIsShapeVisible
= mxAnchor
->isAnchorValid();
267 if( (aShapeRectEmu
.X
>= 0) && (aShapeRectEmu
.Y
>= 0) && (aShapeRectEmu
.Width
>= 0) && (aShapeRectEmu
.Height
>= 0) )
269 // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle)
270 Rectangle
aShapeRectEmu32(
271 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.X
, 0, SAL_MAX_INT32
),
272 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.Y
, 0, SAL_MAX_INT32
),
273 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.Width
, 0, SAL_MAX_INT32
),
274 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.Height
, 0, SAL_MAX_INT32
) );
276 // Make sure to set the position and size *before* calling addShape().
277 mxShape
->setPosition(Point(aShapeRectEmu
.X
, aShapeRectEmu
.Y
));
278 mxShape
->setSize(Size(aShapeRectEmu
.Width
, aShapeRectEmu
.Height
));
280 basegfx::B2DHomMatrix aTransformation
;
281 if ( !bIsShapeVisible
)
282 mxShape
->setHidden(true);
284 mxShape
->addShape( getOoxFilter(), &getTheme(), mxDrawPage
, aTransformation
, mxShape
->getFillProperties(), &aShapeRectEmu32
);
286 /* Collect all shape positions in the WorksheetHelper base
287 class. But first, scale EMUs to 1/100 mm. */
288 Rectangle
aShapeRectHmm(
289 convertEmuToHmm( aShapeRectEmu
.X
), convertEmuToHmm( aShapeRectEmu
.Y
),
290 convertEmuToHmm( aShapeRectEmu
.Width
), convertEmuToHmm( aShapeRectEmu
.Height
) );
291 extendShapeBoundingBox( aShapeRectHmm
);
292 // set cell Anchoring
293 if ( mxAnchor
->getEditAs() != ShapeAnchor::ANCHOR_ABSOLUTE
)
295 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape( mxShape
->getXShape() );
298 ScDrawLayer::SetCellAnchoredFromPosition( *pObj
, getScDocument(), static_cast<SCTAB
>( getSheetIndex() ) );
313 class VmlFindNoteFunc
316 explicit VmlFindNoteFunc( const CellAddress
& rPos
);
317 bool operator()( const ::oox::vml::ShapeBase
& rShape
) const;
324 VmlFindNoteFunc::VmlFindNoteFunc( const CellAddress
& rPos
) :
325 mnCol( rPos
.Column
),
330 bool VmlFindNoteFunc::operator()( const ::oox::vml::ShapeBase
& rShape
) const
332 const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData();
333 return pClientData
&& (pClientData
->mnCol
== mnCol
) && (pClientData
->mnRow
== mnRow
);
338 VmlControlMacroAttacher::VmlControlMacroAttacher( const OUString
& rMacroName
,
339 const Reference
< XIndexContainer
>& rxCtrlFormIC
, sal_Int32 nCtrlIndex
, sal_Int32 nCtrlType
, sal_Int32 nDropStyle
) :
340 VbaMacroAttacherBase( rMacroName
),
341 mxCtrlFormIC( rxCtrlFormIC
),
342 mnCtrlIndex( nCtrlIndex
),
343 mnCtrlType( nCtrlType
),
344 mnDropStyle( nDropStyle
)
348 void VmlControlMacroAttacher::attachMacro( const OUString
& rMacroUrl
)
350 ScriptEventDescriptor aEventDesc
;
351 aEventDesc
.ScriptType
= "Script";
352 aEventDesc
.ScriptCode
= rMacroUrl
;
354 // editable drop downs are treated like edit boxes
355 bool bEditDropDown
= (mnCtrlType
== XML_Drop
) && (mnDropStyle
== XML_ComboEdit
);
356 sal_Int32 nCtrlType
= bEditDropDown
? XML_Edit
: mnCtrlType
;
363 aEventDesc
.ListenerType
= "XActionListener";
364 aEventDesc
.EventMethod
= "actionPerformed";
369 aEventDesc
.ListenerType
= "XMouseListener";
370 aEventDesc
.EventMethod
= "mouseReleased";
373 aEventDesc
.ListenerType
= "XTextListener";
374 aEventDesc
.EventMethod
= "textChanged";
378 aEventDesc
.ListenerType
= "XAdjustmentListener";
379 aEventDesc
.EventMethod
= "adjustmentValueChanged";
383 aEventDesc
.ListenerType
= "XChangeListener";
384 aEventDesc
.EventMethod
= "changed";
387 OSL_ENSURE( false, "VmlControlMacroAttacher::attachMacro - unexpected object type" );
393 Reference
< XEventAttacherManager
> xEventMgr( mxCtrlFormIC
, UNO_QUERY_THROW
);
394 xEventMgr
->registerScriptEvent( mnCtrlIndex
, aEventDesc
);
401 VmlDrawing::VmlDrawing( const WorksheetHelper
& rHelper
) :
402 ::oox::vml::Drawing( rHelper
.getOoxFilter(), rHelper
.getDrawPage(), ::oox::vml::VMLDRAWING_EXCEL
),
403 WorksheetHelper( rHelper
),
404 maControlConv( rHelper
.getBaseFilter().getModel(), rHelper
.getBaseFilter().getGraphicHelper() )
406 // default font for legacy listboxes and dropdowns: Tahoma, 8pt
407 maListBoxFont
.moName
= "Tahoma";
408 maListBoxFont
.moColor
= "auto";
409 maListBoxFont
.monSize
= 160;
412 const ::oox::vml::ShapeBase
* VmlDrawing::getNoteShape( const CellAddress
& rPos
) const
414 return getShapes().findShape( VmlFindNoteFunc( rPos
) );
417 bool VmlDrawing::isShapeSupported( const ::oox::vml::ShapeBase
& rShape
) const
419 const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData();
420 return !pClientData
|| (pClientData
->mnObjType
!= XML_Note
);
423 OUString
VmlDrawing::getShapeBaseName( const ::oox::vml::ShapeBase
& rShape
) const
425 if( const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData() )
427 switch( pClientData
->mnObjType
)
429 case XML_Button
: return OUString( "Button" );
430 case XML_Checkbox
: return OUString( "Check Box" );
431 case XML_Dialog
: return OUString( "Dialog Frame" );
432 case XML_Drop
: return OUString( "Drop Down" );
433 case XML_Edit
: return OUString( "Edit Box" );
434 case XML_GBox
: return OUString( "Group Box" );
435 case XML_Label
: return OUString( "Label" );
436 case XML_List
: return OUString( "List Box" );
437 case XML_Note
: return OUString( "Comment" );
438 case XML_Pict
: return (pClientData
->mbDde
|| getOleObjectInfo( rShape
.getShapeId() )) ? OUString( "Object" ) : OUString( "Picture" );
439 case XML_Radio
: return OUString( "Option Button" );
440 case XML_Scroll
: return OUString( "Scroll Bar" );
441 case XML_Spin
: return OUString( "Spinner" );
444 return ::oox::vml::Drawing::getShapeBaseName( rShape
);
447 bool VmlDrawing::convertClientAnchor( Rectangle
& orShapeRect
, const OUString
& rShapeAnchor
) const
449 if( rShapeAnchor
.isEmpty() )
451 ShapeAnchor
aAnchor( *this );
452 aAnchor
.importVmlAnchor( rShapeAnchor
);
453 orShapeRect
= aAnchor
.calcAnchorRectHmm( getDrawPageSize() );
454 return (orShapeRect
.Width
>= 0) && (orShapeRect
.Height
>= 0);
457 Reference
< XShape
> VmlDrawing::createAndInsertClientXShape( const ::oox::vml::ShapeBase
& rShape
,
458 const Reference
< XShapes
>& rxShapes
, const Rectangle
& rShapeRect
) const
460 // simulate the legacy drawing controls with OLE form controls
461 OUString aShapeName
= rShape
.getShapeName();
462 const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData();
463 if( !aShapeName
.isEmpty() && pClientData
)
465 Rectangle aShapeRect
= rShapeRect
;
466 const ::oox::vml::TextBox
* pTextBox
= rShape
.getTextBox();
467 EmbeddedControl
aControl( aShapeName
);
468 switch( pClientData
->mnObjType
)
472 AxCommandButtonModel
& rAxModel
= aControl
.createModel
< AxCommandButtonModel
>();
473 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
474 rAxModel
.mnFlags
= AX_FLAGS_ENABLED
| AX_FLAGS_OPAQUE
| AX_FLAGS_WORDWRAP
;
475 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
481 AxLabelModel
& rAxModel
= aControl
.createModel
< AxLabelModel
>();
482 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
483 rAxModel
.mnFlags
= AX_FLAGS_ENABLED
| AX_FLAGS_WORDWRAP
;
484 rAxModel
.mnBorderStyle
= AX_BORDERSTYLE_NONE
;
485 rAxModel
.mnSpecialEffect
= AX_SPECIALEFFECT_FLAT
;
486 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
492 bool bNumeric
= (pClientData
->mnVTEdit
== ::oox::vml::VML_CLIENTDATA_INTEGER
) || (pClientData
->mnVTEdit
== ::oox::vml::VML_CLIENTDATA_NUMBER
);
493 AxMorphDataModelBase
& rAxModel
= bNumeric
?
494 static_cast< AxMorphDataModelBase
& >( aControl
.createModel
< AxNumericFieldModel
>() ) :
495 static_cast< AxMorphDataModelBase
& >( aControl
.createModel
< AxTextBoxModel
>() );
496 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maValue
, pTextBox
, pClientData
->mnTextHAlign
);
497 setFlag( rAxModel
.mnFlags
, AX_FLAGS_MULTILINE
, pClientData
->mbMultiLine
);
498 setFlag( rAxModel
.mnScrollBars
, AX_SCROLLBAR_VERTICAL
, pClientData
->mbVScroll
);
499 if( pClientData
->mbSecretEdit
)
500 rAxModel
.mnPasswordChar
= '*';
506 AxFrameModel
& rAxModel
= aControl
.createModel
< AxFrameModel
>();
507 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
508 rAxModel
.mnBorderStyle
= pClientData
->mbNo3D
? AX_BORDERSTYLE_SINGLE
: AX_BORDERSTYLE_NONE
;
509 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_BUMPED
;
511 /* Move top border of groupbox up by half font height, because
512 Excel specifies Y position of the groupbox border line
513 instead the top border of the caption text. */
514 if( const ::oox::vml::TextFontModel
* pFontModel
= pTextBox
? pTextBox
->getFirstFont() : nullptr )
516 sal_Int32 nFontHeightHmm
= getUnitConverter().scaleToMm100( pFontModel
->monSize
.get( 160 ), UNIT_TWIP
);
517 sal_Int32 nYDiff
= ::std::min
< sal_Int32
>( nFontHeightHmm
/ 2, aShapeRect
.Y
);
518 aShapeRect
.Y
-= nYDiff
;
519 aShapeRect
.Height
+= nYDiff
;
526 AxCheckBoxModel
& rAxModel
= aControl
.createModel
< AxCheckBoxModel
>();
527 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
528 convertControlBackground( rAxModel
, rShape
);
529 rAxModel
.maValue
= OUString::number( pClientData
->mnChecked
);
530 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
531 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
532 bool bTriState
= (pClientData
->mnChecked
!= ::oox::vml::VML_CLIENTDATA_UNCHECKED
) && (pClientData
->mnChecked
!= ::oox::vml::VML_CLIENTDATA_CHECKED
);
533 rAxModel
.mnMultiSelect
= bTriState
? AX_SELECTION_MULTI
: AX_SELECTION_SINGLE
;
539 AxOptionButtonModel
& rAxModel
= aControl
.createModel
< AxOptionButtonModel
>();
540 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
541 convertControlBackground( rAxModel
, rShape
);
542 rAxModel
.maValue
= OUString::number( pClientData
->mnChecked
);
543 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
544 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
550 AxListBoxModel
& rAxModel
= aControl
.createModel
< AxListBoxModel
>();
551 convertControlFontData( rAxModel
.maFontData
, rAxModel
.mnTextColor
, maListBoxFont
);
552 rAxModel
.mnBorderStyle
= pClientData
->mbNo3D2
? AX_BORDERSTYLE_SINGLE
: AX_BORDERSTYLE_NONE
;
553 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D2
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
554 switch( pClientData
->mnSelType
)
556 case XML_Single
: rAxModel
.mnMultiSelect
= AX_SELECTION_SINGLE
; break;
557 case XML_Multi
: rAxModel
.mnMultiSelect
= AX_SELECTION_MULTI
; break;
558 case XML_Extend
: rAxModel
.mnMultiSelect
= AX_SELECTION_EXTENDED
; break;
565 AxComboBoxModel
& rAxModel
= aControl
.createModel
< AxComboBoxModel
>();
566 convertControlFontData( rAxModel
.maFontData
, rAxModel
.mnTextColor
, maListBoxFont
);
567 rAxModel
.mnDisplayStyle
= AX_DISPLAYSTYLE_DROPDOWN
;
568 rAxModel
.mnShowDropButton
= AX_SHOWDROPBUTTON_ALWAYS
;
569 rAxModel
.mnBorderStyle
= pClientData
->mbNo3D2
? AX_BORDERSTYLE_SINGLE
: AX_BORDERSTYLE_NONE
;
570 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D2
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
571 rAxModel
.mnListRows
= pClientData
->mnDropLines
;
577 AxSpinButtonModel
& rAxModel
= aControl
.createModel
< AxSpinButtonModel
>();
578 rAxModel
.mnMin
= pClientData
->mnMin
;
579 rAxModel
.mnMax
= pClientData
->mnMax
;
580 rAxModel
.mnPosition
= pClientData
->mnVal
;
581 rAxModel
.mnSmallChange
= pClientData
->mnInc
;
587 AxScrollBarModel
& rAxModel
= aControl
.createModel
< AxScrollBarModel
>();
588 rAxModel
.mnMin
= pClientData
->mnMin
;
589 rAxModel
.mnMax
= pClientData
->mnMax
;
590 rAxModel
.mnPosition
= pClientData
->mnVal
;
591 rAxModel
.mnSmallChange
= pClientData
->mnInc
;
592 rAxModel
.mnLargeChange
= pClientData
->mnPage
;
598 // fake with a group box
599 AxFrameModel
& rAxModel
= aControl
.createModel
< AxFrameModel
>();
600 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, XML_Left
);
601 rAxModel
.mnBorderStyle
= AX_BORDERSTYLE_SINGLE
;
602 rAxModel
.mnSpecialEffect
= AX_SPECIALEFFECT_FLAT
;
607 if( ControlModelBase
* pAxModel
= aControl
.getModel() )
609 // create the control shape
610 pAxModel
->maSize
.first
= aShapeRect
.Width
;
611 pAxModel
->maSize
.second
= aShapeRect
.Height
;
612 sal_Int32 nCtrlIndex
= -1;
613 Reference
< XShape
> xShape
= createAndInsertXControlShape( aControl
, rxShapes
, aShapeRect
, nCtrlIndex
);
615 // control shape macro
616 if( xShape
.is() && (nCtrlIndex
>= 0) && !pClientData
->maFmlaMacro
.isEmpty() )
618 OUString aMacroName
= getFormulaParser().importMacroName( pClientData
->maFmlaMacro
);
619 if( !aMacroName
.isEmpty() )
621 Reference
< XIndexContainer
> xFormIC
= getControlForm().getXForm();
622 VbaMacroAttacherRef
xAttacher( new VmlControlMacroAttacher( aMacroName
, xFormIC
, nCtrlIndex
, pClientData
->mnObjType
, pClientData
->mnDropStyle
) );
623 getBaseFilter().getVbaProject().registerMacroAttacher( xAttacher
);
631 return Reference
< XShape
>();
634 void VmlDrawing::notifyXShapeInserted( const Reference
< XShape
>& rxShape
,
635 const Rectangle
& rShapeRect
, const ::oox::vml::ShapeBase
& rShape
, bool bGroupChild
)
637 // collect all shape positions in the WorksheetHelper base class (but not children of group shapes)
639 extendShapeBoundingBox( rShapeRect
);
641 // convert settings from VML client data
642 if( const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData() )
644 // specific settings for embedded form controls
647 Reference
< XControlShape
> xCtrlShape( rxShape
, UNO_QUERY_THROW
);
648 Reference
< XControlModel
> xCtrlModel( xCtrlShape
->getControl(), UNO_SET_THROW
);
649 PropertySet
aPropSet( xCtrlModel
);
652 aPropSet
.setProperty( PROP_Printable
, pClientData
->mbPrintObject
);
654 // control source links
655 if( !pClientData
->maFmlaLink
.isEmpty() || !pClientData
->maFmlaRange
.isEmpty() )
656 maControlConv
.bindToSources( xCtrlModel
, pClientData
->maFmlaLink
, pClientData
->maFmlaRange
, getSheetIndex() );
664 // private --------------------------------------------------------------------
666 sal_uInt32
VmlDrawing::convertControlTextColor( const OUString
& rTextColor
) const
668 // color attribute not present or 'auto' - use passed default color
669 if( rTextColor
.isEmpty() || rTextColor
.equalsIgnoreAsciiCase( "auto" ) )
670 return AX_SYSCOLOR_WINDOWTEXT
;
672 if( rTextColor
[ 0 ] == '#' )
674 // RGB colors in the format '#RRGGBB'
675 if( rTextColor
.getLength() == 7 )
676 return OleHelper::encodeOleColor( rTextColor
.copy( 1 ).toUInt32( 16 ) );
678 // RGB colors in the format '#RGB'
679 if( rTextColor
.getLength() == 4 )
681 sal_Int32 nR
= rTextColor
.copy( 1, 1 ).toUInt32( 16 ) * 0x11;
682 sal_Int32 nG
= rTextColor
.copy( 2, 1 ).toUInt32( 16 ) * 0x11;
683 sal_Int32 nB
= rTextColor
.copy( 3, 1 ).toUInt32( 16 ) * 0x11;
684 return OleHelper::encodeOleColor( (nR
<< 16) | (nG
<< 8) | nB
);
687 OSL_ENSURE( false, OStringBuffer( "VmlDrawing::convertControlTextColor - invalid color name '" ).
688 append( OUStringToOString( rTextColor
, RTL_TEXTENCODING_ASCII_US
) ).append( '\'' ).getStr() );
689 return AX_SYSCOLOR_WINDOWTEXT
;
692 const GraphicHelper
& rGraphicHelper
= getBaseFilter().getGraphicHelper();
694 /* Predefined color names or system color names (resolve to RGB to detect
695 valid color name). */
696 sal_Int32 nColorToken
= AttributeConversion::decodeToken( rTextColor
);
697 sal_Int32 nRgbValue
= Color::getVmlPresetColor( nColorToken
, API_RGB_TRANSPARENT
);
698 if( nRgbValue
== API_RGB_TRANSPARENT
)
699 nRgbValue
= rGraphicHelper
.getSystemColor( nColorToken
);
700 if( nRgbValue
!= API_RGB_TRANSPARENT
)
701 return OleHelper::encodeOleColor( nRgbValue
);
704 return OleHelper::encodeOleColor( rGraphicHelper
.getPaletteColor( rTextColor
.toInt32() ) );
707 void VmlDrawing::convertControlFontData( AxFontData
& rAxFontData
, sal_uInt32
& rnOleTextColor
, const ::oox::vml::TextFontModel
& rFontModel
) const
709 if( rFontModel
.moName
.has() )
710 rAxFontData
.maFontName
= rFontModel
.moName
.get();
712 // font height: convert from twips to points, then to internal representation of AX controls
713 rAxFontData
.setHeightPoints( static_cast< sal_Int16
>( (rFontModel
.monSize
.get( 200 ) + 10) / 20 ) );
716 rAxFontData
.mnFontEffects
= 0;
717 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_BOLD
, rFontModel
.mobBold
.get( false ) );
718 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_ITALIC
, rFontModel
.mobItalic
.get( false ) );
719 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_STRIKEOUT
, rFontModel
.mobStrikeout
.get( false ) );
720 sal_Int32 nUnderline
= rFontModel
.monUnderline
.get( XML_none
);
721 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_UNDERLINE
, nUnderline
!= XML_none
);
722 rAxFontData
.mbDblUnderline
= nUnderline
== XML_double
;
725 rnOleTextColor
= convertControlTextColor( rFontModel
.moColor
.get( OUString() ) );
728 void VmlDrawing::convertControlText( AxFontData
& rAxFontData
, sal_uInt32
& rnOleTextColor
,
729 OUString
& rCaption
, const ::oox::vml::TextBox
* pTextBox
, sal_Int32 nTextHAlign
) const
733 rCaption
= pTextBox
->getText();
734 if( const ::oox::vml::TextFontModel
* pFontModel
= pTextBox
->getFirstFont() )
735 convertControlFontData( rAxFontData
, rnOleTextColor
, *pFontModel
);
738 switch( nTextHAlign
)
740 case XML_Left
: rAxFontData
.mnHorAlign
= AX_FONTDATA_LEFT
; break;
741 case XML_Center
: rAxFontData
.mnHorAlign
= AX_FONTDATA_CENTER
; break;
742 case XML_Right
: rAxFontData
.mnHorAlign
= AX_FONTDATA_RIGHT
; break;
743 default: rAxFontData
.mnHorAlign
= AX_FONTDATA_LEFT
;
747 void VmlDrawing::convertControlBackground( AxMorphDataModelBase
& rAxModel
, const ::oox::vml::ShapeBase
& rShape
) const
749 const ::oox::vml::FillModel
& rFillModel
= rShape
.getTypeModel().maFillModel
;
750 bool bHasFill
= rFillModel
.moFilled
.get( true );
751 setFlag( rAxModel
.mnFlags
, AX_FLAGS_OPAQUE
, bHasFill
);
754 const GraphicHelper
& rGraphicHelper
= getBaseFilter().getGraphicHelper();
755 sal_Int32 nSysWindowColor
= rGraphicHelper
.getSystemColor( XML_window
, API_RGB_WHITE
);
756 ::oox::drawingml::Color aColor
= ::oox::vml::ConversionHelper::decodeColor( rGraphicHelper
, rFillModel
.moColor
, rFillModel
.moOpacity
, nSysWindowColor
);
757 sal_Int32 nRgbValue
= aColor
.getColor( rGraphicHelper
);
758 rAxModel
.mnBackColor
= OleHelper::encodeOleColor( nRgbValue
);
762 VmlDrawingFragment::VmlDrawingFragment( const WorksheetHelper
& rHelper
, const OUString
& rFragmentPath
) :
763 ::oox::vml::DrawingFragment( rHelper
.getOoxFilter(), rFragmentPath
, rHelper
.getVmlDrawing() ),
764 WorksheetHelper( rHelper
)
768 void VmlDrawingFragment::finalizeImport()
770 ::oox::vml::DrawingFragment::finalizeImport();
771 getVmlDrawing().convertAndInsert();
777 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */