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 .
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
;
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
),
56 void ShapeManagerImpl::activate( bool bSlideBackgoundPainted
)
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() );
69 uno::Reference
<presentation::XShapeEventListener
> xDummyListener
;
70 std::for_each( mrGlobalListenersMap
.begin(),
71 mrGlobalListenersMap
.end(),
72 boost::bind( &ShapeManagerImpl::listenerAdded
,
74 boost::cref(xDummyListener
),
76 o3tl::select1st
<ShapeEventListenerMap::value_type
>(),
80 std::for_each( mrGlobalCursorMap
.begin(),
81 mrGlobalCursorMap
.end(),
82 boost::bind( &ShapeManagerImpl::cursorChanged
,
85 o3tl::select1st
<ShapeCursorMap::value_type
>(),
88 o3tl::select2nd
<ShapeCursorMap::value_type
>(),
92 mpLayerManager
->activate( bSlideBackgoundPainted
);
96 void ShapeManagerImpl::deactivate()
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)
119 maHyperlinkShapes
.clear();
120 maShapeCursorMap
.clear();
121 maShapeListenerMap
.clear();
122 mpLayerManager
.reset();
125 bool ShapeManagerImpl::handleMousePressed( awt::MouseEvent
const& )
128 return false; // did not handle the event
131 bool ShapeManagerImpl::handleMouseReleased( awt::MouseEvent
const& e
)
133 if( !mbEnabled
|| e
.Buttons
!= awt::MouseButton::LEFT
)
136 basegfx::B2DPoint
const aPosition( e
.X
, e
.Y
);
138 // first check for hyperlinks, because these have
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
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
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
,
176 return true; // handled this event
182 return false; // did not handle this event
185 bool ShapeManagerImpl::handleMouseEntered( const awt::MouseEvent
& )
188 return false; // did not handle the event
191 bool ShapeManagerImpl::handleMouseExited( const awt::MouseEvent
& )
194 return false; // did not handle the event
197 bool ShapeManagerImpl::handleMouseDragged( const awt::MouseEvent
& )
200 return false; // did not handle the event
203 bool ShapeManagerImpl::handleMouseMoved( const awt::MouseEvent
& e
)
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
;
218 // find matching shape (scan reversely, to coarsely match
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
;
242 if( nNewCursor
== -1 )
243 mrCursorManager
.resetCursor();
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();
259 bool ShapeManagerImpl::update( ViewSharedPtr
const& /*rView*/ )
261 // am not doing view-specific updates here.
265 bool ShapeManagerImpl::needsUpdate() const
267 if( mbEnabled
&& mpLayerManager
)
268 return mpLayerManager
->isUpdatePending();
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
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
)
313 return mpLayerManager
->getSubsetShape(rOrigShape
,rTreeNode
);
315 return AttributableShapeSharedPtr();
318 void ShapeManagerImpl::revokeSubset( const AttributableShapeSharedPtr
& rOrigShape
,
319 const AttributableShapeSharedPtr
& rSubsetShape
)
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
) );
342 maShapeListenerMap
.insert(
343 ShapeToListenersMap::value_type(
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
) );
362 maShapeListenerMap
.erase(pShape
);
368 bool ShapeManagerImpl::cursorChanged( const uno::Reference
<drawing::XShape
>& xShape
,
371 ShapeSharedPtr
pShape( lookupShape(xShape
) );
373 // is this one of our shapes? other shapes are ignored.
377 if( mrGlobalCursorMap
.find(xShape
) == mrGlobalCursorMap
.end() )
379 // erased from global map - erase locally, too
380 maShapeCursorMap
.erase(pShape
);
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(
396 aIter
->second
= nCursor
;
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
;
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: */