xref: /trunk/main/svx/source/table/celleditsource.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #include <com/sun/star/linguistic2/XLinguServiceManager.hpp>
32 
33 #include <rtl/ref.hxx>
34 #include <osl/mutex.hxx>
35 #include <vos/mutex.hxx>
36 #include <vcl/svapp.hxx>
37 #include <comphelper/processfactory.hxx>
38 #include <svl/lstner.hxx>
39 #include <svl/hint.hxx>
40 #include <svl/style.hxx>
41 
42 #include "celleditsource.hxx"
43 #include "cell.hxx"
44 #include "svx/svdmodel.hxx"
45 #include "svx/svdoutl.hxx"
46 #include "svx/svdobj.hxx"
47 #include "editeng/unoedhlp.hxx"
48 #include "svx/svdview.hxx"
49 #include "svx/svdetc.hxx"
50 #include "editeng/outliner.hxx"
51 #include "editeng/unoforou.hxx"
52 #include "editeng/unoviwou.hxx"
53 #include "editeng/outlobj.hxx"
54 #include "svx/svdotext.hxx"
55 #include "svx/svdpage.hxx"
56 #include "editeng/editeng.hxx"
57 #include "editeng/unotext.hxx"
58 #include "svx/sdrpaintwindow.hxx"
59 
60 //------------------------------------------------------------------------
61 
62 using ::rtl::OUString;
63 using namespace ::osl;
64 using namespace ::vos;
65 
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::linguistic2;
68 using namespace ::com::sun::star::lang;
69 
70 //------------------------------------------------------------------------
71 
72 namespace sdr { namespace table {
73 
74 //------------------------------------------------------------------------
75 // CellEditSourceImpl
76 //------------------------------------------------------------------------
77 
78 /** @descr
79     <p>This class essentially provides the text and view forwarders. If
80     no SdrView is given, this class handles the UNO objects, which are
81     currently not concerned with view issues. In this case,
82     GetViewForwarder() always returns NULL and the underlying
83     EditEngine of the SvxTextForwarder is a background one (i.e. not
84     the official DrawOutliner, but one created exclusively for this
85     object, with no relation to a view).
86     </p>
87 
88     <p>If a SdrView is given at construction time, the caller is
89     responsible for destroying this object when the view becomes
90     invalid (the views cannot notify). If GetViewForwarder(sal_True)
91     is called, the underlying shape is put into edit mode, the view
92     forwarder returned encapsulates the OutlinerView and the next call
93     to GetTextForwarder() yields a forwarder encapsulating the actual
94     DrawOutliner. Thus, changes on that Outliner are immediately
95     reflected on the screen. If the object leaves edit mode, the old
96     behaviour is restored.</p>
97  */
98 class CellEditSourceImpl : public SfxListener, public SfxBroadcaster
99 {
100 private:
101     oslInterlockedCount             maRefCount;
102 
103     SdrView*                        mpView;
104     const Window*                   mpWindow;
105     SdrModel*                       mpModel;
106     SdrOutliner*                    mpOutliner;
107     SvxOutlinerForwarder*           mpTextForwarder;
108     SvxDrawOutlinerViewForwarder*   mpViewForwarder;
109     Reference< ::com::sun::star::linguistic2::XLinguServiceManager > mxLinguServiceManager;
110     Point                           maTextOffset;
111     bool                            mbDataValid;
112     bool                            mbDisposed;
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)
119 
120     CellRef                         mxCell;
121     SvxUnoTextRangeBaseList         maTextRanges;
122 
123     SvxTextForwarder*               GetBackgroundTextForwarder();
124     SvxTextForwarder*               GetEditModeTextForwarder();
125     SvxDrawOutlinerViewForwarder*   CreateViewForwarder();
126 
127     void                            SetupOutliner();
128     void                            UpdateOutliner();
129 
130     bool                            HasView() const { return mpView != 0; }
131     bool                            IsEditMode() const { return mxCell->IsTextEditActive(); };
132     void                            dispose();
133 
134 public:
135     CellEditSourceImpl( const CellRef& xCell );
136     CellEditSourceImpl( const CellRef& xCell, SdrView& rView, const Window& rWindow );
137     ~CellEditSourceImpl();
138 
139     void SAL_CALL acquire();
140     void SAL_CALL release();
141 
142     virtual void            Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
143 
144     SvxEditSource*          Clone() const;
145     SvxTextForwarder*       GetTextForwarder();
146     SvxEditViewForwarder*   GetEditViewForwarder( sal_Bool );
147     void                    UpdateData();
148 
149     void addRange( SvxUnoTextRangeBase* pNewRange );
150     void removeRange( SvxUnoTextRangeBase* pOldRange );
151     const SvxUnoTextRangeBaseList& getRanges() const;
152 
153     void                    lock();
154     void                    unlock();
155 
156     sal_Bool                    IsValid() const;
157 
158     Rectangle               GetVisArea();
159     Point                   LogicToPixel( const Point&, const MapMode& rMapMode );
160     Point                   PixelToLogic( const Point&, const MapMode& rMapMode );
161 
162     DECL_LINK( NotifyHdl, EENotify* );
163 
164     void ChangeModel( SdrModel* pNewModel );
165 };
166 
167 //------------------------------------------------------------------------
168 
169 CellEditSourceImpl::CellEditSourceImpl( const CellRef& xCell )
170   : maRefCount      ( 0 ),
171     mpView          ( NULL ),
172     mpWindow        ( NULL ),
173     mpModel         ( NULL ),
174     mpOutliner      ( NULL ),
175     mpTextForwarder ( NULL ),
176     mpViewForwarder ( NULL ),
177     mbDataValid     ( false ),
178     mbDisposed      ( false ),
179     mbIsLocked      ( false ),
180     mbNeedsUpdate   ( false ),
181     mbOldUndoMode   ( false ),
182     mbForwarderIsEditMode ( false ),
183     mbShapeIsEditMode     ( false ),
184     mbNotificationsDisabled ( false ),
185     mxCell( xCell )
186 {
187 }
188 
189 //------------------------------------------------------------------------
190 
191 CellEditSourceImpl::CellEditSourceImpl( const CellRef& xCell, SdrView& rView, const Window& rWindow )
192   : maRefCount      ( 0 ),
193     mpView          ( &rView ),
194     mpWindow        ( &rWindow ),
195     mpModel         ( NULL ),
196     mpOutliner      ( NULL ),
197     mpTextForwarder ( NULL ),
198     mpViewForwarder ( NULL ),
199     mbDataValid     ( false ),
200     mbDisposed      ( false ),
201     mbIsLocked      ( false ),
202     mbNeedsUpdate   ( false ),
203     mbOldUndoMode   ( false ),
204     mbForwarderIsEditMode ( false ),
205     mbShapeIsEditMode     ( true ),
206     mbNotificationsDisabled ( false ),
207     mxCell( xCell )
208 {
209     if( mpView )
210         StartListening( *mpView );
211 
212     // #104157# Init edit mode state from shape info (IsTextEditActive())
213     mbShapeIsEditMode = IsEditMode();
214 }
215 
216 //------------------------------------------------------------------------
217 
218 CellEditSourceImpl::~CellEditSourceImpl()
219 {
220     DBG_ASSERT( mbIsLocked == sal_False, "CellEditSourceImpl::~CellEditSourceImpl(), was not unlocked before dispose!" );
221     dispose();
222 }
223 
224 //------------------------------------------------------------------------
225 
226 void CellEditSourceImpl::addRange( SvxUnoTextRangeBase* pNewRange )
227 {
228     if( pNewRange )
229         if( std::find( maTextRanges.begin(), maTextRanges.end(), pNewRange ) == maTextRanges.end() )
230             maTextRanges.push_back( pNewRange );
231 }
232 
233 //------------------------------------------------------------------------
234 
235 void CellEditSourceImpl::removeRange( SvxUnoTextRangeBase* pOldRange )
236 {
237     if( pOldRange )
238         maTextRanges.remove( pOldRange );
239 }
240 
241 //------------------------------------------------------------------------
242 
243 const SvxUnoTextRangeBaseList& CellEditSourceImpl::getRanges() const
244 {
245     return maTextRanges;
246 }
247 
248 //------------------------------------------------------------------------
249 
250 void SAL_CALL CellEditSourceImpl::acquire()
251 {
252     osl_incrementInterlockedCount( &maRefCount );
253 }
254 
255 //------------------------------------------------------------------------
256 
257 void SAL_CALL CellEditSourceImpl::release()
258 {
259     if( ! osl_decrementInterlockedCount( &maRefCount ) )
260         delete this;
261 }
262 
263 void CellEditSourceImpl::ChangeModel( SdrModel* pNewModel )
264 {
265     if( mpModel != pNewModel )
266     {
267         if( mpOutliner )
268         {
269             if( mpModel )
270                 mpModel->disposeOutliner( mpOutliner );
271             else
272                 delete mpOutliner;
273             mpOutliner = 0;
274         }
275 
276         if( mpView )
277         {
278             EndListening( *mpView );
279             mpView = 0;
280         }
281 
282         mpWindow = 0;
283         mxLinguServiceManager.clear();
284 
285         mpModel = pNewModel;
286 
287         if( mpTextForwarder )
288         {
289             delete mpTextForwarder;
290             mpTextForwarder = 0;
291         }
292 
293         if( mpViewForwarder )
294         {
295             delete mpViewForwarder;
296             mpViewForwarder = 0;
297         }
298     }
299 }
300 
301 //------------------------------------------------------------------------
302 
303 void CellEditSourceImpl::Notify( SfxBroadcaster&, const SfxHint& rHint )
304 {
305     const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
306     const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
307 
308     if( pViewHint )
309     {
310         switch( pViewHint->GetHintType() )
311         {
312             case SvxViewHint::SVX_HINT_VIEWCHANGED:
313                 Broadcast( *pViewHint );
314                 break;
315         }
316     }
317     else if( pSdrHint )
318     {
319         switch( pSdrHint->GetKind() )
320         {
321             case HINT_OBJCHG:
322             {
323                 mbDataValid = sal_False;                        // Text muss neu geholt werden
324 
325                 if( HasView() )
326                 {
327                     // #104157# Update maTextOffset, object has changed
328                     // #105196#, #105203#: Cannot call that // here,
329                     // since TakeTextRect() (called from there) //
330                     // changes outliner content.
331                     // UpdateOutliner();
332 
333                     // #101029# Broadcast object changes, as they might change visible attributes
334                     SvxViewHint aHint(SvxViewHint::SVX_HINT_VIEWCHANGED);
335                     Broadcast( aHint );
336                 }
337                 break;
338             }
339 
340             case HINT_BEGEDIT:
341 /* todo
342                 if( mpObject == pSdrHint->GetObject() )
343                 {
344                     // invalidate old forwarder
345                     if( !mbForwarderIsEditMode )
346                     {
347                         delete mpTextForwarder;
348                         mpTextForwarder = NULL;
349                     }
350 
351                     // register as listener - need to broadcast state change messages
352                     if( mpView && mpView->GetTextEditOutliner() )
353                         mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, CellEditSourceImpl, NotifyHdl) );
354 
355                     // #104157# Only now we're really in edit mode
356                     mbShapeIsEditMode = sal_True;
357 
358                     Broadcast( *pSdrHint );
359                 }
360 */
361                 break;
362 
363             case HINT_ENDEDIT:
364 /* todo
365                 if( mpObject == pSdrHint->GetObject() )
366                 {
367                     Broadcast( *pSdrHint );
368 
369                     // #104157# We're no longer in edit mode
370                     mbShapeIsEditMode = sal_False;
371 
372                     // remove as listener - outliner might outlive ourselves
373                     if( mpView && mpView->GetTextEditOutliner() )
374                         mpView->GetTextEditOutliner()->SetNotifyHdl( Link() );
375 
376                     // destroy view forwarder, OutlinerView no longer
377                     // valid (no need for UpdateData(), it's been
378                     // synched on SdrEndTextEdit)
379                     delete mpViewForwarder;
380                     mpViewForwarder = NULL;
381 
382                     // #100424# Invalidate text forwarder, we might
383                     // not be called again before entering edit mode a
384                     // second time! Then, the old outliner might be
385                     // invalid.
386                     if( mbForwarderIsEditMode )
387                     {
388                         mbForwarderIsEditMode = sal_False;
389                         delete mpTextForwarder;
390                         mpTextForwarder = NULL;
391                     }
392                 }
393 */
394                 break;
395 
396             case HINT_MODELCLEARED:
397                 dispose();
398                 break;
399             default:
400                 break;
401         }
402     }
403 }
404 
405 /* unregister at all objects and set all references to 0 */
406 void CellEditSourceImpl::dispose()
407 {
408     if( mpTextForwarder )
409     {
410         delete mpTextForwarder;
411         mpTextForwarder = 0;
412     }
413 
414     if( mpViewForwarder )
415     {
416         delete mpViewForwarder;
417         mpViewForwarder = 0;
418     }
419 
420     if( mpOutliner )
421     {
422         if( mpModel )
423         {
424             mpModel->disposeOutliner( mpOutliner );
425         }
426         else
427         {
428             delete mpOutliner;
429         }
430         mpOutliner = 0;
431     }
432 
433     if( mpView )
434     {
435         EndListening( *mpView );
436         mpView = 0;
437     }
438 
439     mpModel = 0;
440     mpWindow = 0;
441 }
442 
443 //------------------------------------------------------------------------
444 
445 void CellEditSourceImpl::SetupOutliner()
446 {
447     // #101029#
448     // only for UAA edit source: setup outliner equivalently as in
449     // SdrTextObj::Paint(), such that formatting equals screen
450     // layout
451 /* todo
452     if( mpObject && mpOutliner )
453     {
454         SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
455         Rectangle aPaintRect;
456         if( pTextObj )
457         {
458             Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
459             pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect );
460 
461             // #101029# calc text offset from shape anchor
462             maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
463         }
464     }
465 */
466 }
467 
468 //------------------------------------------------------------------------
469 
470 void CellEditSourceImpl::UpdateOutliner()
471 {
472     // #104157#
473     // only for UAA edit source: update outliner equivalently as in
474     // SdrTextObj::Paint(), such that formatting equals screen
475     // layout
476 /* todo
477     if( mpObject && mpOutliner )
478     {
479         SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, mpObject );
480         Rectangle aPaintRect;
481         if( pTextObj )
482         {
483             Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
484             pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect );
485 
486             // #101029# calc text offset from shape anchor
487             maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
488         }
489     }
490 */
491 }
492 
493 //------------------------------------------------------------------------
494 
495 
496 SvxTextForwarder* CellEditSourceImpl::GetBackgroundTextForwarder()
497 {
498     sal_Bool bCreated = sal_False;
499 
500     // #99840#: prevent EE/Outliner notifications during setup
501     mbNotificationsDisabled = true;
502 
503     if (!mpTextForwarder)
504     {
505         if( mpOutliner == NULL )
506         {
507             mpOutliner = mpModel->createOutliner( OUTLINERMODE_TEXTOBJECT );
508 
509             // #109151# Do the setup after outliner creation, would be useless otherwise
510             if( HasView() )
511             {
512                 // #101029#, #104157# Setup outliner _before_ filling it
513                 SetupOutliner();
514             }
515 
516 // todo?            mpOutliner->SetTextObjNoInit( pTextObj );
517 
518             if( mbIsLocked )
519             {
520                 ((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_False );
521                 mbOldUndoMode = ((EditEngine*)&(mpOutliner->GetEditEngine()))->IsUndoEnabled();
522                 ((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( sal_False );
523             }
524 
525             if ( !mxLinguServiceManager.is() )
526             {
527                 Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
528                 mxLinguServiceManager = Reference< XLinguServiceManager >(
529                     xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.linguistic2.LinguServiceManager" ))), UNO_QUERY );
530             }
531 
532             if ( mxLinguServiceManager.is() )
533             {
534                 Reference< XHyphenator > xHyphenator( mxLinguServiceManager->getHyphenator(), UNO_QUERY );
535                 if( xHyphenator.is() )
536                     mpOutliner->SetHyphenator( xHyphenator );
537             }
538         }
539 
540         mpTextForwarder = new SvxOutlinerForwarder( *mpOutliner );
541 
542         // delay listener subscription and UAA initialization until Outliner is fully setup
543         bCreated = true;
544         mbForwarderIsEditMode = false;
545     }
546 
547     if( !mbDataValid )
548     {
549         mpTextForwarder->flushCache();
550 
551         OutlinerParaObject* pOutlinerParaObject = NULL;
552         bool bTextEditActive = false;
553 
554         pOutlinerParaObject = mxCell->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
555 
556         if( pOutlinerParaObject )
557             bTextEditActive = true; // text edit active
558         else
559             pOutlinerParaObject = mxCell->GetOutlinerParaObject();
560 
561         if( pOutlinerParaObject )
562         {
563             mpOutliner->SetText( *pOutlinerParaObject );
564         }
565         else
566         {
567             bool bVertical = false; // todo?
568 
569             // set objects style sheet on empty outliner
570             SfxStyleSheetPool* pPool = mxCell->GetStyleSheetPool();
571             if( pPool )
572                 mpOutliner->SetStyleSheetPool( pPool );
573 
574             SfxStyleSheet* pStyleSheet = mxCell->GetStyleSheet();
575             if( pStyleSheet )
576                 mpOutliner->SetStyleSheet( 0, pStyleSheet );
577 
578             if( bVertical )
579                 mpOutliner->SetVertical( sal_True );
580         }
581 
582         // evtually we have to set the border attributes
583         if (mpOutliner->GetParagraphCount()==1)
584         {
585             // if we only have one paragraph we check if it is empty
586             XubString aStr( mpOutliner->GetText( mpOutliner->GetParagraph( 0 ) ) );
587 
588             if(!aStr.Len())
589             {
590                 // its empty, so we have to force the outliner to initialise itself
591                 mpOutliner->SetText( String(), mpOutliner->GetParagraph( 0 ) );
592 
593                 if(mxCell->GetStyleSheet())
594                     mpOutliner->SetStyleSheet( 0, mxCell->GetStyleSheet());
595             }
596         }
597 
598         if( bTextEditActive )
599             delete pOutlinerParaObject;
600 
601         mbDataValid = true;
602     }
603 
604     if( bCreated && mpOutliner && HasView() )
605     {
606         // register as listener - need to broadcast state change messages
607         // registration delayed until outliner is completely set up
608         mpOutliner->SetNotifyHdl( LINK(this, CellEditSourceImpl, NotifyHdl) );
609     }
610 
611     // #99840#: prevent EE/Outliner notifications during setup
612     mbNotificationsDisabled = false;
613 
614     return mpTextForwarder;
615 }
616 
617 //------------------------------------------------------------------------
618 
619 SvxTextForwarder* CellEditSourceImpl::GetEditModeTextForwarder()
620 {
621     if( !mpTextForwarder && HasView() )
622     {
623         SdrOutliner* pEditOutliner = mpView->GetTextEditOutliner();
624 
625         if( pEditOutliner )
626         {
627             mpTextForwarder = new SvxOutlinerForwarder( *pEditOutliner );
628             mbForwarderIsEditMode = true;
629         }
630     }
631 
632     return mpTextForwarder;
633 }
634 
635 //------------------------------------------------------------------------
636 
637 SvxTextForwarder* CellEditSourceImpl::GetTextForwarder()
638 {
639     if( mbDisposed )
640         return NULL;
641 
642     if( mpModel == NULL )
643         return NULL;
644 
645     // distinguish the cases
646     // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner
647     // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code)
648     if( HasView() )
649     {
650         if( IsEditMode() != mbForwarderIsEditMode )
651         {
652             // forwarder mismatch - create new
653             delete mpTextForwarder;
654             mpTextForwarder = NULL;
655         }
656 
657         if( IsEditMode() )
658             return GetEditModeTextForwarder();
659         else
660             return GetBackgroundTextForwarder();
661     }
662     else
663         return GetBackgroundTextForwarder();
664 }
665 
666 //------------------------------------------------------------------------
667 
668 SvxDrawOutlinerViewForwarder* CellEditSourceImpl::CreateViewForwarder()
669 {
670     if( mpView->GetTextEditOutlinerView() )
671     {
672         // register as listener - need to broadcast state change messages
673         mpView->GetTextEditOutliner()->SetNotifyHdl( LINK(this, CellEditSourceImpl, NotifyHdl) );
674 
675         Rectangle aBoundRect( mxCell->GetCurrentBoundRect() );
676         OutlinerView& rOutlView = *mpView->GetTextEditOutlinerView();
677 
678         return new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() );
679     }
680 
681     return NULL;
682 }
683 
684 SvxEditViewForwarder* CellEditSourceImpl::GetEditViewForwarder( sal_Bool bCreate )
685 {
686     if( mbDisposed )
687         return NULL;
688 
689     if( mpModel == NULL )
690         return NULL;
691 
692     // shall we delete?
693     if( mpViewForwarder )
694     {
695         if( !IsEditMode() )
696         {
697             // destroy all forwarders (no need for UpdateData(),
698             // it's been synched on SdrEndTextEdit)
699             delete mpViewForwarder;
700             mpViewForwarder = NULL;
701         }
702     }
703     // which to create? Directly in edit mode, create new, or none?
704     else if( mpView )
705     {
706         if( IsEditMode() )
707         {
708             // create new view forwarder
709             mpViewForwarder = CreateViewForwarder();
710         }
711         else if( bCreate )
712         {
713             // dispose old text forwarder
714             UpdateData();
715 
716             delete mpTextForwarder;
717             mpTextForwarder = NULL;
718 
719             // enter edit mode
720             mpView->SdrEndTextEdit();
721 
722 /* todo
723             if(mpView->SdrBeginTextEdit(mpObject, 0L, 0L, sal_False, (SdrOutliner*)0L, 0L, sal_False, sal_False))
724             {
725                 if( mxCell->IsTextEditActive() )
726                 {
727                     // create new view forwarder
728                     mpViewForwarder = CreateViewForwarder();
729                 }
730                 else
731                 {
732                     // failure. Somehow, SdrBeginTextEdit did not set
733                     // our SdrTextObj into edit mode
734                     mpView->SdrEndTextEdit();
735                 }
736             }
737 */
738         }
739     }
740 
741     return mpViewForwarder;
742 }
743 
744 //------------------------------------------------------------------------
745 
746 void CellEditSourceImpl::UpdateData()
747 {
748     // if we have a view and in edit mode, we're working with the
749     // DrawOutliner. Thus, all changes made on the text forwarder are
750     // reflected on the view and committed to the model on
751     // SdrEndTextEdit(). Thus, no need for explicit updates here.
752     if( !HasView() || !IsEditMode() )
753     {
754         if( mbIsLocked  )
755         {
756             mbNeedsUpdate = true;
757         }
758         else
759         {
760             if( mpOutliner && !mbDisposed )
761             {
762                 if( mpOutliner->GetParagraphCount() != 1 || mpOutliner->GetEditEngine().GetTextLen( 0 ) )
763                 {
764                     mxCell->SetOutlinerParaObject( mpOutliner->CreateParaObject() );
765                 }
766                 else
767                 {
768                     mxCell->SetOutlinerParaObject( NULL );
769                 }
770             }
771         }
772     }
773 }
774 
775 void CellEditSourceImpl::lock()
776 {
777     mbIsLocked = true;
778     if( mpOutliner )
779     {
780         ((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_False );
781         mbOldUndoMode = ((EditEngine*)&(mpOutliner->GetEditEngine()))->IsUndoEnabled();
782         ((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( sal_False );
783     }
784 }
785 
786 void CellEditSourceImpl::unlock()
787 {
788     mbIsLocked = false;
789 
790     if( mbNeedsUpdate )
791     {
792         UpdateData();
793         mbNeedsUpdate = false;
794     }
795 
796     if( mpOutliner )
797     {
798         ((EditEngine*)&(mpOutliner->GetEditEngine()))->SetUpdateMode( sal_True );
799         ((EditEngine*)&(mpOutliner->GetEditEngine()))->EnableUndo( mbOldUndoMode );
800     }
801 }
802 
803 sal_Bool CellEditSourceImpl::IsValid() const
804 {
805     return mpView && mpWindow ? sal_True : sal_False;
806 }
807 
808 Rectangle CellEditSourceImpl::GetVisArea()
809 {
810     if( IsValid() )
811     {
812         SdrPaintWindow* pPaintWindow = mpView->FindPaintWindow(*mpWindow);
813         Rectangle aVisArea;
814 
815         if(pPaintWindow)
816         {
817             aVisArea = pPaintWindow->GetVisibleArea();
818         }
819 
820         // offset vis area by edit engine left-top position
821         Rectangle aAnchorRect;
822         mxCell->TakeTextAnchorRect( aAnchorRect );
823         aVisArea.Move( -aAnchorRect.Left(), -aAnchorRect.Top() );
824 
825         MapMode aMapMode(mpWindow->GetMapMode());
826         aMapMode.SetOrigin(Point());
827         return mpWindow->LogicToPixel( aVisArea, aMapMode );
828     }
829 
830     return Rectangle();
831 }
832 
833 Point CellEditSourceImpl::LogicToPixel( const Point& rPoint, const MapMode& rMapMode )
834 {
835     // #101029#: The responsibilities of ViewForwarder happen to be
836     // somewhat mixed in this case. On the one hand, we need the
837     // different interface queries on the SvxEditSource interface,
838     // since we need both VisAreas. On the other hand, if an
839     // EditViewForwarder exists, maTextOffset does not remain static,
840     // but may change with every key press.
841     if( IsEditMode() )
842     {
843         SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
844 
845         if( pForwarder )
846             return pForwarder->LogicToPixel( rPoint, rMapMode );
847     }
848     else if( IsValid() && mpModel )
849     {
850         // #101029#
851         Point aPoint1( rPoint );
852         aPoint1.X() += maTextOffset.X();
853         aPoint1.Y() += maTextOffset.Y();
854 
855         Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode,
856                                                    MapMode(mpModel->GetScaleUnit()) ) );
857         MapMode aMapMode(mpWindow->GetMapMode());
858         aMapMode.SetOrigin(Point());
859         return mpWindow->LogicToPixel( aPoint2, aMapMode );
860     }
861 
862     return Point();
863 }
864 
865 Point CellEditSourceImpl::PixelToLogic( const Point& rPoint, const MapMode& rMapMode )
866 {
867     // #101029#: The responsibilities of ViewForwarder happen to be
868     // somewhat mixed in this case. On the one hand, we need the
869     // different interface queries on the SvxEditSource interface,
870     // since we need both VisAreas. On the other hand, if an
871     // EditViewForwarder exists, maTextOffset does not remain static,
872     // but may change with every key press.
873     if( IsEditMode() )
874     {
875         SvxEditViewForwarder* pForwarder = GetEditViewForwarder(sal_False);
876 
877         if( pForwarder )
878             return pForwarder->PixelToLogic( rPoint, rMapMode );
879     }
880     else if( IsValid() && mpModel )
881     {
882         MapMode aMapMode(mpWindow->GetMapMode());
883         aMapMode.SetOrigin(Point());
884         Point aPoint1( mpWindow->PixelToLogic( rPoint, aMapMode ) );
885         Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
886                                                    MapMode(mpModel->GetScaleUnit()),
887                                                    rMapMode ) );
888         // #101029#
889         aPoint2.X() -= maTextOffset.X();
890         aPoint2.Y() -= maTextOffset.Y();
891 
892         return aPoint2;
893     }
894 
895     return Point();
896 }
897 
898 IMPL_LINK(CellEditSourceImpl, NotifyHdl, EENotify*, aNotify)
899 {
900     if( aNotify && !mbNotificationsDisabled )
901     {
902         ::std::auto_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( aNotify) );
903 
904         if( aHint.get() )
905             Broadcast( *aHint.get() );
906     }
907 
908     return 0;
909 }
910 
911 //------------------------------------------------------------------------
912 
913 // --------------------------------------------------------------------
914 // CellEditSource
915 // --------------------------------------------------------------------
916 
917 CellEditSource::CellEditSource( const CellRef& xCell )
918 {
919     mpImpl = new CellEditSourceImpl( xCell );
920     mpImpl->acquire();
921 }
922 
923 // --------------------------------------------------------------------
924 CellEditSource::CellEditSource( const CellRef& xCell, SdrView& rView, const Window& rWindow )
925 {
926     mpImpl = new CellEditSourceImpl( xCell, rView, rWindow );
927     mpImpl->acquire();
928 }
929 
930 // --------------------------------------------------------------------
931 
932 CellEditSource::CellEditSource( CellEditSourceImpl* pImpl )
933 {
934     mpImpl = pImpl;
935     mpImpl->acquire();
936 }
937 
938 //------------------------------------------------------------------------
939 CellEditSource::~CellEditSource()
940 {
941     OGuard aGuard( Application::GetSolarMutex() );
942     mpImpl->release();
943 }
944 
945 //------------------------------------------------------------------------
946 SvxEditSource* CellEditSource::Clone() const
947 {
948     return new CellEditSource( mpImpl );
949 }
950 
951 //------------------------------------------------------------------------
952 SvxTextForwarder* CellEditSource::GetTextForwarder()
953 {
954     return mpImpl->GetTextForwarder();
955 }
956 
957 //------------------------------------------------------------------------
958 SvxEditViewForwarder* CellEditSource::GetEditViewForwarder( sal_Bool bCreate )
959 {
960     return mpImpl->GetEditViewForwarder( bCreate );
961 }
962 
963 //------------------------------------------------------------------------
964 
965 SvxViewForwarder* CellEditSource::GetViewForwarder()
966 {
967     return this;
968 }
969 
970 //------------------------------------------------------------------------
971 
972 void CellEditSource::UpdateData()
973 {
974     mpImpl->UpdateData();
975 }
976 
977 //------------------------------------------------------------------------
978 
979 SfxBroadcaster& CellEditSource::GetBroadcaster() const
980 {
981     return *mpImpl;
982 }
983 
984 //------------------------------------------------------------------------
985 
986 void CellEditSource::lock()
987 {
988     mpImpl->lock();
989 }
990 
991 //------------------------------------------------------------------------
992 
993 void CellEditSource::unlock()
994 {
995     mpImpl->unlock();
996 }
997 
998 //------------------------------------------------------------------------
999 
1000 sal_Bool CellEditSource::IsValid() const
1001 {
1002     return mpImpl->IsValid();
1003 }
1004 
1005 //------------------------------------------------------------------------
1006 
1007 Rectangle CellEditSource::GetVisArea() const
1008 {
1009     return mpImpl->GetVisArea();
1010 }
1011 
1012 //------------------------------------------------------------------------
1013 
1014 Point CellEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1015 {
1016     return mpImpl->LogicToPixel( rPoint, rMapMode );
1017 }
1018 
1019 //------------------------------------------------------------------------
1020 
1021 Point CellEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1022 {
1023     return mpImpl->PixelToLogic( rPoint, rMapMode );
1024 }
1025 
1026 //------------------------------------------------------------------------
1027 
1028 void CellEditSource::addRange( SvxUnoTextRangeBase* pNewRange )
1029 {
1030     mpImpl->addRange( pNewRange );
1031 }
1032 
1033 //------------------------------------------------------------------------
1034 
1035 void CellEditSource::removeRange( SvxUnoTextRangeBase* pOldRange )
1036 {
1037     mpImpl->removeRange( pOldRange );
1038 }
1039 
1040 //------------------------------------------------------------------------
1041 
1042 const SvxUnoTextRangeBaseList& CellEditSource::getRanges() const
1043 {
1044     return mpImpl->getRanges();
1045 }
1046 
1047 //------------------------------------------------------------------------
1048 
1049 void CellEditSource::ChangeModel( SdrModel* pNewModel )
1050 {
1051     mpImpl->ChangeModel( pNewModel );
1052 }
1053 
1054 //------------------------------------------------------------------------
1055 
1056 } }
1057