1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unoshtxt.cxx,v $
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 //------------------------------------------------------------------------
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).
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
99 oslInterlockedCount maRefCount
;
104 const Window
* mpWindow
;
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
;
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)
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
;
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
);
154 void addRange( SvxUnoTextRangeBase
* pNewRange
);
155 void removeRange( SvxUnoTextRangeBase
* pOldRange
);
156 const SvxUnoTextRangeBaseList
& getRanges() const;
158 SdrObject
* GetSdrObject() const { return mpObject
; }
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
)
180 mpObject ( pObject
),
184 mpModel ( pObject
? pObject
->GetModel() : 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
),
198 DBG_ASSERT( mpObject
, "invalid pObject!" );
202 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( mpObject
);
204 mpText
= pTextObj
->getText( 0 );
208 StartListening( *mpModel
);
211 mpObject
->AddObjectUser( *this );
214 //------------------------------------------------------------------------
216 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject
& rObject
, SdrText
* pText
, SdrView
& rView
, const Window
& rWindow
)
218 mpObject ( &rObject
),
221 mpWindow ( &rWindow
),
222 mpModel ( rObject
.GetModel() ),
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
),
238 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( mpObject
);
240 mpText
= pTextObj
->getText( 0 );
244 StartListening( *mpModel
);
246 StartListening( *mpView
);
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!" );
260 mpObject
->RemoveObjectUser( *this );
265 //------------------------------------------------------------------------
267 void SvxTextEditSourceImpl::addRange( SvxUnoTextRangeBase
* pNewRange
)
270 if( std::find( maTextRanges
.begin(), maTextRanges
.end(), pNewRange
) == maTextRanges
.end() )
271 maTextRanges
.push_back( pNewRange
);
274 //------------------------------------------------------------------------
276 void SvxTextEditSourceImpl::removeRange( SvxUnoTextRangeBase
* pOldRange
)
279 maTextRanges
.remove( pOldRange
);
282 //------------------------------------------------------------------------
284 const SvxUnoTextRangeBaseList
& SvxTextEditSourceImpl::getRanges() const
289 //------------------------------------------------------------------------
291 void SAL_CALL
SvxTextEditSourceImpl::acquire()
293 osl_incrementInterlockedCount( &maRefCount
);
296 //------------------------------------------------------------------------
298 void SAL_CALL
SvxTextEditSourceImpl::release()
300 if( ! osl_decrementInterlockedCount( &maRefCount
) )
304 void SvxTextEditSourceImpl::ChangeModel( SdrModel
* pNewModel
)
306 if( mpModel
!= pNewModel
)
309 EndListening( *mpModel
);
314 mpModel
->disposeOutliner( mpOutliner
);
322 EndListening( *mpView
);
327 m_xLinguServiceManager
.clear();
332 if( mpTextForwarder
)
334 delete mpTextForwarder
;
338 if( mpViewForwarder
)
340 delete mpViewForwarder
;
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
);
358 switch( pViewHint
->GetHintType() )
360 case SvxViewHint::SVX_HINT_VIEWCHANGED
:
361 Broadcast( *pViewHint
);
367 switch( pSdrHint
->GetKind() )
371 mbDataValid
= FALSE
; // Text muss neu geholt werden
375 // #104157# Update maTextOffset, object has changed
376 // #105196#, #105203#: Cannot call that // here,
377 // since TakeTextRect() (called from there) //
378 // changes outliner content.
381 // #101029# Broadcast object changes, as they might change visible attributes
382 SvxViewHint
aHint(SvxViewHint::SVX_HINT_VIEWCHANGED
);
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
);
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
431 if( mbForwarderIsEditMode
)
433 mbForwarderIsEditMode
= sal_False
;
434 delete mpTextForwarder
;
435 mpTextForwarder
= NULL
;
440 case HINT_MODELCLEARED
:
449 /* this is a callback from the attached SdrObject when it is actually deleted */
450 void SvxTextEditSourceImpl::ObjectInDestruction(const SdrObject
&)
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
;
466 if( mpViewForwarder
)
468 delete mpViewForwarder
;
476 mpModel
->disposeOutliner( mpOutliner
);
487 EndListening( *mpModel
);
493 EndListening( *mpView
);
499 mpObject
->RemoveObjectUser( *this );
505 //------------------------------------------------------------------------
507 void SvxTextEditSourceImpl::SetupOutliner()
510 // only for UAA edit source: setup outliner equivalently as in
511 // SdrTextObj::Paint(), such that formatting equals screen
513 if( mpObject
&& mpOutliner
)
515 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
516 Rectangle aPaintRect
;
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()
533 // only for UAA edit source: update outliner equivalently as in
534 // SdrTextObj::Paint(), such that formatting equals screen
536 if( mpObject
&& mpOutliner
)
538 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
539 Rectangle aPaintRect
;
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
576 // #101029#, #104157# Setup outliner _before_ filling it
580 mpOutliner
->SetTextObjNoInit( pTextObj
);
582 mpOutliner = SdrMakeOutliner( nOutlMode, pModel );
583 Outliner& aDrawOutliner = pModel->GetDrawOutliner();
584 mpOutliner->SetCalcFieldValueHdl( aDrawOutliner.GetCalcFieldValueHdl() );
588 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->SetUpdateMode( sal_False
);
589 mbOldUndoMode
= ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->IsUndoEnabled();
590 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->EnableUndo( sal_False
);
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
);
610 mpTextForwarder
= new SvxOutlinerForwarder( *mpOutliner
, mpObject
);
612 // delay listener subscription and UAA initialization until Outliner is fully setup
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
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 (!)
650 sal_Bool bVertical
= pOutlinerParaObject
? pOutlinerParaObject
->IsVertical() : sal_False
;
652 // set objects style sheet on empty outliner
653 SfxStyleSheetPool
* pPool
= (SfxStyleSheetPool
*)mpObject
->GetModel()->GetStyleSheetPool();
655 mpOutliner
->SetStyleSheetPool( pPool
);
657 SfxStyleSheet
* pStyleSheet
= mpObject
->GetPage()->GetTextStyleSheetForObject( mpObject
);
659 mpOutliner
->SetStyleSheet( 0, pStyleSheet
);
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 ) ) );
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());
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();
710 mpTextForwarder
= new SvxOutlinerForwarder( *pEditOutliner
, mpObject
);
712 mbForwarderIsEditMode
= sal_True
;
716 return mpTextForwarder
;
719 //------------------------------------------------------------------------
721 SvxTextForwarder
* SvxTextEditSourceImpl::GetTextForwarder()
723 if( mbDestroyed
|| mpObject
== NULL
)
726 if( mpModel
== NULL
)
727 mpModel
= mpObject
->GetModel();
729 if( mpModel
== 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)
737 if( IsEditMode() != mbForwarderIsEditMode
)
739 // forwarder mismatch - create new
740 delete mpTextForwarder
;
741 mpTextForwarder
= NULL
;
745 return GetEditModeTextForwarder();
747 return GetBackgroundTextForwarder();
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
);
765 Rectangle
aBoundRect( pTextObj
->GetCurrentBoundRect() );
766 OutlinerView
& rOutlView
= *mpView
->GetTextEditOutlinerView();
768 return new SvxDrawOutlinerViewForwarder( rOutlView
, aBoundRect
.TopLeft() );
775 SvxEditViewForwarder
* SvxTextEditSourceImpl::GetEditViewForwarder( sal_Bool bCreate
)
777 if( mbDestroyed
|| mpObject
== NULL
)
780 if( mpModel
== NULL
)
781 mpModel
= mpObject
->GetModel();
783 if( mpModel
== NULL
)
787 if( mpViewForwarder
)
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?
802 // create new view forwarder
803 mpViewForwarder
= CreateViewForwarder();
807 // dispose old text forwarder
810 delete mpTextForwarder
;
811 mpTextForwarder
= NULL
;
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();
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() )
849 mbNeedsUpdate
= sal_True
;
853 if( mpOutliner
&& mpObject
&& mpText
&& !mbDestroyed
)
855 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( mpObject
);
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
);
876 pTextObj
->NbcSetOutlinerParaObjectForText( NULL
,mpText
);
880 if( mpObject
->IsEmptyPresObj() )
881 mpObject
->SetEmptyPresObj(sal_False
);
887 void SvxTextEditSourceImpl::lock()
889 mbIsLocked
= sal_True
;
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
;
905 mbNeedsUpdate
= sal_False
;
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()
924 SdrPaintWindow
* pPaintWindow
= mpView
->FindPaintWindow(*mpWindow
);
929 aVisArea
= pPaintWindow
->GetVisibleArea();
932 // offset vis area by edit engine left-top position
933 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
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
);
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.
959 SvxEditViewForwarder
* pForwarder
= GetEditViewForwarder(sal_False
);
962 return pForwarder
->LogicToPixel( rPoint
, rMapMode
);
964 else if( IsValid() && mpModel
)
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
);
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.
991 SvxEditViewForwarder
* pForwarder
= GetEditViewForwarder(sal_False
);
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()),
1005 aPoint2
.X() -= maTextOffset
.X();
1006 aPoint2
.Y() -= maTextOffset
.Y();
1014 IMPL_LINK(SvxTextEditSourceImpl
, NotifyHdl
, EENotify
*, aNotify
)
1016 if( aNotify
&& !mbNotificationsDisabled
)
1018 ::std::auto_ptr
< SfxHint
> aHint( SvxEditSourceHelper::EENotification2Hint( aNotify
) );
1021 Broadcast( *aHint
.get() );
1027 //------------------------------------------------------------------------
1029 // --------------------------------------------------------------------
1030 // SvxTextEditSource
1031 // --------------------------------------------------------------------
1033 SvxTextEditSource::SvxTextEditSource( SdrObject
* pObject
, SdrText
* pText
, XInterface
* pOwner
)
1035 mpImpl
= new SvxTextEditSourceImpl( pObject
, pText
, pOwner
);
1039 // --------------------------------------------------------------------
1040 SvxTextEditSource::SvxTextEditSource( SdrObject
& rObj
, SdrText
* pText
, SdrView
& rView
, const Window
& rWindow
)
1042 mpImpl
= new SvxTextEditSourceImpl( rObj
, pText
, rView
, rWindow
);
1046 // --------------------------------------------------------------------
1048 SvxTextEditSource::SvxTextEditSource( SvxTextEditSourceImpl
* pImpl
)
1054 //------------------------------------------------------------------------
1055 SvxTextEditSource::~SvxTextEditSource()
1057 OGuard
aGuard( Application::GetSolarMutex() );
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()
1086 //------------------------------------------------------------------------
1087 void SvxTextEditSource::UpdateData()
1089 mpImpl
->UpdateData();
1092 SfxBroadcaster
& SvxTextEditSource::GetBroadcaster() const
1097 SdrObject
* SvxTextEditSource::GetSdrObject() const
1099 return mpImpl
->GetSdrObject();
1102 void SvxTextEditSource::lock()
1107 void SvxTextEditSource::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
);