1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "vbahyperlinks.hxx"
23 #include <cppuhelper/implbase.hxx>
24 #include <ooo/vba/office/MsoHyperlinkType.hpp>
25 #include <rangelst.hxx>
26 #include "vbahyperlink.hxx"
27 #include "vbarange.hxx"
29 using namespace ::ooo::vba
;
30 using namespace ::com::sun::star
;
34 /** Returns true, if every range of rxInner is contained in any range of rScOuter.
36 @throws css::uno::RuntimeException
38 bool lclContains( const ScRangeList
& rScOuter
, const uno::Reference
< excel::XRange
>& rxInner
)
40 const ScRangeList
& rScInner
= ScVbaRange::getScRangeList( rxInner
);
41 if( rScInner
.empty() || rScOuter
.empty() )
42 throw uno::RuntimeException(u
"Empty range objects"_ustr
);
44 for( size_t nIndex
= 0, nCount
= rScInner
.size(); nIndex
< nCount
; ++nIndex
)
45 if( !rScOuter
.Contains( rScInner
[ nIndex
] ) )
50 /** Functor to decide whether the anchors of two Hyperlink objects are equal. */
51 struct EqualAnchorFunctor
53 uno::Reference
< excel::XRange
> mxAnchorRange
;
54 uno::Reference
< msforms::XShape
> mxAnchorShape
;
56 /// @throws uno::RuntimeException
57 explicit EqualAnchorFunctor( const uno::Reference
< excel::XHyperlink
>& rxHlink
);
58 /// @throws uno::RuntimeException
59 bool operator()( const uno::Reference
< excel::XHyperlink
>& rxHlink
) const;
62 EqualAnchorFunctor::EqualAnchorFunctor( const uno::Reference
< excel::XHyperlink
>& rxHlink
) :
63 mnType( rxHlink
->getType() )
67 case office::MsoHyperlinkType::msoHyperlinkRange
:
68 mxAnchorRange
.set( rxHlink
->getRange(), uno::UNO_SET_THROW
);
70 case office::MsoHyperlinkType::msoHyperlinkShape
:
71 case office::MsoHyperlinkType::msoHyperlinkInlineShape
:
72 mxAnchorShape
.set( rxHlink
->getShape(), uno::UNO_SET_THROW
);
75 throw uno::RuntimeException();
79 bool EqualAnchorFunctor::operator()( const uno::Reference
< excel::XHyperlink
>& rxHlink
) const
81 sal_Int32 nType
= rxHlink
->getType();
87 case office::MsoHyperlinkType::msoHyperlinkRange
:
89 uno::Reference
< excel::XRange
> xAnchorRange( rxHlink
->getRange(), uno::UNO_SET_THROW
);
90 const ScRangeList
& rScRanges1
= ScVbaRange::getScRangeList( xAnchorRange
);
91 const ScRangeList
& rScRanges2
= ScVbaRange::getScRangeList( mxAnchorRange
);
92 return (rScRanges1
.size() == 1) && (rScRanges2
.size() == 1) && (rScRanges1
[ 0 ] == rScRanges2
[ 0 ]);
94 case office::MsoHyperlinkType::msoHyperlinkShape
:
95 case office::MsoHyperlinkType::msoHyperlinkInlineShape
:
97 uno::Reference
< msforms::XShape
> xAnchorShape( rxHlink
->getShape(), uno::UNO_SET_THROW
);
98 return xAnchorShape
.get() == mxAnchorShape
.get();
101 throw uno::RuntimeException();
109 class ScVbaHlinkContainer
: public ::cppu::WeakImplHelper
< container::XIndexAccess
>
112 /// @throws uno::RuntimeException
113 explicit ScVbaHlinkContainer();
114 /// @throws uno::RuntimeException
115 explicit ScVbaHlinkContainer( const ScVbaHlinkContainerRef
& rxSheetContainer
, const ScRangeList
& rScRanges
);
117 /** Inserts the passed hyperlink into the collection. Will remove a
118 Hyperlink object with the same anchor as the passed Hyperlink object.
120 @throws uno::RuntimeException
122 void insertHyperlink( const uno::Reference
< excel::XHyperlink
>& rxHlink
);
125 virtual sal_Int32 SAL_CALL
getCount() override
;
126 virtual uno::Any SAL_CALL
getByIndex( sal_Int32 nIndex
) override
;
129 virtual uno::Type SAL_CALL
getElementType() override
;
130 virtual sal_Bool SAL_CALL
hasElements() override
;
133 typedef ::std::vector
< uno::Reference
< excel::XHyperlink
> > HyperlinkVector
;
134 HyperlinkVector maHlinks
;
137 ScVbaHlinkContainer::ScVbaHlinkContainer()
139 // TODO FIXME: fill with existing hyperlinks
142 ScVbaHlinkContainer::ScVbaHlinkContainer( const ScVbaHlinkContainerRef
& rxSheetContainer
,
143 const ScRangeList
& rScRanges
)
145 for( sal_Int32 nIndex
= 0, nCount
= rxSheetContainer
->getCount(); nIndex
< nCount
; ++nIndex
)
147 uno::Reference
< excel::XHyperlink
> xHlink( rxSheetContainer
->getByIndex( nIndex
), uno::UNO_QUERY_THROW
);
148 uno::Reference
< excel::XRange
> xHlinkRange( xHlink
->getRange(), uno::UNO_SET_THROW
);
149 if( lclContains( rScRanges
, xHlinkRange
) )
150 maHlinks
.push_back( xHlink
);
154 void ScVbaHlinkContainer::insertHyperlink( const uno::Reference
< excel::XHyperlink
>& rxHlink
)
156 HyperlinkVector::iterator aIt
= ::std::find_if( maHlinks
.begin(), maHlinks
.end(), EqualAnchorFunctor( rxHlink
) );
157 if( aIt
== maHlinks
.end() )
158 maHlinks
.push_back( rxHlink
);
163 sal_Int32 SAL_CALL
ScVbaHlinkContainer::getCount()
165 return static_cast< sal_Int32
>( maHlinks
.size() );
168 uno::Any SAL_CALL
ScVbaHlinkContainer::getByIndex( sal_Int32 nIndex
)
170 if( (0 <= nIndex
) && (nIndex
< getCount()) )
171 return uno::Any( maHlinks
[ static_cast< size_t >( nIndex
) ] );
172 throw lang::IndexOutOfBoundsException();
175 uno::Type SAL_CALL
ScVbaHlinkContainer::getElementType()
177 return cppu::UnoType
<excel::XHyperlink
>::get();
180 sal_Bool SAL_CALL
ScVbaHlinkContainer::hasElements()
182 return !maHlinks
.empty();
185 ScVbaHlinkContainerMember::ScVbaHlinkContainerMember( ScVbaHlinkContainer
* pContainer
) :
186 mxContainer( pContainer
)
190 ScVbaHlinkContainerMember::~ScVbaHlinkContainerMember()
194 } // namespace detail
196 ScVbaHyperlinks::ScVbaHyperlinks( const uno::Reference
< XHelperInterface
>& rxParent
,
197 const uno::Reference
< uno::XComponentContext
>& rxContext
) :
198 detail::ScVbaHlinkContainerMember( new detail::ScVbaHlinkContainer
),
199 ScVbaHyperlinks_BASE( rxParent
, rxContext
, uno::Reference
< container::XIndexAccess
>( mxContainer
) )
203 ScVbaHyperlinks::ScVbaHyperlinks( const uno::Reference
< XHelperInterface
>& rxParent
,
204 const uno::Reference
< uno::XComponentContext
>& rxContext
,
205 const ScVbaHyperlinksRef
& rxSheetHlinks
, const ScRangeList
& rScRanges
) :
206 detail::ScVbaHlinkContainerMember( new detail::ScVbaHlinkContainer( rxSheetHlinks
->mxContainer
, rScRanges
) ),
207 ScVbaHyperlinks_BASE( rxParent
, rxContext
, uno::Reference
< container::XIndexAccess
>( mxContainer
) ),
208 mxSheetHlinks( rxSheetHlinks
)
212 ScVbaHyperlinks::~ScVbaHyperlinks()
216 // XHyperlinks ----------------------------------------------------------------
218 uno::Reference
< excel::XHyperlink
> SAL_CALL
ScVbaHyperlinks::Add(
219 const uno::Any
& rAnchor
, const uno::Any
& rAddress
, const uno::Any
& rSubAddress
,
220 const uno::Any
& rScreenTip
, const uno::Any
& rTextToDisplay
)
222 /* If this Hyperlinks object has been created from a Range object, the
223 call to Add() is passed to the Hyperlinks object of the parent
224 worksheet. This container will not be modified (it will not contain the
226 For details, see documentation in hyperlinks.hxx.
228 if( mxSheetHlinks
.is() )
229 return mxSheetHlinks
->Add( rAnchor
, rAddress
, rSubAddress
, rScreenTip
, rTextToDisplay
);
231 // get anchor object (can be a Range or a Shape object)
232 uno::Reference
< XHelperInterface
> xAnchor( rAnchor
, uno::UNO_QUERY_THROW
);
234 /* Create the Hyperlink object, this tries to insert the hyperlink into
235 the spreadsheet document. Parent of the Hyperlink is the anchor object. */
236 uno::Reference
< excel::XHyperlink
> xHlink( new ScVbaHyperlink(
237 xAnchor
, mxContext
, rAddress
, rSubAddress
, rScreenTip
, rTextToDisplay
) );
239 /* If creation of the hyperlink did not throw, insert it into the
241 mxContainer
->insertHyperlink( xHlink
);
245 void SAL_CALL
ScVbaHyperlinks::Delete()
247 // FIXME not implemented
248 throw uno::RuntimeException();
251 // XEnumerationAccess ---------------------------------------------------------
253 uno::Reference
< container::XEnumeration
> SAL_CALL
ScVbaHyperlinks::createEnumeration()
255 return new SimpleIndexAccessToEnumeration( m_xIndexAccess
);
258 // XElementAccess -------------------------------------------------------------
260 uno::Type SAL_CALL
ScVbaHyperlinks::getElementType()
262 return cppu::UnoType
<excel::XHyperlink
>::get();
265 // ScVbaCollectionBase --------------------------------------------------------
267 uno::Any
ScVbaHyperlinks::createCollectionObject( const uno::Any
& rSource
)
269 // container stores XHyperlink objects, just return the passed object
273 // XHelperInterface -----------------------------------------------------------
275 VBAHELPER_IMPL_XHELPERINTERFACE( ScVbaHyperlinks
, u
"ooo.vba.excel.Hyperlinks"_ustr
)
277 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */