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