xref: /aoo41x/main/sc/source/ui/vba/vbahyperlinks.cxx (revision d16f1dca)
1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5b3f79822SAndrew Rist  * distributed with this work for additional information
6b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10b3f79822SAndrew Rist  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12b3f79822SAndrew Rist  *
13b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17b3f79822SAndrew Rist  * specific language governing permissions and limitations
18b3f79822SAndrew Rist  * under the License.
19b3f79822SAndrew Rist  *
20b3f79822SAndrew Rist  *************************************************************/
21b3f79822SAndrew Rist 
22b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "vbahyperlinks.hxx"
25cdf0e10cSrcweir #include <algorithm>
26cdf0e10cSrcweir #include <vector>
27cdf0e10cSrcweir #include <ooo/vba/office/MsoHyperlinkType.hpp>
28cdf0e10cSrcweir #include "rangelst.hxx"
29cdf0e10cSrcweir #include "vbahyperlink.hxx"
30cdf0e10cSrcweir #include "vbarange.hxx"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir using namespace ::ooo::vba;
33cdf0e10cSrcweir using namespace ::com::sun::star;
34cdf0e10cSrcweir using ::rtl::OUString;
35cdf0e10cSrcweir 
36cdf0e10cSrcweir // ============================================================================
37cdf0e10cSrcweir 
38cdf0e10cSrcweir namespace {
39cdf0e10cSrcweir 
40cdf0e10cSrcweir /** Returns true, if every range of rxInner is contained in any range of rScOuter. */
lclContains(const ScRangeList & rScOuter,const uno::Reference<excel::XRange> & rxInner)41cdf0e10cSrcweir bool lclContains( const ScRangeList& rScOuter, const uno::Reference< excel::XRange >& rxInner ) throw (uno::RuntimeException)
42cdf0e10cSrcweir {
43cdf0e10cSrcweir     const ScRangeList& rScInner = ScVbaRange::getScRangeList( rxInner );
44cdf0e10cSrcweir     if( (rScInner.Count() == 0) || (rScOuter.Count() == 0) )
45cdf0e10cSrcweir         throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Empty range objects" ) ), uno::Reference< uno::XInterface >() );
46cdf0e10cSrcweir 
47cdf0e10cSrcweir     for( sal_uLong nIndex = 0, nCount = rScInner.Count(); nIndex < nCount; ++nIndex )
48cdf0e10cSrcweir         if( !rScOuter.In( *rScInner.GetObject( nIndex ) ) )
49cdf0e10cSrcweir             return false;
50cdf0e10cSrcweir     return true;
51cdf0e10cSrcweir }
52cdf0e10cSrcweir 
53cdf0e10cSrcweir // ----------------------------------------------------------------------------
54cdf0e10cSrcweir 
55cdf0e10cSrcweir /** Functor to decide whether the anchors of two Hyperlink objects are equal. */
56cdf0e10cSrcweir struct EqualAnchorFunctor
57cdf0e10cSrcweir {
58cdf0e10cSrcweir     uno::Reference< excel::XRange > mxAnchorRange;
59cdf0e10cSrcweir     uno::Reference< msforms::XShape > mxAnchorShape;
60cdf0e10cSrcweir     sal_Int32 mnType;
61cdf0e10cSrcweir     EqualAnchorFunctor( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException);
62cdf0e10cSrcweir     bool operator()( const uno::Reference< excel::XHyperlink >& rxHlink ) const throw (uno::RuntimeException);
63cdf0e10cSrcweir };
64cdf0e10cSrcweir 
EqualAnchorFunctor(const uno::Reference<excel::XHyperlink> & rxHlink)65cdf0e10cSrcweir EqualAnchorFunctor::EqualAnchorFunctor( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException) :
66cdf0e10cSrcweir     mnType( rxHlink->getType() )
67cdf0e10cSrcweir {
68cdf0e10cSrcweir     switch( mnType )
69cdf0e10cSrcweir     {
70cdf0e10cSrcweir         case office::MsoHyperlinkType::msoHyperlinkRange:
71cdf0e10cSrcweir             mxAnchorRange.set( rxHlink->getRange(), uno::UNO_QUERY_THROW );
72cdf0e10cSrcweir         break;
73cdf0e10cSrcweir         case office::MsoHyperlinkType::msoHyperlinkShape:
74cdf0e10cSrcweir         case office::MsoHyperlinkType::msoHyperlinkInlineShape:
75cdf0e10cSrcweir             mxAnchorShape.set( rxHlink->getShape(), uno::UNO_QUERY_THROW );
76cdf0e10cSrcweir         break;
77cdf0e10cSrcweir         default:
78cdf0e10cSrcweir             throw uno::RuntimeException();
79cdf0e10cSrcweir     }
80cdf0e10cSrcweir }
81cdf0e10cSrcweir 
operator ()(const uno::Reference<excel::XHyperlink> & rxHlink) const82cdf0e10cSrcweir bool EqualAnchorFunctor::operator()( const uno::Reference< excel::XHyperlink >& rxHlink ) const throw (uno::RuntimeException)
83cdf0e10cSrcweir {
84cdf0e10cSrcweir     sal_Int32 nType = rxHlink->getType();
85cdf0e10cSrcweir     if( nType != mnType )
86cdf0e10cSrcweir         return false;
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     switch( nType )
89cdf0e10cSrcweir     {
90cdf0e10cSrcweir         case office::MsoHyperlinkType::msoHyperlinkRange:
91cdf0e10cSrcweir         {
92cdf0e10cSrcweir             uno::Reference< excel::XRange > xAnchorRange( rxHlink->getRange(), uno::UNO_QUERY_THROW );
93cdf0e10cSrcweir             const ScRangeList& rScRanges1 = ScVbaRange::getScRangeList( xAnchorRange );
94cdf0e10cSrcweir             const ScRangeList& rScRanges2 = ScVbaRange::getScRangeList( mxAnchorRange );
95cdf0e10cSrcweir             return (rScRanges1.Count() == 1) && (rScRanges2.Count() == 1) && (*rScRanges1.GetObject( 0 ) == *rScRanges2.GetObject( 0 ));
96cdf0e10cSrcweir         }
97cdf0e10cSrcweir         case office::MsoHyperlinkType::msoHyperlinkShape:
98cdf0e10cSrcweir         case office::MsoHyperlinkType::msoHyperlinkInlineShape:
99cdf0e10cSrcweir         {
100cdf0e10cSrcweir             uno::Reference< msforms::XShape > xAnchorShape( rxHlink->getShape(), uno::UNO_QUERY_THROW );
101cdf0e10cSrcweir             return xAnchorShape.get() == mxAnchorShape.get();
102cdf0e10cSrcweir         }
103cdf0e10cSrcweir         default:
104cdf0e10cSrcweir             throw uno::RuntimeException();
105cdf0e10cSrcweir     }
106cdf0e10cSrcweir }
107cdf0e10cSrcweir 
108cdf0e10cSrcweir } // namespace
109cdf0e10cSrcweir 
110cdf0e10cSrcweir // ============================================================================
111cdf0e10cSrcweir 
112*d16f1dcaSPedro Giffuni namespace vba_detail {
113cdf0e10cSrcweir 
114cdf0e10cSrcweir class ScVbaHlinkContainer : public ::cppu::WeakImplHelper1< container::XIndexAccess >
115cdf0e10cSrcweir {
116cdf0e10cSrcweir public:
117cdf0e10cSrcweir     explicit ScVbaHlinkContainer() throw (uno::RuntimeException);
118cdf0e10cSrcweir     explicit ScVbaHlinkContainer( const ScVbaHlinkContainerRef& rxSheetContainer, const ScRangeList& rScRanges ) throw (uno::RuntimeException);
119cdf0e10cSrcweir     virtual ~ScVbaHlinkContainer();
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     /** Inserts the passed hyperlink into the collection. Will remove a
122cdf0e10cSrcweir         Hyperlink object with the same anchor as the passed Hyperlink object. */
123cdf0e10cSrcweir     void insertHyperlink( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException);
124cdf0e10cSrcweir 
125cdf0e10cSrcweir     // XIndexAccess
126cdf0e10cSrcweir     virtual sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException);
127cdf0e10cSrcweir     virtual uno::Any SAL_CALL getByIndex( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException);
128cdf0e10cSrcweir 
129cdf0e10cSrcweir     // XElementAccess
130cdf0e10cSrcweir     virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException);
131cdf0e10cSrcweir     virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException);
132cdf0e10cSrcweir 
133cdf0e10cSrcweir private:
134cdf0e10cSrcweir     typedef ::std::vector< uno::Reference< excel::XHyperlink > > HyperlinkVector;
135cdf0e10cSrcweir     HyperlinkVector     maHlinks;
136cdf0e10cSrcweir };
137cdf0e10cSrcweir 
138cdf0e10cSrcweir // ----------------------------------------------------------------------------
139cdf0e10cSrcweir 
ScVbaHlinkContainer()140cdf0e10cSrcweir ScVbaHlinkContainer::ScVbaHlinkContainer() throw (uno::RuntimeException)
141cdf0e10cSrcweir {
142cdf0e10cSrcweir     // TODO FIXME: fill with existing hyperlinks
143cdf0e10cSrcweir }
144cdf0e10cSrcweir 
ScVbaHlinkContainer(const ScVbaHlinkContainerRef & rxSheetContainer,const ScRangeList & rScRanges)145cdf0e10cSrcweir ScVbaHlinkContainer::ScVbaHlinkContainer( const ScVbaHlinkContainerRef& rxSheetContainer,
146cdf0e10cSrcweir         const ScRangeList& rScRanges ) throw (uno::RuntimeException)
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     for( sal_Int32 nIndex = 0, nCount = rxSheetContainer->getCount(); nIndex < nCount; ++nIndex )
149cdf0e10cSrcweir     {
150cdf0e10cSrcweir         uno::Reference< excel::XHyperlink > xHlink( rxSheetContainer->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
151cdf0e10cSrcweir         uno::Reference< excel::XRange > xHlinkRange( xHlink->getRange(), uno::UNO_QUERY_THROW );
152cdf0e10cSrcweir         if( lclContains( rScRanges, xHlinkRange ) )
153cdf0e10cSrcweir             maHlinks.push_back( xHlink );
154cdf0e10cSrcweir     }
155cdf0e10cSrcweir }
156cdf0e10cSrcweir 
~ScVbaHlinkContainer()157cdf0e10cSrcweir ScVbaHlinkContainer::~ScVbaHlinkContainer()
158cdf0e10cSrcweir {
159cdf0e10cSrcweir }
160cdf0e10cSrcweir 
insertHyperlink(const uno::Reference<excel::XHyperlink> & rxHlink)161cdf0e10cSrcweir void ScVbaHlinkContainer::insertHyperlink( const uno::Reference< excel::XHyperlink >& rxHlink ) throw (uno::RuntimeException)
162cdf0e10cSrcweir {
163cdf0e10cSrcweir     HyperlinkVector::iterator aIt = ::std::find_if( maHlinks.begin(), maHlinks.end(), EqualAnchorFunctor( rxHlink ) );
164cdf0e10cSrcweir     if( aIt == maHlinks.end() )
165cdf0e10cSrcweir         maHlinks.push_back( rxHlink );
166cdf0e10cSrcweir     else
167cdf0e10cSrcweir         *aIt = rxHlink;
168cdf0e10cSrcweir }
169cdf0e10cSrcweir 
getCount()170cdf0e10cSrcweir sal_Int32 SAL_CALL ScVbaHlinkContainer::getCount() throw (uno::RuntimeException)
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     return static_cast< sal_Int32 >( maHlinks.size() );
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
getByIndex(sal_Int32 nIndex)175cdf0e10cSrcweir uno::Any SAL_CALL ScVbaHlinkContainer::getByIndex( sal_Int32 nIndex )
176cdf0e10cSrcweir         throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException)
177cdf0e10cSrcweir {
178cdf0e10cSrcweir     if( (0 <= nIndex) && (nIndex < getCount()) )
179cdf0e10cSrcweir         return uno::Any( maHlinks[ static_cast< size_t >( nIndex ) ] );
180cdf0e10cSrcweir     throw lang::IndexOutOfBoundsException();
181cdf0e10cSrcweir }
182cdf0e10cSrcweir 
getElementType()183cdf0e10cSrcweir uno::Type SAL_CALL ScVbaHlinkContainer::getElementType() throw (uno::RuntimeException)
184cdf0e10cSrcweir {
185cdf0e10cSrcweir     return excel::XHyperlink::static_type( 0 );
186cdf0e10cSrcweir }
187cdf0e10cSrcweir 
hasElements()188cdf0e10cSrcweir sal_Bool SAL_CALL ScVbaHlinkContainer::hasElements() throw (uno::RuntimeException)
189cdf0e10cSrcweir {
190cdf0e10cSrcweir     return !maHlinks.empty();
191cdf0e10cSrcweir }
192cdf0e10cSrcweir 
193cdf0e10cSrcweir // ============================================================================
194cdf0e10cSrcweir 
ScVbaHlinkContainerMember(ScVbaHlinkContainer * pContainer)195cdf0e10cSrcweir ScVbaHlinkContainerMember::ScVbaHlinkContainerMember( ScVbaHlinkContainer* pContainer ) :
196cdf0e10cSrcweir     mxContainer( pContainer )
197cdf0e10cSrcweir {
198cdf0e10cSrcweir }
199cdf0e10cSrcweir 
~ScVbaHlinkContainerMember()200cdf0e10cSrcweir ScVbaHlinkContainerMember::~ScVbaHlinkContainerMember()
201cdf0e10cSrcweir {
202cdf0e10cSrcweir }
203cdf0e10cSrcweir 
204*d16f1dcaSPedro Giffuni } // namespace vba_detail
205cdf0e10cSrcweir 
206cdf0e10cSrcweir // ============================================================================
207cdf0e10cSrcweir 
ScVbaHyperlinks(const uno::Reference<XHelperInterface> & rxParent,const uno::Reference<uno::XComponentContext> & rxContext)208cdf0e10cSrcweir ScVbaHyperlinks::ScVbaHyperlinks( const uno::Reference< XHelperInterface >& rxParent,
209cdf0e10cSrcweir         const uno::Reference< uno::XComponentContext >& rxContext ) throw (uno::RuntimeException) :
210*d16f1dcaSPedro Giffuni     vba_detail::ScVbaHlinkContainerMember( new vba_detail::ScVbaHlinkContainer ),
211cdf0e10cSrcweir     ScVbaHyperlinks_BASE( rxParent, rxContext, uno::Reference< container::XIndexAccess >( mxContainer.get() ) )
212cdf0e10cSrcweir {
213cdf0e10cSrcweir }
214cdf0e10cSrcweir 
ScVbaHyperlinks(const uno::Reference<XHelperInterface> & rxParent,const uno::Reference<uno::XComponentContext> & rxContext,const ScVbaHyperlinksRef & rxSheetHlinks,const ScRangeList & rScRanges)215cdf0e10cSrcweir ScVbaHyperlinks::ScVbaHyperlinks( const uno::Reference< XHelperInterface >& rxParent,
216cdf0e10cSrcweir         const uno::Reference< uno::XComponentContext >& rxContext,
217cdf0e10cSrcweir         const ScVbaHyperlinksRef& rxSheetHlinks, const ScRangeList& rScRanges ) throw (uno::RuntimeException) :
218*d16f1dcaSPedro Giffuni     vba_detail::ScVbaHlinkContainerMember( new vba_detail::ScVbaHlinkContainer( rxSheetHlinks->mxContainer, rScRanges ) ),
219cdf0e10cSrcweir     ScVbaHyperlinks_BASE( rxParent, rxContext, uno::Reference< container::XIndexAccess >( mxContainer.get() ) ),
220cdf0e10cSrcweir     mxSheetHlinks( rxSheetHlinks )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
~ScVbaHyperlinks()224cdf0e10cSrcweir ScVbaHyperlinks::~ScVbaHyperlinks()
225cdf0e10cSrcweir {
226cdf0e10cSrcweir }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir // XHyperlinks ----------------------------------------------------------------
229cdf0e10cSrcweir 
Add(const uno::Any & rAnchor,const uno::Any & rAddress,const uno::Any & rSubAddress,const uno::Any & rScreenTip,const uno::Any & rTextToDisplay)230cdf0e10cSrcweir uno::Reference< excel::XHyperlink > SAL_CALL ScVbaHyperlinks::Add(
231cdf0e10cSrcweir     const uno::Any& rAnchor, const uno::Any& rAddress, const uno::Any& rSubAddress,
232cdf0e10cSrcweir     const uno::Any& rScreenTip, const uno::Any& rTextToDisplay ) throw (uno::RuntimeException)
233cdf0e10cSrcweir {
234cdf0e10cSrcweir     /*  If this Hyperlinks object has been craeted from a Range object, the
235cdf0e10cSrcweir         call to Add() is passed to the Hyperlinks object of the parent
236cdf0e10cSrcweir         worksheet. This container will not be modified (it will not contain the
237cdf0e10cSrcweir         inserted hyperlink).
238cdf0e10cSrcweir         For details, see documentation in hyperlinks.hxx.
239cdf0e10cSrcweir      */
240cdf0e10cSrcweir     if( mxSheetHlinks.is() )
241cdf0e10cSrcweir         return mxSheetHlinks->Add( rAnchor, rAddress, rSubAddress, rScreenTip, rTextToDisplay );
242cdf0e10cSrcweir 
243cdf0e10cSrcweir     // get anchor object (can be a Range or a Shape object)
244cdf0e10cSrcweir     uno::Reference< XHelperInterface > xAnchor( rAnchor, uno::UNO_QUERY_THROW );
245cdf0e10cSrcweir 
246cdf0e10cSrcweir     /*  Create the Hyperlink object, this tries to insert the hyperlink into
247cdf0e10cSrcweir         the spreadsheet document. Parent of the Hyperlink is the anchor object. */
248cdf0e10cSrcweir     uno::Reference< excel::XHyperlink > xHlink( new ScVbaHyperlink(
249cdf0e10cSrcweir         xAnchor, mxContext, rAddress, rSubAddress, rScreenTip, rTextToDisplay ) );
250cdf0e10cSrcweir 
251cdf0e10cSrcweir     /*  If creation of the hyperlink did not throw, insert it into the
252cdf0e10cSrcweir         collection. */
253cdf0e10cSrcweir     mxContainer->insertHyperlink( xHlink );
254cdf0e10cSrcweir     return xHlink;
255cdf0e10cSrcweir }
256cdf0e10cSrcweir 
Delete()257cdf0e10cSrcweir void SAL_CALL ScVbaHyperlinks::Delete() throw (uno::RuntimeException)
258cdf0e10cSrcweir {
259cdf0e10cSrcweir     // FIXME not implemented
260cdf0e10cSrcweir     throw uno::RuntimeException();
261cdf0e10cSrcweir }
262cdf0e10cSrcweir 
263cdf0e10cSrcweir // XEnumerationAccess ---------------------------------------------------------
264cdf0e10cSrcweir 
createEnumeration()265cdf0e10cSrcweir uno::Reference< container::XEnumeration > SAL_CALL ScVbaHyperlinks::createEnumeration() throw (uno::RuntimeException)
266cdf0e10cSrcweir {
267cdf0e10cSrcweir     return new SimpleIndexAccessToEnumeration( m_xIndexAccess );
268cdf0e10cSrcweir }
269cdf0e10cSrcweir 
270cdf0e10cSrcweir // XElementAccess -------------------------------------------------------------
271cdf0e10cSrcweir 
getElementType()272cdf0e10cSrcweir uno::Type SAL_CALL ScVbaHyperlinks::getElementType() throw (uno::RuntimeException)
273cdf0e10cSrcweir {
274cdf0e10cSrcweir     return excel::XHyperlink::static_type( 0 );
275cdf0e10cSrcweir }
276cdf0e10cSrcweir 
277cdf0e10cSrcweir // ScVbaCollectionBase --------------------------------------------------------
278cdf0e10cSrcweir 
createCollectionObject(const uno::Any & rSource)279cdf0e10cSrcweir uno::Any ScVbaHyperlinks::createCollectionObject( const uno::Any& rSource )
280cdf0e10cSrcweir {
281cdf0e10cSrcweir     // container stores XHyperlink objects, just return the passed object
282cdf0e10cSrcweir     return rSource;
283cdf0e10cSrcweir }
284cdf0e10cSrcweir 
285cdf0e10cSrcweir // XHelperInterface -----------------------------------------------------------
286cdf0e10cSrcweir 
287cdf0e10cSrcweir VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaHyperlinks, "ooo.vba.excel.Hyperlinks" )
288cdf0e10cSrcweir 
289cdf0e10cSrcweir // ============================================================================
290