LibreOffice Module sc (master)  1
postit.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 <memory>
21 #include <postit.hxx>
22 
23 #include <rtl/ustrbuf.hxx>
24 #include <sal/log.hxx>
25 #include <unotools/useroptions.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdocapt.hxx>
28 #include <editeng/outlobj.hxx>
29 #include <editeng/editobj.hxx>
31 #include <osl/diagnose.h>
32 #include <comphelper/lok.hxx>
33 
34 #include <scitems.hxx>
35 #include <svx/xfillit0.hxx>
36 #include <svx/xlnstit.hxx>
37 #include <svx/xlnstwit.hxx>
38 #include <svx/xlnstcit.hxx>
39 #include <svx/sxcecitm.hxx>
40 #include <svx/xflclit.hxx>
41 #include <svx/sdshitm.hxx>
42 #include <svx/sdsxyitm.hxx>
43 #include <svx/sdtditm.hxx>
44 #include <svx/sdtagitm.hxx>
45 #include <svx/sdtmfitm.hxx>
46 #include <tools/gen.hxx>
47 
48 #include <document.hxx>
49 #include <docpool.hxx>
50 #include <patattr.hxx>
51 #include <drwlayer.hxx>
52 #include <userdat.hxx>
53 #include <detfunc.hxx>
54 #include <editutil.hxx>
55 
56 using namespace com::sun::star;
57 
58 namespace {
59 
60 const tools::Long SC_NOTECAPTION_WIDTH = 2900;
61 const tools::Long SC_NOTECAPTION_MAXWIDTH_TEMP = 12000;
62 const tools::Long SC_NOTECAPTION_HEIGHT = 1800;
63 const tools::Long SC_NOTECAPTION_CELLDIST = 600;
64 const tools::Long SC_NOTECAPTION_OFFSET_Y = -1500;
65 const tools::Long SC_NOTECAPTION_OFFSET_X = 1500;
66 const tools::Long SC_NOTECAPTION_BORDERDIST_TEMP = 100;
67 
69 class ScCaptionUtil
70 {
71 public:
73  static void SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown );
75  static void SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown );
77  static void SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos );
79  static void SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc, const SfxItemSet* pExtraItemSet );
80 };
81 
82 void ScCaptionUtil::SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown )
83 {
84  SdrLayerID nLayer = bShown ? SC_LAYER_INTERN : SC_LAYER_HIDDEN;
85  if( nLayer != rCaption.GetLayer() )
86  rCaption.SetLayer( nLayer );
87 }
88 
89 void ScCaptionUtil::SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown )
90 {
91  SetCaptionLayer( rCaption, bShown );
92  rCaption.SetFixedTail();
93  rCaption.SetSpecialTextBoxShadow();
94 }
95 
96 void ScCaptionUtil::SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos )
97 {
98  // pass true to ScDrawLayer::GetObjData() to create the object data entry
99  ScDrawObjData* pObjData = ScDrawLayer::GetObjData( &rCaption, true );
100  OSL_ENSURE( pObjData, "ScCaptionUtil::SetCaptionUserData - missing drawing object user data" );
101  pObjData->maStart = rPos;
102  pObjData->meType = ScDrawObjData::CellNote;
103 }
104 
105 void ScCaptionUtil::SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc, const SfxItemSet* pExtraItemSet )
106 {
107  SfxItemSet aItemSet = rCaption.GetMergedItemSet();
108 
109  // caption tail arrow
110  ::basegfx::B2DPolygon aTriangle;
111  aTriangle.append( ::basegfx::B2DPoint( 10.0, 0.0 ) );
112  aTriangle.append( ::basegfx::B2DPoint( 0.0, 30.0 ) );
113  aTriangle.append( ::basegfx::B2DPoint( 20.0, 30.0 ) );
114  aTriangle.setClosed( true );
115  /* Line ends are now created with an empty name. The
116  checkForUniqueItem() method then finds a unique name for the item's
117  value. */
118  aItemSet.Put( XLineStartItem( OUString(), ::basegfx::B2DPolyPolygon( aTriangle ) ) );
119  aItemSet.Put( XLineStartWidthItem( 200 ) );
120  aItemSet.Put( XLineStartCenterItem( false ) );
121  aItemSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
122  aItemSet.Put( XFillColorItem( OUString(), ScDetectiveFunc::GetCommentColor() ) );
123  aItemSet.Put( SdrCaptionEscDirItem( SdrCaptionEscDir::BestFit ) );
124 
125  // shadow
126  /* SdrShadowItem has sal_False, instead the shadow is set for the
127  rectangle only with SetSpecialTextBoxShadow() when the object is
128  created (item must be set to adjust objects from older files). */
129  aItemSet.Put( makeSdrShadowItem( false ) );
130  aItemSet.Put( makeSdrShadowXDistItem( 100 ) );
131  aItemSet.Put( makeSdrShadowYDistItem( 100 ) );
132 
133  // text attributes
134  aItemSet.Put( makeSdrTextLeftDistItem( 100 ) );
135  aItemSet.Put( makeSdrTextRightDistItem( 100 ) );
136  aItemSet.Put( makeSdrTextUpperDistItem( 100 ) );
137  aItemSet.Put( makeSdrTextLowerDistItem( 100 ) );
138  aItemSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
139  aItemSet.Put( makeSdrTextAutoGrowHeightItem( true ) );
140  // use the default cell style to be able to modify the caption font
141  const ScPatternAttr& rDefPattern = rDoc.GetPool()->GetDefaultItem( ATTR_PATTERN );
142  rDefPattern.FillEditItemSet( &aItemSet );
143 
144  if (pExtraItemSet)
145  {
146  /* Updates caption item set according to the passed item set while removing shadow items. */
147 
148  aItemSet.Put(*pExtraItemSet);
149  // reset shadow items
150  aItemSet.Put( makeSdrShadowItem( false ) );
151  aItemSet.Put( makeSdrShadowXDistItem( 100 ) );
152  aItemSet.Put( makeSdrShadowYDistItem( 100 ) );
153  }
154 
155  rCaption.SetMergedItemSet( aItemSet );
156 
157  if (pExtraItemSet)
158  rCaption.SetSpecialTextBoxShadow();
159 }
160 
163 class ScCaptionCreator
164 {
165 public:
167  explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bTailFront );
169  explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const ScCaptionPtr& xCaption );
170 
172  SdrPage* GetDrawPage();
174  ScCaptionPtr & GetCaption() { return mxCaption; }
175 
177  void FitCaptionToRect( const tools::Rectangle* pVisRect = nullptr );
179  void AutoPlaceCaption( const tools::Rectangle* pVisRect = nullptr );
181  void UpdateCaptionPos();
182 
183 protected:
185  explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos );
186 
188  Point CalcTailPos( bool bTailFront );
190  void CreateCaption( bool bShown, bool bTailFront );
191 
192 private:
194  void Initialize();
196  const tools::Rectangle& GetVisRect( const tools::Rectangle* pVisRect ) const { return pVisRect ? *pVisRect : maPageRect; }
197 
198 private:
199  ScDocument& mrDoc;
200  ScAddress maPos;
201  ScCaptionPtr mxCaption;
202  tools::Rectangle maPageRect;
203  tools::Rectangle maCellRect;
204  bool mbNegPage;
205 };
206 
207 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bTailFront ) :
208  mrDoc( rDoc ),
209  maPos( rPos )
210 {
211  Initialize();
212  CreateCaption( true/*bShown*/, bTailFront );
213 }
214 
215 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, const ScCaptionPtr& xCaption ) :
216  mrDoc( rDoc ),
217  maPos( rPos ),
218  mxCaption( xCaption )
219 {
220  Initialize();
221 }
222 
223 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos ) :
224  mrDoc( rDoc ),
225  maPos( rPos )
226 {
227  Initialize();
228 }
229 
230 SdrPage* ScCaptionCreator::GetDrawPage()
231 {
232  ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
233  return pDrawLayer ? pDrawLayer->GetPage( static_cast< sal_uInt16 >( maPos.Tab() ) ) : nullptr;
234 }
235 
236 void ScCaptionCreator::FitCaptionToRect( const tools::Rectangle* pVisRect )
237 {
238  const tools::Rectangle& rVisRect = GetVisRect( pVisRect );
239 
240  // tail position
241  Point aTailPos = mxCaption->GetTailPos();
242  aTailPos.setX( ::std::clamp( aTailPos.X(), rVisRect.Left(), rVisRect.Right() ) );
243  aTailPos.setY( ::std::clamp( aTailPos.Y(), rVisRect.Top(), rVisRect.Bottom() ) );
244  mxCaption->SetTailPos( aTailPos );
245 
246  // caption rectangle
247  tools::Rectangle aCaptRect = mxCaption->GetLogicRect();
248  Point aCaptPos = aCaptRect.TopLeft();
249  // move textbox inside right border of visible area
250  aCaptPos.setX( ::std::min< tools::Long >( aCaptPos.X(), rVisRect.Right() - aCaptRect.GetWidth() ) );
251  // move textbox inside left border of visible area (this may move it outside on right side again)
252  aCaptPos.setX( ::std::max< tools::Long >( aCaptPos.X(), rVisRect.Left() ) );
253  // move textbox inside bottom border of visible area
254  aCaptPos.setY( ::std::min< tools::Long >( aCaptPos.Y(), rVisRect.Bottom() - aCaptRect.GetHeight() ) );
255  // move textbox inside top border of visible area (this may move it outside on bottom side again)
256  aCaptPos.setY( ::std::max< tools::Long >( aCaptPos.Y(), rVisRect.Top() ) );
257  // update caption
258  aCaptRect.SetPos( aCaptPos );
259  mxCaption->SetLogicRect( aCaptRect );
260 }
261 
262 void ScCaptionCreator::AutoPlaceCaption( const tools::Rectangle* pVisRect )
263 {
264  const tools::Rectangle& rVisRect = GetVisRect( pVisRect );
265 
266  // caption rectangle
267  tools::Rectangle aCaptRect = mxCaption->GetLogicRect();
268  tools::Long nWidth = aCaptRect.GetWidth();
269  tools::Long nHeight = aCaptRect.GetHeight();
270 
271  // n***Space contains available space between border of visible area and cell
272  tools::Long nLeftSpace = maCellRect.Left() - rVisRect.Left() + 1;
273  tools::Long nRightSpace = rVisRect.Right() - maCellRect.Right() + 1;
274  tools::Long nTopSpace = maCellRect.Top() - rVisRect.Top() + 1;
275  tools::Long nBottomSpace = rVisRect.Bottom() - maCellRect.Bottom() + 1;
276 
277  // nNeeded*** contains textbox dimensions plus needed distances to cell or border of visible area
278  tools::Long nNeededSpaceX = nWidth + SC_NOTECAPTION_CELLDIST;
279  tools::Long nNeededSpaceY = nHeight + SC_NOTECAPTION_CELLDIST;
280 
281  // bFitsWidth*** == true means width of textbox fits into horizontal free space of visible area
282  bool bFitsWidthLeft = nNeededSpaceX <= nLeftSpace; // text box width fits into the width left of cell
283  bool bFitsWidthRight = nNeededSpaceX <= nRightSpace; // text box width fits into the width right of cell
284  bool bFitsWidth = nWidth <= rVisRect.GetWidth(); // text box width fits into width of visible area
285 
286  // bFitsHeight*** == true means height of textbox fits into vertical free space of visible area
287  bool bFitsHeightTop = nNeededSpaceY <= nTopSpace; // text box height fits into the height above cell
288  bool bFitsHeightBottom = nNeededSpaceY <= nBottomSpace; // text box height fits into the height below cell
289  bool bFitsHeight = nHeight <= rVisRect.GetHeight(); // text box height fits into height of visible area
290 
291  // bFits*** == true means the textbox fits completely into free space of visible area
292  bool bFitsLeft = bFitsWidthLeft && bFitsHeight;
293  bool bFitsRight = bFitsWidthRight && bFitsHeight;
294  bool bFitsTop = bFitsWidth && bFitsHeightTop;
295  bool bFitsBottom = bFitsWidth && bFitsHeightBottom;
296 
297  Point aCaptPos;
298  // use left/right placement if possible, or if top/bottom placement not possible
299  if( bFitsLeft || bFitsRight || (!bFitsTop && !bFitsBottom) )
300  {
301  // prefer left in RTL sheet and right in LTR sheets
302  bool bPreferLeft = bFitsLeft && (mbNegPage || !bFitsRight);
303  bool bPreferRight = bFitsRight && (!mbNegPage || !bFitsLeft);
304  // move to left, if left is preferred, or if neither left nor right fit and there is more space to the left
305  if( bPreferLeft || (!bPreferRight && (nLeftSpace > nRightSpace)) )
306  aCaptPos.setX( maCellRect.Left() - SC_NOTECAPTION_CELLDIST - nWidth );
307  else // to right
308  aCaptPos.setX( maCellRect.Right() + SC_NOTECAPTION_CELLDIST );
309  // Y position according to top cell border
310  aCaptPos.setY( maCellRect.Top() + SC_NOTECAPTION_OFFSET_Y );
311  }
312  else // top or bottom placement
313  {
314  // X position
315  aCaptPos.setX( maCellRect.Left() + SC_NOTECAPTION_OFFSET_X );
316  // top placement, if possible
317  if( bFitsTop )
318  aCaptPos.setY( maCellRect.Top() - SC_NOTECAPTION_CELLDIST - nHeight );
319  else // bottom placement
320  aCaptPos.setY( maCellRect.Bottom() + SC_NOTECAPTION_CELLDIST );
321  }
322 
323  // update textbox position in note caption object
324  aCaptRect.SetPos( aCaptPos );
325  mxCaption->SetLogicRect( aCaptRect );
326  FitCaptionToRect( pVisRect );
327 }
328 
329 void ScCaptionCreator::UpdateCaptionPos()
330 {
331  ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
332 
333  // update caption position
334  const Point& rOldTailPos = mxCaption->GetTailPos();
335  Point aTailPos = CalcTailPos( false );
336  if( rOldTailPos != aTailPos )
337  {
338  // create drawing undo action
339  if( pDrawLayer && pDrawLayer->IsRecording() )
340  pDrawLayer->AddCalcUndo( std::make_unique<SdrUndoGeoObj>( *mxCaption ) );
341  // calculate new caption rectangle (#i98141# handle LTR<->RTL switch correctly)
342  tools::Rectangle aCaptRect = mxCaption->GetLogicRect();
343  tools::Long nDiffX = (rOldTailPos.X() >= 0) ? (aCaptRect.Left() - rOldTailPos.X()) : (rOldTailPos.X() - aCaptRect.Right());
344  if( mbNegPage ) nDiffX = -nDiffX - aCaptRect.GetWidth();
345  tools::Long nDiffY = aCaptRect.Top() - rOldTailPos.Y();
346  aCaptRect.SetPos( aTailPos + Point( nDiffX, nDiffY ) );
347  // set new tail position and caption rectangle
348  mxCaption->SetTailPos( aTailPos );
349  mxCaption->SetLogicRect( aCaptRect );
350  // fit caption into draw page
351  FitCaptionToRect();
352  }
353 
354  // update cell position in caption user data
355  ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( mxCaption.get(), maPos.Tab() );
356  if( pCaptData && (maPos != pCaptData->maStart) )
357  {
358  // create drawing undo action
359  if( pDrawLayer && pDrawLayer->IsRecording() )
360  pDrawLayer->AddCalcUndo( std::make_unique<ScUndoObjData>( mxCaption.get(), pCaptData->maStart, pCaptData->maEnd, maPos, pCaptData->maEnd ) );
361  // set new position
362  pCaptData->maStart = maPos;
363  }
364 }
365 
366 Point ScCaptionCreator::CalcTailPos( bool bTailFront )
367 {
368  // tail position
369  bool bTailLeft = bTailFront != mbNegPage;
370  Point aTailPos = bTailLeft ? maCellRect.TopLeft() : maCellRect.TopRight();
371  // move caption point 1/10 mm inside cell
372  if( bTailLeft ) aTailPos.AdjustX(10 ); else aTailPos.AdjustX( -10 );
373  aTailPos.AdjustY(10);
374  return aTailPos;
375 }
376 
377 void ScCaptionCreator::CreateCaption( bool bShown, bool bTailFront )
378 {
379  // create the caption drawing object
380  tools::Rectangle aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH, SC_NOTECAPTION_HEIGHT ) );
381  Point aTailPos = CalcTailPos( bTailFront );
382  mxCaption.reset(
383  new SdrCaptionObj(
384  *mrDoc.GetDrawLayer(), // TTTT should ret a ref?
385  aTextRect,
386  aTailPos));
387  // basic caption settings
388  ScCaptionUtil::SetBasicCaptionSettings( *mxCaption, bShown );
389 }
390 
391 void ScCaptionCreator::Initialize()
392 {
393  maCellRect = ScDrawLayer::GetCellRect( mrDoc, maPos, true );
394  mbNegPage = mrDoc.IsNegativePage( maPos.Tab() );
395  if( SdrPage* pDrawPage = GetDrawPage() )
396  {
397  maPageRect = tools::Rectangle( Point( 0, 0 ), pDrawPage->GetSize() );
398  /* #i98141# SdrPage::GetSize() returns negative width in RTL mode.
399  The call to Rectangle::Adjust() orders left/right coordinate
400  accordingly. */
401  maPageRect.Justify();
402  }
403 }
404 
406 class ScNoteCaptionCreator : public ScCaptionCreator
407 {
408 public:
410  explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData );
412  explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScCaptionPtr& xCaption, bool bShown );
413 };
414 
415 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData ) :
416  ScCaptionCreator( rDoc, rPos ) // use helper c'tor that does not create the caption yet
417 {
418  SdrPage* pDrawPage = GetDrawPage();
419  OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
420  if( !pDrawPage )
421  return;
422 
423  // create the caption drawing object
424  CreateCaption( rNoteData.mbShown, false );
425  rNoteData.mxCaption = GetCaption();
426  OSL_ENSURE( rNoteData.mxCaption, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" );
427  if( rNoteData.mxCaption )
428  {
429  // store note position in user data of caption object
430  ScCaptionUtil::SetCaptionUserData( *rNoteData.mxCaption, rPos );
431  // insert object into draw page
432  pDrawPage->InsertObject( rNoteData.mxCaption.get() );
433  }
434 }
435 
436 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScCaptionPtr& xCaption, bool bShown ) :
437  ScCaptionCreator( rDoc, rPos, xCaption )
438 {
439  SdrPage* pDrawPage = GetDrawPage();
440  OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
441  OSL_ENSURE( xCaption->getSdrPageFromSdrObject() == pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" );
442  if( pDrawPage && (xCaption->getSdrPageFromSdrObject() == pDrawPage) )
443  {
444  // store note position in user data of caption object
445  ScCaptionUtil::SetCaptionUserData( *xCaption, rPos );
446  // basic caption settings
447  ScCaptionUtil::SetBasicCaptionSettings( *xCaption, bShown );
448  // set correct tail position
449  xCaption->SetTailPos( CalcTailPos( false ) );
450  }
451 }
452 
453 } // namespace
454 
456  mpHead(nullptr), mpNext(nullptr), mpCaption(nullptr), mbNotOwner(false)
457 {
458 }
459 
461  mpHead(nullptr), mpNext(nullptr), mpCaption(p), mbNotOwner(false)
462 {
463  if (p)
464  {
465  newHead();
466  }
467 }
468 
470  mpHead(r.mpHead), mpCaption(r.mpCaption), mbNotOwner(false)
471 {
472  if (r.mpCaption)
473  {
474  assert(r.mpHead);
475  r.incRef();
476  // Insert into list.
477  mpNext = r.mpNext;
478  r.mpNext = this;
479  }
480  else
481  {
482  assert(!r.mpHead);
483  mpNext = nullptr;
484  }
485 }
486 
488  : mpHead(r.mpHead), mpNext(r.mpNext), mpCaption(r.mpCaption), mbNotOwner(false)
489 {
490  r.replaceInList( this );
491  r.mpCaption = nullptr;
492  r.mbNotOwner = false;
493 }
494 
496 {
497  assert(this != &r);
498 
499  mpHead = r.mpHead;
500  mpNext = r.mpNext;
501  mpCaption = r.mpCaption;
502  mbNotOwner = r.mbNotOwner;
503 
504  r.replaceInList( this );
505  r.mpCaption = nullptr;
506  r.mbNotOwner = false;
507 
508  return *this;
509 }
510 
512 {
513  if (this == &r)
514  return *this;
515 
516  if (mpCaption == r.mpCaption)
517  {
518  // Two lists for the same caption is bad.
519  assert(!mpCaption || mpHead == r.mpHead);
520  assert(!mpCaption); // assigning same caption pointer within same list is weird
521  // Nullptr captions are not inserted to the list, so nothing to do here
522  // if both are.
523  return *this;
524  }
525 
526  // Let's find some weird usage.
527  // Assigning without head doesn't make sense unless it is a nullptr caption.
528  assert(r.mpHead || !r.mpCaption);
529  // A nullptr caption must not be in a list and thus not have a head.
530  assert(!r.mpHead || r.mpCaption);
531  // Same captions were caught above, so here different heads must be present.
532  assert(r.mpHead != mpHead);
533 
534  r.incRef();
536  removeFromList();
537 
538  mpCaption = r.mpCaption;
540  // That head is this' master.
541  mpHead = r.mpHead;
542  // Insert into list.
543  mpNext = r.mpNext;
544  r.mpNext = this;
545 
546  return *this;
547 }
548 
550 {
551  mbNotOwner = true;
552 }
553 
555  mpFirst(p), mnRefs(1)
556 {
557 }
558 
560 {
561  assert(!mpHead);
562  mpHead = new Head(this);
563 }
564 
566 {
567  if (!mpHead && !mpNext)
568  return;
569 
570  assert(mpHead);
571  assert(mpCaption == pNew->mpCaption);
572 
573  ScCaptionPtr* pThat = mpHead->mpFirst;
574  while (pThat && pThat != this && pThat->mpNext != this)
575  {
576  pThat = pThat->mpNext;
577  }
578  if (pThat && pThat != this)
579  {
580  assert(pThat->mpNext == this);
581  pThat->mpNext = pNew;
582  }
583  pNew->mpNext = mpNext;
584  if (mpHead->mpFirst == this)
585  mpHead->mpFirst = pNew;
586 
587  mpHead = nullptr;
588  mpNext = nullptr;
589 }
590 
592 {
593  if (!mpHead && !mpNext && !mpCaption)
594  return;
595 
596 #if OSL_DEBUG_LEVEL > 0
597  oslInterlockedCount nCount = 0;
598 #endif
599  ScCaptionPtr* pThat = (mpHead ? mpHead->mpFirst : nullptr);
600  while (pThat && pThat != this && pThat->mpNext != this)
601  {
602  // Use the walk to check consistency on the fly.
603  assert(pThat->mpHead == mpHead); // all belong to the same
604  assert(pThat->mpHead || !pThat->mpNext); // next without head is bad
605  assert(pThat->mpCaption == mpCaption);
606  pThat = pThat->mpNext;
607 #if OSL_DEBUG_LEVEL > 0
608  ++nCount;
609 #endif
610  }
611  assert(pThat || !mpHead); // not found only if this was standalone
612  if (pThat)
613  {
614  if (pThat != this)
615  {
616 #if OSL_DEBUG_LEVEL > 0
617  // The while loop above was not executed, and for this
618  // (pThat->mpNext) the loop below won't either.
619  ++nCount;
620 #endif
621  pThat->mpNext = mpNext;
622  }
623 #if OSL_DEBUG_LEVEL > 0
624  do
625  {
626  assert(pThat->mpHead == mpHead); // all belong to the same
627  assert(pThat->mpHead || !pThat->mpNext); // next without head is bad
628  assert(pThat->mpCaption == mpCaption);
629  ++nCount;
630  }
631  while ((pThat = pThat->mpNext) != nullptr);
632 #endif
633  }
634 #if OSL_DEBUG_LEVEL > 0
635  // If part of a list then refs were already decremented.
636  assert(nCount == (mpHead ? mpHead->mnRefs + 1 : 0));
637 #endif
638  if (mpHead && mpHead->mpFirst == this)
639  {
640  if (mpNext)
641  mpHead->mpFirst = mpNext;
642  else
643  {
644  // The only one destroys also head.
645  assert(mpHead->mnRefs == 0); // cough
646  delete mpHead; // DEAD now
647  }
648  }
649  mpHead = nullptr;
650  mpNext = nullptr;
651 }
652 
654 {
655  assert(!p || p != mpCaption);
656 #if OSL_DEBUG_LEVEL > 0
657  if (p)
658  {
659  // Check if we end up with a duplicated management in this list.
660  ScCaptionPtr* pThat = (mpHead ? mpHead->mpFirst : nullptr);
661  while (pThat)
662  {
663  assert(pThat->mpCaption != p);
664  pThat = pThat->mpNext;
665  }
666  }
667 #endif
669  removeFromList();
670  mpCaption = p;
671  mbNotOwner = false;
672  if (p)
673  {
674  newHead();
675  }
676 }
677 
679 {
681  removeFromList();
682 }
683 
684 oslInterlockedCount ScCaptionPtr::getRefs() const
685 {
686  return mpHead ? mpHead->mnRefs : 0;
687 }
688 
690 {
691  if (mpHead)
692  osl_atomic_increment(&mpHead->mnRefs);
693 }
694 
696 {
697  return mpHead && mpHead->mnRefs > 0 && !osl_atomic_decrement(&mpHead->mnRefs);
698 }
699 
701 {
702  if (!decRef())
703  return;
704 
705  assert(mpHead->mpFirst == this); // this must be one and only one
706  assert(!mpNext); // this must be one and only one
707  assert(mpCaption);
708 
709 #if 0
710  // Quick workaround for when there are still cases where the caption
711  // pointer is dangling
712  mpCaption = nullptr;
713  mbNotOwner = false;
714 #else
715  // Destroying Draw Undo and some other delete the SdrObject, don't
716  // attempt that twice.
717  if (mbNotOwner)
718  {
719  mpCaption = nullptr;
720  mbNotOwner = false;
721  }
722  else
723  {
724  removeFromDrawPageAndFree( true ); // ignoring Undo
725  if (mpCaption)
726  {
727  // There's no draw page associated so removeFromDrawPageAndFree()
728  // didn't do anything, but still we want to delete the caption
729  // object. release()/dissolve() also resets mpCaption.
730  SdrObject* pObj = release();
731  SdrObject::Free( pObj );
732  }
733  }
734 #endif
735  delete mpHead;
736  mpHead = nullptr;
737 }
738 
740 {
741  assert(mpHead && mpCaption);
742 
743  rDrawPage.InsertObject( mpCaption );
744 }
745 
747 {
748  assert(mpHead && mpCaption);
749  SdrObject* pObj = rDrawPage.RemoveObject( mpCaption->GetOrdNum() );
750  assert(pObj == mpCaption); (void)pObj;
751 }
752 
754 {
755  assert(mpHead && mpCaption);
757  SAL_WARN_IF( !pDrawPage, "sc.core", "ScCaptionPtr::removeFromDrawPageAndFree - object without drawing page");
758  if (!pDrawPage)
759  return;
760 
761  pDrawPage->RecalcObjOrdNums();
762  bool bRecording = false;
763  if(!bIgnoreUndo)
764  {
765  ScDrawLayer* pDrawLayer(dynamic_cast< ScDrawLayer* >(&mpCaption->getSdrModelFromSdrObject()));
766  SAL_WARN_IF( !pDrawLayer, "sc.core", "ScCaptionPtr::removeFromDrawPageAndFree - object without drawing layer");
767  // create drawing undo action (before removing the object to have valid draw page in undo action)
768  bRecording = (pDrawLayer && pDrawLayer->IsRecording());
769  if (bRecording)
770  pDrawLayer->AddCalcUndo( std::make_unique<SdrUndoDelObj>( *mpCaption ));
771  }
772  // remove the object from the drawing page, delete if undo is disabled
773  removeFromDrawPage( *pDrawPage );
774  // If called from outside mnRefs must be 1 to delete. If called from
775  // decRefAndDestroy() mnRefs is already 0.
776  if (!bRecording && getRefs() <= 1)
777  {
778  SdrObject* pObj = release();
779  SdrObject::Free( pObj );
780  }
781 }
782 
784 {
785  SdrCaptionObj* pTmp = mpCaption;
786  dissolve();
787  return pTmp;
788 }
789 
791 {
792  decRef();
793  removeFromList();
794  mpCaption = nullptr;
795  mbNotOwner = false;
796 }
797 
799 {
800  ScCaptionPtr::Head* pHead = mpHead;
801  ScCaptionPtr* pThat = (mpHead ? mpHead->mpFirst : this);
802  while (pThat)
803  {
804  assert(!pThat->mpNext || pThat->mpHead); // next without head is bad
805  assert(pThat->mpHead == pHead); // same head required within one list
806  ScCaptionPtr* p = pThat->mpNext;
807  pThat->clear();
808  pThat = p;
809  }
810  assert(!mpHead && !mpNext && !mpCaption); // should had been cleared during list walk
811  delete pHead;
812 }
813 
815 {
816  mpHead = nullptr;
817  mpNext = nullptr;
818  mpCaption = nullptr;
819  mbNotOwner = false;
820 }
821 
823 {
824  std::optional< SfxItemSet > moItemSet;
826  OUString maSimpleText;
830 
831  explicit ScCaptionInitData();
832 };
833 
835  mbDefaultPosSize( true )
836 {
837 }
838 
839 ScNoteData::ScNoteData( bool bShown ) :
840  mbShown( bShown )
841 {
842 }
843 
844 sal_uInt32 ScPostIt::mnLastPostItId = 1;
845 
846 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, sal_uInt32 nPostItId ) :
847  mrDoc( rDoc ),
848  maNoteData( false )
849 {
850  mnPostItId = nPostItId == 0 ? mnLastPostItId++ : nPostItId;
851  AutoStamp();
852  CreateCaption( rPos );
853 }
854 
855 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNote, sal_uInt32 nPostItId ) :
856  mrDoc( rDoc ),
857  maNoteData( rNote.maNoteData )
858 {
859  mnPostItId = nPostItId == 0 ? mnLastPostItId++ : nPostItId;
860  maNoteData.mxCaption.reset(nullptr);
861  CreateCaption( rPos, rNote.maNoteData.mxCaption.get() );
862 }
863 
864 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScNoteData& rNoteData, bool bAlwaysCreateCaption, sal_uInt32 nPostItId ) :
865  mrDoc( rDoc ),
866  maNoteData( rNoteData )
867 {
868  mnPostItId = nPostItId == 0 ? mnLastPostItId++ : nPostItId;
869  if( bAlwaysCreateCaption || maNoteData.mbShown )
871 }
872 
874 {
875  RemoveCaption();
876 }
877 
878 std::unique_ptr<ScPostIt> ScPostIt::Clone( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, bool bCloneCaption ) const
879 {
880  CreateCaptionFromInitData( rOwnPos );
881  sal_uInt32 nPostItId = comphelper::LibreOfficeKit::isActive() ? 0 : mnPostItId;
882  return bCloneCaption ? std::make_unique<ScPostIt>( rDestDoc, rDestPos, *this, nPostItId ) : std::make_unique<ScPostIt>( rDestDoc, rDestPos, maNoteData, false, mnPostItId );
883 }
884 
885 void ScPostIt::SetDate( const OUString& rDate )
886 {
887  maNoteData.maDate = rDate;
888 }
889 
890 void ScPostIt::SetAuthor( const OUString& rAuthor )
891 {
892  maNoteData.maAuthor = rAuthor;
893 }
894 
896 {
898  maNoteData.maAuthor = SvtUserOptions().GetID();
899 }
900 
902 {
903  if( maNoteData.mxCaption )
905  if( maNoteData.mxInitData && maNoteData.mxInitData->mxOutlinerObj )
906  return &*maNoteData.mxInitData->mxOutlinerObj;
907  return nullptr;
908 }
909 
911 {
912  const OutlinerParaObject* pOPO = GetOutlinerObject();
913  return pOPO ? &pOPO->GetTextObject() : nullptr;
914 }
915 
916 OUString ScPostIt::GetText() const
917 {
918  if( const EditTextObject* pEditObj = GetEditTextObject() )
919  {
920  OUStringBuffer aBuffer;
921  ScNoteEditEngine& rEngine = mrDoc.GetNoteEngine();
922  rEngine.SetTextCurrentDefaults(*pEditObj);
923  sal_Int32 nParaCount = rEngine.GetParagraphCount();
924  for( sal_Int32 nPara = 0; nPara < nParaCount; ++nPara )
925  {
926  if( nPara > 0 )
927  aBuffer.append( '\n' );
928  aBuffer.append(rEngine.GetText(nPara));
929  }
930  return aBuffer.makeStringAndClear();
931  }
932  if( maNoteData.mxInitData )
933  return maNoteData.mxInitData->maSimpleText;
934  return OUString();
935 }
936 
938 {
939  if( const EditTextObject* pEditObj = GetEditTextObject() )
940  return pEditObj->GetParagraphCount() > 1;
941  if( maNoteData.mxInitData )
942  return maNoteData.mxInitData->maSimpleText.indexOf( '\n' ) >= 0;
943  return false;
944 }
945 
946 void ScPostIt::SetText( const ScAddress& rPos, const OUString& rText )
947 {
949  if( maNoteData.mxCaption )
950  maNoteData.mxCaption->SetText( rText );
951 }
952 
954 {
956  return maNoteData.mxCaption.get();
957 }
958 
959 void ScPostIt::ForgetCaption( bool bPreserveData )
960 {
961  if (bPreserveData)
962  {
963  // Used in clipboard when the originating document is destructed to be
964  // able to paste into another document. Caption size and relative
965  // position are not preserved but default created when pasted. Also the
966  // MergedItemSet can not be carried over or it had to be adapted to
967  // defaults and pool. At least preserve the text and outline object if
968  // possible.
969  ScCaptionInitData* pInitData = new ScCaptionInitData;
970  const OutlinerParaObject* pOPO = GetOutlinerObject();
971  if (pOPO)
972  pInitData->mxOutlinerObj = *pOPO;
973  pInitData->maSimpleText = GetText();
974 
975  maNoteData.mxInitData.reset(pInitData);
977  }
978  else
979  {
980  /* This function is used in undo actions to give up the responsibility for
981  the caption object which is handled by separate drawing undo actions. */
983  maNoteData.mxInitData.reset();
984  }
985 }
986 
987 void ScPostIt::ShowCaption( const ScAddress& rPos, bool bShow )
988 {
990  // no separate drawing undo needed, handled completely inside ScUndoShowHideNote
991  maNoteData.mbShown = bShow;
992  if( maNoteData.mxCaption )
993  ScCaptionUtil::SetCaptionLayer( *maNoteData.mxCaption, bShow );
994 }
995 
996 void ScPostIt::ShowCaptionTemp( const ScAddress& rPos, bool bShow )
997 {
999  if( maNoteData.mxCaption )
1000  ScCaptionUtil::SetCaptionLayer( *maNoteData.mxCaption, maNoteData.mbShown || bShow );
1001 }
1002 
1004 {
1005  CreateCaptionFromInitData( rPos );
1006  if( maNoteData.mxCaption )
1007  {
1008  ScCaptionCreator aCreator( mrDoc, rPos, maNoteData.mxCaption );
1009  aCreator.UpdateCaptionPos();
1010  }
1011 }
1012 
1013 // private --------------------------------------------------------------------
1014 
1016 {
1017  // Captions are not created in Undo documents and only rarely in Clipboard,
1018  // but otherwise we need caption or initial data.
1020  if( !maNoteData.mxInitData )
1021  return;
1022 
1023 
1024  /* This function is called from ScPostIt::Clone() when copying cells
1025  to the clipboard/undo document, and when copying cells from the
1026  clipboard/undo document. The former should always be called first,
1027  so if called in a clipboard/undo document, the caption should have
1028  been created already. However, for clipboard in case the
1029  originating document was destructed a new caption has to be
1030  created. */
1031  OSL_ENSURE( !mrDoc.IsUndo() && (!mrDoc.IsClipboard() || !maNoteData.mxCaption),
1032  "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" );
1033 
1034  // going to forget the initial caption data struct when this method returns
1035  auto xInitData = std::move(maNoteData.mxInitData);
1036 
1037  /* #i104915# Never try to create notes in Undo document, leads to
1038  crash due to missing document members (e.g. row height array). */
1039  if( maNoteData.mxCaption || mrDoc.IsUndo() )
1040  return;
1041 
1042  if (mrDoc.IsClipboard())
1043  mrDoc.InitDrawLayer(); // ensure there is a drawing layer
1044 
1045  // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
1046  ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
1047  if( !maNoteData.mxCaption )
1048  return;
1049 
1050  // Prevent triple change broadcasts of the same object.
1051  bool bWasLocked = maNoteData.mxCaption->getSdrModelFromSdrObject().isLocked();
1053 
1054  // transfer ownership of outliner object to caption, or set simple text
1055  OSL_ENSURE( xInitData->mxOutlinerObj || !xInitData->maSimpleText.isEmpty(),
1056  "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" );
1057  if (xInitData->mxOutlinerObj)
1058  maNoteData.mxCaption->SetOutlinerParaObject( std::move(xInitData->mxOutlinerObj) );
1059  else
1060  maNoteData.mxCaption->SetText( xInitData->maSimpleText );
1061 
1062  // copy all items or set default items; reset shadow items
1063  ScCaptionUtil::SetDefaultItems( *maNoteData.mxCaption, mrDoc, xInitData->moItemSet ? &*xInitData->moItemSet : nullptr );
1064 
1065  // set position and size of the caption object
1066  if( xInitData->mbDefaultPosSize )
1067  {
1068  // set other items and fit caption size to text
1069  maNoteData.mxCaption->SetMergedItem( makeSdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
1070  maNoteData.mxCaption->SetMergedItem( makeSdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) );
1072  aCreator.AutoPlaceCaption();
1073  }
1074  else
1075  {
1076  tools::Rectangle aCellRect = ScDrawLayer::GetCellRect( mrDoc, rPos, true );
1077  bool bNegPage = mrDoc.IsNegativePage( rPos.Tab() );
1078  tools::Long nPosX = bNegPage ? (aCellRect.Left() - xInitData->maCaptionOffset.X()) : (aCellRect.Right() + xInitData->maCaptionOffset.X());
1079  tools::Long nPosY = aCellRect.Top() + xInitData->maCaptionOffset.Y();
1080  tools::Rectangle aCaptRect( Point( nPosX, nPosY ), xInitData->maCaptionSize );
1081  maNoteData.mxCaption->SetLogicRect( aCaptRect );
1082  aCreator.FitCaptionToRect();
1083  }
1084 
1085  // End prevent triple change broadcasts of the same object.
1088 }
1089 
1090 void ScPostIt::CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption )
1091 {
1092  OSL_ENSURE( !maNoteData.mxCaption, "ScPostIt::CreateCaption - unexpected caption object found" );
1093  maNoteData.mxCaption.reset(nullptr);
1094 
1095  /* #i104915# Never try to create notes in Undo document, leads to
1096  crash due to missing document members (e.g. row height array). */
1097  OSL_ENSURE( !mrDoc.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" );
1098  if( mrDoc.IsUndo() )
1099  return;
1100 
1101  // drawing layer may be missing, if a note is copied into a clipboard document
1102  if( mrDoc.IsClipboard() )
1103  mrDoc.InitDrawLayer();
1104 
1105  // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
1106  ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
1107  if( !maNoteData.mxCaption )
1108  return;
1109 
1110  // clone settings of passed caption
1111  if( pCaption )
1112  {
1113  // copy edit text object (object must be inserted into page already)
1114  if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
1116  // copy formatting items (after text has been copied to apply font formatting)
1118  // move textbox position relative to new cell, copy textbox size
1119  tools::Rectangle aCaptRect = pCaption->GetLogicRect();
1120  Point aDist = maNoteData.mxCaption->GetTailPos() - pCaption->GetTailPos();
1121  aCaptRect.Move( aDist.X(), aDist.Y() );
1122  maNoteData.mxCaption->SetLogicRect( aCaptRect );
1123  aCreator.FitCaptionToRect();
1124  }
1125  else
1126  {
1127  // set default formatting and default position
1128  ScCaptionUtil::SetDefaultItems( *maNoteData.mxCaption, mrDoc, nullptr );
1129  aCreator.AutoPlaceCaption();
1130  }
1131 
1132  // create undo action
1133  if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() )
1134  if( pDrawLayer->IsRecording() )
1135  pDrawLayer->AddCalcUndo( std::make_unique<SdrUndoNewObj>( *maNoteData.mxCaption ) );
1136 }
1137 
1139 {
1140  if (!maNoteData.mxCaption)
1141  return;
1142 
1143  /* Remove caption object only, if this note is its owner (e.g. notes in
1144  undo documents refer to captions in original document, do not remove
1145  them from drawing layer here). */
1146  // TTTT maybe no longer needed - can that still happen?
1147  ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
1148  if (pDrawLayer == &maNoteData.mxCaption->getSdrModelFromSdrObject())
1150 
1151  SAL_INFO("sc.core","ScPostIt::RemoveCaption - refs: " << maNoteData.mxCaption.getRefs() <<
1152  " IsUndo: " << mrDoc.IsUndo() << " IsClip: " << mrDoc.IsClipboard() <<
1153  " Dtor: " << mrDoc.IsInDtorClear());
1154 
1155  // Forget the caption object if removeFromDrawPageAndFree() did not free it.
1156  if (maNoteData.mxCaption)
1157  {
1158  SAL_INFO("sc.core","ScPostIt::RemoveCaption - forgetting one ref");
1160  }
1161 }
1162 
1164  ScDocument& rDoc, const ScAddress& rPos, SdrPage& rDrawPage,
1165  std::u16string_view rUserText, const tools::Rectangle& rVisRect, bool bTailFront )
1166 {
1167  OUStringBuffer aBuffer( rUserText );
1168  // add plain text of invisible (!) cell note (no formatting etc.)
1169  SdrCaptionObj* pNoteCaption = nullptr;
1170  const ScPostIt* pNote = rDoc.GetNote( rPos );
1171  if( pNote && !pNote->IsCaptionShown() )
1172  {
1173  if( !aBuffer.isEmpty() )
1174  aBuffer.append( "\n--------\n" + pNote->GetText() );
1175  pNoteCaption = pNote->GetOrCreateCaption( rPos );
1176  }
1177 
1178  // create a caption if any text exists
1179  if( !pNoteCaption && aBuffer.isEmpty() )
1180  return ScCaptionPtr();
1181 
1182  // prepare visible rectangle (add default distance to all borders)
1183  tools::Rectangle aVisRect(
1184  rVisRect.Left() + SC_NOTECAPTION_BORDERDIST_TEMP,
1185  rVisRect.Top() + SC_NOTECAPTION_BORDERDIST_TEMP,
1186  rVisRect.Right() - SC_NOTECAPTION_BORDERDIST_TEMP,
1187  rVisRect.Bottom() - SC_NOTECAPTION_BORDERDIST_TEMP );
1188 
1189  // create the caption object
1190  ScCaptionCreator aCreator( rDoc, rPos, bTailFront );
1191 
1192  // insert caption into page (needed to set caption text)
1193  aCreator.GetCaption().insertToDrawPage( rDrawPage );
1194 
1195  SdrCaptionObj* pCaption = aCreator.GetCaption().get(); // just for ease of use
1196 
1197  // clone the edit text object, unless user text is present, then set this text
1198  if( pNoteCaption && rUserText.empty() )
1199  {
1200  if( OutlinerParaObject* pOPO = pNoteCaption->GetOutlinerParaObject() )
1201  pCaption->SetOutlinerParaObject( *pOPO );
1202  // set formatting (must be done after setting text) and resize the box to fit the text
1203  pCaption->SetMergedItemSetAndBroadcast( pNoteCaption->GetMergedItemSet() );
1204  tools::Rectangle aCaptRect( pCaption->GetLogicRect().TopLeft(), pNoteCaption->GetLogicRect().GetSize() );
1205  pCaption->SetLogicRect( aCaptRect );
1206  }
1207  else
1208  {
1209  // if pNoteCaption is null, then aBuffer contains some text
1210  pCaption->SetText( aBuffer.makeStringAndClear() );
1211  ScCaptionUtil::SetDefaultItems( *pCaption, rDoc, nullptr );
1212  // adjust caption size to text size
1213  tools::Long nMaxWidth = ::std::min< tools::Long >( aVisRect.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP );
1214  pCaption->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
1215  pCaption->SetMergedItem( makeSdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
1216  pCaption->SetMergedItem( makeSdrTextMaxFrameWidthItem( nMaxWidth ) );
1217  pCaption->SetMergedItem( makeSdrTextAutoGrowHeightItem( true ) );
1218  pCaption->AdjustTextFrameWidthAndHeight();
1219  }
1220 
1221  // move caption into visible area
1222  aCreator.AutoPlaceCaption( &aVisRect );
1223 
1224  // XXX Note it is already inserted to the draw page.
1225  return aCreator.GetCaption();
1226 }
1227 
1229  ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj* pCaption )
1230 {
1231  ScNoteData aNoteData( true/*bShown*/ );
1232  aNoteData.mxCaption.reset( pCaption );
1233  ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, false );
1234  pNote->AutoStamp();
1235 
1236  rDoc.SetNote(rPos, std::unique_ptr<ScPostIt>(pNote));
1237 
1238  // ScNoteCaptionCreator c'tor updates the caption object to be part of a note
1239  ScNoteCaptionCreator aCreator( rDoc, rPos, aNoteData.mxCaption, true/*bShown*/ );
1240 
1241  return pNote;
1242 }
1243 
1245  ScDocument& rDoc, const ScAddress& rPos, SfxItemSet&& rItemSet,
1246  const OutlinerParaObject& rOutlinerObj, const tools::Rectangle& rCaptionRect,
1247  bool bShown )
1248 {
1249  ScNoteData aNoteData( bShown );
1250  aNoteData.mxInitData = std::make_shared<ScCaptionInitData>();
1251  ScCaptionInitData& rInitData = *aNoteData.mxInitData;
1252  rInitData.moItemSet.emplace(std::move(rItemSet));
1253  rInitData.mxOutlinerObj = rOutlinerObj;
1254 
1255  // convert absolute caption position to relative position
1256  rInitData.mbDefaultPosSize = rCaptionRect.IsEmpty();
1257  if( !rInitData.mbDefaultPosSize )
1258  {
1259  tools::Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, rPos, true );
1260  bool bNegPage = rDoc.IsNegativePage( rPos.Tab() );
1261  rInitData.maCaptionOffset.setX( bNegPage ? (aCellRect.Left() - rCaptionRect.Right()) : (rCaptionRect.Left() - aCellRect.Right()) );
1262  rInitData.maCaptionOffset.setY( rCaptionRect.Top() - aCellRect.Top() );
1263  rInitData.maCaptionSize = rCaptionRect.GetSize();
1264  }
1265 
1266  /* Create the note and insert it into the document. If the note is
1267  visible, the caption object will be created automatically. */
1268  ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, /*bAlwaysCreateCaption*/false, 0/*nPostItId*/ );
1269  pNote->AutoStamp();
1270 
1271  rDoc.SetNote(rPos, std::unique_ptr<ScPostIt>(pNote));
1272 
1273  return pNote;
1274 }
1275 
1277  ScDocument& rDoc, const ScAddress& rPos, const OUString& rNoteText,
1278  bool bShown, bool bAlwaysCreateCaption, sal_uInt32 nPostItId )
1279 {
1280  ScPostIt* pNote = nullptr;
1281  if( !rNoteText.isEmpty() )
1282  {
1283  ScNoteData aNoteData( bShown );
1284  aNoteData.mxInitData = std::make_shared<ScCaptionInitData>();
1285  ScCaptionInitData& rInitData = *aNoteData.mxInitData;
1286  rInitData.maSimpleText = rNoteText;
1287  rInitData.mbDefaultPosSize = true;
1288 
1289  /* Create the note and insert it into the document. If the note is
1290  visible, the caption object will be created automatically. */
1291  pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption, nPostItId );
1292  pNote->AutoStamp();
1293  //insert takes ownership
1294  rDoc.SetNote(rPos, std::unique_ptr<ScPostIt>(pNote));
1295  }
1296  return pNote;
1297 }
1298 
1299 namespace sc {
1300 
1301 NoteEntry::NoteEntry( const ScAddress& rPos, const ScPostIt* pNote ) :
1302  maPos(rPos), mpNote(pNote) {}
1303 
1304 }
1305 
1306 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetPos(const Point &rPoint)
void SetAuthor(const OUString &rAuthor)
Sets a new author date for this note.
Definition: postit.cxx:890
void SetSpecialTextBoxShadow()
SdrMetricItem makeSdrTextUpperDistItem(tools::Long mnHeight)
OUString GetText(LineEnd eEnd=LINEEND_LF) const
static ScCaptionPtr CreateTempCaption(ScDocument &rDoc, const ScAddress &rPos, SdrPage &rDrawPage, std::u16string_view rUserText, const tools::Rectangle &rVisRect, bool bTailFront)
Creates and returns a caption object for a temporary caption.
Definition: postit.cxx:1163
ScCaptionInitDataRef mxInitData
Author of the note.
Definition: postit.hxx:150
SdrMetricItem makeSdrShadowYDistItem(tools::Long nDist)
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
void SetText(const ScAddress &rPos, const OUString &rText)
Changes the caption text of this note.
Definition: postit.cxx:946
constexpr TypedWhichId< ScPatternAttr > ATTR_PATTERN(156)
void decRefAndDestroy()
Definition: postit.cxx:700
void ShowCaption(const ScAddress &rPos, bool bShow)
Shows or hides the note caption object.
Definition: postit.cxx:987
SC_DLLPUBLIC bool IsNegativePage(SCTAB nTab) const
Definition: document.cxx:997
void SetDate(const OUString &rDate)
Sets a new creation date for this note.
Definition: postit.cxx:885
OUString maSimpleText
Text object with all text portion formatting.
Definition: postit.cxx:826
void ForgetCaption(bool bPreserveData=false)
Forgets the pointer to the note caption object.
Definition: postit.cxx:959
constexpr tools::Long Left() const
bool mbNotOwner
whether this caption object is owned by something else, e.g. held in Undo
Definition: postit.hxx:108
oslInterlockedCount mnRefs
use count
Definition: postit.hxx:99
void SetTailPos(const Point &rPos)
long Long
ScCaptionPtr * mpNext
next in list
Definition: postit.hxx:106
static ScDrawObjData * GetObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2602
virtual const tools::Rectangle & GetLogicRect() const override
bool IsUndo() const
Definition: document.hxx:1589
void RecalcObjOrdNums()
const OutlinerParaObject * GetOutlinerObject() const
Returns the pointer to the current outliner object, or null.
Definition: postit.cxx:901
void AutoStamp()
Sets date and author from system settings.
Definition: postit.cxx:895
std::optional< SfxItemSet > moItemSet
Definition: postit.cxx:824
static tools::Rectangle GetCellRect(const ScDocument &rDoc, const ScAddress &rPos, bool bMergedCell)
Returns the rectangle for the passed cell address in 1/100 mm.
Definition: drwlayer.cxx:2107
void removeFromDrawPage(SdrPage &rDrawPage)
Remove from draw page.
Definition: postit.cxx:746
SdrMetricItem makeSdrTextRightDistItem(tools::Long mnHeight)
SdrMetricItem makeSdrTextLowerDistItem(tools::Long mnHeight)
static void Free(SdrObject *&_rpObject)
void forget()
Forget the SdrCaptionObj pointer in this one instance.
Definition: postit.cxx:790
virtual void InsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE)
ScAddress maStart
Definition: userdat.hxx:36
void SetOutlinerParaObject(std::optional< OutlinerParaObject > pTextObject)
ScPostIt(ScDocument &rDoc, const ScAddress &rPos, sal_uInt32 nPostItId=0)
Creates an empty note and its caption object and places it according to the passed cell position...
Definition: postit.cxx:846
SC_DLLPUBLIC ScNoteEditEngine & GetNoteEngine()
Definition: documen2.cxx:489
SdrOnOffItem makeSdrTextAutoGrowHeightItem(bool bAuto)
void RemoveCaption()
Removes the caption object from the drawing layer, if this note is its owner.
Definition: postit.cxx:1138
SC_DLLPUBLIC ScDocumentPool * GetPool()
Definition: document.cxx:6156
~ScPostIt()
Removes the caption object from drawing layer, if this note is its owner.
Definition: postit.cxx:873
void SetFixedTail()
static SC_DLLPUBLIC const LocaleDataWrapper & getLocaleData()
Definition: global.cxx:1015
SC_DLLPUBLIC ScPostIt * GetNote(const ScAddress &rPos)
Definition: document.cxx:6716
SdrMetricItem makeSdrTextMinFrameWidthItem(tools::Long mnWidth)
SdrMetricItem makeSdrTextMaxFrameWidthItem(tools::Long mnWidth)
SdrPage * getSdrPageFromSdrObject() const
EdgeEntry * mpNext
Additional class containing cell annotation data.
Definition: postit.hxx:160
void insertToDrawPage(SdrPage &rDrawPage)
Insert to draw page.
Definition: postit.cxx:739
int nCount
Size maCaptionSize
Caption position relative to cell corner.
Definition: postit.cxx:828
bool isLocked() const
static ScPostIt * CreateNoteFromCaption(ScDocument &rDoc, const ScAddress &rPos, SdrCaptionObj *pCaption)
Creates a cell note using the passed caption drawing object.
Definition: postit.cxx:1228
constexpr tools::Long GetWidth() const
void SetMergedItemSet(const SfxItemSet &rSet, bool bClearAllItems=false)
SCTAB Tab() const
Definition: address.hxx:283
void setNotOwner()
Flag that this instance is in Undo, so drawing layer owns it.
Definition: postit.cxx:549
SdrOnOffItem makeSdrTextAutoGrowWidthItem(bool bAuto)
ScNoteData maNoteData
Parent document containing the note.
Definition: postit.hxx:276
NoteEntry(const ScAddress &rPos, const ScPostIt *pNote)
Definition: postit.cxx:1301
static ScPostIt * CreateNoteFromObjectData(ScDocument &rDoc, const ScAddress &rPos, SfxItemSet &&oItemSet, const OutlinerParaObject &rOutlinerObj, const tools::Rectangle &rCaptionRect, bool bShown)
Creates a cell note based on the passed caption object data.
Definition: postit.cxx:1244
constexpr bool IsEmpty() const
void ShowCaptionTemp(const ScAddress &rPos, bool bShow=true)
Shows or hides the caption temporarily (does not change internal visibility state).
Definition: postit.cxx:996
bool mbShown
Drawing object representing the cell note.
Definition: postit.hxx:152
bool IsClipboard() const
Definition: document.hxx:1590
void replaceInList(ScCaptionPtr *pNew) noexcept
Replace this instance with pNew in a list, if any.
Definition: postit.cxx:565
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1082
virtual void SetLayer(SdrLayerID nLayer)
const EditTextObject & GetTextObject() const
Point maCaptionOffset
Simple text without formatting.
Definition: postit.cxx:827
SdrCaptionObj * mpCaption
the caption object, managed by head master
Definition: postit.hxx:107
SC_DLLPUBLIC void InitDrawLayer(SfxObjectShell *pDocShell=nullptr)
Definition: documen9.cxx:98
void SetTextCurrentDefaults(const EditTextObject &rTextObject)
SetText and apply defaults already set.
Definition: editutil.cxx:616
virtual bool AdjustTextFrameWidthAndHeight(tools::Rectangle &rR, bool bHgt=true, bool bWdt=true) const
bool mbDefaultPosSize
Size of the caption object.
Definition: postit.cxx:829
static sal_uInt32 mnLastPostItId
Definition: postit.hxx:163
static ScDrawObjData * GetNoteCaptionData(SdrObject *pObj, SCTAB nTab)
Returns the object data, if the passed object is a cell note caption.
Definition: drwlayer.cxx:2635
std::unique_ptr< ScPostIt > Clone(const ScAddress &rOwnPos, ScDocument &rDestDoc, const ScAddress &rDestPos, bool bCloneCaption) const
Clones this note and its caption object, if specified.
Definition: postit.cxx:878
ScCaptionPtr * mpFirst
first in list
Definition: postit.hxx:98
void BroadcastObjectChange() const
CAUTION! The following defines must be in the same namespace as the respective type.
const SdrPage * GetPage(sal_uInt16 nPgNum) const
void SetText(const OUString &rStr)
constexpr tools::Long Right() const
void SetMergedItemSetAndBroadcast(const SfxItemSet &rSet, bool bClearAllItems=false)
OUString GetText() const
Returns the caption text of this note.
Definition: postit.cxx:916
SdrModel & getSdrModelFromSdrObject() const
sal_uInt32 GetOrdNum() const
void SetNote(const ScAddress &rPos, std::unique_ptr< ScPostIt > pNote)
Definition: document.cxx:6730
constexpr tools::Long Top() const
Head * mpHead
points to the "master" entry
Definition: postit.hxx:105
void AddCalcUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: drwlayer.cxx:1415
void removeFromList()
Remove from current list and close gap.
Definition: postit.cxx:591
SdrCaptionObj * GetOrCreateCaption(const ScAddress &rPos) const
Returns the caption object of this note.
Definition: postit.cxx:953
void clear()
Just clear everything, while dissolving the list.
Definition: postit.cxx:814
virtual void SetLogicRect(const tools::Rectangle &rRect)
void SetMergedItem(const SfxPoolItem &rItem)
std::optional< OutlinerParaObject > mxOutlinerObj
Caption object formatting.
Definition: postit.cxx:825
const SfxPoolItem & GetDefaultItem(sal_uInt16 nWhich) const
virtual SdrObject * RemoveObject(size_t nObjNum)
sal_Int32 GetParagraphCount() const
SdrMetricItem makeSdrTextLeftDistItem(tools::Long mnHeight)
constexpr Point TopLeft() const
virtual SdrLayerID GetLayer() const
constexpr tools::Long Bottom() const
bool HasMultiLineText() const
Returns true, if the caption text of this note contains line breaks.
Definition: postit.cxx:937
bool IsInDtorClear() const
Definition: document.hxx:2447
OUString getDate(const Date &rDate) const
void setLock(bool bLock)
static Color GetCommentColor()
Definition: detfunc.cxx:1726
OUString maAuthor
Creation date of the note.
Definition: postit.hxx:149
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
void setClosed(bool bNew)
constexpr Size GetSize() const
void incRef() const
Definition: postit.cxx:689
std::unique_ptr< char[]> aBuffer
ScCaptionPtr mxCaption
Initial data for invisible notes without SdrObject.
Definition: postit.hxx:151
constexpr SdrLayerID SC_LAYER_HIDDEN(4)
ScCaptionInitData()
True = use default position and size for caption.
Definition: postit.cxx:834
Some desperate attempt to fight against the caption object ownership mess, to which none of shared/we...
Definition: postit.hxx:42
Internal data for a cell annotation.
Definition: postit.hxx:144
#define SAL_WARN_IF(condition, area, stream)
const SdrCaptionObj * get() const
Definition: postit.hxx:54
virtual OutlinerParaObject * GetOutlinerParaObject() const override
SdrMetricItem makeSdrShadowXDistItem(tools::Long nDist)
sal_uInt32 mnPostItId
Note data with pointer to caption object.
Definition: postit.hxx:277
bool decRef() const
Definition: postit.cxx:695
#define SAL_INFO(area, stream)
const SfxItemSet & GetMergedItemSet() const
oslInterlockedCount getRefs() const
Definition: postit.cxx:684
constexpr SdrLayerID SC_LAYER_INTERN(2)
OUString maDate
Definition: postit.hxx:148
SdrCaptionObj * release()
Release all management of the SdrCaptionObj* in all instances of this list and dissolve.
Definition: postit.cxx:783
void * p
void CreateCaptionFromInitData(const ScAddress &rPos) const
Creates the caption object from initial caption data if existing.
Definition: postit.cxx:1015
SdrOnOffItem makeSdrShadowItem(bool bShadow)
ScCaptionPtr & operator=(const ScCaptionPtr &r)
Definition: postit.cxx:511
const EditTextObject * GetEditTextObject() const
Returns the pointer to the current edit text object, or null.
Definition: postit.cxx:910
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
void removeFromDrawPageAndFree(bool bIgnoreUndo=false)
Remove from draw page and free caption object if no Undo recording.
Definition: postit.cxx:753
void dissolve()
Dissolve list when the caption object is released or gone.
Definition: postit.cxx:798
void CreateCaption(const ScAddress &rPos, const SdrCaptionObj *pCaption=nullptr)
Creates a new caption object at the passed cell position, clones passed existing caption.
Definition: postit.cxx:1090
static ScPostIt * CreateNoteFromString(ScDocument &rDoc, const ScAddress &rPos, const OUString &rNoteText, bool bShown, bool bAlwaysCreateCaption, sal_uInt32 nPostItId=0)
Creates a cell note based on the passed string and inserts it into the document.
Definition: postit.cxx:1276
void newHead()
Definition: postit.cxx:559
ScDocument & mrDoc
Definition: postit.hxx:275
ScAddress maEnd
Definition: userdat.hxx:37
void reset(SdrCaptionObj *p)
Definition: postit.cxx:653
void UpdateCaptionPos(const ScAddress &rPos)
Updates caption position according to position of the passed cell.
Definition: postit.cxx:1003
ScNoteData(bool bShown=false)
True = note is visible.
Definition: postit.cxx:839
const Point & GetTailPos() const
bool m_bDetectedRangeSegmentation false
bool IsCaptionShown() const
Returns true, if the caption object is visible.
Definition: postit.hxx:255
void FillEditItemSet(SfxItemSet *pEditSet, const SfxItemSet *pCondSet=nullptr) const
Converts all Calc items contained in the own item set to edit engine items and puts them into pEditSe...
Definition: patattr.cxx:827
constexpr tools::Long GetHeight() const
bool IsRecording() const
Definition: drwlayer.hxx:142
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo