Update ooo320-m1
[ooovba.git] / svx / source / unodraw / unoshtxt.cxx
blob75c4d7ab681b241518ea414e9f4afb1a63ecc9cb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unoshtxt.cxx,v $
10 * $Revision: 1.62 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <com/sun/star/uno/XInterface.hpp>
34 #include <vcl/svapp.hxx>
36 #include <svx/unoshtxt.hxx>
37 #include <unoedhlp.hxx>
38 #include <svtools/lstner.hxx>
39 #include <rtl/ref.hxx>
40 #include <osl/mutex.hxx>
41 #include <svtools/hint.hxx>
42 #include <svtools/style.hxx>
43 #include <svx/svdmodel.hxx>
44 #include <svx/svdoutl.hxx>
45 #include <svx/svdobj.hxx>
46 #include <svx/svdview.hxx>
47 #include <svx/svdetc.hxx>
48 #include <svx/outliner.hxx>
49 #include <svx/unoforou.hxx>
50 #include <svx/unoviwou.hxx>
51 #include <svx/outlobj.hxx>
52 #include <svx/svdotext.hxx>
53 #include <svx/svdpage.hxx>
54 #include <svx/editeng.hxx>
55 #include <svx/editobj.hxx>
57 #include <svx/unotext.hxx>
58 #include <com/sun/star/linguistic2/XLinguServiceManager.hpp>
59 #include <comphelper/processfactory.hxx>
60 #include <vos/mutex.hxx>
61 #include <sdrpaintwindow.hxx>
63 using namespace ::osl;
64 using namespace ::vos;
65 using namespace ::rtl;
67 using ::com::sun::star::uno::XInterface;
69 namespace css = ::com::sun::star;
72 //------------------------------------------------------------------------
73 // SvxTextEditSourceImpl
74 //------------------------------------------------------------------------
76 /** @descr
77 <p>This class essentially provides the text and view forwarders. If
78 no SdrView is given, this class handles the UNO objects, which are
79 currently not concerned with view issues. In this case,
80 GetViewForwarder() always returns NULL and the underlying
81 EditEngine of the SvxTextForwarder is a background one (i.e. not
82 the official DrawOutliner, but one created exclusively for this
83 object, with no relation to a view).
84 </p>
86 <p>If a SdrView is given at construction time, the caller is
87 responsible for destroying this object when the view becomes
88 invalid (the views cannot notify). If GetViewForwarder(sal_True)
89 is called, the underlying shape is put into edit mode, the view
90 forwarder returned encapsulates the OutlinerView and the next call
91 to GetTextForwarder() yields a forwarder encapsulating the actual
92 DrawOutliner. Thus, changes on that Outliner are immediately
93 reflected on the screen. If the object leaves edit mode, the old
94 behaviour is restored.</p>
96 class SvxTextEditSourceImpl : public SfxListener, public SfxBroadcaster, public sdr::ObjectUser
98 private:
99 oslInterlockedCount maRefCount;
101 SdrObject* mpObject;
102 SdrText* mpText;
103 SdrView* mpView;
104 const Window* mpWindow;
105 SdrModel* mpModel;
106 SdrOutliner* mpOutliner;
107 SvxOutlinerForwarder* mpTextForwarder;
108 SvxDrawOutlinerViewForwarder* mpViewForwarder; // if non-NULL, use GetViewModeTextForwarder text forwarder
109 css::uno::Reference< css::linguistic2::XLinguServiceManager > m_xLinguServiceManager;
110 Point maTextOffset;
111 BOOL mbDataValid;
112 BOOL mbDestroyed;
113 BOOL mbIsLocked;
114 BOOL mbNeedsUpdate;
115 BOOL mbOldUndoMode;
116 BOOL mbForwarderIsEditMode; // have to reflect that, since ENDEDIT can happen more often
117 BOOL mbShapeIsEditMode; // #104157# only true, if HINT_BEGEDIT was received
118 BOOL mbNotificationsDisabled; // prevent EditEngine/Outliner notifications (e.g. when setting up forwarder)
120 XInterface* mpOwner;
121 SvxUnoTextRangeBaseList maTextRanges;
123 SvxTextForwarder* GetBackgroundTextForwarder();
124 SvxTextForwarder* GetEditModeTextForwarder();
125 SvxDrawOutlinerViewForwarder* CreateViewForwarder();
127 void SetupOutliner();
128 void UpdateOutliner();
130 sal_Bool HasView() const { return mpView ? sal_True : sal_False; }
131 sal_Bool IsEditMode() const
133 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
134 return mbShapeIsEditMode && pTextObj && pTextObj->IsTextEditActive() ? sal_True : sal_False;
137 void dispose();
139 public:
140 SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText, XInterface* pOwner );
141 SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const Window& rWindow );
142 ~SvxTextEditSourceImpl();
144 void SAL_CALL acquire();
145 void SAL_CALL release();
147 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
149 SvxEditSource* Clone() const;
150 SvxTextForwarder* GetTextForwarder();
151 SvxEditViewForwarder* GetEditViewForwarder( sal_Bool );
152 void UpdateData();
154 void addRange( SvxUnoTextRangeBase* pNewRange );
155 void removeRange( SvxUnoTextRangeBase* pOldRange );
156 const SvxUnoTextRangeBaseList& getRanges() const;
158 SdrObject* GetSdrObject() const { return mpObject; }
160 void lock();
161 void unlock();
163 BOOL IsValid() const;
165 Rectangle GetVisArea();
166 Point LogicToPixel( const Point&, const MapMode& rMapMode );
167 Point PixelToLogic( const Point&, const MapMode& rMapMode );
169 DECL_LINK( NotifyHdl, EENotify* );
171 virtual void ObjectInDestruction(const SdrObject& rObject);
173 void ChangeModel( SdrModel* pNewModel );
176 //------------------------------------------------------------------------
178 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText, XInterface* pOwner )
179 : maRefCount ( 0 ),
180 mpObject ( pObject ),
181 mpText ( pText ),
182 mpView ( NULL ),
183 mpWindow ( NULL ),
184 mpModel ( pObject ? pObject->GetModel() : NULL ),
185 mpOutliner ( NULL ),
186 mpTextForwarder ( NULL ),
187 mpViewForwarder ( NULL ),
188 mbDataValid ( FALSE ),
189 mbDestroyed ( FALSE ),
190 mbIsLocked ( FALSE ),
191 mbNeedsUpdate ( FALSE ),
192 mbOldUndoMode ( FALSE ),
193 mbForwarderIsEditMode ( FALSE ),
194 mbShapeIsEditMode ( FALSE ),
195 mbNotificationsDisabled ( FALSE ),
196 mpOwner( pOwner )
198 DBG_ASSERT( mpObject, "invalid pObject!" );
200 if( !mpText )
202 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
203 if( pTextObj )
204 mpText = pTextObj->getText( 0 );
207 if( mpModel )
208 StartListening( *mpModel );
210 if( mpObject )
211 mpObject->AddObjectUser( *this );
214 //------------------------------------------------------------------------
216 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const Window& rWindow )
217 : maRefCount ( 0 ),
218 mpObject ( &rObject ),
219 mpText ( pText ),
220 mpView ( &rView ),
221 mpWindow ( &rWindow ),
222 mpModel ( rObject.GetModel() ),
223 mpOutliner ( NULL ),
224 mpTextForwarder ( NULL ),
225 mpViewForwarder ( NULL ),
226 mbDataValid ( FALSE ),
227 mbDestroyed ( FALSE ),
228 mbIsLocked ( FALSE ),
229 mbNeedsUpdate ( FALSE ),
230 mbOldUndoMode ( FALSE ),
231 mbForwarderIsEditMode ( FALSE ),
232 mbShapeIsEditMode ( TRUE ),
233 mbNotificationsDisabled ( FALSE ),
234 mpOwner(0)
236 if( !mpText )
238 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
239 if( pTextObj )
240 mpText = pTextObj->getText( 0 );
243 if( mpModel )
244 StartListening( *mpModel );
245 if( mpView )
246 StartListening( *mpView );
247 if( mpObject )
248 mpObject->AddObjectUser( *this );
250 // #104157# Init edit mode state from shape info (IsTextEditActive())
251 mbShapeIsEditMode = IsEditMode();
254 //------------------------------------------------------------------------
256 SvxTextEditSourceImpl::~SvxTextEditSourceImpl()
258 DBG_ASSERT( mbIsLocked == sal_False, "text edit source was not unlocked before dispose!" );
259 if( mpObject )
260 mpObject->RemoveObjectUser( *this );
262 dispose();
265 //------------------------------------------------------------------------
267 void SvxTextEditSourceImpl::addRange( SvxUnoTextRangeBase* pNewRange )
269 if( pNewRange )
270 if( std::find( maTextRanges.begin(), maTextRanges.end(), pNewRange ) == maTextRanges.end() )
271 maTextRanges.push_back( pNewRange );
274 //------------------------------------------------------------------------
276 void SvxTextEditSourceImpl::removeRange( SvxUnoTextRangeBase* pOldRange )
278 if( pOldRange )
279 maTextRanges.remove( pOldRange );
282 //------------------------------------------------------------------------
284 const SvxUnoTextRangeBaseList& SvxTextEditSourceImpl::getRanges() const
286 return maTextRanges;
289 //------------------------------------------------------------------------
291 void SAL_CALL SvxTextEditSourceImpl::acquire()
293 osl_incrementInterlockedCount( &maRefCount );
296 //------------------------------------------------------------------------
298 void SAL_CALL SvxTextEditSourceImpl::release()
300 if( ! osl_decrementInterlockedCount( &maRefCount ) )
301 delete this;
304 void SvxTextEditSourceImpl::ChangeModel( SdrModel* pNewModel )
306 if( mpModel != pNewModel )
308 if( mpModel )
309 EndListening( *mpModel );
311 if( mpOutliner )
313 if( mpModel )
314 mpModel->disposeOutliner( mpOutliner );
315 else
316 delete mpOutliner;
317 mpOutliner = 0;
320 if( mpView )
322 EndListening( *mpView );
323 mpView = 0;
326 mpWindow = 0;
327 m_xLinguServiceManager.clear();
328 mpOwner = 0;
330 mpModel = pNewModel;
332 if( mpTextForwarder )
334 delete mpTextForwarder;
335 mpTextForwarder = 0;
338 if( mpViewForwarder )
340 delete mpViewForwarder;
341 mpViewForwarder = 0;
344 if( mpModel )
345 StartListening( *mpModel );
349 //------------------------------------------------------------------------
351 void SvxTextEditSourceImpl::Notify( SfxBroadcaster&, const SfxHint& rHint )
353 const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
354 const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
356 if( pViewHint )
358 switch( pViewHint->GetHintType() )
360 case SvxViewHint::SVX_HINT_VIEWCHANGED:
361 Broadcast( *pViewHint );
362 break;
365 else if( pSdrHint )
367 switch( pSdrHint->GetKind() )
369 case HINT_OBJCHG:
371 mbDataValid = FALSE; // Text muss neu geholt werden
373 if( HasView() )
375 // #104157# Update maTextOffset, object has changed
376 // #105196#, #105203#: Cannot call that // here,
377 // since TakeTextRect() (called from there) //
378 // changes outliner content.
379 // UpdateOutliner();
381 // #101029# Broadcast object changes, as they might change visible attributes
382 SvxViewHint aHint(SvxViewHint::SVX_HINT_VIEWCHANGED);
383 Broadcast( aHint );
385 break;
388 case HINT_BEGEDIT:
389 if( mpObject == pSdrHint->GetObject() )
391 // invalidate old forwarder
392 if( !mbForwarderIsEditMode )
394 delete mpTextForwarder;
395 mpTextForwarder = NULL;
398 // register as listener - need to broadcast state change messages
399 if( mpView && mpView->GetTextEditOutliner() )
400 mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
402 // #104157# Only now we're really in edit mode
403 mbShapeIsEditMode = TRUE;
405 Broadcast( *pSdrHint );
407 break;
409 case HINT_ENDEDIT:
410 if( mpObject == pSdrHint->GetObject() )
412 Broadcast( *pSdrHint );
414 // #104157# We're no longer in edit mode
415 mbShapeIsEditMode = FALSE;
417 // remove as listener - outliner might outlive ourselves
418 if( mpView && mpView->GetTextEditOutliner() )
419 mpView->GetTextEditOutliner()->SetNotifyHdl( Link() );
421 // destroy view forwarder, OutlinerView no longer
422 // valid (no need for UpdateData(), it's been
423 // synched on SdrEndTextEdit)
424 delete mpViewForwarder;
425 mpViewForwarder = NULL;
427 // #100424# Invalidate text forwarder, we might
428 // not be called again before entering edit mode a
429 // second time! Then, the old outliner might be
430 // invalid.
431 if( mbForwarderIsEditMode )
433 mbForwarderIsEditMode = sal_False;
434 delete mpTextForwarder;
435 mpTextForwarder = NULL;
438 break;
440 case HINT_MODELCLEARED:
441 dispose();
442 break;
443 default:
444 break;
449 /* this is a callback from the attached SdrObject when it is actually deleted */
450 void SvxTextEditSourceImpl::ObjectInDestruction(const SdrObject&)
452 mpObject = 0;
453 dispose();
454 Broadcast( SfxSimpleHint( SFX_HINT_DYING ) );
457 /* unregister at all objects and set all references to 0 */
458 void SvxTextEditSourceImpl::dispose()
460 if( mpTextForwarder )
462 delete mpTextForwarder;
463 mpTextForwarder = 0;
466 if( mpViewForwarder )
468 delete mpViewForwarder;
469 mpViewForwarder = 0;
472 if( mpOutliner )
474 if( mpModel )
476 mpModel->disposeOutliner( mpOutliner );
478 else
480 delete mpOutliner;
482 mpOutliner = 0;
485 if( mpModel )
487 EndListening( *mpModel );
488 mpModel = 0;
491 if( mpView )
493 EndListening( *mpView );
494 mpView = 0;
497 if( mpObject )
499 mpObject->RemoveObjectUser( *this );
500 mpObject = 0;
502 mpWindow = 0;
505 //------------------------------------------------------------------------
507 void SvxTextEditSourceImpl::SetupOutliner()
509 // #101029#
510 // only for UAA edit source: setup outliner equivalently as in
511 // SdrTextObj::Paint(), such that formatting equals screen
512 // layout
513 if( mpObject && mpOutliner )
515 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
516 Rectangle aPaintRect;
517 if( pTextObj )
519 Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
520 pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect );
522 // #101029# calc text offset from shape anchor
523 maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
528 //------------------------------------------------------------------------
530 void SvxTextEditSourceImpl::UpdateOutliner()
532 // #104157#
533 // only for UAA edit source: update outliner equivalently as in
534 // SdrTextObj::Paint(), such that formatting equals screen
535 // layout
536 if( mpObject && mpOutliner )
538 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
539 Rectangle aPaintRect;
540 if( pTextObj )
542 Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
543 pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect );
545 // #101029# calc text offset from shape anchor
546 maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
551 //------------------------------------------------------------------------
555 SvxTextForwarder* SvxTextEditSourceImpl::GetBackgroundTextForwarder()
557 sal_Bool bCreated = sal_False;
559 // #99840#: prevent EE/Outliner notifications during setup
560 mbNotificationsDisabled = sal_True;
562 if (!mpTextForwarder)
564 if( mpOutliner == NULL )
566 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
567 USHORT nOutlMode = OUTLINERMODE_TEXTOBJECT;
568 if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_OUTLINETEXT )
569 nOutlMode = OUTLINERMODE_OUTLINEOBJECT;
571 mpOutliner = mpModel->createOutliner( nOutlMode );
573 // #109151# Do the setup after outliner creation, would be useless otherwise
574 if( HasView() )
576 // #101029#, #104157# Setup outliner _before_ filling it
577 SetupOutliner();
580 mpOutliner->SetTextObjNoInit( pTextObj );
582 mpOutliner = SdrMakeOutliner( nOutlMode, pModel );
583 Outliner& aDrawOutliner = pModel->GetDrawOutliner();
584 mpOutliner->SetCalcFieldValueHdl( aDrawOutliner.GetCalcFieldValueHdl() );
586 if( mbIsLocked )
588 ((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_False );
589 mbOldUndoMode = ((EditEngine*)&(mpOutliner->GetEditEngine()))->IsUndoEnabled();
590 ((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( sal_False );
593 // -
594 if ( !m_xLinguServiceManager.is() )
596 css::uno::Reference< css::lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
597 m_xLinguServiceManager = css::uno::Reference< css::linguistic2::XLinguServiceManager >(
598 xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.linguistic2.LinguServiceManager" ))), css::uno::UNO_QUERY );
601 if ( m_xLinguServiceManager.is() )
603 css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator( m_xLinguServiceManager->getHyphenator(), css::uno::UNO_QUERY );
604 if( xHyphenator.is() )
605 mpOutliner->SetHyphenator( xHyphenator );
607 // -
610 mpTextForwarder = new SvxOutlinerForwarder( *mpOutliner, mpObject );
612 // delay listener subscription and UAA initialization until Outliner is fully setup
613 bCreated = sal_True;
615 mbForwarderIsEditMode = sal_False;
618 if( mpObject && mpText && !mbDataValid && mpObject->IsInserted() && mpObject->GetPage() )
620 mpTextForwarder->flushCache();
622 OutlinerParaObject* pOutlinerParaObject = NULL;
623 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
624 if( pTextObj && pTextObj->getActiveText() == mpText )
625 pOutlinerParaObject = pTextObj->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
626 bool bOwnParaObj(false);
628 if( pOutlinerParaObject )
629 bOwnParaObj = true; // text edit active
630 else
631 pOutlinerParaObject = mpText->GetOutlinerParaObject();
633 if( pOutlinerParaObject && ( bOwnParaObj || !mpObject->IsEmptyPresObj() || mpObject->GetPage()->IsMasterPage() ) )
635 mpOutliner->SetText( *pOutlinerParaObject );
637 // #91254# put text to object and set EmptyPresObj to FALSE
638 if( mpText && bOwnParaObj && pOutlinerParaObject && mpObject->IsEmptyPresObj() && pTextObj->IsRealyEdited() )
640 mpObject->SetEmptyPresObj( FALSE );
641 static_cast< SdrTextObj* >( mpObject)->NbcSetOutlinerParaObjectForText( pOutlinerParaObject, mpText );
643 // #i103982# Here, due to mpObject->NbcSetOutlinerParaObjectForText, we LOSE ownership of the
644 // OPO, so do NOT delete it when leaving this method (!)
645 bOwnParaObj = false;
648 else
650 sal_Bool bVertical = pOutlinerParaObject ? pOutlinerParaObject->IsVertical() : sal_False;
652 // set objects style sheet on empty outliner
653 SfxStyleSheetPool* pPool = (SfxStyleSheetPool*)mpObject->GetModel()->GetStyleSheetPool();
654 if( pPool )
655 mpOutliner->SetStyleSheetPool( pPool );
657 SfxStyleSheet* pStyleSheet = mpObject->GetPage()->GetTextStyleSheetForObject( mpObject );
658 if( pStyleSheet )
659 mpOutliner->SetStyleSheet( 0, pStyleSheet );
661 if( bVertical )
662 mpOutliner->SetVertical( sal_True );
665 // evtually we have to set the border attributes
666 if (mpOutliner->GetParagraphCount()==1)
668 // if we only have one paragraph we check if it is empty
669 XubString aStr( mpOutliner->GetText( mpOutliner->GetParagraph( 0 ) ) );
671 if(!aStr.Len())
673 // its empty, so we have to force the outliner to initialise itself
674 mpOutliner->SetText( String(), mpOutliner->GetParagraph( 0 ) );
676 if(mpObject->GetStyleSheet())
677 mpOutliner->SetStyleSheet( 0, mpObject->GetStyleSheet());
681 mbDataValid = TRUE;
683 if( bOwnParaObj )
684 delete pOutlinerParaObject;
687 if( bCreated && mpOutliner && HasView() )
689 // register as listener - need to broadcast state change messages
690 // registration delayed until outliner is completely set up
691 mpOutliner->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
694 // #99840#: prevent EE/Outliner notifications during setup
695 mbNotificationsDisabled = sal_False;
697 return mpTextForwarder;
700 //------------------------------------------------------------------------
702 SvxTextForwarder* SvxTextEditSourceImpl::GetEditModeTextForwarder()
704 if( !mpTextForwarder && HasView() )
706 SdrOutliner* pEditOutliner = mpView->GetTextEditOutliner();
708 if( pEditOutliner )
710 mpTextForwarder = new SvxOutlinerForwarder( *pEditOutliner, mpObject );
712 mbForwarderIsEditMode = sal_True;
716 return mpTextForwarder;
719 //------------------------------------------------------------------------
721 SvxTextForwarder* SvxTextEditSourceImpl::GetTextForwarder()
723 if( mbDestroyed || mpObject == NULL )
724 return NULL;
726 if( mpModel == NULL )
727 mpModel = mpObject->GetModel();
729 if( mpModel == NULL )
730 return NULL;
732 // distinguish the cases
733 // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner
734 // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code)
735 if( HasView() )
737 if( IsEditMode() != mbForwarderIsEditMode )
739 // forwarder mismatch - create new
740 delete mpTextForwarder;
741 mpTextForwarder = NULL;
744 if( IsEditMode() )
745 return GetEditModeTextForwarder();
746 else
747 return GetBackgroundTextForwarder();
749 else
750 return GetBackgroundTextForwarder();
753 //------------------------------------------------------------------------
755 SvxDrawOutlinerViewForwarder* SvxTextEditSourceImpl::CreateViewForwarder()
757 if( mpView->GetTextEditOutlinerView() && mpObject )
759 // register as listener - need to broadcast state change messages
760 mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
762 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
763 if( pTextObj )
765 Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
766 OutlinerView& rOutlView = *mpView->GetTextEditOutlinerView();
768 return new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() );
772 return NULL;
775 SvxEditViewForwarder* SvxTextEditSourceImpl::GetEditViewForwarder( sal_Bool bCreate )
777 if( mbDestroyed || mpObject == NULL )
778 return NULL;
780 if( mpModel == NULL )
781 mpModel = mpObject->GetModel();
783 if( mpModel == NULL )
784 return NULL;
786 // shall we delete?
787 if( mpViewForwarder )
789 if( !IsEditMode() )
791 // destroy all forwarders (no need for UpdateData(),
792 // it's been synched on SdrEndTextEdit)
793 delete mpViewForwarder;
794 mpViewForwarder = NULL;
797 // which to create? Directly in edit mode, create new, or none?
798 else if( mpView )
800 if( IsEditMode() )
802 // create new view forwarder
803 mpViewForwarder = CreateViewForwarder();
805 else if( bCreate )
807 // dispose old text forwarder
808 UpdateData();
810 delete mpTextForwarder;
811 mpTextForwarder = NULL;
813 // enter edit mode
814 mpView->SdrEndTextEdit();
816 if(mpView->SdrBeginTextEdit(mpObject, 0L, 0L, sal_False, (SdrOutliner*)0L, 0L, sal_False, sal_False))
818 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
819 if( pTextObj->IsTextEditActive() )
821 // create new view forwarder
822 mpViewForwarder = CreateViewForwarder();
824 else
826 // failure. Somehow, SdrBeginTextEdit did not set
827 // our SdrTextObj into edit mode
828 mpView->SdrEndTextEdit();
834 return mpViewForwarder;
837 //------------------------------------------------------------------------
839 void SvxTextEditSourceImpl::UpdateData()
841 // if we have a view and in edit mode, we're working with the
842 // DrawOutliner. Thus, all changes made on the text forwarder are
843 // reflected on the view and committed to the model on
844 // SdrEndTextEdit(). Thus, no need for explicit updates here.
845 if( !HasView() || !IsEditMode() )
847 if( mbIsLocked )
849 mbNeedsUpdate = sal_True;
851 else
853 if( mpOutliner && mpObject && mpText && !mbDestroyed )
855 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
856 if( pTextObj )
858 if( mpOutliner->GetParagraphCount() != 1 || mpOutliner->GetEditEngine().GetTextLen( 0 ) )
860 if( mpOutliner->GetParagraphCount() > 1 )
862 if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_TITLETEXT )
864 while( mpOutliner->GetParagraphCount() > 1 )
866 ESelection aSel( 0,mpOutliner->GetEditEngine().GetTextLen( 0 ), 1,0 );
867 mpOutliner->QuickInsertLineBreak( aSel );
872 pTextObj->NbcSetOutlinerParaObjectForText( mpOutliner->CreateParaObject(), mpText );
874 else
876 pTextObj->NbcSetOutlinerParaObjectForText( NULL,mpText );
880 if( mpObject->IsEmptyPresObj() )
881 mpObject->SetEmptyPresObj(sal_False);
887 void SvxTextEditSourceImpl::lock()
889 mbIsLocked = sal_True;
890 if( mpOutliner )
892 ((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_False );
893 mbOldUndoMode = ((EditEngine*)&(mpOutliner->GetEditEngine()))->IsUndoEnabled();
894 ((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( sal_False );
898 void SvxTextEditSourceImpl::unlock()
900 mbIsLocked = sal_False;
902 if( mbNeedsUpdate )
904 UpdateData();
905 mbNeedsUpdate = sal_False;
908 if( mpOutliner )
910 ((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_True );
911 ((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( mbOldUndoMode );
915 BOOL SvxTextEditSourceImpl::IsValid() const
917 return mpView && mpWindow ? TRUE : FALSE;
920 Rectangle SvxTextEditSourceImpl::GetVisArea()
922 if( IsValid() )
924 SdrPaintWindow* pPaintWindow = mpView->FindPaintWindow(*mpWindow);
925 Rectangle aVisArea;
927 if(pPaintWindow)
929 aVisArea = pPaintWindow->GetVisibleArea();
932 // offset vis area by edit engine left-top position
933 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
934 if( pTextObj )
936 Rectangle aAnchorRect;
937 pTextObj->TakeTextAnchorRect( aAnchorRect );
938 aVisArea.Move( -aAnchorRect.Left(), -aAnchorRect.Top() );
940 MapMode aMapMode(mpWindow->GetMapMode());
941 aMapMode.SetOrigin(Point());
942 return mpWindow->LogicToPixel( aVisArea, aMapMode );
946 return Rectangle();
949 Point SvxTextEditSourceImpl::LogicToPixel( const Point& rPoint, const MapMode& rMapMode )
951 // #101029#: The responsibilities of ViewForwarder happen to be
952 // somewhat mixed in this case. On the one hand, we need the
953 // different interface queries on the SvxEditSource interface,
954 // since we need both VisAreas. On the other hand, if an
955 // EditViewForwarder exists, maTextOffset does not remain static,
956 // but may change with every key press.
957 if( IsEditMode() )
959 SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
961 if( pForwarder )
962 return pForwarder->LogicToPixel( rPoint, rMapMode );
964 else if( IsValid() && mpModel )
966 // #101029#
967 Point aPoint1( rPoint );
968 aPoint1.X() += maTextOffset.X();
969 aPoint1.Y() += maTextOffset.Y();
971 Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode,
972 MapMode(mpModel->GetScaleUnit()) ) );
973 MapMode aMapMode(mpWindow->GetMapMode());
974 aMapMode.SetOrigin(Point());
975 return mpWindow->LogicToPixel( aPoint2, aMapMode );
978 return Point();
981 Point SvxTextEditSourceImpl::PixelToLogic( const Point& rPoint, const MapMode& rMapMode )
983 // #101029#: The responsibilities of ViewForwarder happen to be
984 // somewhat mixed in this case. On the one hand, we need the
985 // different interface queries on the SvxEditSource interface,
986 // since we need both VisAreas. On the other hand, if an
987 // EditViewForwarder exists, maTextOffset does not remain static,
988 // but may change with every key press.
989 if( IsEditMode() )
991 SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
993 if( pForwarder )
994 return pForwarder->PixelToLogic( rPoint, rMapMode );
996 else if( IsValid() && mpModel )
998 MapMode aMapMode(mpWindow->GetMapMode());
999 aMapMode.SetOrigin(Point());
1000 Point aPoint1( mpWindow->PixelToLogic( rPoint, aMapMode ) );
1001 Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
1002 MapMode(mpModel->GetScaleUnit()),
1003 rMapMode ) );
1004 // #101029#
1005 aPoint2.X() -= maTextOffset.X();
1006 aPoint2.Y() -= maTextOffset.Y();
1008 return aPoint2;
1011 return Point();
1014 IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify*, aNotify)
1016 if( aNotify && !mbNotificationsDisabled )
1018 ::std::auto_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( aNotify) );
1020 if( aHint.get() )
1021 Broadcast( *aHint.get() );
1024 return 0;
1027 //------------------------------------------------------------------------
1029 // --------------------------------------------------------------------
1030 // SvxTextEditSource
1031 // --------------------------------------------------------------------
1033 SvxTextEditSource::SvxTextEditSource( SdrObject* pObject, SdrText* pText, XInterface* pOwner )
1035 mpImpl = new SvxTextEditSourceImpl( pObject, pText, pOwner );
1036 mpImpl->acquire();
1039 // --------------------------------------------------------------------
1040 SvxTextEditSource::SvxTextEditSource( SdrObject& rObj, SdrText* pText, SdrView& rView, const Window& rWindow )
1042 mpImpl = new SvxTextEditSourceImpl( rObj, pText, rView, rWindow );
1043 mpImpl->acquire();
1046 // --------------------------------------------------------------------
1048 SvxTextEditSource::SvxTextEditSource( SvxTextEditSourceImpl* pImpl )
1050 mpImpl = pImpl;
1051 mpImpl->acquire();
1054 //------------------------------------------------------------------------
1055 SvxTextEditSource::~SvxTextEditSource()
1057 OGuard aGuard( Application::GetSolarMutex() );
1059 mpImpl->release();
1062 //------------------------------------------------------------------------
1063 SvxEditSource* SvxTextEditSource::Clone() const
1065 return new SvxTextEditSource( mpImpl );
1068 //------------------------------------------------------------------------
1069 SvxTextForwarder* SvxTextEditSource::GetTextForwarder()
1071 return mpImpl->GetTextForwarder();
1074 //------------------------------------------------------------------------
1075 SvxEditViewForwarder* SvxTextEditSource::GetEditViewForwarder( sal_Bool bCreate )
1077 return mpImpl->GetEditViewForwarder( bCreate );
1080 //------------------------------------------------------------------------
1081 SvxViewForwarder* SvxTextEditSource::GetViewForwarder()
1083 return this;
1086 //------------------------------------------------------------------------
1087 void SvxTextEditSource::UpdateData()
1089 mpImpl->UpdateData();
1092 SfxBroadcaster& SvxTextEditSource::GetBroadcaster() const
1094 return *mpImpl;
1097 SdrObject* SvxTextEditSource::GetSdrObject() const
1099 return mpImpl->GetSdrObject();
1102 void SvxTextEditSource::lock()
1104 mpImpl->lock();
1107 void SvxTextEditSource::unlock()
1109 mpImpl->unlock();
1112 BOOL SvxTextEditSource::IsValid() const
1114 return mpImpl->IsValid();
1117 Rectangle SvxTextEditSource::GetVisArea() const
1119 return mpImpl->GetVisArea();
1122 Point SvxTextEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1124 return mpImpl->LogicToPixel( rPoint, rMapMode );
1127 Point SvxTextEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1129 return mpImpl->PixelToLogic( rPoint, rMapMode );
1132 void SvxTextEditSource::addRange( SvxUnoTextRangeBase* pNewRange )
1134 mpImpl->addRange( pNewRange );
1137 void SvxTextEditSource::removeRange( SvxUnoTextRangeBase* pOldRange )
1139 mpImpl->removeRange( pOldRange );
1142 const SvxUnoTextRangeBaseList& SvxTextEditSource::getRanges() const
1144 return mpImpl->getRanges();
1147 void SvxTextEditSource::ChangeModel( SdrModel* pNewModel )
1149 mpImpl->ChangeModel( pNewModel );