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