Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / forms / source / richtext / richtextimplcontrol.cxx
blob708b13c935eda39d63ff9c4e2f719486d4e99746
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "richtextimplcontrol.hxx"
21 #include "textattributelistener.hxx"
22 #include "richtextengine.hxx"
23 #include <editeng/editeng.hxx>
24 #include <editeng/editview.hxx>
25 #include <editeng/eeitem.hxx>
26 #include <editeng/editstat.hxx>
27 #include <svx/svxids.hrc>
28 #include <editeng/scripttypeitem.hxx>
30 #include <editeng/editobj.hxx>
31 #include <svl/itempool.hxx>
32 #include <svl/itemset.hxx>
33 #include <tools/mapunit.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/settings.hxx>
38 #define EMPTY_PAPER_SIZE 0x7FFFFFFF
41 namespace frm
44 RichTextControlImpl::RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener )
45 :m_pAntiImpl ( _pAntiImpl )
46 ,m_pViewport ( nullptr )
47 ,m_pHScroll ( nullptr )
48 ,m_pVScroll ( nullptr )
49 ,m_pScrollCorner ( nullptr )
50 ,m_pEngine ( _pEngine )
51 ,m_pView ( nullptr )
52 ,m_pTextAttrListener ( _pTextAttrListener )
53 ,m_pSelectionListener ( _pSelectionListener )
54 ,m_bHasEverBeenShown ( false )
56 OSL_ENSURE( m_pAntiImpl, "RichTextControlImpl::RichTextControlImpl: invalid window!" );
57 OSL_ENSURE( m_pEngine, "RichTextControlImpl::RichTextControlImpl: invalid edit engine! This will *definitely* crash!" );
59 m_pViewport = VclPtr<RichTextViewPort>::Create( m_pAntiImpl );
60 m_pViewport->setAttributeInvalidationHandler( LINK( this, RichTextControlImpl, OnInvalidateAllAttributes ) );
61 m_pViewport->Show();
63 // ensure that both the window and the reference device have the same map unit
64 MapMode aRefDeviceMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
65 m_pAntiImpl->SetMapMode( aRefDeviceMapMode );
66 m_pViewport->SetMapMode( aRefDeviceMapMode );
68 m_pView = new EditView( m_pEngine, m_pViewport );
69 m_pEngine->InsertView( m_pView );
70 m_pViewport->setView( *m_pView );
72 m_pEngine->registerEngineStatusListener( this );
75 EVControlBits nViewControlWord = m_pView->GetControlWord();
76 nViewControlWord |= EVControlBits::AUTOSCROLL;
77 m_pView->SetControlWord( nViewControlWord );
80 // ensure that it's initially scrolled to the upper left
81 m_pView->SetVisArea( Rectangle( Point( ), m_pViewport->GetOutputSize() ) );
83 ensureScrollbars();
85 m_pAntiImpl->SetBackground( Wallpaper( m_pAntiImpl->GetSettings().GetStyleSettings().GetFieldColor() ) );
89 RichTextControlImpl::~RichTextControlImpl( )
91 m_pEngine->RemoveView( m_pView );
92 m_pEngine->revokeEngineStatusListener( this );
93 delete m_pView;
94 m_pViewport.disposeAndClear();
95 m_pHScroll.disposeAndClear();
96 m_pVScroll.disposeAndClear();
97 m_pScrollCorner.disposeAndClear();
101 void RichTextControlImpl::implUpdateAttribute( const AttributeHandlerPool::const_iterator& _pHandler )
103 if ( ( _pHandler->first == SID_ATTR_CHAR_WEIGHT )
104 || ( _pHandler->first == SID_ATTR_CHAR_POSTURE )
105 || ( _pHandler->first == SID_ATTR_CHAR_FONT )
106 || ( _pHandler->first == SID_ATTR_CHAR_FONTHEIGHT )
109 // these are attributes whose value depends on the current script type.
110 // I.e., in real, there are *three* items in the ItemSet: One for each script
111 // type (Latin, Asian, Complex). However, if we have an observer who is interested
112 // in the state of this attribute, we have to kind of *merge* the three attributes
113 // to only one.
114 // This is useful in case the observer is for instance a toolbox which contains only
115 // an, e.g., "bold" slot, and thus not interested in the particular script type of the
116 // current selection.
117 SvxScriptSetItem aNormalizedSet( (WhichId)_pHandler->first, *m_pView->GetAttribs().GetPool() );
118 normalizeScriptDependentAttribute( aNormalizedSet );
120 implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( aNormalizedSet.GetItemSet() ) );
122 else
123 implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( m_pView->GetAttribs() ) );
127 void RichTextControlImpl::updateAttribute( AttributeId _nAttribute )
129 AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.find( _nAttribute );
130 if ( pHandler != m_aAttributeHandlers.end() )
131 implUpdateAttribute( pHandler );
135 void RichTextControlImpl::updateAllAttributes( )
137 for ( AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.begin();
138 pHandler != m_aAttributeHandlers.end();
139 ++pHandler
142 implUpdateAttribute( pHandler );
145 // notify changes of the selection, if necessary
146 if ( m_pSelectionListener && m_pView )
148 ESelection aCurrentSelection = m_pView->GetSelection();
149 if ( !aCurrentSelection.IsEqual( m_aLastKnownSelection ) )
151 m_aLastKnownSelection = aCurrentSelection;
152 m_pSelectionListener->onSelectionChanged( m_aLastKnownSelection );
158 AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const
160 StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId );
161 if ( aCachedStatePos == m_aLastKnownStates.end() )
163 OSL_FAIL( "RichTextControlImpl::getAttributeState: Don't ask for the state of an attribute which I never encountered!" );
164 return AttributeState( eIndetermined );
166 return aCachedStatePos->second;
170 bool RichTextControlImpl::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, SvtScriptType _nForScriptType )
172 // let's see whether we have a handler for this attribute
173 AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttribute );
174 if ( aHandlerPos != m_aAttributeHandlers.end() )
176 aHandlerPos->second->executeAttribute( _rCurrentAttribs, _rAttribs, _pArgument, _nForScriptType );
177 return true;
179 return false;
183 void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener )
185 AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId );
186 if ( aHandlerPos == m_aAttributeHandlers.end() )
188 ::rtl::Reference< AttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() );
189 OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" );
190 if ( !aHandler.is() )
191 return;
192 SAL_WARN_IF( _nAttributeId != aHandler->getAttributeId(), "forms.richtext", "RichTextControlImpl::enableAttributeNotification: suspicious handler!" );
194 aHandlerPos = m_aAttributeHandlers.insert( AttributeHandlerPool::value_type( _nAttributeId , aHandler ) ).first;
197 // remember the listener
198 if ( _pListener )
199 m_aAttributeListeners.insert( AttributeListenerPool::value_type( _nAttributeId, _pListener ) );
201 // update (and broadcast) the state of this attribute
202 updateAttribute( _nAttributeId );
206 void RichTextControlImpl::disableAttributeNotification( AttributeId _nAttributeId )
208 // forget the handler for this attribute
209 AttributeHandlerPool::iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId );
210 if ( aHandlerPos != m_aAttributeHandlers.end() )
211 m_aAttributeHandlers.erase( aHandlerPos );
213 // as well as the listener
214 AttributeListenerPool::iterator aListenerPos = m_aAttributeListeners.find( _nAttributeId );
215 if ( aListenerPos != m_aAttributeListeners.end() )
216 m_aAttributeListeners.erase( aListenerPos );
220 void RichTextControlImpl::normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem )
222 _rScriptSetItem.GetItemSet().Put( m_pView->GetAttribs(), false );
223 const SfxPoolItem* pNormalizedItem = _rScriptSetItem.GetItemOfScript( getSelectedScriptType() );
225 WhichId nNormalizedWhichId = _rScriptSetItem.GetItemSet().GetPool()->GetWhich( _rScriptSetItem.Which() );
226 if ( pNormalizedItem )
228 SfxPoolItem* pProperWhich = pNormalizedItem->Clone();
229 pProperWhich->SetWhich( nNormalizedWhichId );
230 _rScriptSetItem.GetItemSet().Put( *pProperWhich );
231 DELETEZ( pProperWhich );
233 else
234 _rScriptSetItem.GetItemSet().InvalidateItem( nNormalizedWhichId );
238 void RichTextControlImpl::implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState )
240 StateCache::iterator aCachePos = m_aLastKnownStates.find( _nAttribute );
241 if ( aCachePos == m_aLastKnownStates.end() )
242 { // nothing known about this attribute, yet
243 m_aLastKnownStates.insert( StateCache::value_type( _nAttribute, _rState ) );
245 else
247 if ( aCachePos->second == _rState )
249 // nothing to do
250 return;
252 aCachePos->second = _rState;
255 // is there a dedicated listener for this particular attribute?
256 AttributeListenerPool::const_iterator aListenerPos = m_aAttributeListeners.find( _nAttribute );
257 if ( aListenerPos != m_aAttributeListeners.end( ) )
258 aListenerPos->second->onAttributeStateChanged( _nAttribute, _rState );
260 // call our global listener, if there is one
261 if ( m_pTextAttrListener )
262 m_pTextAttrListener->onAttributeStateChanged( _nAttribute, _rState );
266 SvtScriptType RichTextControlImpl::getSelectedScriptType() const
268 SvtScriptType nScript = m_pView->GetSelectedScriptType();
269 if ( nScript == SvtScriptType::NONE )
270 nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
271 return nScript;
275 void RichTextControlImpl::EditEngineStatusChanged( const EditStatus& _rStatus )
277 EditStatusFlags nStatusWord( _rStatus.GetStatusWord() );
278 if ( ( nStatusWord & EditStatusFlags::TEXTWIDTHCHANGED )
279 || ( nStatusWord & EditStatusFlags::TEXTHEIGHTCHANGED )
282 if ( ( nStatusWord & EditStatusFlags::TEXTHEIGHTCHANGED ) && windowHasAutomaticLineBreak() )
283 m_pEngine->SetPaperSize( Size( m_pEngine->GetPaperSize().Width(), m_pEngine->GetTextHeight() ) );
285 updateScrollbars();
288 bool bHScroll = bool( nStatusWord & EditStatusFlags::HSCROLL );
289 bool bVScroll = bool( nStatusWord & EditStatusFlags::VSCROLL );
291 // In case of *no* automatic line breaks, we also need to check for the *range* here.
292 // Normally, we would do this only after a EditStatusFlags::TEXTWIDTHCHANGED. However, due to a bug
293 // in the EditEngine (I believe so) this is not fired when the engine does not have
294 // the AutoPaperSize bits set.
295 // So in order to be properly notified, we would need the AutoPaperSize. But, with
296 // AutoPaperSize, other things do not work anymore: Either, when we set a MaxAutoPaperSize,
297 // then the view does automatic soft line breaks at the paper end - which we definitely do
298 // want. Or, if we did not set a MaxAutoPaperSize, then the view does not automatically scroll
299 // anymore in horizontal direction.
300 // So this is some kind of lose-lose situation ... :(
301 if ( !windowHasAutomaticLineBreak() && bHScroll )
303 updateScrollbars();
304 return;
307 if ( bHScroll && m_pHScroll )
308 m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
309 if ( bVScroll && m_pVScroll )
310 m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
314 IMPL_LINK_NOARG_TYPED( RichTextControlImpl, OnInvalidateAllAttributes, LinkParamNone*, void )
316 updateAllAttributes();
320 IMPL_LINK_TYPED( RichTextControlImpl, OnHScroll, ScrollBar*, _pScrollbar, void )
322 m_pView->Scroll( -_pScrollbar->GetDelta(), 0, ScrollRangeCheck::PaperWidthTextSize );
326 IMPL_LINK_TYPED( RichTextControlImpl, OnVScroll, ScrollBar*, _pScrollbar, void )
328 m_pView->Scroll( 0, -_pScrollbar->GetDelta(), ScrollRangeCheck::PaperWidthTextSize );
332 void RichTextControlImpl::ensureScrollbars()
334 bool bNeedVScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_VSCROLL );
335 bool bNeedHScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_HSCROLL );
337 if ( ( bNeedVScroll == hasVScrollBar() ) && ( bNeedHScroll == hasHScrollBar( ) ) )
338 // nothing to do
339 return;
341 // create or delete the scrollbars, as necessary
342 if ( !bNeedVScroll )
344 m_pVScroll.disposeAndClear();
346 else
348 m_pVScroll = VclPtr<ScrollBar>::Create( m_pAntiImpl, WB_VSCROLL | WB_DRAG | WB_REPEAT );
349 m_pVScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnVScroll ) );
350 m_pVScroll->Show();
353 if ( !bNeedHScroll )
355 m_pHScroll.disposeAndClear();
357 else
359 m_pHScroll = VclPtr<ScrollBar>::Create( m_pAntiImpl, WB_HSCROLL | WB_DRAG | WB_REPEAT );
360 m_pHScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnHScroll ) );
361 m_pHScroll->Show();
364 if ( m_pHScroll && m_pVScroll )
366 m_pScrollCorner.disposeAndClear();
367 m_pScrollCorner = VclPtr<ScrollBarBox>::Create( m_pAntiImpl );
368 m_pScrollCorner->Show();
370 else
372 m_pScrollCorner.disposeAndClear();
375 layoutWindow();
379 void RichTextControlImpl::ensureLineBreakSetting()
381 if ( !windowHasAutomaticLineBreak() )
382 m_pEngine->SetPaperSize( Size( EMPTY_PAPER_SIZE, EMPTY_PAPER_SIZE ) );
384 layoutWindow();
388 void RichTextControlImpl::layoutWindow()
390 if ( !m_bHasEverBeenShown )
391 // no need to do anything. Especially, no need to set the paper size on the
392 // EditEngine to anything ....
393 return;
395 const StyleSettings& rStyleSettings = m_pAntiImpl->GetSettings().GetStyleSettings();
397 long nScrollBarWidth = m_pVScroll ? rStyleSettings.GetScrollBarSize() : 0;
398 long nScrollBarHeight = m_pHScroll ? rStyleSettings.GetScrollBarSize() : 0;
400 if ( m_pAntiImpl->IsZoom() )
402 nScrollBarWidth = m_pAntiImpl->CalcZoom( nScrollBarWidth );
403 nScrollBarHeight = m_pAntiImpl->CalcZoom( nScrollBarHeight );
406 // the overall size we can use
407 Size aPlaygroundSizePixel( m_pAntiImpl->GetOutputSizePixel() );
409 // the size of the viewport - note that the viewport does *not* occupy all the place
410 // which is left when subtracting the scrollbar width/height
411 Size aViewportPlaygroundPixel( aPlaygroundSizePixel );
412 aViewportPlaygroundPixel.Width() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) );
413 aViewportPlaygroundPixel.Height() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) );
414 Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) );
416 const long nOffset = 2;
417 Size aViewportSizePixel( aViewportPlaygroundPixel.Width() - 2 * nOffset, aViewportPlaygroundPixel.Height() - 2 * nOffset );
418 Size aViewportSizeLogic( m_pViewport->PixelToLogic( aViewportSizePixel ) );
420 // position the viewport
421 m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel );
422 // position the scrollbars
423 if ( m_pVScroll )
424 m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) );
425 if ( m_pHScroll )
426 m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) );
427 if ( m_pScrollCorner )
428 m_pScrollCorner->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), aViewportPlaygroundPixel.Height() ), Size( nScrollBarWidth, nScrollBarHeight ) );
430 // paper size
431 if ( windowHasAutomaticLineBreak() )
432 m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) );
434 // output area of the view
435 m_pView->SetOutputArea( Rectangle( Point( ), aViewportSizeLogic ) );
436 m_pView->SetVisArea( Rectangle( Point( ), aViewportSizeLogic ) );
438 if ( m_pVScroll )
440 m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() );
442 // the default height of a text line ....
443 long nFontHeight = m_pEngine->GetStandardFont(0).GetFontSize().Height();
444 // ... is the scroll size for the vertical scrollbar
445 m_pVScroll->SetLineSize( nFontHeight );
446 // the viewport width, minus one line, is the page scroll size
447 m_pVScroll->SetPageSize( ::std::max( nFontHeight, aViewportPlaygroundLogic.Height() - nFontHeight ) );
450 // the font width
451 if ( m_pHScroll )
453 m_pHScroll->SetVisibleSize( aViewportPlaygroundLogic.Width() );
455 long nFontWidth = m_pEngine->GetStandardFont(0).GetFontSize().Width();
456 if ( !nFontWidth )
458 m_pViewport->Push( PushFlags::FONT );
459 m_pViewport->SetFont( m_pEngine->GetStandardFont(0) );
460 nFontWidth = m_pViewport->GetTextWidth( "x" );
461 m_pViewport->Pop();
463 // ... is the scroll size for the horizontal scrollbar
464 m_pHScroll->SetLineSize( 5 * nFontWidth );
465 // the viewport height, minus one character, is the page scroll size
466 m_pHScroll->SetPageSize( ::std::max( nFontWidth, aViewportPlaygroundLogic.Width() - nFontWidth ) );
469 // update range and position of the scrollbars
470 updateScrollbars();
474 void RichTextControlImpl::updateScrollbars()
476 if ( m_pVScroll )
478 long nOverallTextHeight = m_pEngine->GetTextHeight();
479 m_pVScroll->SetRange( Range( 0, nOverallTextHeight ) );
480 m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
483 if ( m_pHScroll )
485 Size aPaperSize( m_pEngine->GetPaperSize() );
486 long nOverallTextWidth = ( aPaperSize.Width() == EMPTY_PAPER_SIZE ) ? m_pEngine->CalcTextWidth() : aPaperSize.Width();
487 m_pHScroll->SetRange( Range( 0, nOverallTextWidth ) );
488 m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
493 void RichTextControlImpl::notifyInitShow()
495 if ( !m_bHasEverBeenShown )
497 m_bHasEverBeenShown = true;
498 layoutWindow();
503 void RichTextControlImpl::notifyStyleChanged()
505 ensureScrollbars();
506 ensureLineBreakSetting();
510 void RichTextControlImpl::notifyZoomChanged()
512 const Fraction& rZoom = m_pAntiImpl->GetZoom();
514 MapMode aMapMode( m_pAntiImpl->GetMapMode() );
515 aMapMode.SetScaleX( rZoom );
516 aMapMode.SetScaleY( rZoom );
517 m_pAntiImpl->SetMapMode( aMapMode );
519 m_pViewport->SetZoom( rZoom );
520 m_pViewport->SetMapMode( aMapMode );
522 layoutWindow();
526 bool RichTextControlImpl::windowHasAutomaticLineBreak()
528 return ( m_pAntiImpl->GetStyle() & WB_WORDBREAK ) != 0;
532 void RichTextControlImpl::SetReadOnly( bool _bReadOnly )
534 m_pView->SetReadOnly( _bReadOnly );
538 bool RichTextControlImpl::IsReadOnly() const
540 return m_pView->IsReadOnly( );
544 namespace
546 void lcl_inflate( Rectangle& _rRect, long _nInflateX, long _nInflateY )
548 _rRect.Left() -= _nInflateX;
549 _rRect.Right() += _nInflateX;
550 _rRect.Top() -= _nInflateY;
551 _rRect.Bottom() += _nInflateY;
555 long RichTextControlImpl::HandleCommand( const CommandEvent& _rEvent )
557 if ( ( _rEvent.GetCommand() == CommandEventId::Wheel )
558 || ( _rEvent.GetCommand() == CommandEventId::StartAutoScroll )
559 || ( _rEvent.GetCommand() == CommandEventId::AutoScroll )
562 m_pAntiImpl->HandleScrollCommand( _rEvent, m_pHScroll, m_pVScroll );
563 return 1;
565 return 0;
569 void RichTextControlImpl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, DrawFlags /*_nFlags*/ )
571 // need to normalize the map mode of the device - every paint operation on any device needs
572 // to use the same map mode
573 _pDev->Push( PushFlags::MAPMODE | PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
575 // enforce our "normalize map mode" on the device
576 MapMode aRefMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
577 MapMode aOriginalMapMode( _pDev->GetMapMode() );
578 MapMode aNormalizedMapMode( aRefMapMode.GetMapUnit(), aRefMapMode.GetOrigin(), aOriginalMapMode.GetScaleX(), aOriginalMapMode.GetScaleY() );
579 _pDev->SetMapMode( aNormalizedMapMode );
581 // translate coordinates
582 Point aPos( _rPos );
583 Size aSize( _rSize );
584 if ( aOriginalMapMode.GetMapUnit() == MAP_PIXEL )
586 aPos = _pDev->PixelToLogic( _rPos, aNormalizedMapMode );
587 aSize = _pDev->PixelToLogic( _rSize, aNormalizedMapMode );
589 else
591 aPos = OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode );
592 aSize = OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode );
595 Rectangle aPlayground( aPos, aSize );
596 Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) );
597 aPlayground.Right() -= aOnePixel.Width();
598 aPlayground.Bottom() -= aOnePixel.Height();
600 // background
601 _pDev->SetLineColor();
602 _pDev->DrawRect( aPlayground );
604 // do we need to draw a border?
605 bool bBorder = ( m_pAntiImpl->GetStyle() & WB_BORDER );
606 if ( bBorder )
607 _pDev->SetLineColor( m_pAntiImpl->GetSettings().GetStyleSettings().GetMonoColor() );
608 else
609 _pDev->SetLineColor();
610 _pDev->SetFillColor( m_pAntiImpl->GetBackground().GetColor() );
611 _pDev->DrawRect( aPlayground );
613 if ( bBorder )
614 // don't draw the text over the border
615 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
617 // leave a space of two pixels between the "surroundings" of the control
618 // and the content
619 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
620 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
622 // actually draw the content
623 m_pEngine->Draw( _pDev, aPlayground, Point(), true );
625 _pDev->Pop();
629 void RichTextControlImpl::SetBackgroundColor( )
631 SetBackgroundColor( Application::GetSettings().GetStyleSettings().GetFieldColor() );
635 void RichTextControlImpl::SetBackgroundColor( const Color& _rColor )
637 Wallpaper aWallpaper( _rColor );
638 m_pAntiImpl->SetBackground( aWallpaper );
639 m_pViewport->SetBackground( aWallpaper );
643 void RichTextControlImpl::SetHideInactiveSelection( bool _bHide )
645 m_pViewport->SetHideInactiveSelection( _bHide );
649 bool RichTextControlImpl::GetHideInactiveSelection() const
651 return m_pViewport->GetHideInactiveSelection( );
655 } // namespace frm
658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */