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 126 bool HasView() const { return mpView != 0; } 127 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 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 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 214 CellEditSourceImpl::~CellEditSourceImpl() 215 { 216 DBG_ASSERT( mbIsLocked == sal_False, "CellEditSourceImpl::~CellEditSourceImpl(), was not unlocked before dispose!" ); 217 dispose(); 218 } 219 220 //------------------------------------------------------------------------ 221 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 231 void CellEditSourceImpl::removeRange( SvxUnoTextRangeBase* pOldRange ) 232 { 233 if( pOldRange ) 234 maTextRanges.remove( pOldRange ); 235 } 236 237 //------------------------------------------------------------------------ 238 239 const SvxUnoTextRangeBaseList& CellEditSourceImpl::getRanges() const 240 { 241 return maTextRanges; 242 } 243 244 //------------------------------------------------------------------------ 245 246 void SAL_CALL CellEditSourceImpl::acquire() 247 { 248 osl_incrementInterlockedCount( &maRefCount ); 249 } 250 251 //------------------------------------------------------------------------ 252 253 void SAL_CALL CellEditSourceImpl::release() 254 { 255 if( ! osl_decrementInterlockedCount( &maRefCount ) ) 256 delete this; 257 } 258 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 799 sal_Bool CellEditSourceImpl::IsValid() const 800 { 801 return mpView && mpWindow ? sal_True : sal_False; 802 } 803 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 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 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 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 913 CellEditSource::CellEditSource( const CellRef& xCell ) 914 { 915 mpImpl = new CellEditSourceImpl( xCell ); 916 mpImpl->acquire(); 917 } 918 919 // -------------------------------------------------------------------- 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 928 CellEditSource::CellEditSource( CellEditSourceImpl* pImpl ) 929 { 930 mpImpl = pImpl; 931 mpImpl->acquire(); 932 } 933 934 //------------------------------------------------------------------------ 935 CellEditSource::~CellEditSource() 936 { 937 OGuard aGuard( Application::GetSolarMutex() ); 938 mpImpl->release(); 939 } 940 941 //------------------------------------------------------------------------ 942 SvxEditSource* CellEditSource::Clone() const 943 { 944 return new CellEditSource( mpImpl ); 945 } 946 947 //------------------------------------------------------------------------ 948 SvxTextForwarder* CellEditSource::GetTextForwarder() 949 { 950 return mpImpl->GetTextForwarder(); 951 } 952 953 //------------------------------------------------------------------------ 954 SvxEditViewForwarder* CellEditSource::GetEditViewForwarder( sal_Bool bCreate ) 955 { 956 return mpImpl->GetEditViewForwarder( bCreate ); 957 } 958 959 //------------------------------------------------------------------------ 960 961 SvxViewForwarder* CellEditSource::GetViewForwarder() 962 { 963 return this; 964 } 965 966 //------------------------------------------------------------------------ 967 968 void CellEditSource::UpdateData() 969 { 970 mpImpl->UpdateData(); 971 } 972 973 //------------------------------------------------------------------------ 974 975 SfxBroadcaster& CellEditSource::GetBroadcaster() const 976 { 977 return *mpImpl; 978 } 979 980 //------------------------------------------------------------------------ 981 982 void CellEditSource::lock() 983 { 984 mpImpl->lock(); 985 } 986 987 //------------------------------------------------------------------------ 988 989 void CellEditSource::unlock() 990 { 991 mpImpl->unlock(); 992 } 993 994 //------------------------------------------------------------------------ 995 996 sal_Bool CellEditSource::IsValid() const 997 { 998 return mpImpl->IsValid(); 999 } 1000 1001 //------------------------------------------------------------------------ 1002 1003 Rectangle CellEditSource::GetVisArea() const 1004 { 1005 return mpImpl->GetVisArea(); 1006 } 1007 1008 //------------------------------------------------------------------------ 1009 1010 Point CellEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const 1011 { 1012 return mpImpl->LogicToPixel( rPoint, rMapMode ); 1013 } 1014 1015 //------------------------------------------------------------------------ 1016 1017 Point CellEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const 1018 { 1019 return mpImpl->PixelToLogic( rPoint, rMapMode ); 1020 } 1021 1022 //------------------------------------------------------------------------ 1023 1024 void CellEditSource::addRange( SvxUnoTextRangeBase* pNewRange ) 1025 { 1026 mpImpl->addRange( pNewRange ); 1027 } 1028 1029 //------------------------------------------------------------------------ 1030 1031 void CellEditSource::removeRange( SvxUnoTextRangeBase* pOldRange ) 1032 { 1033 mpImpl->removeRange( pOldRange ); 1034 } 1035 1036 //------------------------------------------------------------------------ 1037 1038 const SvxUnoTextRangeBaseList& CellEditSource::getRanges() const 1039 { 1040 return mpImpl->getRanges(); 1041 } 1042 1043 //------------------------------------------------------------------------ 1044 1045 void CellEditSource::ChangeModel( SdrModel* pNewModel ) 1046 { 1047 mpImpl->ChangeModel( pNewModel ); 1048 } 1049 1050 //------------------------------------------------------------------------ 1051 1052 } } 1053