1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/uno/XInterface.hpp>
21 #include <vcl/svapp.hxx>
23 #include <svx/unoshtxt.hxx>
24 #include <editeng/unoedhlp.hxx>
25 #include <svl/lstner.hxx>
26 #include <rtl/ref.hxx>
27 #include <osl/mutex.hxx>
28 #include <svl/hint.hxx>
29 #include <svl/style.hxx>
30 #include <svx/svdmodel.hxx>
31 #include <svx/svdoutl.hxx>
32 #include <svx/svdobj.hxx>
33 #include <svx/svdview.hxx>
34 #include <svx/svdetc.hxx>
35 #include <editeng/outliner.hxx>
36 #include <editeng/unoforou.hxx>
37 #include <editeng/unoviwou.hxx>
38 #include <editeng/outlobj.hxx>
39 #include <svx/svdotext.hxx>
40 #include <svx/svdpage.hxx>
41 #include <editeng/editeng.hxx>
42 #include <editeng/editobj.hxx>
44 #include <editeng/unotext.hxx>
45 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
46 #include <comphelper/processfactory.hxx>
47 #include <svx/sdrpaintwindow.hxx>
49 using namespace ::osl
;
50 using namespace ::rtl
;
52 using ::com::sun::star::uno::XInterface
;
54 //------------------------------------------------------------------------
55 // SvxTextEditSourceImpl
56 //------------------------------------------------------------------------
59 <p>This class essentially provides the text and view forwarders. If
60 no SdrView is given, this class handles the UNO objects, which are
61 currently not concerned with view issues. In this case,
62 GetViewForwarder() always returns NULL and the underlying
63 EditEngine of the SvxTextForwarder is a background one (i.e. not
64 the official DrawOutliner, but one created exclusively for this
65 object, with no relation to a view).
68 <p>If a SdrView is given at construction time, the caller is
69 responsible for destroying this object when the view becomes
70 invalid (the views cannot notify). If GetViewForwarder(sal_True)
71 is called, the underlying shape is put into edit mode, the view
72 forwarder returned encapsulates the OutlinerView and the next call
73 to GetTextForwarder() yields a forwarder encapsulating the actual
74 DrawOutliner. Thus, changes on that Outliner are immediately
75 reflected on the screen. If the object leaves edit mode, the old
76 behaviour is restored.</p>
78 class SvxTextEditSourceImpl
: public SfxListener
, public SfxBroadcaster
, public sdr::ObjectUser
81 oslInterlockedCount maRefCount
;
86 const Window
* mpWindow
;
88 SdrOutliner
* mpOutliner
;
89 SvxOutlinerForwarder
* mpTextForwarder
;
90 SvxDrawOutlinerViewForwarder
* mpViewForwarder
; // if non-NULL, use GetViewModeTextForwarder text forwarder
91 css::uno::Reference
< css::linguistic2::XLinguServiceManager2
> m_xLinguServiceManager
;
97 sal_Bool mbOldUndoMode
;
98 bool mbForwarderIsEditMode
; // have to reflect that, since ENDEDIT can happen more often
99 bool mbShapeIsEditMode
; // #104157# only true, if HINT_BEGEDIT was received
100 bool mbNotificationsDisabled
; // prevent EditEngine/Outliner notifications (e.g. when setting up forwarder)
103 SvxUnoTextRangeBaseList maTextRanges
;
105 SvxTextForwarder
* GetBackgroundTextForwarder();
106 SvxTextForwarder
* GetEditModeTextForwarder();
107 SvxDrawOutlinerViewForwarder
* CreateViewForwarder();
109 void SetupOutliner();
111 bool HasView() const { return mpView
? true : false; }
112 bool IsEditMode() const
114 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
115 return mbShapeIsEditMode
&& pTextObj
&& pTextObj
->IsTextEditActive() ? true : false;
121 SvxTextEditSourceImpl( SdrObject
* pObject
, SdrText
* pText
, XInterface
* pOwner
);
122 SvxTextEditSourceImpl( SdrObject
& rObject
, SdrText
* pText
, SdrView
& rView
, const Window
& rWindow
);
123 ~SvxTextEditSourceImpl();
125 void SAL_CALL
acquire();
126 void SAL_CALL
release();
128 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
);
130 SvxEditSource
* Clone() const;
131 SvxTextForwarder
* GetTextForwarder();
132 SvxEditViewForwarder
* GetEditViewForwarder( sal_Bool
);
135 void addRange( SvxUnoTextRangeBase
* pNewRange
);
136 void removeRange( SvxUnoTextRangeBase
* pOldRange
);
137 const SvxUnoTextRangeBaseList
& getRanges() const;
139 SdrObject
* GetSdrObject() const { return mpObject
; }
144 sal_Bool
IsValid() const;
146 Rectangle
GetVisArea();
147 Point
LogicToPixel( const Point
&, const MapMode
& rMapMode
);
148 Point
PixelToLogic( const Point
&, const MapMode
& rMapMode
);
150 DECL_LINK( NotifyHdl
, EENotify
* );
152 virtual void ObjectInDestruction(const SdrObject
& rObject
);
154 void ChangeModel( SdrModel
* pNewModel
);
156 void UpdateOutliner();
159 //------------------------------------------------------------------------
161 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject
* pObject
, SdrText
* pText
, XInterface
* pOwner
)
163 mpObject ( pObject
),
167 mpModel ( pObject
? pObject
->GetModel() : NULL
),
169 mpTextForwarder ( NULL
),
170 mpViewForwarder ( NULL
),
171 mbDataValid ( false ),
172 mbDestroyed ( false ),
173 mbIsLocked ( false ),
174 mbNeedsUpdate ( false ),
175 mbOldUndoMode ( sal_False
),
176 mbForwarderIsEditMode ( false ),
177 mbShapeIsEditMode ( false ),
178 mbNotificationsDisabled ( false ),
181 DBG_ASSERT( mpObject
, "invalid pObject!" );
185 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( mpObject
);
187 mpText
= pTextObj
->getText( 0 );
191 StartListening( *mpModel
);
194 mpObject
->AddObjectUser( *this );
197 //------------------------------------------------------------------------
199 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject
& rObject
, SdrText
* pText
, SdrView
& rView
, const Window
& rWindow
)
201 mpObject ( &rObject
),
204 mpWindow ( &rWindow
),
205 mpModel ( rObject
.GetModel() ),
207 mpTextForwarder ( NULL
),
208 mpViewForwarder ( NULL
),
209 mbDataValid ( false ),
210 mbDestroyed ( false ),
211 mbIsLocked ( false ),
212 mbNeedsUpdate ( false ),
213 mbOldUndoMode ( sal_False
),
214 mbForwarderIsEditMode ( false ),
215 mbShapeIsEditMode ( true ),
216 mbNotificationsDisabled ( false ),
221 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( mpObject
);
223 mpText
= pTextObj
->getText( 0 );
227 StartListening( *mpModel
);
229 StartListening( *mpView
);
231 mpObject
->AddObjectUser( *this );
233 // #104157# Init edit mode state from shape info (IsTextEditActive())
234 mbShapeIsEditMode
= IsEditMode();
237 //------------------------------------------------------------------------
239 SvxTextEditSourceImpl::~SvxTextEditSourceImpl()
241 DBG_ASSERT( mbIsLocked
== false, "text edit source was not unlocked before dispose!" );
243 mpObject
->RemoveObjectUser( *this );
248 //------------------------------------------------------------------------
250 void SvxTextEditSourceImpl::addRange( SvxUnoTextRangeBase
* pNewRange
)
253 if( std::find( maTextRanges
.begin(), maTextRanges
.end(), pNewRange
) == maTextRanges
.end() )
254 maTextRanges
.push_back( pNewRange
);
257 //------------------------------------------------------------------------
259 void SvxTextEditSourceImpl::removeRange( SvxUnoTextRangeBase
* pOldRange
)
262 maTextRanges
.remove( pOldRange
);
265 //------------------------------------------------------------------------
267 const SvxUnoTextRangeBaseList
& SvxTextEditSourceImpl::getRanges() const
272 //------------------------------------------------------------------------
274 void SAL_CALL
SvxTextEditSourceImpl::acquire()
276 osl_atomic_increment( &maRefCount
);
279 //------------------------------------------------------------------------
281 void SAL_CALL
SvxTextEditSourceImpl::release()
283 if( ! osl_atomic_decrement( &maRefCount
) )
287 void SvxTextEditSourceImpl::ChangeModel( SdrModel
* pNewModel
)
289 if( mpModel
!= pNewModel
)
292 EndListening( *mpModel
);
297 mpModel
->disposeOutliner( mpOutliner
);
305 EndListening( *mpView
);
310 m_xLinguServiceManager
.clear();
315 if( mpTextForwarder
)
317 delete mpTextForwarder
;
321 if( mpViewForwarder
)
323 delete mpViewForwarder
;
328 StartListening( *mpModel
);
332 //------------------------------------------------------------------------
334 void SvxTextEditSourceImpl::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
336 // #i105988 keep reference to this object
337 rtl::Reference
< SvxTextEditSourceImpl
> xThis( this );
339 const SdrHint
* pSdrHint
= PTR_CAST( SdrHint
, &rHint
);
340 const SvxViewHint
* pViewHint
= PTR_CAST( SvxViewHint
, &rHint
);
344 switch( pViewHint
->GetHintType() )
346 case SvxViewHint::SVX_HINT_VIEWCHANGED
:
347 Broadcast( *pViewHint
);
353 switch( pSdrHint
->GetKind() )
357 mbDataValid
= false; // Text muss neu geholt werden
361 // #104157# Update maTextOffset, object has changed
362 // #105196#, #105203#: Cannot call that // here,
363 // since TakeTextRect() (called from there) //
364 // changes outliner content.
367 // #101029# Broadcast object changes, as they might change visible attributes
368 SvxViewHint
aHint(SvxViewHint::SVX_HINT_VIEWCHANGED
);
375 if( mpObject
== pSdrHint
->GetObject() )
377 // invalidate old forwarder
378 if( !mbForwarderIsEditMode
)
380 delete mpTextForwarder
;
381 mpTextForwarder
= NULL
;
384 // register as listener - need to broadcast state change messages
385 if( mpView
&& mpView
->GetTextEditOutliner() )
386 mpView
->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl
, NotifyHdl
) );
388 // #104157# Only now we're really in edit mode
389 mbShapeIsEditMode
= true;
391 Broadcast( *pSdrHint
);
396 if( mpObject
== pSdrHint
->GetObject() )
398 Broadcast( *pSdrHint
);
400 // #104157# We're no longer in edit mode
401 mbShapeIsEditMode
= false;
403 // remove as listener - outliner might outlive ourselves
404 if( mpView
&& mpView
->GetTextEditOutliner() )
405 mpView
->GetTextEditOutliner()->SetNotifyHdl( Link() );
407 // destroy view forwarder, OutlinerView no longer
408 // valid (no need for UpdateData(), it's been
409 // synched on SdrEndTextEdit)
410 delete mpViewForwarder
;
411 mpViewForwarder
= NULL
;
413 // #100424# Invalidate text forwarder, we might
414 // not be called again before entering edit mode a
415 // second time! Then, the old outliner might be
417 if( mbForwarderIsEditMode
)
419 mbForwarderIsEditMode
= false;
420 delete mpTextForwarder
;
421 mpTextForwarder
= NULL
;
426 case HINT_MODELCLEARED
:
435 /* this is a callback from the attached SdrObject when it is actually deleted */
436 void SvxTextEditSourceImpl::ObjectInDestruction(const SdrObject
&)
440 Broadcast( SfxSimpleHint( SFX_HINT_DYING
) );
443 /* unregister at all objects and set all references to 0 */
444 void SvxTextEditSourceImpl::dispose()
446 if( mpTextForwarder
)
448 delete mpTextForwarder
;
452 if( mpViewForwarder
)
454 delete mpViewForwarder
;
462 mpModel
->disposeOutliner( mpOutliner
);
473 EndListening( *mpModel
);
479 EndListening( *mpView
);
485 mpObject
->RemoveObjectUser( *this );
491 //------------------------------------------------------------------------
493 void SvxTextEditSourceImpl::SetupOutliner()
496 // only for UAA edit source: setup outliner equivalently as in
497 // SdrTextObj::Paint(), such that formatting equals screen
499 if( mpObject
&& mpOutliner
)
501 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
502 Rectangle aPaintRect
;
505 Rectangle
aBoundRect( pTextObj
->GetCurrentBoundRect() );
506 pTextObj
->SetupOutlinerFormatting( *mpOutliner
, aPaintRect
);
508 // #101029# calc text offset from shape anchor
509 maTextOffset
= aPaintRect
.TopLeft() - aBoundRect
.TopLeft();
514 //------------------------------------------------------------------------
516 void SvxTextEditSourceImpl::UpdateOutliner()
519 // only for UAA edit source: update outliner equivalently as in
520 // SdrTextObj::Paint(), such that formatting equals screen
522 if( mpObject
&& mpOutliner
)
524 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
525 Rectangle aPaintRect
;
528 Rectangle
aBoundRect( pTextObj
->GetCurrentBoundRect() );
529 pTextObj
->UpdateOutlinerFormatting( *mpOutliner
, aPaintRect
);
531 // #101029# calc text offset from shape anchor
532 maTextOffset
= aPaintRect
.TopLeft() - aBoundRect
.TopLeft();
537 //------------------------------------------------------------------------
541 SvxTextForwarder
* SvxTextEditSourceImpl::GetBackgroundTextForwarder()
543 bool bCreated
= false;
545 // #99840#: prevent EE/Outliner notifications during setup
546 mbNotificationsDisabled
= true;
548 if (!mpTextForwarder
)
550 if( mpOutliner
== NULL
)
552 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
553 sal_uInt16 nOutlMode
= OUTLINERMODE_TEXTOBJECT
;
554 if( pTextObj
&& pTextObj
->IsTextFrame() && pTextObj
->GetTextKind() == OBJ_OUTLINETEXT
)
555 nOutlMode
= OUTLINERMODE_OUTLINEOBJECT
;
557 mpOutliner
= mpModel
->createOutliner( nOutlMode
);
559 // #109151# Do the setup after outliner creation, would be useless otherwise
562 // #101029#, #104157# Setup outliner _before_ filling it
566 mpOutliner
->SetTextObjNoInit( pTextObj
);
569 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->SetUpdateMode( sal_False
);
570 mbOldUndoMode
= ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->IsUndoEnabled();
571 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->EnableUndo( sal_False
);
574 if ( !m_xLinguServiceManager
.is() )
576 css::uno::Reference
< css::uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
577 m_xLinguServiceManager
.set(css::linguistic2::LinguServiceManager::create(xContext
));
580 css::uno::Reference
< css::linguistic2::XHyphenator
> xHyphenator( m_xLinguServiceManager
->getHyphenator(), css::uno::UNO_QUERY
);
581 if( xHyphenator
.is() )
582 mpOutliner
->SetHyphenator( xHyphenator
);
586 mpTextForwarder
= new SvxOutlinerForwarder( *mpOutliner
, (mpObject
->GetObjInventor() == SdrInventor
) && (mpObject
->GetObjIdentifier() == OBJ_OUTLINETEXT
) );
587 // delay listener subscription and UAA initialization until Outliner is fully setup
590 mbForwarderIsEditMode
= false;
593 if( mpObject
&& mpText
&& !mbDataValid
&& mpObject
->IsInserted() && mpObject
->GetPage() )
595 mpTextForwarder
->flushCache();
597 OutlinerParaObject
* pOutlinerParaObject
= NULL
;
598 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
599 if( pTextObj
&& pTextObj
->getActiveText() == mpText
)
600 pOutlinerParaObject
= pTextObj
->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
601 bool bOwnParaObj(false);
603 if( pOutlinerParaObject
)
604 bOwnParaObj
= true; // text edit active
606 pOutlinerParaObject
= mpText
->GetOutlinerParaObject();
608 if( pOutlinerParaObject
&& ( bOwnParaObj
|| !mpObject
->IsEmptyPresObj() || mpObject
->GetPage()->IsMasterPage() ) )
610 mpOutliner
->SetText( *pOutlinerParaObject
);
612 // #91254# put text to object and set EmptyPresObj to FALSE
613 if( mpText
&& bOwnParaObj
&& pOutlinerParaObject
&& mpObject
->IsEmptyPresObj() && pTextObj
->IsRealyEdited() )
615 mpObject
->SetEmptyPresObj( sal_False
);
616 static_cast< SdrTextObj
* >( mpObject
)->NbcSetOutlinerParaObjectForText( pOutlinerParaObject
, mpText
);
618 // #i103982# Here, due to mpObject->NbcSetOutlinerParaObjectForText, we LOSE ownership of the
619 // OPO, so do NOT delete it when leaving this method (!)
625 bool bVertical
= pOutlinerParaObject
? pOutlinerParaObject
->IsVertical() : false;
627 // set objects style sheet on empty outliner
628 SfxStyleSheetPool
* pPool
= (SfxStyleSheetPool
*)mpObject
->GetModel()->GetStyleSheetPool();
630 mpOutliner
->SetStyleSheetPool( pPool
);
632 SfxStyleSheet
* pStyleSheet
= mpObject
->GetPage()->GetTextStyleSheetForObject( mpObject
);
634 mpOutliner
->SetStyleSheet( 0, pStyleSheet
);
637 mpOutliner
->SetVertical( sal_True
);
640 // evtually we have to set the border attributes
641 if (mpOutliner
->GetParagraphCount()==1)
643 // if we only have one paragraph we check if it is empty
644 OUString
aStr(mpOutliner
->GetText(mpOutliner
->GetParagraph(0)));
648 // its empty, so we have to force the outliner to initialise itself
649 mpOutliner
->SetText( String(), mpOutliner
->GetParagraph( 0 ) );
651 if(mpObject
->GetStyleSheet())
652 mpOutliner
->SetStyleSheet( 0, mpObject
->GetStyleSheet());
659 delete pOutlinerParaObject
;
662 if( bCreated
&& mpOutliner
&& HasView() )
664 // register as listener - need to broadcast state change messages
665 // registration delayed until outliner is completely set up
666 mpOutliner
->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl
, NotifyHdl
) );
669 // #99840#: prevent EE/Outliner notifications during setup
670 mbNotificationsDisabled
= false;
672 return mpTextForwarder
;
675 //------------------------------------------------------------------------
677 SvxTextForwarder
* SvxTextEditSourceImpl::GetEditModeTextForwarder()
679 if( !mpTextForwarder
&& HasView() )
681 SdrOutliner
* pEditOutliner
= mpView
->GetTextEditOutliner();
685 mpTextForwarder
= new SvxOutlinerForwarder( *pEditOutliner
, (mpObject
->GetObjInventor() == SdrInventor
) && (mpObject
->GetObjIdentifier() == OBJ_OUTLINETEXT
) );
686 mbForwarderIsEditMode
= true;
690 return mpTextForwarder
;
693 //------------------------------------------------------------------------
695 SvxTextForwarder
* SvxTextEditSourceImpl::GetTextForwarder()
697 if( mbDestroyed
|| mpObject
== NULL
)
700 if( mpModel
== NULL
)
701 mpModel
= mpObject
->GetModel();
703 if( mpModel
== NULL
)
706 // distinguish the cases
707 // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner
708 // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code)
711 if( IsEditMode() != mbForwarderIsEditMode
)
713 // forwarder mismatch - create new
714 delete mpTextForwarder
;
715 mpTextForwarder
= NULL
;
719 return GetEditModeTextForwarder();
721 return GetBackgroundTextForwarder();
724 return GetBackgroundTextForwarder();
727 //------------------------------------------------------------------------
729 SvxDrawOutlinerViewForwarder
* SvxTextEditSourceImpl::CreateViewForwarder()
731 if( mpView
->GetTextEditOutlinerView() && mpObject
)
733 // register as listener - need to broadcast state change messages
734 mpView
->GetTextEditOutliner()->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl
, NotifyHdl
) );
736 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
739 Rectangle
aBoundRect( pTextObj
->GetCurrentBoundRect() );
740 OutlinerView
& rOutlView
= *mpView
->GetTextEditOutlinerView();
742 return new SvxDrawOutlinerViewForwarder( rOutlView
, aBoundRect
.TopLeft() );
749 SvxEditViewForwarder
* SvxTextEditSourceImpl::GetEditViewForwarder( sal_Bool bCreate
)
751 if( mbDestroyed
|| mpObject
== NULL
)
754 if( mpModel
== NULL
)
755 mpModel
= mpObject
->GetModel();
757 if( mpModel
== NULL
)
761 if( mpViewForwarder
)
765 // destroy all forwarders (no need for UpdateData(),
766 // it's been synched on SdrEndTextEdit)
767 delete mpViewForwarder
;
768 mpViewForwarder
= NULL
;
771 // which to create? Directly in edit mode, create new, or none?
776 // create new view forwarder
777 mpViewForwarder
= CreateViewForwarder();
781 // dispose old text forwarder
784 delete mpTextForwarder
;
785 mpTextForwarder
= NULL
;
788 mpView
->SdrEndTextEdit();
790 if(mpView
->SdrBeginTextEdit(mpObject
, 0L, 0L, sal_False
, (SdrOutliner
*)0L, 0L, sal_False
, sal_False
))
792 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
793 if( pTextObj
->IsTextEditActive() )
795 // create new view forwarder
796 mpViewForwarder
= CreateViewForwarder();
800 // failure. Somehow, SdrBeginTextEdit did not set
801 // our SdrTextObj into edit mode
802 mpView
->SdrEndTextEdit();
808 return mpViewForwarder
;
811 //------------------------------------------------------------------------
813 void SvxTextEditSourceImpl::UpdateData()
815 // if we have a view and in edit mode, we're working with the
816 // DrawOutliner. Thus, all changes made on the text forwarder are
817 // reflected on the view and committed to the model on
818 // SdrEndTextEdit(). Thus, no need for explicit updates here.
819 if( !HasView() || !IsEditMode() )
823 mbNeedsUpdate
= true;
827 if( mpOutliner
&& mpObject
&& mpText
&& !mbDestroyed
)
829 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >( mpObject
);
832 if( mpOutliner
->GetParagraphCount() != 1 || mpOutliner
->GetEditEngine().GetTextLen( 0 ) )
834 if( mpOutliner
->GetParagraphCount() > 1 )
836 if( pTextObj
&& pTextObj
->IsTextFrame() && pTextObj
->GetTextKind() == OBJ_TITLETEXT
)
838 while( mpOutliner
->GetParagraphCount() > 1 )
840 ESelection
aSel( 0,mpOutliner
->GetEditEngine().GetTextLen( 0 ), 1,0 );
841 mpOutliner
->QuickInsertLineBreak( aSel
);
846 pTextObj
->NbcSetOutlinerParaObjectForText( mpOutliner
->CreateParaObject(), mpText
);
850 pTextObj
->NbcSetOutlinerParaObjectForText( NULL
,mpText
);
854 if( mpObject
->IsEmptyPresObj() )
855 mpObject
->SetEmptyPresObj(sal_False
);
861 void SvxTextEditSourceImpl::lock()
866 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->SetUpdateMode( sal_False
);
867 mbOldUndoMode
= ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->IsUndoEnabled();
868 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->EnableUndo( sal_False
);
872 void SvxTextEditSourceImpl::unlock()
879 mbNeedsUpdate
= false;
884 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->SetUpdateMode( sal_True
);
885 ((EditEngine
*)&(mpOutliner
->GetEditEngine()))->EnableUndo( mbOldUndoMode
);
889 sal_Bool
SvxTextEditSourceImpl::IsValid() const
891 return mpView
&& mpWindow
? sal_True
: sal_False
;
894 Rectangle
SvxTextEditSourceImpl::GetVisArea()
898 SdrPaintWindow
* pPaintWindow
= mpView
->FindPaintWindow(*mpWindow
);
903 aVisArea
= pPaintWindow
->GetVisibleArea();
906 // offset vis area by edit engine left-top position
907 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, mpObject
);
910 Rectangle aAnchorRect
;
911 pTextObj
->TakeTextAnchorRect( aAnchorRect
);
912 aVisArea
.Move( -aAnchorRect
.Left(), -aAnchorRect
.Top() );
914 MapMode
aMapMode(mpWindow
->GetMapMode());
915 aMapMode
.SetOrigin(Point());
916 return mpWindow
->LogicToPixel( aVisArea
, aMapMode
);
923 Point
SvxTextEditSourceImpl::LogicToPixel( const Point
& rPoint
, const MapMode
& rMapMode
)
925 // #101029#: The responsibilities of ViewForwarder happen to be
926 // somewhat mixed in this case. On the one hand, we need the
927 // different interface queries on the SvxEditSource interface,
928 // since we need both VisAreas. On the other hand, if an
929 // EditViewForwarder exists, maTextOffset does not remain static,
930 // but may change with every key press.
933 SvxEditViewForwarder
* pForwarder
= GetEditViewForwarder(sal_False
);
936 return pForwarder
->LogicToPixel( rPoint
, rMapMode
);
938 else if( IsValid() && mpModel
)
941 Point
aPoint1( rPoint
);
942 aPoint1
.X() += maTextOffset
.X();
943 aPoint1
.Y() += maTextOffset
.Y();
945 Point
aPoint2( OutputDevice::LogicToLogic( aPoint1
, rMapMode
,
946 MapMode(mpModel
->GetScaleUnit()) ) );
947 MapMode
aMapMode(mpWindow
->GetMapMode());
948 aMapMode
.SetOrigin(Point());
949 return mpWindow
->LogicToPixel( aPoint2
, aMapMode
);
955 Point
SvxTextEditSourceImpl::PixelToLogic( const Point
& rPoint
, const MapMode
& rMapMode
)
957 // #101029#: The responsibilities of ViewForwarder happen to be
958 // somewhat mixed in this case. On the one hand, we need the
959 // different interface queries on the SvxEditSource interface,
960 // since we need both VisAreas. On the other hand, if an
961 // EditViewForwarder exists, maTextOffset does not remain static,
962 // but may change with every key press.
965 SvxEditViewForwarder
* pForwarder
= GetEditViewForwarder(sal_False
);
968 return pForwarder
->PixelToLogic( rPoint
, rMapMode
);
970 else if( IsValid() && mpModel
)
972 MapMode
aMapMode(mpWindow
->GetMapMode());
973 aMapMode
.SetOrigin(Point());
974 Point
aPoint1( mpWindow
->PixelToLogic( rPoint
, aMapMode
) );
975 Point
aPoint2( OutputDevice::LogicToLogic( aPoint1
,
976 MapMode(mpModel
->GetScaleUnit()),
979 aPoint2
.X() -= maTextOffset
.X();
980 aPoint2
.Y() -= maTextOffset
.Y();
988 IMPL_LINK(SvxTextEditSourceImpl
, NotifyHdl
, EENotify
*, aNotify
)
990 if( aNotify
&& !mbNotificationsDisabled
)
992 ::std::auto_ptr
< SfxHint
> aHint( SvxEditSourceHelper::EENotification2Hint( aNotify
) );
995 Broadcast( *aHint
.get() );
1001 //------------------------------------------------------------------------
1003 // --------------------------------------------------------------------
1004 // SvxTextEditSource
1005 // --------------------------------------------------------------------
1007 SvxTextEditSource::SvxTextEditSource( SdrObject
* pObject
, SdrText
* pText
, XInterface
* pOwner
)
1009 mpImpl
= new SvxTextEditSourceImpl( pObject
, pText
, pOwner
);
1013 // --------------------------------------------------------------------
1014 SvxTextEditSource::SvxTextEditSource( SdrObject
& rObj
, SdrText
* pText
, SdrView
& rView
, const Window
& rWindow
)
1016 mpImpl
= new SvxTextEditSourceImpl( rObj
, pText
, rView
, rWindow
);
1020 // --------------------------------------------------------------------
1022 SvxTextEditSource::SvxTextEditSource( SvxTextEditSourceImpl
* pImpl
)
1028 //------------------------------------------------------------------------
1029 SvxTextEditSource::~SvxTextEditSource()
1031 ::SolarMutexGuard aGuard
;
1036 //------------------------------------------------------------------------
1037 SvxEditSource
* SvxTextEditSource::Clone() const
1039 return new SvxTextEditSource( mpImpl
);
1042 //------------------------------------------------------------------------
1043 SvxTextForwarder
* SvxTextEditSource::GetTextForwarder()
1045 return mpImpl
->GetTextForwarder();
1048 //------------------------------------------------------------------------
1049 SvxEditViewForwarder
* SvxTextEditSource::GetEditViewForwarder( sal_Bool bCreate
)
1051 return mpImpl
->GetEditViewForwarder( bCreate
);
1054 //------------------------------------------------------------------------
1055 SvxViewForwarder
* SvxTextEditSource::GetViewForwarder()
1060 //------------------------------------------------------------------------
1061 void SvxTextEditSource::UpdateData()
1063 mpImpl
->UpdateData();
1066 SfxBroadcaster
& SvxTextEditSource::GetBroadcaster() const
1071 void SvxTextEditSource::lock()
1076 void SvxTextEditSource::unlock()
1081 sal_Bool
SvxTextEditSource::IsValid() const
1083 return mpImpl
->IsValid();
1086 Rectangle
SvxTextEditSource::GetVisArea() const
1088 return mpImpl
->GetVisArea();
1091 Point
SvxTextEditSource::LogicToPixel( const Point
& rPoint
, const MapMode
& rMapMode
) const
1093 return mpImpl
->LogicToPixel( rPoint
, rMapMode
);
1096 Point
SvxTextEditSource::PixelToLogic( const Point
& rPoint
, const MapMode
& rMapMode
) const
1098 return mpImpl
->PixelToLogic( rPoint
, rMapMode
);
1101 void SvxTextEditSource::addRange( SvxUnoTextRangeBase
* pNewRange
)
1103 mpImpl
->addRange( pNewRange
);
1106 void SvxTextEditSource::removeRange( SvxUnoTextRangeBase
* pOldRange
)
1108 mpImpl
->removeRange( pOldRange
);
1111 const SvxUnoTextRangeBaseList
& SvxTextEditSource::getRanges() const
1113 return mpImpl
->getRanges();
1116 void SvxTextEditSource::ChangeModel( SdrModel
* pNewModel
)
1118 mpImpl
->ChangeModel( pNewModel
);
1121 void SvxTextEditSource::UpdateOutliner()
1123 mpImpl
->UpdateOutliner();
1126 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */