/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 .
*/
// 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 );
// ensure that it's initially scrolled to the upper left
m_pView->SetVisArea( tools::Rectangle( Point( ), m_pViewport->GetOutDev()->GetOutputSize() ) );
void RichTextControlImpl::implUpdateAttribute( const AttributeHandlerPool::const_iterator& _pHandler )
{ if ( ( _pHandler->first == sal_uInt16(SID_ATTR_CHAR_WEIGHT) )
|| ( _pHandler->first == sal_uInt16(SID_ATTR_CHAR_POSTURE) )
|| ( _pHandler->first == sal_uInt16(SID_ATTR_CHAR_FONT) )
|| ( _pHandler->first == sal_uInt16(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 useful 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( static_cast<WhichId>(_pHandler->first), *m_pView->GetAttribs().GetPool() );
normalizeScriptDependentAttribute( aNormalizedSet );
// notify changes of the selection, if necessary if ( m_pSelectionListener && m_pView )
{
ESelection aCurrentSelection = m_pView->GetSelection(); if ( aCurrentSelection != m_aLastKnownSelection )
{
m_aLastKnownSelection = aCurrentSelection;
m_pSelectionListener->onSelectionChanged();
}
}
}
AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const
{
StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId ); if ( aCachedStatePos == m_aLastKnownStates.end() )
{
OSL_FAIL( "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, SvtScriptType _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 ); returntrue;
} returnfalse;
}
void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener )
{
AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId ); if ( aHandlerPos == m_aAttributeHandlers.end() )
{
::rtl::Reference< AttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() );
OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" ); if ( !aHandler.is() ) return;
SAL_WARN_IF( _nAttributeId != aHandler->getAttributeId(), "forms.richtext", "RichTextControlImpl::enableAttributeNotification: suspicious handler!" );
// remember the listener if ( _pListener )
m_aAttributeListeners.emplace( _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::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.emplace( _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 );
// call our global listener, if there is one if ( m_pTextAttrListener )
m_pTextAttrListener->onAttributeStateChanged( _nAttribute );
}
// In case of *no* automatic line breaks, we also need to check for the *range* here. // Normally, we would do this only after an EditStatusFlags::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 definitely 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() );
}
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;
// 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.setWidth( ::std::max( tools::Long( 10 ), tools::Long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) ) );
aViewportPlaygroundPixel.setHeight( ::std::max( tools::Long( 10 ), tools::Long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) ) );
Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) );
// position the viewport
m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel ); // position the scrollbars if ( m_pVScroll )
{
m_pVScroll->SetThickness(nScrollBarWidth);
m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) );
} if ( m_pHScroll )
{
m_pHScroll->SetThickness(nScrollBarHeight);
m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) );
}
// paper size if ( windowHasAutomaticLineBreak() )
m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) );
// output area of the view
m_pView->SetOutputArea( tools::Rectangle( Point( ), aViewportSizeLogic ) );
m_pView->SetVisArea( tools::Rectangle( Point( ), aViewportSizeLogic ) );
if ( m_pVScroll )
{
m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() );
// the default height of a text line...
tools::Long nFontHeight = m_pEngine->GetStandardFont(0).GetFontSize().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() );
tools::Long nFontWidth = m_pEngine->GetStandardFont(0).GetFontSize().Width(); if ( !nFontWidth )
{
m_pViewport->GetOutDev()->Push( vcl::PushFlags::FONT );
m_pViewport->SetFont( m_pEngine->GetStandardFont(0) );
nFontWidth = m_pViewport->GetTextWidth( u"x"_ustr );
m_pViewport->GetOutDev()->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::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize )
{ // need to normalize the map mode of the device - every paint operation on any device needs // to use the same map mode
_pDev->Push( vcl::PushFlags::MAPMODE | vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
// 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 two pixels 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(), true);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.20Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.