bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / unodraw / unoshtxt.cxx
blob0324abb1fbe8980c14da506ea93fd35f07f8a158
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 //------------------------------------------------------------------------
58 /** @descr
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).
66 </p>
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
80 private:
81 oslInterlockedCount maRefCount;
83 SdrObject* mpObject;
84 SdrText* mpText;
85 SdrView* mpView;
86 const Window* mpWindow;
87 SdrModel* mpModel;
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;
92 Point maTextOffset;
93 bool mbDataValid;
94 bool mbDestroyed;
95 bool mbIsLocked;
96 bool mbNeedsUpdate;
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)
102 XInterface* mpOwner;
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;
118 void dispose();
120 public:
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 );
133 void UpdateData();
135 void addRange( SvxUnoTextRangeBase* pNewRange );
136 void removeRange( SvxUnoTextRangeBase* pOldRange );
137 const SvxUnoTextRangeBaseList& getRanges() const;
139 SdrObject* GetSdrObject() const { return mpObject; }
141 void lock();
142 void unlock();
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 )
162 : maRefCount ( 0 ),
163 mpObject ( pObject ),
164 mpText ( pText ),
165 mpView ( NULL ),
166 mpWindow ( NULL ),
167 mpModel ( pObject ? pObject->GetModel() : NULL ),
168 mpOutliner ( 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 ),
179 mpOwner( pOwner )
181 DBG_ASSERT( mpObject, "invalid pObject!" );
183 if( !mpText )
185 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
186 if( pTextObj )
187 mpText = pTextObj->getText( 0 );
190 if( mpModel )
191 StartListening( *mpModel );
193 if( mpObject )
194 mpObject->AddObjectUser( *this );
197 //------------------------------------------------------------------------
199 SvxTextEditSourceImpl::SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const Window& rWindow )
200 : maRefCount ( 0 ),
201 mpObject ( &rObject ),
202 mpText ( pText ),
203 mpView ( &rView ),
204 mpWindow ( &rWindow ),
205 mpModel ( rObject.GetModel() ),
206 mpOutliner ( NULL ),
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 ),
217 mpOwner(0)
219 if( !mpText )
221 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
222 if( pTextObj )
223 mpText = pTextObj->getText( 0 );
226 if( mpModel )
227 StartListening( *mpModel );
228 if( mpView )
229 StartListening( *mpView );
230 if( mpObject )
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!" );
242 if( mpObject )
243 mpObject->RemoveObjectUser( *this );
245 dispose();
248 //------------------------------------------------------------------------
250 void SvxTextEditSourceImpl::addRange( SvxUnoTextRangeBase* pNewRange )
252 if( pNewRange )
253 if( std::find( maTextRanges.begin(), maTextRanges.end(), pNewRange ) == maTextRanges.end() )
254 maTextRanges.push_back( pNewRange );
257 //------------------------------------------------------------------------
259 void SvxTextEditSourceImpl::removeRange( SvxUnoTextRangeBase* pOldRange )
261 if( pOldRange )
262 maTextRanges.remove( pOldRange );
265 //------------------------------------------------------------------------
267 const SvxUnoTextRangeBaseList& SvxTextEditSourceImpl::getRanges() const
269 return maTextRanges;
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 ) )
284 delete this;
287 void SvxTextEditSourceImpl::ChangeModel( SdrModel* pNewModel )
289 if( mpModel != pNewModel )
291 if( mpModel )
292 EndListening( *mpModel );
294 if( mpOutliner )
296 if( mpModel )
297 mpModel->disposeOutliner( mpOutliner );
298 else
299 delete mpOutliner;
300 mpOutliner = 0;
303 if( mpView )
305 EndListening( *mpView );
306 mpView = 0;
309 mpWindow = 0;
310 m_xLinguServiceManager.clear();
311 mpOwner = 0;
313 mpModel = pNewModel;
315 if( mpTextForwarder )
317 delete mpTextForwarder;
318 mpTextForwarder = 0;
321 if( mpViewForwarder )
323 delete mpViewForwarder;
324 mpViewForwarder = 0;
327 if( mpModel )
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 );
342 if( pViewHint )
344 switch( pViewHint->GetHintType() )
346 case SvxViewHint::SVX_HINT_VIEWCHANGED:
347 Broadcast( *pViewHint );
348 break;
351 else if( pSdrHint )
353 switch( pSdrHint->GetKind() )
355 case HINT_OBJCHG:
357 mbDataValid = false; // Text muss neu geholt werden
359 if( HasView() )
361 // #104157# Update maTextOffset, object has changed
362 // #105196#, #105203#: Cannot call that // here,
363 // since TakeTextRect() (called from there) //
364 // changes outliner content.
365 // UpdateOutliner();
367 // #101029# Broadcast object changes, as they might change visible attributes
368 SvxViewHint aHint(SvxViewHint::SVX_HINT_VIEWCHANGED);
369 Broadcast( aHint );
371 break;
374 case HINT_BEGEDIT:
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 );
393 break;
395 case HINT_ENDEDIT:
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
416 // invalid.
417 if( mbForwarderIsEditMode )
419 mbForwarderIsEditMode = false;
420 delete mpTextForwarder;
421 mpTextForwarder = NULL;
424 break;
426 case HINT_MODELCLEARED:
427 dispose();
428 break;
429 default:
430 break;
435 /* this is a callback from the attached SdrObject when it is actually deleted */
436 void SvxTextEditSourceImpl::ObjectInDestruction(const SdrObject&)
438 mpObject = 0;
439 dispose();
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;
449 mpTextForwarder = 0;
452 if( mpViewForwarder )
454 delete mpViewForwarder;
455 mpViewForwarder = 0;
458 if( mpOutliner )
460 if( mpModel )
462 mpModel->disposeOutliner( mpOutliner );
464 else
466 delete mpOutliner;
468 mpOutliner = 0;
471 if( mpModel )
473 EndListening( *mpModel );
474 mpModel = 0;
477 if( mpView )
479 EndListening( *mpView );
480 mpView = 0;
483 if( mpObject )
485 mpObject->RemoveObjectUser( *this );
486 mpObject = 0;
488 mpWindow = 0;
491 //------------------------------------------------------------------------
493 void SvxTextEditSourceImpl::SetupOutliner()
495 // #101029#
496 // only for UAA edit source: setup outliner equivalently as in
497 // SdrTextObj::Paint(), such that formatting equals screen
498 // layout
499 if( mpObject && mpOutliner )
501 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
502 Rectangle aPaintRect;
503 if( pTextObj )
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()
518 // #104157#
519 // only for UAA edit source: update outliner equivalently as in
520 // SdrTextObj::Paint(), such that formatting equals screen
521 // layout
522 if( mpObject && mpOutliner )
524 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
525 Rectangle aPaintRect;
526 if( pTextObj )
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
560 if( HasView() )
562 // #101029#, #104157# Setup outliner _before_ filling it
563 SetupOutliner();
566 mpOutliner->SetTextObjNoInit( pTextObj );
567 if( mbIsLocked )
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
588 bCreated = true;
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
605 else
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 (!)
620 bOwnParaObj = false;
623 else
625 bool bVertical = pOutlinerParaObject ? pOutlinerParaObject->IsVertical() : false;
627 // set objects style sheet on empty outliner
628 SfxStyleSheetPool* pPool = (SfxStyleSheetPool*)mpObject->GetModel()->GetStyleSheetPool();
629 if( pPool )
630 mpOutliner->SetStyleSheetPool( pPool );
632 SfxStyleSheet* pStyleSheet = mpObject->GetPage()->GetTextStyleSheetForObject( mpObject );
633 if( pStyleSheet )
634 mpOutliner->SetStyleSheet( 0, pStyleSheet );
636 if( bVertical )
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)));
646 if (aStr.isEmpty())
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());
656 mbDataValid = true;
658 if( bOwnParaObj )
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();
683 if( pEditOutliner )
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 )
698 return NULL;
700 if( mpModel == NULL )
701 mpModel = mpObject->GetModel();
703 if( mpModel == NULL )
704 return 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)
709 if( HasView() )
711 if( IsEditMode() != mbForwarderIsEditMode )
713 // forwarder mismatch - create new
714 delete mpTextForwarder;
715 mpTextForwarder = NULL;
718 if( IsEditMode() )
719 return GetEditModeTextForwarder();
720 else
721 return GetBackgroundTextForwarder();
723 else
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 );
737 if( pTextObj )
739 Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
740 OutlinerView& rOutlView = *mpView->GetTextEditOutlinerView();
742 return new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() );
746 return NULL;
749 SvxEditViewForwarder* SvxTextEditSourceImpl::GetEditViewForwarder( sal_Bool bCreate )
751 if( mbDestroyed || mpObject == NULL )
752 return NULL;
754 if( mpModel == NULL )
755 mpModel = mpObject->GetModel();
757 if( mpModel == NULL )
758 return NULL;
760 // shall we delete?
761 if( mpViewForwarder )
763 if( !IsEditMode() )
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?
772 else if( mpView )
774 if( IsEditMode() )
776 // create new view forwarder
777 mpViewForwarder = CreateViewForwarder();
779 else if( bCreate )
781 // dispose old text forwarder
782 UpdateData();
784 delete mpTextForwarder;
785 mpTextForwarder = NULL;
787 // enter edit mode
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();
798 else
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() )
821 if( mbIsLocked )
823 mbNeedsUpdate = true;
825 else
827 if( mpOutliner && mpObject && mpText && !mbDestroyed )
829 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
830 if( pTextObj )
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 );
848 else
850 pTextObj->NbcSetOutlinerParaObjectForText( NULL,mpText );
854 if( mpObject->IsEmptyPresObj() )
855 mpObject->SetEmptyPresObj(sal_False);
861 void SvxTextEditSourceImpl::lock()
863 mbIsLocked = true;
864 if( mpOutliner )
866 ((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_False );
867 mbOldUndoMode = ((EditEngine*)&(mpOutliner->GetEditEngine()))->IsUndoEnabled();
868 ((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( sal_False );
872 void SvxTextEditSourceImpl::unlock()
874 mbIsLocked = false;
876 if( mbNeedsUpdate )
878 UpdateData();
879 mbNeedsUpdate = false;
882 if( mpOutliner )
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()
896 if( IsValid() )
898 SdrPaintWindow* pPaintWindow = mpView->FindPaintWindow(*mpWindow);
899 Rectangle aVisArea;
901 if(pPaintWindow)
903 aVisArea = pPaintWindow->GetVisibleArea();
906 // offset vis area by edit engine left-top position
907 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
908 if( pTextObj )
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 );
920 return Rectangle();
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.
931 if( IsEditMode() )
933 SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
935 if( pForwarder )
936 return pForwarder->LogicToPixel( rPoint, rMapMode );
938 else if( IsValid() && mpModel )
940 // #101029#
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 );
952 return Point();
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.
963 if( IsEditMode() )
965 SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
967 if( pForwarder )
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()),
977 rMapMode ) );
978 // #101029#
979 aPoint2.X() -= maTextOffset.X();
980 aPoint2.Y() -= maTextOffset.Y();
982 return aPoint2;
985 return Point();
988 IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify*, aNotify)
990 if( aNotify && !mbNotificationsDisabled )
992 ::std::auto_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( aNotify) );
994 if( aHint.get() )
995 Broadcast( *aHint.get() );
998 return 0;
1001 //------------------------------------------------------------------------
1003 // --------------------------------------------------------------------
1004 // SvxTextEditSource
1005 // --------------------------------------------------------------------
1007 SvxTextEditSource::SvxTextEditSource( SdrObject* pObject, SdrText* pText, XInterface* pOwner )
1009 mpImpl = new SvxTextEditSourceImpl( pObject, pText, pOwner );
1010 mpImpl->acquire();
1013 // --------------------------------------------------------------------
1014 SvxTextEditSource::SvxTextEditSource( SdrObject& rObj, SdrText* pText, SdrView& rView, const Window& rWindow )
1016 mpImpl = new SvxTextEditSourceImpl( rObj, pText, rView, rWindow );
1017 mpImpl->acquire();
1020 // --------------------------------------------------------------------
1022 SvxTextEditSource::SvxTextEditSource( SvxTextEditSourceImpl* pImpl )
1024 mpImpl = pImpl;
1025 mpImpl->acquire();
1028 //------------------------------------------------------------------------
1029 SvxTextEditSource::~SvxTextEditSource()
1031 ::SolarMutexGuard aGuard;
1033 mpImpl->release();
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()
1057 return this;
1060 //------------------------------------------------------------------------
1061 void SvxTextEditSource::UpdateData()
1063 mpImpl->UpdateData();
1066 SfxBroadcaster& SvxTextEditSource::GetBroadcaster() const
1068 return *mpImpl;
1071 void SvxTextEditSource::lock()
1073 mpImpl->lock();
1076 void SvxTextEditSource::unlock()
1078 mpImpl->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: */