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