| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_forms.hxx" |
| #include "richtextimplcontrol.hxx" |
| #include "textattributelistener.hxx" |
| #include "richtextengine.hxx" |
| #include <editeng/editeng.hxx> |
| #include <editeng/editview.hxx> |
| #include <editeng/eeitem.hxx> |
| #include <editeng/editstat.hxx> |
| #ifndef _SVX_SVXIDS_HRC |
| #include <svx/svxids.hrc> |
| #endif |
| #include <editeng/scripttypeitem.hxx> |
| |
| #include <editeng/editobj.hxx> |
| #include <svl/itempool.hxx> |
| #include <svl/itemset.hxx> |
| #include <tools/mapunit.hxx> |
| #include <vcl/window.hxx> |
| #include <vcl/svapp.hxx> |
| |
| #include <memory> |
| |
| #define EMPTY_PAPER_SIZE 0x7FFFFFFF |
| |
| //........................................................................ |
| namespace frm |
| { |
| //........................................................................ |
| //==================================================================== |
| //= RichTextControlImpl |
| //==================================================================== |
| //-------------------------------------------------------------------- |
| RichTextControlImpl::RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener ) |
| :m_pAntiImpl ( _pAntiImpl ) |
| ,m_pViewport ( NULL ) |
| ,m_pHScroll ( NULL ) |
| ,m_pVScroll ( NULL ) |
| ,m_pScrollCorner ( NULL ) |
| ,m_pEngine ( _pEngine ) |
| ,m_pView ( NULL ) |
| ,m_pTextAttrListener ( _pTextAttrListener ) |
| ,m_pSelectionListener ( _pSelectionListener ) |
| ,m_bHasEverBeenShown ( false ) |
| { |
| OSL_ENSURE( m_pAntiImpl, "RichTextControlImpl::RichTextControlImpl: invalid window!" ); |
| OSL_ENSURE( m_pEngine, "RichTextControlImpl::RichTextControlImpl: invalid edit engine! This will *definately* crash!" ); |
| |
| m_pViewport = new RichTextViewPort( m_pAntiImpl ); |
| m_pViewport->setAttributeInvalidationHandler( LINK( this, RichTextControlImpl, OnInvalidateAllAttributes ) ); |
| m_pViewport->Show(); |
| |
| // ensure that both the window and the reference device have the same map unit |
| MapMode aRefDeviceMapMode( m_pEngine->GetRefDevice()->GetMapMode() ); |
| m_pAntiImpl->SetMapMode( aRefDeviceMapMode ); |
| m_pViewport->SetMapMode( aRefDeviceMapMode ); |
| |
| m_pView = new EditView( m_pEngine, m_pViewport ); |
| m_pEngine->InsertView( m_pView ); |
| m_pViewport->setView( *m_pView ); |
| |
| m_pEngine->registerEngineStatusListener( this ); |
| |
| { |
| sal_uLong nViewControlWord = m_pView->GetControlWord(); |
| nViewControlWord |= EV_CNTRL_AUTOSCROLL; |
| m_pView->SetControlWord( nViewControlWord ); |
| } |
| |
| // ensure that it's initially scrolled to the upper left |
| m_pView->SetVisArea( Rectangle( Point( ), m_pViewport->GetOutputSize() ) ); |
| |
| ensureScrollbars(); |
| |
| m_pAntiImpl->SetBackground( Wallpaper( m_pAntiImpl->GetSettings().GetStyleSettings().GetFieldColor() ) ); |
| } |
| |
| //-------------------------------------------------------------------- |
| RichTextControlImpl::~RichTextControlImpl( ) |
| { |
| m_pEngine->RemoveView( m_pView ); |
| m_pEngine->revokeEngineStatusListener( this ); |
| delete m_pView; |
| delete m_pViewport; |
| delete m_pHScroll; |
| delete m_pVScroll; |
| delete m_pScrollCorner; |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::implUpdateAttribute( AttributeHandlerPool::const_iterator _pHandler ) |
| { |
| if ( ( _pHandler->first == SID_ATTR_CHAR_WEIGHT ) |
| || ( _pHandler->first == SID_ATTR_CHAR_POSTURE ) |
| || ( _pHandler->first == SID_ATTR_CHAR_FONT ) |
| || ( _pHandler->first == SID_ATTR_CHAR_FONTHEIGHT ) |
| ) |
| { |
| // these are attributes whose value depends on the current script type. |
| // I.e., in real, there are *three* items in the ItemSet: One for each script |
| // type (Latin, Asian, Complex). However, if we have an observer who is interested |
| // in the state of this attribute, we have to kind of *merge* the three attributes |
| // to only one. |
| // This is usefull in case the observer is for instance a toolbox which contains only |
| // an, e.g., "bold" slot, and thus not interested in the particular script type of the |
| // current selection. |
| SvxScriptSetItem aNormalizedSet( (WhichId)_pHandler->first, *m_pView->GetAttribs().GetPool() ); |
| normalizeScriptDependentAttribute( aNormalizedSet ); |
| |
| implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( aNormalizedSet.GetItemSet() ) ); |
| } |
| else |
| implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( m_pView->GetAttribs() ) ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::updateAttribute( AttributeId _nAttribute ) |
| { |
| AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.find( _nAttribute ); |
| if ( pHandler != m_aAttributeHandlers.end() ) |
| implUpdateAttribute( pHandler ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::updateAllAttributes( ) |
| { |
| for ( AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.begin(); |
| pHandler != m_aAttributeHandlers.end(); |
| ++pHandler |
| ) |
| { |
| implUpdateAttribute( pHandler ); |
| } |
| |
| // notify changes of the selection, if necessary |
| if ( m_pSelectionListener && m_pView ) |
| { |
| ESelection aCurrentSelection = m_pView->GetSelection(); |
| if ( !aCurrentSelection.IsEqual( m_aLastKnownSelection ) ) |
| { |
| m_aLastKnownSelection = aCurrentSelection; |
| m_pSelectionListener->onSelectionChanged( m_aLastKnownSelection ); |
| } |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const |
| { |
| StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId ); |
| if ( aCachedStatePos == m_aLastKnownStates.end() ) |
| { |
| OSL_ENSURE( sal_False, "RichTextControlImpl::getAttributeState: Don't ask for the state of an attribute which I never encountered!" ); |
| return AttributeState( eIndetermined ); |
| } |
| return aCachedStatePos->second; |
| } |
| |
| //-------------------------------------------------------------------- |
| bool RichTextControlImpl::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, ScriptType _nForScriptType ) |
| { |
| // let's see whether we have a handler for this attribute |
| AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttribute ); |
| if ( aHandlerPos != m_aAttributeHandlers.end() ) |
| { |
| aHandlerPos->second->executeAttribute( _rCurrentAttribs, _rAttribs, _pArgument, _nForScriptType ); |
| return true; |
| } |
| return false; |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener ) |
| { |
| AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId ); |
| if ( aHandlerPos == m_aAttributeHandlers.end() ) |
| { |
| ::rtl::Reference< IAttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() ); |
| OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" ); |
| if ( !aHandler.is() ) |
| return; |
| OSL_POSTCOND( _nAttributeId == aHandler->getAttributeId(), "RichTextControlImpl::enableAttributeNotification: suspicious handler!" ); |
| |
| aHandlerPos = m_aAttributeHandlers.insert( AttributeHandlerPool::value_type( _nAttributeId , aHandler ) ).first; |
| } |
| |
| // remember the listener |
| if ( _pListener ) |
| m_aAttributeListeners.insert( AttributeListenerPool::value_type( _nAttributeId, _pListener ) ); |
| |
| // update (and broadcast) the state of this attribute |
| updateAttribute( _nAttributeId ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::disableAttributeNotification( AttributeId _nAttributeId ) |
| { |
| // forget the handler for this attribute |
| AttributeHandlerPool::iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId ); |
| if ( aHandlerPos != m_aAttributeHandlers.end() ) |
| m_aAttributeHandlers.erase( aHandlerPos ); |
| |
| // as well as the listener |
| AttributeListenerPool::iterator aListenerPos = m_aAttributeListeners.find( _nAttributeId ); |
| if ( aListenerPos != m_aAttributeListeners.end() ) |
| m_aAttributeListeners.erase( aListenerPos ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem ) |
| { |
| _rScriptSetItem.GetItemSet().Put( m_pView->GetAttribs(), sal_False ); |
| const SfxPoolItem* pNormalizedItem = _rScriptSetItem.GetItemOfScript( getSelectedScriptType() ); |
| |
| WhichId nNormalizedWhichId = _rScriptSetItem.GetItemSet().GetPool()->GetWhich( _rScriptSetItem.Which() ); |
| if ( pNormalizedItem ) |
| { |
| SfxPoolItem* pProperWhich = pNormalizedItem->Clone(); |
| pProperWhich->SetWhich( nNormalizedWhichId ); |
| _rScriptSetItem.GetItemSet().Put( *pProperWhich ); |
| DELETEZ( pProperWhich ); |
| } |
| else |
| _rScriptSetItem.GetItemSet().InvalidateItem( nNormalizedWhichId ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState ) |
| { |
| StateCache::iterator aCachePos = m_aLastKnownStates.find( _nAttribute ); |
| if ( aCachePos == m_aLastKnownStates.end() ) |
| { // nothing known about this attribute, yet |
| m_aLastKnownStates.insert( StateCache::value_type( _nAttribute, _rState ) ); |
| } |
| else |
| { |
| if ( aCachePos->second == _rState ) |
| { |
| // nothing to do |
| return; |
| } |
| aCachePos->second = _rState; |
| } |
| |
| // is there a dedicated listener for this particular attribute? |
| AttributeListenerPool::const_iterator aListenerPos = m_aAttributeListeners.find( _nAttribute ); |
| if ( aListenerPos != m_aAttributeListeners.end( ) ) |
| aListenerPos->second->onAttributeStateChanged( _nAttribute, _rState ); |
| |
| // call our global listener, if there is one |
| if ( m_pTextAttrListener ) |
| m_pTextAttrListener->onAttributeStateChanged( _nAttribute, _rState ); |
| } |
| |
| //-------------------------------------------------------------------- |
| ScriptType RichTextControlImpl::getSelectedScriptType() const |
| { |
| ScriptType nScript = m_pView->GetSelectedScriptType(); |
| if ( !nScript ) |
| nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() ); |
| return nScript; |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::EditEngineStatusChanged( const EditStatus& _rStatus ) |
| { |
| sal_uLong nStatusWord( _rStatus.GetStatusWord() ); |
| if ( ( nStatusWord & EE_STAT_TEXTWIDTHCHANGED ) |
| || ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) |
| ) |
| { |
| if ( ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) && windowHasAutomaticLineBreak() ) |
| m_pEngine->SetPaperSize( Size( m_pEngine->GetPaperSize().Width(), m_pEngine->GetTextHeight() ) ); |
| |
| updateScrollbars(); |
| } |
| |
| bool bHScroll = 0 != ( nStatusWord & EE_STAT_HSCROLL ); |
| bool bVScroll = 0 != ( nStatusWord & EE_STAT_VSCROLL ); |
| |
| // In case of *no* automatic line breaks, we also need to check for the *range* here. |
| // Normally, we would do this only after a EE_STAT_TEXTWIDTHCHANGED. However, due to a bug |
| // in the EditEngine (I believe so) this is not fired when the engine does not have |
| // the AutoPaperSize bits set. |
| // So in order to be properly notified, we would need the AutoPaperSize. But, with |
| // AutoPaperSize, other things do not work anymore: Either, when we set a MaxAutoPaperSize, |
| // then the view does automatic soft line breaks at the paper end - which we definately do |
| // want. Or, if we did not set a MaxAutoPaperSize, then the view does not automatically scroll |
| // anymore in horizontal direction. |
| // So this is some kind of lose-lose situation ... :( |
| if ( !windowHasAutomaticLineBreak() && bHScroll ) |
| { |
| updateScrollbars(); |
| return; |
| } |
| |
| if ( bHScroll && m_pHScroll ) |
| m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() ); |
| if ( bVScroll && m_pVScroll ) |
| m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() ); |
| } |
| |
| //-------------------------------------------------------------------- |
| IMPL_LINK( RichTextControlImpl, OnInvalidateAllAttributes, void*, /*_pNotInterestedIn*/ ) |
| { |
| updateAllAttributes(); |
| return 0L; |
| } |
| |
| //-------------------------------------------------------------------- |
| IMPL_LINK( RichTextControlImpl, OnHScroll, ScrollBar*, _pScrollbar ) |
| { |
| m_pView->Scroll( -_pScrollbar->GetDelta(), 0, RGCHK_PAPERSZ1 ); |
| return 0L; |
| } |
| |
| //-------------------------------------------------------------------- |
| IMPL_LINK( RichTextControlImpl, OnVScroll, ScrollBar*, _pScrollbar ) |
| { |
| m_pView->Scroll( 0, -_pScrollbar->GetDelta(), RGCHK_PAPERSZ1 ); |
| return 0L; |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::ensureScrollbars() |
| { |
| bool bNeedVScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_VSCROLL ); |
| bool bNeedHScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_HSCROLL ); |
| |
| if ( ( bNeedVScroll == hasVScrollBar() ) && ( bNeedHScroll == hasHScrollBar( ) ) ) |
| // nothing to do |
| return; |
| |
| // create or delete the scrollbars, as necessary |
| if ( !bNeedVScroll ) |
| { |
| delete m_pVScroll; |
| m_pVScroll = NULL; |
| } |
| else |
| { |
| m_pVScroll = new ScrollBar( m_pAntiImpl, WB_VSCROLL | WB_DRAG | WB_REPEAT ); |
| m_pVScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnVScroll ) ); |
| m_pVScroll->Show(); |
| } |
| |
| if ( !bNeedHScroll ) |
| { |
| delete m_pHScroll; |
| m_pHScroll = NULL; |
| } |
| else |
| { |
| m_pHScroll = new ScrollBar( m_pAntiImpl, WB_HSCROLL | WB_DRAG | WB_REPEAT ); |
| m_pHScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnHScroll ) ); |
| m_pHScroll->Show(); |
| } |
| |
| if ( m_pHScroll && m_pVScroll ) |
| { |
| delete m_pScrollCorner; |
| m_pScrollCorner = new ScrollBarBox( m_pAntiImpl ); |
| m_pScrollCorner->Show(); |
| } |
| else |
| { |
| delete m_pScrollCorner; |
| m_pScrollCorner = NULL; |
| } |
| |
| layoutWindow(); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::ensureLineBreakSetting() |
| { |
| if ( !windowHasAutomaticLineBreak() ) |
| m_pEngine->SetPaperSize( Size( EMPTY_PAPER_SIZE, EMPTY_PAPER_SIZE ) ); |
| |
| layoutWindow(); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::layoutWindow() |
| { |
| if ( !m_bHasEverBeenShown ) |
| // no need to do anything. Especially, no need to set the paper size on the |
| // EditEngine to anything .... |
| return; |
| |
| const StyleSettings& rStyleSettings = m_pAntiImpl->GetSettings().GetStyleSettings(); |
| |
| long nScrollBarWidth = m_pVScroll ? rStyleSettings.GetScrollBarSize() : 0; |
| long nScrollBarHeight = m_pHScroll ? rStyleSettings.GetScrollBarSize() : 0; |
| |
| if ( m_pAntiImpl->IsZoom() ) |
| { |
| nScrollBarWidth = m_pAntiImpl->CalcZoom( nScrollBarWidth ); |
| nScrollBarHeight = m_pAntiImpl->CalcZoom( nScrollBarHeight ); |
| } |
| |
| // the overall size we can use |
| Size aPlaygroundSizePixel( m_pAntiImpl->GetOutputSizePixel() ); |
| |
| // the size of the viewport - note that the viewport does *not* occupy all the place |
| // which is left when subtracting the scrollbar width/height |
| Size aViewportPlaygroundPixel( aPlaygroundSizePixel ); |
| aViewportPlaygroundPixel.Width() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) ); |
| aViewportPlaygroundPixel.Height() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) ); |
| Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) ); |
| |
| const long nOffset = 2; |
| Size aViewportSizePixel( aViewportPlaygroundPixel.Width() - 2 * nOffset, aViewportPlaygroundPixel.Height() - 2 * nOffset ); |
| Size aViewportSizeLogic( m_pViewport->PixelToLogic( aViewportSizePixel ) ); |
| |
| // position the viewport |
| m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel ); |
| // position the scrollbars |
| if ( m_pVScroll ) |
| m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) ); |
| if ( m_pHScroll ) |
| m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) ); |
| if ( m_pScrollCorner ) |
| m_pScrollCorner->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), aViewportPlaygroundPixel.Height() ), Size( nScrollBarWidth, nScrollBarHeight ) ); |
| |
| // paper size |
| if ( windowHasAutomaticLineBreak() ) |
| m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) ); |
| |
| // output area of the view |
| m_pView->SetOutputArea( Rectangle( Point( ), aViewportSizeLogic ) ); |
| m_pView->SetVisArea( Rectangle( Point( ), aViewportSizeLogic ) ); |
| |
| if ( m_pVScroll ) |
| { |
| m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() ); |
| |
| // the default height of a text line .... |
| long nFontHeight = m_pEngine->GetStandardFont(0).GetSize().Height(); |
| // ... is the scroll size for the vertical scrollbar |
| m_pVScroll->SetLineSize( nFontHeight ); |
| // the viewport width, minus one line, is the page scroll size |
| m_pVScroll->SetPageSize( ::std::max( nFontHeight, aViewportPlaygroundLogic.Height() - nFontHeight ) ); |
| } |
| |
| // the font width |
| if ( m_pHScroll ) |
| { |
| m_pHScroll->SetVisibleSize( aViewportPlaygroundLogic.Width() ); |
| |
| long nFontWidth = m_pEngine->GetStandardFont(0).GetSize().Width(); |
| if ( !nFontWidth ) |
| { |
| m_pViewport->Push( PUSH_FONT ); |
| m_pViewport->SetFont( m_pEngine->GetStandardFont(0) ); |
| nFontWidth = m_pViewport->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM( "x" ) ) ); |
| m_pViewport->Pop(); |
| } |
| // ... is the scroll size for the horizontal scrollbar |
| m_pHScroll->SetLineSize( 5 * nFontWidth ); |
| // the viewport height, minus one character, is the page scroll size |
| m_pHScroll->SetPageSize( ::std::max( nFontWidth, aViewportPlaygroundLogic.Width() - nFontWidth ) ); |
| } |
| |
| // update range and position of the scrollbars |
| updateScrollbars(); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::updateScrollbars() |
| { |
| if ( m_pVScroll ) |
| { |
| long nOverallTextHeight = m_pEngine->GetTextHeight(); |
| m_pVScroll->SetRange( Range( 0, nOverallTextHeight ) ); |
| m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() ); |
| } |
| |
| if ( m_pHScroll ) |
| { |
| Size aPaperSize( m_pEngine->GetPaperSize() ); |
| long nOverallTextWidth = ( aPaperSize.Width() == EMPTY_PAPER_SIZE ) ? m_pEngine->CalcTextWidth() : aPaperSize.Width(); |
| m_pHScroll->SetRange( Range( 0, nOverallTextWidth ) ); |
| m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() ); |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::notifyInitShow() |
| { |
| if ( !m_bHasEverBeenShown ) |
| { |
| m_bHasEverBeenShown = true; |
| layoutWindow(); |
| } |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::notifyStyleChanged() |
| { |
| ensureScrollbars(); |
| ensureLineBreakSetting(); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::notifyZoomChanged() |
| { |
| const Fraction& rZoom = m_pAntiImpl->GetZoom(); |
| |
| MapMode aMapMode( m_pAntiImpl->GetMapMode() ); |
| aMapMode.SetScaleX( rZoom ); |
| aMapMode.SetScaleY( rZoom ); |
| m_pAntiImpl->SetMapMode( aMapMode ); |
| |
| m_pViewport->SetZoom( rZoom ); |
| m_pViewport->SetMapMode( aMapMode ); |
| |
| layoutWindow(); |
| } |
| |
| //-------------------------------------------------------------------- |
| bool RichTextControlImpl::windowHasAutomaticLineBreak() |
| { |
| return ( m_pAntiImpl->GetStyle() & WB_WORDBREAK ) != 0; |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::SetReadOnly( bool _bReadOnly ) |
| { |
| m_pView->SetReadOnly( _bReadOnly ); |
| } |
| |
| //-------------------------------------------------------------------- |
| bool RichTextControlImpl::IsReadOnly() const |
| { |
| return m_pView->IsReadOnly( ); |
| } |
| |
| //-------------------------------------------------------------------- |
| namespace |
| { |
| static void lcl_inflate( Rectangle& _rRect, long _nInflateX, long _nInflateY ) |
| { |
| _rRect.Left() -= _nInflateX; |
| _rRect.Right() += _nInflateX; |
| _rRect.Top() -= _nInflateY; |
| _rRect.Bottom() += _nInflateY; |
| } |
| } |
| //-------------------------------------------------------------------- |
| long RichTextControlImpl::HandleCommand( const CommandEvent& _rEvent ) |
| { |
| if ( ( _rEvent.GetCommand() == COMMAND_WHEEL ) |
| || ( _rEvent.GetCommand() == COMMAND_STARTAUTOSCROLL ) |
| || ( _rEvent.GetCommand() == COMMAND_AUTOSCROLL ) |
| ) |
| { |
| m_pAntiImpl->HandleScrollCommand( _rEvent, m_pHScroll, m_pVScroll ); |
| return 1; |
| } |
| return 0; |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, sal_uLong /*_nFlags*/ ) |
| { |
| // need to normalize the map mode of the device - every paint operation on any device needs |
| // to use the same map mode |
| _pDev->Push( PUSH_MAPMODE | PUSH_LINECOLOR | PUSH_FILLCOLOR ); |
| |
| // enforce our "normalize map mode" on the device |
| MapMode aRefMapMode( m_pEngine->GetRefDevice()->GetMapMode() ); |
| MapMode aOriginalMapMode( _pDev->GetMapMode() ); |
| MapMode aNormalizedMapMode( aRefMapMode.GetMapUnit(), aRefMapMode.GetOrigin(), aOriginalMapMode.GetScaleX(), aOriginalMapMode.GetScaleY() ); |
| _pDev->SetMapMode( aNormalizedMapMode ); |
| |
| // translate coordinates |
| Point aPos( _rPos ); |
| Size aSize( _rSize ); |
| if ( aOriginalMapMode.GetMapUnit() == MAP_PIXEL ) |
| { |
| aPos = _pDev->PixelToLogic( _rPos, aNormalizedMapMode ); |
| aSize = _pDev->PixelToLogic( _rSize, aNormalizedMapMode ); |
| } |
| else |
| { |
| aPos = OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode ); |
| aSize = OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode ); |
| } |
| |
| Rectangle aPlayground( aPos, aSize ); |
| Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) ); |
| aPlayground.Right() -= aOnePixel.Width(); |
| aPlayground.Bottom() -= aOnePixel.Height(); |
| |
| // background |
| _pDev->SetLineColor(); |
| _pDev->DrawRect( aPlayground ); |
| |
| // do we need to draw a border? |
| bool bBorder = ( m_pAntiImpl->GetStyle() & WB_BORDER ); |
| if ( bBorder ) |
| _pDev->SetLineColor( m_pAntiImpl->GetSettings().GetStyleSettings().GetMonoColor() ); |
| else |
| _pDev->SetLineColor(); |
| _pDev->SetFillColor( m_pAntiImpl->GetBackground().GetColor() ); |
| _pDev->DrawRect( aPlayground ); |
| |
| if ( bBorder ) |
| // don't draw the text over the border |
| lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); |
| |
| // leave a space of one pixel between the "surroundings" of the control |
| // and the content |
| lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); |
| lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() ); |
| |
| // actually draw the content |
| m_pEngine->Draw( _pDev, aPlayground, Point(), sal_True ); |
| |
| _pDev->Pop(); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::SetBackgroundColor( ) |
| { |
| SetBackgroundColor( Application::GetSettings().GetStyleSettings().GetFieldColor() ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::SetBackgroundColor( const Color& _rColor ) |
| { |
| Wallpaper aWallpaper( _rColor ); |
| m_pAntiImpl->SetBackground( aWallpaper ); |
| m_pViewport->SetBackground( aWallpaper ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void RichTextControlImpl::SetHideInactiveSelection( bool _bHide ) |
| { |
| m_pViewport->SetHideInactiveSelection( _bHide ); |
| } |
| |
| //-------------------------------------------------------------------- |
| bool RichTextControlImpl::GetHideInactiveSelection() const |
| { |
| return m_pViewport->GetHideInactiveSelection( ); |
| } |
| |
| //........................................................................ |
| } // namespace frm |
| //........................................................................ |
| |