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