Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "richtextimplcontrol.hxx"
30 : : #include "textattributelistener.hxx"
31 : : #include "richtextengine.hxx"
32 : : #include <editeng/editeng.hxx>
33 : : #include <editeng/editview.hxx>
34 : : #include <editeng/eeitem.hxx>
35 : : #include <editeng/editstat.hxx>
36 : : #include <svx/svxids.hrc>
37 : : #include <editeng/scripttypeitem.hxx>
38 : :
39 : : #include <editeng/editobj.hxx>
40 : : #include <svl/itempool.hxx>
41 : : #include <svl/itemset.hxx>
42 : : #include <tools/mapunit.hxx>
43 : : #include <vcl/window.hxx>
44 : : #include <vcl/svapp.hxx>
45 : :
46 : : #include <memory>
47 : :
48 : : #define EMPTY_PAPER_SIZE 0x7FFFFFFF
49 : :
50 : : //........................................................................
51 : : namespace frm
52 : : {
53 : : //........................................................................
54 : : //====================================================================
55 : : //= RichTextControlImpl
56 : : //====================================================================
57 : : //--------------------------------------------------------------------
58 : 40 : RichTextControlImpl::RichTextControlImpl( Control* _pAntiImpl, RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttrListener, ITextSelectionListener* _pSelectionListener )
59 : : :m_pAntiImpl ( _pAntiImpl )
60 : : ,m_pViewport ( NULL )
61 : : ,m_pHScroll ( NULL )
62 : : ,m_pVScroll ( NULL )
63 : : ,m_pScrollCorner ( NULL )
64 : : ,m_pEngine ( _pEngine )
65 : : ,m_pView ( NULL )
66 : : ,m_pTextAttrListener ( _pTextAttrListener )
67 : : ,m_pSelectionListener ( _pSelectionListener )
68 [ + - ][ + - ]: 40 : ,m_bHasEverBeenShown ( false )
[ + - ]
69 : : {
70 : : OSL_ENSURE( m_pAntiImpl, "RichTextControlImpl::RichTextControlImpl: invalid window!" );
71 : : OSL_ENSURE( m_pEngine, "RichTextControlImpl::RichTextControlImpl: invalid edit engine! This will *definately* crash!" );
72 : :
73 [ + - ][ + - ]: 40 : m_pViewport = new RichTextViewPort( m_pAntiImpl );
74 [ + - ]: 40 : m_pViewport->setAttributeInvalidationHandler( LINK( this, RichTextControlImpl, OnInvalidateAllAttributes ) );
75 [ + - ]: 40 : m_pViewport->Show();
76 : :
77 : : // ensure that both the window and the reference device have the same map unit
78 [ + - ][ + - ]: 40 : MapMode aRefDeviceMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
79 [ + - ]: 40 : m_pAntiImpl->SetMapMode( aRefDeviceMapMode );
80 [ + - ]: 40 : m_pViewport->SetMapMode( aRefDeviceMapMode );
81 : :
82 [ + - ][ + - ]: 40 : m_pView = new EditView( m_pEngine, m_pViewport );
83 [ + - ]: 40 : m_pEngine->InsertView( m_pView );
84 [ + - ]: 40 : m_pViewport->setView( *m_pView );
85 : :
86 [ + - ]: 40 : m_pEngine->registerEngineStatusListener( this );
87 : :
88 : : {
89 [ + - ]: 40 : sal_uLong nViewControlWord = m_pView->GetControlWord();
90 : 40 : nViewControlWord |= EV_CNTRL_AUTOSCROLL;
91 [ + - ]: 40 : m_pView->SetControlWord( nViewControlWord );
92 : : }
93 : :
94 : : // ensure that it's initially scrolled to the upper left
95 [ + - ][ + - ]: 40 : m_pView->SetVisArea( Rectangle( Point( ), m_pViewport->GetOutputSize() ) );
[ + - ]
96 : :
97 [ + - ]: 40 : ensureScrollbars();
98 : :
99 [ + - ][ + - ]: 40 : m_pAntiImpl->SetBackground( Wallpaper( m_pAntiImpl->GetSettings().GetStyleSettings().GetFieldColor() ) );
[ + - ][ + - ]
100 : 40 : }
101 : :
102 : : //--------------------------------------------------------------------
103 : 40 : RichTextControlImpl::~RichTextControlImpl( )
104 : : {
105 [ + - ]: 40 : m_pEngine->RemoveView( m_pView );
106 [ + - ]: 40 : m_pEngine->revokeEngineStatusListener( this );
107 [ + - ][ + - ]: 40 : delete m_pView;
108 [ + - ][ + - ]: 40 : delete m_pViewport;
109 [ + + ][ + - ]: 40 : delete m_pHScroll;
110 [ + + ][ + - ]: 40 : delete m_pVScroll;
111 [ + + ][ + - ]: 40 : delete m_pScrollCorner;
112 [ - + ]: 80 : }
113 : :
114 : : //--------------------------------------------------------------------
115 : 0 : void RichTextControlImpl::implUpdateAttribute( AttributeHandlerPool::const_iterator _pHandler )
116 : : {
117 [ # # # # : 0 : if ( ( _pHandler->first == SID_ATTR_CHAR_WEIGHT )
# # # # ]
[ # # ]
118 : 0 : || ( _pHandler->first == SID_ATTR_CHAR_POSTURE )
119 : 0 : || ( _pHandler->first == SID_ATTR_CHAR_FONT )
120 : 0 : || ( _pHandler->first == SID_ATTR_CHAR_FONTHEIGHT )
121 : : )
122 : : {
123 : : // these are attributes whose value depends on the current script type.
124 : : // I.e., in real, there are *three* items in the ItemSet: One for each script
125 : : // type (Latin, Asian, Complex). However, if we have an observer who is interested
126 : : // in the state of this attribute, we have to kind of *merge* the three attributes
127 : : // to only one.
128 : : // This is usefull in case the observer is for instance a toolbox which contains only
129 : : // an, e.g., "bold" slot, and thus not interested in the particular script type of the
130 : : // current selection.
131 [ # # ][ # # ]: 0 : SvxScriptSetItem aNormalizedSet( (WhichId)_pHandler->first, *m_pView->GetAttribs().GetPool() );
[ # # ]
132 [ # # ]: 0 : normalizeScriptDependentAttribute( aNormalizedSet );
133 : :
134 [ # # ][ # # ]: 0 : implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( aNormalizedSet.GetItemSet() ) );
[ # # ]
135 : : }
136 : : else
137 [ # # ][ # # ]: 0 : implCheckUpdateCache( _pHandler->first, _pHandler->second->getState( m_pView->GetAttribs() ) );
138 : 0 : }
139 : :
140 : : //--------------------------------------------------------------------
141 : 0 : void RichTextControlImpl::updateAttribute( AttributeId _nAttribute )
142 : : {
143 [ # # ]: 0 : AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.find( _nAttribute );
144 [ # # ]: 0 : if ( pHandler != m_aAttributeHandlers.end() )
145 [ # # ]: 0 : implUpdateAttribute( pHandler );
146 : 0 : }
147 : :
148 : : //--------------------------------------------------------------------
149 : 0 : void RichTextControlImpl::updateAllAttributes( )
150 : : {
151 [ # # ]: 0 : for ( AttributeHandlerPool::const_iterator pHandler = m_aAttributeHandlers.begin();
152 : 0 : pHandler != m_aAttributeHandlers.end();
153 : : ++pHandler
154 : : )
155 : : {
156 [ # # ]: 0 : implUpdateAttribute( pHandler );
157 : : }
158 : :
159 : : // notify changes of the selection, if necessary
160 [ # # ][ # # ]: 0 : if ( m_pSelectionListener && m_pView )
161 : : {
162 [ # # ]: 0 : ESelection aCurrentSelection = m_pView->GetSelection();
163 [ # # ]: 0 : if ( !aCurrentSelection.IsEqual( m_aLastKnownSelection ) )
164 : : {
165 : 0 : m_aLastKnownSelection = aCurrentSelection;
166 [ # # ]: 0 : m_pSelectionListener->onSelectionChanged( m_aLastKnownSelection );
167 : : }
168 : : }
169 : 0 : }
170 : :
171 : : //--------------------------------------------------------------------
172 : 0 : AttributeState RichTextControlImpl::getAttributeState( AttributeId _nAttributeId ) const
173 : : {
174 [ # # ]: 0 : StateCache::const_iterator aCachedStatePos = m_aLastKnownStates.find( _nAttributeId );
175 [ # # ]: 0 : if ( aCachedStatePos == m_aLastKnownStates.end() )
176 : : {
177 : : OSL_FAIL( "RichTextControlImpl::getAttributeState: Don't ask for the state of an attribute which I never encountered!" );
178 : 0 : return AttributeState( eIndetermined );
179 : : }
180 [ # # ]: 0 : return aCachedStatePos->second;
181 : : }
182 : :
183 : : //--------------------------------------------------------------------
184 : 0 : bool RichTextControlImpl::executeAttribute( const SfxItemSet& _rCurrentAttribs, SfxItemSet& _rAttribs, AttributeId _nAttribute, const SfxPoolItem* _pArgument, ScriptType _nForScriptType )
185 : : {
186 : : // let's see whether we have a handler for this attribute
187 [ # # ]: 0 : AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttribute );
188 [ # # ]: 0 : if ( aHandlerPos != m_aAttributeHandlers.end() )
189 : : {
190 [ # # ]: 0 : aHandlerPos->second->executeAttribute( _rCurrentAttribs, _rAttribs, _pArgument, _nForScriptType );
191 : 0 : return true;
192 : : }
193 : 0 : return false;
194 : : }
195 : :
196 : : //--------------------------------------------------------------------
197 : 0 : void RichTextControlImpl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener )
198 : : {
199 [ # # ]: 0 : AttributeHandlerPool::const_iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId );
200 [ # # ]: 0 : if ( aHandlerPos == m_aAttributeHandlers.end() )
201 : : {
202 [ # # ][ # # ]: 0 : ::rtl::Reference< IAttributeHandler > aHandler = AttributeHandlerFactory::getHandlerFor( _nAttributeId, *m_pEngine->GetEmptyItemSet().GetPool() );
203 : : OSL_ENSURE( aHandler.is(), "RichTextControlImpl::enableAttributeNotification: no handler available for this attribute!" );
204 [ # # ]: 0 : if ( !aHandler.is() )
205 : 0 : return;
206 : : OSL_POSTCOND( _nAttributeId == aHandler->getAttributeId(), "RichTextControlImpl::enableAttributeNotification: suspicious handler!" );
207 : :
208 [ # # ][ # # ]: 0 : aHandlerPos = m_aAttributeHandlers.insert( AttributeHandlerPool::value_type( _nAttributeId , aHandler ) ).first;
[ # # ][ # # ]
[ # # ]
209 : : }
210 : :
211 : : // remember the listener
212 [ # # ]: 0 : if ( _pListener )
213 [ # # ]: 0 : m_aAttributeListeners.insert( AttributeListenerPool::value_type( _nAttributeId, _pListener ) );
214 : :
215 : : // update (and broadcast) the state of this attribute
216 [ # # ]: 0 : updateAttribute( _nAttributeId );
217 : : }
218 : :
219 : : //--------------------------------------------------------------------
220 : 0 : void RichTextControlImpl::disableAttributeNotification( AttributeId _nAttributeId )
221 : : {
222 : : // forget the handler for this attribute
223 [ # # ]: 0 : AttributeHandlerPool::iterator aHandlerPos = m_aAttributeHandlers.find( _nAttributeId );
224 [ # # ]: 0 : if ( aHandlerPos != m_aAttributeHandlers.end() )
225 [ # # ]: 0 : m_aAttributeHandlers.erase( aHandlerPos );
226 : :
227 : : // as well as the listener
228 [ # # ]: 0 : AttributeListenerPool::iterator aListenerPos = m_aAttributeListeners.find( _nAttributeId );
229 [ # # ]: 0 : if ( aListenerPos != m_aAttributeListeners.end() )
230 [ # # ]: 0 : m_aAttributeListeners.erase( aListenerPos );
231 : 0 : }
232 : :
233 : : //--------------------------------------------------------------------
234 : 0 : void RichTextControlImpl::normalizeScriptDependentAttribute( SvxScriptSetItem& _rScriptSetItem )
235 : : {
236 [ # # ]: 0 : _rScriptSetItem.GetItemSet().Put( m_pView->GetAttribs(), sal_False );
237 : 0 : const SfxPoolItem* pNormalizedItem = _rScriptSetItem.GetItemOfScript( getSelectedScriptType() );
238 : :
239 : 0 : WhichId nNormalizedWhichId = _rScriptSetItem.GetItemSet().GetPool()->GetWhich( _rScriptSetItem.Which() );
240 [ # # ]: 0 : if ( pNormalizedItem )
241 : : {
242 : 0 : SfxPoolItem* pProperWhich = pNormalizedItem->Clone();
243 : 0 : pProperWhich->SetWhich( nNormalizedWhichId );
244 : 0 : _rScriptSetItem.GetItemSet().Put( *pProperWhich );
245 [ # # ]: 0 : DELETEZ( pProperWhich );
246 : : }
247 : : else
248 : 0 : _rScriptSetItem.GetItemSet().InvalidateItem( nNormalizedWhichId );
249 : 0 : }
250 : :
251 : : //--------------------------------------------------------------------
252 : 0 : void RichTextControlImpl::implCheckUpdateCache( AttributeId _nAttribute, const AttributeState& _rState )
253 : : {
254 [ # # ]: 0 : StateCache::iterator aCachePos = m_aLastKnownStates.find( _nAttribute );
255 [ # # ]: 0 : if ( aCachePos == m_aLastKnownStates.end() )
256 : : { // nothing known about this attribute, yet
257 [ # # ][ # # ]: 0 : m_aLastKnownStates.insert( StateCache::value_type( _nAttribute, _rState ) );
258 : : }
259 : : else
260 : : {
261 [ # # ][ # # ]: 0 : if ( aCachePos->second == _rState )
262 : : {
263 : : // nothing to do
264 : 0 : return;
265 : : }
266 [ # # ]: 0 : aCachePos->second = _rState;
267 : : }
268 : :
269 : : // is there a dedicated listener for this particular attribute?
270 [ # # ]: 0 : AttributeListenerPool::const_iterator aListenerPos = m_aAttributeListeners.find( _nAttribute );
271 [ # # ]: 0 : if ( aListenerPos != m_aAttributeListeners.end( ) )
272 [ # # ]: 0 : aListenerPos->second->onAttributeStateChanged( _nAttribute, _rState );
273 : :
274 : : // call our global listener, if there is one
275 [ # # ]: 0 : if ( m_pTextAttrListener )
276 [ # # ]: 0 : m_pTextAttrListener->onAttributeStateChanged( _nAttribute, _rState );
277 : : }
278 : :
279 : : //--------------------------------------------------------------------
280 : 0 : ScriptType RichTextControlImpl::getSelectedScriptType() const
281 : : {
282 : 0 : ScriptType nScript = m_pView->GetSelectedScriptType();
283 [ # # ]: 0 : if ( !nScript )
284 : 0 : nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() );
285 : 0 : return nScript;
286 : : }
287 : :
288 : : //--------------------------------------------------------------------
289 : 0 : void RichTextControlImpl::EditEngineStatusChanged( const EditStatus& _rStatus )
290 : : {
291 : 0 : sal_uLong nStatusWord( _rStatus.GetStatusWord() );
292 [ # # ][ # # ]: 0 : if ( ( nStatusWord & EE_STAT_TEXTWIDTHCHANGED )
293 : : || ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED )
294 : : )
295 : : {
296 [ # # ][ # # ]: 0 : if ( ( nStatusWord & EE_STAT_TEXTHEIGHTCHANGED ) && windowHasAutomaticLineBreak() )
[ # # ]
297 [ # # ]: 0 : m_pEngine->SetPaperSize( Size( m_pEngine->GetPaperSize().Width(), m_pEngine->GetTextHeight() ) );
298 : :
299 : 0 : updateScrollbars();
300 : : }
301 : :
302 : 0 : bool bHScroll = 0 != ( nStatusWord & EE_STAT_HSCROLL );
303 : 0 : bool bVScroll = 0 != ( nStatusWord & EE_STAT_VSCROLL );
304 : :
305 : : // In case of *no* automatic line breaks, we also need to check for the *range* here.
306 : : // Normally, we would do this only after a EE_STAT_TEXTWIDTHCHANGED. However, due to a bug
307 : : // in the EditEngine (I believe so) this is not fired when the engine does not have
308 : : // the AutoPaperSize bits set.
309 : : // So in order to be properly notified, we would need the AutoPaperSize. But, with
310 : : // AutoPaperSize, other things do not work anymore: Either, when we set a MaxAutoPaperSize,
311 : : // then the view does automatic soft line breaks at the paper end - which we definately do
312 : : // want. Or, if we did not set a MaxAutoPaperSize, then the view does not automatically scroll
313 : : // anymore in horizontal direction.
314 : : // So this is some kind of lose-lose situation ... :(
315 [ # # ][ # # ]: 0 : if ( !windowHasAutomaticLineBreak() && bHScroll )
[ # # ]
316 : : {
317 : 0 : updateScrollbars();
318 : 0 : return;
319 : : }
320 : :
321 [ # # ][ # # ]: 0 : if ( bHScroll && m_pHScroll )
322 : 0 : m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
323 [ # # ][ # # ]: 0 : if ( bVScroll && m_pVScroll )
324 : 0 : m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
325 : : }
326 : :
327 : : //--------------------------------------------------------------------
328 : 0 : IMPL_LINK( RichTextControlImpl, OnInvalidateAllAttributes, void*, /*_pNotInterestedIn*/ )
329 : : {
330 : 0 : updateAllAttributes();
331 : 0 : return 0L;
332 : : }
333 : :
334 : : //--------------------------------------------------------------------
335 : 0 : IMPL_LINK( RichTextControlImpl, OnHScroll, ScrollBar*, _pScrollbar )
336 : : {
337 : 0 : m_pView->Scroll( -_pScrollbar->GetDelta(), 0, RGCHK_PAPERSZ1 );
338 : 0 : return 0L;
339 : : }
340 : :
341 : : //--------------------------------------------------------------------
342 : 0 : IMPL_LINK( RichTextControlImpl, OnVScroll, ScrollBar*, _pScrollbar )
343 : : {
344 : 0 : m_pView->Scroll( 0, -_pScrollbar->GetDelta(), RGCHK_PAPERSZ1 );
345 : 0 : return 0L;
346 : : }
347 : :
348 : : //--------------------------------------------------------------------
349 : 128 : void RichTextControlImpl::ensureScrollbars()
350 : : {
351 : 128 : bool bNeedVScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_VSCROLL );
352 : 128 : bool bNeedHScroll = 0 != ( m_pAntiImpl->GetStyle() & WB_HSCROLL );
353 : :
354 [ + + ][ + + ]: 128 : if ( ( bNeedVScroll == hasVScrollBar() ) && ( bNeedHScroll == hasHScrollBar( ) ) )
[ + + ]
355 : : // nothing to do
356 : 128 : return;
357 : :
358 : : // create or delete the scrollbars, as necessary
359 [ + + ]: 30 : if ( !bNeedVScroll )
360 : : {
361 [ - + ]: 10 : delete m_pVScroll;
362 : 10 : m_pVScroll = NULL;
363 : : }
364 : : else
365 : : {
366 [ + - ]: 20 : m_pVScroll = new ScrollBar( m_pAntiImpl, WB_VSCROLL | WB_DRAG | WB_REPEAT );
367 : 20 : m_pVScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnVScroll ) );
368 : 20 : m_pVScroll->Show();
369 : : }
370 : :
371 [ + + ]: 30 : if ( !bNeedHScroll )
372 : : {
373 [ - + ]: 12 : delete m_pHScroll;
374 : 12 : m_pHScroll = NULL;
375 : : }
376 : : else
377 : : {
378 [ + - ]: 18 : m_pHScroll = new ScrollBar( m_pAntiImpl, WB_HSCROLL | WB_DRAG | WB_REPEAT );
379 : 18 : m_pHScroll->SetScrollHdl ( LINK( this, RichTextControlImpl, OnHScroll ) );
380 : 18 : m_pHScroll->Show();
381 : : }
382 : :
383 [ + + ][ + + ]: 30 : if ( m_pHScroll && m_pVScroll )
384 : : {
385 [ - + ]: 8 : delete m_pScrollCorner;
386 [ + - ]: 8 : m_pScrollCorner = new ScrollBarBox( m_pAntiImpl );
387 : 8 : m_pScrollCorner->Show();
388 : : }
389 : : else
390 : : {
391 [ - + ]: 22 : delete m_pScrollCorner;
392 : 22 : m_pScrollCorner = NULL;
393 : : }
394 : :
395 : 30 : layoutWindow();
396 : : }
397 : :
398 : : //--------------------------------------------------------------------
399 : 88 : void RichTextControlImpl::ensureLineBreakSetting()
400 : : {
401 [ + + ]: 88 : if ( !windowHasAutomaticLineBreak() )
402 [ + - ]: 44 : m_pEngine->SetPaperSize( Size( EMPTY_PAPER_SIZE, EMPTY_PAPER_SIZE ) );
403 : :
404 : 88 : layoutWindow();
405 : 88 : }
406 : :
407 : : //--------------------------------------------------------------------
408 : 118 : void RichTextControlImpl::layoutWindow()
409 : : {
410 [ - + ]: 118 : if ( !m_bHasEverBeenShown )
411 : : // no need to do anything. Especially, no need to set the paper size on the
412 : : // EditEngine to anything ....
413 : 118 : return;
414 : :
415 : 0 : const StyleSettings& rStyleSettings = m_pAntiImpl->GetSettings().GetStyleSettings();
416 : :
417 [ # # ]: 0 : long nScrollBarWidth = m_pVScroll ? rStyleSettings.GetScrollBarSize() : 0;
418 [ # # ]: 0 : long nScrollBarHeight = m_pHScroll ? rStyleSettings.GetScrollBarSize() : 0;
419 : :
420 [ # # ][ # # ]: 0 : if ( m_pAntiImpl->IsZoom() )
421 : : {
422 [ # # ]: 0 : nScrollBarWidth = m_pAntiImpl->CalcZoom( nScrollBarWidth );
423 [ # # ]: 0 : nScrollBarHeight = m_pAntiImpl->CalcZoom( nScrollBarHeight );
424 : : }
425 : :
426 : : // the overall size we can use
427 : 0 : Size aPlaygroundSizePixel( m_pAntiImpl->GetOutputSizePixel() );
428 : :
429 : : // the size of the viewport - note that the viewport does *not* occupy all the place
430 : : // which is left when subtracting the scrollbar width/height
431 : 0 : Size aViewportPlaygroundPixel( aPlaygroundSizePixel );
432 [ # # ]: 0 : aViewportPlaygroundPixel.Width() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Width() - nScrollBarWidth ) );
433 [ # # ]: 0 : aViewportPlaygroundPixel.Height() = ::std::max( long( 10 ), long( aViewportPlaygroundPixel.Height() - nScrollBarHeight ) );
434 [ # # ]: 0 : Size aViewportPlaygroundLogic( m_pViewport->PixelToLogic( aViewportPlaygroundPixel ) );
435 : :
436 : 0 : const long nOffset = 2;
437 : 0 : Size aViewportSizePixel( aViewportPlaygroundPixel.Width() - 2 * nOffset, aViewportPlaygroundPixel.Height() - 2 * nOffset );
438 [ # # ]: 0 : Size aViewportSizeLogic( m_pViewport->PixelToLogic( aViewportSizePixel ) );
439 : :
440 : : // position the viewport
441 [ # # ]: 0 : m_pViewport->SetPosSizePixel( Point( nOffset, nOffset ), aViewportSizePixel );
442 : : // position the scrollbars
443 [ # # ]: 0 : if ( m_pVScroll )
444 [ # # ]: 0 : m_pVScroll->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), 0 ), Size( nScrollBarWidth, aViewportPlaygroundPixel.Height() ) );
445 [ # # ]: 0 : if ( m_pHScroll )
446 [ # # ]: 0 : m_pHScroll->SetPosSizePixel( Point( 0, aViewportPlaygroundPixel.Height() ), Size( aViewportPlaygroundPixel.Width(), nScrollBarHeight ) );
447 [ # # ]: 0 : if ( m_pScrollCorner )
448 [ # # ]: 0 : m_pScrollCorner->SetPosSizePixel( Point( aViewportPlaygroundPixel.Width(), aViewportPlaygroundPixel.Height() ), Size( nScrollBarWidth, nScrollBarHeight ) );
449 : :
450 : : // paper size
451 [ # # ][ # # ]: 0 : if ( windowHasAutomaticLineBreak() )
452 [ # # ][ # # ]: 0 : m_pEngine->SetPaperSize( Size( aViewportSizeLogic.Width(), m_pEngine->GetTextHeight() ) );
453 : :
454 : : // output area of the view
455 [ # # ][ # # ]: 0 : m_pView->SetOutputArea( Rectangle( Point( ), aViewportSizeLogic ) );
456 [ # # ][ # # ]: 0 : m_pView->SetVisArea( Rectangle( Point( ), aViewportSizeLogic ) );
457 : :
458 [ # # ]: 0 : if ( m_pVScroll )
459 : : {
460 [ # # ]: 0 : m_pVScroll->SetVisibleSize( aViewportPlaygroundLogic.Height() );
461 : :
462 : : // the default height of a text line ....
463 [ # # ][ # # ]: 0 : long nFontHeight = m_pEngine->GetStandardFont(0).GetSize().Height();
[ # # ]
464 : : // ... is the scroll size for the vertical scrollbar
465 : 0 : m_pVScroll->SetLineSize( nFontHeight );
466 : : // the viewport width, minus one line, is the page scroll size
467 [ # # ]: 0 : m_pVScroll->SetPageSize( ::std::max( nFontHeight, aViewportPlaygroundLogic.Height() - nFontHeight ) );
468 : : }
469 : :
470 : : // the font width
471 [ # # ]: 0 : if ( m_pHScroll )
472 : : {
473 [ # # ]: 0 : m_pHScroll->SetVisibleSize( aViewportPlaygroundLogic.Width() );
474 : :
475 [ # # ][ # # ]: 0 : long nFontWidth = m_pEngine->GetStandardFont(0).GetSize().Width();
[ # # ]
476 [ # # ]: 0 : if ( !nFontWidth )
477 : : {
478 [ # # ]: 0 : m_pViewport->Push( PUSH_FONT );
479 [ # # ][ # # ]: 0 : m_pViewport->SetFont( m_pEngine->GetStandardFont(0) );
[ # # ]
480 [ # # ][ # # ]: 0 : nFontWidth = m_pViewport->GetTextWidth( String( RTL_CONSTASCII_USTRINGPARAM( "x" ) ) );
[ # # ]
481 [ # # ]: 0 : m_pViewport->Pop();
482 : : }
483 : : // ... is the scroll size for the horizontal scrollbar
484 : 0 : m_pHScroll->SetLineSize( 5 * nFontWidth );
485 : : // the viewport height, minus one character, is the page scroll size
486 [ # # ]: 0 : m_pHScroll->SetPageSize( ::std::max( nFontWidth, aViewportPlaygroundLogic.Width() - nFontWidth ) );
487 : : }
488 : :
489 : : // update range and position of the scrollbars
490 [ # # ]: 118 : updateScrollbars();
491 : : }
492 : :
493 : : //--------------------------------------------------------------------
494 : 0 : void RichTextControlImpl::updateScrollbars()
495 : : {
496 [ # # ]: 0 : if ( m_pVScroll )
497 : : {
498 : 0 : long nOverallTextHeight = m_pEngine->GetTextHeight();
499 [ # # ]: 0 : m_pVScroll->SetRange( Range( 0, nOverallTextHeight ) );
500 : 0 : m_pVScroll->SetThumbPos( m_pView->GetVisArea().Top() );
501 : : }
502 : :
503 [ # # ]: 0 : if ( m_pHScroll )
504 : : {
505 [ # # ]: 0 : Size aPaperSize( m_pEngine->GetPaperSize() );
506 [ # # ][ # # ]: 0 : long nOverallTextWidth = ( aPaperSize.Width() == EMPTY_PAPER_SIZE ) ? m_pEngine->CalcTextWidth() : aPaperSize.Width();
507 [ # # ]: 0 : m_pHScroll->SetRange( Range( 0, nOverallTextWidth ) );
508 [ # # ][ # # ]: 0 : m_pHScroll->SetThumbPos( m_pView->GetVisArea().Left() );
509 : : }
510 : 0 : }
511 : :
512 : : //--------------------------------------------------------------------
513 : 0 : void RichTextControlImpl::notifyInitShow()
514 : : {
515 [ # # ]: 0 : if ( !m_bHasEverBeenShown )
516 : : {
517 : 0 : m_bHasEverBeenShown = true;
518 : 0 : layoutWindow();
519 : : }
520 : 0 : }
521 : :
522 : : //--------------------------------------------------------------------
523 : 88 : void RichTextControlImpl::notifyStyleChanged()
524 : : {
525 : 88 : ensureScrollbars();
526 : 88 : ensureLineBreakSetting();
527 : 88 : }
528 : :
529 : : //--------------------------------------------------------------------
530 : 0 : void RichTextControlImpl::notifyZoomChanged()
531 : : {
532 [ # # ]: 0 : const Fraction& rZoom = m_pAntiImpl->GetZoom();
533 : :
534 [ # # ]: 0 : MapMode aMapMode( m_pAntiImpl->GetMapMode() );
535 [ # # ]: 0 : aMapMode.SetScaleX( rZoom );
536 [ # # ]: 0 : aMapMode.SetScaleY( rZoom );
537 [ # # ]: 0 : m_pAntiImpl->SetMapMode( aMapMode );
538 : :
539 [ # # ]: 0 : m_pViewport->SetZoom( rZoom );
540 [ # # ]: 0 : m_pViewport->SetMapMode( aMapMode );
541 : :
542 [ # # ][ # # ]: 0 : layoutWindow();
543 : 0 : }
544 : :
545 : : //--------------------------------------------------------------------
546 : 88 : bool RichTextControlImpl::windowHasAutomaticLineBreak()
547 : : {
548 : 88 : return ( m_pAntiImpl->GetStyle() & WB_WORDBREAK ) != 0;
549 : : }
550 : :
551 : : //--------------------------------------------------------------------
552 : 48 : void RichTextControlImpl::SetReadOnly( bool _bReadOnly )
553 : : {
554 : 48 : m_pView->SetReadOnly( _bReadOnly );
555 : 48 : }
556 : :
557 : : //--------------------------------------------------------------------
558 : 48 : bool RichTextControlImpl::IsReadOnly() const
559 : : {
560 : 48 : return m_pView->IsReadOnly( );
561 : : }
562 : :
563 : : //--------------------------------------------------------------------
564 : : namespace
565 : : {
566 : 318 : static void lcl_inflate( Rectangle& _rRect, long _nInflateX, long _nInflateY )
567 : : {
568 : 318 : _rRect.Left() -= _nInflateX;
569 : 318 : _rRect.Right() += _nInflateX;
570 : 318 : _rRect.Top() -= _nInflateY;
571 : 318 : _rRect.Bottom() += _nInflateY;
572 : 318 : }
573 : : }
574 : : //--------------------------------------------------------------------
575 : 0 : long RichTextControlImpl::HandleCommand( const CommandEvent& _rEvent )
576 : : {
577 [ # # # # : 0 : if ( ( _rEvent.GetCommand() == COMMAND_WHEEL )
# # ][ # # ]
578 : 0 : || ( _rEvent.GetCommand() == COMMAND_STARTAUTOSCROLL )
579 : 0 : || ( _rEvent.GetCommand() == COMMAND_AUTOSCROLL )
580 : : )
581 : : {
582 : 0 : m_pAntiImpl->HandleScrollCommand( _rEvent, m_pHScroll, m_pVScroll );
583 : 0 : return 1;
584 : : }
585 : 0 : return 0;
586 : : }
587 : :
588 : : //--------------------------------------------------------------------
589 : 106 : void RichTextControlImpl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, sal_uLong /*_nFlags*/ )
590 : : {
591 : : // need to normalize the map mode of the device - every paint operation on any device needs
592 : : // to use the same map mode
593 [ + - ]: 106 : _pDev->Push( PUSH_MAPMODE | PUSH_LINECOLOR | PUSH_FILLCOLOR );
594 : :
595 : : // enforce our "normalize map mode" on the device
596 [ + - ][ + - ]: 106 : MapMode aRefMapMode( m_pEngine->GetRefDevice()->GetMapMode() );
597 [ + - ]: 106 : MapMode aOriginalMapMode( _pDev->GetMapMode() );
598 [ + - ]: 106 : MapMode aNormalizedMapMode( aRefMapMode.GetMapUnit(), aRefMapMode.GetOrigin(), aOriginalMapMode.GetScaleX(), aOriginalMapMode.GetScaleY() );
599 [ + - ]: 106 : _pDev->SetMapMode( aNormalizedMapMode );
600 : :
601 : : // translate coordinates
602 : 106 : Point aPos( _rPos );
603 : 106 : Size aSize( _rSize );
604 [ + - ]: 106 : if ( aOriginalMapMode.GetMapUnit() == MAP_PIXEL )
605 : : {
606 [ + - ]: 106 : aPos = _pDev->PixelToLogic( _rPos, aNormalizedMapMode );
607 [ + - ]: 106 : aSize = _pDev->PixelToLogic( _rSize, aNormalizedMapMode );
608 : : }
609 : : else
610 : : {
611 [ # # ]: 0 : aPos = OutputDevice::LogicToLogic( _rPos, aOriginalMapMode, aNormalizedMapMode );
612 [ # # ]: 0 : aSize = OutputDevice::LogicToLogic( _rSize, aOriginalMapMode, aNormalizedMapMode );
613 : : }
614 : :
615 [ + - ]: 106 : Rectangle aPlayground( aPos, aSize );
616 [ + - ]: 106 : Size aOnePixel( _pDev->PixelToLogic( Size( 1, 1 ) ) );
617 : 106 : aPlayground.Right() -= aOnePixel.Width();
618 : 106 : aPlayground.Bottom() -= aOnePixel.Height();
619 : :
620 : : // background
621 [ + - ]: 106 : _pDev->SetLineColor();
622 [ + - ]: 106 : _pDev->DrawRect( aPlayground );
623 : :
624 : : // do we need to draw a border?
625 [ + - ]: 106 : bool bBorder = ( m_pAntiImpl->GetStyle() & WB_BORDER );
626 [ + - ]: 106 : if ( bBorder )
627 [ + - ]: 106 : _pDev->SetLineColor( m_pAntiImpl->GetSettings().GetStyleSettings().GetMonoColor() );
628 : : else
629 [ # # ]: 0 : _pDev->SetLineColor();
630 [ + - ][ + - ]: 106 : _pDev->SetFillColor( m_pAntiImpl->GetBackground().GetColor() );
631 [ + - ]: 106 : _pDev->DrawRect( aPlayground );
632 : :
633 [ + - ]: 106 : if ( bBorder )
634 : : // don't draw the text over the border
635 : 106 : lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
636 : :
637 : : // leave a space of one pixel between the "surroundings" of the control
638 : : // and the content
639 : 106 : lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
640 : 106 : lcl_inflate( aPlayground, -aOnePixel.Width(), -aOnePixel.Height() );
641 : :
642 : : // actually draw the content
643 [ + - ]: 106 : m_pEngine->Draw( _pDev, aPlayground, Point(), sal_True );
644 : :
645 [ + - ][ + - ]: 106 : _pDev->Pop();
[ + - ][ + - ]
646 : 106 : }
647 : :
648 : : //--------------------------------------------------------------------
649 : 40 : void RichTextControlImpl::SetBackgroundColor( )
650 : : {
651 : 40 : SetBackgroundColor( Application::GetSettings().GetStyleSettings().GetFieldColor() );
652 : 40 : }
653 : :
654 : : //--------------------------------------------------------------------
655 : 40 : void RichTextControlImpl::SetBackgroundColor( const Color& _rColor )
656 : : {
657 [ + - ]: 40 : Wallpaper aWallpaper( _rColor );
658 [ + - ]: 40 : m_pAntiImpl->SetBackground( aWallpaper );
659 [ + - ][ + - ]: 40 : m_pViewport->SetBackground( aWallpaper );
660 : 40 : }
661 : :
662 : : //--------------------------------------------------------------------
663 : 48 : void RichTextControlImpl::SetHideInactiveSelection( bool _bHide )
664 : : {
665 : 48 : m_pViewport->SetHideInactiveSelection( _bHide );
666 : 48 : }
667 : :
668 : : //--------------------------------------------------------------------
669 : 48 : bool RichTextControlImpl::GetHideInactiveSelection() const
670 : : {
671 : 48 : return m_pViewport->GetHideInactiveSelection( );
672 : : }
673 : :
674 : : //........................................................................
675 : : } // namespace frm
676 : : //........................................................................
677 : :
678 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|