Files
libreoffice/slideshow/source/engine/rehearsetimingsactivity.cxx
Oliver Bolte dafb45b3ae INTEGRATION: CWS pchfix02 (1.7.48); FILE MERGED
2006/09/01 17:39:32 kaib 1.7.48.1: #i68856# Added header markers and pch files
2006-09-17 07:27:18 +00:00

493 lines
15 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: rehearsetimingsactivity.cxx,v $
*
* $Revision: 1.8 $
*
* last change: $Author: obo $ $Date: 2006-09-17 08:27:18 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"
#include "rtl/ustrbuf.hxx"
#include "vcl/svapp.hxx"
#include "vcl/gdimtf.hxx"
#include "vcl/virdev.hxx"
#include "vcl/metric.hxx"
#include "cppcanvas/vclfactory.hxx"
#include "cppcanvas/basegfxfactory.hxx"
#include "eventqueue.hxx"
#include "eventmultiplexer.hxx"
#include "activitiesqueue.hxx"
#include "mouseeventhandler.hxx"
#include "rehearsetimingsactivity.hxx"
#include "com/sun/star/awt/MouseButton.hpp"
#include "com/sun/star/awt/MouseEvent.hpp"
#include "com/sun/star/rendering/XBitmap.hpp"
#include "boost/bind.hpp"
#include <algorithm>
using namespace com::sun::star;
using namespace com::sun::star::uno;
namespace presentation {
namespace internal {
class RehearseTimingsActivity::MouseHandler
: public MouseEventHandler, private boost::noncopyable
{
public:
MouseHandler( boost::shared_ptr<RehearseTimingsActivity> const & rta );
void reset();
bool hasBeenClicked() const { return m_hasBeenClicked; }
// Disposable:
virtual void dispose();
// MouseEventHandler
virtual bool handleMousePressed( awt::MouseEvent const & evt );
virtual bool handleMouseReleased( awt::MouseEvent const & evt );
virtual bool handleMouseEntered( awt::MouseEvent const & evt );
virtual bool handleMouseExited( awt::MouseEvent const & evt );
virtual bool handleMouseDragged( awt::MouseEvent const & evt );
virtual bool handleMouseMoved( awt::MouseEvent const & evt );
private:
boost::shared_ptr<RehearseTimingsActivity> m_rta;
bool isInArea( com::sun::star::awt::MouseEvent const & evt ) const;
bool isDisposed() const { return m_rta.get() == 0 || hasBeenClicked(); }
void updatePressedState( const bool pressedState ) const;
bool m_hasBeenClicked;
bool m_mouseStartedInArea;
};
const sal_Int32 LEFT_BORDER_SPACE = 10;
const sal_Int32 LOWER_BORDER_SPACE = 30;
RehearseTimingsActivity::RehearseTimingsActivity(
EventQueue & rEventQueue,
EventMultiplexer & rEventMultiplexer,
ActivitiesQueue & rActivitiesQueue )
: m_rEventQueue(rEventQueue),
m_rEventMultiplexer(rEventMultiplexer),
m_rActivitiesQueue(rActivitiesQueue),
m_this(),
m_elapsedTime( rEventQueue.getTimer() ),
m_views(),
m_spriteRectangle(),
m_font( Application::GetSettings().GetStyleSettings().GetInfoFont() ),
m_wakeUpEvent( new WakeupEvent( rEventQueue.getTimer(),
rActivitiesQueue ) ),
m_mouseHandler(),
m_bActive(false),
m_drawPressed(false)
{
// m_font.SetOutline(true);
m_font.SetHeight( m_font.GetHeight() * 2 );
m_font.SetWidth( m_font.GetWidth() * 2 );
m_font.SetAlign( ALIGN_BASELINE );
// m_font.SetColor( COL_WHITE );
m_font.SetColor( COL_BLACK );
// determine sprite size (in pixel):
VirtualDevice blackHole;
blackHole.EnableOutput(false);
blackHole.SetFont( m_font );
blackHole.SetMapMode( MAP_PIXEL );
Rectangle rect;
const FontMetric metric( blackHole.GetFontMetric() );
blackHole.GetTextBoundRect(
rect, String(RTL_CONSTASCII_USTRINGPARAM("XX:XX:XX")) );
m_spriteSizePixel = Size(
rect.getWidth() * 12 / 10, metric.GetLineHeight() * 11 / 10 );
m_nYOffset = (metric.GetAscent() + (metric.GetLineHeight() / 20));
}
boost::shared_ptr<RehearseTimingsActivity> RehearseTimingsActivity::create(
EventQueue & rEventQueue,
EventMultiplexer & rEventMultiplexer,
ActivitiesQueue & rActivitiesQueue )
{
boost::shared_ptr<RehearseTimingsActivity> activity(
new RehearseTimingsActivity( rEventQueue,
rEventMultiplexer,
rActivitiesQueue ) );
activity->m_this = activity;
activity->m_mouseHandler.reset( new MouseHandler(activity) );
activity->m_wakeUpEvent->setActivity(activity);
return activity;
}
void RehearseTimingsActivity::start()
{
m_elapsedTime.reset();
m_drawPressed = false;
m_bActive = true;
// paint and show all sprites:
paintAllSprites();
for_each_sprite( boost::bind( &cppcanvas::Sprite::show, _1 ) );
m_rActivitiesQueue.addActivity( m_this );
m_mouseHandler->reset();
m_rEventMultiplexer.addClickHandler(
m_mouseHandler, 42 /* highest prio of all, > 3.0 */ );
m_rEventMultiplexer.addMouseMoveHandler(
m_mouseHandler, 42 /* highest prio of all, > 3.0 */ );
}
double RehearseTimingsActivity::stop()
{
m_rEventMultiplexer.removeMouseMoveHandler( m_mouseHandler );
m_rEventMultiplexer.removeClickHandler( m_mouseHandler );
m_bActive = false; // will be removed from queue
for_each_sprite( boost::bind( &cppcanvas::Sprite::hide, _1 ) );
return m_elapsedTime.getElapsedTime();
}
bool RehearseTimingsActivity::hasBeenClicked() const
{
if (m_mouseHandler.get() != 0)
return m_mouseHandler->hasBeenClicked();
return false;
}
// Disposable:
void RehearseTimingsActivity::dispose()
{
stop();
if (m_wakeUpEvent.get() != 0) {
m_wakeUpEvent->dispose();
m_wakeUpEvent.reset();
}
if (m_mouseHandler.get() != 0) {
m_mouseHandler->dispose();
m_mouseHandler.reset();
}
ViewsVecT().swap( m_views );
m_this.reset();
}
// Activity:
double RehearseTimingsActivity::calcTimeLag() const
{
return 0.0;
}
bool RehearseTimingsActivity::perform()
{
if (! isActive())
return false;
OSL_ENSURE( m_wakeUpEvent.get() != 0, "### no wake-up event!" );
if (m_wakeUpEvent.get() == 0)
return false;
m_wakeUpEvent->start();
m_wakeUpEvent->setNextTimeout( 0.5 /* secs */ );
m_rEventQueue.addEvent( m_wakeUpEvent );
paintAllSprites();
return false; // don't reinsert, WakeupEvent will perform
// that after the given timeout
}
bool RehearseTimingsActivity::isActive() const
{
return m_bActive;
}
bool RehearseTimingsActivity::needsScreenUpdate() const
{
return isActive();
}
void RehearseTimingsActivity::dequeued()
{
// not used here
}
void RehearseTimingsActivity::end()
{
if (isActive()) {
stop();
m_bActive = false;
}
}
basegfx::B2DRectangle RehearseTimingsActivity::calcSpriteRectangle(
UnoViewSharedPtr const & rView ) const
{
const Reference<rendering::XBitmap> xBitmap(
rView->getCanvas()->getUNOCanvas(), UNO_QUERY_THROW );
const geometry::IntegerSize2D realSize( xBitmap->getSize() );
// pixel:
basegfx::B2DPoint spritePos(
std::min<sal_Int32>( realSize.Width, LEFT_BORDER_SPACE ),
std::max<sal_Int32>( 0, realSize.Height - m_spriteSizePixel.getHeight()
- LOWER_BORDER_SPACE ) );
basegfx::B2DHomMatrix transformation( rView->getTransformation() );
transformation.invert();
spritePos *= transformation;
basegfx::B2DSize spriteSize( m_spriteSizePixel.getWidth(),
m_spriteSizePixel.getHeight() );
spriteSize *= transformation;
return basegfx::B2DRectangle(
spritePos.getX(), spritePos.getY(),
spritePos.getX() + spriteSize.getX(),
spritePos.getY() + spriteSize.getY() );
}
void RehearseTimingsActivity::addView( UnoViewSharedPtr const & rView )
{
const ViewsVecT::iterator iEnd( m_views.end() );
if (std::find_if(
m_views.begin(), iEnd,
boost::bind(
std::equal_to<UnoViewSharedPtr>(),
rView,
// select view:
boost::bind( std::select1st<ViewsVecT::value_type>(), _1 ) ) )!=
iEnd)
return; // already added
cppcanvas::CustomSpriteSharedPtr sprite(
rView->createSprite( basegfx::B2DSize(
m_spriteSizePixel.getWidth(),
m_spriteSizePixel.getHeight() ) ) );
sprite->setAlpha( 0.9 );
const basegfx::B2DRectangle spriteRectangle( calcSpriteRectangle( rView ) );
sprite->move( basegfx::B2DPoint(
spriteRectangle.getMinX(), spriteRectangle.getMinY() ) );
m_views.push_back( ViewsVecT::value_type( rView, sprite ) );
if (isActive())
sprite->show();
}
void RehearseTimingsActivity::removeView( UnoViewSharedPtr const & rView )
{
m_views.erase(
std::remove_if(
m_views.begin(), m_views.end(),
boost::bind(
std::equal_to<UnoViewSharedPtr>(),
rView,
// select view:
boost::bind( std::select1st<ViewsVecT::value_type>(), _1 ) ) ),
m_views.end() );
}
void RehearseTimingsActivity::notifyViewChange()
{
if (! m_views.empty()) {
// new sprite pos, transformation might have changed:
m_spriteRectangle = calcSpriteRectangle( m_views.begin()->first );
// reposition all sprites:
const basegfx::B2DPoint spritePos(
m_spriteRectangle.getMinX(), m_spriteRectangle.getMinY() );
for_each_sprite( boost::bind( &cppcanvas::Sprite::move,
_1, boost::cref(spritePos) ) );
}
}
void RehearseTimingsActivity::paintAllSprites() const
{
for_each_sprite(
boost::bind( &RehearseTimingsActivity::paint, this,
// call getContentCanvas() on each sprite:
boost::bind(
&cppcanvas::CustomSprite::getContentCanvas, _1 ) ) );
}
void RehearseTimingsActivity::paint(
cppcanvas::CanvasSharedPtr const & canvas ) const
{
// build timer string:
const sal_Int32 nTimeSecs =
static_cast<sal_Int32>(m_elapsedTime.getElapsedTime());
rtl::OUStringBuffer buf;
sal_Int32 n = (nTimeSecs / 3600);
if (n < 10)
buf.append( static_cast<sal_Unicode>('0') );
buf.append( n );
buf.append( static_cast<sal_Unicode>(':') );
n = ((nTimeSecs % 3600) / 60);
if (n < 10)
buf.append( static_cast<sal_Unicode>('0') );
buf.append( n );
buf.append( static_cast<sal_Unicode>(':') );
n = (nTimeSecs % 60);
if (n < 10)
buf.append( static_cast<sal_Unicode>('0') );
buf.append( n );
const rtl::OUString time = buf.makeStringAndClear();
cppcanvas::BaseGfxFactory & factory =
cppcanvas::BaseGfxFactory::getInstance();
// create the MetaFile:
GDIMetaFile metaFile;
VirtualDevice blackHole;
metaFile.Record( &blackHole );
metaFile.SetPrefSize( Size( 1, 1 ) );
blackHole.EnableOutput(false);
blackHole.SetMapMode( MAP_PIXEL );
blackHole.SetFont( m_font );
Rectangle rect = Rectangle( Point(), m_spriteSizePixel );
if (m_drawPressed) {
blackHole.SetTextColor( COL_BLACK );
blackHole.SetFillColor( COL_LIGHTGRAY );
blackHole.SetLineColor( COL_GRAY );
}
else {
blackHole.SetTextColor( COL_BLACK );
blackHole.SetFillColor( COL_WHITE );
blackHole.SetLineColor( COL_GRAY );
}
blackHole.DrawRect( rect );
blackHole.GetTextBoundRect( rect, time );
blackHole.DrawText(
Point( (m_spriteSizePixel.getWidth() - rect.getWidth()) / 2,
m_nYOffset ), time );
metaFile.Stop();
metaFile.WindStart();
cppcanvas::RendererSharedPtr renderer(
cppcanvas::VCLFactory::getInstance().createRenderer(
canvas, metaFile, cppcanvas::Renderer::Parameters() ) );
const bool succ = renderer->draw();
OSL_ASSERT( succ ); succ;
}
RehearseTimingsActivity::MouseHandler::MouseHandler(
boost::shared_ptr<RehearseTimingsActivity> const & rta )
: m_rta(rta),
m_hasBeenClicked(false),
m_mouseStartedInArea(false)
{
}
void RehearseTimingsActivity::MouseHandler::reset()
{
m_hasBeenClicked = false;
m_mouseStartedInArea = false;
}
// Disposable:
void RehearseTimingsActivity::MouseHandler::dispose()
{
m_rta.reset();
}
bool RehearseTimingsActivity::MouseHandler::isInArea(
awt::MouseEvent const & evt ) const
{
if (m_rta.get() != 0)
return m_rta->m_spriteRectangle.isInside(
basegfx::B2DPoint( evt.X, evt.Y ) );
return false;
}
void RehearseTimingsActivity::MouseHandler::updatePressedState(
const bool pressedState ) const
{
if (pressedState != m_rta->m_drawPressed)
{
m_rta->m_drawPressed = pressedState;
m_rta->paintAllSprites();
// update screen immediately (cannot wait for next
// ActivitiesQueue loop)
m_rta->m_rEventMultiplexer.updateScreenContent( true );
}
}
// MouseEventHandler
bool RehearseTimingsActivity::MouseHandler::handleMousePressed(
awt::MouseEvent const & evt )
{
if (evt.Buttons == awt::MouseButton::LEFT &&
!isDisposed() && isInArea(evt))
{
m_mouseStartedInArea = true;
updatePressedState(true);
return true; // consume event
}
return false;
}
bool RehearseTimingsActivity::MouseHandler::handleMouseReleased(
awt::MouseEvent const & evt )
{
if (evt.Buttons == awt::MouseButton::LEFT &&
!isDisposed() && m_mouseStartedInArea)
{
m_hasBeenClicked = isInArea(evt); // fini if in
m_mouseStartedInArea = false;
updatePressedState(false);
if (! m_hasBeenClicked)
return true; // consume event, else next slide (manual advance)
}
return false;
}
bool RehearseTimingsActivity::MouseHandler::handleMouseEntered(
awt::MouseEvent const & evt )
{
return false;
}
bool RehearseTimingsActivity::MouseHandler::handleMouseExited(
awt::MouseEvent const & evt )
{
return false;
}
bool RehearseTimingsActivity::MouseHandler::handleMouseDragged(
awt::MouseEvent const & evt )
{
if (!isDisposed() && m_mouseStartedInArea)
updatePressedState( isInArea(evt) );
return false;
}
bool RehearseTimingsActivity::MouseHandler::handleMouseMoved(
awt::MouseEvent const & evt )
{
return false;
}
} // namespace internal
} // namespace presentation