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 <com/sun/star/beans/PropertyValue.hpp>
23 #include <com/sun/star/container/XNameReplace.hpp>
24 #include <com/sun/star/document/XEventsSupplier.hpp>
25 #include <com/sun/star/drawing/XControlShape.hpp>
26 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
27 #include <com/sun/star/script/XEventAttacherManager.hpp>
28 #include <rtl/strbuf.hxx>
29 #include <svx/svdobj.hxx>
30 #include "drwlayer.hxx"
31 #include "userdat.hxx"
32 #include <oox/drawingml/connectorshapecontext.hxx>
33 #include <oox/drawingml/graphicshapecontext.hxx>
34 #include <oox/helper/attributelist.hxx>
35 #include <oox/helper/propertyset.hxx>
36 #include <oox/vml/vmlshape.hxx>
37 #include <oox/vml/vmlshapecontainer.hxx>
38 #include "formulaparser.hxx"
39 #include "stylesbuffer.hxx"
40 #include "themebuffer.hxx"
41 #include "unitconverter.hxx"
42 #include "worksheetbuffer.hxx"
46 using namespace ::com::sun::star::beans
;
47 using namespace ::com::sun::star::container
;
48 using namespace ::com::sun::star::document
;
49 using namespace ::com::sun::star::drawing
;
50 using namespace ::com::sun::star::script
;
51 using namespace ::com::sun::star::table
;
52 using namespace ::com::sun::star::uno
;
53 using namespace ::com::sun::star::xml::sax
;
54 using namespace ::oox::core
;
55 using namespace ::oox::drawingml
;
56 using namespace ::oox::ole
;
58 using ::com::sun::star::awt::Size
;
59 using ::com::sun::star::awt::Point
;
60 using ::com::sun::star::awt::Rectangle
;
61 using ::com::sun::star::awt::XControlModel
;
62 // no using's for ::oox::vml, that may clash with ::oox::drawingml types
64 ShapeMacroAttacher::ShapeMacroAttacher( const OUString
& rMacroName
, const Reference
< XShape
>& rxShape
) :
65 VbaMacroAttacherBase( rMacroName
),
70 void ShapeMacroAttacher::attachMacro( const OUString
& rMacroUrl
)
74 Reference
< XEventsSupplier
> xSupplier( mxShape
, UNO_QUERY_THROW
);
75 Reference
< XNameReplace
> xEvents( xSupplier
->getEvents(), UNO_SET_THROW
);
76 Sequence
< PropertyValue
> aEventProps( 2 );
77 aEventProps
[ 0 ].Name
= "EventType";
78 aEventProps
[ 0 ].Value
<<= OUString( "Script" );
79 aEventProps
[ 1 ].Name
= "Script";
80 aEventProps
[ 1 ].Value
<<= rMacroUrl
;
81 xEvents
->replaceByName( "OnClick", Any( aEventProps
) );
88 Shape::Shape( const WorksheetHelper
& rHelper
, const AttributeList
& rAttribs
, const sal_Char
* pcServiceName
) :
89 ::oox::drawingml::Shape( pcServiceName
),
90 WorksheetHelper( rHelper
)
92 OUString aMacro
= rAttribs
.getXString( XML_macro
, OUString() );
93 if( !aMacro
.isEmpty() )
94 maMacroName
= getFormulaParser().importMacroName( aMacro
);
97 void Shape::finalizeXShape( XmlFilterBase
& rFilter
, const Reference
< XShapes
>& rxShapes
)
100 getShapeProperties().getProperty( PROP_URL
) >>= sURL
;
101 getWorksheets().convertSheetNameRef( sURL
);
102 if( !maMacroName
.isEmpty() && mxShape
.is() )
104 VbaMacroAttacherRef
xAttacher( new ShapeMacroAttacher( maMacroName
, mxShape
) );
105 getBaseFilter().getVbaProject().registerMacroAttacher( xAttacher
);
107 ::oox::drawingml::Shape::finalizeXShape( rFilter
, rxShapes
);
108 if ( !sURL
.isEmpty() )
110 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape( mxShape
);
113 if ( ScMacroInfo
* pInfo
= ScDrawLayer::GetMacroInfo( pObj
, true ) )
114 pInfo
->SetHlink( sURL
);
119 GroupShapeContext::GroupShapeContext( ContextHandler2Helper
& rParent
,
120 const WorksheetHelper
& rHelper
, const ShapePtr
& rxParentShape
, const ShapePtr
& rxShape
) :
121 ShapeGroupContext( rParent
, rxParentShape
, rxShape
),
122 WorksheetHelper( rHelper
)
126 /*static*/ ContextHandlerRef
GroupShapeContext::createShapeContext( ContextHandler2Helper
& rParent
,
127 const WorksheetHelper
& rHelper
, sal_Int32 nElement
, const AttributeList
& rAttribs
,
128 const ShapePtr
& rxParentShape
, ShapePtr
* pxShape
)
132 case XDR_TOKEN( sp
):
134 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.CustomShape" ) );
135 if( pxShape
) *pxShape
= xShape
;
136 return new ShapeContext( rParent
, rxParentShape
, xShape
);
138 case XDR_TOKEN( cxnSp
):
140 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.ConnectorShape" ) );
141 if( pxShape
) *pxShape
= xShape
;
142 return new ConnectorShapeContext( rParent
, rxParentShape
, xShape
);
144 case XDR_TOKEN( pic
):
146 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.GraphicObjectShape" ) );
147 if( pxShape
) *pxShape
= xShape
;
148 return new GraphicShapeContext( rParent
, rxParentShape
, xShape
);
150 case XDR_TOKEN( graphicFrame
):
152 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.GraphicObjectShape" ) );
153 if( pxShape
) *pxShape
= xShape
;
154 return new GraphicalObjectFrameContext( rParent
, rxParentShape
, xShape
, rHelper
.getSheetType() != SHEETTYPE_CHARTSHEET
);
156 case XDR_TOKEN( grpSp
):
158 ShapePtr
xShape( new Shape( rHelper
, rAttribs
, "com.sun.star.drawing.GroupShape" ) );
159 if( pxShape
) *pxShape
= xShape
;
160 return new GroupShapeContext( rParent
, rHelper
, rxParentShape
, xShape
);
166 ContextHandlerRef
GroupShapeContext::onCreateContext(
167 sal_Int32 nElement
, const AttributeList
& rAttribs
)
169 ContextHandlerRef xContext
= createShapeContext( *this, *this, nElement
, rAttribs
, mpGroupShapePtr
);
170 return xContext
.get() ? xContext
.get() : ShapeGroupContext::onCreateContext( nElement
, rAttribs
);
173 DrawingFragment::DrawingFragment( const WorksheetHelper
& rHelper
, const OUString
& rFragmentPath
) :
174 WorksheetFragmentBase( rHelper
, rFragmentPath
),
175 mxDrawPage( rHelper
.getDrawPage(), UNO_QUERY
)
177 OSL_ENSURE( mxDrawPage
.is(), "DrawingFragment::DrawingFragment - missing drawing page" );
180 ContextHandlerRef
DrawingFragment::onCreateContext( sal_Int32 nElement
, const AttributeList
& rAttribs
)
182 switch( getCurrentElement() )
184 case XML_ROOT_CONTEXT
:
185 if( nElement
== XDR_TOKEN( wsDr
) ) return this;
188 case XDR_TOKEN( wsDr
):
191 case XDR_TOKEN( absoluteAnchor
):
192 case XDR_TOKEN( oneCellAnchor
):
193 case XDR_TOKEN( twoCellAnchor
):
194 mxAnchor
.reset( new ShapeAnchor( *this ) );
195 mxAnchor
->importAnchor( nElement
, rAttribs
);
200 case XDR_TOKEN( absoluteAnchor
):
201 case XDR_TOKEN( oneCellAnchor
):
202 case XDR_TOKEN( twoCellAnchor
):
206 case XDR_TOKEN( from
):
207 case XDR_TOKEN( to
): return this;
209 case XDR_TOKEN( pos
): if( mxAnchor
.get() ) mxAnchor
->importPos( rAttribs
); break;
210 case XDR_TOKEN( ext
): if( mxAnchor
.get() ) mxAnchor
->importExt( rAttribs
); break;
211 case XDR_TOKEN( clientData
): if( mxAnchor
.get() ) mxAnchor
->importClientData( rAttribs
); break;
213 default: return GroupShapeContext::createShapeContext( *this, *this, nElement
, rAttribs
, ShapePtr(), &mxShape
);
218 case XDR_TOKEN( from
):
219 case XDR_TOKEN( to
):
222 case XDR_TOKEN( col
):
223 case XDR_TOKEN( row
):
224 case XDR_TOKEN( colOff
):
225 case XDR_TOKEN( rowOff
): return this; // collect index in onCharacters()
232 void DrawingFragment::onCharacters( const OUString
& rChars
)
234 switch( getCurrentElement() )
236 case XDR_TOKEN( col
):
237 case XDR_TOKEN( row
):
238 case XDR_TOKEN( colOff
):
239 case XDR_TOKEN( rowOff
):
240 if( mxAnchor
.get() ) mxAnchor
->setCellPos( getCurrentElement(), getParentElement(), rChars
);
245 void DrawingFragment::onEndElement()
247 switch( getCurrentElement() )
249 case XDR_TOKEN( absoluteAnchor
):
250 case XDR_TOKEN( oneCellAnchor
):
251 case XDR_TOKEN( twoCellAnchor
):
252 if( mxDrawPage
.is() && mxShape
.get() && mxAnchor
.get() )
254 // Rotation is decided by orientation of shape determined
255 // by the anchor position given by 'twoCellAnchor'
256 if ( getCurrentElement() == XDR_TOKEN( twoCellAnchor
) )
257 mxShape
->setRotation(0);
258 EmuRectangle aShapeRectEmu
= mxAnchor
->calcAnchorRectEmu( getDrawPageSize() );
259 if( (aShapeRectEmu
.X
>= 0) && (aShapeRectEmu
.Y
>= 0) && (aShapeRectEmu
.Width
>= 0) && (aShapeRectEmu
.Height
>= 0) )
261 // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle)
262 Rectangle
aShapeRectEmu32(
263 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.X
, 0, SAL_MAX_INT32
),
264 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.Y
, 0, SAL_MAX_INT32
),
265 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.Width
, 0, SAL_MAX_INT32
),
266 getLimitedValue
< sal_Int32
, sal_Int64
>( aShapeRectEmu
.Height
, 0, SAL_MAX_INT32
) );
268 // Make sure to set the position and size *before* calling addShape().
269 mxShape
->setPosition(Point(aShapeRectEmu
.X
, aShapeRectEmu
.Y
));
270 mxShape
->setSize(Size(aShapeRectEmu
.Width
, aShapeRectEmu
.Height
));
272 basegfx::B2DHomMatrix aTransformation
;
273 mxShape
->addShape( getOoxFilter(), &getTheme(), mxDrawPage
, aTransformation
, mxShape
->getFillProperties(), &aShapeRectEmu32
);
275 /* Collect all shape positions in the WorksheetHelper base
276 class. But first, scale EMUs to 1/100 mm. */
277 Rectangle
aShapeRectHmm(
278 convertEmuToHmm( aShapeRectEmu
.X
), convertEmuToHmm( aShapeRectEmu
.Y
),
279 convertEmuToHmm( aShapeRectEmu
.Width
), convertEmuToHmm( aShapeRectEmu
.Height
) );
280 extendShapeBoundingBox( aShapeRectHmm
);
281 // set cell Anchoring
282 if ( mxAnchor
->getEditAs() != ShapeAnchor::ANCHOR_ABSOLUTE
)
284 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape( mxShape
->getXShape() );
287 ScDrawLayer::SetCellAnchoredFromPosition( *pObj
, getScDocument(), static_cast<SCTAB
>( getSheetIndex() ) );
302 class VmlFindNoteFunc
305 explicit VmlFindNoteFunc( const CellAddress
& rPos
);
306 bool operator()( const ::oox::vml::ShapeBase
& rShape
) const;
313 VmlFindNoteFunc::VmlFindNoteFunc( const CellAddress
& rPos
) :
314 mnCol( rPos
.Column
),
319 bool VmlFindNoteFunc::operator()( const ::oox::vml::ShapeBase
& rShape
) const
321 const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData();
322 return pClientData
&& (pClientData
->mnCol
== mnCol
) && (pClientData
->mnRow
== mnRow
);
327 VmlControlMacroAttacher::VmlControlMacroAttacher( const OUString
& rMacroName
,
328 const Reference
< XIndexContainer
>& rxCtrlFormIC
, sal_Int32 nCtrlIndex
, sal_Int32 nCtrlType
, sal_Int32 nDropStyle
) :
329 VbaMacroAttacherBase( rMacroName
),
330 mxCtrlFormIC( rxCtrlFormIC
),
331 mnCtrlIndex( nCtrlIndex
),
332 mnCtrlType( nCtrlType
),
333 mnDropStyle( nDropStyle
)
337 void VmlControlMacroAttacher::attachMacro( const OUString
& rMacroUrl
)
339 ScriptEventDescriptor aEventDesc
;
340 aEventDesc
.ScriptType
= "Script";
341 aEventDesc
.ScriptCode
= rMacroUrl
;
343 // editable drop downs are treated like edit boxes
344 bool bEditDropDown
= (mnCtrlType
== XML_Drop
) && (mnDropStyle
== XML_ComboEdit
);
345 sal_Int32 nCtrlType
= bEditDropDown
? XML_Edit
: mnCtrlType
;
352 aEventDesc
.ListenerType
= "XActionListener";
353 aEventDesc
.EventMethod
= "actionPerformed";
358 aEventDesc
.ListenerType
= "XMouseListener";
359 aEventDesc
.EventMethod
= "mouseReleased";
362 aEventDesc
.ListenerType
= "XTextListener";
363 aEventDesc
.EventMethod
= "textChanged";
367 aEventDesc
.ListenerType
= "XAdjustmentListener";
368 aEventDesc
.EventMethod
= "adjustmentValueChanged";
372 aEventDesc
.ListenerType
= "XChangeListener";
373 aEventDesc
.EventMethod
= "changed";
376 OSL_ENSURE( false, "VmlControlMacroAttacher::attachMacro - unexpected object type" );
382 Reference
< XEventAttacherManager
> xEventMgr( mxCtrlFormIC
, UNO_QUERY_THROW
);
383 xEventMgr
->registerScriptEvent( mnCtrlIndex
, aEventDesc
);
390 VmlDrawing::VmlDrawing( const WorksheetHelper
& rHelper
) :
391 ::oox::vml::Drawing( rHelper
.getOoxFilter(), rHelper
.getDrawPage(), ::oox::vml::VMLDRAWING_EXCEL
),
392 WorksheetHelper( rHelper
),
393 maControlConv( rHelper
.getBaseFilter().getModel(), rHelper
.getBaseFilter().getGraphicHelper() )
395 // default font for legacy listboxes and dropdowns: Tahoma, 8pt
396 maListBoxFont
.moName
= "Tahoma";
397 maListBoxFont
.moColor
= "auto";
398 maListBoxFont
.monSize
= 160;
401 const ::oox::vml::ShapeBase
* VmlDrawing::getNoteShape( const CellAddress
& rPos
) const
403 return getShapes().findShape( VmlFindNoteFunc( rPos
) );
406 bool VmlDrawing::isShapeSupported( const ::oox::vml::ShapeBase
& rShape
) const
408 const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData();
409 return !pClientData
|| (pClientData
->mnObjType
!= XML_Note
);
412 OUString
VmlDrawing::getShapeBaseName( const ::oox::vml::ShapeBase
& rShape
) const
414 if( const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData() )
416 switch( pClientData
->mnObjType
)
418 case XML_Button
: return OUString( "Button" );
419 case XML_Checkbox
: return OUString( "Check Box" );
420 case XML_Dialog
: return OUString( "Dialog Frame" );
421 case XML_Drop
: return OUString( "Drop Down" );
422 case XML_Edit
: return OUString( "Edit Box" );
423 case XML_GBox
: return OUString( "Group Box" );
424 case XML_Label
: return OUString( "Label" );
425 case XML_List
: return OUString( "List Box" );
426 case XML_Note
: return OUString( "Comment" );
427 case XML_Pict
: return (pClientData
->mbDde
|| getOleObjectInfo( rShape
.getShapeId() )) ? OUString( "Object" ) : OUString( "Picture" );
428 case XML_Radio
: return OUString( "Option Button" );
429 case XML_Scroll
: return OUString( "Scroll Bar" );
430 case XML_Spin
: return OUString( "Spinner" );
433 return ::oox::vml::Drawing::getShapeBaseName( rShape
);
436 bool VmlDrawing::convertClientAnchor( Rectangle
& orShapeRect
, const OUString
& rShapeAnchor
) const
438 if( rShapeAnchor
.isEmpty() )
440 ShapeAnchor
aAnchor( *this );
441 aAnchor
.importVmlAnchor( rShapeAnchor
);
442 orShapeRect
= aAnchor
.calcAnchorRectHmm( getDrawPageSize() );
443 return (orShapeRect
.Width
>= 0) && (orShapeRect
.Height
>= 0);
446 Reference
< XShape
> VmlDrawing::createAndInsertClientXShape( const ::oox::vml::ShapeBase
& rShape
,
447 const Reference
< XShapes
>& rxShapes
, const Rectangle
& rShapeRect
) const
449 // simulate the legacy drawing controls with OLE form controls
450 OUString aShapeName
= rShape
.getShapeName();
451 const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData();
452 if( !aShapeName
.isEmpty() && pClientData
)
454 Rectangle aShapeRect
= rShapeRect
;
455 const ::oox::vml::TextBox
* pTextBox
= rShape
.getTextBox();
456 EmbeddedControl
aControl( aShapeName
);
457 switch( pClientData
->mnObjType
)
461 AxCommandButtonModel
& rAxModel
= aControl
.createModel
< AxCommandButtonModel
>();
462 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
463 rAxModel
.mnFlags
= AX_FLAGS_ENABLED
| AX_FLAGS_OPAQUE
| AX_FLAGS_WORDWRAP
;
464 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
470 AxLabelModel
& rAxModel
= aControl
.createModel
< AxLabelModel
>();
471 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
472 rAxModel
.mnFlags
= AX_FLAGS_ENABLED
| AX_FLAGS_WORDWRAP
;
473 rAxModel
.mnBorderStyle
= AX_BORDERSTYLE_NONE
;
474 rAxModel
.mnSpecialEffect
= AX_SPECIALEFFECT_FLAT
;
475 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
481 bool bNumeric
= (pClientData
->mnVTEdit
== ::oox::vml::VML_CLIENTDATA_INTEGER
) || (pClientData
->mnVTEdit
== ::oox::vml::VML_CLIENTDATA_NUMBER
);
482 AxMorphDataModelBase
& rAxModel
= bNumeric
?
483 static_cast< AxMorphDataModelBase
& >( aControl
.createModel
< AxNumericFieldModel
>() ) :
484 static_cast< AxMorphDataModelBase
& >( aControl
.createModel
< AxTextBoxModel
>() );
485 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maValue
, pTextBox
, pClientData
->mnTextHAlign
);
486 setFlag( rAxModel
.mnFlags
, AX_FLAGS_MULTILINE
, pClientData
->mbMultiLine
);
487 setFlag( rAxModel
.mnScrollBars
, AX_SCROLLBAR_VERTICAL
, pClientData
->mbVScroll
);
488 if( pClientData
->mbSecretEdit
)
489 rAxModel
.mnPasswordChar
= '*';
495 AxFrameModel
& rAxModel
= aControl
.createModel
< AxFrameModel
>();
496 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
497 rAxModel
.mnBorderStyle
= pClientData
->mbNo3D
? AX_BORDERSTYLE_SINGLE
: AX_BORDERSTYLE_NONE
;
498 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_BUMPED
;
500 /* Move top border of groupbox up by half font height, because
501 Excel specifies Y position of the groupbox border line
502 instead the top border of the caption text. */
503 if( const ::oox::vml::TextFontModel
* pFontModel
= pTextBox
? pTextBox
->getFirstFont() : 0 )
505 sal_Int32 nFontHeightHmm
= getUnitConverter().scaleToMm100( pFontModel
->monSize
.get( 160 ), UNIT_TWIP
);
506 sal_Int32 nYDiff
= ::std::min
< sal_Int32
>( nFontHeightHmm
/ 2, aShapeRect
.Y
);
507 aShapeRect
.Y
-= nYDiff
;
508 aShapeRect
.Height
+= nYDiff
;
515 AxCheckBoxModel
& rAxModel
= aControl
.createModel
< AxCheckBoxModel
>();
516 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
517 convertControlBackground( rAxModel
, rShape
);
518 rAxModel
.maValue
= OUString::number( pClientData
->mnChecked
);
519 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
520 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
521 bool bTriState
= (pClientData
->mnChecked
!= ::oox::vml::VML_CLIENTDATA_UNCHECKED
) && (pClientData
->mnChecked
!= ::oox::vml::VML_CLIENTDATA_CHECKED
);
522 rAxModel
.mnMultiSelect
= bTriState
? AX_SELECTION_MULTI
: AX_SELECTION_SINGLE
;
528 AxOptionButtonModel
& rAxModel
= aControl
.createModel
< AxOptionButtonModel
>();
529 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, pClientData
->mnTextHAlign
);
530 convertControlBackground( rAxModel
, rShape
);
531 rAxModel
.maValue
= OUString::number( pClientData
->mnChecked
);
532 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
533 rAxModel
.mnVerticalAlign
= pClientData
->mnTextVAlign
;
539 AxListBoxModel
& rAxModel
= aControl
.createModel
< AxListBoxModel
>();
540 convertControlFontData( rAxModel
.maFontData
, rAxModel
.mnTextColor
, maListBoxFont
);
541 rAxModel
.mnBorderStyle
= pClientData
->mbNo3D2
? AX_BORDERSTYLE_SINGLE
: AX_BORDERSTYLE_NONE
;
542 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D2
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
543 switch( pClientData
->mnSelType
)
545 case XML_Single
: rAxModel
.mnMultiSelect
= AX_SELECTION_SINGLE
; break;
546 case XML_Multi
: rAxModel
.mnMultiSelect
= AX_SELECTION_MULTI
; break;
547 case XML_Extend
: rAxModel
.mnMultiSelect
= AX_SELECTION_EXTENDED
; break;
554 AxComboBoxModel
& rAxModel
= aControl
.createModel
< AxComboBoxModel
>();
555 convertControlFontData( rAxModel
.maFontData
, rAxModel
.mnTextColor
, maListBoxFont
);
556 rAxModel
.mnDisplayStyle
= AX_DISPLAYSTYLE_DROPDOWN
;
557 rAxModel
.mnShowDropButton
= AX_SHOWDROPBUTTON_ALWAYS
;
558 rAxModel
.mnBorderStyle
= pClientData
->mbNo3D2
? AX_BORDERSTYLE_SINGLE
: AX_BORDERSTYLE_NONE
;
559 rAxModel
.mnSpecialEffect
= pClientData
->mbNo3D2
? AX_SPECIALEFFECT_FLAT
: AX_SPECIALEFFECT_SUNKEN
;
560 rAxModel
.mnListRows
= pClientData
->mnDropLines
;
566 AxSpinButtonModel
& rAxModel
= aControl
.createModel
< AxSpinButtonModel
>();
567 rAxModel
.mnMin
= pClientData
->mnMin
;
568 rAxModel
.mnMax
= pClientData
->mnMax
;
569 rAxModel
.mnPosition
= pClientData
->mnVal
;
570 rAxModel
.mnSmallChange
= pClientData
->mnInc
;
576 AxScrollBarModel
& rAxModel
= aControl
.createModel
< AxScrollBarModel
>();
577 rAxModel
.mnMin
= pClientData
->mnMin
;
578 rAxModel
.mnMax
= pClientData
->mnMax
;
579 rAxModel
.mnPosition
= pClientData
->mnVal
;
580 rAxModel
.mnSmallChange
= pClientData
->mnInc
;
581 rAxModel
.mnLargeChange
= pClientData
->mnPage
;
587 // fake with a group box
588 AxFrameModel
& rAxModel
= aControl
.createModel
< AxFrameModel
>();
589 convertControlText( rAxModel
.maFontData
, rAxModel
.mnTextColor
, rAxModel
.maCaption
, pTextBox
, XML_Left
);
590 rAxModel
.mnBorderStyle
= AX_BORDERSTYLE_SINGLE
;
591 rAxModel
.mnSpecialEffect
= AX_SPECIALEFFECT_FLAT
;
596 if( ControlModelBase
* pAxModel
= aControl
.getModel() )
598 // create the control shape
599 pAxModel
->maSize
.first
= aShapeRect
.Width
;
600 pAxModel
->maSize
.second
= aShapeRect
.Height
;
601 sal_Int32 nCtrlIndex
= -1;
602 Reference
< XShape
> xShape
= createAndInsertXControlShape( aControl
, rxShapes
, aShapeRect
, nCtrlIndex
);
604 // control shape macro
605 if( xShape
.is() && (nCtrlIndex
>= 0) && !pClientData
->maFmlaMacro
.isEmpty() )
607 OUString aMacroName
= getFormulaParser().importMacroName( pClientData
->maFmlaMacro
);
608 if( !aMacroName
.isEmpty() )
610 Reference
< XIndexContainer
> xFormIC
= getControlForm().getXForm();
611 VbaMacroAttacherRef
xAttacher( new VmlControlMacroAttacher( aMacroName
, xFormIC
, nCtrlIndex
, pClientData
->mnObjType
, pClientData
->mnDropStyle
) );
612 getBaseFilter().getVbaProject().registerMacroAttacher( xAttacher
);
620 return Reference
< XShape
>();
623 void VmlDrawing::notifyXShapeInserted( const Reference
< XShape
>& rxShape
,
624 const Rectangle
& rShapeRect
, const ::oox::vml::ShapeBase
& rShape
, bool bGroupChild
)
626 // collect all shape positions in the WorksheetHelper base class (but not children of group shapes)
628 extendShapeBoundingBox( rShapeRect
);
630 // convert settings from VML client data
631 if( const ::oox::vml::ClientData
* pClientData
= rShape
.getClientData() )
633 // specific settings for embedded form controls
636 Reference
< XControlShape
> xCtrlShape( rxShape
, UNO_QUERY_THROW
);
637 Reference
< XControlModel
> xCtrlModel( xCtrlShape
->getControl(), UNO_SET_THROW
);
638 PropertySet
aPropSet( xCtrlModel
);
641 aPropSet
.setProperty( PROP_Printable
, pClientData
->mbPrintObject
);
643 // control source links
644 if( !pClientData
->maFmlaLink
.isEmpty() || !pClientData
->maFmlaRange
.isEmpty() )
645 maControlConv
.bindToSources( xCtrlModel
, pClientData
->maFmlaLink
, pClientData
->maFmlaRange
, getSheetIndex() );
653 // private --------------------------------------------------------------------
655 sal_uInt32
VmlDrawing::convertControlTextColor( const OUString
& rTextColor
) const
657 // color attribute not present or 'auto' - use passed default color
658 if( rTextColor
.isEmpty() || rTextColor
.equalsIgnoreAsciiCase( "auto" ) )
659 return AX_SYSCOLOR_WINDOWTEXT
;
661 if( rTextColor
[ 0 ] == '#' )
663 // RGB colors in the format '#RRGGBB'
664 if( rTextColor
.getLength() == 7 )
665 return OleHelper::encodeOleColor( rTextColor
.copy( 1 ).toUInt32( 16 ) );
667 // RGB colors in the format '#RGB'
668 if( rTextColor
.getLength() == 4 )
670 sal_Int32 nR
= rTextColor
.copy( 1, 1 ).toUInt32( 16 ) * 0x11;
671 sal_Int32 nG
= rTextColor
.copy( 2, 1 ).toUInt32( 16 ) * 0x11;
672 sal_Int32 nB
= rTextColor
.copy( 3, 1 ).toUInt32( 16 ) * 0x11;
673 return OleHelper::encodeOleColor( (nR
<< 16) | (nG
<< 8) | nB
);
676 OSL_ENSURE( false, OStringBuffer( "VmlDrawing::convertControlTextColor - invalid color name '" ).
677 append( OUStringToOString( rTextColor
, RTL_TEXTENCODING_ASCII_US
) ).append( '\'' ).getStr() );
678 return AX_SYSCOLOR_WINDOWTEXT
;
681 const GraphicHelper
& rGraphicHelper
= getBaseFilter().getGraphicHelper();
683 /* Predefined color names or system color names (resolve to RGB to detect
684 valid color name). */
685 sal_Int32 nColorToken
= AttributeConversion::decodeToken( rTextColor
);
686 sal_Int32 nRgbValue
= Color::getVmlPresetColor( nColorToken
, API_RGB_TRANSPARENT
);
687 if( nRgbValue
== API_RGB_TRANSPARENT
)
688 nRgbValue
= rGraphicHelper
.getSystemColor( nColorToken
, API_RGB_TRANSPARENT
);
689 if( nRgbValue
!= API_RGB_TRANSPARENT
)
690 return OleHelper::encodeOleColor( nRgbValue
);
693 return OleHelper::encodeOleColor( rGraphicHelper
.getPaletteColor( rTextColor
.toInt32() ) );
696 void VmlDrawing::convertControlFontData( AxFontData
& rAxFontData
, sal_uInt32
& rnOleTextColor
, const ::oox::vml::TextFontModel
& rFontModel
) const
698 if( rFontModel
.moName
.has() )
699 rAxFontData
.maFontName
= rFontModel
.moName
.get();
701 // font height: convert from twips to points, then to internal representation of AX controls
702 rAxFontData
.setHeightPoints( static_cast< sal_Int16
>( (rFontModel
.monSize
.get( 200 ) + 10) / 20 ) );
705 rAxFontData
.mnFontEffects
= 0;
706 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_BOLD
, rFontModel
.mobBold
.get( false ) );
707 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_ITALIC
, rFontModel
.mobItalic
.get( false ) );
708 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_STRIKEOUT
, rFontModel
.mobStrikeout
.get( false ) );
709 sal_Int32 nUnderline
= rFontModel
.monUnderline
.get( XML_none
);
710 setFlag( rAxFontData
.mnFontEffects
, AX_FONTDATA_UNDERLINE
, nUnderline
!= XML_none
);
711 rAxFontData
.mbDblUnderline
= nUnderline
== XML_double
;
714 rnOleTextColor
= convertControlTextColor( rFontModel
.moColor
.get( OUString() ) );
717 void VmlDrawing::convertControlText( AxFontData
& rAxFontData
, sal_uInt32
& rnOleTextColor
,
718 OUString
& rCaption
, const ::oox::vml::TextBox
* pTextBox
, sal_Int32 nTextHAlign
) const
722 rCaption
= pTextBox
->getText();
723 if( const ::oox::vml::TextFontModel
* pFontModel
= pTextBox
->getFirstFont() )
724 convertControlFontData( rAxFontData
, rnOleTextColor
, *pFontModel
);
727 switch( nTextHAlign
)
729 case XML_Left
: rAxFontData
.mnHorAlign
= AX_FONTDATA_LEFT
; break;
730 case XML_Center
: rAxFontData
.mnHorAlign
= AX_FONTDATA_CENTER
; break;
731 case XML_Right
: rAxFontData
.mnHorAlign
= AX_FONTDATA_RIGHT
; break;
732 default: rAxFontData
.mnHorAlign
= AX_FONTDATA_LEFT
;
736 void VmlDrawing::convertControlBackground( AxMorphDataModelBase
& rAxModel
, const ::oox::vml::ShapeBase
& rShape
) const
738 const ::oox::vml::FillModel
& rFillModel
= rShape
.getTypeModel().maFillModel
;
739 bool bHasFill
= rFillModel
.moFilled
.get( true );
740 setFlag( rAxModel
.mnFlags
, AX_FLAGS_OPAQUE
, bHasFill
);
743 const GraphicHelper
& rGraphicHelper
= getBaseFilter().getGraphicHelper();
744 sal_Int32 nSysWindowColor
= rGraphicHelper
.getSystemColor( XML_window
, API_RGB_WHITE
);
745 ::oox::drawingml::Color aColor
= ::oox::vml::ConversionHelper::decodeColor( rGraphicHelper
, rFillModel
.moColor
, rFillModel
.moOpacity
, nSysWindowColor
);
746 sal_Int32 nRgbValue
= aColor
.getColor( rGraphicHelper
);
747 rAxModel
.mnBackColor
= OleHelper::encodeOleColor( nRgbValue
);
751 VmlDrawingFragment::VmlDrawingFragment( const WorksheetHelper
& rHelper
, const OUString
& rFragmentPath
) :
752 ::oox::vml::DrawingFragment( rHelper
.getOoxFilter(), rFragmentPath
, rHelper
.getVmlDrawing() ),
753 WorksheetHelper( rHelper
)
757 void VmlDrawingFragment::finalizeImport()
759 ::oox::vml::DrawingFragment::finalizeImport();
760 getVmlDrawing().convertAndInsert();
766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */