Bump version to 6.0-36
[LibreOffice.git] / slideshow / source / engine / slide / userpaintoverlay.cxx
blobf1a1789ad8c9262c41bc4eb3a18665af3ce4cc62
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 <comphelper/anytostring.hxx>
22 #include <cppuhelper/exc_hlp.hxx>
24 #include <com/sun/star/awt/MouseButton.hpp>
25 #include <com/sun/star/awt/MouseEvent.hpp>
27 #include <basegfx/point/b2dpoint.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
29 #include <cppcanvas/basegfxfactory.hxx>
31 #include <activity.hxx>
32 #include <slideshowcontext.hxx>
33 #include "userpaintoverlay.hxx"
34 #include <mouseeventhandler.hxx>
35 #include <eventmultiplexer.hxx>
36 #include <screenupdater.hxx>
37 #include <vieweventhandler.hxx>
39 #include <slide.hxx>
40 #include <cursormanager.hxx>
42 using namespace ::com::sun::star;
44 namespace slideshow
46 namespace internal
48 class PaintOverlayHandler : public MouseEventHandler,
49 public ViewEventHandler,
50 public UserPaintEventHandler
52 public:
53 PaintOverlayHandler( const RGBColor& rStrokeColor,
54 double nStrokeWidth,
55 ScreenUpdater& rScreenUpdater,
56 const UnoViewContainer& rViews,
57 Slide& rSlide,
58 const PolyPolygonVector& rPolygons,
59 bool bActive ) :
60 mrScreenUpdater( rScreenUpdater ),
61 maViews(),
62 maPolygons( rPolygons ),
63 maStrokeColor( rStrokeColor ),
64 mnStrokeWidth( nStrokeWidth ),
65 maLastPoint(),
66 maLastMouseDownPos(),
67 mbIsLastPointValid( false ),
68 mbIsLastMouseDownPosValid( false ),
69 //handle the "remove all ink from slide" mode of erasing
70 mbIsEraseAllModeActivated( false ),
71 //handle the "remove stroke by stroke" mode of erasing
72 mbIsEraseModeActivated( false ),
73 mrSlide(rSlide),
74 mnSize(100),
75 mbActive( bActive )
77 for( const auto& rView : rViews )
78 viewAdded( rView );
80 drawPolygons();
83 void dispose()
85 maViews.clear();
88 // ViewEventHandler methods
89 virtual void viewAdded( const UnoViewSharedPtr& rView ) override
91 maViews.push_back( rView );
94 virtual void viewRemoved( const UnoViewSharedPtr& rView ) override
96 maViews.erase( ::std::remove( maViews.begin(),
97 maViews.end(),
98 rView ) );
101 virtual void viewChanged( const UnoViewSharedPtr& /*rView*/ ) override
103 // TODO(F2): for persistent drawings, need to store
104 // polygon and repaint here.
107 virtual void viewsChanged() override
109 // TODO(F2): for persistent drawings, need to store
110 // polygon and repaint here.
113 bool colorChanged( RGBColor const& rUserColor ) override
115 mbIsLastPointValid = false;
116 mbActive = true;
117 maStrokeColor = rUserColor;
118 mbIsEraseModeActivated = false;
119 return true;
122 bool widthChanged( double nUserStrokeWidth ) override
124 mnStrokeWidth = nUserStrokeWidth;
125 mbIsEraseModeActivated = false;
126 return true;
129 void repaintWithoutPolygons()
131 // must get access to the instance to erase all polygon
132 for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
133 aIter!=aEnd;
134 ++aIter )
136 // fully clear view content to background color
137 //(*aIter)->getCanvas()->clear();
139 //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
140 SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( *aIter ) );
141 ::cppcanvas::CanvasSharedPtr pCanvas( (*aIter)->getCanvas() );
143 const ::basegfx::B2DHomMatrix aViewTransform( (*aIter)->getTransformation() );
144 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
146 // setup a canvas with device coordinate space, the slide
147 // bitmap already has the correct dimension.
148 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
150 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
152 // render at given output position
153 pBitmap->move( aOutPosPixel );
155 // clear clip (might have been changed, e.g. from comb
156 // transition)
157 pBitmap->clip( ::basegfx::B2DPolyPolygon() );
158 pBitmap->draw( pDevicePixelCanvas );
160 mrScreenUpdater.notifyUpdate(*aIter,true);
164 bool eraseAllInkChanged( bool bEraseAllInk ) override
166 mbIsEraseAllModeActivated = bEraseAllInk;
167 // if the erase all mode is activated it will remove all ink from slide,
168 // therefore destroy all the polygons stored
169 if(mbIsEraseAllModeActivated)
171 // The Erase Mode should be deactivated
172 mbIsEraseModeActivated = false;
173 repaintWithoutPolygons();
174 maPolygons.clear();
176 mbIsEraseAllModeActivated=false;
177 return true;
180 bool eraseInkWidthChanged( sal_Int32 rEraseInkSize ) override
182 // Change the size
183 mnSize=rEraseInkSize;
184 // Changed to mode Erase
185 mbIsEraseModeActivated = true;
186 return true;
189 bool switchPenMode() override
191 mbIsLastPointValid = false;
192 mbActive = true;
193 mbIsEraseModeActivated = false;
194 return true;
197 bool switchEraserMode() override
199 mbIsLastPointValid = false;
200 mbActive = true;
201 mbIsEraseModeActivated = true;
202 return true;
205 bool disable() override
207 mbIsLastPointValid = false;
208 mbIsLastMouseDownPosValid = false;
209 mbActive = false;
210 return true;
213 //Draw all registered polygons.
214 void drawPolygons()
216 for( PolyPolygonVector::iterator aIter=maPolygons.begin(), aEnd=maPolygons.end();
217 aIter!=aEnd;
218 ++aIter )
220 (*aIter)->draw();
222 // screen update necessary to show painting
223 mrScreenUpdater.notifyUpdate();
226 //Retrieve all registered polygons.
227 const PolyPolygonVector& getPolygons()
229 return maPolygons;
232 // MouseEventHandler methods
233 virtual bool handleMousePressed( const awt::MouseEvent& e ) override
235 if( !mbActive )
236 return false;
238 if (e.Buttons == awt::MouseButton::RIGHT)
240 mbIsLastPointValid = false;
241 return false;
244 if (e.Buttons != awt::MouseButton::LEFT)
245 return false;
247 maLastMouseDownPos.setX( e.X );
248 maLastMouseDownPos.setY( e.Y );
249 mbIsLastMouseDownPosValid = true;
251 // eat mouse click (though we don't process it
252 // _directly_, it enables the drag mode
253 return true;
256 virtual bool handleMouseReleased( const awt::MouseEvent& e ) override
258 if( !mbActive )
259 return false;
261 if (e.Buttons == awt::MouseButton::RIGHT)
263 mbIsLastPointValid = false;
264 return false;
267 if (e.Buttons != awt::MouseButton::LEFT)
268 return false;
270 // check, whether up- and down press are on exactly
271 // the same pixel. If that's the case, ignore the
272 // click, and pass on the event to low-prio
273 // handlers. This effectively permits effect
274 // advancements via clicks also when user paint is
275 // enabled.
276 if( mbIsLastMouseDownPosValid &&
277 ::basegfx::B2DPoint( e.X,
278 e.Y ) == maLastMouseDownPos )
280 mbIsLastMouseDownPosValid = false;
281 return false;
284 // invalidate, next downpress will have to start a new
285 // polygon.
286 mbIsLastPointValid = false;
288 // eat mouse click (though we don't process it
289 // _directly_, it enables the drag mode
290 return true;
293 virtual bool handleMouseDragged( const awt::MouseEvent& e ) override
295 if( !mbActive )
296 return false;
298 if (e.Buttons == awt::MouseButton::RIGHT)
300 mbIsLastPointValid = false;
301 return false;
304 if(mbIsEraseModeActivated)
306 //define the last point as an object
307 //we suppose that there's no way this point could be valid
308 ::basegfx::B2DPolygon aPoly;
310 maLastPoint.setX( e.X-mnSize );
311 maLastPoint.setY( e.Y-mnSize );
313 aPoly.append( maLastPoint );
315 maLastPoint.setX( e.X-mnSize );
316 maLastPoint.setY( e.Y+mnSize );
318 aPoly.append( maLastPoint );
319 maLastPoint.setX( e.X+mnSize );
320 maLastPoint.setY( e.Y+mnSize );
322 aPoly.append( maLastPoint );
323 maLastPoint.setX( e.X+mnSize );
324 maLastPoint.setY( e.Y-mnSize );
326 aPoly.append( maLastPoint );
327 maLastPoint.setX( e.X-mnSize );
328 maLastPoint.setY( e.Y-mnSize );
330 aPoly.append( maLastPoint );
332 //now we have defined a Polygon that is closed
334 //The point is to redraw the LastPoint the way it was originally on the bitmap,
335 //of the slide
336 for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
337 aIter!=aEnd;
338 ++aIter )
341 //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
342 SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( *aIter ) );
343 ::cppcanvas::CanvasSharedPtr pCanvas( (*aIter)->getCanvas() );
345 ::basegfx::B2DHomMatrix aViewTransform( (*aIter)->getTransformation() );
346 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
348 // setup a canvas with device coordinate space, the slide
349 // bitmap already has the correct dimension.
350 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
352 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
354 // render at given output position
355 pBitmap->move( aOutPosPixel );
357 ::basegfx::B2DPolyPolygon aPolyPoly=::basegfx::B2DPolyPolygon(aPoly);
358 aViewTransform.translate(-aOutPosPixel.getX(), -aOutPosPixel.getY());
359 aPolyPoly.transform(aViewTransform);
360 // set clip so that we just redraw a part of the canvas
361 pBitmap->clip(aPolyPoly);
362 pBitmap->draw( pDevicePixelCanvas );
364 mrScreenUpdater.notifyUpdate(*aIter,true);
368 else
370 if( !mbIsLastPointValid )
372 mbIsLastPointValid = true;
373 maLastPoint.setX( e.X );
374 maLastPoint.setY( e.Y );
376 else
378 ::basegfx::B2DPolygon aPoly;
379 aPoly.append( maLastPoint );
381 maLastPoint.setX( e.X );
382 maLastPoint.setY( e.Y );
384 aPoly.append( maLastPoint );
386 // paint to all views
387 for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
388 aIter!=aEnd;
389 ++aIter )
391 ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
392 ::cppcanvas::BaseGfxFactory::createPolyPolygon( (*aIter)->getCanvas(),
393 aPoly ) );
395 if( pPolyPoly )
397 pPolyPoly->setStrokeWidth(mnStrokeWidth);
398 pPolyPoly->setRGBALineColor( maStrokeColor.getIntegerColor() );
399 pPolyPoly->draw();
400 maPolygons.push_back(pPolyPoly);
404 // screen update necessary to show painting
405 mrScreenUpdater.notifyUpdate();
408 // mouse events captured
409 return true;
412 virtual bool handleMouseMoved( const awt::MouseEvent& /*e*/ ) override
414 // not used here
415 return false; // did not handle the event
418 private:
419 ScreenUpdater& mrScreenUpdater;
420 UnoViewVector maViews;
421 PolyPolygonVector maPolygons;
422 RGBColor maStrokeColor;
423 double mnStrokeWidth;
424 basegfx::B2DPoint maLastPoint;
425 basegfx::B2DPoint maLastMouseDownPos;
426 bool mbIsLastPointValid;
427 bool mbIsLastMouseDownPosValid;
428 // added bool for erasing purpose :
429 bool mbIsEraseAllModeActivated;
430 bool mbIsEraseModeActivated;
431 Slide& mrSlide;
432 sal_Int32 mnSize;
433 bool mbActive;
436 UserPaintOverlaySharedPtr UserPaintOverlay::create( const RGBColor& rStrokeColor,
437 double nStrokeWidth,
438 const SlideShowContext& rContext,
439 const PolyPolygonVector& rPolygons,
440 bool bActive )
442 UserPaintOverlaySharedPtr pRet( new UserPaintOverlay( rStrokeColor,
443 nStrokeWidth,
444 rContext,
445 rPolygons,
446 bActive));
448 return pRet;
451 UserPaintOverlay::UserPaintOverlay( const RGBColor& rStrokeColor,
452 double nStrokeWidth,
453 const SlideShowContext& rContext,
454 const PolyPolygonVector& rPolygons,
455 bool bActive ) :
456 mpHandler( new PaintOverlayHandler( rStrokeColor,
457 nStrokeWidth,
458 rContext.mrScreenUpdater,
459 rContext.mrViewContainer,
460 //adding a link to Slide
461 dynamic_cast<Slide&>(rContext.mrCursorManager),
462 rPolygons, bActive )),
463 mrMultiplexer( rContext.mrEventMultiplexer )
465 mrMultiplexer.addClickHandler( mpHandler, 3.0 );
466 mrMultiplexer.addMouseMoveHandler( mpHandler, 3.0 );
467 mrMultiplexer.addViewHandler( mpHandler );
468 mrMultiplexer.addUserPaintHandler(mpHandler);
471 PolyPolygonVector UserPaintOverlay::getPolygons()
473 return mpHandler->getPolygons();
476 void UserPaintOverlay::drawPolygons()
478 mpHandler->drawPolygons();
481 UserPaintOverlay::~UserPaintOverlay()
485 mrMultiplexer.removeMouseMoveHandler( mpHandler );
486 mrMultiplexer.removeClickHandler( mpHandler );
487 mrMultiplexer.removeViewHandler( mpHandler );
488 mpHandler->dispose();
490 catch (const uno::Exception& e)
492 SAL_WARN("slideshow", e);
498 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */