Use o3tl::convert in Math
[LibreOffice.git] / slideshow / source / engine / slide / shapemanagerimpl.cxx
blob73c7cda1ac02735df0ba67d687fc3913925faab1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <comphelper/processfactory.hxx>
21 #include <comphelper/servicehelper.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <com/sun/star/awt/MouseButton.hpp>
24 #include <com/sun/star/awt/SystemPointer.hpp>
25 #include <com/sun/star/presentation/XShapeEventListener.hpp>
26 #include <com/sun/star/system/SystemShellExecute.hpp>
27 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
28 #include <com/sun/star/system/XSystemShellExecute.hpp>
29 #include <svx/unoshape.hxx>
30 #include <svx/ImageMapInfo.hxx>
32 #include "shapemanagerimpl.hxx"
34 #include <functional>
36 using namespace css;
37 using namespace css::uno;
38 using namespace css::drawing;
39 using namespace css::system;
41 namespace slideshow::internal {
43 ShapeManagerImpl::ShapeManagerImpl( EventMultiplexer& rMultiplexer,
44 LayerManagerSharedPtr const& rLayerManager,
45 CursorManager& rCursorManager,
46 const ShapeEventListenerMap& rGlobalListenersMap,
47 const ShapeCursorMap& rGlobalCursorMap,
48 const Reference<XDrawPage>& xDrawPage ):
49 mrMultiplexer(rMultiplexer),
50 mpLayerManager(rLayerManager),
51 mrCursorManager(rCursorManager),
52 mrGlobalListenersMap(rGlobalListenersMap),
53 mrGlobalCursorMap(rGlobalCursorMap),
54 maShapeListenerMap(),
55 maShapeCursorMap(),
56 maHyperlinkShapes(),
57 mbEnabled(false),
58 mxDrawPage(xDrawPage)
62 void ShapeManagerImpl::activate()
64 if( mbEnabled )
65 return;
67 mbEnabled = true;
69 // register this handler on EventMultiplexer.
70 // Higher prio (overrides other engine handlers)
71 mrMultiplexer.addMouseMoveHandler( shared_from_this(), 2.0 );
72 mrMultiplexer.addClickHandler( shared_from_this(), 2.0 );
73 mrMultiplexer.addShapeListenerHandler( shared_from_this() );
75 // clone listener map
76 for( const auto& rListener : mrGlobalListenersMap )
77 listenerAdded( rListener.first );
79 // clone cursor map
80 for( const auto& rListener : mrGlobalCursorMap )
81 cursorChanged( rListener.first, rListener.second );
83 if( mpLayerManager )
84 mpLayerManager->activate();
87 void ShapeManagerImpl::deactivate()
89 if( !mbEnabled )
90 return;
92 mbEnabled = false;
94 if( mpLayerManager )
95 mpLayerManager->deactivate();
97 maShapeListenerMap.clear();
98 maShapeCursorMap.clear();
100 mrMultiplexer.removeShapeListenerHandler( shared_from_this() );
101 mrMultiplexer.removeMouseMoveHandler( shared_from_this() );
102 mrMultiplexer.removeClickHandler( shared_from_this() );
105 void ShapeManagerImpl::dispose()
107 // remove listeners (EventMultiplexer holds shared_ptr on us)
108 deactivate();
110 maHyperlinkShapes.clear();
111 maShapeCursorMap.clear();
112 maShapeListenerMap.clear();
113 mpLayerManager.reset();
116 bool ShapeManagerImpl::handleMousePressed( awt::MouseEvent const& )
118 // not used here
119 return false; // did not handle the event
122 bool ShapeManagerImpl::handleMouseReleased( awt::MouseEvent const& e )
124 if( !mbEnabled || e.Buttons != awt::MouseButton::LEFT)
125 return false;
127 basegfx::B2DPoint const aPosition( e.X, e.Y );
129 // first check for hyperlinks, because these have
130 // highest prio:
131 OUString const hyperlink( checkForHyperlink(aPosition) );
132 if( !hyperlink.isEmpty() )
134 mrMultiplexer.notifyHyperlinkClicked(hyperlink);
135 return true; // event consumed
138 // tdf#74045 Handle ImageMaps
139 OUString const imageMapLink(checkForImageMap(e));
140 if (!imageMapLink.isEmpty())
142 Reference<XSystemShellExecute> exec(
143 SystemShellExecute::create(comphelper::getProcessComponentContext()));
144 exec->execute(imageMapLink, OUString(), SystemShellExecuteFlags::URIS_ONLY);
146 return true;
149 // find matching shape (scan reversely, to coarsely match
150 // paint order)
151 auto aCurrBroadcaster = std::find_if(maShapeListenerMap.rbegin(), maShapeListenerMap.rend(),
152 [&aPosition](const ShapeToListenersMap::value_type& rBroadcaster) {
153 // TODO(F2): Get proper geometry polygon from the
154 // shape, to avoid having areas outside the shape
155 // react on the mouse
156 return rBroadcaster.first->getBounds().isInside( aPosition )
157 && rBroadcaster.first->isVisible();
159 if (aCurrBroadcaster != maShapeListenerMap.rend())
161 // shape hit, and shape is visible. Raise
162 // event.
164 std::shared_ptr<comphelper::OInterfaceContainerHelper2> const pCont(
165 aCurrBroadcaster->second );
166 uno::Reference<drawing::XShape> const xShape(
167 aCurrBroadcaster->first->getXShape() );
169 // DON'T do anything with /this/ after this point!
170 pCont->forEach<presentation::XShapeEventListener>(
171 [&xShape, &e]( const uno::Reference< presentation::XShapeEventListener >& rListener )
172 { return rListener->click( xShape, e ); } );
174 return true; // handled this event
177 return false; // did not handle this event
180 bool ShapeManagerImpl::handleMouseDragged( const awt::MouseEvent& )
182 // not used here
183 return false; // did not handle the event
186 bool ShapeManagerImpl::handleMouseMoved( const awt::MouseEvent& e )
188 if( !mbEnabled )
189 return false;
191 // find hit shape in map
192 const ::basegfx::B2DPoint aPosition( e.X, e.Y );
193 sal_Int16 nNewCursor(-1);
195 if( !checkForHyperlink(aPosition).isEmpty() || !checkForImageMap(e).isEmpty() )
197 nNewCursor = awt::SystemPointer::REFHAND;
199 else
201 // find matching shape (scan reversely, to coarsely match
202 // paint order)
203 auto aCurrCursor = std::find_if(maShapeCursorMap.rbegin(), maShapeCursorMap.rend(),
204 [&aPosition](const ShapeToCursorMap::value_type& rCursor) {
205 // TODO(F2): Get proper geometry polygon from the
206 // shape, to avoid having areas outside the shape
207 // react on the mouse
208 return rCursor.first->getBounds().isInside( aPosition )
209 && rCursor.first->isVisible();
211 if (aCurrCursor != maShapeCursorMap.rend())
213 // shape found, and it's visible. set
214 // requested cursor to shape's
215 nNewCursor = aCurrCursor->second;
219 if( nNewCursor == -1 )
220 mrCursorManager.resetCursor();
221 else
222 mrCursorManager.requestCursor( nNewCursor );
224 return false; // we don't /eat/ this event. Lower prio
225 // handler should see it, too.
228 bool ShapeManagerImpl::update()
230 if( mbEnabled && mpLayerManager )
231 return mpLayerManager->update();
233 return false;
236 bool ShapeManagerImpl::needsUpdate() const
238 if( mbEnabled && mpLayerManager )
239 return mpLayerManager->isUpdatePending();
241 return false;
244 void ShapeManagerImpl::enterAnimationMode( const AnimatableShapeSharedPtr& rShape )
246 if( mbEnabled && mpLayerManager )
247 mpLayerManager->enterAnimationMode(rShape);
250 void ShapeManagerImpl::leaveAnimationMode( const AnimatableShapeSharedPtr& rShape )
252 if( mbEnabled && mpLayerManager )
253 mpLayerManager->leaveAnimationMode(rShape);
256 void ShapeManagerImpl::notifyShapeUpdate( const ShapeSharedPtr& rShape )
258 if( mbEnabled && mpLayerManager )
259 mpLayerManager->notifyShapeUpdate(rShape);
262 ShapeSharedPtr ShapeManagerImpl::lookupShape( uno::Reference< drawing::XShape > const & xShape ) const
264 if( mpLayerManager )
265 return mpLayerManager->lookupShape(xShape);
267 return ShapeSharedPtr();
270 const XShapeToShapeMap& ShapeManagerImpl::getXShapeToShapeMap() const
272 assert( mpLayerManager );
273 return mpLayerManager->getXShapeToShapeMap();
276 void ShapeManagerImpl::addHyperlinkArea( const HyperlinkAreaSharedPtr& rArea )
278 maHyperlinkShapes.insert(rArea);
281 AttributableShapeSharedPtr ShapeManagerImpl::getSubsetShape( const AttributableShapeSharedPtr& rOrigShape,
282 const DocTreeNode& rTreeNode )
284 if( mpLayerManager )
285 return mpLayerManager->getSubsetShape(rOrigShape,rTreeNode);
287 return AttributableShapeSharedPtr();
290 void ShapeManagerImpl::revokeSubset( const AttributableShapeSharedPtr& rOrigShape,
291 const AttributableShapeSharedPtr& rSubsetShape )
293 if( mpLayerManager )
294 mpLayerManager->revokeSubset(rOrigShape,rSubsetShape);
297 bool ShapeManagerImpl::listenerAdded(
298 const uno::Reference<drawing::XShape>& xShape )
300 ShapeEventListenerMap::const_iterator aIter;
301 if( (aIter = mrGlobalListenersMap.find( xShape )) ==
302 mrGlobalListenersMap.end() )
304 ENSURE_OR_RETURN_FALSE(false,
305 "ShapeManagerImpl::listenerAdded(): global "
306 "shape listener map inconsistency!");
309 // is this one of our shapes? other shapes are ignored.
310 ShapeSharedPtr pShape( lookupShape(xShape) );
311 if( pShape )
313 maShapeListenerMap.emplace(pShape, aIter->second);
316 return true;
319 bool ShapeManagerImpl::listenerRemoved( const uno::Reference<drawing::XShape>& xShape )
321 // shape really erased from map? maybe there are other listeners
322 // for the same shape pending...
323 if( mrGlobalListenersMap.find(xShape) == mrGlobalListenersMap.end() )
325 // is this one of our shapes? other shapes are ignored.
326 ShapeSharedPtr pShape( lookupShape(xShape) );
327 if( pShape )
328 maShapeListenerMap.erase(pShape);
331 return true;
334 void ShapeManagerImpl::cursorChanged( const uno::Reference<drawing::XShape>& xShape,
335 sal_Int16 nCursor )
337 ShapeSharedPtr pShape( lookupShape(xShape) );
339 // is this one of our shapes? other shapes are ignored.
340 if( !pShape )
341 return;
343 if( mrGlobalCursorMap.find(xShape) == mrGlobalCursorMap.end() )
345 // erased from global map - erase locally, too
346 maShapeCursorMap.erase(pShape);
348 else
350 // included in global map - update local one
351 ShapeToCursorMap::iterator aIter;
352 if( (aIter = maShapeCursorMap.find(pShape))
353 == maShapeCursorMap.end() )
355 maShapeCursorMap.emplace(pShape, nCursor);
357 else
359 aIter->second = nCursor;
364 OUString ShapeManagerImpl::checkForHyperlink( basegfx::B2DPoint const& hitPos ) const
366 // find matching region (scan reversely, to coarsely match
367 // paint order): set is ordered by priority
368 AreaSet::const_reverse_iterator iPos( maHyperlinkShapes.rbegin() );
369 AreaSet::const_reverse_iterator const iEnd( maHyperlinkShapes.rend() );
370 for( ; iPos != iEnd; ++iPos )
372 HyperlinkAreaSharedPtr const& pArea = *iPos;
374 HyperlinkArea::HyperlinkRegions const linkRegions(
375 pArea->getHyperlinkRegions() );
377 for( std::size_t i = linkRegions.size(); i--; )
379 basegfx::B2DRange const& region = linkRegions[i].first;
380 if( region.isInside(hitPos) )
381 return linkRegions[i].second;
385 return OUString();
388 OUString ShapeManagerImpl::checkForImageMap( awt::MouseEvent const& evt ) const
390 for (sal_Int32 i = 0; i < mxDrawPage->getCount(); i++)
392 Reference<XShape> xShape(mxDrawPage->getByIndex(i), UNO_QUERY_THROW);
393 SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape);
394 if (!pObj)
395 continue;
396 const IMapObject* pIMapObj = SvxIMapInfo::GetHitIMapObject(pObj, Point(evt.X, evt.Y));
397 if (pIMapObj && !pIMapObj->GetURL().isEmpty())
399 return pIMapObj->GetURL();
402 return OUString();
405 void ShapeManagerImpl::addIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler )
407 maIntrinsicAnimationEventHandlers.add( rHandler );
410 void ShapeManagerImpl::removeIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler )
412 maIntrinsicAnimationEventHandlers.remove( rHandler );
415 void ShapeManagerImpl::notifyIntrinsicAnimationsEnabled()
417 maIntrinsicAnimationEventHandlers.applyAll(
418 std::mem_fn(&IntrinsicAnimationEventHandler::enableAnimations));
421 void ShapeManagerImpl::notifyIntrinsicAnimationsDisabled()
423 maIntrinsicAnimationEventHandlers.applyAll(
424 std::mem_fn(&IntrinsicAnimationEventHandler::disableAnimations));
428 } // namespace slideshow::internal
430 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */