android: Update app-specific/MIME type icons
[LibreOffice.git] / slideshow / source / engine / slide / userpaintoverlay.cxx
blobffae0a17d883270cfe591f0e64c9e0f813f0b43c
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 <com/sun/star/awt/MouseButton.hpp>
22 #include <com/sun/star/awt/MouseEvent.hpp>
24 #include <basegfx/point/b2dpoint.hxx>
25 #include <basegfx/polygon/b2dpolygon.hxx>
26 #include <basegfx/matrix/b2dhommatrix.hxx>
27 #include <cppcanvas/basegfxfactory.hxx>
28 #include <comphelper/diagnose_ex.hxx>
30 #include <slideshowcontext.hxx>
31 #include "userpaintoverlay.hxx"
32 #include <mouseeventhandler.hxx>
33 #include <eventmultiplexer.hxx>
34 #include <screenupdater.hxx>
35 #include <vieweventhandler.hxx>
37 #include <slide.hxx>
38 #include <cursormanager.hxx>
40 using namespace ::com::sun::star;
42 namespace slideshow::internal
44 class PaintOverlayHandler : public MouseEventHandler,
45 public ViewEventHandler,
46 public UserPaintEventHandler
48 public:
49 PaintOverlayHandler( const RGBColor& rStrokeColor,
50 double nStrokeWidth,
51 ScreenUpdater& rScreenUpdater,
52 const UnoViewContainer& rViews,
53 Slide& rSlide,
54 PolyPolygonVector&& rPolygons,
55 bool bActive ) :
56 mrScreenUpdater( rScreenUpdater ),
57 maViews(),
58 maPolygons( std::move(rPolygons) ),
59 maStrokeColor( rStrokeColor ),
60 mnStrokeWidth( nStrokeWidth ),
61 maLastPoint(),
62 maLastMouseDownPos(),
63 mbIsLastPointValid( false ),
64 mbIsLastMouseDownPosValid( false ),
65 //handle the "remove all ink from slide" mode of erasing
66 mbIsEraseAllModeActivated( false ),
67 //handle the "remove stroke by stroke" mode of erasing
68 mbIsEraseModeActivated( false ),
69 mrSlide(rSlide),
70 mnSize(100),
71 mbActive( bActive )
73 for( const auto& rView : rViews )
74 viewAdded( rView );
76 drawPolygons();
79 void dispose()
81 maViews.clear();
84 // ViewEventHandler methods
85 virtual void viewAdded( const UnoViewSharedPtr& rView ) override
87 maViews.push_back( rView );
90 virtual void viewRemoved( const UnoViewSharedPtr& rView ) override
92 maViews.erase( ::std::remove( maViews.begin(),
93 maViews.end(),
94 rView ) );
97 virtual void viewChanged( const UnoViewSharedPtr& /*rView*/ ) override
99 // TODO(F2): for persistent drawings, need to store
100 // polygon and repaint here.
103 virtual void viewsChanged() override
105 // TODO(F2): for persistent drawings, need to store
106 // polygon and repaint here.
109 bool colorChanged( RGBColor const& rUserColor ) override
111 mbIsLastPointValid = false;
112 mbActive = true;
113 maStrokeColor = rUserColor;
114 mbIsEraseModeActivated = false;
115 return true;
118 bool widthChanged( double nUserStrokeWidth ) override
120 mnStrokeWidth = nUserStrokeWidth;
121 mbIsEraseModeActivated = false;
122 return true;
125 void repaintWithoutPolygons()
127 // must get access to the instance to erase all polygon
128 for( const auto& rxView : maViews )
130 // fully clear view content to background color
131 //rxView->getCanvas()->clear();
133 //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
134 SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( rxView ) );
135 ::cppcanvas::CanvasSharedPtr pCanvas( rxView->getCanvas() );
137 const ::basegfx::B2DHomMatrix aViewTransform( rxView->getTransformation() );
138 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
140 // setup a canvas with device coordinate space, the slide
141 // bitmap already has the correct dimension.
142 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
144 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
146 // render at given output position
147 pBitmap->move( aOutPosPixel );
149 // clear clip (might have been changed, e.g. from comb
150 // transition)
151 pBitmap->clip( ::basegfx::B2DPolyPolygon() );
152 pBitmap->draw( pDevicePixelCanvas );
154 mrScreenUpdater.notifyUpdate(rxView,true);
158 bool eraseAllInkChanged( bool bEraseAllInk ) override
160 mbIsEraseAllModeActivated = bEraseAllInk;
161 // if the erase all mode is activated it will remove all ink from slide,
162 // therefore destroy all the polygons stored
163 if(mbIsEraseAllModeActivated)
165 // The Erase Mode should be deactivated
166 mbIsEraseModeActivated = false;
167 repaintWithoutPolygons();
168 maPolygons.clear();
170 mbIsEraseAllModeActivated=false;
171 return true;
174 bool eraseInkWidthChanged( sal_Int32 rEraseInkSize ) override
176 // Change the size
177 mnSize=rEraseInkSize;
178 // Changed to mode Erase
179 mbIsEraseModeActivated = true;
180 return true;
183 bool switchPenMode() override
185 mbIsLastPointValid = false;
186 mbActive = true;
187 mbIsEraseModeActivated = false;
188 return true;
191 bool switchEraserMode() override
193 mbIsLastPointValid = false;
194 mbActive = true;
195 mbIsEraseModeActivated = true;
196 return true;
199 bool disable() override
201 mbIsLastPointValid = false;
202 mbIsLastMouseDownPosValid = false;
203 mbActive = false;
204 return true;
207 //Draw all registered polygons.
208 void drawPolygons()
210 for( const auto& rxPolygon : maPolygons )
212 rxPolygon->draw();
214 // screen update necessary to show painting
215 mrScreenUpdater.notifyUpdate();
218 //Retrieve all registered polygons.
219 const PolyPolygonVector& getPolygons() const
221 return maPolygons;
224 // MouseEventHandler methods
225 virtual bool handleMousePressed( const awt::MouseEvent& e ) override
227 if( !mbActive )
228 return false;
230 if (e.Buttons == awt::MouseButton::RIGHT)
232 mbIsLastPointValid = false;
233 return false;
236 if (e.Buttons != awt::MouseButton::LEFT)
237 return false;
239 maLastMouseDownPos.setX( e.X );
240 maLastMouseDownPos.setY( e.Y );
241 mbIsLastMouseDownPosValid = true;
243 // eat mouse click (though we don't process it
244 // _directly_, it enables the drag mode
245 return true;
248 virtual bool handleMouseReleased( const awt::MouseEvent& e ) override
250 if( !mbActive )
251 return false;
253 if (e.Buttons == awt::MouseButton::RIGHT)
255 mbIsLastPointValid = false;
256 return false;
259 if (e.Buttons != awt::MouseButton::LEFT)
260 return false;
262 // check, whether up- and down press are on exactly
263 // the same pixel. If that's the case, ignore the
264 // click, and pass on the event to low-prio
265 // handlers. This effectively permits effect
266 // advancements via clicks also when user paint is
267 // enabled.
268 if( mbIsLastMouseDownPosValid &&
269 ::basegfx::B2DPoint( e.X,
270 e.Y ) == maLastMouseDownPos )
272 mbIsLastMouseDownPosValid = false;
273 return false;
276 // invalidate, next downpress will have to start a new
277 // polygon.
278 mbIsLastPointValid = false;
280 // eat mouse click (though we don't process it
281 // _directly_, it enables the drag mode
282 return true;
285 virtual bool handleMouseDragged( const awt::MouseEvent& e ) override
287 if( !mbActive )
288 return false;
290 if (e.Buttons == awt::MouseButton::RIGHT)
292 mbIsLastPointValid = false;
293 return false;
296 if(mbIsEraseModeActivated)
298 //define the last point as an object
299 //we suppose that there's no way this point could be valid
300 ::basegfx::B2DPolygon aPoly;
302 maLastPoint.setX( e.X-mnSize );
303 maLastPoint.setY( e.Y-mnSize );
305 aPoly.append( maLastPoint );
307 maLastPoint.setX( e.X-mnSize );
308 maLastPoint.setY( e.Y+mnSize );
310 aPoly.append( maLastPoint );
311 maLastPoint.setX( e.X+mnSize );
312 maLastPoint.setY( e.Y+mnSize );
314 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 );
324 //now we have defined a Polygon that is closed
326 //The point is to redraw the LastPoint the way it was originally on the bitmap,
327 //of the slide
328 for (const auto& rxView : maViews)
331 //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
332 SlideBitmapSharedPtr pBitmap( mrSlide.getCurrentSlideBitmap( rxView ) );
333 ::cppcanvas::CanvasSharedPtr pCanvas( rxView->getCanvas() );
335 ::basegfx::B2DHomMatrix aViewTransform( rxView->getTransformation() );
336 const ::basegfx::B2DPoint aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
338 // setup a canvas with device coordinate space, the slide
339 // bitmap already has the correct dimension.
340 ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
342 pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
344 // render at given output position
345 pBitmap->move( aOutPosPixel );
347 ::basegfx::B2DPolyPolygon aPolyPoly(aPoly);
348 aViewTransform.translate(-aOutPosPixel.getX(), -aOutPosPixel.getY());
349 aPolyPoly.transform(aViewTransform);
350 // set clip so that we just redraw a part of the canvas
351 pBitmap->clip(aPolyPoly);
352 pBitmap->draw( pDevicePixelCanvas );
354 mrScreenUpdater.notifyUpdate(rxView,true);
358 else
360 if( !mbIsLastPointValid )
362 mbIsLastPointValid = true;
363 maLastPoint.setX( e.X );
364 maLastPoint.setY( e.Y );
366 else
368 ::basegfx::B2DPolygon aPoly;
369 aPoly.append( maLastPoint );
371 maLastPoint.setX( e.X );
372 maLastPoint.setY( e.Y );
374 aPoly.append( maLastPoint );
376 // paint to all views
377 for (const auto& rxView : maViews)
379 ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
380 ::cppcanvas::BaseGfxFactory::createPolyPolygon( rxView->getCanvas(),
381 aPoly ) );
383 if( pPolyPoly )
385 pPolyPoly->setStrokeWidth(mnStrokeWidth);
386 pPolyPoly->setRGBALineColor( maStrokeColor.getIntegerColor() );
387 pPolyPoly->draw();
388 maPolygons.push_back(pPolyPoly);
392 // screen update necessary to show painting
393 mrScreenUpdater.notifyUpdate();
396 // mouse events captured
397 return true;
400 virtual bool handleMouseMoved( const awt::MouseEvent& /*e*/ ) override
402 // not used here
403 return false; // did not handle the event
406 private:
407 ScreenUpdater& mrScreenUpdater;
408 UnoViewVector maViews;
409 PolyPolygonVector maPolygons;
410 RGBColor maStrokeColor;
411 double mnStrokeWidth;
412 basegfx::B2DPoint maLastPoint;
413 basegfx::B2DPoint maLastMouseDownPos;
414 bool mbIsLastPointValid;
415 bool mbIsLastMouseDownPosValid;
416 // added bool for erasing purpose :
417 bool mbIsEraseAllModeActivated;
418 bool mbIsEraseModeActivated;
419 Slide& mrSlide;
420 sal_Int32 mnSize;
421 bool mbActive;
424 UserPaintOverlaySharedPtr UserPaintOverlay::create( const RGBColor& rStrokeColor,
425 double nStrokeWidth,
426 const SlideShowContext& rContext,
427 PolyPolygonVector&& rPolygons,
428 bool bActive )
430 UserPaintOverlaySharedPtr pRet( new UserPaintOverlay( rStrokeColor,
431 nStrokeWidth,
432 rContext,
433 std::move(rPolygons),
434 bActive));
436 return pRet;
439 UserPaintOverlay::UserPaintOverlay( const RGBColor& rStrokeColor,
440 double nStrokeWidth,
441 const SlideShowContext& rContext,
442 PolyPolygonVector&& rPolygons,
443 bool bActive ) :
444 mpHandler( std::make_shared<PaintOverlayHandler>( rStrokeColor,
445 nStrokeWidth,
446 rContext.mrScreenUpdater,
447 rContext.mrViewContainer,
448 //adding a link to Slide
449 dynamic_cast<Slide&>(rContext.mrCursorManager),
450 std::move(rPolygons), bActive )),
451 mrMultiplexer( rContext.mrEventMultiplexer )
453 mrMultiplexer.addClickHandler( mpHandler, 3.0 );
454 mrMultiplexer.addMouseMoveHandler( mpHandler, 3.0 );
455 mrMultiplexer.addViewHandler( mpHandler );
456 mrMultiplexer.addUserPaintHandler(mpHandler);
459 PolyPolygonVector const & UserPaintOverlay::getPolygons() const
461 return mpHandler->getPolygons();
464 void UserPaintOverlay::drawPolygons()
466 mpHandler->drawPolygons();
469 UserPaintOverlay::~UserPaintOverlay()
473 mrMultiplexer.removeMouseMoveHandler( mpHandler );
474 mrMultiplexer.removeClickHandler( mpHandler );
475 mrMultiplexer.removeViewHandler( mpHandler );
476 mpHandler->dispose();
478 catch (const uno::Exception&)
480 TOOLS_WARN_EXCEPTION("slideshow", "");
485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */