1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_forms.hxx" 30 #include "richtextimplcontrol.hxx" 31 #include "textattributelistener.hxx" 32 #include "richtextengine.hxx" 33 #include <editeng/editeng.hxx> 34 #include <editeng/editview.hxx> 35 #include <editeng/eeitem.hxx> 36 #include <editeng/editstat.hxx> 37 #ifndef _SVX_SVXIDS_HRC 38 #include <svx/svxids.hrc> 39 #endif 40 #include <editeng/scripttypeitem.hxx> 41 42 #include <editeng/editobj.hxx> 43 #include <svl/itempool.hxx> 44 #include <svl/itemset.hxx> 45 #include <tools/mapunit.hxx> 46 #include <vcl/window.hxx> 47 #include <vcl/svapp.hxx> 48 49 #include <memory> 50 51 #define EMPTY_PAPER_SIZE 0x7FFFFFFF 52 53 //........................................................................ 54 namespace frm 55 { 56 //........................................................................ 57 //==================================================================== 58 //= RichTextControlImpl 59 //==================================================================== 60 //-------------------------------------------------------------------- 61 RichTextControlImpl::RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener ) 62 :m_pAntiImpl ( _pAntiImpl ) 63 ,m_pViewport ( NULL ) 64 ,m_pHScroll ( NULL ) 65 ,m_pVScroll ( NULL ) 66 ,m_pScrollCorner ( NULL ) 67 ,m_pEngine ( _pEngine ) 68 ,m_pView ( NULL ) 69 ,m_pTextAttrListener ( _pTextAttrListener ) 70 ,m_pSelectionListener ( _pSelectionListener ) 71 ,m_bHasEverBeenShown ( false ) 72 { 73 OSL_ENSURE( m_pAntiImpl, "RichTextControlImpl::RichTextControlImpl: invalid window!" ); 74 OSL_ENSURE( m_pEngine, "RichTextControlImpl::RichTextControlImpl: invalid edit engine! This will *definately* crash!" ); 75 76 m_pViewport = new RichTextViewPort( m_pAntiImpl ); 77 m_pViewport->setAttributeInvalidationHandler( LINK( this, RichTextControlImpl, OnInvalidateAllAttributes ) ); 78 m_pViewport->Show(); 79 80 // ensure that both the window and the reference device have the same map unit 81 MapMode aRefDeviceMapMode( m_pEngine->GetRefDevice()->GetMapMode() ); 82 m_pAntiImpl->SetMapMode( aRefDeviceMapMode ); 83 m_pViewport->SetMapMode( aRefDeviceMapMode ); 84 85 m_pView = new EditView( m_pEngine, m_pViewport ); 86 m_pEngine->InsertView( m_pView ); 87 m_pViewport->setView( *m_pView ); 88 89 m_pEngine->registerEngineStatusListener( this ); 90 91 { 92 sal_uLong nViewControlWord = m_pView->GetControlWord(); 93 nViewControlWord |= EV_CNTRL_AUTOSCROLL; 94 m_pView->SetControlWord( nViewControlWord ); 95 } 96 97 // ensure that it's initially scrolled to the upper left 98 m_pView->SetVisArea( Rectangle( Point( ), m_pViewport->GetOutputSize() ) ); 99 100 ensureScrollbars(); 101 102 m_pAntiImpl->SetBackground( Wallpaper( m_pAntiImpl->GetSettings().GetStyleSettings().GetFieldColor() ) ); 103 } 104 105 //-------------------------------------------------------------------- 106 RichTextControlImpl::~RichTextControlImpl( ) 107 { 108 m_pEngine->RemoveView( m_pView ); 109 m_pEngine->revokeEngineStatusListener( this ); 110 delete m_pView; 111 delete m_pViewport; 112 delete m_pHScroll; 113 delete m_pVScroll; 114 delete m_pScrollCorner; 115 } 116 117 //-------------------------------------------------------------------- 118 void RichTextControlImpl::implUpdateAttribute( AttributeHandlerPool::const_iterator _pHandler ) 119 { 120 if ( ( _pHandler->first == SID_ATTR_CHAR_WEIGHT ) 121 || ( _pHandler->first == SID_ATTR_CHAR_POSTURE ) 122 || ( _pHandler->first == SID_ATTR_CHAR_FONT ) 123 || ( _pHandler->first == SID_ATTR_CHAR_FONTHEIGHT ) 124 ) 125 { 126 // these are attributes whose value depends on the current script type. 127 // I.e., in real, there are *three* items in the ItemSet: One for each script 128 // type (Latin, Asian, Complex). However, if we have an observer who is interested 129 // in the state of this attribute, we have to kind of *merge* the three attributes 130 // to only one. 131 // This is usefull in case the observer is for instance a toolbox which contains only 132 // an, e.g., "bold" slot, and thus not interested in the particular script type of the 133 // current selection. 134 SvxScriptSetItem aNormalizedSet( (WhichId)_pHandler->first, *m_pView->GetAttribs().GetPool() ); 135 normalizeScriptDependentAttribute( aNormalizedSet ); 136 137 implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( aNormalizedSet.GetItemSet() ) ); 138 } 139 else 140 implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( m_pView->GetAttribs() ) ); 141 } 142 143 //-------------------------------------------------------------------- 144 void RichTextControlImpl::updateAttribute( AttributeId _nAttribute ) 145 { 146 AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.find( _nAttribute ); 147 if ( pHandler != m_aAttributeHandlers.end() ) 148 implUpdateAttribute( pHandler ); 149 } 150 151 //-------------------------------------------------------------------- 152 void RichTextControlImpl::updateAllAttributes( ) 153 { 154 for ( AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.begin(); 155 pHandler != m_aAttributeHandlers.end(); 156 ++pHandler 157 ) 158 { 159 implUpdateAttribute( pHandler ); 160 } 161 162 // notify changes of the selection, if necessary 163 if ( m_pSelectionListener && m_pView ) 164 { 165 ESelection aCurrentSelection = m_pView->GetSelection(); 166 if ( !aCurrentSelection.IsEqual( m_aLastKnownSelection ) ) 167 { 168 m_aLastKnownSelection = aCurrentSelection; 169 m_pSelectionListener->onSelectionChanged( m_aLastKnownSelection ); 170 } 171 } 172 } 173 174 //-------------------------------------------------------------------- 175 AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const 176 { 177 StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId ); 178 if ( aCachedStatePos == m_aLastKnownStates.end() ) 179 { 180 OSL_ENSURE( sal_False, "RichTextControlImpl::getAttributeState: Don't ask for the state of an attribute which I never encountered!" ); 181 return AttributeState( eIndetermined ); 182 } 183 return aCachedStatePos->second; 184 } 185 186 //-------------------------------------------------------------------- 187 bool RichTextControlImpl::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, ScriptType _nForScriptType ) 188 { 189 // let's see whether we have a handler for this attribute 190 AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttribute ); 191 if ( aHandlerPos != m_aAttributeHandlers.end() ) 192 { 193 aHandlerPos->second->executeAttribute( _rCurrentAttribs, _rAttribs, _pArgument, _nForScriptType ); 194 return true; 195 } 196 return false; 197 } 198 199 //-------------------------------------------------------------------- 200 void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener ) 201 { 202 AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId ); 203 if ( aHandlerPos == m_aAttributeHandlers.end() ) 204 { 205 ::rtl::Reference< IAttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() ); 206 OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" ); 207 if ( !aHandler.is() ) 208 return; 209 OSL_POSTCOND( _nAttributeId == aHandler->getAttributeId(), "RichTextControlImpl::enableAttributeNotification: suspicious handler!" ); 210 211 aHandlerPos = m_aAttributeHandlers.insert( AttributeHandlerPool::value_type( _nAttributeId , aHandler ) ).first; 212 } 213 214 // remember the listener 215 if ( _pListener ) 216 m_aAttributeListeners.insert( AttributeListenerPool::value_type( _nAttributeId, _pListener ) ); 217 218 // update (and broadcast) the state of this attribute 219 updateAttribute( _nAttributeId ); 220 } 221 222 //-------------------------------------------------------------------- 223 void RichTextControlImpl::disableAttributeNotification( AttributeId _nAttributeId ) 224 { 225 // forget the handler for this attribute 226 AttributeHandlerPool::iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId ); 227 if ( aHandlerPos != m_aAttributeHandlers.end() ) 228 m_aAttributeHandlers.erase( aHandlerPos ); 229 230 // as well as the listener 231 AttributeListenerPool::iterator aListenerPos = m_aAttributeListeners.find( _nAttributeId ); 232 if ( aListenerPos != m_aAttributeListeners.end() ) 233 m_aAttributeListeners.erase( aListenerPos ); 234 } 235 236 //-------------------------------------------------------------------- 237 void RichTextControlImpl::normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem ) 238 { 239 _rScriptSetItem.GetItemSet().Put( m_pView->GetAttribs(), sal_False ); 240 const SfxPoolItem* pNormalizedItem = _rScriptSetItem.GetItemOfScript( getSelectedScriptType() ); 241 242 WhichId nNormalizedWhichId = _rScriptSetItem.GetItemSet().GetPool()->GetWhich( _rScriptSetItem.Which() ); 243 if ( pNormalizedItem ) 244 { 245 SfxPoolItem* pProperWhich = pNormalizedItem->Clone(); 246 pProperWhich->SetWhich( nNormalizedWhichId ); 247 _rScriptSetItem.GetItemSet().Put( *pProperWhich ); 248 DELETEZ( pProperWhich ); 249 } 250 else 251 _rScriptSetItem.GetItemSet().InvalidateItem( nNormalizedWhichId ); 252 } 253 254 //-------------------------------------------------------------------- 255 void RichTextControlImpl::implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState ) 256 { 257 StateCache::iterator aCachePos = m_aLastKnownStates.find( _nAttribute ); 258 if ( aCachePos == m_aLastKnownStates.end() ) 259 { // nothing known about this attribute, yet 260 m_aLastKnownStates.insert( StateCache::value_type( _nAttribute, _rState ) ); 261 } 262 else 263 { 264 if ( aCachePos->second == _rState ) 265 { 266 // nothing to do 267 return; 268 } 269 aCachePos->second = _rState; 270 } 271 272 // is there a dedicated listener for this particular attribute? 273 AttributeListenerPool::const_iterator aListenerPos = m_aAttributeListeners.find( _nAttribute ); 274 if ( aListenerPos != m_aAttributeListeners.end( ) ) 275 aListenerPos->second->onAttributeStateChanged( _nAttribute, _rState ); 276 277 // call our global listener, if there is one 278 if ( m_pTextAttrListener ) 279 m_pTextAttrListener->onAttributeStateChanged( _nAttribute, _rState ); 280 } 281 282 //-------------------------------------------------------------------- 283 ScriptType RichTextControlImpl::getSelectedScriptType() const 284 { 285 ScriptType nScript = m_pView->GetSelectedScriptType(); 286 if ( !nScript ) 287 nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() ); 288 return nScript; 289 } 290 291 //-------------------------------------------------------------------- 292 void RichTextControlImpl::EditEngineStatusChanged( const EditStatus& _rStatus ) 293 { 294 sal_uLong nStatusWord( _rStatus.GetStatusWord() ); 295 if ( ( nStatusWord & EE_STAT_TEXTWIDTHCHANGED ) 296 || ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) 297 ) 298 { 299 if ( ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) && windowHasAutomaticLineBreak() ) 300 m_pEngine->SetPaperSize( Size( m_pEngine->GetPaperSize().Width(), m_pEngine->GetTextHeight() ) ); 301 302 updateScrollbars(); 303 } 304 305 bool bHScroll = 0 != ( nStatusWord & EE_STAT_HSCROLL ); 306 bool bVScroll = 0 != ( nStatusWord & EE_STAT_VSCROLL ); 307 308 // In case of *no* automatic line breaks, we also need to check for the *range* here. 309 // Normally, we would do this only after a EE_STAT_TEXTWIDTHCHANGED. However, due to a bug 310 // in the EditEngine (I believe so) this is not fired when the engine does not have 311 // the AutoPaperSize bits set. 312 // So in order to be properly notified, we would need the AutoPaperSize. But, with 313 // AutoPaperSize, other things do not work anymore: Either, when we set a MaxAutoPaperSize, 314 // then the view does automatic soft line breaks at the paper end - which we definately do 315 // want. Or, if we did not set a MaxAutoPaperSize, then the view does not automatically scroll 316 // anymore in horizontal direction. 317 // So this is some kind of lose-lose situation ... :( 318 if ( !windowHasAutomaticLineBreak() && bHScroll ) 319 { 320 updateScrollbars(); 321 return; 322 } 323 324 if ( bHScroll && m_pHScroll ) 325 m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() ); 326 if ( bVScroll && m_pVScroll ) 327 m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() ); 328 } 329 330 //-------------------------------------------------------------------- 331 IMPL_LINK( RichTextControlImpl, OnInvalidateAllAttributes, void*, /*_pNotInterestedIn*/ ) 332 { 333 updateAllAttributes(); 334 return 0L; 335 } 336 337 //-------------------------------------------------------------------- 338 IMPL_LINK( RichTextControlImpl, OnHScroll, ScrollBar*, _pScrollbar ) 339 { 340 m_pView->Scroll( -_pScrollbar->GetDelta(), 0, RGCHK_PAPERSZ1 ); 341 return 0L; 342 } 343 344 //-------------------------------------------------------------------- 345 IMPL_LINK( RichTextControlImpl, OnVScroll, ScrollBar*, _pScrollbar ) 346 { 347 m_pView->Scroll( 0, -_pScrollbar->GetDelta(), RGCHK_PAPERSZ1 ); 348 return 0L; 349 } 350 351 //-------------------------------------------------------------------- 352 void RichTextControlImpl::ensureScrollbars() 353 { 354 bool bNeedVScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_VSCROLL ); 355 bool bNeedHScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_HSCROLL ); 356 357 if ( ( bNeedVScroll == hasVScrollBar() ) && ( bNeedHScroll == hasHScrollBar( ) ) ) 358 // nothing to do 359 return; 360 361 // create or delete the scrollbars, as necessary 362 if ( !bNeedVScroll ) 363 { 364 delete m_pVScroll; 365 m_pVScroll = NULL; 366 } 367 else 368 { 369 m_pVScroll = new ScrollBar( m_pAntiImpl, WB_VSCROLL | WB_DRAG | WB_REPEAT ); 370 m_pVScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnVScroll ) ); 371 m_pVScroll->Show(); 372 } 373 374 if ( !bNeedHScroll ) 375 { 376 delete m_pHScroll; 377 m_pHScroll = NULL; 378 } 379 else 380 { 381 m_pHScroll = new ScrollBar( m_pAntiImpl, WB_HSCROLL | WB_DRAG | WB_REPEAT ); 382 m_pHScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnHScroll ) ); 383 m_pHScroll->Show(); 384 } 385 386 if ( m_pHScroll && m_pVScroll ) 387 { 388 delete m_pScrollCorner; 389 m_pScrollCorner = new ScrollBarBox( m_pAntiImpl ); 390 m_pScrollCorner->Show(); 391 } 392 else 393 { 394 delete m_pScrollCorner; 395 m_pScrollCorner = NULL; 396 } 397 398 layoutWindow(); 399 } 400 401 //-------------------------------------------------------------------- 402 void RichTextControlImpl::ensureLineBreakSetting() 403 { 404 if ( !windowHasAutomaticLineBreak() ) 405 m_pEngine->SetPaperSize( Size( EMPTY_PAPER_SIZE, EMPTY_PAPER_SIZE ) ); 406 407 layoutWindow(); 408 } 409 410 //-------------------------------------------------------------------- 411 void RichTextControlImpl::layoutWindow() 412 { 413 if ( !m_bHasEverBeenShown ) 414 // no need to do anything. Especially, no need to set the paper size on the 415 // EditEngine to anything .... 416 return; 417 418 const StyleSettings& rStyleSettings = m_pAntiImpl->GetSettings().GetStyleSettings(); 419 420 long nScrollBarWidth = m_pVScroll ? rStyleSettings.GetScrollBarSize() : 0; 421 long nScrollBarHeight = m_pHScroll ? rStyleSettings.GetScrollBarSize() : 0; 422 423 if ( m_pAntiImpl->IsZoom() ) 424 { 425 nScrollBarWidth = m_pAntiImpl->CalcZoom( nScrollBarWidth ); 426 nScrollBarHeight = m_pAntiImpl->CalcZoom( nScrollBarHeight ); 427 } 428 429 // the overall size we can use 430 Size aPlaygroundSizePixel( m_pAntiImpl->GetOutputSizePixel() ); 431 432 // the size of the viewport - note that the viewport does *not* occupy all the place 433 // which is left when subtracting the scrollbar width/height 434 Size aViewportPlaygroundPixel( aPlaygroundSizePixel ); 435 aViewportPlaygroundPixel.Width() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) ); 436 aViewportPlaygroundPixel.Height() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) ); 437 Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) ); 438 439 const long nOffset = 2; 440 Size aViewportSizePixel( aViewportPlaygroundPixel.Width() - 2 * nOffset, aViewportPlaygroundPixel.Height() - 2 * nOffset ); 441 Size aViewportSizeLogic( m_pViewport->PixelToLogic( aViewportSizePixel ) ); 442 443 // position the viewport 444 m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel ); 445 // position the scrollbars 446 if ( m_pVScroll ) 447 m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) ); 448 if ( m_pHScroll ) 449 m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) ); 450 if ( m_pScrollCorner ) 451 m_pScrollCorner->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), aViewportPlaygroundPixel.Height() ), Size( nScrollBarWidth, nScrollBarHeight ) ); 452 453 // paper size 454 if ( windowHasAutomaticLineBreak() ) 455 m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) ); 456 457 // output area of the view 458 m_pView->SetOutputArea( Rectangle( Point( ), aViewportSizeLogic ) ); 459 m_pView->SetVisArea( Rectangle( Point( ), aViewportSizeLogic ) ); 460 461 if ( m_pVScroll ) 462 { 463 m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() ); 464 465 // the default height of a text line .... 466 long nFontHeight = m_pEngine->GetStandardFont(0).GetSize().Height(); 467 // ... is the scroll size for the vertical scrollbar 468 m_pVScroll->SetLineSize( nFontHeight ); 469 // the viewport width, minus one line, is the page scroll size 470 m_pVScroll->SetPageSize( ::std::max( nFontHeight, aViewportPlaygroundLogic.Height() - nFontHeight ) ); 471 } 472 473 // the font width 474 if ( m_pHScroll ) 475 { 476 m_pHScroll->SetVisibleSize( aViewportPlaygroundLogic.Width() ); 477 478 long nFontWidth = m_pEngine->GetStandardFont(0).GetSize().Width(); 479 if ( !nFontWidth ) 480 { 481 m_pViewport->Push( PUSH_FONT ); 482 m_pViewport->SetFont( m_pEngine->GetStandardFont(0) ); 483 nFontWidth = m_pViewport->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM( "x" ) ) ); 484 m_pViewport->Pop(); 485 } 486 // ... is the scroll size for the horizontal scrollbar 487 m_pHScroll->SetLineSize( 5 * nFontWidth ); 488 // the viewport height, minus one character, is the page scroll size 489 m_pHScroll->SetPageSize( ::std::max( nFontWidth, aViewportPlaygroundLogic.Width() - nFontWidth ) ); 490 } 491 492 // update range and position of the scrollbars 493 updateScrollbars(); 494 } 495 496 //-------------------------------------------------------------------- 497 void RichTextControlImpl::updateScrollbars() 498 { 499 if ( m_pVScroll ) 500 { 501 long nOverallTextHeight = m_pEngine->GetTextHeight(); 502 m_pVScroll->SetRange( Range( 0, nOverallTextHeight ) ); 503 m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() ); 504 } 505 506 if ( m_pHScroll ) 507 { 508 Size aPaperSize( m_pEngine->GetPaperSize() ); 509 long nOverallTextWidth = ( aPaperSize.Width() == EMPTY_PAPER_SIZE ) ? m_pEngine->CalcTextWidth() : aPaperSize.Width(); 510 m_pHScroll->SetRange( Range( 0, nOverallTextWidth ) ); 511 m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() ); 512 } 513 } 514 515 //-------------------------------------------------------------------- 516 void RichTextControlImpl::notifyInitShow() 517 { 518 if ( !m_bHasEverBeenShown ) 519 { 520 m_bHasEverBeenShown = true; 521 layoutWindow(); 522 } 523 } 524 525 //-------------------------------------------------------------------- 526 void RichTextControlImpl::notifyStyleChanged() 527 { 528 ensureScrollbars(); 529 ensureLineBreakSetting(); 530 } 531 532 //-------------------------------------------------------------------- 533 void RichTextControlImpl::notifyZoomChanged() 534 { 535 const Fraction& rZoom = m_pAntiImpl->GetZoom(); 536 537 MapMode aMapMode( m_pAntiImpl->GetMapMode() ); 538 aMapMode.SetScaleX( rZoom ); 539 aMapMode.SetScaleY( rZoom ); 540 m_pAntiImpl->SetMapMode( aMapMode ); 541 542 m_pViewport->SetZoom( rZoom ); 543 m_pViewport->SetMapMode( aMapMode ); 544 545 layoutWindow(); 546 } 547 548 //-------------------------------------------------------------------- 549 bool RichTextControlImpl::windowHasAutomaticLineBreak() 550 { 551 return ( m_pAntiImpl->GetStyle() & WB_WORDBREAK ) != 0; 552 } 553 554 //-------------------------------------------------------------------- 555 void RichTextControlImpl::SetReadOnly( bool _bReadOnly ) 556 { 557 m_pView->SetReadOnly( _bReadOnly ); 558 } 559 560 //-------------------------------------------------------------------- 561 bool RichTextControlImpl::IsReadOnly() const 562 { 563 return m_pView->IsReadOnly( ); 564 } 565 566 //-------------------------------------------------------------------- 567 namespace 568 { 569 static void lcl_inflate( Rectangle& _rRect, long _nInflateX, long _nInflateY ) 570 { 571 _rRect.Left() -= _nInflateX; 572 _rRect.Right() += _nInflateX; 573 _rRect.Top() -= _nInflateY; 574 _rRect.Bottom() += _nInflateY; 575 } 576 } 577 //-------------------------------------------------------------------- 578 long RichTextControlImpl::HandleCommand( const CommandEvent& _rEvent ) 579 { 580 if ( ( _rEvent.GetCommand() == COMMAND_WHEEL ) 581 || ( _rEvent.GetCommand() == COMMAND_STARTAUTOSCROLL ) 582 || ( _rEvent.GetCommand() == COMMAND_AUTOSCROLL ) 583 ) 584 { 585 m_pAntiImpl->HandleScrollCommand( _rEvent, m_pHScroll, m_pVScroll ); 586 return 1; 587 } 588 return 0; 589 } 590 591 //-------------------------------------------------------------------- 592 void RichTextControlImpl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, sal_uLong /*_nFlags*/ ) 593 { 594 // need to normalize the map mode of the device - every paint operation on any device needs 595 // to use the same map mode 596 _pDev->Push( PUSH_MAPMODE | PUSH_LINECOLOR | PUSH_FILLCOLOR ); 597 598 // enforce our "normalize map mode" on the device 599 MapMode aRefMapMode( m_pEngine->GetRefDevice()->GetMapMode() ); 600 MapMode aOriginalMapMode( _pDev->GetMapMode() ); 601 MapMode aNormalizedMapMode( aRefMapMode.GetMapUnit(), aRefMapMode.GetOrigin(), aOriginalMapMode.GetScaleX(), aOriginalMapMode.GetScaleY() ); 602 _pDev->SetMapMode( aNormalizedMapMode ); 603 604 // translate coordinates 605 Point aPos( _rPos ); 606 Size aSize( _rSize ); 607 if ( aOriginalMapMode.GetMapUnit() == MAP_PIXEL ) 608 { 609 aPos = _pDev->PixelToLogic( _rPos, aNormalizedMapMode ); 610 aSize = _pDev->PixelToLogic( _rSize, aNormalizedMapMode ); 611 } 612 else 613 { 614 aPos = OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode ); 615 aSize = OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode ); 616 } 617 618 Rectangle aPlayground( aPos, aSize ); 619 Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) ); 620 aPlayground.Right() -= aOnePixel.Width(); 621 aPlayground.Bottom() -= aOnePixel.Height(); 622 623 // background 624 _pDev->SetLineColor(); 625 _pDev->DrawRect( aPlayground ); 626 627 // do we need to draw a border? 628 bool bBorder = ( m_pAntiImpl->GetStyle() & WB_BORDER ); 629 if ( bBorder ) 630 _pDev->SetLineColor( m_pAntiImpl->GetSettings().GetStyleSettings().GetMonoColor() ); 631 else 632 _pDev->SetLineColor(); 633 _pDev->SetFillColor( m_pAntiImpl->GetBackground().GetColor() ); 634 _pDev->DrawRect( aPlayground ); 635 636 if ( bBorder ) 637 // don't draw the text over the border 638 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); 639 640 // leave a space of one pixel between the "surroundings" of the control 641 // and the content 642 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); 643 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); 644 645 // actually draw the content 646 m_pEngine->Draw( _pDev, aPlayground, Point(), sal_True ); 647 648 _pDev->Pop(); 649 } 650 651 //-------------------------------------------------------------------- 652 void RichTextControlImpl::SetBackgroundColor( ) 653 { 654 SetBackgroundColor( Application::GetSettings().GetStyleSettings().GetFieldColor() ); 655 } 656 657 //-------------------------------------------------------------------- 658 void RichTextControlImpl::SetBackgroundColor( const Color& _rColor ) 659 { 660 Wallpaper aWallpaper( _rColor ); 661 m_pAntiImpl->SetBackground( aWallpaper ); 662 m_pViewport->SetBackground( aWallpaper ); 663 } 664 665 //-------------------------------------------------------------------- 666 void RichTextControlImpl::SetHideInactiveSelection( bool _bHide ) 667 { 668 m_pViewport->SetHideInactiveSelection( _bHide ); 669 } 670 671 //-------------------------------------------------------------------- 672 bool RichTextControlImpl::GetHideInactiveSelection() const 673 { 674 return m_pViewport->GetHideInactiveSelection( ); 675 } 676 677 //........................................................................ 678 } // namespace frm 679 //........................................................................ 680 681