INTEGRATION: CWS frmcontrols03 (1.1.2); FILE ADDED
2004/03/19 10:03:47 fs 1.1.2.12: wheel scrolling 2004/03/02 15:39:46 fs 1.1.2.11: layout slightly changed 2004/03/01 16:51:45 fs 1.1.2.10: merging the rich text control with the edit control 2004/02/26 07:31:45 fs 1.1.2.9: VCL cleanup after resync 2004/02/26 06:10:44 fs 1.1.2.8: draw a border when printing 2004/02/25 18:53:12 fs 1.1.2.7: 1-pixel-gap between control border and viewport - loks better 2004/02/25 17:04:15 fs 1.1.2.6: #i24387# reference device handling 2004/02/25 16:17:11 fs 1.1.2.5: #i24387# changes for drawing the control onto ordinary output devices 2004/02/23 17:11:21 fs 1.1.2.4: #i24387# some more implementations (mainly CJK relevant) 2004/02/23 11:35:43 fs 1.1.2.3: some more implementations (mainly CJK relevant) 2004/02/19 11:17:58 fs 1.1.2.2: refined some bits - proper scroll and word break handling now 2004/02/18 15:27:17 fs 1.1.2.1: impl class for a rich text VCL control
This commit is contained in:
711
forms/source/richtext/richtextimplcontrol.cxx
Normal file
711
forms/source/richtext/richtextimplcontrol.cxx
Normal file
@@ -0,0 +1,711 @@
|
||||
/*************************************************************************
|
||||
*
|
||||
* $RCSfile: richtextimplcontrol.cxx,v $
|
||||
*
|
||||
* $Revision: 1.2 $
|
||||
*
|
||||
* last change: $Author: rt $ $Date: 2004-05-07 16:13:04 $
|
||||
*
|
||||
* The Contents of this file are made available subject to the terms of
|
||||
* either of the following licenses
|
||||
*
|
||||
* - GNU Lesser General Public License Version 2.1
|
||||
* - Sun Industry Standards Source License Version 1.1
|
||||
*
|
||||
* Sun Microsystems Inc., October, 2000
|
||||
*
|
||||
* GNU Lesser General Public License Version 2.1
|
||||
* =============================================
|
||||
* Copyright 2000 by Sun Microsystems, Inc.
|
||||
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
* Sun Industry Standards Source License Version 1.1
|
||||
* =================================================
|
||||
* The contents of this file are subject to the Sun Industry Standards
|
||||
* Source License Version 1.1 (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.openoffice.org/license.html.
|
||||
*
|
||||
* Software provided under this License is provided on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
||||
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
||||
* See the License for the specific provisions governing your rights and
|
||||
* obligations concerning the Software.
|
||||
*
|
||||
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
||||
*
|
||||
* Copyright: 2000 by Sun Microsystems, Inc.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): _______________________________________
|
||||
*
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTIMPLCONTOL_HXX
|
||||
#include "richtextimplcontrol.hxx"
|
||||
#endif
|
||||
#ifndef FORMS_SOURCE_RICHTEXT_TEXTATTRIBUTELISTENER_HXX
|
||||
#include "textattributelistener.hxx"
|
||||
#endif
|
||||
#ifndef FORMS_SOURCE_RICHTEXT_RICHTEXTENGINE_HXX
|
||||
#include "richtextengine.hxx"
|
||||
#endif
|
||||
|
||||
#ifndef _MyEDITENG_HXX
|
||||
#include <svx/editeng.hxx>
|
||||
#endif
|
||||
#ifndef _MyEDITVIEW_HXX
|
||||
#include <svx/editview.hxx>
|
||||
#endif
|
||||
#ifndef _EEITEM_HXX
|
||||
#include <svx/eeitem.hxx>
|
||||
#endif
|
||||
#ifndef _EDITSTAT_HXX
|
||||
#include <svx/editstat.hxx>
|
||||
#endif
|
||||
#ifndef _SVX_SVXIDS_HRC
|
||||
#include <svx/svxids.hrc>
|
||||
#endif
|
||||
#ifndef _SVX_SCRIPTTYPEITEM_HXX
|
||||
#include <svx/scripttypeitem.hxx>
|
||||
#endif
|
||||
|
||||
#include <svx/editobj.hxx>
|
||||
|
||||
#ifndef _SFXITEMPOOL_HXX
|
||||
#include <svtools/itempool.hxx>
|
||||
#endif
|
||||
#ifndef _SFXITEMSET_HXX
|
||||
#include <svtools/itemset.hxx>
|
||||
#endif
|
||||
|
||||
#ifndef _VCL_MAPUNIT_HXX
|
||||
#include <vcl/mapunit.hxx>
|
||||
#endif
|
||||
#ifndef _SV_WINDOW_HXX
|
||||
#include <vcl/window.hxx>
|
||||
#endif
|
||||
#ifndef _SV_SVAPP_HXX
|
||||
#include <vcl/svapp.hxx>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define EMPTY_PAPER_SIZE 0x7FFFFFFF
|
||||
|
||||
//........................................................................
|
||||
namespace frm
|
||||
{
|
||||
//........................................................................
|
||||
//====================================================================
|
||||
//= RichTextControlImpl
|
||||
//====================================================================
|
||||
//--------------------------------------------------------------------
|
||||
RichTextControlImpl::RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener )
|
||||
:m_pAntiImpl ( _pAntiImpl )
|
||||
,m_pEngine ( _pEngine )
|
||||
,m_pTextAttrListener ( _pTextAttrListener )
|
||||
,m_pSelectionListener ( _pSelectionListener )
|
||||
,m_pView ( NULL )
|
||||
,m_pViewport ( NULL )
|
||||
,m_pScrollCorner ( NULL )
|
||||
,m_pHScroll ( NULL )
|
||||
,m_pVScroll ( NULL )
|
||||
,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 );
|
||||
|
||||
{
|
||||
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(), 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 )
|
||||
{
|
||||
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, 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 );
|
||||
|
||||
// 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( OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode ) );
|
||||
Size aSize( OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode ) );
|
||||
|
||||
Rectangle aPlayground( aPos, aSize );
|
||||
Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) );
|
||||
|
||||
if ( m_pAntiImpl->GetStyle() & WB_BORDER )
|
||||
{
|
||||
// let's draw a border
|
||||
_pDev->SetLineColor( COL_BLACK );
|
||||
_pDev->DrawRect( aPlayground );
|
||||
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() );
|
||||
|
||||
m_pEngine->Draw( _pDev, aPlayground, Point(), TRUE );
|
||||
|
||||
#ifdef DEBUG_DRAW_CONTROL
|
||||
_pDev->SetLineColor( COL_LIGHTRED );
|
||||
_pDev->DrawRect( Rectangle( aPlayground.TopLeft(), m_pEngine->GetPaperSize()) );
|
||||
#endif
|
||||
|
||||
_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 );
|
||||
}
|
||||
|
||||
//........................................................................
|
||||
} // namespace frm
|
||||
//........................................................................
|
||||
|
||||
Reference in New Issue
Block a user