Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / data / postit.cxx
blobcbff1e6cc82e5174772ae8fe84f764fa92dacb23
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "postit.hxx"
23 #include <rtl/ustrbuf.hxx>
24 #include <unotools/useroptions.hxx>
25 #include <svx/svdpage.hxx>
26 #include <svx/svdocapt.hxx>
27 #include <editeng/outlobj.hxx>
28 #include <editeng/editobj.hxx>
29 #include <basegfx/polygon/b2dpolygon.hxx>
31 #include "scitems.hxx"
32 #include <svx/xlnstit.hxx>
33 #include <svx/xlnstwit.hxx>
34 #include <svx/xlnstcit.hxx>
35 #include <svx/sxcecitm.hxx>
36 #include <svx/xflclit.hxx>
37 #include <svx/sdshitm.hxx>
38 #include <svx/sdsxyitm.hxx>
39 #include <tools/gen.hxx>
41 #include "table.hxx"
42 #include "document.hxx"
43 #include "docpool.hxx"
44 #include "patattr.hxx"
45 #include "formulacell.hxx"
46 #include "drwlayer.hxx"
47 #include "userdat.hxx"
48 #include "detfunc.hxx"
50 #include <utility>
53 // ============================================================================
55 namespace {
57 const long SC_NOTECAPTION_WIDTH = 2900; /// Default width of note caption textbox.
58 const long SC_NOTECAPTION_MAXWIDTH_TEMP = 12000; /// Maximum width of temporary note caption textbox.
59 const long SC_NOTECAPTION_HEIGHT = 1800; /// Default height of note caption textbox.
60 const long SC_NOTECAPTION_CELLDIST = 600; /// Default distance of note captions to border of anchor cell.
61 const long SC_NOTECAPTION_OFFSET_Y = -1500; /// Default Y offset of note captions to top border of anchor cell.
62 const long SC_NOTECAPTION_OFFSET_X = 1500; /// Default X offset of note captions to left border of anchor cell.
63 const long SC_NOTECAPTION_BORDERDIST_TEMP = 100; /// Distance of temporary note captions to visible sheet area.
65 // ============================================================================
67 /** Static helper functions for caption objects. */
68 class ScCaptionUtil
70 public:
71 /** Moves the caption object to the correct layer according to passed visibility. */
72 static void SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown );
73 /** Sets basic caption settings required for note caption objects. */
74 static void SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown );
75 /** Stores the cell position of the note in the user data area of the caption. */
76 static void SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos );
77 /** Sets all default formatting attributes to the caption object. */
78 static void SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc );
79 /** Updates caption item set according to the passed item set while removing shadow items. */
80 static void SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet );
83 // ----------------------------------------------------------------------------
85 void ScCaptionUtil::SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown )
87 SdrLayerID nLayer = bShown ? SC_LAYER_INTERN : SC_LAYER_HIDDEN;
88 if( nLayer != rCaption.GetLayer() )
89 rCaption.SetLayer( nLayer );
92 void ScCaptionUtil::SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown )
94 SetCaptionLayer( rCaption, bShown );
95 rCaption.SetFixedTail();
96 rCaption.SetSpecialTextBoxShadow();
99 void ScCaptionUtil::SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos )
101 // pass true to ScDrawLayer::GetObjData() to create the object data entry
102 ScDrawObjData* pObjData = ScDrawLayer::GetObjData( &rCaption, true );
103 OSL_ENSURE( pObjData, "ScCaptionUtil::SetCaptionUserData - missing drawing object user data" );
104 pObjData->maStart = rPos;
105 pObjData->meType = ScDrawObjData::CellNote;
108 void ScCaptionUtil::SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc )
110 SfxItemSet aItemSet = rCaption.GetMergedItemSet();
112 // caption tail arrow
113 ::basegfx::B2DPolygon aTriangle;
114 aTriangle.append( ::basegfx::B2DPoint( 10.0, 0.0 ) );
115 aTriangle.append( ::basegfx::B2DPoint( 0.0, 30.0 ) );
116 aTriangle.append( ::basegfx::B2DPoint( 20.0, 30.0 ) );
117 aTriangle.setClosed( true );
118 /* Line ends are now created with an empty name. The
119 checkForUniqueItem() method then finds a unique name for the item's
120 value. */
121 aItemSet.Put( XLineStartItem( OUString(), ::basegfx::B2DPolyPolygon( aTriangle ) ) );
122 aItemSet.Put( XLineStartWidthItem( 200 ) );
123 aItemSet.Put( XLineStartCenterItem( false ) );
124 aItemSet.Put( XFillStyleItem( XFILL_SOLID ) );
125 aItemSet.Put( XFillColorItem( OUString(), ScDetectiveFunc::GetCommentColor() ) );
126 aItemSet.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT ) );
128 // shadow
129 /* SdrShadowItem has sal_False, instead the shadow is set for the
130 rectangle only with SetSpecialTextBoxShadow() when the object is
131 created (item must be set to adjust objects from older files). */
132 aItemSet.Put( SdrShadowItem( false ) );
133 aItemSet.Put( SdrShadowXDistItem( 100 ) );
134 aItemSet.Put( SdrShadowYDistItem( 100 ) );
136 // text attributes
137 aItemSet.Put( SdrTextLeftDistItem( 100 ) );
138 aItemSet.Put( SdrTextRightDistItem( 100 ) );
139 aItemSet.Put( SdrTextUpperDistItem( 100 ) );
140 aItemSet.Put( SdrTextLowerDistItem( 100 ) );
141 aItemSet.Put( SdrTextAutoGrowWidthItem( false ) );
142 aItemSet.Put( SdrTextAutoGrowHeightItem( true ) );
143 // use the default cell style to be able to modify the caption font
144 const ScPatternAttr& rDefPattern = static_cast< const ScPatternAttr& >( rDoc.GetPool()->GetDefaultItem( ATTR_PATTERN ) );
145 rDefPattern.FillEditItemSet( &aItemSet );
147 rCaption.SetMergedItemSet( aItemSet );
150 void ScCaptionUtil::SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet )
152 // copy all items
153 rCaption.SetMergedItemSet( rItemSet );
154 // reset shadow items
155 rCaption.SetMergedItem( SdrShadowItem( false ) );
156 rCaption.SetMergedItem( SdrShadowXDistItem( 100 ) );
157 rCaption.SetMergedItem( SdrShadowYDistItem( 100 ) );
158 rCaption.SetSpecialTextBoxShadow();
161 // ============================================================================
163 /** Helper for creation and manipulation of caption drawing objects independent
164 from cell annotations. */
165 class ScCaptionCreator
167 public:
168 /** Create a new caption. The caption will not be inserted into the document. */
169 explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bShown, bool bTailFront );
170 /** Manipulate an existing caption. */
171 explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption );
173 /** Returns the drawing layer page of the sheet contained in maPos. */
174 SdrPage* GetDrawPage();
175 /** Returns the caption drawing obejct. */
176 inline SdrCaptionObj* GetCaption() { return mpCaption; }
178 /** Moves the caption inside the passed rectangle. Uses page area if 0 is passed. */
179 void FitCaptionToRect( const Rectangle* pVisRect = 0 );
180 /** Places the caption inside the passed rectangle, tries to keep the cell rectangle uncovered. Uses page area if 0 is passed. */
181 void AutoPlaceCaption( const Rectangle* pVisRect = 0 );
182 /** Updates caption tail and textbox according to current cell position. Uses page area if 0 is passed. */
183 void UpdateCaptionPos( const Rectangle* pVisRect = 0 );
185 protected:
186 /** Helper constructor for derived classes. */
187 explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos );
189 /** Calculates the caption tail position according to current cell position. */
190 Point CalcTailPos( bool bTailFront );
191 /** Implements creation of the caption object. The caption will not be inserted into the document. */
192 void CreateCaption( bool bShown, bool bTailFront );
194 private:
195 /** Initializes all members. */
196 void Initialize();
197 /** Returns the passed rectangle if existing, page rectangle otherwise. */
198 inline const Rectangle& GetVisRect( const Rectangle* pVisRect ) const { return pVisRect ? *pVisRect : maPageRect; }
200 private:
201 ScDocument& mrDoc;
202 ScAddress maPos;
203 SdrCaptionObj* mpCaption;
204 Rectangle maPageRect;
205 Rectangle maCellRect;
206 bool mbNegPage;
209 // ----------------------------------------------------------------------------
211 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bShown, bool bTailFront ) :
212 mrDoc( rDoc ),
213 maPos( rPos ),
214 mpCaption( 0 )
216 Initialize();
217 CreateCaption( bShown, bTailFront );
220 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption ) :
221 mrDoc( rDoc ),
222 maPos( rPos ),
223 mpCaption( &rCaption )
225 Initialize();
228 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos ) :
229 mrDoc( rDoc ),
230 maPos( rPos ),
231 mpCaption( 0 )
233 Initialize();
236 SdrPage* ScCaptionCreator::GetDrawPage()
238 ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
239 return pDrawLayer ? pDrawLayer->GetPage( static_cast< sal_uInt16 >( maPos.Tab() ) ) : 0;
242 void ScCaptionCreator::FitCaptionToRect( const Rectangle* pVisRect )
244 const Rectangle& rVisRect = GetVisRect( pVisRect );
246 // tail position
247 Point aTailPos = mpCaption->GetTailPos();
248 aTailPos.X() = ::std::max( ::std::min( aTailPos.X(), rVisRect.Right() ), rVisRect.Left() );
249 aTailPos.Y() = ::std::max( ::std::min( aTailPos.Y(), rVisRect.Bottom() ), rVisRect.Top() );
250 mpCaption->SetTailPos( aTailPos );
252 // caption rectangle
253 Rectangle aCaptRect = mpCaption->GetLogicRect();
254 Point aCaptPos = aCaptRect.TopLeft();
255 // move textbox inside right border of visible area
256 aCaptPos.X() = ::std::min< long >( aCaptPos.X(), rVisRect.Right() - aCaptRect.GetWidth() );
257 // move textbox inside left border of visible area (this may move it outside on right side again)
258 aCaptPos.X() = ::std::max< long >( aCaptPos.X(), rVisRect.Left() );
259 // move textbox inside bottom border of visible area
260 aCaptPos.Y() = ::std::min< long >( aCaptPos.Y(), rVisRect.Bottom() - aCaptRect.GetHeight() );
261 // move textbox inside top border of visible area (this may move it outside on bottom side again)
262 aCaptPos.Y() = ::std::max< long >( aCaptPos.Y(), rVisRect.Top() );
263 // update caption
264 aCaptRect.SetPos( aCaptPos );
265 mpCaption->SetLogicRect( aCaptRect );
268 void ScCaptionCreator::AutoPlaceCaption( const Rectangle* pVisRect )
270 const Rectangle& rVisRect = GetVisRect( pVisRect );
272 // caption rectangle
273 Rectangle aCaptRect = mpCaption->GetLogicRect();
274 long nWidth = aCaptRect.GetWidth();
275 long nHeight = aCaptRect.GetHeight();
277 // n***Space contains available space between border of visible area and cell
278 long nLeftSpace = maCellRect.Left() - rVisRect.Left() + 1;
279 long nRightSpace = rVisRect.Right() - maCellRect.Right() + 1;
280 long nTopSpace = maCellRect.Top() - rVisRect.Top() + 1;
281 long nBottomSpace = rVisRect.Bottom() - maCellRect.Bottom() + 1;
283 // nNeeded*** contains textbox dimensions plus needed distances to cell or border of visible area
284 long nNeededSpaceX = nWidth + SC_NOTECAPTION_CELLDIST;
285 long nNeededSpaceY = nHeight + SC_NOTECAPTION_CELLDIST;
287 // bFitsWidth*** == true means width of textbox fits into horizontal free space of visible area
288 bool bFitsWidthLeft = nNeededSpaceX <= nLeftSpace; // text box width fits into the width left of cell
289 bool bFitsWidthRight = nNeededSpaceX <= nRightSpace; // text box width fits into the width right of cell
290 bool bFitsWidth = nWidth <= rVisRect.GetWidth(); // text box width fits into width of visible area
292 // bFitsHeight*** == true means height of textbox fits into vertical free space of visible area
293 bool bFitsHeightTop = nNeededSpaceY <= nTopSpace; // text box height fits into the height above cell
294 bool bFitsHeightBottom = nNeededSpaceY <= nBottomSpace; // text box height fits into the height below cell
295 bool bFitsHeight = nHeight <= rVisRect.GetHeight(); // text box height fits into height of visible area
297 // bFits*** == true means the textbox fits completely into free space of visible area
298 bool bFitsLeft = bFitsWidthLeft && bFitsHeight;
299 bool bFitsRight = bFitsWidthRight && bFitsHeight;
300 bool bFitsTop = bFitsWidth && bFitsHeightTop;
301 bool bFitsBottom = bFitsWidth && bFitsHeightBottom;
303 Point aCaptPos;
304 // use left/right placement if possible, or if top/bottom placement not possible
305 if( bFitsLeft || bFitsRight || (!bFitsTop && !bFitsBottom) )
307 // prefer left in RTL sheet and right in LTR sheets
308 bool bPreferLeft = bFitsLeft && (mbNegPage || !bFitsRight);
309 bool bPreferRight = bFitsRight && (!mbNegPage || !bFitsLeft);
310 // move to left, if left is preferred, or if neither left nor right fit and there is more space to the left
311 if( bPreferLeft || (!bPreferRight && (nLeftSpace > nRightSpace)) )
312 aCaptPos.X() = maCellRect.Left() - SC_NOTECAPTION_CELLDIST - nWidth;
313 else // to right
314 aCaptPos.X() = maCellRect.Right() + SC_NOTECAPTION_CELLDIST;
315 // Y position according to top cell border
316 aCaptPos.Y() = maCellRect.Top() + SC_NOTECAPTION_OFFSET_Y;
318 else // top or bottom placement
320 // X position
321 aCaptPos.X() = maCellRect.Left() + SC_NOTECAPTION_OFFSET_X;
322 // top placement, if possible
323 if( bFitsTop )
324 aCaptPos.Y() = maCellRect.Top() - SC_NOTECAPTION_CELLDIST - nHeight;
325 else // bottom placement
326 aCaptPos.Y() = maCellRect.Bottom() + SC_NOTECAPTION_CELLDIST;
329 // update textbox position in note caption object
330 aCaptRect.SetPos( aCaptPos );
331 mpCaption->SetLogicRect( aCaptRect );
332 FitCaptionToRect( pVisRect );
335 void ScCaptionCreator::UpdateCaptionPos( const Rectangle* pVisRect )
337 ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
339 // update caption position
340 const Point& rOldTailPos = mpCaption->GetTailPos();
341 Point aTailPos = CalcTailPos( false );
342 if( rOldTailPos != aTailPos )
344 // create drawing undo action
345 if( pDrawLayer && pDrawLayer->IsRecording() )
346 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoGeoObject( *mpCaption ) );
347 // calculate new caption rectangle (#i98141# handle LTR<->RTL switch correctly)
348 Rectangle aCaptRect = mpCaption->GetLogicRect();
349 long nDiffX = (rOldTailPos.X() >= 0) ? (aCaptRect.Left() - rOldTailPos.X()) : (rOldTailPos.X() - aCaptRect.Right());
350 if( mbNegPage ) nDiffX = -nDiffX - aCaptRect.GetWidth();
351 long nDiffY = aCaptRect.Top() - rOldTailPos.Y();
352 aCaptRect.SetPos( aTailPos + Point( nDiffX, nDiffY ) );
353 // set new tail position and caption rectangle
354 mpCaption->SetTailPos( aTailPos );
355 mpCaption->SetLogicRect( aCaptRect );
356 // fit caption into draw page
357 FitCaptionToRect( pVisRect );
360 // update cell position in caption user data
361 ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( mpCaption, maPos.Tab() );
362 if( pCaptData && (maPos != pCaptData->maStart) )
364 // create drawing undo action
365 if( pDrawLayer && pDrawLayer->IsRecording() )
366 pDrawLayer->AddCalcUndo( new ScUndoObjData( mpCaption, pCaptData->maStart, pCaptData->maEnd, maPos, pCaptData->maEnd ) );
367 // set new position
368 pCaptData->maStart = maPos;
372 Point ScCaptionCreator::CalcTailPos( bool bTailFront )
374 // tail position
375 bool bTailLeft = bTailFront != mbNegPage;
376 Point aTailPos = bTailLeft ? maCellRect.TopLeft() : maCellRect.TopRight();
377 // move caption point 1/10 mm inside cell
378 if( bTailLeft ) aTailPos.X() += 10; else aTailPos.X() -= 10;
379 aTailPos.Y() += 10;
380 return aTailPos;
383 void ScCaptionCreator::CreateCaption( bool bShown, bool bTailFront )
385 // create the caption drawing object
386 Rectangle aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH, SC_NOTECAPTION_HEIGHT ) );
387 Point aTailPos = CalcTailPos( bTailFront );
388 mpCaption = new SdrCaptionObj( aTextRect, aTailPos );
389 // basic caption settings
390 ScCaptionUtil::SetBasicCaptionSettings( *mpCaption, bShown );
393 void ScCaptionCreator::Initialize()
395 maCellRect = ScDrawLayer::GetCellRect( mrDoc, maPos, true );
396 mbNegPage = mrDoc.IsNegativePage( maPos.Tab() );
397 if( SdrPage* pDrawPage = GetDrawPage() )
399 maPageRect = Rectangle( Point( 0, 0 ), pDrawPage->GetSize() );
400 /* #i98141# SdrPage::GetSize() returns negative width in RTL mode.
401 The call to Rectangle::Adjust() orders left/right coordinate
402 accordingly. */
403 maPageRect.Justify();
407 // ============================================================================
409 /** Helper for creation of permanent caption drawing objects for cell notes. */
410 class ScNoteCaptionCreator : public ScCaptionCreator
412 public:
413 /** Create a new caption object and inserts it into the document. */
414 explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData );
415 /** Manipulate an existing caption. */
416 explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown );
419 // ----------------------------------------------------------------------------
421 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData ) :
422 ScCaptionCreator( rDoc, rPos ) // use helper c'tor that does not create the caption yet
424 SdrPage* pDrawPage = GetDrawPage();
425 OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
426 if( pDrawPage )
428 // create the caption drawing object
429 CreateCaption( rNoteData.mbShown, false );
430 rNoteData.mpCaption = GetCaption();
431 OSL_ENSURE( rNoteData.mpCaption, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" );
432 if( rNoteData.mpCaption )
434 // store note position in user data of caption object
435 ScCaptionUtil::SetCaptionUserData( *rNoteData.mpCaption, rPos );
436 // insert object into draw page
437 pDrawPage->InsertObject( rNoteData.mpCaption );
442 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown ) :
443 ScCaptionCreator( rDoc, rPos, rCaption )
445 SdrPage* pDrawPage = GetDrawPage();
446 OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
447 OSL_ENSURE( rCaption.GetPage() == pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" );
448 if( pDrawPage && (rCaption.GetPage() == pDrawPage) )
450 // store note position in user data of caption object
451 ScCaptionUtil::SetCaptionUserData( rCaption, rPos );
452 // basic caption settings
453 ScCaptionUtil::SetBasicCaptionSettings( rCaption, bShown );
454 // set correct tail position
455 rCaption.SetTailPos( CalcTailPos( false ) );
459 } // namespace
461 // ============================================================================
463 struct ScCaptionInitData
465 typedef ::std::auto_ptr< SfxItemSet > SfxItemSetPtr;
466 typedef ::std::auto_ptr< OutlinerParaObject > OutlinerParaObjPtr;
468 SfxItemSetPtr mxItemSet; /// Caption object formatting.
469 OutlinerParaObjPtr mxOutlinerObj; /// Text object with all text portion formatting.
470 OUString maSimpleText; /// Simple text without formatting.
471 Point maCaptionOffset; /// Caption position relative to cell corner.
472 Size maCaptionSize; /// Size of the caption object.
473 bool mbDefaultPosSize; /// True = use default position and size for caption.
475 explicit ScCaptionInitData();
478 // ----------------------------------------------------------------------------
480 ScCaptionInitData::ScCaptionInitData() :
481 mbDefaultPosSize( true )
485 // ============================================================================
487 ScNoteData::ScNoteData( bool bShown ) :
488 mpCaption( 0 ),
489 mbShown( bShown )
493 ScNoteData::~ScNoteData()
497 // ============================================================================
499 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, bool bShown ) :
500 mrDoc( rDoc ),
501 maNoteData( bShown )
503 AutoStamp();
504 CreateCaption( rPos );
507 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNote ) :
508 mrDoc( rDoc ),
509 maNoteData( rNote.maNoteData )
511 maNoteData.mpCaption = 0;
512 CreateCaption( rPos, rNote.maNoteData.mpCaption );
515 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScNoteData& rNoteData, bool bAlwaysCreateCaption ) :
516 mrDoc( rDoc ),
517 maNoteData( rNoteData )
519 if( bAlwaysCreateCaption || maNoteData.mbShown )
520 CreateCaptionFromInitData( rPos );
523 ScPostIt::~ScPostIt()
525 RemoveCaption();
528 ScPostIt* ScPostIt::Clone( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, bool bCloneCaption ) const
530 CreateCaptionFromInitData( rOwnPos );
531 return bCloneCaption ? new ScPostIt( rDestDoc, rDestPos, *this ) : new ScPostIt( rDestDoc, rDestPos, maNoteData, false );
534 const ScNoteData& ScPostIt::GetNoteData() const
536 return maNoteData;
539 const OUString& ScPostIt::GetDate() const
541 return maNoteData.maDate;
544 void ScPostIt::SetDate( const OUString& rDate )
546 maNoteData.maDate = rDate;
549 const OUString& ScPostIt::GetAuthor() const
551 return maNoteData.maAuthor;
554 void ScPostIt::SetAuthor( const OUString& rAuthor )
556 maNoteData.maAuthor = rAuthor;
559 void ScPostIt::AutoStamp()
561 maNoteData.maDate = ScGlobal::pLocaleData->getDate( Date( Date::SYSTEM ) );
562 maNoteData.maAuthor = SvtUserOptions().GetID();
565 const OutlinerParaObject* ScPostIt::GetOutlinerObject() const
567 if( maNoteData.mpCaption )
568 return maNoteData.mpCaption->GetOutlinerParaObject();
569 if( maNoteData.mxInitData.get() )
570 return maNoteData.mxInitData->mxOutlinerObj.get();
571 return 0;
574 const EditTextObject* ScPostIt::GetEditTextObject() const
576 const OutlinerParaObject* pOPO = GetOutlinerObject();
577 return pOPO ? &pOPO->GetTextObject() : 0;
580 OUString ScPostIt::GetText() const
582 if( const EditTextObject* pEditObj = GetEditTextObject() )
584 OUStringBuffer aBuffer;
585 for( sal_Int32 nPara = 0, nParaCount = pEditObj->GetParagraphCount(); nPara < nParaCount; ++nPara )
587 if( nPara > 0 )
588 aBuffer.append( '\n' );
589 aBuffer.append( pEditObj->GetText( nPara ) );
591 return aBuffer.makeStringAndClear();
593 if( maNoteData.mxInitData.get() )
594 return maNoteData.mxInitData->maSimpleText;
595 return OUString();
598 void ScPostIt::SetText( const ScAddress& rPos, const OUString& rText )
600 CreateCaptionFromInitData( rPos );
601 if( maNoteData.mpCaption )
602 maNoteData.mpCaption->SetText( rText );
605 SdrCaptionObj* ScPostIt::GetCaption() const
607 return maNoteData.mpCaption;
610 SdrCaptionObj* ScPostIt::GetOrCreateCaption( const ScAddress& rPos ) const
612 CreateCaptionFromInitData( rPos );
613 return maNoteData.mpCaption;
616 void ScPostIt::ForgetCaption()
618 /* This function is used in undo actions to give up the responsibility for
619 the caption object which is handled by separate drawing undo actions. */
620 maNoteData.mpCaption = 0;
621 maNoteData.mxInitData.reset();
624 void ScPostIt::ShowCaption( const ScAddress& rPos, bool bShow )
626 CreateCaptionFromInitData( rPos );
627 // no separate drawing undo needed, handled completely inside ScUndoShowHideNote
628 maNoteData.mbShown = bShow;
629 if( maNoteData.mpCaption )
630 ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, bShow );
633 bool ScPostIt::IsCaptionShown() const
635 return maNoteData.mbShown;
638 void ScPostIt::ShowCaptionTemp( const ScAddress& rPos, bool bShow )
640 CreateCaptionFromInitData( rPos );
641 if( maNoteData.mpCaption )
642 ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, maNoteData.mbShown || bShow );
645 void ScPostIt::UpdateCaptionPos( const ScAddress& rPos )
647 CreateCaptionFromInitData( rPos );
648 if( maNoteData.mpCaption )
650 ScCaptionCreator aCreator( mrDoc, rPos, *maNoteData.mpCaption );
651 aCreator.UpdateCaptionPos();
655 // private --------------------------------------------------------------------
657 void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const
659 OSL_ENSURE( maNoteData.mpCaption || maNoteData.mxInitData.get(), "ScPostIt::CreateCaptionFromInitData - need caption object or initial caption data" );
660 if( maNoteData.mxInitData.get() )
662 /* This function is called from ScPostIt::Clone() when copying cells
663 to the clipboard/undo document, and when copying cells from the
664 clipboard/undo document. The former should always be called first,
665 so if called in an clipboard/undo document, the caption should have
666 been created already. */
667 OSL_ENSURE( !mrDoc.IsUndo() && !mrDoc.IsClipboard(), "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" );
669 /* #i104915# Never try to create notes in Undo document, leads to
670 crash due to missing document members (e.g. row height array). */
671 if( !maNoteData.mpCaption && !mrDoc.IsUndo() )
673 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
674 ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
675 if( maNoteData.mpCaption )
677 ScCaptionInitData& rInitData = *maNoteData.mxInitData;
679 // transfer ownership of outliner object to caption, or set simple text
680 OSL_ENSURE( rInitData.mxOutlinerObj.get() || !rInitData.maSimpleText.isEmpty(),
681 "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" );
682 if( rInitData.mxOutlinerObj.get() )
683 maNoteData.mpCaption->SetOutlinerParaObject( rInitData.mxOutlinerObj.release() );
684 else
685 maNoteData.mpCaption->SetText( rInitData.maSimpleText );
687 // copy all items or set default items; reset shadow items
688 ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
689 if( rInitData.mxItemSet.get() )
690 ScCaptionUtil::SetCaptionItems( *maNoteData.mpCaption, *rInitData.mxItemSet );
692 // set position and size of the caption object
693 if( rInitData.mbDefaultPosSize )
695 // set other items and fit caption size to text
696 maNoteData.mpCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
697 maNoteData.mpCaption->SetMergedItem( SdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) );
698 maNoteData.mpCaption->AdjustTextFrameWidthAndHeight();
699 aCreator.AutoPlaceCaption();
701 else
703 Rectangle aCellRect = ScDrawLayer::GetCellRect( mrDoc, rPos, true );
704 bool bNegPage = mrDoc.IsNegativePage( rPos.Tab() );
705 long nPosX = bNegPage ? (aCellRect.Left() - rInitData.maCaptionOffset.X()) : (aCellRect.Right() + rInitData.maCaptionOffset.X());
706 long nPosY = aCellRect.Top() + rInitData.maCaptionOffset.Y();
707 Rectangle aCaptRect( Point( nPosX, nPosY ), rInitData.maCaptionSize );
708 maNoteData.mpCaption->SetLogicRect( aCaptRect );
709 aCreator.FitCaptionToRect();
713 // forget the initial caption data struct
714 maNoteData.mxInitData.reset();
718 void ScPostIt::CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption )
720 OSL_ENSURE( !maNoteData.mpCaption, "ScPostIt::CreateCaption - unexpected caption object found" );
721 maNoteData.mpCaption = 0;
723 /* #i104915# Never try to create notes in Undo document, leads to
724 crash due to missing document members (e.g. row height array). */
725 OSL_ENSURE( !mrDoc.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" );
726 if( mrDoc.IsUndo() )
727 return;
729 // drawing layer may be missing, if a note is copied into a clipboard document
730 if( mrDoc.IsClipboard() )
731 mrDoc.InitDrawLayer();
733 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
734 ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
735 if( maNoteData.mpCaption )
737 // clone settings of passed caption
738 if( pCaption )
740 // copy edit text object (object must be inserted into page already)
741 if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
742 maNoteData.mpCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
743 // copy formatting items (after text has been copied to apply font formatting)
744 maNoteData.mpCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() );
745 // move textbox position relative to new cell, copy textbox size
746 Rectangle aCaptRect = pCaption->GetLogicRect();
747 Point aDist = maNoteData.mpCaption->GetTailPos() - pCaption->GetTailPos();
748 aCaptRect.Move( aDist.X(), aDist.Y() );
749 maNoteData.mpCaption->SetLogicRect( aCaptRect );
750 aCreator.FitCaptionToRect();
752 else
754 // set default formatting and default position
755 ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
756 aCreator.AutoPlaceCaption();
759 // create undo action
760 if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() )
761 if( pDrawLayer->IsRecording() )
762 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoNewObject( *maNoteData.mpCaption ) );
766 void ScPostIt::RemoveCaption()
769 /* Remove caption object only, if this note is its owner (e.g. notes in
770 undo documents refer to captions in original document, do not remove
771 them from drawing layer here). */
772 ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
773 if( maNoteData.mpCaption && (pDrawLayer == maNoteData.mpCaption->GetModel()) )
775 OSL_ENSURE( pDrawLayer, "ScPostIt::RemoveCaption - object without drawing layer" );
776 SdrPage* pDrawPage = maNoteData.mpCaption->GetPage();
777 OSL_ENSURE( pDrawPage, "ScPostIt::RemoveCaption - object without drawing page" );
778 if( pDrawPage )
780 pDrawPage->RecalcObjOrdNums();
781 // create drawing undo action (before removing the object to have valid draw page in undo action)
782 bool bRecording = ( pDrawLayer && pDrawLayer->IsRecording() );
783 if( bRecording )
784 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoDeleteObject( *maNoteData.mpCaption ) );
785 // remove the object from the drawing page, delete if undo is disabled
786 SdrObject* pObj = pDrawPage->RemoveObject( maNoteData.mpCaption->GetOrdNum() );
787 if( !bRecording )
788 SdrObject::Free( pObj );
791 maNoteData.mpCaption = 0;
794 // ============================================================================
796 SdrCaptionObj* ScNoteUtil::CreateTempCaption(
797 ScDocument& rDoc, const ScAddress& rPos, SdrPage& rDrawPage,
798 const OUString& rUserText, const Rectangle& rVisRect, bool bTailFront )
800 OUStringBuffer aBuffer( rUserText );
801 // add plain text of invisible (!) cell note (no formatting etc.)
802 SdrCaptionObj* pNoteCaption = 0;
803 const ScPostIt* pNote = rDoc.GetNote( rPos );
804 if( pNote && !pNote->IsCaptionShown() )
806 if( !aBuffer.isEmpty() )
807 aBuffer.append( "\n--------\n" ).append( pNote->GetText() );
808 pNoteCaption = pNote->GetOrCreateCaption( rPos );
811 // create a caption if any text exists
812 if( !pNoteCaption && aBuffer.isEmpty() )
813 return 0;
815 // prepare visible rectangle (add default distance to all borders)
816 Rectangle aVisRect(
817 rVisRect.Left() + SC_NOTECAPTION_BORDERDIST_TEMP,
818 rVisRect.Top() + SC_NOTECAPTION_BORDERDIST_TEMP,
819 rVisRect.Right() - SC_NOTECAPTION_BORDERDIST_TEMP,
820 rVisRect.Bottom() - SC_NOTECAPTION_BORDERDIST_TEMP );
822 // create the caption object
823 ScCaptionCreator aCreator( rDoc, rPos, true, bTailFront );
824 SdrCaptionObj* pCaption = aCreator.GetCaption();
826 // insert caption into page (needed to set caption text)
827 rDrawPage.InsertObject( pCaption );
829 // clone the edit text object, unless user text is present, then set this text
830 if( pNoteCaption && rUserText.isEmpty() )
832 if( OutlinerParaObject* pOPO = pNoteCaption->GetOutlinerParaObject() )
833 pCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
834 // set formatting (must be done after setting text) and resize the box to fit the text
835 pCaption->SetMergedItemSetAndBroadcast( pNoteCaption->GetMergedItemSet() );
836 Rectangle aCaptRect( pCaption->GetLogicRect().TopLeft(), pNoteCaption->GetLogicRect().GetSize() );
837 pCaption->SetLogicRect( aCaptRect );
839 else
841 // if pNoteCaption is null, then aBuffer contains some text
842 pCaption->SetText( aBuffer.makeStringAndClear() );
843 ScCaptionUtil::SetDefaultItems( *pCaption, rDoc );
844 // adjust caption size to text size
845 long nMaxWidth = ::std::min< long >( aVisRect.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP );
846 pCaption->SetMergedItem( SdrTextAutoGrowWidthItem( sal_True ) );
847 pCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
848 pCaption->SetMergedItem( SdrTextMaxFrameWidthItem( nMaxWidth ) );
849 pCaption->SetMergedItem( SdrTextAutoGrowHeightItem( sal_True ) );
850 pCaption->AdjustTextFrameWidthAndHeight();
853 // move caption into visible area
854 aCreator.AutoPlaceCaption( &aVisRect );
855 return pCaption;
858 ScPostIt* ScNoteUtil::CreateNoteFromCaption(
859 ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown )
861 ScNoteData aNoteData( bShown );
862 aNoteData.mpCaption = &rCaption;
863 ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, false );
864 pNote->AutoStamp();
866 // if pNote still points to the note after TakeNote(), insertion was successful
867 rDoc.SetNote(rPos, pNote);
868 if( pNote )
870 // ScNoteCaptionCreator c'tor updates the caption object to be part of a note
871 ScNoteCaptionCreator aCreator( rDoc, rPos, rCaption, bShown );
873 else
874 return NULL;
876 return pNote;
879 ScPostIt* ScNoteUtil::CreateNoteFromObjectData(
880 ScDocument& rDoc, const ScAddress& rPos, SfxItemSet* pItemSet,
881 OutlinerParaObject* pOutlinerObj, const Rectangle& rCaptionRect,
882 bool bShown, bool bAlwaysCreateCaption )
884 OSL_ENSURE( pItemSet && pOutlinerObj, "ScNoteUtil::CreateNoteFromObjectData - item set and outliner object expected" );
885 ScNoteData aNoteData( bShown );
886 aNoteData.mxInitData.reset( new ScCaptionInitData );
887 ScCaptionInitData& rInitData = *aNoteData.mxInitData;
888 rInitData.mxItemSet.reset( pItemSet );
889 rInitData.mxOutlinerObj.reset( pOutlinerObj );
891 // convert absolute caption position to relative position
892 rInitData.mbDefaultPosSize = rCaptionRect.IsEmpty();
893 if( !rInitData.mbDefaultPosSize )
895 Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, rPos, true );
896 bool bNegPage = rDoc.IsNegativePage( rPos.Tab() );
897 rInitData.maCaptionOffset.X() = bNegPage ? (aCellRect.Left() - rCaptionRect.Right()) : (rCaptionRect.Left() - aCellRect.Right());
898 rInitData.maCaptionOffset.Y() = rCaptionRect.Top() - aCellRect.Top();
899 rInitData.maCaptionSize = rCaptionRect.GetSize();
902 /* Create the note and insert it into the document. If the note is
903 visible, the caption object will be created automatically. */
904 ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
905 pNote->AutoStamp();
907 rDoc.SetNote(rPos, pNote);
909 if(pNote)
910 return pNote;
911 else
912 return NULL;
915 ScPostIt* ScNoteUtil::CreateNoteFromString(
916 ScDocument& rDoc, const ScAddress& rPos, const OUString& rNoteText,
917 bool bShown, bool bAlwaysCreateCaption )
919 ScPostIt* pNote = 0;
920 if( !rNoteText.isEmpty() )
922 ScNoteData aNoteData( bShown );
923 aNoteData.mxInitData.reset( new ScCaptionInitData );
924 ScCaptionInitData& rInitData = *aNoteData.mxInitData;
925 rInitData.maSimpleText = rNoteText;
926 rInitData.mbDefaultPosSize = true;
928 /* Create the note and insert it into the document. If the note is
929 visible, the caption object will be created automatically. */
930 pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
931 pNote->AutoStamp();
932 //insert takes ownership
933 rDoc.SetNote(rPos, pNote);
934 if(!pNote)
935 pNote = NULL;
937 return pNote;
940 namespace sc {
942 NoteEntry::NoteEntry( const ScAddress& rPos, const ScPostIt* pNote ) :
943 maPos(rPos), mpNote(pNote) {}
947 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */