xref: /aoo42x/main/sc/source/ui/vba/vbahyperlink.cxx (revision b3f79822)
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