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