1c142477cSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3c142477cSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4c142477cSAndrew Rist * or more contributor license agreements. See the NOTICE file 5c142477cSAndrew Rist * distributed with this work for additional information 6c142477cSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7c142477cSAndrew Rist * to you under the Apache License, Version 2.0 (the 8c142477cSAndrew Rist * "License"); you may not use this file except in compliance 9c142477cSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11c142477cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13c142477cSAndrew Rist * Unless required by applicable law or agreed to in writing, 14c142477cSAndrew Rist * software distributed under the License is distributed on an 15c142477cSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16c142477cSAndrew Rist * KIND, either express or implied. See the License for the 17c142477cSAndrew Rist * specific language governing permissions and limitations 18c142477cSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20c142477cSAndrew Rist *************************************************************/ 21c142477cSAndrew Rist 22c142477cSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_sdext.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "PresenterHelpView.hxx" 28cdf0e10cSrcweir #include "PresenterButton.hxx" 29cdf0e10cSrcweir #include "PresenterCanvasHelper.hxx" 30cdf0e10cSrcweir #include "PresenterGeometryHelper.hxx" 31cdf0e10cSrcweir #include "PresenterHelper.hxx" 32cdf0e10cSrcweir #include "PresenterWindowManager.hxx" 33cdf0e10cSrcweir #include <com/sun/star/awt/XWindowPeer.hpp> 34cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp> 35cdf0e10cSrcweir #include <com/sun/star/drawing/framework/XConfigurationController.hpp> 36cdf0e10cSrcweir #include <com/sun/star/drawing/framework/XControllerManager.hpp> 37cdf0e10cSrcweir #include <com/sun/star/rendering/CompositeOperation.hpp> 38cdf0e10cSrcweir #include <com/sun/star/rendering/TextDirection.hpp> 39cdf0e10cSrcweir #include <com/sun/star/util/Color.hpp> 40cdf0e10cSrcweir #include <algorithm> 41cdf0e10cSrcweir #include <vector> 42cdf0e10cSrcweir #include <boost/bind.hpp> 43cdf0e10cSrcweir 44cdf0e10cSrcweir using namespace ::com::sun::star; 45cdf0e10cSrcweir using namespace ::com::sun::star::uno; 46cdf0e10cSrcweir using namespace ::com::sun::star::drawing::framework; 47cdf0e10cSrcweir using ::rtl::OUString; 48cdf0e10cSrcweir using ::std::vector; 49cdf0e10cSrcweir 50cdf0e10cSrcweir #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) 51cdf0e10cSrcweir 52cdf0e10cSrcweir 53cdf0e10cSrcweir namespace sdext { namespace presenter { 54cdf0e10cSrcweir 55cdf0e10cSrcweir namespace { 56cdf0e10cSrcweir const static sal_Int32 gnHorizontalGap (20); 57cdf0e10cSrcweir const static sal_Int32 gnVerticalBorder (30); 58cdf0e10cSrcweir const static sal_Int32 gnVerticalButtonPadding (12); 59cdf0e10cSrcweir 60cdf0e10cSrcweir class LineDescriptor 61cdf0e10cSrcweir { 62cdf0e10cSrcweir public: 63cdf0e10cSrcweir LineDescriptor(void); 64cdf0e10cSrcweir void AddPart ( 65cdf0e10cSrcweir const OUString& rsLine, 66cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont); 67cdf0e10cSrcweir bool IsEmpty (void) const; 68cdf0e10cSrcweir 69cdf0e10cSrcweir OUString msLine; 70cdf0e10cSrcweir geometry::RealSize2D maSize; 71cdf0e10cSrcweir double mnVerticalOffset; 72cdf0e10cSrcweir 73cdf0e10cSrcweir void CalculateSize (const css::uno::Reference<css::rendering::XCanvasFont>& rxFont); 74cdf0e10cSrcweir }; 75cdf0e10cSrcweir 76cdf0e10cSrcweir class LineDescriptorList 77cdf0e10cSrcweir { 78cdf0e10cSrcweir public: 79cdf0e10cSrcweir LineDescriptorList ( 80cdf0e10cSrcweir const OUString& rsText, 81cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 82cdf0e10cSrcweir const sal_Int32 nMaximalWidth); 83cdf0e10cSrcweir 84cdf0e10cSrcweir void Update ( 85cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 86cdf0e10cSrcweir const sal_Int32 nMaximalWidth); 87cdf0e10cSrcweir 88cdf0e10cSrcweir double Paint( 89cdf0e10cSrcweir const Reference<rendering::XCanvas>& rxCanvas, 90cdf0e10cSrcweir const geometry::RealRectangle2D& rBBox, 91cdf0e10cSrcweir const bool bFlushLeft, 92cdf0e10cSrcweir const rendering::ViewState& rViewState, 93cdf0e10cSrcweir rendering::RenderState& rRenderState, 94cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const; 95cdf0e10cSrcweir double GetHeight (void) const; 96cdf0e10cSrcweir 97cdf0e10cSrcweir private: 98cdf0e10cSrcweir const OUString msText; 99cdf0e10cSrcweir ::boost::shared_ptr<vector<LineDescriptor> > mpLineDescriptors; 100cdf0e10cSrcweir 101cdf0e10cSrcweir void SplitText (const ::rtl::OUString& rsText, vector<rtl::OUString>& rTextParts); 102cdf0e10cSrcweir void FormatText ( 103cdf0e10cSrcweir const vector<rtl::OUString>& rTextParts, 104cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 105cdf0e10cSrcweir const sal_Int32 nMaximalWidth); 106cdf0e10cSrcweir }; 107cdf0e10cSrcweir 108cdf0e10cSrcweir class Block 109cdf0e10cSrcweir { 110cdf0e10cSrcweir public: 111cdf0e10cSrcweir Block (const Block& rBlock); 112cdf0e10cSrcweir Block ( 113cdf0e10cSrcweir const OUString& rsLeftText, 114cdf0e10cSrcweir const OUString& rsRightText, 115cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 116cdf0e10cSrcweir const sal_Int32 nMaximalWidth); 117cdf0e10cSrcweir void Update ( 118cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 119cdf0e10cSrcweir const sal_Int32 nMaximalWidth); 120cdf0e10cSrcweir 121cdf0e10cSrcweir LineDescriptorList maLeft; 122cdf0e10cSrcweir LineDescriptorList maRight; 123cdf0e10cSrcweir }; 124cdf0e10cSrcweir } // end of anonymous namespace 125cdf0e10cSrcweir 126cdf0e10cSrcweir class PresenterHelpView::TextContainer : public vector<boost::shared_ptr<Block> > 127cdf0e10cSrcweir { 128cdf0e10cSrcweir }; 129cdf0e10cSrcweir 130cdf0e10cSrcweir 131cdf0e10cSrcweir PresenterHelpView::PresenterHelpView ( 132cdf0e10cSrcweir const Reference<uno::XComponentContext>& rxContext, 133cdf0e10cSrcweir const Reference<XResourceId>& rxViewId, 134cdf0e10cSrcweir const Reference<frame::XController>& rxController, 135cdf0e10cSrcweir const ::rtl::Reference<PresenterController>& rpPresenterController) 136cdf0e10cSrcweir : PresenterHelpViewInterfaceBase(m_aMutex), 137cdf0e10cSrcweir mxComponentContext(rxContext), 138cdf0e10cSrcweir mxViewId(rxViewId), 139cdf0e10cSrcweir mxPane(), 140cdf0e10cSrcweir mxWindow(), 141cdf0e10cSrcweir mxCanvas(), 142cdf0e10cSrcweir mpPresenterController(rpPresenterController), 143cdf0e10cSrcweir mpFont(), 144cdf0e10cSrcweir mpTextContainer(), 145cdf0e10cSrcweir mpCloseButton(), 146cdf0e10cSrcweir mnSeparatorY(0), 147cdf0e10cSrcweir mnMaximalWidth(0) 148cdf0e10cSrcweir { 149cdf0e10cSrcweir try 150cdf0e10cSrcweir { 151cdf0e10cSrcweir // Get the content window via the pane anchor. 152cdf0e10cSrcweir Reference<XControllerManager> xCM (rxController, UNO_QUERY_THROW); 153cdf0e10cSrcweir Reference<XConfigurationController> xCC ( 154cdf0e10cSrcweir xCM->getConfigurationController(), UNO_QUERY_THROW); 155cdf0e10cSrcweir mxPane = Reference<XPane>(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW); 156cdf0e10cSrcweir 157cdf0e10cSrcweir mxWindow = mxPane->getWindow(); 158cdf0e10cSrcweir ProvideCanvas(); 159cdf0e10cSrcweir 160cdf0e10cSrcweir mxWindow->addWindowListener(this); 161cdf0e10cSrcweir mxWindow->addPaintListener(this); 162cdf0e10cSrcweir Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY); 163cdf0e10cSrcweir if (xPeer.is()) 164cdf0e10cSrcweir xPeer->setBackground(util::Color(0xff000000)); 165cdf0e10cSrcweir mxWindow->setVisible(sal_True); 166cdf0e10cSrcweir 167cdf0e10cSrcweir if (mpPresenterController.is()) 168cdf0e10cSrcweir { 169cdf0e10cSrcweir mpFont = mpPresenterController->GetViewFont(mxViewId->getResourceURL()); 170cdf0e10cSrcweir if (mpFont.get() != NULL) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir mpFont->PrepareFont(mxCanvas); 173cdf0e10cSrcweir } 174cdf0e10cSrcweir } 175cdf0e10cSrcweir 176cdf0e10cSrcweir // Create the close button. 177cdf0e10cSrcweir mpCloseButton = PresenterButton::Create( 178cdf0e10cSrcweir mxComponentContext, 179cdf0e10cSrcweir mpPresenterController, 180cdf0e10cSrcweir mpPresenterController->GetTheme(), 181cdf0e10cSrcweir mxWindow, 182cdf0e10cSrcweir mxCanvas, 183cdf0e10cSrcweir A2S("HelpViewCloser")); 184cdf0e10cSrcweir 185cdf0e10cSrcweir ReadHelpStrings(); 186cdf0e10cSrcweir Resize(); 187cdf0e10cSrcweir } 188cdf0e10cSrcweir catch (RuntimeException&) 189cdf0e10cSrcweir { 190cdf0e10cSrcweir mxViewId = NULL; 191cdf0e10cSrcweir mxWindow = NULL; 192cdf0e10cSrcweir throw; 193cdf0e10cSrcweir } 194cdf0e10cSrcweir } 195cdf0e10cSrcweir 196cdf0e10cSrcweir 197cdf0e10cSrcweir 198cdf0e10cSrcweir 199cdf0e10cSrcweir PresenterHelpView::~PresenterHelpView (void) 200cdf0e10cSrcweir { 201cdf0e10cSrcweir } 202cdf0e10cSrcweir 203cdf0e10cSrcweir 204cdf0e10cSrcweir 205cdf0e10cSrcweir 206cdf0e10cSrcweir void SAL_CALL PresenterHelpView::disposing (void) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir mxViewId = NULL; 209cdf0e10cSrcweir 210cdf0e10cSrcweir if (mpCloseButton.is()) 211cdf0e10cSrcweir { 212cdf0e10cSrcweir Reference<lang::XComponent> xComponent ( 213cdf0e10cSrcweir static_cast<XWeak*>(mpCloseButton.get()), UNO_QUERY); 214cdf0e10cSrcweir mpCloseButton = NULL; 215cdf0e10cSrcweir if (xComponent.is()) 216cdf0e10cSrcweir xComponent->dispose(); 217cdf0e10cSrcweir } 218cdf0e10cSrcweir 219cdf0e10cSrcweir if (mxWindow.is()) 220cdf0e10cSrcweir { 221cdf0e10cSrcweir mxWindow->removeWindowListener(this); 222cdf0e10cSrcweir mxWindow->removePaintListener(this); 223cdf0e10cSrcweir } 224cdf0e10cSrcweir } 225cdf0e10cSrcweir 226cdf0e10cSrcweir 227cdf0e10cSrcweir 228cdf0e10cSrcweir 229cdf0e10cSrcweir //----- lang::XEventListener -------------------------------------------------- 230cdf0e10cSrcweir 231cdf0e10cSrcweir void SAL_CALL PresenterHelpView::disposing (const lang::EventObject& rEventObject) 232cdf0e10cSrcweir throw (RuntimeException) 233cdf0e10cSrcweir { 234cdf0e10cSrcweir if (rEventObject.Source == mxCanvas) 235cdf0e10cSrcweir { 236cdf0e10cSrcweir mxCanvas = NULL; 237cdf0e10cSrcweir } 238cdf0e10cSrcweir else if (rEventObject.Source == mxWindow) 239cdf0e10cSrcweir { 240cdf0e10cSrcweir mxWindow = NULL; 241cdf0e10cSrcweir dispose(); 242cdf0e10cSrcweir } 243cdf0e10cSrcweir } 244cdf0e10cSrcweir 245cdf0e10cSrcweir 246cdf0e10cSrcweir 247cdf0e10cSrcweir 248cdf0e10cSrcweir //----- XWindowListener ------------------------------------------------------- 249cdf0e10cSrcweir 250cdf0e10cSrcweir void SAL_CALL PresenterHelpView::windowResized (const awt::WindowEvent& rEvent) 251cdf0e10cSrcweir throw (uno::RuntimeException) 252cdf0e10cSrcweir { 253cdf0e10cSrcweir (void)rEvent; 254cdf0e10cSrcweir ThrowIfDisposed(); 255cdf0e10cSrcweir Resize(); 256cdf0e10cSrcweir } 257cdf0e10cSrcweir 258cdf0e10cSrcweir 259cdf0e10cSrcweir 260cdf0e10cSrcweir 261cdf0e10cSrcweir void SAL_CALL PresenterHelpView::windowMoved (const awt::WindowEvent& rEvent) 262cdf0e10cSrcweir throw (uno::RuntimeException) 263cdf0e10cSrcweir { 264cdf0e10cSrcweir (void)rEvent; 265cdf0e10cSrcweir ThrowIfDisposed(); 266cdf0e10cSrcweir } 267cdf0e10cSrcweir 268cdf0e10cSrcweir 269cdf0e10cSrcweir 270cdf0e10cSrcweir 271cdf0e10cSrcweir void SAL_CALL PresenterHelpView::windowShown (const lang::EventObject& rEvent) 272cdf0e10cSrcweir throw (uno::RuntimeException) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir (void)rEvent; 275cdf0e10cSrcweir ThrowIfDisposed(); 276cdf0e10cSrcweir Resize(); 277cdf0e10cSrcweir } 278cdf0e10cSrcweir 279cdf0e10cSrcweir 280cdf0e10cSrcweir 281cdf0e10cSrcweir 282cdf0e10cSrcweir void SAL_CALL PresenterHelpView::windowHidden (const lang::EventObject& rEvent) 283cdf0e10cSrcweir throw (uno::RuntimeException) 284cdf0e10cSrcweir { 285cdf0e10cSrcweir (void)rEvent; 286cdf0e10cSrcweir ThrowIfDisposed(); 287cdf0e10cSrcweir } 288cdf0e10cSrcweir 289cdf0e10cSrcweir 290cdf0e10cSrcweir 291cdf0e10cSrcweir 292cdf0e10cSrcweir //----- XPaintListener -------------------------------------------------------- 293cdf0e10cSrcweir 294cdf0e10cSrcweir void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent) 295cdf0e10cSrcweir throw (RuntimeException) 296cdf0e10cSrcweir { 297cdf0e10cSrcweir Paint(rEvent.UpdateRect); 298cdf0e10cSrcweir } 299cdf0e10cSrcweir 300cdf0e10cSrcweir 301cdf0e10cSrcweir 302cdf0e10cSrcweir 303cdf0e10cSrcweir void PresenterHelpView::Paint (const awt::Rectangle& rUpdateBox) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir ProvideCanvas(); 306cdf0e10cSrcweir if ( ! mxCanvas.is()) 307cdf0e10cSrcweir return; 308cdf0e10cSrcweir 309cdf0e10cSrcweir // Clear background. 310cdf0e10cSrcweir const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 311cdf0e10cSrcweir mpPresenterController->GetCanvasHelper()->Paint( 312cdf0e10cSrcweir mpPresenterController->GetViewBackground(mxViewId->getResourceURL()), 313cdf0e10cSrcweir Reference<rendering::XCanvas>(mxCanvas, UNO_QUERY), 314cdf0e10cSrcweir rUpdateBox, 315cdf0e10cSrcweir awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height), 316cdf0e10cSrcweir awt::Rectangle()); 317cdf0e10cSrcweir 318cdf0e10cSrcweir // Paint vertical divider. 319cdf0e10cSrcweir 320cdf0e10cSrcweir rendering::ViewState aViewState( 321cdf0e10cSrcweir geometry::AffineMatrix2D(1,0,0, 0,1,0), 322cdf0e10cSrcweir PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice())); 323cdf0e10cSrcweir 324cdf0e10cSrcweir rendering::RenderState aRenderState ( 325cdf0e10cSrcweir geometry::AffineMatrix2D(1,0,0, 0,1,0), 326cdf0e10cSrcweir NULL, 327cdf0e10cSrcweir Sequence<double>(4), 328cdf0e10cSrcweir rendering::CompositeOperation::SOURCE); 329cdf0e10cSrcweir PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor); 330cdf0e10cSrcweir 331cdf0e10cSrcweir mxCanvas->drawLine( 332cdf0e10cSrcweir geometry::RealPoint2D(aWindowBox.Width/2, gnVerticalBorder), 333cdf0e10cSrcweir geometry::RealPoint2D(aWindowBox.Width/2, mnSeparatorY - gnVerticalBorder), 334cdf0e10cSrcweir aViewState, 335cdf0e10cSrcweir aRenderState); 336cdf0e10cSrcweir 337cdf0e10cSrcweir // Paint the horizontal separator. 338cdf0e10cSrcweir mxCanvas->drawLine( 339cdf0e10cSrcweir geometry::RealPoint2D(0, mnSeparatorY), 340cdf0e10cSrcweir geometry::RealPoint2D(aWindowBox.Width, mnSeparatorY), 341cdf0e10cSrcweir aViewState, 342cdf0e10cSrcweir aRenderState); 343cdf0e10cSrcweir 344cdf0e10cSrcweir // Paint text. 345cdf0e10cSrcweir double nY (gnVerticalBorder); 346cdf0e10cSrcweir TextContainer::const_iterator iBlock (mpTextContainer->begin()); 347cdf0e10cSrcweir TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); 348cdf0e10cSrcweir for ( ; iBlock!=iBlockEnd; ++iBlock) 349cdf0e10cSrcweir { 350cdf0e10cSrcweir const double nLeftHeight ( 351cdf0e10cSrcweir (*iBlock)->maLeft.Paint(mxCanvas, 352cdf0e10cSrcweir geometry::RealRectangle2D( 353cdf0e10cSrcweir gnHorizontalGap, 354cdf0e10cSrcweir nY, 355cdf0e10cSrcweir aWindowBox.Width/2 - gnHorizontalGap, 356cdf0e10cSrcweir aWindowBox.Height - gnVerticalBorder), 357cdf0e10cSrcweir false, 358cdf0e10cSrcweir aViewState, 359cdf0e10cSrcweir aRenderState, 360cdf0e10cSrcweir mpFont->mxFont)); 361cdf0e10cSrcweir const double nRightHeight ( 362cdf0e10cSrcweir (*iBlock)->maRight.Paint(mxCanvas, 363cdf0e10cSrcweir geometry::RealRectangle2D( 364cdf0e10cSrcweir aWindowBox.Width/2 + gnHorizontalGap, 365cdf0e10cSrcweir nY, 366cdf0e10cSrcweir aWindowBox.Width - gnHorizontalGap, 367cdf0e10cSrcweir aWindowBox.Height - gnVerticalBorder), 368cdf0e10cSrcweir true, 369cdf0e10cSrcweir aViewState, 370cdf0e10cSrcweir aRenderState, 371cdf0e10cSrcweir mpFont->mxFont)); 372cdf0e10cSrcweir nY += ::std::max(nLeftHeight,nRightHeight); 373cdf0e10cSrcweir } 374cdf0e10cSrcweir 375cdf0e10cSrcweir Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY); 376cdf0e10cSrcweir if (xSpriteCanvas.is()) 377cdf0e10cSrcweir xSpriteCanvas->updateScreen(sal_False); 378cdf0e10cSrcweir } 379cdf0e10cSrcweir 380cdf0e10cSrcweir 381cdf0e10cSrcweir 382cdf0e10cSrcweir 383cdf0e10cSrcweir void PresenterHelpView::ReadHelpStrings (void) 384cdf0e10cSrcweir { 385cdf0e10cSrcweir mpTextContainer.reset(new TextContainer()); 386cdf0e10cSrcweir PresenterConfigurationAccess aConfiguration ( 387cdf0e10cSrcweir mxComponentContext, 388*79e0a548SAriel Constenla-Haile OUString::createFromAscii("/org.openoffice.Office.PresenterScreen/"), 389cdf0e10cSrcweir PresenterConfigurationAccess::READ_ONLY); 390cdf0e10cSrcweir Reference<container::XNameAccess> xStrings ( 391cdf0e10cSrcweir aConfiguration.GetConfigurationNode(A2S("PresenterScreenSettings/HelpView/HelpStrings")), 392cdf0e10cSrcweir UNO_QUERY); 393cdf0e10cSrcweir PresenterConfigurationAccess::ForAll( 394cdf0e10cSrcweir xStrings, 395cdf0e10cSrcweir ::boost::bind(&PresenterHelpView::ProcessString, this, _2)); 396cdf0e10cSrcweir } 397cdf0e10cSrcweir 398cdf0e10cSrcweir 399cdf0e10cSrcweir 400cdf0e10cSrcweir 401cdf0e10cSrcweir void PresenterHelpView::ProcessString ( 402cdf0e10cSrcweir const Reference<beans::XPropertySet>& rsProperties) 403cdf0e10cSrcweir { 404cdf0e10cSrcweir if ( ! rsProperties.is()) 405cdf0e10cSrcweir return; 406cdf0e10cSrcweir 407cdf0e10cSrcweir OUString sLeftText; 408cdf0e10cSrcweir PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Left")) >>= sLeftText; 409cdf0e10cSrcweir OUString sRightText; 410cdf0e10cSrcweir PresenterConfigurationAccess::GetProperty(rsProperties, A2S("Right")) >>= sRightText; 411cdf0e10cSrcweir 412cdf0e10cSrcweir const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 413cdf0e10cSrcweir mpTextContainer->push_back( 414cdf0e10cSrcweir ::boost::shared_ptr<Block>( 415cdf0e10cSrcweir new Block(sLeftText, sRightText, mpFont->mxFont, mnMaximalWidth))); 416cdf0e10cSrcweir } 417cdf0e10cSrcweir 418cdf0e10cSrcweir 419cdf0e10cSrcweir 420cdf0e10cSrcweir 421cdf0e10cSrcweir void PresenterHelpView::CheckFontSize (void) 422cdf0e10cSrcweir { 423cdf0e10cSrcweir if (mpFont.get() == NULL) 424cdf0e10cSrcweir return; 425cdf0e10cSrcweir 426cdf0e10cSrcweir const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 427cdf0e10cSrcweir if (aWindowBox.Width<=0 || aWindowBox.Height<=0) 428cdf0e10cSrcweir return; 429cdf0e10cSrcweir 430cdf0e10cSrcweir sal_Int32 nBestSize (6); 431cdf0e10cSrcweir 432cdf0e10cSrcweir // Scaling down and then reformatting can cause the text to be too large 433cdf0e10cSrcweir // still. So do this again and again until the text size is 434cdf0e10cSrcweir // small enough. Restrict the number of loops. 435cdf0e10cSrcweir for (int nLoopCount=0; nLoopCount<5; ++nLoopCount) 436cdf0e10cSrcweir { 437cdf0e10cSrcweir double nY (gnVerticalBorder); 438cdf0e10cSrcweir TextContainer::iterator iBlock (mpTextContainer->begin()); 439cdf0e10cSrcweir TextContainer::const_iterator iBlockEnd (mpTextContainer->end()); 440cdf0e10cSrcweir for ( ; iBlock!=iBlockEnd; ++iBlock) 441cdf0e10cSrcweir nY += ::std::max( 442cdf0e10cSrcweir (*iBlock)->maLeft.GetHeight(), 443cdf0e10cSrcweir (*iBlock)->maRight.GetHeight()); 444cdf0e10cSrcweir 445cdf0e10cSrcweir const double nHeightDifference (nY - (aWindowBox.Height-gnVerticalBorder)); 446cdf0e10cSrcweir if (nHeightDifference <= 0 && nHeightDifference > -50) 447cdf0e10cSrcweir { 448cdf0e10cSrcweir // We have found a good font size that is large and leaves not 449cdf0e10cSrcweir // too much space below the help text. 450cdf0e10cSrcweir return; 451cdf0e10cSrcweir } 452cdf0e10cSrcweir 453cdf0e10cSrcweir // Font is too large. Make it smaller. 454cdf0e10cSrcweir 455cdf0e10cSrcweir // Use a simple linear transformation to calculate initial guess of 456cdf0e10cSrcweir // a size that lets all help text be shown inside the window. 457cdf0e10cSrcweir const double nScale (double(aWindowBox.Height-gnVerticalBorder) / nY); 458cdf0e10cSrcweir if (nScale > 0.95 && nScale <1.05) 459cdf0e10cSrcweir break; 460cdf0e10cSrcweir 461cdf0e10cSrcweir sal_Int32 nFontSizeGuess (::std::max(sal_Int32(1),sal_Int32(mpFont->mnSize * nScale))); 462cdf0e10cSrcweir if (nHeightDifference<0 && mpFont->mnSize>nBestSize) 463cdf0e10cSrcweir nBestSize = mpFont->mnSize; 464cdf0e10cSrcweir mpFont->mnSize = nFontSizeGuess; 465cdf0e10cSrcweir mpFont->mxFont = NULL; 466cdf0e10cSrcweir mpFont->PrepareFont(mxCanvas); 467cdf0e10cSrcweir 468cdf0e10cSrcweir // Reformat blocks. 469cdf0e10cSrcweir for (iBlock=mpTextContainer->begin(); iBlock!=iBlockEnd; ++iBlock) 470cdf0e10cSrcweir (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); 471cdf0e10cSrcweir } 472cdf0e10cSrcweir 473cdf0e10cSrcweir if (nBestSize != mpFont->mnSize) 474cdf0e10cSrcweir { 475cdf0e10cSrcweir mpFont->mnSize = nBestSize; 476cdf0e10cSrcweir mpFont->mxFont = NULL; 477cdf0e10cSrcweir mpFont->PrepareFont(mxCanvas); 478cdf0e10cSrcweir 479cdf0e10cSrcweir // Reformat blocks. 480cdf0e10cSrcweir for (TextContainer::iterator 481cdf0e10cSrcweir iBlock (mpTextContainer->begin()), 482cdf0e10cSrcweir iEnd (mpTextContainer->end()); 483cdf0e10cSrcweir iBlock!=iEnd; 484cdf0e10cSrcweir ++iBlock) 485cdf0e10cSrcweir { 486cdf0e10cSrcweir (*iBlock)->Update(mpFont->mxFont, mnMaximalWidth); 487cdf0e10cSrcweir } 488cdf0e10cSrcweir } 489cdf0e10cSrcweir } 490cdf0e10cSrcweir 491cdf0e10cSrcweir 492cdf0e10cSrcweir 493cdf0e10cSrcweir 494cdf0e10cSrcweir //----- XResourceId ----------------------------------------------------------- 495cdf0e10cSrcweir 496cdf0e10cSrcweir Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId (void) 497cdf0e10cSrcweir throw (RuntimeException) 498cdf0e10cSrcweir { 499cdf0e10cSrcweir ThrowIfDisposed(); 500cdf0e10cSrcweir return mxViewId; 501cdf0e10cSrcweir } 502cdf0e10cSrcweir 503cdf0e10cSrcweir 504cdf0e10cSrcweir 505cdf0e10cSrcweir 506cdf0e10cSrcweir sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly (void) 507cdf0e10cSrcweir throw (RuntimeException) 508cdf0e10cSrcweir { 509cdf0e10cSrcweir return false; 510cdf0e10cSrcweir } 511cdf0e10cSrcweir 512cdf0e10cSrcweir 513cdf0e10cSrcweir 514cdf0e10cSrcweir 515cdf0e10cSrcweir //----------------------------------------------------------------------------- 516cdf0e10cSrcweir 517cdf0e10cSrcweir void PresenterHelpView::ProvideCanvas (void) 518cdf0e10cSrcweir { 519cdf0e10cSrcweir if ( ! mxCanvas.is() && mxPane.is()) 520cdf0e10cSrcweir { 521cdf0e10cSrcweir mxCanvas = mxPane->getCanvas(); 522cdf0e10cSrcweir if ( ! mxCanvas.is()) 523cdf0e10cSrcweir return; 524cdf0e10cSrcweir Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY); 525cdf0e10cSrcweir if (xComponent.is()) 526cdf0e10cSrcweir xComponent->addEventListener(static_cast<awt::XPaintListener*>(this)); 527cdf0e10cSrcweir 528cdf0e10cSrcweir if (mpCloseButton.is()) 529cdf0e10cSrcweir mpCloseButton->SetCanvas(mxCanvas, mxWindow); 530cdf0e10cSrcweir } 531cdf0e10cSrcweir } 532cdf0e10cSrcweir 533cdf0e10cSrcweir 534cdf0e10cSrcweir 535cdf0e10cSrcweir 536cdf0e10cSrcweir void PresenterHelpView::Resize (void) 537cdf0e10cSrcweir { 538cdf0e10cSrcweir if (mpCloseButton.get() != NULL && mxWindow.is()) 539cdf0e10cSrcweir { 540cdf0e10cSrcweir const awt::Rectangle aWindowBox (mxWindow->getPosSize()); 541cdf0e10cSrcweir mnMaximalWidth = (mxWindow->getPosSize().Width - 4*gnHorizontalGap) / 2; 542cdf0e10cSrcweir 543cdf0e10cSrcweir // Place vertical separator. 544cdf0e10cSrcweir mnSeparatorY = aWindowBox.Height 545cdf0e10cSrcweir - mpCloseButton->GetSize().Height - gnVerticalButtonPadding; 546cdf0e10cSrcweir 547cdf0e10cSrcweir mpCloseButton->SetCenter(geometry::RealPoint2D( 548cdf0e10cSrcweir aWindowBox.Width/2, 549cdf0e10cSrcweir aWindowBox.Height - mpCloseButton->GetSize().Height/2)); 550cdf0e10cSrcweir 551cdf0e10cSrcweir CheckFontSize(); 552cdf0e10cSrcweir } 553cdf0e10cSrcweir } 554cdf0e10cSrcweir 555cdf0e10cSrcweir 556cdf0e10cSrcweir 557cdf0e10cSrcweir 558cdf0e10cSrcweir void PresenterHelpView::ThrowIfDisposed (void) 559cdf0e10cSrcweir throw (lang::DisposedException) 560cdf0e10cSrcweir { 561cdf0e10cSrcweir if (rBHelper.bDisposed || rBHelper.bInDispose) 562cdf0e10cSrcweir { 563cdf0e10cSrcweir throw lang::DisposedException ( 564cdf0e10cSrcweir OUString(RTL_CONSTASCII_USTRINGPARAM( 565cdf0e10cSrcweir "PresenterHelpView has been already disposed")), 566cdf0e10cSrcweir const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); 567cdf0e10cSrcweir } 568cdf0e10cSrcweir } 569cdf0e10cSrcweir 570cdf0e10cSrcweir 571cdf0e10cSrcweir 572cdf0e10cSrcweir 573cdf0e10cSrcweir //===== LineDescritor ========================================================= 574cdf0e10cSrcweir 575cdf0e10cSrcweir namespace { 576cdf0e10cSrcweir 577cdf0e10cSrcweir LineDescriptor::LineDescriptor (void) 578cdf0e10cSrcweir : msLine(), 579cdf0e10cSrcweir maSize(0,0), 580cdf0e10cSrcweir mnVerticalOffset(0) 581cdf0e10cSrcweir { 582cdf0e10cSrcweir } 583cdf0e10cSrcweir 584cdf0e10cSrcweir 585cdf0e10cSrcweir 586cdf0e10cSrcweir 587cdf0e10cSrcweir void LineDescriptor::AddPart ( 588cdf0e10cSrcweir const OUString& rsLine, 589cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) 590cdf0e10cSrcweir { 591cdf0e10cSrcweir msLine += rsLine; 592cdf0e10cSrcweir 593cdf0e10cSrcweir CalculateSize(rxFont); 594cdf0e10cSrcweir } 595cdf0e10cSrcweir 596cdf0e10cSrcweir 597cdf0e10cSrcweir 598cdf0e10cSrcweir 599cdf0e10cSrcweir bool LineDescriptor::IsEmpty (void) const 600cdf0e10cSrcweir { 601cdf0e10cSrcweir return msLine.getLength()==0; 602cdf0e10cSrcweir } 603cdf0e10cSrcweir 604cdf0e10cSrcweir 605cdf0e10cSrcweir 606cdf0e10cSrcweir 607cdf0e10cSrcweir void LineDescriptor::CalculateSize ( 608cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) 609cdf0e10cSrcweir { 610cdf0e10cSrcweir OSL_ASSERT(rxFont.is()); 611cdf0e10cSrcweir 612cdf0e10cSrcweir rendering::StringContext aContext (msLine, 0, msLine.getLength()); 613cdf0e10cSrcweir Reference<rendering::XTextLayout> xLayout ( 614cdf0e10cSrcweir rxFont->createTextLayout(aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0)); 615cdf0e10cSrcweir const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds()); 616cdf0e10cSrcweir maSize = css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); 617cdf0e10cSrcweir mnVerticalOffset = aTextBBox.Y2; 618cdf0e10cSrcweir } 619cdf0e10cSrcweir 620cdf0e10cSrcweir } // end of anonymous namespace 621cdf0e10cSrcweir 622cdf0e10cSrcweir 623cdf0e10cSrcweir 624cdf0e10cSrcweir 625cdf0e10cSrcweir //===== LineDescriptorList ==================================================== 626cdf0e10cSrcweir 627cdf0e10cSrcweir namespace { 628cdf0e10cSrcweir 629cdf0e10cSrcweir LineDescriptorList::LineDescriptorList ( 630cdf0e10cSrcweir const OUString& rsText, 631cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 632cdf0e10cSrcweir const sal_Int32 nMaximalWidth) 633cdf0e10cSrcweir : msText(rsText) 634cdf0e10cSrcweir { 635cdf0e10cSrcweir Update(rxFont, nMaximalWidth); 636cdf0e10cSrcweir } 637cdf0e10cSrcweir 638cdf0e10cSrcweir 639cdf0e10cSrcweir 640cdf0e10cSrcweir 641cdf0e10cSrcweir double LineDescriptorList::Paint( 642cdf0e10cSrcweir const Reference<rendering::XCanvas>& rxCanvas, 643cdf0e10cSrcweir const geometry::RealRectangle2D& rBBox, 644cdf0e10cSrcweir const bool bFlushLeft, 645cdf0e10cSrcweir const rendering::ViewState& rViewState, 646cdf0e10cSrcweir rendering::RenderState& rRenderState, 647cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const 648cdf0e10cSrcweir { 649cdf0e10cSrcweir if ( ! rxCanvas.is()) 650cdf0e10cSrcweir return 0; 651cdf0e10cSrcweir 652cdf0e10cSrcweir double nY (rBBox.Y1); 653cdf0e10cSrcweir vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); 654cdf0e10cSrcweir vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); 655cdf0e10cSrcweir for ( ; iLine!=iEnd; ++iLine) 656cdf0e10cSrcweir { 657cdf0e10cSrcweir double nX (rBBox.X1); 658cdf0e10cSrcweir if ( ! bFlushLeft) 659cdf0e10cSrcweir nX = rBBox.X2 - iLine->maSize.Width; 660cdf0e10cSrcweir rRenderState.AffineTransform.m02 = nX; 661cdf0e10cSrcweir rRenderState.AffineTransform.m12 = nY + iLine->maSize.Height - iLine->mnVerticalOffset; 662cdf0e10cSrcweir 663cdf0e10cSrcweir const rendering::StringContext aContext (iLine->msLine, 0, iLine->msLine.getLength()); 664cdf0e10cSrcweir 665cdf0e10cSrcweir rxCanvas->drawText ( 666cdf0e10cSrcweir aContext, 667cdf0e10cSrcweir rxFont, 668cdf0e10cSrcweir rViewState, 669cdf0e10cSrcweir rRenderState, 670cdf0e10cSrcweir rendering::TextDirection::WEAK_LEFT_TO_RIGHT); 671cdf0e10cSrcweir 672cdf0e10cSrcweir nY += iLine->maSize.Height * 1.2; 673cdf0e10cSrcweir } 674cdf0e10cSrcweir 675cdf0e10cSrcweir return nY - rBBox.Y1; 676cdf0e10cSrcweir } 677cdf0e10cSrcweir 678cdf0e10cSrcweir 679cdf0e10cSrcweir 680cdf0e10cSrcweir 681cdf0e10cSrcweir double LineDescriptorList::GetHeight (void) const 682cdf0e10cSrcweir { 683cdf0e10cSrcweir double nHeight (0); 684cdf0e10cSrcweir vector<LineDescriptor>::const_iterator iLine (mpLineDescriptors->begin()); 685cdf0e10cSrcweir vector<LineDescriptor>::const_iterator iEnd (mpLineDescriptors->end()); 686cdf0e10cSrcweir for ( ; iLine!=iEnd; ++iLine) 687cdf0e10cSrcweir nHeight += iLine->maSize.Height * 1.2; 688cdf0e10cSrcweir 689cdf0e10cSrcweir return nHeight; 690cdf0e10cSrcweir } 691cdf0e10cSrcweir 692cdf0e10cSrcweir 693cdf0e10cSrcweir 694cdf0e10cSrcweir 695cdf0e10cSrcweir void LineDescriptorList::Update ( 696cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 697cdf0e10cSrcweir const sal_Int32 nMaximalWidth) 698cdf0e10cSrcweir { 699cdf0e10cSrcweir vector<OUString> aTextParts; 700cdf0e10cSrcweir SplitText(msText, aTextParts); 701cdf0e10cSrcweir FormatText(aTextParts, rxFont, nMaximalWidth); 702cdf0e10cSrcweir } 703cdf0e10cSrcweir 704cdf0e10cSrcweir 705cdf0e10cSrcweir 706cdf0e10cSrcweir 707cdf0e10cSrcweir void LineDescriptorList::SplitText ( 708cdf0e10cSrcweir const OUString& rsText, 709cdf0e10cSrcweir vector<OUString>& rTextParts) 710cdf0e10cSrcweir { 711cdf0e10cSrcweir const sal_Char cQuote ('\''); 712cdf0e10cSrcweir const sal_Char cSeparator (','); 713cdf0e10cSrcweir 714cdf0e10cSrcweir sal_Int32 nIndex (0); 715cdf0e10cSrcweir sal_Int32 nStart (0); 716cdf0e10cSrcweir sal_Int32 nLength (rsText.getLength()); 717cdf0e10cSrcweir bool bIsQuoted (false); 718cdf0e10cSrcweir while (nIndex < nLength) 719cdf0e10cSrcweir { 720cdf0e10cSrcweir const sal_Int32 nQuoteIndex (rsText.indexOf(cQuote, nIndex)); 721cdf0e10cSrcweir const sal_Int32 nSeparatorIndex (rsText.indexOf(cSeparator, nIndex)); 722cdf0e10cSrcweir if (nQuoteIndex>=0 && (nSeparatorIndex==-1 || nQuoteIndex<nSeparatorIndex)) 723cdf0e10cSrcweir { 724cdf0e10cSrcweir bIsQuoted = !bIsQuoted; 725cdf0e10cSrcweir nIndex = nQuoteIndex+1; 726cdf0e10cSrcweir continue; 727cdf0e10cSrcweir } 728cdf0e10cSrcweir 729cdf0e10cSrcweir const sal_Int32 nNextIndex = nSeparatorIndex; 730cdf0e10cSrcweir if (nNextIndex < 0) 731cdf0e10cSrcweir { 732cdf0e10cSrcweir break; 733cdf0e10cSrcweir } 734cdf0e10cSrcweir else if ( ! bIsQuoted) 735cdf0e10cSrcweir { 736cdf0e10cSrcweir rTextParts.push_back(rsText.copy(nStart, nNextIndex-nStart)); 737cdf0e10cSrcweir nStart = nNextIndex + 1; 738cdf0e10cSrcweir } 739cdf0e10cSrcweir nIndex = nNextIndex+1; 740cdf0e10cSrcweir } 741cdf0e10cSrcweir if (nStart < nLength) 742cdf0e10cSrcweir rTextParts.push_back(rsText.copy(nStart, nLength-nStart)); 743cdf0e10cSrcweir } 744cdf0e10cSrcweir 745cdf0e10cSrcweir 746cdf0e10cSrcweir 747cdf0e10cSrcweir 748cdf0e10cSrcweir void LineDescriptorList::FormatText ( 749cdf0e10cSrcweir const vector<OUString>& rTextParts, 750cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 751cdf0e10cSrcweir const sal_Int32 nMaximalWidth) 752cdf0e10cSrcweir { 753cdf0e10cSrcweir LineDescriptor aLineDescriptor; 754cdf0e10cSrcweir 755cdf0e10cSrcweir mpLineDescriptors.reset(new vector<LineDescriptor>()); 756cdf0e10cSrcweir 757cdf0e10cSrcweir vector<OUString>::const_iterator iPart (rTextParts.begin()); 758cdf0e10cSrcweir vector<OUString>::const_iterator iEnd (rTextParts.end()); 759cdf0e10cSrcweir for ( ; iPart!=iEnd; ++iPart) 760cdf0e10cSrcweir { 761cdf0e10cSrcweir if (aLineDescriptor.IsEmpty()) 762cdf0e10cSrcweir { 763cdf0e10cSrcweir // Avoid empty lines. 764cdf0e10cSrcweir aLineDescriptor.AddPart(*iPart, rxFont); 765cdf0e10cSrcweir } 766cdf0e10cSrcweir else if (PresenterCanvasHelper::GetTextSize( 767cdf0e10cSrcweir rxFont, aLineDescriptor.msLine+A2S(", ")+*iPart).Width > nMaximalWidth) 768cdf0e10cSrcweir { 769cdf0e10cSrcweir aLineDescriptor.AddPart(A2S(","), rxFont); 770cdf0e10cSrcweir mpLineDescriptors->push_back(aLineDescriptor); 771cdf0e10cSrcweir aLineDescriptor = LineDescriptor(); 772cdf0e10cSrcweir aLineDescriptor.AddPart(*iPart, rxFont); 773cdf0e10cSrcweir } 774cdf0e10cSrcweir else 775cdf0e10cSrcweir { 776cdf0e10cSrcweir aLineDescriptor.AddPart(A2S(", ")+*iPart, rxFont); 777cdf0e10cSrcweir } 778cdf0e10cSrcweir } 779cdf0e10cSrcweir if ( ! aLineDescriptor.IsEmpty()) 780cdf0e10cSrcweir { 781cdf0e10cSrcweir mpLineDescriptors->push_back(aLineDescriptor); 782cdf0e10cSrcweir } 783cdf0e10cSrcweir } 784cdf0e10cSrcweir 785cdf0e10cSrcweir 786cdf0e10cSrcweir } // end of anonymous namespace 787cdf0e10cSrcweir 788cdf0e10cSrcweir 789cdf0e10cSrcweir 790cdf0e10cSrcweir 791cdf0e10cSrcweir //===== Block ================================================================= 792cdf0e10cSrcweir 793cdf0e10cSrcweir namespace { 794cdf0e10cSrcweir 795cdf0e10cSrcweir Block::Block ( 796cdf0e10cSrcweir const OUString& rsLeftText, 797cdf0e10cSrcweir const OUString& rsRightText, 798cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 799cdf0e10cSrcweir const sal_Int32 nMaximalWidth) 800cdf0e10cSrcweir : maLeft(rsLeftText, rxFont, nMaximalWidth), 801cdf0e10cSrcweir maRight(rsRightText, rxFont, nMaximalWidth) 802cdf0e10cSrcweir { 803cdf0e10cSrcweir } 804cdf0e10cSrcweir 805cdf0e10cSrcweir 806cdf0e10cSrcweir 807cdf0e10cSrcweir void Block::Update ( 808cdf0e10cSrcweir const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, 809cdf0e10cSrcweir const sal_Int32 nMaximalWidth) 810cdf0e10cSrcweir { 811cdf0e10cSrcweir maLeft.Update(rxFont, nMaximalWidth); 812cdf0e10cSrcweir maRight.Update(rxFont, nMaximalWidth); 813cdf0e10cSrcweir } 814cdf0e10cSrcweir 815cdf0e10cSrcweir } // end of anonymous namespace 816cdf0e10cSrcweir 817cdf0e10cSrcweir } } // end of namespace ::sdext::presenter 818cdf0e10cSrcweir 819cdf0e10cSrcweir 820