fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / slideshow / source / engine / slide / shapemanagerimpl.cxx
bloba8d324838bcf932ecedba319d75f3ef5c01bdcda
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 .
21 #include <canvas/debug.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/presentation/XSlideShowListener.hpp>
28 #include "shapemanagerimpl.hxx"
30 #include <boost/bind.hpp>
32 #include <o3tl/compat_functional.hxx>
34 using namespace com::sun::star;
36 namespace slideshow {
37 namespace internal {
39 ShapeManagerImpl::ShapeManagerImpl( EventMultiplexer& rMultiplexer,
40 LayerManagerSharedPtr const& rLayerManager,
41 CursorManager& rCursorManager,
42 const ShapeEventListenerMap& rGlobalListenersMap,
43 const ShapeCursorMap& rGlobalCursorMap ):
44 mrMultiplexer(rMultiplexer),
45 mpLayerManager(rLayerManager),
46 mrCursorManager(rCursorManager),
47 mrGlobalListenersMap(rGlobalListenersMap),
48 mrGlobalCursorMap(rGlobalCursorMap),
49 maShapeListenerMap(),
50 maShapeCursorMap(),
51 maHyperlinkShapes(),
52 mbEnabled(false)
56 void ShapeManagerImpl::activate( bool bSlideBackgoundPainted )
58 if( !mbEnabled )
60 mbEnabled = true;
62 // register this handler on EventMultiplexer.
63 // Higher prio (overrides other engine handlers)
64 mrMultiplexer.addMouseMoveHandler( shared_from_this(), 2.0 );
65 mrMultiplexer.addClickHandler( shared_from_this(), 2.0 );
66 mrMultiplexer.addShapeListenerHandler( shared_from_this() );
68 // clone listener map
69 uno::Reference<presentation::XShapeEventListener> xDummyListener;
70 std::for_each( mrGlobalListenersMap.begin(),
71 mrGlobalListenersMap.end(),
72 boost::bind( &ShapeManagerImpl::listenerAdded,
73 this,
74 boost::cref(xDummyListener),
75 boost::bind(
76 o3tl::select1st<ShapeEventListenerMap::value_type>(),
77 _1 )));
79 // clone cursor map
80 std::for_each( mrGlobalCursorMap.begin(),
81 mrGlobalCursorMap.end(),
82 boost::bind( &ShapeManagerImpl::cursorChanged,
83 this,
84 boost::bind(
85 o3tl::select1st<ShapeCursorMap::value_type>(),
86 _1 ),
87 boost::bind(
88 o3tl::select2nd<ShapeCursorMap::value_type>(),
89 _1 )));
91 if( mpLayerManager )
92 mpLayerManager->activate( bSlideBackgoundPainted );
96 void ShapeManagerImpl::deactivate()
98 if( mbEnabled )
100 mbEnabled = false;
102 if( mpLayerManager )
103 mpLayerManager->deactivate();
105 maShapeListenerMap.clear();
106 maShapeCursorMap.clear();
108 mrMultiplexer.removeShapeListenerHandler( shared_from_this() );
109 mrMultiplexer.removeMouseMoveHandler( shared_from_this() );
110 mrMultiplexer.removeClickHandler( shared_from_this() );
114 void ShapeManagerImpl::dispose()
116 // remove listeners (EventMultiplexer holds shared_ptr on us)
117 deactivate();
119 maHyperlinkShapes.clear();
120 maShapeCursorMap.clear();
121 maShapeListenerMap.clear();
122 mpLayerManager.reset();
125 bool ShapeManagerImpl::handleMousePressed( awt::MouseEvent const& )
127 // not used here
128 return false; // did not handle the event
131 bool ShapeManagerImpl::handleMouseReleased( awt::MouseEvent const& e )
133 if( !mbEnabled || e.Buttons != awt::MouseButton::LEFT)
134 return false;
136 basegfx::B2DPoint const aPosition( e.X, e.Y );
138 // first check for hyperlinks, because these have
139 // highest prio:
140 OUString const hyperlink( checkForHyperlink(aPosition) );
141 if( !hyperlink.isEmpty() )
143 mrMultiplexer.notifyHyperlinkClicked(hyperlink);
144 return true; // event consumed
147 // find matching shape (scan reversely, to coarsely match
148 // paint order)
149 ShapeToListenersMap::reverse_iterator aCurrBroadcaster(
150 maShapeListenerMap.rbegin() );
151 ShapeToListenersMap::reverse_iterator const aEndBroadcasters(
152 maShapeListenerMap.rend() );
153 while( aCurrBroadcaster != aEndBroadcasters )
155 // TODO(F2): Get proper geometry polygon from the
156 // shape, to avoid having areas outside the shape
157 // react on the mouse
158 if( aCurrBroadcaster->first->getBounds().isInside( aPosition ) &&
159 aCurrBroadcaster->first->isVisible() )
161 // shape hit, and shape is visible. Raise
162 // event.
164 boost::shared_ptr<cppu::OInterfaceContainerHelper> 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 boost::bind( &presentation::XShapeEventListener::click,
173 boost::cref(xShape),
174 boost::cref(e) ));
176 return true; // handled this event
179 ++aCurrBroadcaster;
182 return false; // did not handle this event
185 bool ShapeManagerImpl::handleMouseEntered( const awt::MouseEvent& )
187 // not used here
188 return false; // did not handle the event
191 bool ShapeManagerImpl::handleMouseExited( const awt::MouseEvent& )
193 // not used here
194 return false; // did not handle the event
197 bool ShapeManagerImpl::handleMouseDragged( const awt::MouseEvent& )
199 // not used here
200 return false; // did not handle the event
203 bool ShapeManagerImpl::handleMouseMoved( const awt::MouseEvent& e )
205 if( !mbEnabled )
206 return false;
208 // find hit shape in map
209 const ::basegfx::B2DPoint aPosition( e.X, e.Y );
210 sal_Int16 nNewCursor(-1);
212 if( !checkForHyperlink(aPosition).isEmpty() )
214 nNewCursor = awt::SystemPointer::REFHAND;
216 else
218 // find matching shape (scan reversely, to coarsely match
219 // paint order)
220 ShapeToCursorMap::reverse_iterator aCurrCursor(
221 maShapeCursorMap.rbegin() );
222 ShapeToCursorMap::reverse_iterator const aEndCursors(
223 maShapeCursorMap.rend() );
224 while( aCurrCursor != aEndCursors )
226 // TODO(F2): Get proper geometry polygon from the
227 // shape, to avoid having areas outside the shape
228 // react on the mouse
229 if( aCurrCursor->first->getBounds().isInside( aPosition ) &&
230 aCurrCursor->first->isVisible() )
232 // shape found, and it's visible. set
233 // requested cursor to shape's
234 nNewCursor = aCurrCursor->second;
235 break;
238 ++aCurrCursor;
242 if( nNewCursor == -1 )
243 mrCursorManager.resetCursor();
244 else
245 mrCursorManager.requestCursor( nNewCursor );
247 return false; // we don't /eat/ this event. Lower prio
248 // handler should see it, too.
251 bool ShapeManagerImpl::update()
253 if( mbEnabled && mpLayerManager )
254 return mpLayerManager->update();
256 return false;
259 bool ShapeManagerImpl::update( ViewSharedPtr const& /*rView*/ )
261 // am not doing view-specific updates here.
262 return false;
265 bool ShapeManagerImpl::needsUpdate() const
267 if( mbEnabled && mpLayerManager )
268 return mpLayerManager->isUpdatePending();
270 return false;
273 void ShapeManagerImpl::enterAnimationMode( const AnimatableShapeSharedPtr& rShape )
275 if( mbEnabled && mpLayerManager )
276 mpLayerManager->enterAnimationMode(rShape);
279 void ShapeManagerImpl::leaveAnimationMode( const AnimatableShapeSharedPtr& rShape )
281 if( mbEnabled && mpLayerManager )
282 mpLayerManager->leaveAnimationMode(rShape);
285 void ShapeManagerImpl::notifyShapeUpdate( const ShapeSharedPtr& rShape )
287 if( mbEnabled && mpLayerManager )
288 mpLayerManager->notifyShapeUpdate(rShape);
291 ShapeSharedPtr ShapeManagerImpl::lookupShape( uno::Reference< drawing::XShape > const & xShape ) const
293 if( mpLayerManager )
294 return mpLayerManager->lookupShape(xShape);
296 return ShapeSharedPtr();
299 void ShapeManagerImpl::addHyperlinkArea( const HyperlinkAreaSharedPtr& rArea )
301 maHyperlinkShapes.insert(rArea);
304 void ShapeManagerImpl::removeHyperlinkArea( const HyperlinkAreaSharedPtr& rArea )
306 maHyperlinkShapes.erase(rArea);
309 AttributableShapeSharedPtr ShapeManagerImpl::getSubsetShape( const AttributableShapeSharedPtr& rOrigShape,
310 const DocTreeNode& rTreeNode )
312 if( mpLayerManager )
313 return mpLayerManager->getSubsetShape(rOrigShape,rTreeNode);
315 return AttributableShapeSharedPtr();
318 void ShapeManagerImpl::revokeSubset( const AttributableShapeSharedPtr& rOrigShape,
319 const AttributableShapeSharedPtr& rSubsetShape )
321 if( mpLayerManager )
322 mpLayerManager->revokeSubset(rOrigShape,rSubsetShape);
325 bool ShapeManagerImpl::listenerAdded(
326 const uno::Reference<presentation::XShapeEventListener>& /*xListener*/,
327 const uno::Reference<drawing::XShape>& xShape )
329 ShapeEventListenerMap::const_iterator aIter;
330 if( (aIter = mrGlobalListenersMap.find( xShape )) ==
331 mrGlobalListenersMap.end() )
333 ENSURE_OR_RETURN_FALSE(false,
334 "ShapeManagerImpl::listenerAdded(): global "
335 "shape listener map inconsistency!");
338 // is this one of our shapes? other shapes are ignored.
339 ShapeSharedPtr pShape( lookupShape(xShape) );
340 if( pShape )
342 maShapeListenerMap.insert(
343 ShapeToListenersMap::value_type(
344 pShape,
345 aIter->second));
348 return true;
351 bool ShapeManagerImpl::listenerRemoved(
352 const uno::Reference<presentation::XShapeEventListener>& /*xListener*/,
353 const uno::Reference<drawing::XShape>& xShape )
355 // shape really erased from map? maybe there are other listeners
356 // for the same shape pending...
357 if( mrGlobalListenersMap.find(xShape) == mrGlobalListenersMap.end() )
359 // is this one of our shapes? other shapes are ignored.
360 ShapeSharedPtr pShape( lookupShape(xShape) );
361 if( pShape )
362 maShapeListenerMap.erase(pShape);
365 return true;
368 bool ShapeManagerImpl::cursorChanged( const uno::Reference<drawing::XShape>& xShape,
369 sal_Int16 nCursor )
371 ShapeSharedPtr pShape( lookupShape(xShape) );
373 // is this one of our shapes? other shapes are ignored.
374 if( !pShape )
375 return false;
377 if( mrGlobalCursorMap.find(xShape) == mrGlobalCursorMap.end() )
379 // erased from global map - erase locally, too
380 maShapeCursorMap.erase(pShape);
382 else
384 // included in global map - update local one
385 ShapeToCursorMap::iterator aIter;
386 if( (aIter = maShapeCursorMap.find(pShape))
387 == maShapeCursorMap.end() )
389 maShapeCursorMap.insert(
390 ShapeToCursorMap::value_type(
391 pShape,
392 nCursor ));
394 else
396 aIter->second = nCursor;
400 return true;
403 OUString ShapeManagerImpl::checkForHyperlink( basegfx::B2DPoint const& hitPos ) const
405 // find matching region (scan reversely, to coarsely match
406 // paint order): set is ordered by priority
407 AreaSet::const_reverse_iterator iPos( maHyperlinkShapes.rbegin() );
408 AreaSet::const_reverse_iterator const iEnd( maHyperlinkShapes.rend() );
409 for( ; iPos != iEnd; ++iPos )
411 HyperlinkAreaSharedPtr const& pArea = *iPos;
413 HyperlinkArea::HyperlinkRegions const linkRegions(
414 pArea->getHyperlinkRegions() );
416 for( std::size_t i = linkRegions.size(); i--; )
418 basegfx::B2DRange const& region = linkRegions[i].first;
419 if( region.isInside(hitPos) )
420 return linkRegions[i].second;
424 return OUString();
427 void ShapeManagerImpl::addIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler )
429 maIntrinsicAnimationEventHandlers.add( rHandler );
432 void ShapeManagerImpl::removeIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr& rHandler )
434 maIntrinsicAnimationEventHandlers.remove( rHandler );
437 bool ShapeManagerImpl::notifyIntrinsicAnimationsEnabled()
439 return maIntrinsicAnimationEventHandlers.applyAll(
440 boost::mem_fn(&IntrinsicAnimationEventHandler::enableAnimations));
443 bool ShapeManagerImpl::notifyIntrinsicAnimationsDisabled()
445 return maIntrinsicAnimationEventHandlers.applyAll(
446 boost::mem_fn(&IntrinsicAnimationEventHandler::disableAnimations));
451 } // namespace internal
452 } // namespace presentation
454 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */