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 <editeng/outliner.hxx>
38 #include <editeng/unoforou.hxx>
39 #include <editeng/unoviwou.hxx>
40 #include <editeng/outlobj.hxx>
41 #include <svx/svdotext.hxx>
42 #include <svx/svdpage.hxx>
43 #include <editeng/editeng.hxx>
44 
45 #include <editeng/unotext.hxx>
46 #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
48 #include <svx/svdotable.hxx>
49 #include <cell.hxx>
50 #include <unotools/configmgr.hxx>
51 
52 
53 // SvxTextEditSourceImpl
54 
55 
77 {
78 private:
79  oslInterlockedCount maRefCount;
80 
81  SdrObject* mpObject; // TTTT could be reference (?)
85  SdrModel* mpModel; // TTTT probably not needed -> use SdrModel from SdrObject (?)
86  std::unique_ptr<SdrOutliner> mpOutliner;
87  std::unique_ptr<SvxOutlinerForwarder> mpTextForwarder;
88  std::unique_ptr<SvxDrawOutlinerViewForwarder> mpViewForwarder; // if non-NULL, use GetViewModeTextForwarder text forwarder
89  css::uno::Reference< css::linguistic2::XLinguServiceManager2 > m_xLinguServiceManager;
92  bool mbIsLocked;
95  bool mbForwarderIsEditMode; // have to reflect that, since ENDEDIT can happen more often
96  bool mbShapeIsEditMode; // only true, if SdrHintKind::BeginEdit was received
97  bool mbNotificationsDisabled; // prevent EditEngine/Outliner notifications (e.g. when setting up forwarder)
99 
101 
104  std::unique_ptr<SvxDrawOutlinerViewForwarder> CreateViewForwarder();
105 
106  void SetupOutliner();
107 
108  bool HasView() const { return mpView != nullptr; }
109  bool IsEditMode() const
110  {
111  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
112  return mbShapeIsEditMode && pTextObj && pTextObj->IsTextEditActive();
113  }
114 
115  void dispose();
116 
117 public:
118  SvxTextEditSourceImpl( SdrObject* pObject, SdrText* pText );
119  SvxTextEditSourceImpl( SdrObject& rObject, SdrText* pText, SdrView& rView, const OutputDevice& rWindow );
120  virtual ~SvxTextEditSourceImpl() override;
121 
122  void acquire();
123  void release();
124 
125  virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
126 
129  void UpdateData();
130 
131  void addRange( SvxUnoTextRangeBase* pNewRange );
132  void removeRange( SvxUnoTextRangeBase* pOldRange );
134 
135  void lock();
136  void unlock();
137 
138  bool IsValid() const;
139 
140  Point LogicToPixel( const Point&, const MapMode& rMapMode );
141  Point PixelToLogic( const Point&, const MapMode& rMapMode );
142 
143  DECL_LINK( NotifyHdl, EENotify&, void );
144 
145  virtual void ObjectInDestruction(const SdrObject& rObject) override;
146 
147  void UpdateOutliner();
148 };
149 
150 
152  : maRefCount ( 0 ),
153  mpObject ( pObject ),
154  mpText ( pText ),
155  mpView ( nullptr ),
156  mpWindow ( nullptr ),
157  mpModel ( pObject ? &pObject->getSdrModelFromSdrObject() : nullptr ), // TTTT should be reference
158  mbDataValid ( false ),
159  mbIsLocked ( false ),
160  mbNeedsUpdate ( false ),
161  mbOldUndoMode ( false ),
162  mbForwarderIsEditMode ( false ),
163  mbShapeIsEditMode ( false ),
164  mbNotificationsDisabled ( false ),
165  mbNotifyEditOutlinerSet ( false )
166 {
167  DBG_ASSERT( mpObject, "invalid pObject!" );
168 
169  if( !mpText )
170  {
171  SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
172  if( pTextObj )
173  mpText = pTextObj->getText( 0 );
174  }
175 
176  if( mpModel )
178 
179  if( mpObject )
180  mpObject->AddObjectUser( *this );
181 }
182 
183 
185  : maRefCount ( 0 ),
186  mpObject ( &rObject ),
187  mpText ( pText ),
188  mpView ( &rView ),
189  mpWindow ( &rWindow ),
190  mpModel ( &rObject.getSdrModelFromSdrObject() ), // TTTT should be reference
191  mbDataValid ( false ),
192  mbIsLocked ( false ),
193  mbNeedsUpdate ( false ),
194  mbOldUndoMode ( false ),
195  mbForwarderIsEditMode ( false ),
196  mbShapeIsEditMode ( true ),
197  mbNotificationsDisabled ( false ),
198  mbNotifyEditOutlinerSet ( false )
199 {
200  if( !mpText )
201  {
202  SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
203  if( pTextObj )
204  mpText = pTextObj->getText( 0 );
205  }
206 
209  mpObject->AddObjectUser( *this );
210 
211  // Init edit mode state from shape info (IsTextEditActive())
213 }
214 
215 
217 {
218  DBG_ASSERT( !mbIsLocked, "text edit source was not unlocked before dispose!" );
219  if( mpObject )
220  mpObject->RemoveObjectUser( *this );
221 
222  dispose();
223 }
224 
225 
227 {
228  if( pNewRange )
229  if( std::find( mvTextRanges.begin(), mvTextRanges.end(), pNewRange ) == mvTextRanges.end() )
230  mvTextRanges.push_back( pNewRange );
231 }
232 
233 
235 {
236  if( pOldRange )
237  mvTextRanges.erase( std::remove(mvTextRanges.begin(), mvTextRanges.end(), pOldRange), mvTextRanges.end() );
238 }
239 
240 
242 {
243  osl_atomic_increment( &maRefCount );
244 }
245 
246 
248 {
249  if( ! osl_atomic_decrement( &maRefCount ) )
250  delete this;
251 }
252 
254 {
255  // #i105988 keep reference to this object
257 
258  if (SfxHintId::Dying == rHint.GetId())
259  {
260  if (&rBC == mpView)
261  {
262  mpView = nullptr;
263  mpViewForwarder.reset();
264  }
265  }
266  else if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
267  {
268  const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
269  switch( pSdrHint->GetKind() )
270  {
272  {
273  mbDataValid = false; // Text has to be get again
274 
275  if( HasView() )
276  {
277  // Update maTextOffset, object has changed
278  // Cannot call that here, since TakeTextRect() (called from there)
279  // changes outliner content.
280  // UpdateOutliner();
281 
282  // Broadcast object changes, as they might change visible attributes
283  SvxViewChangedHint aHint;
284  Broadcast( aHint );
285  }
286  break;
287  }
288 
290  if( mpObject == pSdrHint->GetObject() )
291  {
292  // Once SdrHintKind::BeginEdit is broadcast, each EditSource of
293  // AccessibleCell will handle it here and call below:
294  // mpView->GetTextEditOutliner()->SetNotifyHdl(), which
295  // will replace the Notifier for current editable cell. It
296  // is totally wrong. So add check here to avoid the
297  // incorrect replacement of notifier.
298 
299  // Currently it only happens on the editsource of
300  // AccessibleCell
301  if (mpObject && mpText)
302  {
303  sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mpObject );
304  if(pTableObj)
305  {
306  const sdr::table::CellRef& xCell = pTableObj->getActiveCell();
307  if (xCell.is())
308  {
309  sdr::table::Cell* pCellObj = dynamic_cast< sdr::table::Cell* >( mpText );
310  if (pCellObj && xCell.get() != pCellObj)
311  break;
312  }
313  }
314  }
315  // invalidate old forwarder
316  if( !mbForwarderIsEditMode )
317  {
318  mpTextForwarder.reset();
319  }
320 
321  // register as listener - need to broadcast state change messages
322  if( mpView && mpView->GetTextEditOutliner() )
323  {
326  }
327 
328  // Only now we're really in edit mode
329  mbShapeIsEditMode = true;
330 
331  Broadcast( *pSdrHint );
332  }
333  break;
334 
336  if( mpObject == pSdrHint->GetObject() )
337  {
338  Broadcast( *pSdrHint );
339 
340  // We're no longer in edit mode
341  mbShapeIsEditMode = false;
342 
343  // remove as listener - outliner might outlive ourselves
344  if( mpView && mpView->GetTextEditOutliner() )
345  {
347  mbNotifyEditOutlinerSet = false;
348  }
349 
350  // destroy view forwarder, OutlinerView no longer
351  // valid (no need for UpdateData(), it's been
352  // synched on SdrEndTextEdit)
353  mpViewForwarder.reset();
354 
355  // Invalidate text forwarder, we might
356  // not be called again before entering edit mode a
357  // second time! Then, the old outliner might be
358  // invalid.
360  {
361  mbForwarderIsEditMode = false;
362  mpTextForwarder.reset();
363  }
364  }
365  break;
366 
368  dispose();
369  break;
370  default:
371  break;
372  }
373  }
374  else if (const SvxViewChangedHint* pViewHint = dynamic_cast<const SvxViewChangedHint*>(&rHint))
375  {
376  Broadcast( *pViewHint );
377  }
378 }
379 
380 /* this is a callback from the attached SdrObject when it is actually deleted */
382 {
383  mpObject = nullptr;
384  dispose();
385  Broadcast( SfxHint( SfxHintId::Dying ) );
386 }
387 
388 /* unregister at all objects and set all references to 0 */
390 {
391  mpTextForwarder.reset();
392  mpViewForwarder.reset();
393 
394  if( mpOutliner )
395  {
396  if( mpModel )
397  {
398  mpModel->disposeOutliner( std::move(mpOutliner) );
399  }
400  else
401  {
402  mpOutliner.reset();
403  }
404  }
405 
406  if( mpModel )
407  {
408  EndListening( *mpModel );
409  mpModel = nullptr;
410  }
411 
412  if( mpView )
413  {
414  // remove as listener - outliner might outlive ourselves
416  {
418  mbNotifyEditOutlinerSet = false;
419  }
420  EndListening( *mpView );
421  mpView = nullptr;
422  }
423 
424  if( mpObject )
425  {
426  mpObject->RemoveObjectUser( *this );
427  mpObject = nullptr;
428  }
429  mpWindow = nullptr;
430 }
431 
432 
434 {
435  // only for UAA edit source: setup outliner equivalently as in
436  // SdrTextObj::Paint(), such that formatting equals screen
437  // layout
438  if( !(mpObject && mpOutliner) )
439  return;
440 
441  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
442  if( pTextObj )
443  {
444  tools::Rectangle aPaintRect;
445  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
446  pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect );
447 
448  // calc text offset from shape anchor
449  maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
450  }
451 }
452 
453 
455 {
456  // only for UAA edit source: update outliner equivalently as in
457  // SdrTextObj::Paint(), such that formatting equals screen
458  // layout
459  if( !(mpObject && mpOutliner) )
460  return;
461 
462  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
463  if( pTextObj )
464  {
465  tools::Rectangle aPaintRect;
466  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
467  pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect );
468 
469  // calc text offset from shape anchor
470  maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
471  }
472 }
473 
474 
476 {
477  bool bCreated = false;
478 
479  // prevent EE/Outliner notifications during setup
481 
482  if (!mpTextForwarder)
483  {
484  if( mpOutliner == nullptr )
485  {
486  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
487  OutlinerMode nOutlMode = OutlinerMode::TextObject;
488  if( pTextObj && pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_OUTLINETEXT )
489  nOutlMode = OutlinerMode::OutlineObject;
490 
491  mpOutliner = mpModel->createOutliner( nOutlMode );
492 
493  // Do the setup after outliner creation, would be useless otherwise
494  if( HasView() )
495  {
496  // Setup outliner _before_ filling it
497  SetupOutliner();
498  }
499 
500  mpOutliner->SetTextObjNoInit( pTextObj );
501  if( mbIsLocked )
502  {
503  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateMode( false );
504  mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled();
505  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false );
506  }
507 
509  {
510  if ( !m_xLinguServiceManager.is() )
511  {
512  css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
513  m_xLinguServiceManager.set(css::linguistic2::LinguServiceManager::create(xContext));
514  }
515 
516  css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator = m_xLinguServiceManager->getHyphenator();
517  if( xHyphenator.is() )
518  mpOutliner->SetHyphenator( xHyphenator );
519  }
520  }
521 
522 
524  // delay listener subscription and UAA initialization until Outliner is fully setup
525  bCreated = true;
526 
527  mbForwarderIsEditMode = false;
528  mbDataValid = false;
529  }
530 
532  {
533  mpTextForwarder->flushCache();
534 
535  OutlinerParaObject* pOutlinerParaObject = nullptr;
536  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
537  if( pTextObj && pTextObj->getActiveText() == mpText )
538  pOutlinerParaObject = pTextObj->CreateEditOutlinerParaObject().release(); // Get the OutlinerParaObject if text edit is active
539  bool bOwnParaObj(false);
540 
541  if( pOutlinerParaObject )
542  bOwnParaObj = true; // text edit active
543  else
544  pOutlinerParaObject = mpText->GetOutlinerParaObject();
545 
546  if( pOutlinerParaObject && ( bOwnParaObj || !mpObject->IsEmptyPresObj() || mpObject->getSdrPageFromSdrObject()->IsMasterPage() ) )
547  {
548  // tdf#72776: do not set empty text to SdrOutliner, if it is already set
549  if( !mpOutliner->GetEditEngine().GetTextLen() || pOutlinerParaObject->Count() > 1 || ( pOutlinerParaObject->Count() == 1 &&
550  !pOutlinerParaObject->GetTextObject().GetText(0).isEmpty() ) )
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->CanCreateEditOutlinerParaObject())
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  return;
769 
770  if( mbIsLocked )
771  {
772  mbNeedsUpdate = true;
773  }
774  else
775  {
776  if( mpOutliner && mpObject && mpText )
777  {
778  SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
779  if( pTextObj )
780  {
781  if( mpOutliner->GetParagraphCount() != 1 || mpOutliner->GetEditEngine().GetTextLen( 0 ) )
782  {
783  if( mpOutliner->GetParagraphCount() > 1 )
784  {
785  if (pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_TITLETEXT)
786  {
787  while( mpOutliner->GetParagraphCount() > 1 )
788  {
789  ESelection aSel( 0,mpOutliner->GetEditEngine().GetTextLen( 0 ), 1,0 );
790  mpOutliner->QuickInsertLineBreak( aSel );
791  }
792  }
793  }
794 
795  pTextObj->NbcSetOutlinerParaObjectForText( mpOutliner->CreateParaObject(), mpText );
796  }
797  else
798  {
799  pTextObj->NbcSetOutlinerParaObjectForText( nullptr,mpText );
800  }
801  }
802 
803  if( mpObject->IsEmptyPresObj() )
804  mpObject->SetEmptyPresObj(false);
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:84
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:857
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
Definition: svdedxv.cxx:1399
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
std::unique_ptr< SvxDrawOutlinerViewForwarder > mpViewForwarder
Definition: unoshtxt.cxx:88
void SetUpdateMode(bool bUpdate, bool bRestoring=false)
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void RemoveObjectUser(sdr::ObjectUser &rOldUser)
Definition: svdobj.cxx:227
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:85
virtual std::unique_ptr< SvxEditSource > Clone() const override
Definition: unoshtxt.cxx:941
bool IsInserted() const
Definition: svdobj.hxx:744
const MapMode & GetMapMode() const
void SetEmptyPresObj(bool bEpt)
Definition: svdobj.cxx:2468
oslInterlockedCount maRefCount
Definition: unoshtxt.cxx:79
virtual SdrObjKind GetObjIdentifier() const
Definition: svdobj.cxx:558
bool IsTextEditActive() const
Definition: svdotext.hxx:363
SbxObjectRef mpObject
std::unique_ptr< SvxOutlinerForwarder > mpTextForwarder
Definition: unoshtxt.cxx:87
SfxHintId GetId() const
void AddObjectUser(sdr::ObjectUser &rNewUser)
Definition: svdobj.cxx:222
virtual ~SvxTextEditSourceImpl() override
Definition: unoshtxt.cxx:216
SvxUnoTextRangeBaseVec mvTextRanges
Definition: unoshtxt.cxx:100
MapUnit GetScaleUnit() const
Definition: svdmodel.hxx:367
bool GetDirectVertical() const
virtual SvxTextForwarder * GetTextForwarder() override
Definition: unoshtxt.cxx:947
SdrPage * getSdrPageFromSdrObject() const
Definition: svdobj.cxx:263
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: unoshtxt.cxx:253
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:2149
std::unique_ptr< SdrOutliner > mpOutliner
Definition: unoshtxt.cxx:86
virtual SvxEditViewForwarder * GetEditViewForwarder(bool bCreate=false) override
Definition: unoshtxt.cxx:953
std::unique_ptr< SdrOutliner > createOutliner(OutlinerMode nOutlinerMode)
Definition: svdmodel.cxx:1840
SvxTextForwarder * GetEditModeTextForwarder()
Definition: unoshtxt.cxx:620
OUString GetText(sal_Int32 nPara) const
void SetNotifyHdl(const Link< EENotify &, void > &rLink)
virtual ~SvxTextEditSource() override
Definition: unoshtxt.cxx:934
std::unique_ptr< OutlinerParaObject > CreateEditOutlinerParaObject() const
Definition: svdotext.cxx:800
const EditTextObject & GetTextObject() const
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)
void removeRange(SvxUnoTextRangeBase *pOldRange)
Definition: unoshtxt.cxx:234
virtual SfxStyleSheet * GetTextStyleSheetForObject(SdrObject *pObj) const
Definition: svdpage.cxx:1684
css::uno::Reference< css::linguistic2::XLinguServiceManager2 > m_xLinguServiceManager
Definition: unoshtxt.cxx:89
SvxTextEditSourceImpl(SdrObject *pObject, SdrText *pText)
Definition: unoshtxt.cxx:151
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:1052
SdrModel & getSdrModelFromSdrObject() const
Definition: svdobj.cxx:273
const OutlinerView * GetTextEditOutlinerView() const
Definition: svdedxv.hxx:235
bool IsMasterPage() const
Definition: svdpage.hxx:450
virtual const SvxUnoTextRangeBaseVec & getRanges() const override
Definition: unoshtxt.cxx:1010
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
bool IsEditMode() const
Definition: unoshtxt.cxx:109
virtual SdrText * getActiveText() const
returns the currently active text.
Definition: svdotext.cxx:2048
Abstract DrawObject.
Definition: svdobj.hxx:261
virtual SdrInventor GetObjInventor() const
Definition: svdobj.cxx:553
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
bool CanCreateEditOutlinerParaObject() const
Definition: svdotext.cxx:791
virtual SfxBroadcaster & GetBroadcaster() const override
Definition: unoshtxt.cxx:970
sal_Int32 Count() const
rtl::Reference< SvxTextEditSourceImpl > mpImpl
Definition: unoshtxt.hxx:84
void Broadcast(const SfxHint &rHint)
virtual void ObjectInDestruction(const SdrObject &rObject) override
Definition: unoshtxt.cxx:381
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:108
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
text object
Definition: svdobjkind.hxx:43
virtual SvxViewForwarder * GetViewForwarder() override
Definition: unoshtxt.cxx:959
DECL_LINK(NotifyHdl, EENotify &, void)
void disposeOutliner(std::unique_ptr< SdrOutliner > pOutliner)
Definition: svdmodel.cxx:1857
OutlinerParaObject * GetOutlinerParaObject() const
Definition: svdtext.cxx:88
SdrObjKind GetTextKind() const
Definition: svdotext.hxx:358
TitleText, special text object for StarDraw.
Definition: svdobjkind.hxx:44
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:81
void addRange(SvxUnoTextRangeBase *pNewRange)
Definition: unoshtxt.cxx:226
aStr
const sdr::table::CellRef & getActiveCell() const
The active table has the focus or is currently edited.
Definition: svdotable.cxx:1546
const SvxUnoTextRangeBaseVec & getRanges() const
Definition: unoshtxt.cxx:133
SvxTextForwarder * GetBackgroundTextForwarder()
Definition: unoshtxt.cxx:475
virtual void UpdateData() override
Definition: unoshtxt.cxx:965
const SdrObject * GetObject() const
Definition: svdmodel.hxx:123
bool IsEmptyPresObj() const
Definition: svdobj.hxx:832