Bump version to 6.4-15
[LibreOffice.git] / slideshow / source / engine / slide / userpaintoverlay.cxx
blob3ad95c1a6cdbd8dd11775b588bf44e7c87b394b3
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 <cppuhelper/exc_hlp.hxx>
23 #include <com/sun/star/awt/MouseButton.hpp>
24 #include <com/sun/star/awt/MouseEvent.hpp>
26 #include <sal/log.hxx>
27 #include <basegfx/point/b2dpoint.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
29 #include <basegfx/matrix/b2dhommatrix.hxx>
30 #include <cppcanvas/basegfxfactory.hxx>
31 #include <tools/diagnose_ex.h>
33 #include <activity.hxx>
34 #include <slideshowcontext.hxx>
35 #include "userpaintoverlay.hxx"
36 #include <mouseeventhandler.hxx>
37 #include <eventmultiplexer.hxx>
38 #include <screenupdater.hxx>
39 #include <vieweventhandler.hxx>
41 #include <slide.hxx>
42 #include <cursormanager.hxx>
44 using namespace ::com::sun::star;
46 namespace slideshow
48 namespace internal
50 class PaintOverlayHandler : public MouseEventHandler,
51 public ViewEventHandler,
52 public UserPaintEventHandler
54 public:
55 PaintOverlayHandler( const RGBColor& rStrokeColor,
56 double nStrokeWidth,
57 ScreenUpdater& rScreenUpdater,
58 const UnoViewContainer& rViews,
59 Slide& rSlide,
60 const PolyPolygonVector& rPolygons,
61 bool bActive ) :
62 mrScreenUpdater( rScreenUpdater ),
63 maViews(),
64 maPolygons( rPolygons ),
65 maStrokeColor( rStrokeColor ),
66 mnStrokeWidth( nStrokeWidth ),
67 maLastPoint(),
68 maLastMouseDownPos(),
69 mbIsLastPointValid( false ),
70 mbIsLastMouseDownPosValid( false ),
71 //handle the "remove all ink from slide" mode of erasing
72 mbIsEraseAllModeActivated( false ),
73 //handle the "remove stroke by stroke" mode of erasing
74 mbIsEraseModeActivated( false ),
75 mrSlide(rSlide),
76 mnSize(100),
77 mbActive( bActive )
79 for( const auto& rView : rViews )
80 viewAdded( rView );
82 drawPolygons();
85 void dispose()
87 maViews.clear();
90 // ViewEventHandler methods
91 virtual void viewAdded( const UnoViewSharedPtr& rView ) override
93 maViews.push_back( rView );
96 virtual void viewRemoved( const UnoViewSharedPtr& rView ) override
98 maViews.erase( ::std::remove( maViews.begin(),
99 maViews.end(),
100 rView ) );
103 virtual void viewChanged( const UnoViewSharedPtr& /*rView*/ ) override
105 // TODO(F2): for persistent drawings, need to store
106 // polygon and repaint here.
109 virtual void viewsChanged() override
111 // TODO(F2): for persistent drawings, need to store
112 // polygon and repaint here.
115 bool colorChanged( RGBColor const& rUserColor ) override
117 mbIsLastPointValid = false;
118 mbActive = true;
119 maStrokeColor = rUserColor;
120 mbIsEraseModeActivated = false;
121 return true;
124 bool widthChanged( double nUserStrokeWidth ) override
126 mnStrokeWidth = nUserStrokeWidth;
127 mbIsEraseModeActivated = false;
128 return true;
131 void repaintWithoutPolygons()
133 // must get access to the instance to erase all polygon
134 for( const auto& rxView : maViews )
136 // fully clear view content to background color
137 //rxView->getCanvas()->clear();
139 //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
140 SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( rxView ) );
141 ::cppcanvas::CanvasSharedPtr pCanvas( rxView->getCanvas() );
143 const ::basegfx::B2DHomMatrix aViewTransform( rxView->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(rxView,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( const auto& rxPolygon : maPolygons )
218 rxPolygon->draw();
220 // screen update necessary to show painting
221 mrScreenUpdater.notifyUpdate();
224 //Retrieve all registered polygons.
225 const PolyPolygonVector& getPolygons() const
227 return maPolygons;
230 // MouseEventHandler methods
231 virtual bool handleMousePressed( const awt::MouseEvent& e ) override
233 if( !mbActive )
234 return false;
236 if (e.Buttons == awt::MouseButton::RIGHT)
238 mbIsLastPointValid = false;
239 return false;
242 if (e.Buttons != awt::MouseButton::LEFT)
243 return false;
245 maLastMouseDownPos.setX( e.X );
246 maLastMouseDownPos.setY( e.Y );
247 mbIsLastMouseDownPosValid = true;
249 // eat mouse click (though we don't process it
250 // _directly_, it enables the drag mode
251 return true;
254 virtual bool handleMouseReleased( const awt::MouseEvent& e ) override
256 if( !mbActive )
257 return false;
259 if (e.Buttons == awt::MouseButton::RIGHT)
261 mbIsLastPointValid = false;
262 return false;
265 if (e.Buttons != awt::MouseButton::LEFT)
266 return false;
268 // check, whether up- and down press are on exactly
269 // the same pixel. If that's the case, ignore the
270 // click, and pass on the event to low-prio
271 // handlers. This effectively permits effect
272 // advancements via clicks also when user paint is
273 // enabled.
274 if( mbIsLastMouseDownPosValid &&
275 ::basegfx::B2DPoint( e.X,
276 e.Y ) == maLastMouseDownPos )
278 mbIsLastMouseDownPosValid = false;
279 return false;
282 // invalidate, next downpress will have to start a new
283 // polygon.
284 mbIsLastPointValid = false;
286 // eat mouse click (though we don't process it
287 // _directly_, it enables the drag mode
288 return true;
291 virtual bool handleMouseDragged( const awt::MouseEvent& e ) override
293 if( !mbActive )
294 return false;
296 if (e.Buttons == awt::MouseButton::RIGHT)
298 mbIsLastPointValid = false;
299 return false;
302 if(mbIsEraseModeActivated)
304 //define the last point as an object
305 //we suppose that there's no way this point could be valid
306 ::basegfx::B2DPolygon aPoly;
308 maLastPoint.setX( e.X-mnSize );
309 maLastPoint.setY( e.Y-mnSize );
311 aPoly.append( maLastPoint );
313 maLastPoint.setX( e.X-mnSize );
314 maLastPoint.setY( e.Y+mnSize );
316 aPoly.append( maLastPoint );
317 maLastPoint.setX( e.X+mnSize );
318 maLastPoint.setY( e.Y+mnSize );
320 aPoly.append( maLastPoint );
321 maLastPoint.setX( e.X+mnSize );
322 maLastPoint.setY( e.Y-mnSize );
324 aPoly.append( maLastPoint );
325 maLastPoint.setX( e.X-mnSize );
326 maLastPoint.setY( e.Y-mnSize );
328 aPoly.append( maLastPoint );
330 //now we have defined a Polygon that is closed
332 //The point is to redraw the LastPoint the way it was originally on the bitmap,
333 //of the slide
334 for (const auto& rxView : maViews)
337 //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
338 SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( rxView ) );
339 ::cppcanvas::CanvasSharedPtr pCanvas( rxView->getCanvas() );
341 ::basegfx::B2DHomMatrix aViewTransform( rxView->getTransformation() );
342 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
344 // setup a canvas with device coordinate space, the slide
345 // bitmap already has the correct dimension.
346 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
348 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
350 // render at given output position
351 pBitmap->move( aOutPosPixel );
353 ::basegfx::B2DPolyPolygon aPolyPoly(aPoly);
354 aViewTransform.translate(-aOutPosPixel.getX(), -aOutPosPixel.getY());
355 aPolyPoly.transform(aViewTransform);
356 // set clip so that we just redraw a part of the canvas
357 pBitmap->clip(aPolyPoly);
358 pBitmap->draw( pDevicePixelCanvas );
360 mrScreenUpdater.notifyUpdate(rxView,true);
364 else
366 if( !mbIsLastPointValid )
368 mbIsLastPointValid = true;
369 maLastPoint.setX( e.X );
370 maLastPoint.setY( e.Y );
372 else
374 ::basegfx::B2DPolygon aPoly;
375 aPoly.append( maLastPoint );
377 maLastPoint.setX( e.X );
378 maLastPoint.setY( e.Y );
380 aPoly.append( maLastPoint );
382 // paint to all views
383 for (const auto& rxView : maViews)
385 ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
386 ::cppcanvas::BaseGfxFactory::createPolyPolygon( rxView->getCanvas(),
387 aPoly ) );
389 if( pPolyPoly )
391 pPolyPoly->setStrokeWidth(mnStrokeWidth);
392 pPolyPoly->setRGBALineColor( maStrokeColor.getIntegerColor() );
393 pPolyPoly->draw();
394 maPolygons.push_back(pPolyPoly);
398 // screen update necessary to show painting
399 mrScreenUpdater.notifyUpdate();
402 // mouse events captured
403 return true;
406 virtual bool handleMouseMoved( const awt::MouseEvent& /*e*/ ) override
408 // not used here
409 return false; // did not handle the event
412 private:
413 ScreenUpdater& mrScreenUpdater;
414 UnoViewVector maViews;
415 PolyPolygonVector maPolygons;
416 RGBColor maStrokeColor;
417 double mnStrokeWidth;
418 basegfx::B2DPoint maLastPoint;
419 basegfx::B2DPoint maLastMouseDownPos;
420 bool mbIsLastPointValid;
421 bool mbIsLastMouseDownPosValid;
422 // added bool for erasing purpose :
423 bool mbIsEraseAllModeActivated;
424 bool mbIsEraseModeActivated;
425 Slide& mrSlide;
426 sal_Int32 mnSize;
427 bool mbActive;
430 UserPaintOverlaySharedPtr UserPaintOverlay::create( const RGBColor& rStrokeColor,
431 double nStrokeWidth,
432 const SlideShowContext& rContext,
433 const PolyPolygonVector& rPolygons,
434 bool bActive )
436 UserPaintOverlaySharedPtr pRet( new UserPaintOverlay( rStrokeColor,
437 nStrokeWidth,
438 rContext,
439 rPolygons,
440 bActive));
442 return pRet;
445 UserPaintOverlay::UserPaintOverlay( const RGBColor& rStrokeColor,
446 double nStrokeWidth,
447 const SlideShowContext& rContext,
448 const PolyPolygonVector& rPolygons,
449 bool bActive ) :
450 mpHandler( new PaintOverlayHandler( rStrokeColor,
451 nStrokeWidth,
452 rContext.mrScreenUpdater,
453 rContext.mrViewContainer,
454 //adding a link to Slide
455 dynamic_cast<Slide&>(rContext.mrCursorManager),
456 rPolygons, bActive )),
457 mrMultiplexer( rContext.mrEventMultiplexer )
459 mrMultiplexer.addClickHandler( mpHandler, 3.0 );
460 mrMultiplexer.addMouseMoveHandler( mpHandler, 3.0 );
461 mrMultiplexer.addViewHandler( mpHandler );
462 mrMultiplexer.addUserPaintHandler(mpHandler);
465 PolyPolygonVector const & UserPaintOverlay::getPolygons() const
467 return mpHandler->getPolygons();
470 void UserPaintOverlay::drawPolygons()
472 mpHandler->drawPolygons();
475 UserPaintOverlay::~UserPaintOverlay()
479 mrMultiplexer.removeMouseMoveHandler( mpHandler );
480 mrMultiplexer.removeClickHandler( mpHandler );
481 mrMultiplexer.removeViewHandler( mpHandler );
482 mpHandler->dispose();
484 catch (const uno::Exception&)
486 TOOLS_WARN_EXCEPTION("slideshow", "");
492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */