LCOV - code coverage report
Current view: top level - slideshow/source/engine/slide - userpaintoverlay.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 201 0.5 %
Date: 2015-06-13 12:38:46 Functions: 2 31 6.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : #include <canvas/debug.hxx>
      22             : 
      23             : #include <comphelper/anytostring.hxx>
      24             : #include <cppuhelper/exc_hlp.hxx>
      25             : 
      26             : #include <com/sun/star/awt/MouseButton.hpp>
      27             : #include <com/sun/star/presentation/XSlideShowView.hpp>
      28             : 
      29             : #include <basegfx/point/b2dpoint.hxx>
      30             : #include <basegfx/polygon/b2dpolygon.hxx>
      31             : #include <cppcanvas/basegfxfactory.hxx>
      32             : 
      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"
      40             : 
      41             : #include <boost/bind.hpp>
      42             : #include <boost/noncopyable.hpp>
      43             : #include "slide.hxx"
      44             : #include "cursormanager.hxx"
      45             : 
      46             : using namespace ::com::sun::star;
      47             : 
      48             : namespace slideshow
      49             : {
      50             :     namespace internal
      51             :     {
      52           0 :         class PaintOverlayHandler : public MouseEventHandler,
      53             :                                     public ViewEventHandler,
      54             :                     public UserPaintEventHandler
      55             :         {
      56             :         public:
      57           0 :             PaintOverlayHandler( const RGBColor&          rStrokeColor,
      58             :                                  double                   nStrokeWidth,
      59             :                                  ScreenUpdater&           rScreenUpdater,
      60             :                                  const UnoViewContainer&  rViews,
      61             :                                  Slide&                   rSlide,
      62             :                                  const PolyPolygonVector& rPolygons,
      63             :                                  bool                     bActive ) :
      64             :                 mrScreenUpdater( rScreenUpdater ),
      65             :                 maViews(),
      66             :                 maPolygons( rPolygons ),
      67             :                 maStrokeColor( rStrokeColor ),
      68             :                 mnStrokeWidth( nStrokeWidth ),
      69             :                 maLastPoint(),
      70             :                 maLastMouseDownPos(),
      71             :                 mbIsLastPointValid( false ),
      72             :                 mbIsLastMouseDownPosValid( false ),
      73             :                 //handle the "remove all ink from slide" mode of erasing
      74             :                 mbIsEraseAllModeActivated( false ),
      75             :                 //handle the "remove stroke by stroke" mode of erasing
      76             :                 mbIsEraseModeActivated( false ),
      77             :                 mrSlide(rSlide),
      78             :                 mnSize(100),
      79           0 :                 mbActive( bActive )
      80             :             {
      81             :                 std::for_each( rViews.begin(),
      82             :                                rViews.end(),
      83             :                                boost::bind( &PaintOverlayHandler::viewAdded,
      84             :                                             this,
      85           0 :                                             _1 ));
      86           0 :                 drawPolygons();
      87           0 :             }
      88             : 
      89           0 :             void dispose()
      90             :             {
      91           0 :                 maViews.clear();
      92           0 :             }
      93             : 
      94             :             // ViewEventHandler methods
      95           0 :             virtual void viewAdded( const UnoViewSharedPtr& rView ) SAL_OVERRIDE
      96             :             {
      97           0 :                 maViews.push_back( rView );
      98           0 :             }
      99             : 
     100           0 :             virtual void viewRemoved( const UnoViewSharedPtr& rView ) SAL_OVERRIDE
     101             :             {
     102             :                 maViews.erase( ::std::remove( maViews.begin(),
     103             :                                               maViews.end(),
     104           0 :                                               rView ) );
     105           0 :             }
     106             : 
     107           0 :             virtual void viewChanged( const UnoViewSharedPtr& /*rView*/ ) SAL_OVERRIDE
     108             :             {
     109             :                 // TODO(F2): for persistent drawings, need to store
     110             :                 // polygon and repaint here.
     111           0 :             }
     112             : 
     113           0 :             virtual void viewsChanged() SAL_OVERRIDE
     114             :             {
     115             :                 // TODO(F2): for persistent drawings, need to store
     116             :                 // polygon and repaint here.
     117           0 :             }
     118             : 
     119           0 :             bool colorChanged( RGBColor const& rUserColor ) SAL_OVERRIDE
     120             :             {
     121           0 :                 mbIsLastPointValid = false;
     122           0 :                 mbActive = true;
     123           0 :                 this->maStrokeColor = rUserColor;
     124           0 :                 this->mbIsEraseModeActivated = false;
     125           0 :                 return true;
     126             :             }
     127             : 
     128           0 :             bool widthChanged( double nUserStrokeWidth ) SAL_OVERRIDE
     129             :             {
     130           0 :                 this->mnStrokeWidth = nUserStrokeWidth;
     131           0 :                 mbIsEraseModeActivated = false;
     132           0 :                 return true;
     133             :             }
     134             : 
     135           0 :             void repaintWithoutPolygons()
     136             :             {
     137             :                     // must get access to the instance to erase all polygon
     138           0 :                     for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
     139             :                         aIter!=aEnd;
     140             :                         ++aIter )
     141             :                     {
     142             :                         // fully clear view content to background color
     143             :                         //(*aIter)->getCanvas()->clear();
     144             : 
     145             :                         //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
     146           0 :                         SlideBitmapSharedPtr         pBitmap( mrSlide.getCurrentSlideBitmap( (*aIter) ) );
     147           0 :                         ::cppcanvas::CanvasSharedPtr pCanvas( (*aIter)->getCanvas() );
     148             : 
     149           0 :                         const ::basegfx::B2DHomMatrix   aViewTransform( (*aIter)->getTransformation() );
     150           0 :                         const ::basegfx::B2DPoint       aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
     151             : 
     152             :                         // setup a canvas with device coordinate space, the slide
     153             :                         // bitmap already has the correct dimension.
     154           0 :                         ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
     155             : 
     156           0 :                         pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
     157             : 
     158             :                         // render at given output position
     159           0 :                         pBitmap->move( aOutPosPixel );
     160             : 
     161             :                         // clear clip (might have been changed, e.g. from comb
     162             :                         // transition)
     163           0 :                         pBitmap->clip( ::basegfx::B2DPolyPolygon() );
     164           0 :                         pBitmap->draw( pDevicePixelCanvas );
     165             : 
     166           0 :                         mrScreenUpdater.notifyUpdate(*aIter,true);
     167           0 :                     }
     168           0 :             }
     169             : 
     170           0 :             bool eraseAllInkChanged( bool const& rEraseAllInk ) SAL_OVERRIDE
     171             :             {
     172           0 :                 this->mbIsEraseAllModeActivated= rEraseAllInk;
     173             :                 // if the erase all mode is activated it will remove all ink from slide,
     174             :                 // therefore destroy all the polygons stored
     175           0 :                 if(mbIsEraseAllModeActivated)
     176             :                 {
     177             :                     // The Erase Mode should be desactivated
     178           0 :                     mbIsEraseModeActivated = false;
     179           0 :                     repaintWithoutPolygons();
     180           0 :                     maPolygons.clear();
     181             :                 }
     182           0 :             mbIsEraseAllModeActivated=false;
     183           0 :             return true;
     184             :             }
     185             : 
     186           0 :             bool eraseInkWidthChanged( sal_Int32 rEraseInkSize ) SAL_OVERRIDE
     187             :             {
     188             :                 // Change the size
     189           0 :                 this->mnSize=rEraseInkSize;
     190             :                 // Changed to mode Erase
     191           0 :                 this->mbIsEraseModeActivated = true;
     192           0 :                 return true;
     193             :             }
     194             : 
     195           0 :             bool switchPenMode() SAL_OVERRIDE
     196             :             {
     197           0 :                 mbIsLastPointValid = false;
     198           0 :                 mbActive = true;
     199           0 :                 this->mbIsEraseModeActivated = false;
     200           0 :                 return true;
     201             :             }
     202             : 
     203           0 :             bool switchEraserMode() SAL_OVERRIDE
     204             :             {
     205           0 :                 mbIsLastPointValid = false;
     206           0 :                 mbActive = true;
     207           0 :                 this->mbIsEraseModeActivated = true;
     208           0 :                 return true;
     209             :             }
     210             : 
     211           0 :             bool disable() SAL_OVERRIDE
     212             :             {
     213           0 :                 mbIsLastPointValid = false;
     214           0 :                 mbIsLastMouseDownPosValid = false;
     215           0 :                 mbActive = false;
     216           0 :                 return true;
     217             :             }
     218             : 
     219             :             //Draw all registered polygons.
     220           0 :             void drawPolygons()
     221             :             {
     222           0 :                 for( PolyPolygonVector::iterator aIter=maPolygons.begin(), aEnd=maPolygons.end();
     223             :                                      aIter!=aEnd;
     224             :                                      ++aIter )
     225             :                 {
     226           0 :                     (*aIter)->draw();
     227             :                 }
     228             :                 // screen update necessary to show painting
     229           0 :                 mrScreenUpdater.notifyUpdate();
     230           0 :             }
     231             : 
     232             :             //Retrieve all registered polygons.
     233           0 :             PolyPolygonVector getPolygons()
     234             :             {
     235           0 :                 return maPolygons;
     236             :             }
     237             : 
     238             :             // MouseEventHandler methods
     239           0 :             virtual bool handleMousePressed( const awt::MouseEvent& e ) SAL_OVERRIDE
     240             :             {
     241           0 :                 if( !mbActive )
     242           0 :                     return false;
     243             : 
     244           0 :                 if (e.Buttons == awt::MouseButton::RIGHT)
     245             :                 {
     246           0 :                     mbIsLastPointValid = false;
     247           0 :                     return false;
     248             :                 }
     249             : 
     250           0 :                 if (e.Buttons != awt::MouseButton::LEFT)
     251           0 :                     return false;
     252             : 
     253           0 :                 maLastMouseDownPos.setX( e.X );
     254           0 :                 maLastMouseDownPos.setY( e.Y );
     255           0 :                 mbIsLastMouseDownPosValid = true;
     256             : 
     257             :                 // eat mouse click (though we don't process it
     258             :                 // _directly_, it enables the drag mode
     259           0 :                 return true;
     260             :             }
     261             : 
     262           0 :             virtual bool handleMouseReleased( const awt::MouseEvent& e ) SAL_OVERRIDE
     263             :             {
     264           0 :                 if( !mbActive )
     265           0 :                     return false;
     266             : 
     267           0 :                 if (e.Buttons == awt::MouseButton::RIGHT)
     268             :                 {
     269           0 :                     mbIsLastPointValid = false;
     270           0 :                     return false;
     271             :                 }
     272             : 
     273           0 :                 if (e.Buttons != awt::MouseButton::LEFT)
     274           0 :                     return false;
     275             : 
     276             :                 // check, whether up- and down press are on exactly
     277             :                 // the same pixel. If that's the case, ignore the
     278             :                 // click, and pass on the event to low-prio
     279             :                 // handlers. This effectively permits effect
     280             :                 // advancements via clicks also when user paint is
     281             :                 // enabled.
     282           0 :                 if( mbIsLastMouseDownPosValid &&
     283             :                     ::basegfx::B2DPoint( e.X,
     284           0 :                                          e.Y ) == maLastMouseDownPos )
     285             :                 {
     286           0 :                     mbIsLastMouseDownPosValid = false;
     287           0 :                     return false;
     288             :                 }
     289             : 
     290             :                 // invalidate, next downpress will have to start a new
     291             :                 // polygon.
     292           0 :                 mbIsLastPointValid = false;
     293             : 
     294             :                 // eat mouse click (though we don't process it
     295             :                 // _directly_, it enables the drag mode
     296           0 :                 return true;
     297             :             }
     298             : 
     299           0 :             virtual bool handleMouseEntered( const awt::MouseEvent& e ) SAL_OVERRIDE
     300             :             {
     301           0 :                 if( !mbActive )
     302           0 :                     return false;
     303             : 
     304           0 :                 mbIsLastPointValid = true;
     305           0 :                 maLastPoint.setX( e.X );
     306           0 :                 maLastPoint.setY( e.Y );
     307             : 
     308           0 :                 return true;
     309             :             }
     310             : 
     311           0 :             virtual bool handleMouseExited( const awt::MouseEvent& ) SAL_OVERRIDE
     312             :             {
     313           0 :                 if( !mbActive )
     314           0 :                     return false;
     315             : 
     316           0 :                 mbIsLastPointValid = false;
     317           0 :                 mbIsLastMouseDownPosValid = false;
     318             : 
     319           0 :                 return true;
     320             :             }
     321             : 
     322           0 :             virtual bool handleMouseDragged( const awt::MouseEvent& e ) SAL_OVERRIDE
     323             :             {
     324           0 :                 if( !mbActive )
     325           0 :                     return false;
     326             : 
     327           0 :                 if (e.Buttons == awt::MouseButton::RIGHT)
     328             :                 {
     329           0 :                     mbIsLastPointValid = false;
     330           0 :                     return false;
     331             :                 }
     332             : 
     333           0 :                 if(mbIsEraseModeActivated)
     334             :                 {
     335             :                     //define the last point as an object
     336             :                     //we suppose that there's no way this point could be valid
     337           0 :                     ::basegfx::B2DPolygon aPoly;
     338             : 
     339           0 :                     maLastPoint.setX( e.X-mnSize );
     340           0 :                     maLastPoint.setY( e.Y-mnSize );
     341             : 
     342           0 :                     aPoly.append( maLastPoint );
     343             : 
     344           0 :                     maLastPoint.setX( e.X-mnSize );
     345           0 :                     maLastPoint.setY( e.Y+mnSize );
     346             : 
     347           0 :                     aPoly.append( maLastPoint );
     348           0 :                     maLastPoint.setX( e.X+mnSize );
     349           0 :                     maLastPoint.setY( e.Y+mnSize );
     350             : 
     351           0 :                     aPoly.append( maLastPoint );
     352           0 :                     maLastPoint.setX( e.X+mnSize );
     353           0 :                     maLastPoint.setY( e.Y-mnSize );
     354             : 
     355           0 :                     aPoly.append( maLastPoint );
     356           0 :                     maLastPoint.setX( e.X-mnSize );
     357           0 :                     maLastPoint.setY( e.Y-mnSize );
     358             : 
     359           0 :                     aPoly.append( maLastPoint );
     360             : 
     361             :                     //now we have defined a Polygon that is closed
     362             : 
     363             :                     //The point is to redraw the LastPoint the way it was originally on the bitmap,
     364             :                     //of the slide
     365           0 :             for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
     366             :                         aIter!=aEnd;
     367             :                         ++aIter )
     368             :                     {
     369             : 
     370             :                         //get via SlideImpl instance the bitmap of the slide unmodified to redraw it
     371           0 :                         SlideBitmapSharedPtr         pBitmap( mrSlide.getCurrentSlideBitmap( (*aIter) ) );
     372           0 :                         ::cppcanvas::CanvasSharedPtr pCanvas( (*aIter)->getCanvas() );
     373             : 
     374           0 :                         ::basegfx::B2DHomMatrix     aViewTransform( (*aIter)->getTransformation() );
     375           0 :                         const ::basegfx::B2DPoint       aOutPosPixel( aViewTransform * ::basegfx::B2DPoint() );
     376             : 
     377             :                         // setup a canvas with device coordinate space, the slide
     378             :                         // bitmap already has the correct dimension.
     379           0 :                         ::cppcanvas::CanvasSharedPtr pDevicePixelCanvas( pCanvas->clone() );
     380             : 
     381           0 :                         pDevicePixelCanvas->setTransformation( ::basegfx::B2DHomMatrix() );
     382             : 
     383             :                         // render at given output position
     384           0 :                         pBitmap->move( aOutPosPixel );
     385             : 
     386           0 :                         ::basegfx::B2DPolyPolygon aPolyPoly=::basegfx::B2DPolyPolygon(aPoly);
     387           0 :                         aViewTransform.translate(-aOutPosPixel.getX(), -aOutPosPixel.getY());
     388           0 :                         aPolyPoly.transform(aViewTransform);
     389             :                         // set clip so that we just redraw a part of the canvas
     390           0 :                         pBitmap->clip(aPolyPoly);
     391           0 :                         pBitmap->draw( pDevicePixelCanvas );
     392             : 
     393           0 :                         mrScreenUpdater.notifyUpdate(*aIter,true);
     394           0 :                     }
     395             : 
     396             :         }
     397             :                 else
     398             :                 {
     399           0 :                     if( !mbIsLastPointValid )
     400             :                     {
     401           0 :                         mbIsLastPointValid = true;
     402           0 :                         maLastPoint.setX( e.X );
     403           0 :                         maLastPoint.setY( e.Y );
     404             :                     }
     405             :                     else
     406             :                     {
     407           0 :                         ::basegfx::B2DPolygon aPoly;
     408           0 :                         aPoly.append( maLastPoint );
     409             : 
     410           0 :                         maLastPoint.setX( e.X );
     411           0 :                         maLastPoint.setY( e.Y );
     412             : 
     413           0 :                         aPoly.append( maLastPoint );
     414             : 
     415             :                         // paint to all views
     416           0 :                         for( UnoViewVector::iterator aIter=maViews.begin(), aEnd=maViews.end();
     417             :                              aIter!=aEnd;
     418             :                              ++aIter )
     419             :                         {
     420             :                             ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
     421           0 :                                 ::cppcanvas::BaseGfxFactory::createPolyPolygon( (*aIter)->getCanvas(),
     422           0 :                                                                                 aPoly ) );
     423             : 
     424           0 :                             if( pPolyPoly )
     425             :                             {
     426           0 :                                 pPolyPoly->setStrokeWidth(mnStrokeWidth);
     427           0 :                                 pPolyPoly->setRGBALineColor( maStrokeColor.getIntegerColor() );
     428           0 :                                 pPolyPoly->draw();
     429           0 :                                 maPolygons.push_back(pPolyPoly);
     430             :                             }
     431           0 :                         }
     432             : 
     433             :                         // screen update necessary to show painting
     434           0 :                         mrScreenUpdater.notifyUpdate();
     435             :                     }
     436             :                 }
     437             :                 // mouse events captured
     438           0 :                 return true;
     439             :             }
     440             : 
     441           0 :             virtual bool handleMouseMoved( const awt::MouseEvent& /*e*/ ) SAL_OVERRIDE
     442             :             {
     443             :                 // not used here
     444           0 :                 return false; // did not handle the event
     445             :             }
     446             : 
     447             :         private:
     448             :             ScreenUpdater&          mrScreenUpdater;
     449             :             UnoViewVector           maViews;
     450             :             PolyPolygonVector       maPolygons;
     451             :             RGBColor                maStrokeColor;
     452             :             double                  mnStrokeWidth;
     453             :             basegfx::B2DPoint       maLastPoint;
     454             :             basegfx::B2DPoint       maLastMouseDownPos;
     455             :             bool                    mbIsLastPointValid;
     456             :             bool                    mbIsLastMouseDownPosValid;
     457             :             // added bool for erasing purpose :
     458             :             bool                    mbIsEraseAllModeActivated;
     459             :             bool                    mbIsEraseModeActivated;
     460             :             Slide&                  mrSlide;
     461             :             sal_Int32               mnSize;
     462             :             bool                    mbActive;
     463             :         };
     464             : 
     465           0 :         UserPaintOverlaySharedPtr UserPaintOverlay::create( const RGBColor&          rStrokeColor,
     466             :                                                             double                   nStrokeWidth,
     467             :                                                             const SlideShowContext&  rContext,
     468             :                                                             const PolyPolygonVector& rPolygons,
     469             :                                                             bool                     bActive )
     470             :         {
     471             :             UserPaintOverlaySharedPtr pRet( new UserPaintOverlay( rStrokeColor,
     472             :                                                                   nStrokeWidth,
     473             :                                                                   rContext,
     474             :                                                                   rPolygons,
     475           0 :                                                                   bActive));
     476             : 
     477           0 :             return pRet;
     478             :         }
     479             : 
     480           0 :         UserPaintOverlay::UserPaintOverlay( const RGBColor&          rStrokeColor,
     481             :                                             double                   nStrokeWidth,
     482             :                                             const SlideShowContext&  rContext,
     483             :                                             const PolyPolygonVector& rPolygons,
     484             :                                             bool                     bActive ) :
     485             :             mpHandler( new PaintOverlayHandler( rStrokeColor,
     486             :                                                 nStrokeWidth,
     487             :                                                 rContext.mrScreenUpdater,
     488             :                                                 rContext.mrViewContainer,
     489             :                                                 //adding a link to Slide
     490           0 :                                                 dynamic_cast<Slide&>(rContext.mrCursorManager),
     491           0 :                                                 rPolygons, bActive )),
     492           0 :             mrMultiplexer( rContext.mrEventMultiplexer )
     493             :         {
     494           0 :             mrMultiplexer.addClickHandler( mpHandler, 3.0 );
     495           0 :             mrMultiplexer.addMouseMoveHandler( mpHandler, 3.0 );
     496           0 :             mrMultiplexer.addViewHandler( mpHandler );
     497           0 :             mrMultiplexer.addUserPaintHandler(mpHandler);
     498           0 :         }
     499             : 
     500           0 :         PolyPolygonVector UserPaintOverlay::getPolygons()
     501             :         {
     502           0 :             return mpHandler->getPolygons();
     503             :         }
     504             : 
     505           0 :         void UserPaintOverlay::drawPolygons()
     506             :         {
     507           0 :             mpHandler->drawPolygons();
     508           0 :         }
     509             : 
     510           0 :         UserPaintOverlay::~UserPaintOverlay()
     511             :         {
     512             :             try
     513             :             {
     514           0 :                 mrMultiplexer.removeMouseMoveHandler( mpHandler );
     515           0 :                 mrMultiplexer.removeClickHandler( mpHandler );
     516           0 :                 mrMultiplexer.removeViewHandler( mpHandler );
     517           0 :                 mpHandler->dispose();
     518             :             }
     519           0 :             catch (uno::Exception &)
     520             :             {
     521             :                 OSL_FAIL( OUStringToOString(
     522             :                                 comphelper::anyToString(
     523             :                                     cppu::getCaughtException() ),
     524             :                                 RTL_TEXTENCODING_UTF8 ).getStr() );
     525             :             }
     526           0 :         }
     527             :     }
     528           3 : }
     529             : 
     530             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11