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