LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / forms / source / richtext / richtextimplcontrol.cxx
blobd1cbd7f6aec31e3c16f6abd7b464ea52fb62bc79
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 <sal/log.hxx>
24 #include <osl/diagnose.h>
25 #include <i18nlangtag/languagetag.hxx>
26 #include <editeng/editids.hrc>
27 #include <editeng/editview.hxx>
28 #include <editeng/editstat.hxx>
29 #include <editeng/scripttypeitem.hxx>
31 #include <svl/itempool.hxx>
32 #include <svl/itemset.hxx>
33 #include <tools/mapunit.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/settings.hxx>
36 #include <vcl/commandevent.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_pTextAttrListener ( _pTextAttrListener )
52 ,m_pSelectionListener ( _pSelectionListener )
53 ,m_bHasEverBeenShown ( false )
55 OSL_ENSURE( m_pAntiImpl, "RichTextControlImpl::RichTextControlImpl: invalid window!" );
56 OSL_ENSURE( m_pEngine, "RichTextControlImpl::RichTextControlImpl: invalid edit engine! This will *definitely* crash!" );
58 m_pViewport = VclPtr<RichTextViewPort>::Create( m_pAntiImpl );
59 m_pViewport->setAttributeInvalidationHandler( LINK( this, RichTextControlImpl, OnInvalidateAllAttributes ) );
60 m_pViewport->Show();
62 // ensure that both the window and the reference device have the same map unit
63 MapMode aRefDeviceMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
64 m_pAntiImpl->SetMapMode( aRefDeviceMapMode );
65 m_pViewport->SetMapMode( aRefDeviceMapMode );
67 m_pView.reset(new EditView( m_pEngine, m_pViewport ));
68 m_pEngine->InsertView( m_pView.get() );
69 m_pViewport->setView( *m_pView );
71 m_pEngine->registerEngineStatusListener( this );
74 EVControlBits nViewControlWord = m_pView->GetControlWord();
75 nViewControlWord |= EVControlBits::AUTOSCROLL;
76 m_pView->SetControlWord( nViewControlWord );
79 // ensure that it's initially scrolled to the upper left
80 m_pView->SetVisArea( tools::Rectangle( Point( ), m_pViewport->GetOutDev()->GetOutputSize() ) );
82 ensureScrollbars();
84 m_pAntiImpl->SetBackground( Wallpaper( m_pAntiImpl->GetSettings().GetStyleSettings().GetFieldColor() ) );
88 RichTextControlImpl::~RichTextControlImpl( )
90 m_pEngine->RemoveView( m_pView.get() );
91 m_pEngine->revokeEngineStatusListener( this );
92 m_pView.reset();
93 m_pViewport.disposeAndClear();
94 m_pHScroll.disposeAndClear();
95 m_pVScroll.disposeAndClear();
96 m_pScrollCorner.disposeAndClear();
100 void RichTextControlImpl::implUpdateAttribute( const AttributeHandlerPool::const_iterator& _pHandler )
102 if ( ( _pHandler->first == SID_ATTR_CHAR_WEIGHT )
103 || ( _pHandler->first == SID_ATTR_CHAR_POSTURE )
104 || ( _pHandler->first == SID_ATTR_CHAR_FONT )
105 || ( _pHandler->first == SID_ATTR_CHAR_FONTHEIGHT )
108 // these are attributes whose value depends on the current script type.
109 // I.e., in real, there are *three* items in the ItemSet: One for each script
110 // type (Latin, Asian, Complex). However, if we have an observer who is interested
111 // in the state of this attribute, we have to kind of *merge* the three attributes
112 // to only one.
113 // This is useful in case the observer is for instance a toolbox which contains only
114 // an, e.g., "bold" slot, and thus not interested in the particular script type of the
115 // current selection.
116 SvxScriptSetItem aNormalizedSet( static_cast<WhichId>(_pHandler->first), *m_pView->GetAttribs().GetPool() );
117 normalizeScriptDependentAttribute( aNormalizedSet );
119 implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( aNormalizedSet.GetItemSet() ) );
121 else
122 implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( m_pView->GetAttribs() ) );
126 void RichTextControlImpl::updateAttribute( AttributeId _nAttribute )
128 AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.find( _nAttribute );
129 if ( pHandler != m_aAttributeHandlers.end() )
130 implUpdateAttribute( pHandler );
134 void RichTextControlImpl::updateAllAttributes( )
136 for ( AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.begin();
137 pHandler != m_aAttributeHandlers.end();
138 ++pHandler
141 implUpdateAttribute( pHandler );
144 // notify changes of the selection, if necessary
145 if ( m_pSelectionListener && m_pView )
147 ESelection aCurrentSelection = m_pView->GetSelection();
148 if ( aCurrentSelection != m_aLastKnownSelection )
150 m_aLastKnownSelection = aCurrentSelection;
151 m_pSelectionListener->onSelectionChanged();
157 AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const
159 StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId );
160 if ( aCachedStatePos == m_aLastKnownStates.end() )
162 OSL_FAIL( "RichTextControlImpl::getAttributeState: Don't ask for the state of an attribute which I never encountered!" );
163 return AttributeState( eIndetermined );
165 return aCachedStatePos->second;
169 bool RichTextControlImpl::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, SvtScriptType _nForScriptType )
171 // let's see whether we have a handler for this attribute
172 AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttribute );
173 if ( aHandlerPos != m_aAttributeHandlers.end() )
175 aHandlerPos->second->executeAttribute( _rCurrentAttribs, _rAttribs, _pArgument, _nForScriptType );
176 return true;
178 return false;
182 void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener )
184 AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId );
185 if ( aHandlerPos == m_aAttributeHandlers.end() )
187 ::rtl::Reference< AttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() );
188 OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" );
189 if ( !aHandler.is() )
190 return;
191 SAL_WARN_IF( _nAttributeId != aHandler->getAttributeId(), "forms.richtext", "RichTextControlImpl::enableAttributeNotification: suspicious handler!" );
193 aHandlerPos = m_aAttributeHandlers.emplace( _nAttributeId , aHandler ).first;
196 // remember the listener
197 if ( _pListener )
198 m_aAttributeListeners.emplace( _nAttributeId, _pListener );
200 // update (and broadcast) the state of this attribute
201 updateAttribute( _nAttributeId );
205 void RichTextControlImpl::disableAttributeNotification( AttributeId _nAttributeId )
207 // forget the handler for this attribute
208 AttributeHandlerPool::iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId );
209 if ( aHandlerPos != m_aAttributeHandlers.end() )
210 m_aAttributeHandlers.erase( aHandlerPos );
212 // as well as the listener
213 AttributeListenerPool::iterator aListenerPos = m_aAttributeListeners.find( _nAttributeId );
214 if ( aListenerPos != m_aAttributeListeners.end() )
215 m_aAttributeListeners.erase( aListenerPos );
219 void RichTextControlImpl::normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem )
221 _rScriptSetItem.GetItemSet().Put( m_pView->GetAttribs(), false );
222 const SfxPoolItem* pNormalizedItem = _rScriptSetItem.GetItemOfScript( getSelectedScriptType() );
224 WhichId nNormalizedWhichId = _rScriptSetItem.GetItemSet().GetPool()->GetWhich( _rScriptSetItem.Which() );
225 if ( pNormalizedItem )
227 _rScriptSetItem.GetItemSet().Put( pNormalizedItem->CloneSetWhich(nNormalizedWhichId) );
229 else
230 _rScriptSetItem.GetItemSet().InvalidateItem( nNormalizedWhichId );
234 void RichTextControlImpl::implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState )
236 StateCache::iterator aCachePos = m_aLastKnownStates.find( _nAttribute );
237 if ( aCachePos == m_aLastKnownStates.end() )
238 { // nothing known about this attribute, yet
239 m_aLastKnownStates.emplace( _nAttribute, _rState );
241 else
243 if ( aCachePos->second == _rState )
245 // nothing to do
246 return;
248 aCachePos->second = _rState;
251 // is there a dedicated listener for this particular attribute?
252 AttributeListenerPool::const_iterator aListenerPos = m_aAttributeListeners.find( _nAttribute );
253 if ( aListenerPos != m_aAttributeListeners.end( ) )
254 aListenerPos->second->onAttributeStateChanged( _nAttribute );
256 // call our global listener, if there is one
257 if ( m_pTextAttrListener )
258 m_pTextAttrListener->onAttributeStateChanged( _nAttribute );
262 SvtScriptType RichTextControlImpl::getSelectedScriptType() const
264 SvtScriptType nScript = m_pView->GetSelectedScriptType();
265 if ( nScript == SvtScriptType::NONE )
266 nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
267 return nScript;
271 void RichTextControlImpl::EditEngineStatusChanged( const EditStatus& _rStatus )
273 EditStatusFlags nStatusWord( _rStatus.GetStatusWord() );
274 if ( ( nStatusWord & EditStatusFlags::TEXTWIDTHCHANGED )
275 || ( nStatusWord & EditStatusFlags::TextHeightChanged )
278 if ( ( nStatusWord & EditStatusFlags::TextHeightChanged ) && windowHasAutomaticLineBreak() )
279 m_pEngine->SetPaperSize( Size( m_pEngine->GetPaperSize().Width(), m_pEngine->GetTextHeight() ) );
281 updateScrollbars();
284 bool bHScroll = bool( nStatusWord & EditStatusFlags::HSCROLL );
285 bool bVScroll = bool( nStatusWord & EditStatusFlags::VSCROLL );
287 // In case of *no* automatic line breaks, we also need to check for the *range* here.
288 // Normally, we would do this only after an EditStatusFlags::TEXTWIDTHCHANGED. However, due to a bug
289 // in the EditEngine (I believe so) this is not fired when the engine does not have
290 // the AutoPaperSize bits set.
291 // So in order to be properly notified, we would need the AutoPaperSize. But, with
292 // AutoPaperSize, other things do not work anymore: Either, when we set a MaxAutoPaperSize,
293 // then the view does automatic soft line breaks at the paper end - which we definitely do
294 // want. Or, if we did not set a MaxAutoPaperSize, then the view does not automatically scroll
295 // anymore in horizontal direction.
296 // So this is some kind of lose-lose situation ... :(
297 if ( !windowHasAutomaticLineBreak() && bHScroll )
299 updateScrollbars();
300 return;
303 if ( bHScroll && m_pHScroll )
304 m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
305 if ( bVScroll && m_pVScroll )
306 m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
310 IMPL_LINK_NOARG( RichTextControlImpl, OnInvalidateAllAttributes, LinkParamNone*, void )
312 updateAllAttributes();
316 IMPL_LINK( RichTextControlImpl, OnHScroll, ScrollBar*, _pScrollbar, void )
318 m_pView->Scroll( -_pScrollbar->GetDelta(), 0, ScrollRangeCheck::PaperWidthTextSize );
322 IMPL_LINK( RichTextControlImpl, OnVScroll, ScrollBar*, _pScrollbar, void )
324 m_pView->Scroll( 0, -_pScrollbar->GetDelta(), ScrollRangeCheck::PaperWidthTextSize );
328 void RichTextControlImpl::ensureScrollbars()
330 bool bNeedVScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_VSCROLL );
331 bool bNeedHScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_HSCROLL );
333 if ( ( bNeedVScroll == hasVScrollBar() ) && ( bNeedHScroll == hasHScrollBar( ) ) )
334 // nothing to do
335 return;
337 // create or delete the scrollbars, as necessary
338 if ( !bNeedVScroll )
340 m_pVScroll.disposeAndClear();
342 else
344 m_pVScroll = VclPtr<ScrollBar>::Create( m_pAntiImpl, WB_VSCROLL | WB_DRAG | WB_REPEAT );
345 m_pVScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnVScroll ) );
346 m_pVScroll->Show();
349 if ( !bNeedHScroll )
351 m_pHScroll.disposeAndClear();
353 else
355 m_pHScroll = VclPtr<ScrollBar>::Create( m_pAntiImpl, WB_HSCROLL | WB_DRAG | WB_REPEAT );
356 m_pHScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnHScroll ) );
357 m_pHScroll->Show();
360 if ( m_pHScroll && m_pVScroll )
362 m_pScrollCorner.disposeAndClear();
363 m_pScrollCorner = VclPtr<ScrollBarBox>::Create( m_pAntiImpl );
364 m_pScrollCorner->Show();
366 else
368 m_pScrollCorner.disposeAndClear();
371 layoutWindow();
375 void RichTextControlImpl::ensureLineBreakSetting()
377 if ( !windowHasAutomaticLineBreak() )
378 m_pEngine->SetPaperSize( Size( EMPTY_PAPER_SIZE, EMPTY_PAPER_SIZE ) );
380 layoutWindow();
384 void RichTextControlImpl::layoutWindow()
386 if ( !m_bHasEverBeenShown )
387 // no need to do anything. Especially, no need to set the paper size on the
388 // EditEngine to anything...
389 return;
391 const StyleSettings& rStyleSettings = m_pAntiImpl->GetSettings().GetStyleSettings();
393 tools::Long nScrollBarWidth = m_pVScroll ? rStyleSettings.GetScrollBarSize() : 0;
394 tools::Long nScrollBarHeight = m_pHScroll ? rStyleSettings.GetScrollBarSize() : 0;
396 if ( m_pAntiImpl->IsZoom() )
398 nScrollBarWidth = m_pAntiImpl->CalcZoom( nScrollBarWidth );
399 nScrollBarHeight = m_pAntiImpl->CalcZoom( nScrollBarHeight );
402 // the overall size we can use
403 Size aPlaygroundSizePixel( m_pAntiImpl->GetOutputSizePixel() );
405 // the size of the viewport - note that the viewport does *not* occupy all the place
406 // which is left when subtracting the scrollbar width/height
407 Size aViewportPlaygroundPixel( aPlaygroundSizePixel );
408 aViewportPlaygroundPixel.setWidth( ::std::max( tools::Long( 10 ), tools::Long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) ) );
409 aViewportPlaygroundPixel.setHeight( ::std::max( tools::Long( 10 ), tools::Long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) ) );
410 Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) );
412 const tools::Long nOffset = 2;
413 Size aViewportSizePixel( aViewportPlaygroundPixel.Width() - 2 * nOffset, aViewportPlaygroundPixel.Height() - 2 * nOffset );
414 Size aViewportSizeLogic( m_pViewport->PixelToLogic( aViewportSizePixel ) );
416 // position the viewport
417 m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel );
418 // position the scrollbars
419 if ( m_pVScroll )
420 m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) );
421 if ( m_pHScroll )
422 m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) );
423 if ( m_pScrollCorner )
424 m_pScrollCorner->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), aViewportPlaygroundPixel.Height() ), Size( nScrollBarWidth, nScrollBarHeight ) );
426 // paper size
427 if ( windowHasAutomaticLineBreak() )
428 m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) );
430 // output area of the view
431 m_pView->SetOutputArea( tools::Rectangle( Point( ), aViewportSizeLogic ) );
432 m_pView->SetVisArea( tools::Rectangle( Point( ), aViewportSizeLogic ) );
434 if ( m_pVScroll )
436 m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() );
438 // the default height of a text line...
439 tools::Long nFontHeight = m_pEngine->GetStandardFont(0).GetFontSize().Height();
440 // ... is the scroll size for the vertical scrollbar
441 m_pVScroll->SetLineSize( nFontHeight );
442 // the viewport width, minus one line, is the page scroll size
443 m_pVScroll->SetPageSize( ::std::max( nFontHeight, aViewportPlaygroundLogic.Height() - nFontHeight ) );
446 // the font width
447 if ( m_pHScroll )
449 m_pHScroll->SetVisibleSize( aViewportPlaygroundLogic.Width() );
451 tools::Long nFontWidth = m_pEngine->GetStandardFont(0).GetFontSize().Width();
452 if ( !nFontWidth )
454 m_pViewport->GetOutDev()->Push( vcl::PushFlags::FONT );
455 m_pViewport->SetFont( m_pEngine->GetStandardFont(0) );
456 nFontWidth = m_pViewport->GetTextWidth( "x" );
457 m_pViewport->GetOutDev()->Pop();
459 // ... is the scroll size for the horizontal scrollbar
460 m_pHScroll->SetLineSize( 5 * nFontWidth );
461 // the viewport height, minus one character, is the page scroll size
462 m_pHScroll->SetPageSize( ::std::max( nFontWidth, aViewportPlaygroundLogic.Width() - nFontWidth ) );
465 // update range and position of the scrollbars
466 updateScrollbars();
470 void RichTextControlImpl::updateScrollbars()
472 if ( m_pVScroll )
474 tools::Long nOverallTextHeight = m_pEngine->GetTextHeight();
475 m_pVScroll->SetRange( Range( 0, nOverallTextHeight ) );
476 m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
479 if ( m_pHScroll )
481 Size aPaperSize( m_pEngine->GetPaperSize() );
482 tools::Long nOverallTextWidth = ( aPaperSize.Width() == EMPTY_PAPER_SIZE ) ? m_pEngine->CalcTextWidth() : aPaperSize.Width();
483 m_pHScroll->SetRange( Range( 0, nOverallTextWidth ) );
484 m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
489 void RichTextControlImpl::notifyInitShow()
491 if ( !m_bHasEverBeenShown )
493 m_bHasEverBeenShown = true;
494 layoutWindow();
499 void RichTextControlImpl::notifyStyleChanged()
501 ensureScrollbars();
502 ensureLineBreakSetting();
506 void RichTextControlImpl::notifyZoomChanged()
508 const Fraction& rZoom = m_pAntiImpl->GetZoom();
510 MapMode aMapMode( m_pAntiImpl->GetMapMode() );
511 aMapMode.SetScaleX( rZoom );
512 aMapMode.SetScaleY( rZoom );
513 m_pAntiImpl->SetMapMode( aMapMode );
515 m_pViewport->SetZoom( rZoom );
516 m_pViewport->SetMapMode( aMapMode );
518 layoutWindow();
522 bool RichTextControlImpl::windowHasAutomaticLineBreak()
524 return ( m_pAntiImpl->GetStyle() & WB_WORDBREAK ) != 0;
528 void RichTextControlImpl::SetReadOnly( bool _bReadOnly )
530 m_pView->SetReadOnly( _bReadOnly );
534 bool RichTextControlImpl::IsReadOnly() const
536 return m_pView->IsReadOnly( );
540 namespace
542 void lcl_inflate( tools::Rectangle& _rRect, tools::Long _nInflateX, tools::Long _nInflateY )
544 _rRect.AdjustLeft( -_nInflateX );
545 _rRect.AdjustRight(_nInflateX );
546 _rRect.AdjustTop( -_nInflateY );
547 _rRect.AdjustBottom(_nInflateY );
551 bool RichTextControlImpl::HandleCommand( const CommandEvent& _rEvent )
553 if ( ( _rEvent.GetCommand() == CommandEventId::Wheel )
554 || ( _rEvent.GetCommand() == CommandEventId::StartAutoScroll )
555 || ( _rEvent.GetCommand() == CommandEventId::AutoScroll )
558 m_pAntiImpl->HandleScrollCommand( _rEvent, m_pHScroll, m_pVScroll );
559 return true;
561 return false;
565 void RichTextControlImpl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize )
567 // need to normalize the map mode of the device - every paint operation on any device needs
568 // to use the same map mode
569 _pDev->Push( vcl::PushFlags::MAPMODE | vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
571 // enforce our "normalize map mode" on the device
572 MapMode aRefMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
573 MapMode aOriginalMapMode( _pDev->GetMapMode() );
574 MapMode aNormalizedMapMode( aRefMapMode.GetMapUnit(), aRefMapMode.GetOrigin(), aOriginalMapMode.GetScaleX(), aOriginalMapMode.GetScaleY() );
575 _pDev->SetMapMode( aNormalizedMapMode );
577 // translate coordinates
578 Point aPos( _rPos );
579 Size aSize( _rSize );
580 if ( aOriginalMapMode.GetMapUnit() == MapUnit::MapPixel )
582 aPos = _pDev->PixelToLogic( _rPos, aNormalizedMapMode );
583 aSize = _pDev->PixelToLogic( _rSize, aNormalizedMapMode );
585 else
587 aPos = OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode );
588 aSize = OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode );
591 tools::Rectangle aPlayground( aPos, aSize );
592 Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) );
593 aPlayground.AdjustRight( -(aOnePixel.Width()) );
594 aPlayground.AdjustBottom( -(aOnePixel.Height()) );
596 // background
597 _pDev->SetLineColor();
598 _pDev->DrawRect( aPlayground );
600 // do we need to draw a border?
601 bool bBorder = ( m_pAntiImpl->GetStyle() & WB_BORDER );
602 if ( bBorder )
603 _pDev->SetLineColor( m_pAntiImpl->GetSettings().GetStyleSettings().GetMonoColor() );
604 else
605 _pDev->SetLineColor();
606 _pDev->SetFillColor( m_pAntiImpl->GetBackground().GetColor() );
607 _pDev->DrawRect( aPlayground );
609 if ( bBorder )
610 // don't draw the text over the border
611 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
613 // leave a space of two pixels between the "surroundings" of the control
614 // and the content
615 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
616 lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
618 // actually draw the content
619 m_pEngine->Draw(*_pDev, aPlayground, Point(), true);
621 _pDev->Pop();
625 void RichTextControlImpl::SetBackgroundColor( )
627 SetBackgroundColor( Application::GetSettings().GetStyleSettings().GetFieldColor() );
631 void RichTextControlImpl::SetBackgroundColor( const Color& _rColor )
633 Wallpaper aWallpaper( _rColor );
634 m_pAntiImpl->SetBackground( aWallpaper );
635 m_pViewport->SetBackground( aWallpaper );
639 void RichTextControlImpl::SetHideInactiveSelection( bool _bHide )
641 m_pViewport->SetHideInactiveSelection( _bHide );
645 bool RichTextControlImpl::GetHideInactiveSelection() const
647 return m_pViewport->GetHideInactiveSelection( );
651 } // namespace frm
654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */