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 #include "vbahyperlink.hxx" 29 #include <vbahelper/helperdecl.hxx> 30 #include <com/sun/star/container/XIndexAccess.hpp> 31 #include <com/sun/star/text/XText.hpp> 32 #include <com/sun/star/text/XTextFieldsSupplier.hpp> 33 #include <com/sun/star/container/XEnumerationAccess.hpp> 34 #include <ooo/vba/office/MsoHyperlinkType.hpp> 35 #include <ooo/vba/msforms/XShape.hpp> 36 #include "vbarange.hxx" 37 38 using namespace ::ooo::vba; 39 using namespace ::com::sun::star; 40 using ::rtl::OUString; 41 using ::rtl::OUStringBuffer; 42 43 // ============================================================================ 44 45 ScVbaHyperlink::ScVbaHyperlink( const uno::Sequence< uno::Any >& rArgs, 46 const uno::Reference< uno::XComponentContext >& rxContext ) throw (lang::IllegalArgumentException) : 47 HyperlinkImpl_BASE( getXSomethingFromArgs< XHelperInterface >( rArgs, 0 ), rxContext ), 48 mxCell( getXSomethingFromArgs< table::XCell >( rArgs, 1, false ) ), 49 mnType( office::MsoHyperlinkType::msoHyperlinkRange ) 50 { 51 uno::Reference< text::XTextFieldsSupplier > xTextFields( mxCell, uno::UNO_QUERY_THROW ); 52 uno::Reference< container::XIndexAccess > xIndex( xTextFields->getTextFields(), uno::UNO_QUERY_THROW ); 53 mxTextField.set( xIndex->getByIndex(0), uno::UNO_QUERY_THROW ); 54 } 55 56 ScVbaHyperlink::ScVbaHyperlink( const uno::Reference< XHelperInterface >& rxAnchor, 57 const uno::Reference< uno::XComponentContext >& rxContext, 58 const uno::Any& rAddress, const uno::Any& rSubAddress, 59 const uno::Any& rScreenTip, const uno::Any& rTextToDisplay ) throw (uno::RuntimeException) : 60 HyperlinkImpl_BASE( rxAnchor, rxContext ) // parent of Hyperlink is the anchor object 61 { 62 // extract parameters, Address must not be empty 63 UrlComponents aUrlComp; 64 OUString aTextToDisplay; 65 if( !(rAddress >>= aUrlComp.first) || (aUrlComp.first.getLength() == 0) ) 66 throw uno::RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( "Cannot get address" ) ), uno::Reference< uno::XInterface >() ); 67 rSubAddress >>= aUrlComp.second; 68 rScreenTip >>= maScreenTip; 69 rTextToDisplay >>= aTextToDisplay; 70 71 // get anchor range or anchor shape 72 uno::Reference< excel::XRange > xAnchorRange( rxAnchor, uno::UNO_QUERY ); 73 if( xAnchorRange.is() ) 74 { 75 mnType = office::MsoHyperlinkType::msoHyperlinkRange; 76 // only single ranges are allowed 77 uno::Reference< table::XCellRange > xUnoRange( ScVbaRange::getCellRange( xAnchorRange ), uno::UNO_QUERY_THROW ); 78 // insert the hyperlink into the top-left cell only 79 mxCell.set( xUnoRange->getCellByPosition( 0, 0 ), uno::UNO_SET_THROW ); 80 uno::Reference< text::XText > xText( mxCell, uno::UNO_QUERY_THROW ); 81 // use cell text or URL if no TextToDisplay has been passed 82 if( aTextToDisplay.getLength() == 0 ) 83 { 84 aTextToDisplay = xText->getString(); 85 if( aTextToDisplay.getLength() == 0 ) 86 { 87 OUStringBuffer aBuffer( aUrlComp.first ); 88 if( aUrlComp.second.getLength() > 0 ) 89 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " - " ) ).append( aUrlComp.second ); 90 aTextToDisplay = aBuffer.makeStringAndClear(); 91 } 92 } 93 // create and initialize a new URL text field 94 uno::Reference< lang::XMultiServiceFactory > xFactory( ScVbaRange::getUnoModel( xAnchorRange ), uno::UNO_QUERY_THROW ); 95 uno::Reference< text::XTextContent > xUrlField( xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextField.URL" ) ) ), uno::UNO_QUERY_THROW ); 96 mxTextField.set( xUrlField, uno::UNO_QUERY_THROW ); 97 setUrlComponents( aUrlComp ); 98 setTextToDisplay( aTextToDisplay ); 99 // insert the text field into the document 100 xText->setString( OUString() ); 101 uno::Reference< text::XTextRange > xRange( xText->createTextCursor(), uno::UNO_QUERY_THROW ); 102 xText->insertTextContent( xRange, xUrlField, sal_False ); 103 } 104 else 105 { 106 uno::Reference< msforms::XShape > xAnchorShape( rxAnchor, uno::UNO_QUERY_THROW ); 107 mnType = office::MsoHyperlinkType::msoHyperlinkShape; 108 // FIXME: insert hyperlink into shape 109 throw uno::RuntimeException(); 110 } 111 } 112 113 ScVbaHyperlink::~ScVbaHyperlink() 114 { 115 } 116 117 OUString ScVbaHyperlink::getName() throw (uno::RuntimeException) 118 { 119 // it seems this attribute is same as TextToDisplay 120 return getTextToDisplay(); 121 } 122 123 void ScVbaHyperlink::setName( const OUString& rName ) throw (uno::RuntimeException) 124 { 125 setTextToDisplay( rName ); 126 } 127 128 OUString ScVbaHyperlink::getAddress() throw (uno::RuntimeException) 129 { 130 return getUrlComponents().first; 131 } 132 133 void ScVbaHyperlink::setAddress( const OUString& rAddress ) throw (uno::RuntimeException) 134 { 135 UrlComponents aUrlComp = getUrlComponents(); 136 aUrlComp.first = rAddress; 137 setUrlComponents( aUrlComp ); 138 } 139 140 OUString ScVbaHyperlink::getSubAddress() throw (uno::RuntimeException) 141 { 142 return getUrlComponents().second; 143 } 144 145 void ScVbaHyperlink::setSubAddress( const OUString& rSubAddress ) throw (uno::RuntimeException) 146 { 147 UrlComponents aUrlComp = getUrlComponents(); 148 aUrlComp.second = rSubAddress; 149 setUrlComponents( aUrlComp ); 150 } 151 152 OUString SAL_CALL ScVbaHyperlink::getScreenTip() throw (uno::RuntimeException) 153 { 154 return maScreenTip; 155 } 156 157 void SAL_CALL ScVbaHyperlink::setScreenTip( const OUString& rScreenTip ) throw (uno::RuntimeException) 158 { 159 maScreenTip = rScreenTip; 160 } 161 162 OUString ScVbaHyperlink::getTextToDisplay() throw (uno::RuntimeException) 163 { 164 ensureTextField(); 165 OUString aTextToDisplay; 166 mxTextField->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Representation" ) ) ) >>= aTextToDisplay; 167 return aTextToDisplay; 168 } 169 170 void ScVbaHyperlink::setTextToDisplay( const OUString& rTextToDisplay ) throw (uno::RuntimeException) 171 { 172 ensureTextField(); 173 mxTextField->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "Representation" ) ), uno::Any( rTextToDisplay ) ); 174 } 175 176 sal_Int32 SAL_CALL ScVbaHyperlink::getType() throw (uno::RuntimeException) 177 { 178 return mnType; 179 } 180 181 uno::Reference< excel::XRange > SAL_CALL ScVbaHyperlink::getRange() throw (uno::RuntimeException) 182 { 183 if( mnType == office::MsoHyperlinkType::msoHyperlinkRange ) 184 { 185 // if constructed from Hyperlinks object, range has been passed as parent 186 uno::Reference< excel::XRange > xAnchorRange( getParent(), uno::UNO_QUERY ); 187 if( !xAnchorRange.is() ) 188 { 189 // if constructed via service c'tor, create new range based on cell 190 uno::Reference< table::XCellRange > xRange( mxCell, uno::UNO_QUERY_THROW ); 191 // FIXME: need to pass current worksheet as the parent of XRange. 192 xAnchorRange.set( new ScVbaRange( uno::Reference< XHelperInterface >(), mxContext, xRange ) ); 193 } 194 return xAnchorRange; 195 } 196 // error if called at a shape Hyperlink object 197 throw uno::RuntimeException(); 198 } 199 200 uno::Reference< msforms::XShape > SAL_CALL ScVbaHyperlink::getShape() throw (uno::RuntimeException) 201 { 202 // error if called at a range Hyperlink object 203 return uno::Reference< msforms::XShape >( getParent(), uno::UNO_QUERY_THROW ); 204 } 205 206 VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaHyperlink, "ooo.vba.excel.Hyperlink" ) 207 208 // private -------------------------------------------------------------------- 209 210 void ScVbaHyperlink::ensureTextField() throw (uno::RuntimeException) 211 { 212 if( !mxTextField.is() ) 213 throw uno::RuntimeException(); 214 } 215 216 ScVbaHyperlink::UrlComponents ScVbaHyperlink::getUrlComponents() throw (uno::RuntimeException) 217 { 218 ensureTextField(); 219 OUString aUrl; 220 mxTextField->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) ) >>= aUrl; 221 sal_Int32 nHashPos = aUrl.indexOf( '#' ); 222 if( nHashPos < 0 ) 223 return UrlComponents( aUrl, OUString() ); 224 return UrlComponents( aUrl.copy( 0, nHashPos ), aUrl.copy( nHashPos + 1 ) ); 225 } 226 227 void ScVbaHyperlink::setUrlComponents( const UrlComponents& rUrlComp ) throw (uno::RuntimeException) 228 { 229 ensureTextField(); 230 OUStringBuffer aUrl( rUrlComp.first ); 231 if( rUrlComp.second.getLength() > 0 ) 232 aUrl.append( sal_Unicode( '#' ) ).append( rUrlComp.second ); 233 mxTextField->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ), uno::Any( aUrl.makeStringAndClear() ) ); 234 } 235 236 namespace hyperlink 237 { 238 namespace sdecl = comphelper::service_decl; 239 sdecl::vba_service_class_<ScVbaHyperlink, sdecl::with_args<true> > serviceImpl; 240 extern sdecl::ServiceDecl const serviceDecl( 241 serviceImpl, 242 "ScVbaHyperlink", 243 "ooo.vba.excel.Hyperlink" ); 244 } 245 246 // ============================================================================ 247