LibreOffice Module svx (master)  1
unoshtxt.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <memory>
23 
24 #include <vcl/svapp.hxx>
25 
26 #include <svx/unoshtxt.hxx>
27 #include <editeng/unoedhlp.hxx>
28 #include <svl/lstner.hxx>
29 #include <rtl/ref.hxx>
30 #include <tools/debug.hxx>
31 #include <svl/hint.hxx>
32 #include <svl/style.hxx>
33 #include <svx/svdmodel.hxx>
34 #include <svx/svdoutl.hxx>
35 #include <svx/svdobj.hxx>
36 #include <svx/svdview.hxx>
37 #include <svx/svdetc.hxx>
38 #include <editeng/outliner.hxx>
39 #include <editeng/unoforou.hxx>
40 #include <editeng/unoviwou.hxx>
41 #include <editeng/outlobj.hxx>
42 #include <svx/svdotext.hxx>
43 #include <svx/svdpage.hxx>
44 #include <editeng/editeng.hxx>
45 #include <editeng/editobj.hxx>
46 
47 #include <editeng/unotext.hxx>
48 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
50 #include <svx/svdotable.hxx>
51 #include <cell.hxx>
52 #include <svx/sdrpaintwindow.hxx>
53 #include <unotools/configmgr.hxx>
54 
55 
56 // SvxTextEditSourceImpl
57 
58 
80 {
81 private:
82  oslInterlockedCount maRefCount;
83 
84  SdrObject* mpObject; // TTTT could be reference (?)
88  SdrModel* mpModel; // TTTT probably not needed -> use SdrModel from SdrObject (?)
89  std::unique_ptr<SdrOutliner> mpOutliner;
90  std::unique_ptr<SvxOutlinerForwarder> mpTextForwarder;
91  std::unique_ptr<SvxDrawOutlinerViewForwarder> mpViewForwarder; // if non-NULL, use GetViewModeTextForwarder text forwarder
92  css::uno::Reference< css::linguistic2::XLinguServiceManager2 > m_xLinguServiceManager;
95  bool mbIsLocked;
98  bool mbForwarderIsEditMode; // have to reflect that, since ENDEDIT can happen more often
99  bool mbShapeIsEditMode; // only true, if SdrHintKind::BeginEdit was received
100  bool mbNotificationsDisabled; // prevent EditEngine/Outliner notifications (e.g. when setting up forwarder)
102 
104 
107  std::unique_ptr<SvxDrawOutlinerViewForwarder> CreateViewForwarder();
108 
109  void SetupOutliner();
110 
111  bool HasView() const { return mpView != nullptr; }
112  bool IsEditMode() const
113  {
114  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
115  return mbShapeIsEditMode && pTextObj && pTextObj->IsTextEditActive();
116  }
117 
118  void dispose();
119 
120 public:
121  SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText );
122  SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const OutputDevice& rWindow );
123  virtual ~SvxTextEditSourceImpl() override;
124 
125  void acquire();
126  void release();
127 
128  virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
129 
132  void UpdateData();
133 
134  void addRange( SvxUnoTextRangeBase* pNewRange );
135  void removeRange( SvxUnoTextRangeBase* pOldRange );
137 
138  void lock();
139  void unlock();
140 
141  bool IsValid() const;
142 
143  Point LogicToPixel( const Point&, const MapMode& rMapMode );
144  Point PixelToLogic( const Point&, const MapMode& rMapMode );
145 
146  DECL_LINK( NotifyHdl, EENotify&, void );
147 
148  virtual void ObjectInDestruction(const SdrObject& rObject) override;
149 
150  void UpdateOutliner();
151 };
152 
153 
155  : maRefCount ( 0 ),
156  mpObject ( pObject ),
157  mpText ( pText ),
158  mpView ( nullptr ),
159  mpWindow ( nullptr ),
160  mpModel ( pObject ? &pObject->getSdrModelFromSdrObject() : nullptr ), // TTTT should be reference
161  mbDataValid ( false ),
162  mbIsLocked ( false ),
163  mbNeedsUpdate ( false ),
164  mbOldUndoMode ( false ),
165  mbForwarderIsEditMode ( false ),
166  mbShapeIsEditMode ( false ),
167  mbNotificationsDisabled ( false ),
168  mbNotifyEditOutlinerSet ( false )
169 {
170  DBG_ASSERT( mpObject, "invalid pObject!" );
171 
172  if( !mpText )
173  {
174  SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
175  if( pTextObj )
176  mpText = pTextObj->getText( 0 );
177  }
178 
179  if( mpModel )
181 
182  if( mpObject )
183  mpObject->AddObjectUser( *this );
184 }
185 
186 
188  : maRefCount ( 0 ),
189  mpObject ( &rObject ),
190  mpText ( pText ),
191  mpView ( &rView ),
192  mpWindow ( &rWindow ),
193  mpModel ( &rObject.getSdrModelFromSdrObject() ), // TTTT should be reference
194  mbDataValid ( false ),
195  mbIsLocked ( false ),
196  mbNeedsUpdate ( false ),
197  mbOldUndoMode ( false ),
198  mbForwarderIsEditMode ( false ),
199  mbShapeIsEditMode ( true ),
200  mbNotificationsDisabled ( false ),
201  mbNotifyEditOutlinerSet ( false )
202 {
203  if( !mpText )
204  {
205  SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
206  if( pTextObj )
207  mpText = pTextObj->getText( 0 );
208  }
209 
212  mpObject->AddObjectUser( *this );
213 
214  // Init edit mode state from shape info (IsTextEditActive())
216 }
217 
218 
220 {
221  DBG_ASSERT( !mbIsLocked, "text edit source was not unlocked before dispose!" );
222  if( mpObject )
223  mpObject->RemoveObjectUser( *this );
224 
225  dispose();
226 }
227 
228 
230 {
231  if( pNewRange )
232  if( std::find( mvTextRanges.begin(), mvTextRanges.end(), pNewRange ) == mvTextRanges.end() )
233  mvTextRanges.push_back( pNewRange );
234 }
235 
236 
238 {
239  if( pOldRange )
240  mvTextRanges.erase( std::remove(mvTextRanges.begin(), mvTextRanges.end(), pOldRange), mvTextRanges.end() );
241 }
242 
243 
245 {
246  osl_atomic_increment( &maRefCount );
247 }
248 
249 
251 {
252  if( ! osl_atomic_decrement( &maRefCount ) )
253  delete this;
254 }
255 
257 {
258  // #i105988 keep reference to this object
260 
261  if (SfxHintId::Dying == rHint.GetId())
262  {
263  if (&rBC == mpView)
264  {
265  mpView = nullptr;
266  mpViewForwarder.reset();
267  }
268  }
269  else if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
270  {
271  const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
272  switch( pSdrHint->GetKind() )
273  {
275  {
276  mbDataValid = false; // Text has to be get again
277 
278  if( HasView() )
279  {
280  // Update maTextOffset, object has changed
281  // Cannot call that here, since TakeTextRect() (called from there)
282  // changes outliner content.
283  // UpdateOutliner();
284 
285  // Broadcast object changes, as they might change visible attributes
286  SvxViewChangedHint aHint;
287  Broadcast( aHint );
288  }
289  break;
290  }
291 
293  if( mpObject == pSdrHint->GetObject() )
294  {
295  // Once SdrHintKind::BeginEdit is broadcast, each EditSource of
296  // AccessibleCell will handle it here and call below:
297  // mpView->GetTextEditOutliner()->SetNotifyHdl(), which
298  // will replace the Notifier for current editable cell. It
299  // is totally wrong. So add check here to avoid the
300  // incorrect replacement of notifier.
301 
302  // Currently it only happens on the editsource of
303  // AccessibleCell
304  if (mpObject && mpText)
305  {
306  sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mpObject );
307  if(pTableObj)
308  {
309  const sdr::table::CellRef& xCell = pTableObj->getActiveCell();
310  if (xCell.is())
311  {
312  sdr::table::Cell* pCellObj = dynamic_cast< sdr::table::Cell* >( mpText );
313  if (pCellObj && xCell.get() != pCellObj)
314  break;
315  }
316  }
317  }
318  // invalidate old forwarder
319  if( !mbForwarderIsEditMode )
320  {
321  mpTextForwarder.reset();
322  }
323 
324  // register as listener - need to broadcast state change messages
325  if( mpView && mpView->GetTextEditOutliner() )
326  {
329  }
330 
331  // Only now we're really in edit mode
332  mbShapeIsEditMode = true;
333 
334  Broadcast( *pSdrHint );
335  }
336  break;
337 
339  if( mpObject == pSdrHint->GetObject() )
340  {
341  Broadcast( *pSdrHint );
342 
343  // We're no longer in edit mode
344  mbShapeIsEditMode = false;
345 
346  // remove as listener - outliner might outlive ourselves
347  if( mpView && mpView->GetTextEditOutliner() )
348  {
350  mbNotifyEditOutlinerSet = false;
351  }
352 
353  // destroy view forwarder, OutlinerView no longer
354  // valid (no need for UpdateData(), it's been
355  // synched on SdrEndTextEdit)
356  mpViewForwarder.reset();
357 
358  // Invalidate text forwarder, we might
359  // not be called again before entering edit mode a
360  // second time! Then, the old outliner might be
361  // invalid.
363  {
364  mbForwarderIsEditMode = false;
365  mpTextForwarder.reset();
366  }
367  }
368  break;
369 
371  dispose();
372  break;
373  default:
374  break;
375  }
376  }
377  else if (const SvxViewChangedHint* pViewHint = dynamic_cast<const SvxViewChangedHint*>(&rHint))
378  {
379  Broadcast( *pViewHint );
380  }
381 }
382 
383 /* this is a callback from the attached SdrObject when it is actually deleted */
385 {
386  mpObject = nullptr;
387  dispose();
388  Broadcast( SfxHint( SfxHintId::Dying ) );
389 }
390 
391 /* unregister at all objects and set all references to 0 */
393 {
394  mpTextForwarder.reset();
395  mpViewForwarder.reset();
396 
397  if( mpOutliner )
398  {
399  if( mpModel )
400  {
401  mpModel->disposeOutliner( std::move(mpOutliner) );
402  }
403  else
404  {
405  mpOutliner.reset();
406  }
407  }
408 
409  if( mpModel )
410  {
411  EndListening( *mpModel );
412  mpModel = nullptr;
413  }
414 
415  if( mpView )
416  {
417  // remove as listener - outliner might outlive ourselves
419  {
421  mbNotifyEditOutlinerSet = false;
422  }
423  EndListening( *mpView );
424  mpView = nullptr;
425  }
426 
427  if( mpObject )
428  {
429  mpObject->RemoveObjectUser( *this );
430  mpObject = nullptr;
431  }
432  mpWindow = nullptr;
433 }
434 
435 
437 {
438  // only for UAA edit source: setup outliner equivalently as in
439  // SdrTextObj::Paint(), such that formatting equals screen
440  // layout
441  if( mpObject && mpOutliner )
442  {
443  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
444  tools::Rectangle aPaintRect;
445  if( pTextObj )
446  {
447  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
448  pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect );
449 
450  // calc text offset from shape anchor
451  maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
452  }
453  }
454 }
455 
456 
458 {
459  // only for UAA edit source: update outliner equivalently as in
460  // SdrTextObj::Paint(), such that formatting equals screen
461  // layout
462  if( mpObject && mpOutliner )
463  {
464  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
465  tools::Rectangle aPaintRect;
466  if( pTextObj )
467  {
468  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
469  pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect );
470 
471  // calc text offset from shape anchor
472  maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
473  }
474  }
475 }
476 
477 
479 {
480  bool bCreated = false;
481 
482  // prevent EE/Outliner notifications during setup
484 
485  if (!mpTextForwarder)
486  {
487  if( mpOutliner == nullptr )
488  {
489  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
490  OutlinerMode nOutlMode = OutlinerMode::TextObject;
491  if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_OUTLINETEXT )
492  nOutlMode = OutlinerMode::OutlineObject;
493 
494  mpOutliner = mpModel->createOutliner( nOutlMode );
495 
496  // Do the setup after outliner creation, would be useless otherwise
497  if( HasView() )
498  {
499  // Setup outliner _before_ filling it
500  SetupOutliner();
501  }
502 
503  mpOutliner->SetTextObjNoInit( pTextObj );
504  if( mbIsLocked )
505  {
506  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateMode( false );
507  mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled();
508  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false );
509  }
510 
512  {
513  if ( !m_xLinguServiceManager.is() )
514  {
515  css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
516  m_xLinguServiceManager.set(css::linguistic2::LinguServiceManager::create(xContext));
517  }
518 
519  css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator = m_xLinguServiceManager->getHyphenator();
520  if( xHyphenator.is() )
521  mpOutliner->SetHyphenator( xHyphenator );
522  }
523  }
524 
525 
527  // delay listener subscription and UAA initialization until Outliner is fully setup
528  bCreated = true;
529 
530  mbForwarderIsEditMode = false;
531  mbDataValid = false;
532  }
533 
535  {
536  mpTextForwarder->flushCache();
537 
538  OutlinerParaObject* pOutlinerParaObject = nullptr;
539  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
540  if( pTextObj && pTextObj->getActiveText() == mpText )
541  pOutlinerParaObject = pTextObj->GetEditOutlinerParaObject().release(); // Get the OutlinerParaObject if text edit is active
542  bool bOwnParaObj(false);
543 
544  if( pOutlinerParaObject )
545  bOwnParaObj = true; // text edit active
546  else
547  pOutlinerParaObject = mpText->GetOutlinerParaObject();
548 
549  if( pOutlinerParaObject && ( bOwnParaObj || !mpObject->IsEmptyPresObj() || mpObject->getSdrPageFromSdrObject()->IsMasterPage() ) )
550  {
551  mpOutliner->SetText( *pOutlinerParaObject );
552 
553  // put text to object and set EmptyPresObj to FALSE
554  if( mpText && bOwnParaObj && mpObject->IsEmptyPresObj() && pTextObj->IsReallyEdited() )
555  {
556  mpObject->SetEmptyPresObj( false );
557  static_cast< SdrTextObj* >( mpObject)->NbcSetOutlinerParaObjectForText( std::unique_ptr<OutlinerParaObject>(pOutlinerParaObject), mpText );
558 
559  // #i103982# Here, due to mpObject->NbcSetOutlinerParaObjectForText, we LOSE ownership of the
560  // OPO, so do NOT delete it when leaving this method (!)
561  bOwnParaObj = false;
562  }
563  }
564  else
565  {
566  bool bVertical = pOutlinerParaObject && pOutlinerParaObject->IsVertical();
567 
568  // set objects style sheet on empty outliner
570  if( pPool )
571  mpOutliner->SetStyleSheetPool( pPool );
572 
574  if( pStyleSheet )
575  mpOutliner->SetStyleSheet( 0, pStyleSheet );
576 
577  if( bVertical )
578  {
579  mpOutliner->SetVertical( pOutlinerParaObject->GetDirectVertical());
580  mpOutliner->SetRotation( pOutlinerParaObject->GetRotation());
581  }
582  }
583 
584  // maybe we have to set the border attributes
585  if (mpOutliner->GetParagraphCount()==1)
586  {
587  // if we only have one paragraph we check if it is empty
588  OUString aStr(mpOutliner->GetText(mpOutliner->GetParagraph(0)));
589 
590  if (aStr.isEmpty())
591  {
592  // its empty, so we have to force the outliner to initialise itself
593  mpOutliner->SetText( "", mpOutliner->GetParagraph( 0 ) );
594 
595  if(mpObject->GetStyleSheet())
596  mpOutliner->SetStyleSheet( 0, mpObject->GetStyleSheet());
597  }
598  }
599 
600  mbDataValid = true;
601 
602  if( bOwnParaObj )
603  delete pOutlinerParaObject;
604  }
605 
606  if( bCreated && mpOutliner && HasView() )
607  {
608  // register as listener - need to broadcast state change messages
609  // registration delayed until outliner is completely set up
610  mpOutliner->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
611  }
612 
613  // prevent EE/Outliner notifications during setup
614  mbNotificationsDisabled = false;
615 
616  return mpTextForwarder.get();
617 }
618 
619 
621 {
622  if( !mpTextForwarder && HasView() )
623  {
624  SdrOutliner* pEditOutliner = mpView->GetTextEditOutliner();
625 
626  if( pEditOutliner )
627  {
629  mbForwarderIsEditMode = true;
630  }
631  }
632 
633  return mpTextForwarder.get();
634 }
635 
636 
638 {
639  if( mpObject == nullptr )
640  return nullptr;
641 
642  if( mpModel == nullptr )
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  {
651  {
652  // forwarder mismatch - create new
653  mpTextForwarder.reset();
654  }
655 
656  if( IsEditMode() )
657  return GetEditModeTextForwarder();
658  else
660  }
661  else
662  {
663  // tdf#123470 if the text edit mode of the shape is active, then we
664  // cannot trust a previously cached TextForwarder state as the text may
665  // be out of date, so force a refetch in that case.
666  if (IsEditMode())
667  {
668  assert(!mbForwarderIsEditMode); // because without a view there is no other option except !mbForwarderIsEditMode
669  bool bTextEditActive = false;
670  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(mpObject);
671  // similar to the GetBackgroundTextForwarder check, see if the text edit is active
672  if (pTextObj && pTextObj->getActiveText() == mpText && pTextObj->GetEditOutlinerParaObject())
673  bTextEditActive = true; // text edit active
674  if (bTextEditActive)
675  mbDataValid = false;
676  }
677 
679  }
680 }
681 
682 std::unique_ptr<SvxDrawOutlinerViewForwarder> SvxTextEditSourceImpl::CreateViewForwarder()
683 {
685  {
686  // register as listener - need to broadcast state change messages
689 
690  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
691  if( pTextObj )
692  {
693  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
695 
696  return std::unique_ptr<SvxDrawOutlinerViewForwarder>(new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() ));
697  }
698  }
699 
700  return nullptr;
701 }
702 
704 {
705  if( mpObject == nullptr )
706  return nullptr;
707 
708  if( mpModel == nullptr )
710 
711  // shall we delete?
712  if( mpViewForwarder )
713  {
714  if( !IsEditMode() )
715  {
716  // destroy all forwarders (no need for UpdateData(),
717  // it's been synched on SdrEndTextEdit)
718  mpViewForwarder.reset();
719  }
720  }
721  // which to create? Directly in edit mode, create new, or none?
722  else if( mpView )
723  {
724  if( IsEditMode() )
725  {
726  // create new view forwarder
728  }
729  else if( bCreate )
730  {
731  // dispose old text forwarder
732  UpdateData();
733 
734  mpTextForwarder.reset();
735 
736  // enter edit mode
738 
740  {
741  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
742  if (pTextObj && pTextObj->IsTextEditActive())
743  {
744  // create new view forwarder
746  }
747  else
748  {
749  // failure. Somehow, SdrBeginTextEdit did not set
750  // our SdrTextObj into edit mode
752  }
753  }
754  }
755  }
756 
757  return mpViewForwarder.get();
758 }
759 
760 
762 {
763  // if we have a view and in edit mode, we're working with the
764  // DrawOutliner. Thus, all changes made on the text forwarder are
765  // reflected on the view and committed to the model on
766  // SdrEndTextEdit(). Thus, no need for explicit updates here.
767  if( !HasView() || !IsEditMode() )
768  {
769  if( mbIsLocked )
770  {
771  mbNeedsUpdate = true;
772  }
773  else
774  {
775  if( mpOutliner && mpObject && mpText )
776  {
777  SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
778  if( pTextObj )
779  {
780  if( mpOutliner->GetParagraphCount() != 1 || mpOutliner->GetEditEngine().GetTextLen( 0 ) )
781  {
782  if( mpOutliner->GetParagraphCount() > 1 )
783  {
784  if (pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_TITLETEXT)
785  {
786  while( mpOutliner->GetParagraphCount() > 1 )
787  {
788  ESelection aSel( 0,mpOutliner->GetEditEngine().GetTextLen( 0 ), 1,0 );
789  mpOutliner->QuickInsertLineBreak( aSel );
790  }
791  }
792  }
793 
794  pTextObj->NbcSetOutlinerParaObjectForText( mpOutliner->CreateParaObject(), mpText );
795  }
796  else
797  {
798  pTextObj->NbcSetOutlinerParaObjectForText( nullptr,mpText );
799  }
800  }
801 
802  if( mpObject->IsEmptyPresObj() )
803  mpObject->SetEmptyPresObj(false);
804  }
805  }
806  }
807 }
808 
810 {
811  mbIsLocked = true;
812  if( mpOutliner )
813  {
814  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateMode( false );
815  mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled();
816  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false );
817  }
818 }
819 
821 {
822  mbIsLocked = false;
823 
824  if( mbNeedsUpdate )
825  {
826  UpdateData();
827  mbNeedsUpdate = false;
828  }
829 
830  if( mpOutliner )
831  {
832  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateMode( true );
833  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( mbOldUndoMode );
834  }
835 }
836 
838 {
839  return mpView && mpWindow;
840 }
841 
842 Point SvxTextEditSourceImpl::LogicToPixel( const Point& rPoint, const MapMode& rMapMode )
843 {
844  // The responsibilities of ViewForwarder happen to be
845  // somewhat mixed in this case. On the one hand, we need the
846  // different interface queries on the SvxEditSource interface,
847  // since we need both VisAreas. On the other hand, if an
848  // EditViewForwarder exists, maTextOffset does not remain static,
849  // but may change with every key press.
850  if( IsEditMode() )
851  {
852  SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false);
853 
854  if( pForwarder )
855  return pForwarder->LogicToPixel( rPoint, rMapMode );
856  }
857  else if( IsValid() && mpModel )
858  {
859  Point aPoint1( rPoint );
860  aPoint1.AdjustX(maTextOffset.X() );
861  aPoint1.AdjustY(maTextOffset.Y() );
862 
863  Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode,
864  MapMode(mpModel->GetScaleUnit()) ) );
865  MapMode aMapMode(mpWindow->GetMapMode());
866  aMapMode.SetOrigin(Point());
867  return mpWindow->LogicToPixel( aPoint2, aMapMode );
868  }
869 
870  return Point();
871 }
872 
873 Point SvxTextEditSourceImpl::PixelToLogic( const Point& rPoint, const MapMode& rMapMode )
874 {
875  // The responsibilities of ViewForwarder happen to be
876  // somewhat mixed in this case. On the one hand, we need the
877  // different interface queries on the SvxEditSource interface,
878  // since we need both VisAreas. On the other hand, if an
879  // EditViewForwarder exists, maTextOffset does not remain static,
880  // but may change with every key press.
881  if( IsEditMode() )
882  {
883  SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false);
884 
885  if( pForwarder )
886  return pForwarder->PixelToLogic( rPoint, rMapMode );
887  }
888  else if( IsValid() && mpModel )
889  {
890  MapMode aMapMode(mpWindow->GetMapMode());
891  aMapMode.SetOrigin(Point());
892  Point aPoint1( mpWindow->PixelToLogic( rPoint, aMapMode ) );
893  Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
895  rMapMode ) );
896  aPoint2.AdjustX( -(maTextOffset.X()) );
897  aPoint2.AdjustY( -(maTextOffset.Y()) );
898 
899  return aPoint2;
900  }
901 
902  return Point();
903 }
904 
905 IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify&, rNotify, void)
906 {
907  if( !mbNotificationsDisabled )
908  {
909  std::unique_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( &rNotify) );
910 
911  if (aHint)
912  Broadcast(*aHint);
913  }
914 }
915 
917 {
918  mpImpl = new SvxTextEditSourceImpl( pObject, pText );
919 }
920 
921 
923 {
924  mpImpl = new SvxTextEditSourceImpl( rObj, pText, rView, rWindow );
925 }
926 
927 
929 {
930  mpImpl = pImpl;
931 }
932 
933 
935 {
936  ::SolarMutexGuard aGuard;
937  mpImpl.clear();
938 }
939 
940 
941 std::unique_ptr<SvxEditSource> SvxTextEditSource::Clone() const
942 {
943  return std::unique_ptr<SvxEditSource>(new SvxTextEditSource( mpImpl.get() ));
944 }
945 
946 
948 {
949  return mpImpl->GetTextForwarder();
950 }
951 
952 
954 {
955  return mpImpl->GetEditViewForwarder( bCreate );
956 }
957 
958 
960 {
961  return this;
962 }
963 
964 
966 {
967  mpImpl->UpdateData();
968 }
969 
971 {
972  return *mpImpl;
973 }
974 
976 {
977  mpImpl->lock();
978 }
979 
981 {
982  mpImpl->unlock();
983 }
984 
986 {
987  return mpImpl->IsValid();
988 }
989 
990 Point SvxTextEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
991 {
992  return mpImpl->LogicToPixel( rPoint, rMapMode );
993 }
994 
995 Point SvxTextEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
996 {
997  return mpImpl->PixelToLogic( rPoint, rMapMode );
998 }
999 
1001 {
1002  mpImpl->addRange( pNewRange );
1003 }
1004 
1006 {
1007  mpImpl->removeRange( pOldRange );
1008 }
1009 
1011 {
1012  return mpImpl->getRanges();
1013 }
1014 
1016 {
1017  mpImpl->UpdateOutliner();
1018 }
1019 
1020 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
VclPtr< const OutputDevice > mpWindow
Definition: unoshtxt.cxx:87
Point TopLeft() const
virtual void removeRange(SvxUnoTextRangeBase *pOldRange) override
Definition: unoshtxt.cxx:1005
virtual Point LogicToPixel(const Point &, const MapMode &) const override
Definition: unoshtxt.cxx:990
OutlinerMode
SdrHintKind GetKind() const
Definition: svdmodel.hxx:124
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:881
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
Definition: svdedxv.cxx:1400
std::unique_ptr< SvxDrawOutlinerViewForwarder > CreateViewForwarder()
Definition: unoshtxt.cxx:682
void SetupOutlinerFormatting(SdrOutliner &rOutl, tools::Rectangle &rPaintRect) const
Setup given Outliner equivalently to SdrTextObj::Paint()
Definition: svdotext.cxx:1332
long AdjustX(long nHorzMove)
std::unique_ptr< SvxDrawOutlinerViewForwarder > mpViewForwarder
Definition: unoshtxt.cxx:91
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void RemoveObjectUser(sdr::ObjectUser &rOldUser)
Definition: svdobj.cxx:253
virtual SdrText * getText(sal_Int32 nIndex) const override
returns the nth available text.
Definition: svdotext.cxx:2057
Point PixelToLogic(const Point &, const MapMode &rMapMode)
Definition: unoshtxt.cxx:873
bool IsVertical() const
static::std::unique_ptr< SfxHint > EENotification2Hint(EENotify const *aNotify)
bool IsTextFrame() const
Definition: svdotext.hxx:343
SdrModel * mpModel
Definition: unoshtxt.cxx:88
virtual std::unique_ptr< SvxEditSource > Clone() const override
Definition: unoshtxt.cxx:941
bool IsInserted() const
Definition: svdobj.hxx:792
const MapMode & GetMapMode() const
void SetEmptyPresObj(bool bEpt)
Definition: svdobj.cxx:2481
oslInterlockedCount maRefCount
Definition: unoshtxt.cxx:82
bool IsTextEditActive() const
Definition: svdotext.hxx:363
SbxObjectRef mpObject
std::unique_ptr< SvxOutlinerForwarder > mpTextForwarder
Definition: unoshtxt.cxx:90
SfxHintId GetId() const
void AddObjectUser(sdr::ObjectUser &rNewUser)
Definition: svdobj.cxx:248
virtual ~SvxTextEditSourceImpl() override
Definition: unoshtxt.cxx:219
SvxUnoTextRangeBaseVec mvTextRanges
Definition: unoshtxt.cxx:103
MapUnit GetScaleUnit() const
Definition: svdmodel.hxx:367
bool GetDirectVertical() const
virtual SvxTextForwarder * GetTextForwarder() override
Definition: unoshtxt.cxx:947
SdrPage * getSdrPageFromSdrObject() const
Definition: svdobj.cxx:289
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: unoshtxt.cxx:256
static bool IsFuzzing()
std::vector< SvxUnoTextRangeBase * > SvxUnoTextRangeBaseVec
virtual bool IsReallyEdited() const
returns true only if we are in edit mode and the user actually changed anything
Definition: svdotext.cxx:1700
SfxStyleSheet * GetStyleSheet() const
Definition: svdobj.cxx:2162
std::unique_ptr< SdrOutliner > mpOutliner
Definition: unoshtxt.cxx:89
virtual SvxEditViewForwarder * GetEditViewForwarder(bool bCreate=false) override
Definition: unoshtxt.cxx:953
std::unique_ptr< OutlinerParaObject > GetEditOutlinerParaObject() const
Definition: svdotext.cxx:808
std::unique_ptr< SdrOutliner > createOutliner(OutlinerMode nOutlinerMode)
Definition: svdmodel.cxx:1853
SvxTextForwarder * GetEditModeTextForwarder()
Definition: unoshtxt.cxx:620
void SetNotifyHdl(const Link< EENotify &, void > &rLink)
virtual ~SvxTextEditSource() override
Definition: unoshtxt.cxx:934
const SdrOutliner * GetTextEditOutliner() const
Definition: svdedxv.hxx:233
VclPtr< vcl::Window > mpWindow
Point LogicToPixel(const Point &, const MapMode &rMapMode)
Definition: unoshtxt.cxx:842
void UpdateOutlinerFormatting(SdrOutliner &rOutl, tools::Rectangle &rPaintRect) const
Update given Outliner equivalently to SdrTextObj::Paint()
Definition: svdotext.cxx:1338
SvxEditViewForwarder * GetEditViewForwarder(bool)
Definition: unoshtxt.cxx:703
#define DBG_ASSERT(sCon, aError)
long AdjustY(long nVertMove)
void removeRange(SvxUnoTextRangeBase *pOldRange)
Definition: unoshtxt.cxx:237
virtual sal_uInt16 GetObjIdentifier() const
Definition: svdobj.cxx:585
virtual SfxStyleSheet * GetTextStyleSheetForObject(SdrObject *pObj) const
Definition: svdpage.cxx:1709
css::uno::Reference< css::linguistic2::XLinguServiceManager2 > m_xLinguServiceManager
Definition: unoshtxt.cxx:92
SvxTextEditSourceImpl(SdrObject *pObject, SdrText *pText)
Definition: unoshtxt.cxx:154
virtual void addRange(SvxUnoTextRangeBase *pNewRange) override
Definition: unoshtxt.cxx:1000
SvxTextForwarder * GetTextForwarder()
Definition: unoshtxt.cxx:637
virtual bool SdrBeginTextEdit(SdrObject *pObj, SdrPageView *pPV=nullptr, vcl::Window *pWin=nullptr, bool bIsNewObj=false, SdrOutliner *pGivenOutliner=nullptr, OutlinerView *pGivenOutlinerView=nullptr, bool bDontDeleteOutliner=false, bool bOnlyOneView=false, bool bGrabFocus=true)
Definition: svdedxv.cxx:1053
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:299
const OutlinerView * GetTextEditOutlinerView() const
Definition: svdedxv.hxx:235
bool IsMasterPage() const
Definition: svdpage.hxx:451
virtual const SvxUnoTextRangeBaseVec & getRanges() const override
Definition: unoshtxt.cxx:1010
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
bool IsEditMode() const
Definition: unoshtxt.cxx:112
virtual SdrText * getActiveText() const
returns the currently active text.
Definition: svdotext.cxx:2048
Abstract DrawObject.
Definition: svdobj.hxx:312
long X() const
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:580
virtual Point LogicToPixel(const Point &rPoint, const MapMode &rMapMode) const =0
SvxTextEditSource(SdrObject *pObj, SdrText *pText)
Definition: unoshtxt.cxx:916
virtual Point PixelToLogic(const Point &rPoint, const MapMode &rMapMode) const =0
Point PixelToLogic(const Point &rDevicePt) const
Point LogicToPixel(const Point &rLogicPt) const
virtual SfxBroadcaster & GetBroadcaster() const override
Definition: unoshtxt.cxx:970
void SetUpdateMode(bool bUpdate)
TitleText, special text object for StarDraw.
Definition: svdobj.hxx:135
rtl::Reference< SvxTextEditSourceImpl > mpImpl
Definition: unoshtxt.hxx:84
void Broadcast(const SfxHint &rHint)
virtual void ObjectInDestruction(const SdrObject &rObject) override
Definition: unoshtxt.cxx:384
bool IsValid() const
Definition: unoshtxt.cxx:837
IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify &, rNotify, void)
Definition: unoshtxt.cxx:905
TextRotation GetRotation() const
bool HasView() const
Definition: unoshtxt.cxx:111
SfxStyleSheetBasePool * GetStyleSheetPool() const
Definition: svdmodel.hxx:538
void NbcSetOutlinerParaObjectForText(std::unique_ptr< OutlinerParaObject > pTextObject, SdrText *pText)
Definition: svdotext.cxx:1376
void EnableUndo(bool bEnable)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
Reference< XComponentContext > getProcessComponentContext()
UnoViewSharedPtr mpView
virtual SvxViewForwarder * GetViewForwarder() override
Definition: unoshtxt.cxx:959
DECL_LINK(NotifyHdl, EENotify &, void)
void disposeOutliner(std::unique_ptr< SdrOutliner > pOutliner)
Definition: svdmodel.cxx:1870
OutlinerParaObject * GetOutlinerParaObject() const
Definition: svdtext.cxx:90
SdrObjKind GetTextKind() const
Definition: svdotext.hxx:358
virtual Point PixelToLogic(const Point &, const MapMode &) const override
Definition: unoshtxt.cxx:995
virtual bool IsValid() const override
Definition: unoshtxt.cxx:985
SdrObject * mpObject
Definition: unoshtxt.cxx:84
void addRange(SvxUnoTextRangeBase *pNewRange)
Definition: unoshtxt.cxx:229
aStr
text object
Definition: svdobj.hxx:134
const sdr::table::CellRef & getActiveCell() const
The active table has the focus or is currently edited.
Definition: svdotable.cxx:1547
const SvxUnoTextRangeBaseVec & getRanges() const
Definition: unoshtxt.cxx:136
long Y() const
SvxTextForwarder * GetBackgroundTextForwarder()
Definition: unoshtxt.cxx:478
virtual void UpdateData() override
Definition: unoshtxt.cxx:965
const SdrObject * GetObject() const
Definition: svdmodel.hxx:123
bool IsEmptyPresObj() const
Definition: svdobj.hxx:880