blob: 13a9eea0be16bff097f742dc730e794f3b96976d [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sdext.hxx"
#include "PresenterToolBar.hxx"
#include "PresenterBitmapContainer.hxx"
#include "PresenterCanvasHelper.hxx"
#include "PresenterGeometryHelper.hxx"
#include "PresenterPaintManager.hxx"
#include "PresenterPaneBase.hxx"
#include "PresenterPaneFactory.hxx"
#include "PresenterTimer.hxx"
#include "PresenterWindowManager.hxx"
#include <cppuhelper/compbase2.hxx>
#include <com/sun/star/awt/FontDescriptor.hpp>
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/deployment/XPackageInformationProvider.hpp>
#include <com/sun/star/drawing/framework/XControllerManager.hpp>
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#include <com/sun/star/drawing/framework/XPane.hpp>
#include <com/sun/star/geometry/AffineMatrix2D.hpp>
#include <com/sun/star/lang/XServiceName.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/RenderState.hpp>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <com/sun/star/rendering/ViewState.hpp>
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/util/Color.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <rtl/ustrbuf.hxx>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <map>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;
using ::rtl::OUString;
#define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
namespace sdext { namespace presenter {
static const sal_Int32 gnGapSize (20);
static const sal_Int32 gnMinimalSeparatorSize (20);
static const sal_Int32 gnSeparatorInset (0);
namespace {
class Text
{
public:
Text (void);
Text (const Text& rText);
Text (
const OUString& rsText,
const PresenterTheme::SharedFontDescriptor& rpFont);
void SetText (const OUString& rsText);
OUString GetText (void) const;
PresenterTheme::SharedFontDescriptor GetFont (void) const;
void Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState,
const awt::Rectangle& rBoundingBox,
const awt::Point& rOffset);
geometry::RealRectangle2D GetBoundingBox (
const Reference<rendering::XCanvas>& rxCanvas);
private:
OUString msText;
PresenterTheme::SharedFontDescriptor mpFont;
};
class ElementMode
: private ::boost::noncopyable
{
public:
ElementMode (void);
SharedBitmapDescriptor mpIcon;
OUString msAction;
Text maText;
void ReadElementMode (
const Reference<beans::XPropertySet>& rxProperties,
const ::rtl::OUString& rsModeName,
::boost::shared_ptr<ElementMode>& rpDefaultMode,
::sdext::presenter::PresenterToolBar::Context& rContext);
};
typedef ::boost::shared_ptr<ElementMode> SharedElementMode;
} // end of anonymous namespace
class PresenterToolBar::Context
: private ::boost::noncopyable
{
public:
Reference<drawing::XPresenterHelper> mxPresenterHelper;
css::uno::Reference<css::rendering::XCanvas> mxCanvas;
};
//===== PresenterToolBar::Element =============================================
namespace {
typedef cppu::WeakComponentImplHelper2<
css::document::XEventListener,
css::frame::XStatusListener
> ElementInterfaceBase;
class Element
: private ::cppu::BaseMutex,
private ::boost::noncopyable,
public ElementInterfaceBase
{
public:
Element (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual ~Element (void);
virtual void SAL_CALL disposing (void);
virtual void SetModes (
const SharedElementMode& rpNormalMode,
const SharedElementMode& rpMouseOverMode,
const SharedElementMode& rpSelectedMode,
const SharedElementMode& rpDisabledMode);
virtual void CurrentSlideHasChanged (void);
virtual void SetLocation (const awt::Point& rLocation);
virtual void SetSize (const geometry::RealSize2D& rSize);
virtual void Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState) = 0;
awt::Size GetBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas);
awt::Rectangle GetBoundingBox (void) const;
virtual bool SetState (const bool bIsOver, const bool bIsPressed);
virtual void Invalidate (const bool bSynchronous = true);
virtual bool IsOutside (const awt::Rectangle& rBox);
virtual bool IsFilling (void) const;
void UpdateState (void);
OUString GetAction (void) const;
// lang::XEventListener
virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
throw(css::uno::RuntimeException);
// document::XEventListener
virtual void SAL_CALL notifyEvent (const css::document::EventObject& rEvent)
throw(css::uno::RuntimeException);
// frame::XStatusListener
virtual void SAL_CALL statusChanged (const css::frame::FeatureStateEvent& rEvent)
throw(css::uno::RuntimeException);
protected:
::rtl::Reference<PresenterToolBar> mpToolBar;
awt::Point maLocation;
awt::Size maSize;
SharedElementMode mpNormal;
SharedElementMode mpMouseOver;
SharedElementMode mpSelected;
SharedElementMode mpDisabled;
SharedElementMode mpMode;
bool mbIsOver;
bool mbIsPressed;
bool mbIsSelected;
virtual awt::Size CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas) = 0;
bool IsEnabled (void) const;
void SetEnabledState (const bool bIsEnabled);
private:
bool mbIsEnabled;
};
} // end of anonymous namespace
class PresenterToolBar::ElementContainerPart
: public ::std::vector<rtl::Reference<Element> >
{
};
//===== Button ================================================================
namespace {
class Button : public Element
{
public:
static ::rtl::Reference<Element> Create (
const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual ~Button (void);
virtual void SAL_CALL disposing (void);
virtual void Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState);
// lang::XEventListener
virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent)
throw(css::uno::RuntimeException);
protected:
virtual awt::Size CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas);
private:
bool mbIsListenerRegistered;
Button (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
void Initialize (void);
void PaintIcon (
const Reference<rendering::XCanvas>& rxCanvas,
const sal_Int32 nTextHeight,
const rendering::ViewState& rViewState);
PresenterBitmapDescriptor::Mode GetMode (void) const;
};
//===== Label =================================================================
class Label : public Element
{
public:
Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
void SetText (const OUString& rsText);
virtual void Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState);
virtual bool SetState (const bool bIsOver, const bool bIsPressed);
protected:
virtual awt::Size CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas);
};
// Some specialized controls.
class ProgressLabel : public Label
{
public:
ProgressLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual void CurrentSlideHasChanged (void);
};
class TimeFormatter
{
public:
TimeFormatter (void);
OUString FormatTime (const oslDateTime& rTime);
private:
bool mbIs24HourFormat;
bool mbIsAmPmFormat;
bool mbIsShowSeconds;
};
class TimeLabel : public Label
{
public:
void ConnectToTimer (void);
virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0;
protected:
TimeLabel(const ::rtl::Reference<PresenterToolBar>& rpToolBar);
using Element::disposing;
virtual void SAL_CALL disposing (void);
private:
class Listener : public PresenterClockTimer::Listener
{
public:
Listener (const ::rtl::Reference<TimeLabel>& rxLabel)
: mxLabel(rxLabel) {}
virtual ~Listener (void) {}
virtual void TimeHasChanged (const oslDateTime& rCurrentTime)
{ if (mxLabel.is()) mxLabel->TimeHasChanged(rCurrentTime); }
private:
::rtl::Reference<TimeLabel> mxLabel;
};
::boost::shared_ptr<PresenterClockTimer::Listener> mpListener;
};
class CurrentTimeLabel : public TimeLabel
{
public:
static ::rtl::Reference<Element> Create (
const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual void SetModes (
const SharedElementMode& rpNormalMode,
const SharedElementMode& rpMouseOverMode,
const SharedElementMode& rpSelectedMode,
const SharedElementMode& rpDisabledMode);
private:
TimeFormatter maTimeFormatter;
CurrentTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual ~CurrentTimeLabel (void);
virtual void TimeHasChanged (const oslDateTime& rCurrentTime);
};
class PresentationTimeLabel : public TimeLabel
{
public:
static ::rtl::Reference<Element> Create (
const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual void SetModes (
const SharedElementMode& rpNormalMode,
const SharedElementMode& rpMouseOverMode,
const SharedElementMode& rpSelectedMode,
const SharedElementMode& rpDisabledMode);
private:
TimeFormatter maTimeFormatter;
TimeValue maStartTimeValue;
PresentationTimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual ~PresentationTimeLabel (void);
virtual void TimeHasChanged (const oslDateTime& rCurrentTime);
};
class VerticalSeparator : public Element
{
public:
explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual void Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState);
virtual bool IsFilling (void) const;
protected:
virtual awt::Size CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas);
};
class HorizontalSeparator : public Element
{
public:
explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar);
virtual void Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState);
virtual bool IsFilling (void) const;
protected:
virtual awt::Size CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas);
};
} // end of anonymous namespace
//===== PresenterToolBar ======================================================
PresenterToolBar::PresenterToolBar (
const Reference<XComponentContext>& rxContext,
const css::uno::Reference<css::awt::XWindow>& rxWindow,
const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
const ::rtl::Reference<PresenterController>& rpPresenterController,
const Anchor eAnchor)
: PresenterToolBarInterfaceBase(m_aMutex),
mxComponentContext(rxContext),
maElementContainer(),
mpCurrentContainerPart(),
mxWindow(rxWindow),
mxCanvas(rxCanvas),
mxSlideShowController(),
mxCurrentSlide(),
mpPresenterController(rpPresenterController),
mbIsLayoutPending(false),
meAnchor(eAnchor),
maBoundingBox(),
maMinimalSize()
{
}
void PresenterToolBar::Initialize (
const ::rtl::OUString& rsConfigurationPath)
{
try
{
CreateControls(rsConfigurationPath);
if (mxWindow.is())
{
mxWindow->addWindowListener(this);
mxWindow->addPaintListener(this);
mxWindow->addMouseListener(this);
mxWindow->addMouseMotionListener(this);
Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
if (xPeer.is())
xPeer->setBackground(util::Color(0xff000000));
mxWindow->setVisible(sal_True);
}
mxSlideShowController = mpPresenterController->GetSlideShowController();
UpdateSlideNumber();
mbIsLayoutPending = true;
}
catch (RuntimeException&)
{
mpCurrentContainerPart.reset();
maElementContainer.clear();
throw;
}
}
PresenterToolBar::~PresenterToolBar (void)
{
}
void SAL_CALL PresenterToolBar::disposing (void)
{
if (mxWindow.is())
{
mxWindow->removeWindowListener(this);
mxWindow->removePaintListener(this);
mxWindow->removeMouseListener(this);
mxWindow->removeMouseMotionListener(this);
mxWindow = NULL;
}
// Dispose tool bar elements.
ElementContainer::iterator iPart (maElementContainer.begin());
ElementContainer::const_iterator iEnd (maElementContainer.end());
for ( ; iPart!=iEnd; ++iPart)
{
OSL_ASSERT(iPart->get()!=NULL);
ElementContainerPart::iterator iElement ((*iPart)->begin());
ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
for ( ; iElement!=iPartEnd; ++iElement)
{
if (iElement->get() != NULL)
{
::rtl::Reference<Element> pElement (*iElement);
Reference<lang::XComponent> xComponent (
static_cast<XWeak*>(pElement.get()), UNO_QUERY);
if (xComponent.is())
xComponent->dispose();
}
}
}
mpCurrentContainerPart.reset();
maElementContainer.clear();
}
void PresenterToolBar::InvalidateArea (
const awt::Rectangle& rRepaintBox,
const bool bSynchronous)
{
mpPresenterController->GetPaintManager()->Invalidate(
mxWindow,
rRepaintBox,
bSynchronous);
}
sal_Int32 PresenterToolBar::GetCurrentSlideIndex (void)
{
if (mxSlideShowController.is())
return mxSlideShowController->getCurrentSlideIndex();
else
return -1;
}
sal_Int32 PresenterToolBar::GetSlideCount (void)
{
if (mxSlideShowController.is())
return mxSlideShowController->getSlideCount();
else
return 0;
}
void PresenterToolBar::RequestLayout (void)
{
mbIsLayoutPending = true;
mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
}
geometry::RealSize2D PresenterToolBar::GetSize (void)
{
if (mbIsLayoutPending)
Layout(mxCanvas);
return geometry::RealSize2D(
maBoundingBox.X2 - maBoundingBox.X1,
maBoundingBox.Y2 - maBoundingBox.Y1);
}
geometry::RealSize2D PresenterToolBar::GetMinimalSize (void)
{
if (mbIsLayoutPending)
Layout(mxCanvas);
return maMinimalSize;
}
::rtl::Reference<PresenterController> PresenterToolBar::GetPresenterController (void) const
{
return mpPresenterController;
}
Reference<awt::XWindow> PresenterToolBar::GetWindow (void) const
{
return mxWindow;
}
Reference<XComponentContext> PresenterToolBar::GetComponentContext (void) const
{
return mxComponentContext;
}
//----- lang::XEventListener -------------------------------------------------
void SAL_CALL PresenterToolBar::disposing (const lang::EventObject& rEventObject)
throw (RuntimeException)
{
if (rEventObject.Source == mxWindow)
mxWindow = NULL;
}
//----- XWindowListener -------------------------------------------------------
void SAL_CALL PresenterToolBar::windowResized (const awt::WindowEvent& rEvent)
throw (RuntimeException)
{
(void)rEvent;
mbIsLayoutPending = true;
}
void SAL_CALL PresenterToolBar::windowMoved (const awt::WindowEvent& rEvent)
throw (RuntimeException)
{
(void)rEvent;
}
void SAL_CALL PresenterToolBar::windowShown (const lang::EventObject& rEvent)
throw (RuntimeException)
{
(void)rEvent;
mbIsLayoutPending = true;
}
void SAL_CALL PresenterToolBar::windowHidden (const lang::EventObject& rEvent)
throw (RuntimeException)
{
(void)rEvent;
}
//----- XPaintListener --------------------------------------------------------
void SAL_CALL PresenterToolBar::windowPaint (const css::awt::PaintEvent& rEvent)
throw (RuntimeException)
{
if ( ! mxCanvas.is())
return;
if ( ! mbIsPresenterViewActive)
return;
const rendering::ViewState aViewState (
geometry::AffineMatrix2D(1,0,0, 0,1,0),
PresenterGeometryHelper::CreatePolygon(rEvent.UpdateRect, mxCanvas->getDevice()));
if (mbIsLayoutPending)
Layout(mxCanvas);
Paint(rEvent.UpdateRect, aViewState);
// Make the back buffer visible.
Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
if (xSpriteCanvas.is())
xSpriteCanvas->updateScreen(sal_False);
}
//----- XMouseListener --------------------------------------------------------
void SAL_CALL PresenterToolBar::mousePressed (const css::awt::MouseEvent& rEvent)
throw(css::uno::RuntimeException)
{
CheckMouseOver(rEvent, true, true);
}
void SAL_CALL PresenterToolBar::mouseReleased (const css::awt::MouseEvent& rEvent)
throw(css::uno::RuntimeException)
{
CheckMouseOver(rEvent, true);
}
void SAL_CALL PresenterToolBar::mouseEntered (const css::awt::MouseEvent& rEvent)
throw(css::uno::RuntimeException)
{
CheckMouseOver(rEvent, true);
}
void SAL_CALL PresenterToolBar::mouseExited (const css::awt::MouseEvent& rEvent)
throw(css::uno::RuntimeException)
{
CheckMouseOver(rEvent, false);
}
//----- XMouseMotionListener --------------------------------------------------
void SAL_CALL PresenterToolBar::mouseMoved (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
ThrowIfDisposed();
CheckMouseOver(rEvent, true);
}
void SAL_CALL PresenterToolBar::mouseDragged (const css::awt::MouseEvent& rEvent)
throw (css::uno::RuntimeException)
{
ThrowIfDisposed();
(void)rEvent;
}
//----- XDrawView -------------------------------------------------------------
void SAL_CALL PresenterToolBar::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
throw (RuntimeException)
{
if (rxSlide != mxCurrentSlide)
{
mxCurrentSlide = rxSlide;
UpdateSlideNumber();
}
}
Reference<drawing::XDrawPage> SAL_CALL PresenterToolBar::getCurrentPage (void)
throw (RuntimeException)
{
return mxCurrentSlide;
}
//-----------------------------------------------------------------------------
void PresenterToolBar::CreateControls (
const ::rtl::OUString& rsConfigurationPath)
{
if ( ! mxWindow.is())
return;
// Expand the macro in the bitmap file names.
PresenterConfigurationAccess aConfiguration (
mxComponentContext,
OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"),
PresenterConfigurationAccess::READ_ONLY);
mpCurrentContainerPart.reset(new ElementContainerPart());
maElementContainer.clear();
maElementContainer.push_back(mpCurrentContainerPart);
Reference<container::XHierarchicalNameAccess> xToolBarNode (
aConfiguration.GetConfigurationNode(rsConfigurationPath),
UNO_QUERY);
if (xToolBarNode.is())
{
Reference<container::XNameAccess> xEntries (
PresenterConfigurationAccess::GetConfigurationNode(xToolBarNode, A2S("Entries")),
UNO_QUERY);
Context aContext;
aContext.mxPresenterHelper = mpPresenterController->GetPresenterHelper();
aContext.mxCanvas = mxCanvas;
if (xEntries.is()
&& aContext.mxPresenterHelper.is()
&& aContext.mxCanvas.is())
{
PresenterConfigurationAccess::ForAll(
xEntries,
::boost::bind(&PresenterToolBar::ProcessEntry, this, _2, ::boost::ref(aContext)));
}
}
}
void PresenterToolBar::ProcessEntry (
const Reference<beans::XPropertySet>& rxProperties,
Context& rContext)
{
if ( ! rxProperties.is())
return;
// Type has to be present.
OUString sType;
if ( ! (PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Type")) >>= sType))
return;
OUString sName;
PresenterConfigurationAccess::GetProperty(rxProperties, A2S("Name")) >>= sName;
// Read mode specific values.
SharedElementMode pNormalMode (new ElementMode());
SharedElementMode pMouseOverMode (new ElementMode());
SharedElementMode pSelectedMode (new ElementMode());
SharedElementMode pDisabledMode (new ElementMode());
pNormalMode->ReadElementMode(rxProperties, A2S("Normal"), pNormalMode, rContext);
pMouseOverMode->ReadElementMode(rxProperties, A2S("MouseOver"), pNormalMode, rContext);
pSelectedMode->ReadElementMode(rxProperties, A2S("Selected"), pNormalMode, rContext);
pDisabledMode->ReadElementMode(rxProperties, A2S("Disabled"), pNormalMode, rContext);
// Create new element.
::rtl::Reference<Element> pElement;
if (sType.equalsAscii("Button"))
pElement = Button::Create(this);
else if (sType.equalsAscii("CurrentTimeLabel"))
pElement = CurrentTimeLabel::Create(this);
else if (sType.equalsAscii("PresentationTimeLabel"))
pElement = PresentationTimeLabel::Create(this);
else if (sType.equalsAscii("VerticalSeparator"))
pElement = ::rtl::Reference<Element>(new VerticalSeparator(this));
else if (sType.equalsAscii("HorizontalSeparator"))
pElement = ::rtl::Reference<Element>(new HorizontalSeparator(this));
else if (sType.equalsAscii("Label"))
pElement = ::rtl::Reference<Element>(new Label(this));
else if (sType.equalsAscii("ChangeOrientation"))
{
mpCurrentContainerPart.reset(new ElementContainerPart());
maElementContainer.push_back(mpCurrentContainerPart);
return;
}
if (pElement.is())
{
pElement->SetModes( pNormalMode, pMouseOverMode, pSelectedMode, pDisabledMode);
pElement->UpdateState();
if (mpCurrentContainerPart.get() != NULL)
mpCurrentContainerPart->push_back(pElement);
}
}
void PresenterToolBar::Layout (
const Reference<rendering::XCanvas>& rxCanvas)
{
if (maElementContainer.size() == 0)
return;
mbIsLayoutPending = false;
const awt::Rectangle aWindowBox (mxWindow->getPosSize());
ElementContainer::iterator iPart;
ElementContainer::iterator iEnd (maElementContainer.end());
::std::vector<geometry::RealSize2D> aPartSizes (maElementContainer.size());
geometry::RealSize2D aTotalSize (0,0);
bool bIsHorizontal (true);
sal_Int32 nIndex;
double nTotalHorizontalGap (0);
sal_Int32 nGapCount (0);
for (iPart=maElementContainer.begin(),nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
{
geometry::RealSize2D aSize (CalculatePartSize(rxCanvas, *iPart, bIsHorizontal));
// Remember the size of each part for later.
aPartSizes[nIndex] = aSize;
// Add gaps between elements.
if ((*iPart)->size()>1 && bIsHorizontal)
{
nTotalHorizontalGap += ((*iPart)->size() - 1) * gnGapSize;
nGapCount += (*iPart)->size()-1;
}
// Orientation changes for each part.
bIsHorizontal = !bIsHorizontal;
// Width is accumulated.
aTotalSize.Width += aSize.Width;
// Height is the maximum height of all parts.
aTotalSize.Height = ::std::max(aTotalSize.Height, aSize.Height);
}
// Add gaps between parts.
if (maElementContainer.size() > 1)
{
nTotalHorizontalGap += (maElementContainer.size() - 1) * gnGapSize;
nGapCount += maElementContainer.size()-1;
}
// Calculate the minimal size so that the window size of the tool bar
// can be adapted accordingly.
maMinimalSize = aTotalSize;
maMinimalSize.Width += nTotalHorizontalGap;
// Calculate the gaps between elements.
double nGapWidth (0);
if (nGapCount > 0)
{
if (aTotalSize.Width + nTotalHorizontalGap > aWindowBox.Width)
nTotalHorizontalGap = aWindowBox.Width - aTotalSize.Width;
nGapWidth = nTotalHorizontalGap / nGapCount;
}
// Determine the location of the left edge.
double nX (0);
switch (meAnchor)
{
case Left : nX = 0; break;
case Center: nX = (aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap) / 2; break;
case Right: nX = aWindowBox.Width - aTotalSize.Width - nTotalHorizontalGap; break;
}
// Place the parts.
double nY ((aWindowBox.Height - aTotalSize.Height) / 2);
bIsHorizontal = true;
maBoundingBox.X1 = nX;
maBoundingBox.Y1 = nY;
maBoundingBox.X2 = nX + aTotalSize.Width + nTotalHorizontalGap;
maBoundingBox.Y2 = nY + aTotalSize.Height;
for (iPart=maElementContainer.begin(), nIndex=0; iPart!=iEnd; ++iPart,++nIndex)
{
geometry::RealRectangle2D aBoundingBox(
nX, nY,
nX+aPartSizes[nIndex].Width, nY+aTotalSize.Height);
// Add space for gaps between elements.
if ((*iPart)->size() > 1)
if (bIsHorizontal)
aBoundingBox.X2 += ((*iPart)->size()-1) * nGapWidth;
LayoutPart(rxCanvas, *iPart, aBoundingBox, aPartSizes[nIndex], bIsHorizontal);
bIsHorizontal = !bIsHorizontal;
nX += aBoundingBox.X2 - aBoundingBox.X1 + nGapWidth;
}
// The whole window has to be repainted.
mpPresenterController->GetPaintManager()->Invalidate(mxWindow);
}
geometry::RealSize2D PresenterToolBar::CalculatePartSize (
const Reference<rendering::XCanvas>& rxCanvas,
const SharedElementContainerPart& rpPart,
const bool bIsHorizontal)
{
geometry::RealSize2D aTotalSize (0,0);
if (mxWindow.is())
{
const awt::Rectangle aWindowBox (mxWindow->getPosSize());
// Calculate the summed width of all elements.
ElementContainerPart::const_iterator iElement;
for (iElement=rpPart->begin(); iElement!=rpPart->end(); ++iElement)
{
if (iElement->get() == NULL)
continue;
const awt::Size aBSize ((*iElement)->GetBoundingSize(rxCanvas));
if (bIsHorizontal)
{
aTotalSize.Width += aBSize.Width;
if (aBSize.Height > aTotalSize.Height)
aTotalSize.Height = aBSize.Height;
}
else
{
aTotalSize.Height += aBSize.Height;
if (aBSize.Width > aTotalSize.Width)
aTotalSize.Width = aBSize.Width;
}
}
}
return aTotalSize;
}
void PresenterToolBar::LayoutPart (
const Reference<rendering::XCanvas>& rxCanvas,
const SharedElementContainerPart& rpPart,
const geometry::RealRectangle2D& rBoundingBox,
const geometry::RealSize2D& rPartSize,
const bool bIsHorizontal)
{
double nGap (0);
if (rpPart->size() > 1)
{
if (bIsHorizontal)
nGap = (rBoundingBox.X2 - rBoundingBox.X1 - rPartSize.Width) / (rpPart->size()-1);
else
nGap = (rBoundingBox.Y2 - rBoundingBox.Y1 - rPartSize.Height) / (rpPart->size()-1);
}
// Place the elements.
double nX (rBoundingBox.X1);
double nY (rBoundingBox.Y1);
ElementContainerPart::const_iterator iElement;
ElementContainerPart::const_iterator iEnd (rpPart->end());
for (iElement=rpPart->begin(); iElement!=iEnd; ++iElement)
{
if (iElement->get() == NULL)
continue;
const awt::Size aElementSize ((*iElement)->GetBoundingSize(rxCanvas));
if (bIsHorizontal)
{
if ((*iElement)->IsFilling())
{
nY = rBoundingBox.Y1;
(*iElement)->SetSize(geometry::RealSize2D(aElementSize.Width, rBoundingBox.Y2 - rBoundingBox.Y1));
}
else
nY = rBoundingBox.Y1 + (rBoundingBox.Y2-rBoundingBox.Y1 - aElementSize.Height) / 2;
(*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
nX += aElementSize.Width + nGap;
}
else
{
if ((*iElement)->IsFilling())
{
nX = rBoundingBox.X1;
(*iElement)->SetSize(geometry::RealSize2D(rBoundingBox.X2 - rBoundingBox.X1, aElementSize.Height));
}
else
nX = rBoundingBox.X1 + (rBoundingBox.X2-rBoundingBox.X1 - aElementSize.Width) / 2;
(*iElement)->SetLocation(awt::Point(sal_Int32(0.5 + nX), sal_Int32(0.5 + nY)));
nY += aElementSize.Height + nGap;
}
}
}
void PresenterToolBar::Paint (
const awt::Rectangle& rUpdateBox,
const rendering::ViewState& rViewState)
{
OSL_ASSERT(mxCanvas.is());
ElementContainer::iterator iPart;
ElementContainer::const_iterator iEnd (maElementContainer.end());
for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
{
ElementContainerPart::iterator iElement;
ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
{
if (iElement->get() != NULL)
{
if ( ! (*iElement)->IsOutside(rUpdateBox))
(*iElement)->Paint(mxCanvas, rViewState);
}
}
}
}
void PresenterToolBar::UpdateSlideNumber (void)
{
if( mxSlideShowController.is() )
{
ElementContainer::iterator iPart;
ElementContainer::const_iterator iEnd (maElementContainer.end());
for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
{
ElementContainerPart::iterator iElement;
ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
{
if (iElement->get() != NULL)
(*iElement)->CurrentSlideHasChanged();
}
}
}
}
void PresenterToolBar::CheckMouseOver (
const css::awt::MouseEvent& rEvent,
const bool bOverWindow,
const bool bMouseDown)
{
ElementContainer::iterator iPart;
ElementContainer::const_iterator iEnd (maElementContainer.end());
for (iPart=maElementContainer.begin(); iPart!=iEnd; ++iPart)
{
ElementContainerPart::iterator iElement;
ElementContainerPart::const_iterator iPartEnd ((*iPart)->end());
for (iElement=(*iPart)->begin(); iElement!=iPartEnd; ++iElement)
{
if (iElement->get() == NULL)
continue;
awt::Rectangle aBox ((*iElement)->GetBoundingBox());
const bool bIsOver = bOverWindow
&& aBox.X <= rEvent.X
&& aBox.Width+aBox.X-1 >= rEvent.X
&& aBox.Y <= rEvent.Y
&& aBox.Height+aBox.Y-1 >= rEvent.Y;
(*iElement)->SetState(
bIsOver,
bIsOver && rEvent.Buttons!=0 && bMouseDown && rEvent.ClickCount>0);
}
}
}
void PresenterToolBar::ThrowIfDisposed (void) const
throw (::com::sun::star::lang::DisposedException)
{
if (rBHelper.bDisposed || rBHelper.bInDispose)
{
throw lang::DisposedException (
OUString(RTL_CONSTASCII_USTRINGPARAM(
"PresenterToolBar has already been disposed")),
const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
}
}
//===== PresenterToolBarView ==================================================
PresenterToolBarView::PresenterToolBarView (
const Reference<XComponentContext>& rxContext,
const Reference<XResourceId>& rxViewId,
const Reference<frame::XController>& rxController,
const ::rtl::Reference<PresenterController>& rpPresenterController)
: PresenterToolBarViewInterfaceBase(m_aMutex),
mxPane(),
mxViewId(rxViewId),
mxWindow(),
mxCanvas(),
mpPresenterController(rpPresenterController),
mxSlideShowController(rpPresenterController->GetSlideShowController()),
mpToolBar()
{
try
{
Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW);
Reference<XConfigurationController> xCC(xCM->getConfigurationController(),UNO_QUERY_THROW);
mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);
mxWindow = mxPane->getWindow();
mxCanvas = mxPane->getCanvas();
mpToolBar = new PresenterToolBar(
rxContext,
mxWindow,
mxCanvas,
rpPresenterController,
PresenterToolBar::Center);
mpToolBar->Initialize(A2S("PresenterScreenSettings/ToolBars/ToolBar"));
if (mxWindow.is())
{
mxWindow->addPaintListener(this);
Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
if (xPeer.is())
xPeer->setBackground(util::Color(0xff000000));
mxWindow->setVisible(sal_True);
}
}
catch (RuntimeException&)
{
mxViewId = NULL;
throw;
}
}
PresenterToolBarView::~PresenterToolBarView (void)
{
}
void SAL_CALL PresenterToolBarView::disposing (void)
{
Reference<lang::XComponent> xComponent (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
mpToolBar = NULL;
if (xComponent.is())
xComponent->dispose();
if (mxWindow.is())
{
mxWindow->removePaintListener(this);
mxWindow = NULL;
}
mxCanvas = NULL;
mxViewId = NULL;
mxPane = NULL;
mpPresenterController = NULL;
mxSlideShowController = NULL;
}
::rtl::Reference<PresenterToolBar> PresenterToolBarView::GetPresenterToolBar (void) const
{
return mpToolBar;
}
//----- XPaintListener --------------------------------------------------------
void SAL_CALL PresenterToolBarView::windowPaint (const css::awt::PaintEvent& rEvent)
throw (RuntimeException)
{
awt::Rectangle aWindowBox (mxWindow->getPosSize());
mpPresenterController->GetCanvasHelper()->Paint(
mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
mxCanvas,
rEvent.UpdateRect,
awt::Rectangle(0,0,aWindowBox.Width, aWindowBox.Height),
awt::Rectangle());
}
//----- lang::XEventListener -------------------------------------------------
void SAL_CALL PresenterToolBarView::disposing (const lang::EventObject& rEventObject)
throw (RuntimeException)
{
if (rEventObject.Source == mxWindow)
mxWindow = NULL;
}
//----- XResourceId -----------------------------------------------------------
Reference<XResourceId> SAL_CALL PresenterToolBarView::getResourceId (void)
throw (RuntimeException)
{
return mxViewId;
}
sal_Bool SAL_CALL PresenterToolBarView::isAnchorOnly (void)
throw (RuntimeException)
{
return false;
}
//----- XDrawView -------------------------------------------------------------
void SAL_CALL PresenterToolBarView::setCurrentPage (const Reference<drawing::XDrawPage>& rxSlide)
throw (RuntimeException)
{
Reference<drawing::XDrawView> xToolBar (static_cast<XWeak*>(mpToolBar.get()), UNO_QUERY);
if (xToolBar.is())
xToolBar->setCurrentPage(rxSlide);
}
Reference<drawing::XDrawPage> SAL_CALL PresenterToolBarView::getCurrentPage (void)
throw (RuntimeException)
{
return NULL;
}
//-----------------------------------------------------------------------------
void PresenterToolBarView::ThrowIfDisposed (void) const
throw (::com::sun::star::lang::DisposedException)
{
if (rBHelper.bDisposed || rBHelper.bInDispose)
{
throw lang::DisposedException (
OUString(RTL_CONSTASCII_USTRINGPARAM(
"PresenterToolBarView has already been disposed")),
const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
}
}
//===== PresenterToolBar::Element =============================================
namespace {
Element::Element (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: ElementInterfaceBase(m_aMutex),
mpToolBar(rpToolBar),
maLocation(),
maSize(),
mpNormal(),
mpMouseOver(),
mpSelected(),
mpDisabled(),
mpMode(),
mbIsOver(false),
mbIsPressed(false),
mbIsSelected(false),
mbIsEnabled(true)
{
if (mpToolBar.get() != NULL)
{
OSL_ASSERT(mpToolBar->GetPresenterController().is());
OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
}
}
Element::~Element (void)
{
}
void Element::SetModes (
const SharedElementMode& rpNormalMode,
const SharedElementMode& rpMouseOverMode,
const SharedElementMode& rpSelectedMode,
const SharedElementMode& rpDisabledMode)
{
mpNormal = rpNormalMode;
mpMouseOver = rpMouseOverMode;
mpSelected = rpSelectedMode;
mpDisabled = rpDisabledMode;
mpMode = rpNormalMode;
}
void Element::disposing (void)
{
}
awt::Size Element::GetBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas)
{
maSize = CreateBoundingSize(rxCanvas);
return maSize;
}
awt::Rectangle Element::GetBoundingBox (void) const
{
return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height);
}
void Element::CurrentSlideHasChanged (void)
{
UpdateState();
}
void Element::SetLocation (const awt::Point& rLocation)
{
maLocation = rLocation;
}
void Element::SetSize (const geometry::RealSize2D& rSize)
{
maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height));
}
bool Element::SetState (
const bool bIsOver,
const bool bIsPressed)
{
bool bModified (mbIsOver != bIsOver || mbIsPressed != bIsPressed);
bool bClicked (mbIsPressed && bIsOver && ! bIsPressed);
mbIsOver = bIsOver;
mbIsPressed = bIsPressed;
// When the element is disabled then ignore mouse over or selection.
// When the element is selected then ignore mouse over.
if ( ! mbIsEnabled)
mpMode = mpDisabled;
else if (mbIsSelected)
mpMode = mpSelected;
else if (mbIsOver)
mpMode = mpMouseOver;
else
mpMode = mpNormal;
if (bClicked && mbIsEnabled)
{
if (mpMode.get() != NULL)
{
do
{
if (mpMode->msAction.getLength() <= 0)
break;
if (mpToolBar.get() == NULL)
break;
if (mpToolBar->GetPresenterController().get() == NULL)
break;
mpToolBar->GetPresenterController()->DispatchUnoCommand(mpMode->msAction);
mpToolBar->RequestLayout();
}
while (false);
}
}
else if (bModified)
{
Invalidate();
}
return bModified;
}
void Element::Invalidate (const bool bSynchronous)
{
OSL_ASSERT(mpToolBar.is());
mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous);
}
bool Element::IsOutside (const awt::Rectangle& rBox)
{
if (rBox.X >= maLocation.X+maSize.Width)
return true;
else if (rBox.Y >= maLocation.Y+maSize.Height)
return true;
else if (maLocation.X >= rBox.X+rBox.Width)
return true;
else if (maLocation.Y >= rBox.Y+rBox.Height)
return true;
else
return false;
}
bool Element::IsEnabled (void) const
{
return mbIsEnabled;
}
void Element::SetEnabledState (const bool bIsEnabled)
{
mbIsEnabled = bIsEnabled;
}
bool Element::IsFilling (void) const
{
return false;
}
void Element::UpdateState (void)
{
OSL_ASSERT(mpToolBar.get() != NULL);
OSL_ASSERT(mpToolBar->GetPresenterController().get() != NULL);
if (mpMode.get() == NULL)
return;
util::URL aURL (mpToolBar->GetPresenterController()->CreateURLFromString(mpMode->msAction));
Reference<frame::XDispatch> xDispatch (mpToolBar->GetPresenterController()->GetDispatch(aURL));
if (xDispatch.is())
{
xDispatch->addStatusListener(this, aURL);
xDispatch->removeStatusListener(this, aURL);
}
}
//----- lang::XEventListener --------------------------------------------------
void SAL_CALL Element::disposing (const css::lang::EventObject& rEvent)
throw(css::uno::RuntimeException)
{
(void)rEvent;
}
//----- document::XEventListener ----------------------------------------------
void SAL_CALL Element::notifyEvent (const css::document::EventObject& rEvent)
throw(css::uno::RuntimeException)
{
(void)rEvent;
UpdateState();
}
//----- frame::XStatusListener ------------------------------------------------
void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent)
throw(css::uno::RuntimeException)
{
bool bIsSelected (mbIsSelected);
bool bIsEnabled (rEvent.IsEnabled);
rEvent.State >>= bIsSelected;
if (bIsSelected != mbIsSelected || bIsEnabled != mbIsEnabled)
{
mbIsEnabled = bIsEnabled;
mbIsSelected = bIsSelected;
SetState(mbIsOver, mbIsPressed);
mpToolBar->RequestLayout();
}
}
} // end of anonymous namespace
//===== ElementMode ===========================================================
namespace {
ElementMode::ElementMode (void)
: mpIcon(),
msAction(),
maText()
{
}
void ElementMode::ReadElementMode (
const Reference<beans::XPropertySet>& rxElementProperties,
const OUString& rsModeName,
::boost::shared_ptr<ElementMode>& rpDefaultMode,
::sdext::presenter::PresenterToolBar::Context& rContext)
{
try
{
Reference<container::XHierarchicalNameAccess> xNode (
PresenterConfigurationAccess::GetProperty(rxElementProperties, rsModeName),
UNO_QUERY);
Reference<beans::XPropertySet> xProperties (
PresenterConfigurationAccess::GetNodeProperties(xNode, OUString()));
if ( ! xProperties.is() && rpDefaultMode.get()!=NULL)
{
// The mode is not specified. Use the given, possibly empty,
// default mode instead.
mpIcon = rpDefaultMode->mpIcon;
msAction = rpDefaultMode->msAction;
maText = rpDefaultMode->maText;
}
// Read action.
if ( ! (PresenterConfigurationAccess::GetProperty(xProperties, A2S("Action")) >>= msAction))
if (rpDefaultMode.get()!=NULL)
msAction = rpDefaultMode->msAction;
// Read text and font
OUString sText (rpDefaultMode.get()!=NULL ? rpDefaultMode->maText.GetText() : OUString());
PresenterConfigurationAccess::GetProperty(xProperties, A2S("Text")) >>= sText;
Reference<container::XHierarchicalNameAccess> xFontNode (
PresenterConfigurationAccess::GetProperty(xProperties, A2S("Font")), UNO_QUERY);
PresenterTheme::SharedFontDescriptor pFont (PresenterTheme::ReadFont(
xFontNode,
A2S(""),
rpDefaultMode.get()!=NULL
? rpDefaultMode->maText.GetFont()
: PresenterTheme::SharedFontDescriptor()));
maText = Text(sText,pFont);
// Read bitmaps to display as icons.
Reference<container::XHierarchicalNameAccess> xIconNode (
PresenterConfigurationAccess::GetProperty(xProperties, A2S("Icon")), UNO_QUERY);
mpIcon = PresenterBitmapContainer::LoadBitmap(
xIconNode,
A2S(""),
rContext.mxPresenterHelper,
rContext.mxCanvas,
rpDefaultMode.get()!=NULL ? rpDefaultMode->mpIcon : SharedBitmapDescriptor());
}
catch(Exception&)
{
OSL_ASSERT(false);
}
}
} // end of anonymous namespace
//===== Button ================================================================
namespace {
::rtl::Reference<Element> Button::Create (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
{
::rtl::Reference<Button> pElement (new Button(rpToolBar));
pElement->Initialize();
return ::rtl::Reference<Element>(pElement.get());
}
Button::Button (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: Element(rpToolBar),
mbIsListenerRegistered(false)
{
OSL_ASSERT(mpToolBar.get() != NULL);
OSL_ASSERT(mpToolBar->GetPresenterController().is());
OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
}
Button::~Button (void)
{
}
void Button::Initialize (void)
{
mpToolBar->GetPresenterController()->GetWindowManager()->AddLayoutListener(this);
mbIsListenerRegistered = true;
}
void Button::disposing (void)
{
OSL_ASSERT(mpToolBar.get() != NULL);
if (mpToolBar.get() != NULL
&& mbIsListenerRegistered)
{
OSL_ASSERT(mpToolBar->GetPresenterController().is());
OSL_ASSERT(mpToolBar->GetPresenterController()->GetWindowManager().is());
mbIsListenerRegistered = false;
mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this);
}
Element::disposing();
}
void Button::Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState)
{
OSL_ASSERT(rxCanvas.is());
if (mpMode.get() == NULL)
return;
if (mpMode->mpIcon.get() == NULL)
return;
geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
PaintIcon(rxCanvas, nTextHeight, rViewState);
awt::Point aOffset(0,0);
if ( ! IsEnabled())
if (mpMode->mpIcon.get() != NULL)
{
Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetNormalBitmap());
if (xBitmap.is())
aOffset.Y = xBitmap->getSize().Height;
}
mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), aOffset);
}
awt::Size Button::CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas)
{
if (mpMode.get() == NULL)
return awt::Size();
geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
const sal_Int32 nGap (5);
sal_Int32 nTextHeight (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
sal_Int32 nTextWidth (sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1));
Reference<rendering::XBitmap> xBitmap;
if (mpMode->mpIcon.get() != NULL)
xBitmap = mpMode->mpIcon->GetNormalBitmap();
if (xBitmap.is())
{
geometry::IntegerSize2D aSize (xBitmap->getSize());
return awt::Size(
::std::max(aSize.Width, sal_Int32(0.5 + aTextBBox.X2 - aTextBBox.X1)),
aSize.Height+ nGap + nTextHeight);
}
else
return awt::Size(nTextWidth,nTextHeight);
}
void Button::PaintIcon (
const Reference<rendering::XCanvas>& rxCanvas,
const sal_Int32 nTextHeight,
const rendering::ViewState& rViewState)
{
if (mpMode.get() == NULL)
return;
Reference<rendering::XBitmap> xBitmap (mpMode->mpIcon->GetBitmap(GetMode()));
if (xBitmap.is())
{
const sal_Int32 nX (maLocation.X
+ (maSize.Width-xBitmap->getSize().Width) / 2);
const sal_Int32 nY (maLocation.Y
+ (maSize.Height - nTextHeight - xBitmap->getSize().Height) / 2);
const rendering::RenderState aRenderState(
geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
NULL,
Sequence<double>(4),
rendering::CompositeOperation::OVER);
rxCanvas->drawBitmap(xBitmap, rViewState, aRenderState);
}
}
PresenterBitmapDescriptor::Mode Button::GetMode (void) const
{
if ( ! IsEnabled())
return PresenterBitmapDescriptor::Disabled;
else if (mbIsPressed)
return PresenterBitmapDescriptor::ButtonDown;
else if (mbIsOver)
return PresenterBitmapDescriptor::MouseOver;
else
return PresenterBitmapDescriptor::Normal;
}
//----- lang::XEventListener --------------------------------------------------
void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent)
throw(css::uno::RuntimeException)
{
(void)rEvent;
mbIsListenerRegistered = false;
Element::disposing(rEvent);
}
} // end of anonymous namespace
//===== PresenterToolBar::Label ===============================================
namespace {
Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: Element(rpToolBar)
{
}
awt::Size Label::CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas)
{
if (mpMode.get() == NULL)
return awt::Size(0,0);
geometry::RealRectangle2D aTextBBox (mpMode->maText.GetBoundingBox(rxCanvas));
return awt::Size(
sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.X2 - aTextBBox.X1),
sal::static_int_cast<sal_Int32>(0.5 + aTextBBox.Y2 - aTextBBox.Y1));
}
void Label::SetText (const OUString& rsText)
{
OSL_ASSERT(mpToolBar.get() != NULL);
if (mpMode.get() == NULL)
return;
const bool bRequestLayout (mpMode->maText.GetText().getLength() != rsText.getLength());
mpMode->maText.SetText(rsText);
// Just use the character count for determing whether a layout is
// necessary. This is an optimization to avoid layouts every time a new
// time value is set on some labels.
if (bRequestLayout)
mpToolBar->RequestLayout();
else
Invalidate(false);
}
void Label::Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState)
{
OSL_ASSERT(rxCanvas.is());
if (mpMode.get() == NULL)
return;
mpMode->maText.Paint(rxCanvas, rViewState, GetBoundingBox(), awt::Point(0,0));
}
bool Label::SetState (const bool bIsOver, const bool bIsPressed)
{
// For labels there is no mouse over effect.
(void)bIsOver;
(void)bIsPressed;
return Element::SetState(false, false);
}
} // end of anonymous namespace
//===== Text ==================================================================
namespace {
Text::Text (void)
: msText(),
mpFont()
{
}
Text::Text (const Text& rText)
: msText(rText.msText),
mpFont(rText.mpFont)
{
}
Text::Text (
const OUString& rsText,
const PresenterTheme::SharedFontDescriptor& rpFont)
: msText(rsText),
mpFont(rpFont)
{
}
void Text::SetText (const OUString& rsText)
{
msText = rsText;
}
OUString Text::GetText (void) const
{
return msText;
}
PresenterTheme::SharedFontDescriptor Text::GetFont (void) const
{
return mpFont;
}
void Text::Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState,
const awt::Rectangle& rBoundingBox,
const awt::Point& rOffset)
{
(void)rOffset;
OSL_ASSERT(rxCanvas.is());
if (msText.getLength() <= 0)
return;
if (mpFont.get() == NULL)
return;
if ( ! mpFont->mxFont.is())
mpFont->PrepareFont(rxCanvas);
if ( ! mpFont->mxFont.is())
return;
rendering::StringContext aContext (msText, 0, msText.getLength());
Reference<rendering::XTextLayout> xLayout (
mpFont->mxFont->createTextLayout(
aContext,
rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
0));
geometry::RealRectangle2D aBox (xLayout->queryTextBounds());
const double nTextWidth = aBox.X2 - aBox.X1;
const double nY = rBoundingBox.Y + rBoundingBox.Height - aBox.Y2;
const double nX = rBoundingBox.X + (rBoundingBox.Width - nTextWidth)/2;
rendering::RenderState aRenderState(
geometry::AffineMatrix2D(1,0,nX, 0,1,nY),
NULL,
Sequence<double>(4),
rendering::CompositeOperation::SOURCE);
PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);
rxCanvas->drawText(
aContext,
mpFont->mxFont,
rViewState,
aRenderState,
rendering::TextDirection::WEAK_LEFT_TO_RIGHT);
}
geometry::RealRectangle2D Text::GetBoundingBox (const Reference<rendering::XCanvas>& rxCanvas)
{
if (mpFont.get() != NULL && msText.getLength() > 0)
{
if ( ! mpFont->mxFont.is())
mpFont->PrepareFont(rxCanvas);
if (mpFont->mxFont.is())
{
rendering::StringContext aContext (msText, 0, msText.getLength());
Reference<rendering::XTextLayout> xLayout (
mpFont->mxFont->createTextLayout(
aContext,
rendering::TextDirection::WEAK_LEFT_TO_RIGHT,
0));
return xLayout->queryTextBounds();
}
}
return geometry::RealRectangle2D(0,0,0,0);
}
//===== ProgressLabel =========================================================
ProgressLabel::ProgressLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: Label(rpToolBar)
{
SetText(A2S("-/-"));
}
void ProgressLabel::CurrentSlideHasChanged (void)
{
Label::CurrentSlideHasChanged();
OSL_ASSERT(mpToolBar.is());
try
{
const sal_Int32 nCurrentSlideIndex (mpToolBar->GetCurrentSlideIndex() + 1);
const sal_Int32 nSlideCount (mpToolBar->GetSlideCount());
if (nCurrentSlideIndex >= 0 && nSlideCount > 0)
SetText(
OUString::valueOf(nCurrentSlideIndex)
+ OUString::createFromAscii(" / ")
+ OUString::valueOf(nSlideCount));
else
SetText(A2S(""));
Invalidate();
}
catch (RuntimeException&)
{
}
}
//===== TimeFormatter =========================================================
TimeFormatter::TimeFormatter (void)
: mbIs24HourFormat(true),
mbIsAmPmFormat(false),
mbIsShowSeconds(true)
{
}
OUString TimeFormatter::FormatTime (const oslDateTime& rTime)
{
::rtl::OUStringBuffer sText;
const sal_Int32 nHours (sal::static_int_cast<sal_Int32>(rTime.Hours));
const sal_Int32 nMinutes (sal::static_int_cast<sal_Int32>(rTime.Minutes));
const sal_Int32 nSeconds(sal::static_int_cast<sal_Int32>(rTime.Seconds));
// Hours
if (mbIs24HourFormat)
sText.append(OUString::valueOf(nHours));
else
sText.append(OUString::valueOf(
sal::static_int_cast<sal_Int32>(nHours>12 ? nHours-12 : nHours)));
sText.append(A2S(":"));
// Minutes
const OUString sMinutes (OUString::valueOf(nMinutes));
if (sMinutes.getLength() == 1)
sText.append(A2S("0"));
sText.append(sMinutes);
// Seconds
if (mbIsShowSeconds)
{
sText.append(A2S(":"));
const OUString sSeconds (OUString::valueOf(nSeconds));
if (sSeconds.getLength() == 1)
sText.append(A2S("0"));
sText.append(sSeconds);
}
if (mbIsAmPmFormat)
{
if (rTime.Hours < 12)
sText.append(A2S("am"));
else
sText.append(A2S("pm"));
}
return sText.makeStringAndClear();
}
//===== TimeLabel =============================================================
TimeLabel::TimeLabel (const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: Label(rpToolBar),
mpListener()
{
}
void SAL_CALL TimeLabel::disposing (void)
{
PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->RemoveListener(mpListener);
mpListener.reset();
}
void TimeLabel::ConnectToTimer (void)
{
mpListener.reset(new Listener(this));
PresenterClockTimer::Instance(mpToolBar->GetComponentContext())->AddListener(mpListener);
}
//===== CurrentTimeLabel ======================================================
::rtl::Reference<Element> CurrentTimeLabel::Create (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
{
::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar));
pElement->ConnectToTimer();
return ::rtl::Reference<Element>(pElement.get());
}
CurrentTimeLabel::~CurrentTimeLabel (void)
{
}
CurrentTimeLabel::CurrentTimeLabel (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: TimeLabel(rpToolBar),
maTimeFormatter()
{
}
void CurrentTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
{
SetText(maTimeFormatter.FormatTime(rCurrentTime));
Invalidate(false);
}
void CurrentTimeLabel::SetModes (
const SharedElementMode& rpNormalMode,
const SharedElementMode& rpMouseOverMode,
const SharedElementMode& rpSelectedMode,
const SharedElementMode& rpDisabledMode)
{
TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
SetText(maTimeFormatter.FormatTime(PresenterClockTimer::GetCurrentTime()));
}
//===== PresentationTimeLabel =================================================
::rtl::Reference<Element> PresentationTimeLabel::Create (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
{
::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar));
pElement->ConnectToTimer();
return ::rtl::Reference<Element>(pElement.get());
}
PresentationTimeLabel::~PresentationTimeLabel (void)
{
}
PresentationTimeLabel::PresentationTimeLabel (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: TimeLabel(rpToolBar),
maTimeFormatter(),
maStartTimeValue()
{
maStartTimeValue.Seconds = 0;
maStartTimeValue.Nanosec = 0;
}
void PresentationTimeLabel::TimeHasChanged (const oslDateTime& rCurrentTime)
{
TimeValue aCurrentTimeValue;
if (osl_getTimeValueFromDateTime(const_cast<oslDateTime*>(&rCurrentTime), &aCurrentTimeValue))
{
if (maStartTimeValue.Seconds==0 && maStartTimeValue.Nanosec==0)
{
// This method is called for the first time. Initialize the
// start time. The start time is rounded to nearest second to
// keep the time updates synchronized with the current time label.
maStartTimeValue = aCurrentTimeValue;
if (maStartTimeValue.Nanosec >= 500000000)
maStartTimeValue.Seconds += 1;
maStartTimeValue.Nanosec = 0;
}
TimeValue aElapsedTimeValue;
aElapsedTimeValue.Seconds = aCurrentTimeValue.Seconds - maStartTimeValue.Seconds;
aElapsedTimeValue.Nanosec = aCurrentTimeValue.Nanosec - maStartTimeValue.Nanosec;
oslDateTime aElapsedDateTime;
if (osl_getDateTimeFromTimeValue(&aElapsedTimeValue, &aElapsedDateTime))
{
SetText(maTimeFormatter.FormatTime(aElapsedDateTime));
Invalidate(false);
}
}
}
void PresentationTimeLabel::SetModes (
const SharedElementMode& rpNormalMode,
const SharedElementMode& rpMouseOverMode,
const SharedElementMode& rpSelectedMode,
const SharedElementMode& rpDisabledMode)
{
TimeLabel::SetModes(rpNormalMode, rpMouseOverMode, rpSelectedMode, rpDisabledMode);
oslDateTime aStartDateTime;
if (osl_getDateTimeFromTimeValue(&maStartTimeValue, &aStartDateTime))
{
SetText(maTimeFormatter.FormatTime(aStartDateTime));
}
}
//===== VerticalSeparator =====================================================
VerticalSeparator::VerticalSeparator (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: Element(rpToolBar)
{
}
void VerticalSeparator::Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState)
{
OSL_ASSERT(rxCanvas.is());
awt::Rectangle aBBox (GetBoundingBox());
rendering::RenderState aRenderState(
geometry::AffineMatrix2D(1,0,0, 0,1,0),
NULL,
Sequence<double>(4),
rendering::CompositeOperation::OVER);
if (mpMode.get() != NULL)
{
PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
if (pFont.get() != NULL)
PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
}
if (aBBox.Height >= gnMinimalSeparatorSize + 2*gnSeparatorInset)
{
aBBox.Height -= 2*gnSeparatorInset;
aBBox.Y += gnSeparatorInset;
}
rxCanvas->fillPolyPolygon(
PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
rViewState,
aRenderState);
}
awt::Size VerticalSeparator::CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas)
{
(void)rxCanvas;
return awt::Size(1,20);
}
bool VerticalSeparator::IsFilling (void) const
{
return true;
}
//===== HorizontalSeparator ===================================================
HorizontalSeparator::HorizontalSeparator (
const ::rtl::Reference<PresenterToolBar>& rpToolBar)
: Element(rpToolBar)
{
}
void HorizontalSeparator::Paint (
const Reference<rendering::XCanvas>& rxCanvas,
const rendering::ViewState& rViewState)
{
OSL_ASSERT(rxCanvas.is());
awt::Rectangle aBBox (GetBoundingBox());
rendering::RenderState aRenderState(
geometry::AffineMatrix2D(1,0,0, 0,1,0),
NULL,
Sequence<double>(4),
rendering::CompositeOperation::OVER);
if (mpMode.get() != NULL)
{
PresenterTheme::SharedFontDescriptor pFont (mpMode->maText.GetFont());
if (pFont.get() != NULL)
PresenterCanvasHelper::SetDeviceColor(aRenderState, pFont->mnColor);
}
if (aBBox.Width >= gnMinimalSeparatorSize+2*gnSeparatorInset)
{
aBBox.Width -= 2*gnSeparatorInset;
aBBox.X += gnSeparatorInset;
}
rxCanvas->fillPolyPolygon(
PresenterGeometryHelper::CreatePolygon(aBBox, rxCanvas->getDevice()),
rViewState,
aRenderState);
}
awt::Size HorizontalSeparator::CreateBoundingSize (
const Reference<rendering::XCanvas>& rxCanvas)
{
(void)rxCanvas;
return awt::Size(20,1);
}
bool HorizontalSeparator::IsFilling (void) const
{
return true;
}
} // end of anonymous namespace
} } // end of namespace ::sdext::presenter