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 <tools/diagnose_ex.h>
22 #include <com/sun/star/awt/MouseButton.hpp>
23 #include <com/sun/star/awt/SystemPointer.hpp>
24 #include <com/sun/star/presentation/XShapeEventListener.hpp>
26 #include "shapemanagerimpl.hxx"
30 using namespace com::sun::star
;
35 ShapeManagerImpl::ShapeManagerImpl( EventMultiplexer
& rMultiplexer
,
36 LayerManagerSharedPtr
const& rLayerManager
,
37 CursorManager
& rCursorManager
,
38 const ShapeEventListenerMap
& rGlobalListenersMap
,
39 const ShapeCursorMap
& rGlobalCursorMap
):
40 mrMultiplexer(rMultiplexer
),
41 mpLayerManager(rLayerManager
),
42 mrCursorManager(rCursorManager
),
43 mrGlobalListenersMap(rGlobalListenersMap
),
44 mrGlobalCursorMap(rGlobalCursorMap
),
52 void ShapeManagerImpl::activate()
58 // register this handler on EventMultiplexer.
59 // Higher prio (overrides other engine handlers)
60 mrMultiplexer
.addMouseMoveHandler( shared_from_this(), 2.0 );
61 mrMultiplexer
.addClickHandler( shared_from_this(), 2.0 );
62 mrMultiplexer
.addShapeListenerHandler( shared_from_this() );
65 uno::Reference
<presentation::XShapeEventListener
> xDummyListener
;
66 for( const auto& rListener
: mrGlobalListenersMap
)
67 listenerAdded( xDummyListener
, rListener
.first
);
70 for( const auto& rListener
: mrGlobalCursorMap
)
71 cursorChanged( rListener
.first
, rListener
.second
);
74 mpLayerManager
->activate();
78 void ShapeManagerImpl::deactivate()
85 mpLayerManager
->deactivate();
87 maShapeListenerMap
.clear();
88 maShapeCursorMap
.clear();
90 mrMultiplexer
.removeShapeListenerHandler( shared_from_this() );
91 mrMultiplexer
.removeMouseMoveHandler( shared_from_this() );
92 mrMultiplexer
.removeClickHandler( shared_from_this() );
96 void ShapeManagerImpl::dispose()
98 // remove listeners (EventMultiplexer holds shared_ptr on us)
101 maHyperlinkShapes
.clear();
102 maShapeCursorMap
.clear();
103 maShapeListenerMap
.clear();
104 mpLayerManager
.reset();
107 bool ShapeManagerImpl::handleMousePressed( awt::MouseEvent
const& )
110 return false; // did not handle the event
113 bool ShapeManagerImpl::handleMouseReleased( awt::MouseEvent
const& e
)
115 if( !mbEnabled
|| e
.Buttons
!= awt::MouseButton::LEFT
)
118 basegfx::B2DPoint
const aPosition( e
.X
, e
.Y
);
120 // first check for hyperlinks, because these have
122 OUString
const hyperlink( checkForHyperlink(aPosition
) );
123 if( !hyperlink
.isEmpty() )
125 mrMultiplexer
.notifyHyperlinkClicked(hyperlink
);
126 return true; // event consumed
129 // find matching shape (scan reversely, to coarsely match
131 ShapeToListenersMap::reverse_iterator
aCurrBroadcaster(
132 maShapeListenerMap
.rbegin() );
133 ShapeToListenersMap::reverse_iterator
const aEndBroadcasters(
134 maShapeListenerMap
.rend() );
135 while( aCurrBroadcaster
!= aEndBroadcasters
)
137 // TODO(F2): Get proper geometry polygon from the
138 // shape, to avoid having areas outside the shape
139 // react on the mouse
140 if( aCurrBroadcaster
->first
->getBounds().isInside( aPosition
) &&
141 aCurrBroadcaster
->first
->isVisible() )
143 // shape hit, and shape is visible. Raise
146 std::shared_ptr
<comphelper::OInterfaceContainerHelper2
> const pCont(
147 aCurrBroadcaster
->second
);
148 uno::Reference
<drawing::XShape
> const xShape(
149 aCurrBroadcaster
->first
->getXShape() );
151 // DON'T do anything with /this/ after this point!
152 pCont
->forEach
<presentation::XShapeEventListener
>(
153 [&xShape
, &e
]( const uno::Reference
< presentation::XShapeEventListener
>& rListener
)
154 { return rListener
->click( xShape
, e
); } );
156 return true; // handled this event
162 return false; // did not handle this event
165 bool ShapeManagerImpl::handleMouseDragged( const awt::MouseEvent
& )
168 return false; // did not handle the event
171 bool ShapeManagerImpl::handleMouseMoved( const awt::MouseEvent
& e
)
176 // find hit shape in map
177 const ::basegfx::B2DPoint
aPosition( e
.X
, e
.Y
);
178 sal_Int16
nNewCursor(-1);
180 if( !checkForHyperlink(aPosition
).isEmpty() )
182 nNewCursor
= awt::SystemPointer::REFHAND
;
186 // find matching shape (scan reversely, to coarsely match
188 ShapeToCursorMap::reverse_iterator
aCurrCursor(
189 maShapeCursorMap
.rbegin() );
190 ShapeToCursorMap::reverse_iterator
const aEndCursors(
191 maShapeCursorMap
.rend() );
192 while( aCurrCursor
!= aEndCursors
)
194 // TODO(F2): Get proper geometry polygon from the
195 // shape, to avoid having areas outside the shape
196 // react on the mouse
197 if( aCurrCursor
->first
->getBounds().isInside( aPosition
) &&
198 aCurrCursor
->first
->isVisible() )
200 // shape found, and it's visible. set
201 // requested cursor to shape's
202 nNewCursor
= aCurrCursor
->second
;
210 if( nNewCursor
== -1 )
211 mrCursorManager
.resetCursor();
213 mrCursorManager
.requestCursor( nNewCursor
);
215 return false; // we don't /eat/ this event. Lower prio
216 // handler should see it, too.
219 bool ShapeManagerImpl::update()
221 if( mbEnabled
&& mpLayerManager
)
222 return mpLayerManager
->update();
227 bool ShapeManagerImpl::needsUpdate() const
229 if( mbEnabled
&& mpLayerManager
)
230 return mpLayerManager
->isUpdatePending();
235 void ShapeManagerImpl::enterAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
237 if( mbEnabled
&& mpLayerManager
)
238 mpLayerManager
->enterAnimationMode(rShape
);
241 void ShapeManagerImpl::leaveAnimationMode( const AnimatableShapeSharedPtr
& rShape
)
243 if( mbEnabled
&& mpLayerManager
)
244 mpLayerManager
->leaveAnimationMode(rShape
);
247 void ShapeManagerImpl::notifyShapeUpdate( const ShapeSharedPtr
& rShape
)
249 if( mbEnabled
&& mpLayerManager
)
250 mpLayerManager
->notifyShapeUpdate(rShape
);
253 ShapeSharedPtr
ShapeManagerImpl::lookupShape( uno::Reference
< drawing::XShape
> const & xShape
) const
256 return mpLayerManager
->lookupShape(xShape
);
258 return ShapeSharedPtr();
261 void ShapeManagerImpl::addHyperlinkArea( const HyperlinkAreaSharedPtr
& rArea
)
263 maHyperlinkShapes
.insert(rArea
);
266 AttributableShapeSharedPtr
ShapeManagerImpl::getSubsetShape( const AttributableShapeSharedPtr
& rOrigShape
,
267 const DocTreeNode
& rTreeNode
)
270 return mpLayerManager
->getSubsetShape(rOrigShape
,rTreeNode
);
272 return AttributableShapeSharedPtr();
275 void ShapeManagerImpl::revokeSubset( const AttributableShapeSharedPtr
& rOrigShape
,
276 const AttributableShapeSharedPtr
& rSubsetShape
)
279 mpLayerManager
->revokeSubset(rOrigShape
,rSubsetShape
);
282 bool ShapeManagerImpl::listenerAdded(
283 const uno::Reference
<presentation::XShapeEventListener
>& /*xListener*/,
284 const uno::Reference
<drawing::XShape
>& xShape
)
286 ShapeEventListenerMap::const_iterator aIter
;
287 if( (aIter
= mrGlobalListenersMap
.find( xShape
)) ==
288 mrGlobalListenersMap
.end() )
290 ENSURE_OR_RETURN_FALSE(false,
291 "ShapeManagerImpl::listenerAdded(): global "
292 "shape listener map inconsistency!");
295 // is this one of our shapes? other shapes are ignored.
296 ShapeSharedPtr
pShape( lookupShape(xShape
) );
299 maShapeListenerMap
.emplace(pShape
, aIter
->second
);
305 bool ShapeManagerImpl::listenerRemoved(
306 const uno::Reference
<presentation::XShapeEventListener
>& /*xListener*/,
307 const uno::Reference
<drawing::XShape
>& xShape
)
309 // shape really erased from map? maybe there are other listeners
310 // for the same shape pending...
311 if( mrGlobalListenersMap
.find(xShape
) == mrGlobalListenersMap
.end() )
313 // is this one of our shapes? other shapes are ignored.
314 ShapeSharedPtr
pShape( lookupShape(xShape
) );
316 maShapeListenerMap
.erase(pShape
);
322 void ShapeManagerImpl::cursorChanged( const uno::Reference
<drawing::XShape
>& xShape
,
325 ShapeSharedPtr
pShape( lookupShape(xShape
) );
327 // is this one of our shapes? other shapes are ignored.
331 if( mrGlobalCursorMap
.find(xShape
) == mrGlobalCursorMap
.end() )
333 // erased from global map - erase locally, too
334 maShapeCursorMap
.erase(pShape
);
338 // included in global map - update local one
339 ShapeToCursorMap::iterator aIter
;
340 if( (aIter
= maShapeCursorMap
.find(pShape
))
341 == maShapeCursorMap
.end() )
343 maShapeCursorMap
.emplace(pShape
, nCursor
);
347 aIter
->second
= nCursor
;
352 OUString
ShapeManagerImpl::checkForHyperlink( basegfx::B2DPoint
const& hitPos
) const
354 // find matching region (scan reversely, to coarsely match
355 // paint order): set is ordered by priority
356 AreaSet::const_reverse_iterator
iPos( maHyperlinkShapes
.rbegin() );
357 AreaSet::const_reverse_iterator
const iEnd( maHyperlinkShapes
.rend() );
358 for( ; iPos
!= iEnd
; ++iPos
)
360 HyperlinkAreaSharedPtr
const& pArea
= *iPos
;
362 HyperlinkArea::HyperlinkRegions
const linkRegions(
363 pArea
->getHyperlinkRegions() );
365 for( std::size_t i
= linkRegions
.size(); i
--; )
367 basegfx::B2DRange
const& region
= linkRegions
[i
].first
;
368 if( region
.isInside(hitPos
) )
369 return linkRegions
[i
].second
;
376 void ShapeManagerImpl::addIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr
& rHandler
)
378 maIntrinsicAnimationEventHandlers
.add( rHandler
);
381 void ShapeManagerImpl::removeIntrinsicAnimationHandler( const IntrinsicAnimationEventHandlerSharedPtr
& rHandler
)
383 maIntrinsicAnimationEventHandlers
.remove( rHandler
);
386 void ShapeManagerImpl::notifyIntrinsicAnimationsEnabled()
388 maIntrinsicAnimationEventHandlers
.applyAll(
389 std::mem_fn(&IntrinsicAnimationEventHandler::enableAnimations
));
392 void ShapeManagerImpl::notifyIntrinsicAnimationsDisabled()
394 maIntrinsicAnimationEventHandlers
.applyAll(
395 std::mem_fn(&IntrinsicAnimationEventHandler::disableAnimations
));
399 } // namespace internal
400 } // namespace presentation
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */