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