LCOV - code coverage report
Current view: top level - libreoffice/sc/source/filter/oox - drawingfragment.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 113 362 31.2 %
Date: 2012-12-27 Functions: 20 30 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "drawingfragment.hxx"
      21             : 
      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"
      43             : namespace oox {
      44             : namespace xls {
      45             : 
      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;
      57             : 
      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             : using ::rtl::OStringBuffer;
      63             : using ::rtl::OUString;
      64             : using ::rtl::OUStringToOString;
      65             : // no using's for ::oox::vml, that may clash with ::oox::drawingml types
      66             : 
      67             : // ============================================================================
      68             : 
      69           0 : ShapeMacroAttacher::ShapeMacroAttacher( const OUString& rMacroName, const Reference< XShape >& rxShape ) :
      70             :     VbaMacroAttacherBase( rMacroName ),
      71           0 :     mxShape( rxShape )
      72             : {
      73           0 : }
      74             : 
      75           0 : void ShapeMacroAttacher::attachMacro( const OUString& rMacroUrl )
      76             : {
      77             :     try
      78             :     {
      79           0 :         Reference< XEventsSupplier > xSupplier( mxShape, UNO_QUERY_THROW );
      80           0 :         Reference< XNameReplace > xEvents( xSupplier->getEvents(), UNO_SET_THROW );
      81           0 :         Sequence< PropertyValue > aEventProps( 2 );
      82           0 :         aEventProps[ 0 ].Name = "EventType";
      83           0 :         aEventProps[ 0 ].Value <<= OUString( "Script" );
      84           0 :         aEventProps[ 1 ].Name = "Script";
      85           0 :         aEventProps[ 1 ].Value <<= rMacroUrl;
      86           0 :         xEvents->replaceByName( "OnClick", Any( aEventProps ) );
      87             :     }
      88           0 :     catch( Exception& )
      89             :     {
      90             :     }
      91           0 : }
      92             : 
      93             : // ============================================================================
      94             : 
      95           0 : Shape::Shape( const WorksheetHelper& rHelper, const AttributeList& rAttribs, const sal_Char* pcServiceName ) :
      96             :     ::oox::drawingml::Shape( pcServiceName ),
      97           0 :     WorksheetHelper( rHelper )
      98             : {
      99           0 :     OUString aMacro = rAttribs.getXString( XML_macro, OUString() );
     100           0 :     if( !aMacro.isEmpty() )
     101           0 :         maMacroName = getFormulaParser().importMacroName( aMacro );
     102           0 : }
     103             : 
     104           0 : void Shape::finalizeXShape( XmlFilterBase& rFilter, const Reference< XShapes >& rxShapes )
     105             : {
     106           0 :     rtl::OUString sURL;
     107           0 :     getShapeProperties()[ PROP_URL ] >>= sURL;
     108           0 :     getWorksheets().convertSheetNameRef( sURL );
     109           0 :     if( !maMacroName.isEmpty() && mxShape.is() )
     110             :     {
     111           0 :         VbaMacroAttacherRef xAttacher( new ShapeMacroAttacher( maMacroName, mxShape ) );
     112           0 :         getBaseFilter().getVbaProject().registerMacroAttacher( xAttacher );
     113             :     }
     114           0 :     ::oox::drawingml::Shape::finalizeXShape( rFilter, rxShapes );
     115           0 :     if ( !sURL.isEmpty() )
     116             :     {
     117           0 :         SdrObject* pObj = SdrObject::getSdrObjectFromXShape( mxShape );
     118           0 :         if ( pObj )
     119             :         {
     120           0 :             if ( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, sal_True ) )
     121           0 :                 pInfo->SetHlink( sURL );
     122             :         }
     123           0 :     }
     124           0 : }
     125             : 
     126             : // ============================================================================
     127             : 
     128           0 : GroupShapeContext::GroupShapeContext( ContextHandler& rParent,
     129             :         const WorksheetHelper& rHelper, const ShapePtr& rxParentShape, const ShapePtr& rxShape ) :
     130             :     ShapeGroupContext( rParent, rxParentShape, rxShape ),
     131           0 :     WorksheetHelper( rHelper )
     132             : {
     133           0 : }
     134             : 
     135           0 : /*static*/ ContextHandlerRef GroupShapeContext::createShapeContext( ContextHandler& rParent,
     136             :         const WorksheetHelper& rHelper, sal_Int32 nElement, const AttributeList& rAttribs,
     137             :         const ShapePtr& rxParentShape, ShapePtr* pxShape )
     138             : {
     139           0 :     switch( nElement )
     140             :     {
     141             :         case XDR_TOKEN( sp ):
     142             :         {
     143           0 :             ShapePtr xShape( new Shape( rHelper, rAttribs, "com.sun.star.drawing.CustomShape" ) );
     144           0 :             if( pxShape ) *pxShape = xShape;
     145           0 :             return new ShapeContext( rParent, rxParentShape, xShape );
     146             :         }
     147             :         case XDR_TOKEN( cxnSp ):
     148             :         {
     149           0 :             ShapePtr xShape( new Shape( rHelper, rAttribs, "com.sun.star.drawing.ConnectorShape" ) );
     150           0 :             if( pxShape ) *pxShape = xShape;
     151           0 :             return new ConnectorShapeContext( rParent, rxParentShape, xShape );
     152             :         }
     153             :         case XDR_TOKEN( pic ):
     154             :         {
     155           0 :             ShapePtr xShape( new Shape( rHelper, rAttribs, "com.sun.star.drawing.GraphicObjectShape" ) );
     156           0 :             if( pxShape ) *pxShape = xShape;
     157           0 :             return new GraphicShapeContext( rParent, rxParentShape, xShape );
     158             :         }
     159             :         case XDR_TOKEN( graphicFrame ):
     160             :         {
     161           0 :             ShapePtr xShape( new Shape( rHelper, rAttribs, "com.sun.star.drawing.GraphicObjectShape" ) );
     162           0 :             if( pxShape ) *pxShape = xShape;
     163           0 :             return new GraphicalObjectFrameContext( rParent, rxParentShape, xShape, rHelper.getSheetType() != SHEETTYPE_CHARTSHEET );
     164             :         }
     165             :         case XDR_TOKEN( grpSp ):
     166             :         {
     167           0 :             ShapePtr xShape( new Shape( rHelper, rAttribs, "com.sun.star.drawing.GroupShape" ) );
     168           0 :             if( pxShape ) *pxShape = xShape;
     169           0 :             return new GroupShapeContext( rParent, rHelper, rxParentShape, xShape );
     170             :         }
     171             :     }
     172           0 :     return 0;
     173             : }
     174             : 
     175           0 : Reference< XFastContextHandler > SAL_CALL GroupShapeContext::createFastChildContext(
     176             :         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw (SAXException, RuntimeException)
     177             : {
     178           0 :     ContextHandlerRef xContext = createShapeContext( *this, *this, nElement, AttributeList( rxAttribs ), mpGroupShapePtr );
     179           0 :     return xContext.get() ? xContext.get() : ShapeGroupContext::createFastChildContext( nElement, rxAttribs );
     180             : }
     181             : 
     182             : // ============================================================================
     183             : 
     184           2 : DrawingFragment::DrawingFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
     185             :     WorksheetFragmentBase( rHelper, rFragmentPath ),
     186           2 :     mxDrawPage( rHelper.getDrawPage(), UNO_QUERY )
     187             : {
     188             :     OSL_ENSURE( mxDrawPage.is(), "DrawingFragment::DrawingFragment - missing drawing page" );
     189           2 : }
     190             : 
     191           2 : ContextHandlerRef DrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
     192             : {
     193           2 :     switch( getCurrentElement() )
     194             :     {
     195             :         case XML_ROOT_CONTEXT:
     196           2 :             if( nElement == XDR_TOKEN( wsDr ) ) return this;
     197           0 :         break;
     198             : 
     199             :         case XDR_TOKEN( wsDr ):
     200           0 :             switch( nElement )
     201             :             {
     202             :                 case XDR_TOKEN( absoluteAnchor ):
     203             :                 case XDR_TOKEN( oneCellAnchor ):
     204             :                 case XDR_TOKEN( twoCellAnchor ):
     205           0 :                     mxAnchor.reset( new ShapeAnchor( *this ) );
     206           0 :                     mxAnchor->importAnchor( nElement, rAttribs );
     207           0 :                     return this;
     208             :             }
     209           0 :         break;
     210             : 
     211             :         case XDR_TOKEN( absoluteAnchor ):
     212             :         case XDR_TOKEN( oneCellAnchor ):
     213             :         case XDR_TOKEN( twoCellAnchor ):
     214             :         {
     215           0 :             switch( nElement )
     216             :             {
     217             :                 case XDR_TOKEN( from ):
     218           0 :                 case XDR_TOKEN( to ):           return this;
     219             : 
     220           0 :                 case XDR_TOKEN( pos ):          if( mxAnchor.get() ) mxAnchor->importPos( rAttribs );           break;
     221           0 :                 case XDR_TOKEN( ext ):          if( mxAnchor.get() ) mxAnchor->importExt( rAttribs );           break;
     222           0 :                 case XDR_TOKEN( clientData ):   if( mxAnchor.get() ) mxAnchor->importClientData( rAttribs );    break;
     223             : 
     224           0 :                 default:                        return GroupShapeContext::createShapeContext( *this, *this, nElement, rAttribs, ShapePtr(), &mxShape );
     225             :             }
     226             :         }
     227           0 :         break;
     228             : 
     229             :         case XDR_TOKEN( from ):
     230             :         case XDR_TOKEN( to ):
     231           0 :             switch( nElement )
     232             :             {
     233             :                 case XDR_TOKEN( col ):
     234             :                 case XDR_TOKEN( row ):
     235             :                 case XDR_TOKEN( colOff ):
     236           0 :                 case XDR_TOKEN( rowOff ):       return this;    // collect index in onCharacters()
     237             :             }
     238           0 :         break;
     239             :     }
     240           0 :     return 0;
     241             : }
     242             : 
     243           0 : void DrawingFragment::onCharacters( const OUString& rChars )
     244             : {
     245           0 :     switch( getCurrentElement() )
     246             :     {
     247             :         case XDR_TOKEN( col ):
     248             :         case XDR_TOKEN( row ):
     249             :         case XDR_TOKEN( colOff ):
     250             :         case XDR_TOKEN( rowOff ):
     251           0 :             if( mxAnchor.get() ) mxAnchor->setCellPos( getCurrentElement(), getParentElement(), rChars );
     252           0 :         break;
     253             :     }
     254           0 : }
     255             : 
     256           4 : void DrawingFragment::onEndElement()
     257             : {
     258           4 :     switch( getCurrentElement() )
     259             :     {
     260             :         case XDR_TOKEN( absoluteAnchor ):
     261             :         case XDR_TOKEN( oneCellAnchor ):
     262             :         case XDR_TOKEN( twoCellAnchor ):
     263           0 :             if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() )
     264             :             {
     265             :                 // Rotation is decided by orientation of shape determined
     266             :                 // by the anchor position given by 'twoCellAnchor'
     267           0 :                 if ( getCurrentElement() == XDR_TOKEN( twoCellAnchor ) )
     268           0 :                     mxShape->setRotation(0);
     269           0 :                 EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( getDrawPageSize() );
     270           0 :                 if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) )
     271             :                 {
     272             :                     // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle)
     273             :                     Rectangle aShapeRectEmu32(
     274           0 :                         getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.X, 0, SAL_MAX_INT32 ),
     275           0 :                         getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Y, 0, SAL_MAX_INT32 ),
     276           0 :                         getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Width, 0, SAL_MAX_INT32 ),
     277           0 :                         getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Height, 0, SAL_MAX_INT32 ) );
     278             : 
     279             :                     // Make sure to set the position and size *before* calling addShape().
     280           0 :                     mxShape->setPosition(Point(aShapeRectEmu.X, aShapeRectEmu.Y));
     281           0 :                     mxShape->setSize(Size(aShapeRectEmu.Width, aShapeRectEmu.Height));
     282             : 
     283           0 :                     basegfx::B2DHomMatrix aTransformation;
     284           0 :                     mxShape->addShape( getOoxFilter(), &getTheme(), mxDrawPage, aTransformation, &aShapeRectEmu32 );
     285             : 
     286             :                     /*  Collect all shape positions in the WorksheetHelper base
     287             :                         class. But first, scale EMUs to 1/100 mm. */
     288             :                     Rectangle aShapeRectHmm(
     289           0 :                         convertEmuToHmm( aShapeRectEmu.X ), convertEmuToHmm( aShapeRectEmu.Y ),
     290           0 :                         convertEmuToHmm( aShapeRectEmu.Width ), convertEmuToHmm( aShapeRectEmu.Height ) );
     291           0 :                     extendShapeBoundingBox( aShapeRectHmm );
     292             :                 }
     293             :             }
     294           0 :             mxShape.reset();
     295           0 :             mxAnchor.reset();
     296           0 :         break;
     297             :     }
     298           4 : }
     299             : 
     300             : // ============================================================================
     301             : // VML
     302             : // ============================================================================
     303             : 
     304             : namespace {
     305             : 
     306             : class VmlFindNoteFunc
     307             : {
     308             : public:
     309             :     explicit            VmlFindNoteFunc( const CellAddress& rPos );
     310             :     bool                operator()( const ::oox::vml::ShapeBase& rShape ) const;
     311             : 
     312             : private:
     313             :     sal_Int32           mnCol;
     314             :     sal_Int32           mnRow;
     315             : };
     316             : 
     317             : // ----------------------------------------------------------------------------
     318             : 
     319           1 : VmlFindNoteFunc::VmlFindNoteFunc( const CellAddress& rPos ) :
     320             :     mnCol( rPos.Column ),
     321           1 :     mnRow( rPos.Row )
     322             : {
     323           1 : }
     324             : 
     325           1 : bool VmlFindNoteFunc::operator()( const ::oox::vml::ShapeBase& rShape ) const
     326             : {
     327           1 :     const ::oox::vml::ClientData* pClientData = rShape.getClientData();
     328           1 :     return pClientData && (pClientData->mnCol == mnCol) && (pClientData->mnRow == mnRow);
     329             : }
     330             : 
     331             : } // namespace
     332             : 
     333             : // ============================================================================
     334             : 
     335           0 : VmlControlMacroAttacher::VmlControlMacroAttacher( const OUString& rMacroName,
     336             :         const Reference< XIndexContainer >& rxCtrlFormIC, sal_Int32 nCtrlIndex, sal_Int32 nCtrlType, sal_Int32 nDropStyle ) :
     337             :     VbaMacroAttacherBase( rMacroName ),
     338             :     mxCtrlFormIC( rxCtrlFormIC ),
     339             :     mnCtrlIndex( nCtrlIndex ),
     340             :     mnCtrlType( nCtrlType ),
     341           0 :     mnDropStyle( nDropStyle )
     342             : {
     343           0 : }
     344             : 
     345           0 : void VmlControlMacroAttacher::attachMacro( const OUString& rMacroUrl )
     346             : {
     347           0 :     ScriptEventDescriptor aEventDesc;
     348           0 :     aEventDesc.ScriptType = "Script";
     349           0 :     aEventDesc.ScriptCode = rMacroUrl;
     350             : 
     351             :     // editable drop downs are treated like edit boxes
     352           0 :     bool bEditDropDown = (mnCtrlType == XML_Drop) && (mnDropStyle == XML_ComboEdit);
     353           0 :     sal_Int32 nCtrlType = bEditDropDown ? XML_Edit : mnCtrlType;
     354             : 
     355           0 :     switch( nCtrlType )
     356             :     {
     357             :         case XML_Button:
     358             :         case XML_Checkbox:
     359             :         case XML_Radio:
     360           0 :             aEventDesc.ListenerType = "XActionListener";
     361           0 :             aEventDesc.EventMethod = "actionPerformed";
     362           0 :         break;
     363             :         case XML_Label:
     364             :         case XML_GBox:
     365             :         case XML_Dialog:
     366           0 :             aEventDesc.ListenerType = "XMouseListener";
     367           0 :             aEventDesc.EventMethod = "mouseReleased";
     368           0 :         break;
     369             :         case XML_Edit:
     370           0 :             aEventDesc.ListenerType = "XTextListener";
     371           0 :             aEventDesc.EventMethod = "textChanged";
     372           0 :         break;
     373             :         case XML_Spin:
     374             :         case XML_Scroll:
     375           0 :             aEventDesc.ListenerType = "XAdjustmentListener";
     376           0 :             aEventDesc.EventMethod = "adjustmentValueChanged";
     377           0 :         break;
     378             :         case XML_List:
     379             :         case XML_Drop:
     380           0 :             aEventDesc.ListenerType = "XChangeListener";
     381           0 :             aEventDesc.EventMethod = "changed";
     382           0 :         break;
     383             :         default:
     384             :             OSL_ENSURE( false, "VmlControlMacroAttacher::attachMacro - unexpected object type" );
     385           0 :             return;
     386             :     }
     387             : 
     388             :     try
     389             :     {
     390           0 :         Reference< XEventAttacherManager > xEventMgr( mxCtrlFormIC, UNO_QUERY_THROW );
     391           0 :         xEventMgr->registerScriptEvent( mnCtrlIndex, aEventDesc );
     392             :     }
     393           0 :     catch( Exception& )
     394             :     {
     395           0 :     }
     396             : }
     397             : 
     398             : // ============================================================================
     399             : 
     400          25 : VmlDrawing::VmlDrawing( const WorksheetHelper& rHelper ) :
     401          25 :     ::oox::vml::Drawing( rHelper.getOoxFilter(), rHelper.getDrawPage(), ::oox::vml::VMLDRAWING_EXCEL ),
     402             :     WorksheetHelper( rHelper ),
     403          50 :     maControlConv( rHelper.getBaseFilter().getModel(), rHelper.getBaseFilter().getGraphicHelper() )
     404             : {
     405             :     // default font for legacy listboxes and dropdowns: Tahoma, 8pt
     406          25 :     maListBoxFont.moName = "Tahoma";
     407          25 :     maListBoxFont.moColor = "auto";
     408          25 :     maListBoxFont.monSize = 160;
     409          25 : }
     410             : 
     411           1 : const ::oox::vml::ShapeBase* VmlDrawing::getNoteShape( const CellAddress& rPos ) const
     412             : {
     413           1 :     return getShapes().findShape( VmlFindNoteFunc( rPos ) );
     414             : }
     415             : 
     416           2 : bool VmlDrawing::isShapeSupported( const ::oox::vml::ShapeBase& rShape ) const
     417             : {
     418           2 :     const ::oox::vml::ClientData* pClientData = rShape.getClientData();
     419           2 :     return !pClientData || (pClientData->mnObjType != XML_Note);
     420             : }
     421             : 
     422           1 : OUString VmlDrawing::getShapeBaseName( const ::oox::vml::ShapeBase& rShape ) const
     423             : {
     424           1 :     if( const ::oox::vml::ClientData* pClientData = rShape.getClientData() )
     425             :     {
     426           1 :         switch( pClientData->mnObjType )
     427             :         {
     428           0 :             case XML_Button:    return OUString( "Button" );
     429           1 :             case XML_Checkbox:  return OUString( "Check Box" );
     430           0 :             case XML_Dialog:    return OUString( "Dialog Frame" );
     431           0 :             case XML_Drop:      return OUString( "Drop Down" );
     432           0 :             case XML_Edit:      return OUString( "Edit Box" );
     433           0 :             case XML_GBox:      return OUString( "Group Box" );
     434           0 :             case XML_Label:     return OUString( "Label" );
     435           0 :             case XML_List:      return OUString( "List Box" );
     436           0 :             case XML_Note:      return OUString( "Comment" );
     437           0 :             case XML_Pict:      return (pClientData->mbDde || getOleObjectInfo( rShape.getShapeId() )) ? OUString( "Object" ) : OUString( "Picture" );
     438           0 :             case XML_Radio:     return OUString( "Option Button" );
     439           0 :             case XML_Scroll:    return OUString( "Scroll Bar" );
     440           0 :             case XML_Spin:      return OUString( "Spinner" );
     441             :         }
     442             :     }
     443           0 :     return ::oox::vml::Drawing::getShapeBaseName( rShape );
     444             : }
     445             : 
     446           2 : bool VmlDrawing::convertClientAnchor( Rectangle& orShapeRect, const OUString& rShapeAnchor ) const
     447             : {
     448           2 :     if( rShapeAnchor.isEmpty() )
     449           0 :         return false;
     450           2 :     ShapeAnchor aAnchor( *this );
     451           2 :     aAnchor.importVmlAnchor( rShapeAnchor );
     452           2 :     orShapeRect = aAnchor.calcAnchorRectHmm( getDrawPageSize() );
     453           2 :     return (orShapeRect.Width >= 0) && (orShapeRect.Height >= 0);
     454             : }
     455             : 
     456           1 : Reference< XShape > VmlDrawing::createAndInsertClientXShape( const ::oox::vml::ShapeBase& rShape,
     457             :         const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
     458             : {
     459             :     // simulate the legacy drawing controls with OLE form controls
     460           1 :     OUString aShapeName = rShape.getShapeName();
     461           1 :     const ::oox::vml::ClientData* pClientData = rShape.getClientData();
     462           1 :     if( !aShapeName.isEmpty() && pClientData )
     463             :     {
     464           1 :         Rectangle aShapeRect = rShapeRect;
     465           1 :         const ::oox::vml::TextBox* pTextBox = rShape.getTextBox();
     466           1 :         EmbeddedControl aControl( aShapeName );
     467           1 :         switch( pClientData->mnObjType )
     468             :         {
     469             :             case XML_Button:
     470             :             {
     471           0 :                 AxCommandButtonModel& rAxModel = aControl.createModel< AxCommandButtonModel >();
     472           0 :                 convertControlText( rAxModel.maFontData, rAxModel.mnTextColor, rAxModel.maCaption, pTextBox, pClientData->mnTextHAlign );
     473           0 :                 rAxModel.mnFlags = AX_FLAGS_ENABLED | AX_FLAGS_OPAQUE | AX_FLAGS_WORDWRAP;
     474           0 :                 rAxModel.mnVerticalAlign = pClientData->mnTextVAlign;
     475             :             }
     476           0 :             break;
     477             : 
     478             :             case XML_Label:
     479             :             {
     480           0 :                 AxLabelModel& rAxModel = aControl.createModel< AxLabelModel >();
     481           0 :                 convertControlText( rAxModel.maFontData, rAxModel.mnTextColor, rAxModel.maCaption, pTextBox, pClientData->mnTextHAlign );
     482           0 :                 rAxModel.mnFlags = AX_FLAGS_ENABLED | AX_FLAGS_WORDWRAP;
     483           0 :                 rAxModel.mnBorderStyle = AX_BORDERSTYLE_NONE;
     484           0 :                 rAxModel.mnSpecialEffect = AX_SPECIALEFFECT_FLAT;
     485           0 :                 rAxModel.mnVerticalAlign = pClientData->mnTextVAlign;
     486             :             }
     487           0 :             break;
     488             : 
     489             :             case XML_Edit:
     490             :             {
     491           0 :                 bool bNumeric = (pClientData->mnVTEdit == ::oox::vml::VML_CLIENTDATA_INTEGER) || (pClientData->mnVTEdit == ::oox::vml::VML_CLIENTDATA_NUMBER);
     492             :                 AxMorphDataModelBase& rAxModel = bNumeric ?
     493           0 :                     static_cast< AxMorphDataModelBase& >( aControl.createModel< AxNumericFieldModel >() ) :
     494           0 :                     static_cast< AxMorphDataModelBase& >( aControl.createModel< AxTextBoxModel >() );
     495           0 :                 convertControlText( rAxModel.maFontData, rAxModel.mnTextColor, rAxModel.maValue, pTextBox, pClientData->mnTextHAlign );
     496           0 :                 setFlag( rAxModel.mnFlags, AX_FLAGS_MULTILINE, pClientData->mbMultiLine );
     497           0 :                 setFlag( rAxModel.mnScrollBars, AX_SCROLLBAR_VERTICAL, pClientData->mbVScroll );
     498           0 :                 if( pClientData->mbSecretEdit )
     499           0 :                     rAxModel.mnPasswordChar = '*';
     500             :             }
     501           0 :             break;
     502             : 
     503             :             case XML_GBox:
     504             :             {
     505           0 :                 AxFrameModel& rAxModel = aControl.createModel< AxFrameModel >();
     506           0 :                 convertControlText( rAxModel.maFontData, rAxModel.mnTextColor, rAxModel.maCaption, pTextBox, pClientData->mnTextHAlign );
     507           0 :                 rAxModel.mnBorderStyle = pClientData->mbNo3D ? AX_BORDERSTYLE_SINGLE : AX_BORDERSTYLE_NONE;
     508           0 :                 rAxModel.mnSpecialEffect = pClientData->mbNo3D ? AX_SPECIALEFFECT_FLAT : AX_SPECIALEFFECT_BUMPED;
     509             : 
     510             :                 /*  Move top border of groupbox up by half font height, because
     511             :                     Excel specifies Y position of the groupbox border line
     512             :                     instead the top border of the caption text. */
     513           0 :                 if( const ::oox::vml::TextFontModel* pFontModel = pTextBox ? pTextBox->getFirstFont() : 0 )
     514             :                 {
     515           0 :                     sal_Int32 nFontHeightHmm = getUnitConverter().scaleToMm100( pFontModel->monSize.get( 160 ), UNIT_TWIP );
     516           0 :                     sal_Int32 nYDiff = ::std::min< sal_Int32 >( nFontHeightHmm / 2, aShapeRect.Y );
     517           0 :                     aShapeRect.Y -= nYDiff;
     518           0 :                     aShapeRect.Height += nYDiff;
     519             :                 }
     520             :             }
     521           0 :             break;
     522             : 
     523             :             case XML_Checkbox:
     524             :             {
     525           1 :                 AxCheckBoxModel& rAxModel = aControl.createModel< AxCheckBoxModel >();
     526           1 :                 convertControlText( rAxModel.maFontData, rAxModel.mnTextColor, rAxModel.maCaption, pTextBox, pClientData->mnTextHAlign );
     527           1 :                 convertControlBackground( rAxModel, rShape );
     528           1 :                 rAxModel.maValue = OUString::valueOf( pClientData->mnChecked );
     529           1 :                 rAxModel.mnSpecialEffect = pClientData->mbNo3D ? AX_SPECIALEFFECT_FLAT : AX_SPECIALEFFECT_SUNKEN;
     530           1 :                 rAxModel.mnVerticalAlign = pClientData->mnTextVAlign;
     531           1 :                 bool bTriState = (pClientData->mnChecked != ::oox::vml::VML_CLIENTDATA_UNCHECKED) && (pClientData->mnChecked != ::oox::vml::VML_CLIENTDATA_CHECKED);
     532           1 :                 rAxModel.mnMultiSelect = bTriState ? AX_SELCTION_MULTI : AX_SELCTION_SINGLE;
     533             :             }
     534           1 :             break;
     535             : 
     536             :             case XML_Radio:
     537             :             {
     538           0 :                 AxOptionButtonModel& rAxModel = aControl.createModel< AxOptionButtonModel >();
     539           0 :                 convertControlText( rAxModel.maFontData, rAxModel.mnTextColor, rAxModel.maCaption, pTextBox, pClientData->mnTextHAlign );
     540           0 :                 convertControlBackground( rAxModel, rShape );
     541           0 :                 rAxModel.maValue = OUString::valueOf( pClientData->mnChecked );
     542           0 :                 rAxModel.mnSpecialEffect = pClientData->mbNo3D ? AX_SPECIALEFFECT_FLAT : AX_SPECIALEFFECT_SUNKEN;
     543           0 :                 rAxModel.mnVerticalAlign = pClientData->mnTextVAlign;
     544             :             }
     545           0 :             break;
     546             : 
     547             :             case XML_List:
     548             :             {
     549           0 :                 AxListBoxModel& rAxModel = aControl.createModel< AxListBoxModel >();
     550           0 :                 convertControlFontData( rAxModel.maFontData, rAxModel.mnTextColor, maListBoxFont );
     551           0 :                 rAxModel.mnBorderStyle = pClientData->mbNo3D2 ? AX_BORDERSTYLE_SINGLE : AX_BORDERSTYLE_NONE;
     552           0 :                 rAxModel.mnSpecialEffect = pClientData->mbNo3D2 ? AX_SPECIALEFFECT_FLAT : AX_SPECIALEFFECT_SUNKEN;
     553           0 :                 switch( pClientData->mnSelType )
     554             :                 {
     555           0 :                     case XML_Single:    rAxModel.mnMultiSelect = AX_SELCTION_SINGLE;    break;
     556           0 :                     case XML_Multi:     rAxModel.mnMultiSelect = AX_SELCTION_MULTI;     break;
     557           0 :                     case XML_Extend:    rAxModel.mnMultiSelect = AX_SELCTION_EXTENDED;  break;
     558             :                 }
     559             :             }
     560           0 :             break;
     561             : 
     562             :             case XML_Drop:
     563             :             {
     564           0 :                 AxComboBoxModel& rAxModel = aControl.createModel< AxComboBoxModel >();
     565           0 :                 convertControlFontData( rAxModel.maFontData, rAxModel.mnTextColor, maListBoxFont );
     566           0 :                 rAxModel.mnDisplayStyle = AX_DISPLAYSTYLE_DROPDOWN;
     567           0 :                 rAxModel.mnShowDropButton = AX_SHOWDROPBUTTON_ALWAYS;
     568           0 :                 rAxModel.mnBorderStyle = pClientData->mbNo3D2 ? AX_BORDERSTYLE_SINGLE : AX_BORDERSTYLE_NONE;
     569           0 :                 rAxModel.mnSpecialEffect = pClientData->mbNo3D2 ? AX_SPECIALEFFECT_FLAT : AX_SPECIALEFFECT_SUNKEN;
     570           0 :                 rAxModel.mnListRows = pClientData->mnDropLines;
     571             :             }
     572           0 :             break;
     573             : 
     574             :             case XML_Spin:
     575             :             {
     576           0 :                 AxSpinButtonModel& rAxModel = aControl.createModel< AxSpinButtonModel >();
     577           0 :                 rAxModel.mnMin = pClientData->mnMin;
     578           0 :                 rAxModel.mnMax = pClientData->mnMax;
     579           0 :                 rAxModel.mnPosition = pClientData->mnVal;
     580           0 :                 rAxModel.mnSmallChange = pClientData->mnInc;
     581             :             }
     582           0 :             break;
     583             : 
     584             :             case XML_Scroll:
     585             :             {
     586           0 :                 AxScrollBarModel& rAxModel = aControl.createModel< AxScrollBarModel >();
     587           0 :                 rAxModel.mnMin = pClientData->mnMin;
     588           0 :                 rAxModel.mnMax = pClientData->mnMax;
     589           0 :                 rAxModel.mnPosition = pClientData->mnVal;
     590           0 :                 rAxModel.mnSmallChange = pClientData->mnInc;
     591           0 :                 rAxModel.mnLargeChange = pClientData->mnPage;
     592             :             }
     593           0 :             break;
     594             : 
     595             :             case XML_Dialog:
     596             :             {
     597             :                 // fake with a group box
     598           0 :                 AxFrameModel& rAxModel = aControl.createModel< AxFrameModel >();
     599           0 :                 convertControlText( rAxModel.maFontData, rAxModel.mnTextColor, rAxModel.maCaption, pTextBox, XML_Left );
     600           0 :                 rAxModel.mnBorderStyle = AX_BORDERSTYLE_SINGLE;
     601           0 :                 rAxModel.mnSpecialEffect = AX_SPECIALEFFECT_FLAT;
     602             :             }
     603           0 :             break;
     604             :         }
     605             : 
     606           1 :         if( ControlModelBase* pAxModel = aControl.getModel() )
     607             :         {
     608             :             // create the control shape
     609           1 :             pAxModel->maSize.first = aShapeRect.Width;
     610           1 :             pAxModel->maSize.second = aShapeRect.Height;
     611           1 :             sal_Int32 nCtrlIndex = -1;
     612           1 :             Reference< XShape > xShape = createAndInsertXControlShape( aControl, rxShapes, aShapeRect, nCtrlIndex );
     613             : 
     614             :             // control shape macro
     615           1 :             if( xShape.is() && (nCtrlIndex >= 0) && !pClientData->maFmlaMacro.isEmpty() )
     616             :             {
     617           0 :                 OUString aMacroName = getFormulaParser().importMacroName( pClientData->maFmlaMacro );
     618           0 :                 if( !aMacroName.isEmpty() )
     619             :                 {
     620           0 :                     Reference< XIndexContainer > xFormIC = getControlForm().getXForm();
     621           0 :                     VbaMacroAttacherRef xAttacher( new VmlControlMacroAttacher( aMacroName, xFormIC, nCtrlIndex, pClientData->mnObjType, pClientData->mnDropStyle ) );
     622           0 :                     getBaseFilter().getVbaProject().registerMacroAttacher( xAttacher );
     623           0 :                 }
     624             :             }
     625             : 
     626           1 :             return xShape;
     627           1 :         }
     628             :     }
     629             : 
     630           0 :     return Reference< XShape >();
     631             : }
     632             : 
     633           1 : void VmlDrawing::notifyXShapeInserted( const Reference< XShape >& rxShape,
     634             :         const Rectangle& rShapeRect, const ::oox::vml::ShapeBase& rShape, bool bGroupChild )
     635             : {
     636             :     // collect all shape positions in the WorksheetHelper base class (but not children of group shapes)
     637           1 :     if( !bGroupChild )
     638           1 :         extendShapeBoundingBox( rShapeRect );
     639             : 
     640             :     // convert settings from VML client data
     641           1 :     if( const ::oox::vml::ClientData* pClientData = rShape.getClientData() )
     642             :     {
     643             :         // specific settings for embedded form controls
     644             :         try
     645             :         {
     646           1 :             Reference< XControlShape > xCtrlShape( rxShape, UNO_QUERY_THROW );
     647           1 :             Reference< XControlModel > xCtrlModel( xCtrlShape->getControl(), UNO_SET_THROW );
     648           1 :             PropertySet aPropSet( xCtrlModel );
     649             : 
     650             :             // printable
     651           1 :             aPropSet.setProperty( PROP_Printable, pClientData->mbPrintObject );
     652             : 
     653             :             // control source links
     654           1 :             if( !pClientData->maFmlaLink.isEmpty() || !pClientData->maFmlaRange.isEmpty() )
     655           0 :                 maControlConv.bindToSources( xCtrlModel, pClientData->maFmlaLink, pClientData->maFmlaRange, getSheetIndex() );
     656             :         }
     657           0 :         catch( Exception& )
     658             :         {
     659             :         }
     660             :     }
     661           1 : }
     662             : 
     663             : // private --------------------------------------------------------------------
     664             : 
     665           1 : sal_uInt32 VmlDrawing::convertControlTextColor( const OUString& rTextColor ) const
     666             : {
     667             :     // color attribute not present or 'auto' - use passed default color
     668           1 :     if( rTextColor.isEmpty() || rTextColor.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "auto" ) ) )
     669           0 :         return AX_SYSCOLOR_WINDOWTEXT;
     670             : 
     671           1 :     if( rTextColor[ 0 ] == '#' )
     672             :     {
     673             :         // RGB colors in the format '#RRGGBB'
     674           1 :         if( rTextColor.getLength() == 7 )
     675           1 :             return OleHelper::encodeOleColor( rTextColor.copy( 1 ).toInt32( 16 ) );
     676             : 
     677             :         // RGB colors in the format '#RGB'
     678           0 :         if( rTextColor.getLength() == 4 )
     679             :         {
     680           0 :             sal_Int32 nR = rTextColor.copy( 1, 1 ).toInt32( 16 ) * 0x11;
     681           0 :             sal_Int32 nG = rTextColor.copy( 2, 1 ).toInt32( 16 ) * 0x11;
     682           0 :             sal_Int32 nB = rTextColor.copy( 3, 1 ).toInt32( 16 ) * 0x11;
     683           0 :             return OleHelper::encodeOleColor( (nR << 16) | (nG << 8) | nB );
     684             :         }
     685             : 
     686             :         OSL_ENSURE( false, OStringBuffer( "VmlDrawing::convertControlTextColor - invalid color name '" ).
     687             :             append( OUStringToOString( rTextColor, RTL_TEXTENCODING_ASCII_US ) ).append( '\'' ).getStr() );
     688           0 :         return AX_SYSCOLOR_WINDOWTEXT;
     689             :     }
     690             : 
     691           0 :     const GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
     692             : 
     693             :     /*  Predefined color names or system color names (resolve to RGB to detect
     694             :         valid color name). */
     695           0 :     sal_Int32 nColorToken = AttributeConversion::decodeToken( rTextColor );
     696           0 :     sal_Int32 nRgbValue = Color::getVmlPresetColor( nColorToken, API_RGB_TRANSPARENT );
     697           0 :     if( nRgbValue == API_RGB_TRANSPARENT )
     698           0 :         nRgbValue = rGraphicHelper.getSystemColor( nColorToken, API_RGB_TRANSPARENT );
     699           0 :     if( nRgbValue != API_RGB_TRANSPARENT )
     700           0 :         return OleHelper::encodeOleColor( nRgbValue );
     701             : 
     702             :     // try palette color
     703           0 :     return OleHelper::encodeOleColor( rGraphicHelper.getPaletteColor( rTextColor.toInt32() ) );
     704             : }
     705             : 
     706           1 : void VmlDrawing::convertControlFontData( AxFontData& rAxFontData, sal_uInt32& rnOleTextColor, const ::oox::vml::TextFontModel& rFontModel ) const
     707             : {
     708           1 :     if( rFontModel.moName.has() )
     709           1 :         rAxFontData.maFontName = rFontModel.moName.get();
     710             : 
     711             :     // font height: convert from twips to points, then to internal representation of AX controls
     712           1 :     rAxFontData.setHeightPoints( static_cast< sal_Int16 >( (rFontModel.monSize.get( 200 ) + 10) / 20 ) );
     713             : 
     714             :     // font effects
     715           1 :     rAxFontData.mnFontEffects = 0;
     716           1 :     setFlag( rAxFontData.mnFontEffects, AX_FONTDATA_BOLD, rFontModel.mobBold.get( false ) );
     717           1 :     setFlag( rAxFontData.mnFontEffects, AX_FONTDATA_ITALIC, rFontModel.mobItalic.get( false ) );
     718           1 :     setFlag( rAxFontData.mnFontEffects, AX_FONTDATA_STRIKEOUT, rFontModel.mobStrikeout.get( false ) );
     719           1 :     sal_Int32 nUnderline = rFontModel.monUnderline.get( XML_none );
     720           1 :     setFlag( rAxFontData.mnFontEffects, AX_FONTDATA_UNDERLINE, nUnderline != XML_none );
     721           1 :     rAxFontData.mbDblUnderline = nUnderline == XML_double;
     722             : 
     723             :     // font color
     724           1 :     rnOleTextColor = convertControlTextColor( rFontModel.moColor.get( OUString() ) );
     725           1 : }
     726             : 
     727           1 : void VmlDrawing::convertControlText( AxFontData& rAxFontData, sal_uInt32& rnOleTextColor,
     728             :         OUString& rCaption, const ::oox::vml::TextBox* pTextBox, sal_Int32 nTextHAlign ) const
     729             : {
     730           1 :     if( pTextBox )
     731             :     {
     732           1 :         rCaption = pTextBox->getText();
     733           1 :         if( const ::oox::vml::TextFontModel* pFontModel = pTextBox->getFirstFont() )
     734           1 :             convertControlFontData( rAxFontData, rnOleTextColor, *pFontModel );
     735             :     }
     736             : 
     737           1 :     switch( nTextHAlign )
     738             :     {
     739           1 :         case XML_Left:      rAxFontData.mnHorAlign = AX_FONTDATA_LEFT;      break;
     740           0 :         case XML_Center:    rAxFontData.mnHorAlign = AX_FONTDATA_CENTER;    break;
     741           0 :         case XML_Right:     rAxFontData.mnHorAlign = AX_FONTDATA_RIGHT;     break;
     742           0 :         default:            rAxFontData.mnHorAlign = AX_FONTDATA_LEFT;
     743             :     }
     744           1 : }
     745             : 
     746           1 : void VmlDrawing::convertControlBackground( AxMorphDataModelBase& rAxModel, const ::oox::vml::ShapeBase& rShape ) const
     747             : {
     748           1 :     const ::oox::vml::FillModel& rFillModel = rShape.getTypeModel().maFillModel;
     749           1 :     bool bHasFill = rFillModel.moFilled.get( true );
     750           1 :     setFlag( rAxModel.mnFlags, AX_FLAGS_OPAQUE, bHasFill );
     751           1 :     if( bHasFill )
     752             :     {
     753           0 :         const GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
     754           0 :         sal_Int32 nSysWindowColor = rGraphicHelper.getSystemColor( XML_window, API_RGB_WHITE );
     755           0 :         ::oox::drawingml::Color aColor = ::oox::vml::ConversionHelper::decodeColor( rGraphicHelper, rFillModel.moColor, rFillModel.moOpacity, nSysWindowColor );
     756           0 :         sal_Int32 nRgbValue = aColor.getColor( rGraphicHelper );
     757           0 :         rAxModel.mnBackColor = OleHelper::encodeOleColor( nRgbValue );
     758             :     }
     759           1 : }
     760             : 
     761             : // ============================================================================
     762             : 
     763           2 : VmlDrawingFragment::VmlDrawingFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
     764           4 :     ::oox::vml::DrawingFragment( rHelper.getOoxFilter(), rFragmentPath, rHelper.getVmlDrawing() ),
     765           4 :     WorksheetHelper( rHelper )
     766             : {
     767           2 : }
     768             : 
     769           2 : void VmlDrawingFragment::finalizeImport()
     770             : {
     771           2 :     ::oox::vml::DrawingFragment::finalizeImport();
     772           2 :     getVmlDrawing().convertAndInsert();
     773           2 : }
     774             : 
     775             : // ============================================================================
     776             : 
     777             : } // namespace xls
     778           9 : } // namespace oox
     779             : 
     780             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10