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