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  {
440  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
441  tools::Rectangle aPaintRect;
442  if( pTextObj )
443  {
444  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
445  pTextObj->SetupOutlinerFormatting( *mpOutliner, aPaintRect );
446 
447  // calc text offset from shape anchor
448  maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
449  }
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  {
461  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
462  tools::Rectangle aPaintRect;
463  if( pTextObj )
464  {
465  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
466  pTextObj->UpdateOutlinerFormatting( *mpOutliner, aPaintRect );
467 
468  // calc text offset from shape anchor
469  maTextOffset = aPaintRect.TopLeft() - aBoundRect.TopLeft();
470  }
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  mpOutliner->SetText( *pOutlinerParaObject );
549 
550  // put text to object and set EmptyPresObj to FALSE
551  if( mpText && bOwnParaObj && mpObject->IsEmptyPresObj() && pTextObj->IsReallyEdited() )
552  {
553  mpObject->SetEmptyPresObj( false );
554  static_cast< SdrTextObj* >( mpObject)->NbcSetOutlinerParaObjectForText( std::unique_ptr<OutlinerParaObject>(pOutlinerParaObject), mpText );
555 
556  // #i103982# Here, due to mpObject->NbcSetOutlinerParaObjectForText, we LOSE ownership of the
557  // OPO, so do NOT delete it when leaving this method (!)
558  bOwnParaObj = false;
559  }
560  }
561  else
562  {
563  bool bVertical = pOutlinerParaObject && pOutlinerParaObject->IsVertical();
564 
565  // set objects style sheet on empty outliner
567  if( pPool )
568  mpOutliner->SetStyleSheetPool( pPool );
569 
571  if( pStyleSheet )
572  mpOutliner->SetStyleSheet( 0, pStyleSheet );
573 
574  if( bVertical )
575  {
576  mpOutliner->SetVertical( pOutlinerParaObject->GetDirectVertical());
577  mpOutliner->SetRotation( pOutlinerParaObject->GetRotation());
578  }
579  }
580 
581  // maybe we have to set the border attributes
582  if (mpOutliner->GetParagraphCount()==1)
583  {
584  // if we only have one paragraph we check if it is empty
585  OUString aStr(mpOutliner->GetText(mpOutliner->GetParagraph(0)));
586 
587  if (aStr.isEmpty())
588  {
589  // its empty, so we have to force the outliner to initialise itself
590  mpOutliner->SetText( "", mpOutliner->GetParagraph( 0 ) );
591 
592  if(mpObject->GetStyleSheet())
593  mpOutliner->SetStyleSheet( 0, mpObject->GetStyleSheet());
594  }
595  }
596 
597  mbDataValid = true;
598 
599  if( bOwnParaObj )
600  delete pOutlinerParaObject;
601  }
602 
603  if( bCreated && mpOutliner && HasView() )
604  {
605  // register as listener - need to broadcast state change messages
606  // registration delayed until outliner is completely set up
607  mpOutliner->SetNotifyHdl( LINK(this, SvxTextEditSourceImpl, NotifyHdl) );
608  }
609 
610  // prevent EE/Outliner notifications during setup
611  mbNotificationsDisabled = false;
612 
613  return mpTextForwarder.get();
614 }
615 
616 
618 {
619  if( !mpTextForwarder && HasView() )
620  {
621  SdrOutliner* pEditOutliner = mpView->GetTextEditOutliner();
622 
623  if( pEditOutliner )
624  {
626  mbForwarderIsEditMode = true;
627  }
628  }
629 
630  return mpTextForwarder.get();
631 }
632 
633 
635 {
636  if( mpObject == nullptr )
637  return nullptr;
638 
639  if( mpModel == nullptr )
641 
642  // distinguish the cases
643  // a) connected to view, maybe edit mode is active, can work directly on the EditOutliner
644  // b) background Outliner, reflect changes into ParaOutlinerObject (this is exactly the old UNO code)
645  if( HasView() )
646  {
648  {
649  // forwarder mismatch - create new
650  mpTextForwarder.reset();
651  }
652 
653  if( IsEditMode() )
654  return GetEditModeTextForwarder();
655  else
657  }
658  else
659  {
660  // tdf#123470 if the text edit mode of the shape is active, then we
661  // cannot trust a previously cached TextForwarder state as the text may
662  // be out of date, so force a refetch in that case.
663  if (IsEditMode())
664  {
665  assert(!mbForwarderIsEditMode); // because without a view there is no other option except !mbForwarderIsEditMode
666  bool bTextEditActive = false;
667  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>(mpObject);
668  // similar to the GetBackgroundTextForwarder check, see if the text edit is active
669  if (pTextObj && pTextObj->getActiveText() == mpText && pTextObj->CanCreateEditOutlinerParaObject())
670  bTextEditActive = true; // text edit active
671  if (bTextEditActive)
672  mbDataValid = false;
673  }
674 
676  }
677 }
678 
679 std::unique_ptr<SvxDrawOutlinerViewForwarder> SvxTextEditSourceImpl::CreateViewForwarder()
680 {
682  {
683  // register as listener - need to broadcast state change messages
686 
687  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
688  if( pTextObj )
689  {
690  tools::Rectangle aBoundRect( pTextObj->GetCurrentBoundRect() );
692 
693  return std::unique_ptr<SvxDrawOutlinerViewForwarder>(new SvxDrawOutlinerViewForwarder( rOutlView, aBoundRect.TopLeft() ));
694  }
695  }
696 
697  return nullptr;
698 }
699 
701 {
702  if( mpObject == nullptr )
703  return nullptr;
704 
705  if( mpModel == nullptr )
707 
708  // shall we delete?
709  if( mpViewForwarder )
710  {
711  if( !IsEditMode() )
712  {
713  // destroy all forwarders (no need for UpdateData(),
714  // it's been synched on SdrEndTextEdit)
715  mpViewForwarder.reset();
716  }
717  }
718  // which to create? Directly in edit mode, create new, or none?
719  else if( mpView )
720  {
721  if( IsEditMode() )
722  {
723  // create new view forwarder
725  }
726  else if( bCreate )
727  {
728  // dispose old text forwarder
729  UpdateData();
730 
731  mpTextForwarder.reset();
732 
733  // enter edit mode
735 
737  {
738  SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( mpObject );
739  if (pTextObj && pTextObj->IsTextEditActive())
740  {
741  // create new view forwarder
743  }
744  else
745  {
746  // failure. Somehow, SdrBeginTextEdit did not set
747  // our SdrTextObj into edit mode
749  }
750  }
751  }
752  }
753 
754  return mpViewForwarder.get();
755 }
756 
757 
759 {
760  // if we have a view and in edit mode, we're working with the
761  // DrawOutliner. Thus, all changes made on the text forwarder are
762  // reflected on the view and committed to the model on
763  // SdrEndTextEdit(). Thus, no need for explicit updates here.
764  if( !HasView() || !IsEditMode() )
765  {
766  if( mbIsLocked )
767  {
768  mbNeedsUpdate = true;
769  }
770  else
771  {
772  if( mpOutliner && mpObject && mpText )
773  {
774  SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( mpObject );
775  if( pTextObj )
776  {
777  if( mpOutliner->GetParagraphCount() != 1 || mpOutliner->GetEditEngine().GetTextLen( 0 ) )
778  {
779  if( mpOutliner->GetParagraphCount() > 1 )
780  {
781  if (pTextObj->IsTextFrame() && pTextObj->GetTextKind() == OBJ_TITLETEXT)
782  {
783  while( mpOutliner->GetParagraphCount() > 1 )
784  {
785  ESelection aSel( 0,mpOutliner->GetEditEngine().GetTextLen( 0 ), 1,0 );
786  mpOutliner->QuickInsertLineBreak( aSel );
787  }
788  }
789  }
790 
791  pTextObj->NbcSetOutlinerParaObjectForText( mpOutliner->CreateParaObject(), mpText );
792  }
793  else
794  {
795  pTextObj->NbcSetOutlinerParaObjectForText( nullptr,mpText );
796  }
797  }
798 
799  if( mpObject->IsEmptyPresObj() )
800  mpObject->SetEmptyPresObj(false);
801  }
802  }
803  }
804 }
805 
807 {
808  mbIsLocked = true;
809  if( mpOutliner )
810  {
811  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateMode( false );
812  mbOldUndoMode = mpOutliner->GetEditEngine().IsUndoEnabled();
813  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( false );
814  }
815 }
816 
818 {
819  mbIsLocked = false;
820 
821  if( mbNeedsUpdate )
822  {
823  UpdateData();
824  mbNeedsUpdate = false;
825  }
826 
827  if( mpOutliner )
828  {
829  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->SetUpdateMode( true );
830  const_cast<EditEngine*>(&(mpOutliner->GetEditEngine()))->EnableUndo( mbOldUndoMode );
831  }
832 }
833 
835 {
836  return mpView && mpWindow;
837 }
838 
839 Point SvxTextEditSourceImpl::LogicToPixel( const Point& rPoint, const MapMode& rMapMode )
840 {
841  // The responsibilities of ViewForwarder happen to be
842  // somewhat mixed in this case. On the one hand, we need the
843  // different interface queries on the SvxEditSource interface,
844  // since we need both VisAreas. On the other hand, if an
845  // EditViewForwarder exists, maTextOffset does not remain static,
846  // but may change with every key press.
847  if( IsEditMode() )
848  {
849  SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false);
850 
851  if( pForwarder )
852  return pForwarder->LogicToPixel( rPoint, rMapMode );
853  }
854  else if( IsValid() && mpModel )
855  {
856  Point aPoint1( rPoint );
857  aPoint1.AdjustX(maTextOffset.X() );
858  aPoint1.AdjustY(maTextOffset.Y() );
859 
860  Point aPoint2( OutputDevice::LogicToLogic( aPoint1, rMapMode,
861  MapMode(mpModel->GetScaleUnit()) ) );
862  MapMode aMapMode(mpWindow->GetMapMode());
863  aMapMode.SetOrigin(Point());
864  return mpWindow->LogicToPixel( aPoint2, aMapMode );
865  }
866 
867  return Point();
868 }
869 
870 Point SvxTextEditSourceImpl::PixelToLogic( const Point& rPoint, const MapMode& rMapMode )
871 {
872  // The responsibilities of ViewForwarder happen to be
873  // somewhat mixed in this case. On the one hand, we need the
874  // different interface queries on the SvxEditSource interface,
875  // since we need both VisAreas. On the other hand, if an
876  // EditViewForwarder exists, maTextOffset does not remain static,
877  // but may change with every key press.
878  if( IsEditMode() )
879  {
880  SvxEditViewForwarder* pForwarder = GetEditViewForwarder(false);
881 
882  if( pForwarder )
883  return pForwarder->PixelToLogic( rPoint, rMapMode );
884  }
885  else if( IsValid() && mpModel )
886  {
887  MapMode aMapMode(mpWindow->GetMapMode());
888  aMapMode.SetOrigin(Point());
889  Point aPoint1( mpWindow->PixelToLogic( rPoint, aMapMode ) );
890  Point aPoint2( OutputDevice::LogicToLogic( aPoint1,
892  rMapMode ) );
893  aPoint2.AdjustX( -(maTextOffset.X()) );
894  aPoint2.AdjustY( -(maTextOffset.Y()) );
895 
896  return aPoint2;
897  }
898 
899  return Point();
900 }
901 
902 IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify&, rNotify, void)
903 {
904  if( !mbNotificationsDisabled )
905  {
906  std::unique_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( &rNotify) );
907 
908  if (aHint)
909  Broadcast(*aHint);
910  }
911 }
912 
914 {
915  mpImpl = new SvxTextEditSourceImpl( pObject, pText );
916 }
917 
918 
920 {
921  mpImpl = new SvxTextEditSourceImpl( rObj, pText, rView, rWindow );
922 }
923 
924 
926 {
927  mpImpl = pImpl;
928 }
929 
930 
932 {
933  ::SolarMutexGuard aGuard;
934  mpImpl.clear();
935 }
936 
937 
938 std::unique_ptr<SvxEditSource> SvxTextEditSource::Clone() const
939 {
940  return std::unique_ptr<SvxEditSource>(new SvxTextEditSource( mpImpl.get() ));
941 }
942 
943 
945 {
946  return mpImpl->GetTextForwarder();
947 }
948 
949 
951 {
952  return mpImpl->GetEditViewForwarder( bCreate );
953 }
954 
955 
957 {
958  return this;
959 }
960 
961 
963 {
964  mpImpl->UpdateData();
965 }
966 
968 {
969  return *mpImpl;
970 }
971 
973 {
974  mpImpl->lock();
975 }
976 
978 {
979  mpImpl->unlock();
980 }
981 
983 {
984  return mpImpl->IsValid();
985 }
986 
987 Point SvxTextEditSource::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
988 {
989  return mpImpl->LogicToPixel( rPoint, rMapMode );
990 }
991 
992 Point SvxTextEditSource::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
993 {
994  return mpImpl->PixelToLogic( rPoint, rMapMode );
995 }
996 
998 {
999  mpImpl->addRange( pNewRange );
1000 }
1001 
1003 {
1004  mpImpl->removeRange( pOldRange );
1005 }
1006 
1008 {
1009  return mpImpl->getRanges();
1010 }
1011 
1013 {
1014  mpImpl->UpdateOutliner();
1015 }
1016 
1017 /* 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:1002
virtual Point LogicToPixel(const Point &, const MapMode &) const override
Definition: unoshtxt.cxx:987
OutlinerMode
SdrHintKind GetKind() const
Definition: svdmodel.hxx:124
virtual const tools::Rectangle & GetCurrentBoundRect() const
Definition: svdobj.cxx:854
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
Definition: svdedxv.cxx:1392
std::unique_ptr< SvxDrawOutlinerViewForwarder > CreateViewForwarder()
Definition: unoshtxt.cxx:679
void SetupOutlinerFormatting(SdrOutliner &rOutl, tools::Rectangle &rPaintRect) const
Setup given Outliner equivalently to SdrTextObj::Paint()
Definition: svdotext.cxx:1324
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:2049
Point PixelToLogic(const Point &, const MapMode &rMapMode)
Definition: unoshtxt.cxx:870
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:938
bool IsInserted() const
Definition: svdobj.hxx:793
const MapMode & GetMapMode() const
void SetEmptyPresObj(bool bEpt)
Definition: svdobj.cxx:2459
oslInterlockedCount maRefCount
Definition: unoshtxt.cxx:79
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:944
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:1692
SfxStyleSheet * GetStyleSheet() const
Definition: svdobj.cxx:2140
std::unique_ptr< SdrOutliner > mpOutliner
Definition: unoshtxt.cxx:86
virtual SvxEditViewForwarder * GetEditViewForwarder(bool bCreate=false) override
Definition: unoshtxt.cxx:950
std::unique_ptr< SdrOutliner > createOutliner(OutlinerMode nOutlinerMode)
Definition: svdmodel.cxx:1840
SvxTextForwarder * GetEditModeTextForwarder()
Definition: unoshtxt.cxx:617
void SetNotifyHdl(const Link< EENotify &, void > &rLink)
virtual ~SvxTextEditSource() override
Definition: unoshtxt.cxx:931
std::unique_ptr< OutlinerParaObject > CreateEditOutlinerParaObject() const
Definition: svdotext.cxx:800
const SdrOutliner * GetTextEditOutliner() const
Definition: svdedxv.hxx:233
VclPtr< vcl::Window > mpWindow
Point LogicToPixel(const Point &, const MapMode &rMapMode)
Definition: unoshtxt.cxx:839
void UpdateOutlinerFormatting(SdrOutliner &rOutl, tools::Rectangle &rPaintRect) const
Update given Outliner equivalently to SdrTextObj::Paint()
Definition: svdotext.cxx:1330
SvxEditViewForwarder * GetEditViewForwarder(bool)
Definition: unoshtxt.cxx:700
#define DBG_ASSERT(sCon, aError)
void removeRange(SvxUnoTextRangeBase *pOldRange)
Definition: unoshtxt.cxx:234
virtual sal_uInt16 GetObjIdentifier() const
Definition: svdobj.cxx:558
virtual SfxStyleSheet * GetTextStyleSheetForObject(SdrObject *pObj) const
Definition: svdpage.cxx:1685
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:997
SvxTextForwarder * GetTextForwarder()
Definition: unoshtxt.cxx:634
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:1045
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:1007
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:2040
Abstract DrawObject.
Definition: svdobj.hxx:312
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:913
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:967
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:381
bool IsValid() const
Definition: unoshtxt.cxx:834
IMPL_LINK(SvxTextEditSourceImpl, NotifyHdl, EENotify &, rNotify, void)
Definition: unoshtxt.cxx:902
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:1368
void EnableUndo(bool bEnable)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
Reference< XComponentContext > getProcessComponentContext()
UnoViewSharedPtr mpView
virtual SvxViewForwarder * GetViewForwarder() override
Definition: unoshtxt.cxx:956
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
virtual Point PixelToLogic(const Point &, const MapMode &) const override
Definition: unoshtxt.cxx:992
virtual bool IsValid() const override
Definition: unoshtxt.cxx:982
SdrObject * mpObject
Definition: unoshtxt.cxx:81
void addRange(SvxUnoTextRangeBase *pNewRange)
Definition: unoshtxt.cxx:226
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:1542
const SvxUnoTextRangeBaseVec & getRanges() const
Definition: unoshtxt.cxx:133
SvxTextForwarder * GetBackgroundTextForwarder()
Definition: unoshtxt.cxx:475
virtual void UpdateData() override
Definition: unoshtxt.cxx:962
const SdrObject * GetObject() const
Definition: svdmodel.hxx:123
bool IsEmptyPresObj() const
Definition: svdobj.hxx:881