1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include <rtl/ustrbuf.hxx>
23 #include <unotools/useroptions.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdocapt.hxx>
26 #include <editeng/outlobj.hxx>
27 #include <editeng/editobj.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
30 #include "scitems.hxx"
31 #include <svx/xlnstit.hxx>
32 #include <svx/xlnstwit.hxx>
33 #include <svx/xlnstcit.hxx>
34 #include <svx/sxcecitm.hxx>
35 #include <svx/xflclit.hxx>
36 #include <svx/sdshitm.hxx>
37 #include <svx/sdsxyitm.hxx>
38 #include <tools/gen.hxx>
41 #include "document.hxx"
42 #include "docpool.hxx"
43 #include "patattr.hxx"
44 #include "formulacell.hxx"
45 #include "drwlayer.hxx"
46 #include "userdat.hxx"
47 #include "detfunc.hxx"
48 #include "editutil.hxx"
52 using namespace com::sun::star
;
56 const long SC_NOTECAPTION_WIDTH
= 2900; /// Default width of note caption textbox.
57 const long SC_NOTECAPTION_MAXWIDTH_TEMP
= 12000; /// Maximum width of temporary note caption textbox.
58 const long SC_NOTECAPTION_HEIGHT
= 1800; /// Default height of note caption textbox.
59 const long SC_NOTECAPTION_CELLDIST
= 600; /// Default distance of note captions to border of anchor cell.
60 const long SC_NOTECAPTION_OFFSET_Y
= -1500; /// Default Y offset of note captions to top border of anchor cell.
61 const long SC_NOTECAPTION_OFFSET_X
= 1500; /// Default X offset of note captions to left border of anchor cell.
62 const long SC_NOTECAPTION_BORDERDIST_TEMP
= 100; /// Distance of temporary note captions to visible sheet area.
64 /** Static helper functions for caption objects. */
68 /** Moves the caption object to the correct layer according to passed visibility. */
69 static void SetCaptionLayer( SdrCaptionObj
& rCaption
, bool bShown
);
70 /** Sets basic caption settings required for note caption objects. */
71 static void SetBasicCaptionSettings( SdrCaptionObj
& rCaption
, bool bShown
);
72 /** Stores the cell position of the note in the user data area of the caption. */
73 static void SetCaptionUserData( SdrCaptionObj
& rCaption
, const ScAddress
& rPos
);
74 /** Sets all default formatting attributes to the caption object. */
75 static void SetDefaultItems( SdrCaptionObj
& rCaption
, ScDocument
& rDoc
);
76 /** Updates caption item set according to the passed item set while removing shadow items. */
77 static void SetCaptionItems( SdrCaptionObj
& rCaption
, const SfxItemSet
& rItemSet
);
80 void ScCaptionUtil::SetCaptionLayer( SdrCaptionObj
& rCaption
, bool bShown
)
82 SdrLayerID nLayer
= bShown
? SC_LAYER_INTERN
: SC_LAYER_HIDDEN
;
83 if( nLayer
!= rCaption
.GetLayer() )
84 rCaption
.SetLayer( nLayer
);
87 void ScCaptionUtil::SetBasicCaptionSettings( SdrCaptionObj
& rCaption
, bool bShown
)
89 SetCaptionLayer( rCaption
, bShown
);
90 rCaption
.SetFixedTail();
91 rCaption
.SetSpecialTextBoxShadow();
94 void ScCaptionUtil::SetCaptionUserData( SdrCaptionObj
& rCaption
, const ScAddress
& rPos
)
96 // pass true to ScDrawLayer::GetObjData() to create the object data entry
97 ScDrawObjData
* pObjData
= ScDrawLayer::GetObjData( &rCaption
, true );
98 OSL_ENSURE( pObjData
, "ScCaptionUtil::SetCaptionUserData - missing drawing object user data" );
99 pObjData
->maStart
= rPos
;
100 pObjData
->meType
= ScDrawObjData::CellNote
;
103 void ScCaptionUtil::SetDefaultItems( SdrCaptionObj
& rCaption
, ScDocument
& rDoc
)
105 SfxItemSet aItemSet
= rCaption
.GetMergedItemSet();
107 // caption tail arrow
108 ::basegfx::B2DPolygon aTriangle
;
109 aTriangle
.append( ::basegfx::B2DPoint( 10.0, 0.0 ) );
110 aTriangle
.append( ::basegfx::B2DPoint( 0.0, 30.0 ) );
111 aTriangle
.append( ::basegfx::B2DPoint( 20.0, 30.0 ) );
112 aTriangle
.setClosed( true );
113 /* Line ends are now created with an empty name. The
114 checkForUniqueItem() method then finds a unique name for the item's
116 aItemSet
.Put( XLineStartItem( OUString(), ::basegfx::B2DPolyPolygon( aTriangle
) ) );
117 aItemSet
.Put( XLineStartWidthItem( 200 ) );
118 aItemSet
.Put( XLineStartCenterItem( false ) );
119 aItemSet
.Put( XFillStyleItem( drawing::FillStyle_SOLID
) );
120 aItemSet
.Put( XFillColorItem( OUString(), ScDetectiveFunc::GetCommentColor() ) );
121 aItemSet
.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT
) );
124 /* SdrShadowItem has sal_False, instead the shadow is set for the
125 rectangle only with SetSpecialTextBoxShadow() when the object is
126 created (item must be set to adjust objects from older files). */
127 aItemSet
.Put( makeSdrShadowItem( false ) );
128 aItemSet
.Put( makeSdrShadowXDistItem( 100 ) );
129 aItemSet
.Put( makeSdrShadowYDistItem( 100 ) );
132 aItemSet
.Put( makeSdrTextLeftDistItem( 100 ) );
133 aItemSet
.Put( makeSdrTextRightDistItem( 100 ) );
134 aItemSet
.Put( makeSdrTextUpperDistItem( 100 ) );
135 aItemSet
.Put( makeSdrTextLowerDistItem( 100 ) );
136 aItemSet
.Put( makeSdrTextAutoGrowWidthItem( false ) );
137 aItemSet
.Put( makeSdrTextAutoGrowHeightItem( true ) );
138 // use the default cell style to be able to modify the caption font
139 const ScPatternAttr
& rDefPattern
= static_cast< const ScPatternAttr
& >( rDoc
.GetPool()->GetDefaultItem( ATTR_PATTERN
) );
140 rDefPattern
.FillEditItemSet( &aItemSet
);
142 rCaption
.SetMergedItemSet( aItemSet
);
145 void ScCaptionUtil::SetCaptionItems( SdrCaptionObj
& rCaption
, const SfxItemSet
& rItemSet
)
148 rCaption
.SetMergedItemSet( rItemSet
);
149 // reset shadow items
150 rCaption
.SetMergedItem( makeSdrShadowItem( false ) );
151 rCaption
.SetMergedItem( makeSdrShadowXDistItem( 100 ) );
152 rCaption
.SetMergedItem( makeSdrShadowYDistItem( 100 ) );
153 rCaption
.SetSpecialTextBoxShadow();
156 /** Helper for creation and manipulation of caption drawing objects independent
157 from cell annotations. */
158 class ScCaptionCreator
161 /** Create a new caption. The caption will not be inserted into the document. */
162 explicit ScCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, bool bShown
, bool bTailFront
);
163 /** Manipulate an existing caption. */
164 explicit ScCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, SdrCaptionObj
& rCaption
);
166 /** Returns the drawing layer page of the sheet contained in maPos. */
167 SdrPage
* GetDrawPage();
168 /** Returns the caption drawing object. */
169 inline SdrCaptionObj
* GetCaption() { return mpCaption
; }
171 /** Moves the caption inside the passed rectangle. Uses page area if 0 is passed. */
172 void FitCaptionToRect( const Rectangle
* pVisRect
= 0 );
173 /** Places the caption inside the passed rectangle, tries to keep the cell rectangle uncovered. Uses page area if 0 is passed. */
174 void AutoPlaceCaption( const Rectangle
* pVisRect
= 0 );
175 /** Updates caption tail and textbox according to current cell position. Uses page area if 0 is passed. */
176 void UpdateCaptionPos( const Rectangle
* pVisRect
= 0 );
179 /** Helper constructor for derived classes. */
180 explicit ScCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
);
182 /** Calculates the caption tail position according to current cell position. */
183 Point
CalcTailPos( bool bTailFront
);
184 /** Implements creation of the caption object. The caption will not be inserted into the document. */
185 void CreateCaption( bool bShown
, bool bTailFront
);
188 /** Initializes all members. */
190 /** Returns the passed rectangle if existing, page rectangle otherwise. */
191 inline const Rectangle
& GetVisRect( const Rectangle
* pVisRect
) const { return pVisRect
? *pVisRect
: maPageRect
; }
196 SdrCaptionObj
* mpCaption
;
197 Rectangle maPageRect
;
198 Rectangle maCellRect
;
202 ScCaptionCreator::ScCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, bool bShown
, bool bTailFront
) :
208 CreateCaption( bShown
, bTailFront
);
211 ScCaptionCreator::ScCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, SdrCaptionObj
& rCaption
) :
214 mpCaption( &rCaption
)
219 ScCaptionCreator::ScCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
) :
227 SdrPage
* ScCaptionCreator::GetDrawPage()
229 ScDrawLayer
* pDrawLayer
= mrDoc
.GetDrawLayer();
230 return pDrawLayer
? pDrawLayer
->GetPage( static_cast< sal_uInt16
>( maPos
.Tab() ) ) : 0;
233 void ScCaptionCreator::FitCaptionToRect( const Rectangle
* pVisRect
)
235 const Rectangle
& rVisRect
= GetVisRect( pVisRect
);
238 Point aTailPos
= mpCaption
->GetTailPos();
239 aTailPos
.X() = ::std::max( ::std::min( aTailPos
.X(), rVisRect
.Right() ), rVisRect
.Left() );
240 aTailPos
.Y() = ::std::max( ::std::min( aTailPos
.Y(), rVisRect
.Bottom() ), rVisRect
.Top() );
241 mpCaption
->SetTailPos( aTailPos
);
244 Rectangle aCaptRect
= mpCaption
->GetLogicRect();
245 Point aCaptPos
= aCaptRect
.TopLeft();
246 // move textbox inside right border of visible area
247 aCaptPos
.X() = ::std::min
< long >( aCaptPos
.X(), rVisRect
.Right() - aCaptRect
.GetWidth() );
248 // move textbox inside left border of visible area (this may move it outside on right side again)
249 aCaptPos
.X() = ::std::max
< long >( aCaptPos
.X(), rVisRect
.Left() );
250 // move textbox inside bottom border of visible area
251 aCaptPos
.Y() = ::std::min
< long >( aCaptPos
.Y(), rVisRect
.Bottom() - aCaptRect
.GetHeight() );
252 // move textbox inside top border of visible area (this may move it outside on bottom side again)
253 aCaptPos
.Y() = ::std::max
< long >( aCaptPos
.Y(), rVisRect
.Top() );
255 aCaptRect
.SetPos( aCaptPos
);
256 mpCaption
->SetLogicRect( aCaptRect
);
259 void ScCaptionCreator::AutoPlaceCaption( const Rectangle
* pVisRect
)
261 const Rectangle
& rVisRect
= GetVisRect( pVisRect
);
264 Rectangle aCaptRect
= mpCaption
->GetLogicRect();
265 long nWidth
= aCaptRect
.GetWidth();
266 long nHeight
= aCaptRect
.GetHeight();
268 // n***Space contains available space between border of visible area and cell
269 long nLeftSpace
= maCellRect
.Left() - rVisRect
.Left() + 1;
270 long nRightSpace
= rVisRect
.Right() - maCellRect
.Right() + 1;
271 long nTopSpace
= maCellRect
.Top() - rVisRect
.Top() + 1;
272 long nBottomSpace
= rVisRect
.Bottom() - maCellRect
.Bottom() + 1;
274 // nNeeded*** contains textbox dimensions plus needed distances to cell or border of visible area
275 long nNeededSpaceX
= nWidth
+ SC_NOTECAPTION_CELLDIST
;
276 long nNeededSpaceY
= nHeight
+ SC_NOTECAPTION_CELLDIST
;
278 // bFitsWidth*** == true means width of textbox fits into horizontal free space of visible area
279 bool bFitsWidthLeft
= nNeededSpaceX
<= nLeftSpace
; // text box width fits into the width left of cell
280 bool bFitsWidthRight
= nNeededSpaceX
<= nRightSpace
; // text box width fits into the width right of cell
281 bool bFitsWidth
= nWidth
<= rVisRect
.GetWidth(); // text box width fits into width of visible area
283 // bFitsHeight*** == true means height of textbox fits into vertical free space of visible area
284 bool bFitsHeightTop
= nNeededSpaceY
<= nTopSpace
; // text box height fits into the height above cell
285 bool bFitsHeightBottom
= nNeededSpaceY
<= nBottomSpace
; // text box height fits into the height below cell
286 bool bFitsHeight
= nHeight
<= rVisRect
.GetHeight(); // text box height fits into height of visible area
288 // bFits*** == true means the textbox fits completely into free space of visible area
289 bool bFitsLeft
= bFitsWidthLeft
&& bFitsHeight
;
290 bool bFitsRight
= bFitsWidthRight
&& bFitsHeight
;
291 bool bFitsTop
= bFitsWidth
&& bFitsHeightTop
;
292 bool bFitsBottom
= bFitsWidth
&& bFitsHeightBottom
;
295 // use left/right placement if possible, or if top/bottom placement not possible
296 if( bFitsLeft
|| bFitsRight
|| (!bFitsTop
&& !bFitsBottom
) )
298 // prefer left in RTL sheet and right in LTR sheets
299 bool bPreferLeft
= bFitsLeft
&& (mbNegPage
|| !bFitsRight
);
300 bool bPreferRight
= bFitsRight
&& (!mbNegPage
|| !bFitsLeft
);
301 // move to left, if left is preferred, or if neither left nor right fit and there is more space to the left
302 if( bPreferLeft
|| (!bPreferRight
&& (nLeftSpace
> nRightSpace
)) )
303 aCaptPos
.X() = maCellRect
.Left() - SC_NOTECAPTION_CELLDIST
- nWidth
;
305 aCaptPos
.X() = maCellRect
.Right() + SC_NOTECAPTION_CELLDIST
;
306 // Y position according to top cell border
307 aCaptPos
.Y() = maCellRect
.Top() + SC_NOTECAPTION_OFFSET_Y
;
309 else // top or bottom placement
312 aCaptPos
.X() = maCellRect
.Left() + SC_NOTECAPTION_OFFSET_X
;
313 // top placement, if possible
315 aCaptPos
.Y() = maCellRect
.Top() - SC_NOTECAPTION_CELLDIST
- nHeight
;
316 else // bottom placement
317 aCaptPos
.Y() = maCellRect
.Bottom() + SC_NOTECAPTION_CELLDIST
;
320 // update textbox position in note caption object
321 aCaptRect
.SetPos( aCaptPos
);
322 mpCaption
->SetLogicRect( aCaptRect
);
323 FitCaptionToRect( pVisRect
);
326 void ScCaptionCreator::UpdateCaptionPos( const Rectangle
* pVisRect
)
328 ScDrawLayer
* pDrawLayer
= mrDoc
.GetDrawLayer();
330 // update caption position
331 const Point
& rOldTailPos
= mpCaption
->GetTailPos();
332 Point aTailPos
= CalcTailPos( false );
333 if( rOldTailPos
!= aTailPos
)
335 // create drawing undo action
336 if( pDrawLayer
&& pDrawLayer
->IsRecording() )
337 pDrawLayer
->AddCalcUndo( new SdrUndoGeoObj( *mpCaption
) );
338 // calculate new caption rectangle (#i98141# handle LTR<->RTL switch correctly)
339 Rectangle aCaptRect
= mpCaption
->GetLogicRect();
340 long nDiffX
= (rOldTailPos
.X() >= 0) ? (aCaptRect
.Left() - rOldTailPos
.X()) : (rOldTailPos
.X() - aCaptRect
.Right());
341 if( mbNegPage
) nDiffX
= -nDiffX
- aCaptRect
.GetWidth();
342 long nDiffY
= aCaptRect
.Top() - rOldTailPos
.Y();
343 aCaptRect
.SetPos( aTailPos
+ Point( nDiffX
, nDiffY
) );
344 // set new tail position and caption rectangle
345 mpCaption
->SetTailPos( aTailPos
);
346 mpCaption
->SetLogicRect( aCaptRect
);
347 // fit caption into draw page
348 FitCaptionToRect( pVisRect
);
351 // update cell position in caption user data
352 ScDrawObjData
* pCaptData
= ScDrawLayer::GetNoteCaptionData( mpCaption
, maPos
.Tab() );
353 if( pCaptData
&& (maPos
!= pCaptData
->maStart
) )
355 // create drawing undo action
356 if( pDrawLayer
&& pDrawLayer
->IsRecording() )
357 pDrawLayer
->AddCalcUndo( new ScUndoObjData( mpCaption
, pCaptData
->maStart
, pCaptData
->maEnd
, maPos
, pCaptData
->maEnd
) );
359 pCaptData
->maStart
= maPos
;
363 Point
ScCaptionCreator::CalcTailPos( bool bTailFront
)
366 bool bTailLeft
= bTailFront
!= mbNegPage
;
367 Point aTailPos
= bTailLeft
? maCellRect
.TopLeft() : maCellRect
.TopRight();
368 // move caption point 1/10 mm inside cell
369 if( bTailLeft
) aTailPos
.X() += 10; else aTailPos
.X() -= 10;
374 void ScCaptionCreator::CreateCaption( bool bShown
, bool bTailFront
)
376 // create the caption drawing object
377 Rectangle
aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH
, SC_NOTECAPTION_HEIGHT
) );
378 Point aTailPos
= CalcTailPos( bTailFront
);
379 mpCaption
= new SdrCaptionObj( aTextRect
, aTailPos
);
380 // basic caption settings
381 ScCaptionUtil::SetBasicCaptionSettings( *mpCaption
, bShown
);
384 void ScCaptionCreator::Initialize()
386 maCellRect
= ScDrawLayer::GetCellRect( mrDoc
, maPos
, true );
387 mbNegPage
= mrDoc
.IsNegativePage( maPos
.Tab() );
388 if( SdrPage
* pDrawPage
= GetDrawPage() )
390 maPageRect
= Rectangle( Point( 0, 0 ), pDrawPage
->GetSize() );
391 /* #i98141# SdrPage::GetSize() returns negative width in RTL mode.
392 The call to Rectangle::Adjust() orders left/right coordinate
394 maPageRect
.Justify();
398 /** Helper for creation of permanent caption drawing objects for cell notes. */
399 class ScNoteCaptionCreator
: public ScCaptionCreator
402 /** Create a new caption object and inserts it into the document. */
403 explicit ScNoteCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, ScNoteData
& rNoteData
);
404 /** Manipulate an existing caption. */
405 explicit ScNoteCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, SdrCaptionObj
& rCaption
, bool bShown
);
408 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, ScNoteData
& rNoteData
) :
409 ScCaptionCreator( rDoc
, rPos
) // use helper c'tor that does not create the caption yet
411 SdrPage
* pDrawPage
= GetDrawPage();
412 OSL_ENSURE( pDrawPage
, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
415 // create the caption drawing object
416 CreateCaption( rNoteData
.mbShown
, false );
417 rNoteData
.mpCaption
= GetCaption();
418 OSL_ENSURE( rNoteData
.mpCaption
, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" );
419 if( rNoteData
.mpCaption
)
421 // store note position in user data of caption object
422 ScCaptionUtil::SetCaptionUserData( *rNoteData
.mpCaption
, rPos
);
423 // insert object into draw page
424 pDrawPage
->InsertObject( rNoteData
.mpCaption
);
429 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument
& rDoc
, const ScAddress
& rPos
, SdrCaptionObj
& rCaption
, bool bShown
) :
430 ScCaptionCreator( rDoc
, rPos
, rCaption
)
432 SdrPage
* pDrawPage
= GetDrawPage();
433 OSL_ENSURE( pDrawPage
, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
434 OSL_ENSURE( rCaption
.GetPage() == pDrawPage
, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" );
435 if( pDrawPage
&& (rCaption
.GetPage() == pDrawPage
) )
437 // store note position in user data of caption object
438 ScCaptionUtil::SetCaptionUserData( rCaption
, rPos
);
439 // basic caption settings
440 ScCaptionUtil::SetBasicCaptionSettings( rCaption
, bShown
);
441 // set correct tail position
442 rCaption
.SetTailPos( CalcTailPos( false ) );
448 struct ScCaptionInitData
450 typedef ::std::unique_ptr
< SfxItemSet
> SfxItemSetPtr
;
451 typedef ::std::unique_ptr
< OutlinerParaObject
> OutlinerParaObjPtr
;
453 SfxItemSetPtr mxItemSet
; /// Caption object formatting.
454 OutlinerParaObjPtr mxOutlinerObj
; /// Text object with all text portion formatting.
455 OUString maSimpleText
; /// Simple text without formatting.
456 Point maCaptionOffset
; /// Caption position relative to cell corner.
457 Size maCaptionSize
; /// Size of the caption object.
458 bool mbDefaultPosSize
; /// True = use default position and size for caption.
460 explicit ScCaptionInitData();
463 ScCaptionInitData::ScCaptionInitData() :
464 mbDefaultPosSize( true )
468 ScNoteData::ScNoteData( bool bShown
) :
474 ScNoteData::~ScNoteData()
478 ScPostIt::ScPostIt( ScDocument
& rDoc
, const ScAddress
& rPos
, bool bShown
) :
483 CreateCaption( rPos
);
486 ScPostIt::ScPostIt( ScDocument
& rDoc
, const ScAddress
& rPos
, const ScPostIt
& rNote
) :
488 maNoteData( rNote
.maNoteData
)
490 maNoteData
.mpCaption
= 0;
491 CreateCaption( rPos
, rNote
.maNoteData
.mpCaption
);
494 ScPostIt::ScPostIt( ScDocument
& rDoc
, const ScAddress
& rPos
, const ScNoteData
& rNoteData
, bool bAlwaysCreateCaption
) :
496 maNoteData( rNoteData
)
498 if( bAlwaysCreateCaption
|| maNoteData
.mbShown
)
499 CreateCaptionFromInitData( rPos
);
502 ScPostIt::~ScPostIt()
507 ScPostIt
* ScPostIt::Clone( const ScAddress
& rOwnPos
, ScDocument
& rDestDoc
, const ScAddress
& rDestPos
, bool bCloneCaption
) const
509 CreateCaptionFromInitData( rOwnPos
);
510 return bCloneCaption
? new ScPostIt( rDestDoc
, rDestPos
, *this ) : new ScPostIt( rDestDoc
, rDestPos
, maNoteData
, false );
513 void ScPostIt::SetDate( const OUString
& rDate
)
515 maNoteData
.maDate
= rDate
;
518 void ScPostIt::SetAuthor( const OUString
& rAuthor
)
520 maNoteData
.maAuthor
= rAuthor
;
523 void ScPostIt::AutoStamp()
525 maNoteData
.maDate
= ScGlobal::pLocaleData
->getDate( Date( Date::SYSTEM
) );
526 maNoteData
.maAuthor
= SvtUserOptions().GetID();
529 const OutlinerParaObject
* ScPostIt::GetOutlinerObject() const
531 if( maNoteData
.mpCaption
)
532 return maNoteData
.mpCaption
->GetOutlinerParaObject();
533 if( maNoteData
.mxInitData
.get() )
534 return maNoteData
.mxInitData
->mxOutlinerObj
.get();
538 const EditTextObject
* ScPostIt::GetEditTextObject() const
540 const OutlinerParaObject
* pOPO
= GetOutlinerObject();
541 return pOPO
? &pOPO
->GetTextObject() : 0;
544 OUString
ScPostIt::GetText() const
546 if( const EditTextObject
* pEditObj
= GetEditTextObject() )
548 OUStringBuffer aBuffer
;
549 ScNoteEditEngine
& rEngine
= mrDoc
.GetNoteEngine();
550 rEngine
.SetText(*pEditObj
);
551 sal_Int32 nParaCount
= rEngine
.GetParagraphCount();
552 for( sal_Int32 nPara
= 0; nPara
< nParaCount
; ++nPara
)
555 aBuffer
.append( '\n' );
556 aBuffer
.append(rEngine
.GetText(nPara
));
558 return aBuffer
.makeStringAndClear();
560 if( maNoteData
.mxInitData
.get() )
561 return maNoteData
.mxInitData
->maSimpleText
;
565 void ScPostIt::SetText( const ScAddress
& rPos
, const OUString
& rText
)
567 CreateCaptionFromInitData( rPos
);
568 if( maNoteData
.mpCaption
)
569 maNoteData
.mpCaption
->SetText( rText
);
572 SdrCaptionObj
* ScPostIt::GetOrCreateCaption( const ScAddress
& rPos
) const
574 CreateCaptionFromInitData( rPos
);
575 return maNoteData
.mpCaption
;
578 void ScPostIt::ForgetCaption()
580 /* This function is used in undo actions to give up the responsibility for
581 the caption object which is handled by separate drawing undo actions. */
582 maNoteData
.mpCaption
= 0;
583 maNoteData
.mxInitData
.reset();
586 void ScPostIt::ShowCaption( const ScAddress
& rPos
, bool bShow
)
588 CreateCaptionFromInitData( rPos
);
589 // no separate drawing undo needed, handled completely inside ScUndoShowHideNote
590 maNoteData
.mbShown
= bShow
;
591 if( maNoteData
.mpCaption
)
592 ScCaptionUtil::SetCaptionLayer( *maNoteData
.mpCaption
, bShow
);
595 void ScPostIt::ShowCaptionTemp( const ScAddress
& rPos
, bool bShow
)
597 CreateCaptionFromInitData( rPos
);
598 if( maNoteData
.mpCaption
)
599 ScCaptionUtil::SetCaptionLayer( *maNoteData
.mpCaption
, maNoteData
.mbShown
|| bShow
);
602 void ScPostIt::UpdateCaptionPos( const ScAddress
& rPos
)
604 CreateCaptionFromInitData( rPos
);
605 if( maNoteData
.mpCaption
)
607 ScCaptionCreator
aCreator( mrDoc
, rPos
, *maNoteData
.mpCaption
);
608 aCreator
.UpdateCaptionPos();
612 // private --------------------------------------------------------------------
614 void ScPostIt::CreateCaptionFromInitData( const ScAddress
& rPos
) const
616 OSL_ENSURE( maNoteData
.mpCaption
|| maNoteData
.mxInitData
.get(), "ScPostIt::CreateCaptionFromInitData - need caption object or initial caption data" );
617 if( maNoteData
.mxInitData
.get() )
619 /* This function is called from ScPostIt::Clone() when copying cells
620 to the clipboard/undo document, and when copying cells from the
621 clipboard/undo document. The former should always be called first,
622 so if called in an clipboard/undo document, the caption should have
623 been created already. */
624 OSL_ENSURE( !mrDoc
.IsUndo() && !mrDoc
.IsClipboard(), "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" );
626 /* #i104915# Never try to create notes in Undo document, leads to
627 crash due to missing document members (e.g. row height array). */
628 if( !maNoteData
.mpCaption
&& !mrDoc
.IsUndo() )
630 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
631 ScNoteCaptionCreator
aCreator( mrDoc
, rPos
, maNoteData
);
632 if( maNoteData
.mpCaption
)
634 ScCaptionInitData
& rInitData
= *maNoteData
.mxInitData
;
636 // transfer ownership of outliner object to caption, or set simple text
637 OSL_ENSURE( rInitData
.mxOutlinerObj
.get() || !rInitData
.maSimpleText
.isEmpty(),
638 "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" );
639 if( rInitData
.mxOutlinerObj
.get() )
640 maNoteData
.mpCaption
->SetOutlinerParaObject( rInitData
.mxOutlinerObj
.release() );
642 maNoteData
.mpCaption
->SetText( rInitData
.maSimpleText
);
644 // copy all items or set default items; reset shadow items
645 ScCaptionUtil::SetDefaultItems( *maNoteData
.mpCaption
, mrDoc
);
646 if( rInitData
.mxItemSet
.get() )
647 ScCaptionUtil::SetCaptionItems( *maNoteData
.mpCaption
, *rInitData
.mxItemSet
);
649 // set position and size of the caption object
650 if( rInitData
.mbDefaultPosSize
)
652 // set other items and fit caption size to text
653 maNoteData
.mpCaption
->SetMergedItem( makeSdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH
) );
654 maNoteData
.mpCaption
->SetMergedItem( makeSdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP
) );
655 maNoteData
.mpCaption
->AdjustTextFrameWidthAndHeight();
656 aCreator
.AutoPlaceCaption();
660 Rectangle aCellRect
= ScDrawLayer::GetCellRect( mrDoc
, rPos
, true );
661 bool bNegPage
= mrDoc
.IsNegativePage( rPos
.Tab() );
662 long nPosX
= bNegPage
? (aCellRect
.Left() - rInitData
.maCaptionOffset
.X()) : (aCellRect
.Right() + rInitData
.maCaptionOffset
.X());
663 long nPosY
= aCellRect
.Top() + rInitData
.maCaptionOffset
.Y();
664 Rectangle
aCaptRect( Point( nPosX
, nPosY
), rInitData
.maCaptionSize
);
665 maNoteData
.mpCaption
->SetLogicRect( aCaptRect
);
666 aCreator
.FitCaptionToRect();
670 // forget the initial caption data struct
671 maNoteData
.mxInitData
.reset();
675 void ScPostIt::CreateCaption( const ScAddress
& rPos
, const SdrCaptionObj
* pCaption
)
677 OSL_ENSURE( !maNoteData
.mpCaption
, "ScPostIt::CreateCaption - unexpected caption object found" );
678 maNoteData
.mpCaption
= 0;
680 /* #i104915# Never try to create notes in Undo document, leads to
681 crash due to missing document members (e.g. row height array). */
682 OSL_ENSURE( !mrDoc
.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" );
686 // drawing layer may be missing, if a note is copied into a clipboard document
687 if( mrDoc
.IsClipboard() )
688 mrDoc
.InitDrawLayer();
690 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
691 ScNoteCaptionCreator
aCreator( mrDoc
, rPos
, maNoteData
);
692 if( maNoteData
.mpCaption
)
694 // clone settings of passed caption
697 // copy edit text object (object must be inserted into page already)
698 if( OutlinerParaObject
* pOPO
= pCaption
->GetOutlinerParaObject() )
699 maNoteData
.mpCaption
->SetOutlinerParaObject( new OutlinerParaObject( *pOPO
) );
700 // copy formatting items (after text has been copied to apply font formatting)
701 maNoteData
.mpCaption
->SetMergedItemSetAndBroadcast( pCaption
->GetMergedItemSet() );
702 // move textbox position relative to new cell, copy textbox size
703 Rectangle aCaptRect
= pCaption
->GetLogicRect();
704 Point aDist
= maNoteData
.mpCaption
->GetTailPos() - pCaption
->GetTailPos();
705 aCaptRect
.Move( aDist
.X(), aDist
.Y() );
706 maNoteData
.mpCaption
->SetLogicRect( aCaptRect
);
707 aCreator
.FitCaptionToRect();
711 // set default formatting and default position
712 ScCaptionUtil::SetDefaultItems( *maNoteData
.mpCaption
, mrDoc
);
713 aCreator
.AutoPlaceCaption();
716 // create undo action
717 if( ScDrawLayer
* pDrawLayer
= mrDoc
.GetDrawLayer() )
718 if( pDrawLayer
->IsRecording() )
719 pDrawLayer
->AddCalcUndo( new SdrUndoNewObj( *maNoteData
.mpCaption
) );
723 void ScPostIt::RemoveCaption()
726 /* Remove caption object only, if this note is its owner (e.g. notes in
727 undo documents refer to captions in original document, do not remove
728 them from drawing layer here). */
729 ScDrawLayer
* pDrawLayer
= mrDoc
.GetDrawLayer();
730 if( maNoteData
.mpCaption
&& (pDrawLayer
== maNoteData
.mpCaption
->GetModel()) )
732 OSL_ENSURE( pDrawLayer
, "ScPostIt::RemoveCaption - object without drawing layer" );
733 SdrPage
* pDrawPage
= maNoteData
.mpCaption
->GetPage();
734 OSL_ENSURE( pDrawPage
, "ScPostIt::RemoveCaption - object without drawing page" );
737 pDrawPage
->RecalcObjOrdNums();
738 // create drawing undo action (before removing the object to have valid draw page in undo action)
739 bool bRecording
= ( pDrawLayer
&& pDrawLayer
->IsRecording() );
741 pDrawLayer
->AddCalcUndo( new SdrUndoDelObj( *maNoteData
.mpCaption
) );
742 // remove the object from the drawing page, delete if undo is disabled
743 SdrObject
* pObj
= pDrawPage
->RemoveObject( maNoteData
.mpCaption
->GetOrdNum() );
745 SdrObject::Free( pObj
);
748 maNoteData
.mpCaption
= 0;
751 SdrCaptionObj
* ScNoteUtil::CreateTempCaption(
752 ScDocument
& rDoc
, const ScAddress
& rPos
, SdrPage
& rDrawPage
,
753 const OUString
& rUserText
, const Rectangle
& rVisRect
, bool bTailFront
)
755 OUStringBuffer
aBuffer( rUserText
);
756 // add plain text of invisible (!) cell note (no formatting etc.)
757 SdrCaptionObj
* pNoteCaption
= 0;
758 const ScPostIt
* pNote
= rDoc
.GetNote( rPos
);
759 if( pNote
&& !pNote
->IsCaptionShown() )
761 if( !aBuffer
.isEmpty() )
762 aBuffer
.append( "\n--------\n" ).append( pNote
->GetText() );
763 pNoteCaption
= pNote
->GetOrCreateCaption( rPos
);
766 // create a caption if any text exists
767 if( !pNoteCaption
&& aBuffer
.isEmpty() )
770 // prepare visible rectangle (add default distance to all borders)
772 rVisRect
.Left() + SC_NOTECAPTION_BORDERDIST_TEMP
,
773 rVisRect
.Top() + SC_NOTECAPTION_BORDERDIST_TEMP
,
774 rVisRect
.Right() - SC_NOTECAPTION_BORDERDIST_TEMP
,
775 rVisRect
.Bottom() - SC_NOTECAPTION_BORDERDIST_TEMP
);
777 // create the caption object
778 ScCaptionCreator
aCreator( rDoc
, rPos
, true, bTailFront
);
779 SdrCaptionObj
* pCaption
= aCreator
.GetCaption();
781 // insert caption into page (needed to set caption text)
782 rDrawPage
.InsertObject( pCaption
);
784 // clone the edit text object, unless user text is present, then set this text
785 if( pNoteCaption
&& rUserText
.isEmpty() )
787 if( OutlinerParaObject
* pOPO
= pNoteCaption
->GetOutlinerParaObject() )
788 pCaption
->SetOutlinerParaObject( new OutlinerParaObject( *pOPO
) );
789 // set formatting (must be done after setting text) and resize the box to fit the text
790 pCaption
->SetMergedItemSetAndBroadcast( pNoteCaption
->GetMergedItemSet() );
791 Rectangle
aCaptRect( pCaption
->GetLogicRect().TopLeft(), pNoteCaption
->GetLogicRect().GetSize() );
792 pCaption
->SetLogicRect( aCaptRect
);
796 // if pNoteCaption is null, then aBuffer contains some text
797 pCaption
->SetText( aBuffer
.makeStringAndClear() );
798 ScCaptionUtil::SetDefaultItems( *pCaption
, rDoc
);
799 // adjust caption size to text size
800 long nMaxWidth
= ::std::min
< long >( aVisRect
.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP
);
801 pCaption
->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
802 pCaption
->SetMergedItem( makeSdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH
) );
803 pCaption
->SetMergedItem( makeSdrTextMaxFrameWidthItem( nMaxWidth
) );
804 pCaption
->SetMergedItem( makeSdrTextAutoGrowHeightItem( true ) );
805 pCaption
->AdjustTextFrameWidthAndHeight();
808 // move caption into visible area
809 aCreator
.AutoPlaceCaption( &aVisRect
);
813 ScPostIt
* ScNoteUtil::CreateNoteFromCaption(
814 ScDocument
& rDoc
, const ScAddress
& rPos
, SdrCaptionObj
& rCaption
, bool bShown
)
816 ScNoteData
aNoteData( bShown
);
817 aNoteData
.mpCaption
= &rCaption
;
818 ScPostIt
* pNote
= new ScPostIt( rDoc
, rPos
, aNoteData
, false );
821 rDoc
.SetNote(rPos
, pNote
);
823 // ScNoteCaptionCreator c'tor updates the caption object to be part of a note
824 ScNoteCaptionCreator
aCreator( rDoc
, rPos
, rCaption
, bShown
);
829 ScPostIt
* ScNoteUtil::CreateNoteFromObjectData(
830 ScDocument
& rDoc
, const ScAddress
& rPos
, SfxItemSet
* pItemSet
,
831 OutlinerParaObject
* pOutlinerObj
, const Rectangle
& rCaptionRect
,
832 bool bShown
, bool bAlwaysCreateCaption
)
834 OSL_ENSURE( pItemSet
&& pOutlinerObj
, "ScNoteUtil::CreateNoteFromObjectData - item set and outliner object expected" );
835 ScNoteData
aNoteData( bShown
);
836 aNoteData
.mxInitData
.reset( new ScCaptionInitData
);
837 ScCaptionInitData
& rInitData
= *aNoteData
.mxInitData
;
838 rInitData
.mxItemSet
.reset( pItemSet
);
839 rInitData
.mxOutlinerObj
.reset( pOutlinerObj
);
841 // convert absolute caption position to relative position
842 rInitData
.mbDefaultPosSize
= rCaptionRect
.IsEmpty();
843 if( !rInitData
.mbDefaultPosSize
)
845 Rectangle aCellRect
= ScDrawLayer::GetCellRect( rDoc
, rPos
, true );
846 bool bNegPage
= rDoc
.IsNegativePage( rPos
.Tab() );
847 rInitData
.maCaptionOffset
.X() = bNegPage
? (aCellRect
.Left() - rCaptionRect
.Right()) : (rCaptionRect
.Left() - aCellRect
.Right());
848 rInitData
.maCaptionOffset
.Y() = rCaptionRect
.Top() - aCellRect
.Top();
849 rInitData
.maCaptionSize
= rCaptionRect
.GetSize();
852 /* Create the note and insert it into the document. If the note is
853 visible, the caption object will be created automatically. */
854 ScPostIt
* pNote
= new ScPostIt( rDoc
, rPos
, aNoteData
, bAlwaysCreateCaption
);
857 rDoc
.SetNote(rPos
, pNote
);
862 ScPostIt
* ScNoteUtil::CreateNoteFromString(
863 ScDocument
& rDoc
, const ScAddress
& rPos
, const OUString
& rNoteText
,
864 bool bShown
, bool bAlwaysCreateCaption
)
867 if( !rNoteText
.isEmpty() )
869 ScNoteData
aNoteData( bShown
);
870 aNoteData
.mxInitData
.reset( new ScCaptionInitData
);
871 ScCaptionInitData
& rInitData
= *aNoteData
.mxInitData
;
872 rInitData
.maSimpleText
= rNoteText
;
873 rInitData
.mbDefaultPosSize
= true;
875 /* Create the note and insert it into the document. If the note is
876 visible, the caption object will be created automatically. */
877 pNote
= new ScPostIt( rDoc
, rPos
, aNoteData
, bAlwaysCreateCaption
);
879 //insert takes ownership
880 rDoc
.SetNote(rPos
, pNote
);
887 NoteEntry::NoteEntry( const ScAddress
& rPos
, const ScPostIt
* pNote
) :
888 maPos(rPos
), mpNote(pNote
) {}
892 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */