1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shapemanagerimpl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
34 #include <canvas/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <com/sun/star/awt/MouseButton.hpp>
37 #include <com/sun/star/awt/SystemPointer.hpp>
38 #include <com/sun/star/presentation/XShapeEventListener.hpp>
39 #include <com/sun/star/presentation/XSlideShowListener.hpp>
40 #include <com/sun/star/awt/MouseButton.hpp>
42 #include "shapemanagerimpl.hxx"
44 #include <boost/bind.hpp>
46 using namespace com::sun::star
;
51 ShapeManagerImpl::ShapeManagerImpl( EventMultiplexer
& rMultiplexer
,
52 LayerManagerSharedPtr
const& rLayerManager
,
53 CursorManager
& rCursorManager
,
54 const ShapeEventListenerMap
& rGlobalListenersMap
,
55 const ShapeCursorMap
& rGlobalCursorMap
):
56 mrMultiplexer(rMultiplexer
),
57 mpLayerManager(rLayerManager
),
58 mrCursorManager(rCursorManager
),
59 mrGlobalListenersMap(rGlobalListenersMap
),
60 mrGlobalCursorMap(rGlobalCursorMap
),
68 void ShapeManagerImpl::activate( bool bSlideBackgoundPainted
)
74 // register this handler on EventMultiplexer.
75 // Higher prio (overrides other engine handlers)
76 mrMultiplexer
.addMouseMoveHandler( shared_from_this(), 2.0 );
77 mrMultiplexer
.addClickHandler( shared_from_this(), 2.0 );
78 mrMultiplexer
.addShapeListenerHandler( shared_from_this() );
81 uno::Reference
<presentation::XShapeEventListener
> xDummyListener
;
82 std::for_each( mrGlobalListenersMap
.begin(),
83 mrGlobalListenersMap
.end(),
84 boost::bind( &ShapeManagerImpl::listenerAdded
,
86 boost::cref(xDummyListener
),
88 std::select1st
<ShapeEventListenerMap::value_type
>(),
92 std::for_each( mrGlobalCursorMap
.begin(),
93 mrGlobalCursorMap
.end(),
94 boost::bind( &ShapeManagerImpl::cursorChanged
,
97 std::select1st
<ShapeCursorMap::value_type
>(),
100 std::select2nd
<ShapeCursorMap::value_type
>(),
104 mpLayerManager
->activate( bSlideBackgoundPainted
);
108 void ShapeManagerImpl::deactivate()
115 mpLayerManager
->deactivate();
117 maShapeListenerMap
.clear();
118 maShapeCursorMap
.clear();
120 mrMultiplexer
.removeShapeListenerHandler( shared_from_this() );
121 mrMultiplexer
.removeMouseMoveHandler( shared_from_this() );
122 mrMultiplexer
.removeClickHandler( shared_from_this() );
126 void ShapeManagerImpl::dispose()
128 // remove listeners (EventMultiplexer holds shared_ptr on us)
131 maHyperlinkShapes
.clear();
132 maShapeCursorMap
.clear();
133 maShapeListenerMap
.clear();
134 mpLayerManager
.reset();
137 bool ShapeManagerImpl::handleMousePressed( awt::MouseEvent
const& )
140 return false; // did not handle the event
143 bool ShapeManagerImpl::handleMouseReleased( awt::MouseEvent
const& e
)
145 if( !mbEnabled
|| e
.Buttons
!= awt::MouseButton::LEFT
)
148 basegfx::B2DPoint
const aPosition( e
.X
, e
.Y
);
150 // first check for hyperlinks, because these have
152 rtl::OUString
const hyperlink( checkForHyperlink(aPosition
) );
153 if( hyperlink
.getLength() > 0 )
155 mrMultiplexer
.notifyHyperlinkClicked(hyperlink
);
156 return true; // event consumed
159 // find matching shape (scan reversely, to coarsely match
161 ShapeToListenersMap::reverse_iterator
aCurrBroadcaster(
162 maShapeListenerMap
.rbegin() );
163 ShapeToListenersMap::reverse_iterator
const aEndBroadcasters(
164 maShapeListenerMap
.rend() );
165 while( aCurrBroadcaster
!= aEndBroadcasters
)
167 // TODO(F2): Get proper geometry polygon from the
168 // shape, to avoid having areas outside the shape
169 // react on the mouse
170 if( aCurrBroadcaster
->first
->getBounds().isInside( aPosition
) &&
171 aCurrBroadcaster
->first
->isVisible() )
173 // shape hit, and shape is visible. Raise
176 boost::shared_ptr
<cppu::OInterfaceContainerHelper
> const pCont(
177 aCurrBroadcaster
->second
);
178 uno::Reference
<drawing::XShape
> const xShape(
179 aCurrBroadcaster
->first
->getXShape() );
181 // DON'T do anything with /this/ after this point!
182 pCont
->forEach
<presentation::XShapeEventListener
>(
183 boost::bind( &presentation::XShapeEventListener::click
,
188 return true; // handled this event
194 return false; // did not handle this event
197 bool ShapeManagerImpl::handleMouseEntered( const awt::MouseEvent
& )
200 return false; // did not handle the event
203 bool ShapeManagerImpl::handleMouseExited( const awt::MouseEvent
& )
206 return false; // did not handle the event
209 bool ShapeManagerImpl::handleMouseDragged( const awt::MouseEvent
& )
212 return false; // did not handle the event
215 bool ShapeManagerImpl::handleMouseMoved( const awt::MouseEvent
& e
)
220 // find hit shape in map
221 const ::basegfx::B2DPoint
aPosition( e
.X
, e
.Y
);
222 sal_Int16
nNewCursor(-1);
224 if( checkForHyperlink(aPosition
).getLength() > 0 )
226 nNewCursor
= awt::SystemPointer::REFHAND
;
230 // find matching shape (scan reversely, to coarsely match
232 ShapeToCursorMap::reverse_iterator
aCurrCursor(
233 maShapeCursorMap
.rbegin() );
234 ShapeToCursorMap::reverse_iterator
const aEndCursors(
235 maShapeCursorMap
.rend() );
236 while( aCurrCursor
!= aEndCursors
)
238 // TODO(F2): Get proper geometry polygon from the
239 // shape, to avoid having areas outside the shape
240 // react on the mouse
241 if( aCurrCursor
->first
->getBounds().isInside( aPosition
) &&
242 aCurrCursor
->first
->isVisible() )
244 // shape found, and it's visible. set
245 // requested cursor to shape's
246 nNewCursor
= aCurrCursor
->second
;
254 if( nNewCursor
== -1 )
255 mrCursorManager
.resetCursor();
257 mrCursorManager
.requestCursor( nNewCursor
);
259 return false; // we don't /eat/ this event. Lower prio
260 // handler should see it, too.
263 bool ShapeManagerImpl::update()
265 if( mbEnabled
&& mpLayerManager
)
266 return mpLayerManager
->update();
271 bool ShapeManagerImpl::update( ViewSharedPtr
const& /*rView*/ )
273 // am not doing view-specific updates here.
277 bool ShapeManagerImpl::needsUpdate() const
279 if( mbEnabled
&& mpLayerManager
)
280 return mpLayerManager
->isUpdatePending();
285 void ShapeManagerImpl::enterAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
287 if( mbEnabled
&& mpLayerManager
)
288 mpLayerManager
->enterAnimationMode(rShape
);
291 void ShapeManagerImpl::leaveAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
293 if( mbEnabled
&& mpLayerManager
)
294 mpLayerManager
->leaveAnimationMode(rShape
);
297 void ShapeManagerImpl::notifyShapeUpdate( const ShapeSharedPtr
& rShape
)
299 if( mbEnabled
&& mpLayerManager
)
300 mpLayerManager
->notifyShapeUpdate(rShape
);
303 ShapeSharedPtr
ShapeManagerImpl::lookupShape( uno::Reference
< drawing::XShape
> const & xShape
) const
306 return mpLayerManager
->lookupShape(xShape
);
308 return ShapeSharedPtr();
311 void ShapeManagerImpl::addHyperlinkArea( const HyperlinkAreaSharedPtr
& rArea
)
313 maHyperlinkShapes
.insert(rArea
);
316 void ShapeManagerImpl::removeHyperlinkArea( const HyperlinkAreaSharedPtr
& rArea
)
318 maHyperlinkShapes
.erase(rArea
);
321 AttributableShapeSharedPtr
ShapeManagerImpl::getSubsetShape( const AttributableShapeSharedPtr
& rOrigShape
,
322 const DocTreeNode
& rTreeNode
)
325 return mpLayerManager
->getSubsetShape(rOrigShape
,rTreeNode
);
327 return AttributableShapeSharedPtr();
330 void ShapeManagerImpl::revokeSubset( const AttributableShapeSharedPtr
& rOrigShape
,
331 const AttributableShapeSharedPtr
& rSubsetShape
)
334 mpLayerManager
->revokeSubset(rOrigShape
,rSubsetShape
);
337 bool ShapeManagerImpl::listenerAdded(
338 const uno::Reference
<presentation::XShapeEventListener
>& /*xListener*/,
339 const uno::Reference
<drawing::XShape
>& xShape
)
341 ShapeEventListenerMap::const_iterator aIter
;
342 if( (aIter
= mrGlobalListenersMap
.find( xShape
)) ==
343 mrGlobalListenersMap
.end() )
345 ENSURE_OR_RETURN(false,
346 "ShapeManagerImpl::listenerAdded(): global "
347 "shape listener map inconsistency!");
350 // is this one of our shapes? other shapes are ignored.
351 ShapeSharedPtr
pShape( lookupShape(xShape
) );
354 maShapeListenerMap
.insert(
355 ShapeToListenersMap::value_type(
363 bool ShapeManagerImpl::listenerRemoved(
364 const uno::Reference
<presentation::XShapeEventListener
>& /*xListener*/,
365 const uno::Reference
<drawing::XShape
>& xShape
)
367 // shape really erased from map? maybe there are other listeners
368 // for the same shape pending...
369 if( mrGlobalListenersMap
.find(xShape
) == mrGlobalListenersMap
.end() )
371 // is this one of our shapes? other shapes are ignored.
372 ShapeSharedPtr
pShape( lookupShape(xShape
) );
374 maShapeListenerMap
.erase(pShape
);
380 bool ShapeManagerImpl::cursorChanged( const uno::Reference
<drawing::XShape
>& xShape
,
383 ShapeSharedPtr
pShape( lookupShape(xShape
) );
385 // is this one of our shapes? other shapes are ignored.
389 if( mrGlobalCursorMap
.find(xShape
) == mrGlobalCursorMap
.end() )
391 // erased from global map - erase locally, too
392 maShapeCursorMap
.erase(pShape
);
396 // included in global map - update local one
397 ShapeToCursorMap::iterator aIter
;
398 if( (aIter
= maShapeCursorMap
.find(pShape
))
399 == maShapeCursorMap
.end() )
401 maShapeCursorMap
.insert(
402 ShapeToCursorMap::value_type(
408 aIter
->second
= nCursor
;
415 rtl::OUString
ShapeManagerImpl::checkForHyperlink( basegfx::B2DPoint
const& hitPos
) const
417 // find matching region (scan reversely, to coarsely match
418 // paint order): set is ordered by priority
419 AreaSet::const_reverse_iterator
iPos( maHyperlinkShapes
.rbegin() );
420 AreaSet::const_reverse_iterator
const iEnd( maHyperlinkShapes
.rend() );
421 for( ; iPos
!= iEnd
; ++iPos
)
423 HyperlinkAreaSharedPtr
const& pArea
= *iPos
;
425 HyperlinkArea::HyperlinkRegions
const linkRegions(
426 pArea
->getHyperlinkRegions() );
428 for( std::size_t i
= linkRegions
.size(); i
--; )
430 basegfx::B2DRange
const& region
= linkRegions
[i
].first
;
431 if( region
.isInside(hitPos
) )
432 return linkRegions
[i
].second
;
436 return rtl::OUString();
439 void ShapeManagerImpl::addIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr
& rHandler
)
441 maIntrinsicAnimationEventHandlers
.add( rHandler
);
444 void ShapeManagerImpl::removeIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr
& rHandler
)
446 maIntrinsicAnimationEventHandlers
.remove( rHandler
);
449 bool ShapeManagerImpl::notifyIntrinsicAnimationsEnabled()
451 return maIntrinsicAnimationEventHandlers
.applyAll(
452 boost::mem_fn(&IntrinsicAnimationEventHandler::enableAnimations
));
455 bool ShapeManagerImpl::notifyIntrinsicAnimationsDisabled()
457 return maIntrinsicAnimationEventHandlers
.applyAll(
458 boost::mem_fn(&IntrinsicAnimationEventHandler::disableAnimations
));
463 } // namespace internal
464 } // namespace presentation