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