1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 31 #include "ChartDropTargetHelper.hxx" 32 #include "DiagramHelper.hxx" 33 #include "DataSourceHelper.hxx" 34 35 #include <com/sun/star/chart2/XChartDocument.hpp> 36 #include <com/sun/star/chart2/data/XDataProvider.hpp> 37 #include <com/sun/star/container/XChild.hpp> 38 39 #include <sot/formats.hxx> 40 #include <vector> 41 42 using namespace ::com::sun::star; 43 44 using ::com::sun::star::uno::Reference; 45 using ::com::sun::star::uno::Sequence; 46 using ::rtl::OUString; 47 48 namespace 49 { 50 51 ::std::vector< OUString > lcl_getStringsFromByteSequence( 52 const Sequence< sal_Int8 > & aByteSequence ) 53 { 54 ::std::vector< OUString > aResult; 55 const sal_Int32 nLength = aByteSequence.getLength(); 56 const sal_Char * pBytes( reinterpret_cast< const sal_Char* >( aByteSequence.getConstArray())); 57 sal_Int32 nStartPos = 0; 58 for( sal_Int32 nPos=0; nPos<nLength; ++nPos ) 59 { 60 if( pBytes[nPos] == '\0' ) 61 { 62 aResult.push_back( OUString( pBytes + nStartPos, (nPos - nStartPos), RTL_TEXTENCODING_ASCII_US )); 63 nStartPos = nPos + 1; 64 } 65 } 66 return aResult; 67 } 68 69 } // anonymous namespace 70 71 namespace chart 72 { 73 74 ChartDropTargetHelper::ChartDropTargetHelper( 75 const Reference< datatransfer::dnd::XDropTarget >& rxDropTarget, 76 const Reference< chart2::XChartDocument > & xChartDocument ) : 77 DropTargetHelper( rxDropTarget ), 78 m_xChartDocument( xChartDocument ) 79 {} 80 81 ChartDropTargetHelper::~ChartDropTargetHelper() 82 {} 83 84 bool ChartDropTargetHelper::satisfiesPrerequisites() const 85 { 86 return ( m_xChartDocument.is() && 87 ! m_xChartDocument->hasInternalDataProvider()); 88 } 89 90 sal_Int8 ChartDropTargetHelper::AcceptDrop( const AcceptDropEvent& rEvt ) 91 { 92 sal_Int8 nResult = DND_ACTION_NONE; 93 94 if( ( rEvt.mnAction == DND_ACTION_COPY || 95 rEvt.mnAction == DND_ACTION_MOVE ) && 96 satisfiesPrerequisites() && 97 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) ) 98 { 99 // @todo: check if the data is suitable. Is this possible without XTransferable? 100 nResult = rEvt.mnAction; 101 } 102 103 return nResult; 104 } 105 106 sal_Int8 ChartDropTargetHelper::ExecuteDrop( const ExecuteDropEvent& rEvt ) 107 { 108 sal_Int8 nResult = DND_ACTION_NONE; 109 110 if( ( rEvt.mnAction == DND_ACTION_COPY || 111 rEvt.mnAction == DND_ACTION_MOVE ) && 112 rEvt.maDropEvent.Transferable.is() && 113 satisfiesPrerequisites()) 114 { 115 TransferableDataHelper aDataHelper( rEvt.maDropEvent.Transferable ); 116 if( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK )) 117 { 118 Sequence< sal_Int8 > aBytes; 119 if( aDataHelper.GetSequence( SOT_FORMATSTR_ID_LINK, aBytes )) 120 { 121 ::std::vector< OUString > aStrings( lcl_getStringsFromByteSequence( aBytes )); 122 if( aStrings.size() >= 3 && 123 aStrings[0].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "soffice" ))) 124 { 125 OUString aDocName( aStrings[1] ); 126 OUString aRangeString( aStrings[2] ); 127 Reference< container::XChild > xChild( m_xChartDocument, uno::UNO_QUERY ); 128 if( xChild.is()) 129 { 130 Reference< frame::XModel > xParentModel( xChild->getParent(), uno::UNO_QUERY ); 131 if( xParentModel.is() && 132 m_xChartDocument.is()) 133 { 134 bool bDataComesFromParent = true; 135 // @todo: get the title somehow and compare it to 136 // aDocName if successful (the document is the 137 // parent) 138 if( bDataComesFromParent ) 139 { 140 Reference< chart2::XDiagram > xDiagram( m_xChartDocument->getFirstDiagram() ); 141 Reference< chart2::data::XDataProvider > xDataProvider( m_xChartDocument->getDataProvider()); 142 if( xDataProvider.is() && xDiagram.is() && 143 DataSourceHelper::allArgumentsForRectRangeDetected( m_xChartDocument )) 144 { 145 Reference< chart2::data::XDataSource > xDataSource( 146 DataSourceHelper::pressUsedDataIntoRectangularFormat( m_xChartDocument )); 147 Sequence< beans::PropertyValue > aArguments( 148 xDataProvider->detectArguments( xDataSource )); 149 150 OUString aOldRange; 151 beans::PropertyValue * pCellRange = 0; 152 for( sal_Int32 i=0; i<aArguments.getLength(); ++i ) 153 { 154 if( aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) 155 { 156 pCellRange = (aArguments.getArray() + i); 157 aArguments[i].Value >>= aOldRange; 158 break; 159 } 160 } 161 if( pCellRange ) 162 { 163 // copy means add ranges, move means replace 164 if( rEvt.mnAction == DND_ACTION_COPY ) 165 { 166 // @todo: using implcit knowledge that ranges can be 167 // merged with ";". This should be done more general 168 pCellRange->Value <<= (aOldRange + OUString( sal_Unicode(';')) + aRangeString ); 169 } 170 // move means replace range 171 else 172 { 173 pCellRange->Value <<= aRangeString; 174 } 175 176 xDataSource.set( xDataProvider->createDataSource( aArguments )); 177 xDiagram->setDiagramData( xDataSource, aArguments ); 178 179 // always return copy state to avoid deletion of the dragged range 180 nResult = DND_ACTION_COPY; 181 } 182 } 183 } 184 } 185 } 186 } 187 } 188 } 189 } 190 return nResult; 191 } 192 193 } // namespace chart 194