Update ooo320-m1
[ooovba.git] / sc / source / core / data / postit.cxx
blob7a08f352ed916ad6c3b15d149d9279b47522228d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: postit.cxx,v $
10 * $Revision: 1.12.54.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "postit.hxx"
36 #include <rtl/ustrbuf.hxx>
37 #include <svtools/useroptions.hxx>
38 #include <svx/svdpage.hxx>
39 #include <svx/svdocapt.hxx>
40 #include <svx/outlobj.hxx>
41 #include <svx/editobj.hxx>
42 #include <basegfx/polygon/b2dpolygon.hxx>
44 #include "scitems.hxx"
45 #include <svx/xlnstit.hxx>
46 #include <svx/xlnstwit.hxx>
47 #include <svx/xlnstcit.hxx>
48 #include <svx/sxcecitm.hxx>
49 #include <svx/xflclit.hxx>
50 #include <svx/sdshitm.hxx>
51 #include <svx/sdsxyitm.hxx>
53 #include "document.hxx"
54 #include "docpool.hxx"
55 #include "patattr.hxx"
56 #include "cell.hxx"
57 #include "drwlayer.hxx"
58 #include "userdat.hxx"
59 #include "detfunc.hxx"
61 using ::rtl::OUString;
62 using ::rtl::OUStringBuffer;
64 // ============================================================================
66 namespace {
68 const long SC_NOTECAPTION_WIDTH = 2900; /// Default width of note caption textbox.
69 const long SC_NOTECAPTION_MAXWIDTH_TEMP = 12000; /// Maximum width of temporary note caption textbox.
70 const long SC_NOTECAPTION_HEIGHT = 1800; /// Default height of note caption textbox.
71 const long SC_NOTECAPTION_CELLDIST = 600; /// Default distance of note captions to border of anchor cell.
72 const long SC_NOTECAPTION_OFFSET_Y = -1500; /// Default Y offset of note captions to top border of anchor cell.
73 const long SC_NOTECAPTION_OFFSET_X = 1500; /// Default X offset of note captions to left border of anchor cell.
74 const long SC_NOTECAPTION_BORDERDIST_TEMP = 100; /// Distance of temporary note captions to visible sheet area.
76 // ============================================================================
78 /** Static helper functions for caption objects. */
79 class ScCaptionUtil
81 public:
82 /** Moves the caption object to the correct layer according to passed visibility. */
83 static void SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown );
84 /** Sets basic caption settings required for note caption objects. */
85 static void SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown );
86 /** Stores the cell position of the note in the user data area of the caption. */
87 static void SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos );
88 /** Sets all default formatting attributes to the caption object. */
89 static void SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc );
90 /** Updates caption item set according to the passed item set while removing shadow items. */
91 static void SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet );
94 // ----------------------------------------------------------------------------
96 void ScCaptionUtil::SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown )
98 SdrLayerID nLayer = bShown ? SC_LAYER_INTERN : SC_LAYER_HIDDEN;
99 if( nLayer != rCaption.GetLayer() )
100 rCaption.SetLayer( nLayer );
103 void ScCaptionUtil::SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown )
105 ScDrawLayer::SetAnchor( &rCaption, SCA_PAGE );
106 SetCaptionLayer( rCaption, bShown );
107 rCaption.SetFixedTail();
108 rCaption.SetSpecialTextBoxShadow();
111 void ScCaptionUtil::SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos )
113 // pass true to ScDrawLayer::GetObjData() to create the object data entry
114 ScDrawObjData* pObjData = ScDrawLayer::GetObjData( &rCaption, true );
115 OSL_ENSURE( pObjData, "ScCaptionUtil::SetCaptionUserData - missing drawing object user data" );
116 pObjData->maStart = rPos;
117 pObjData->mbNote = true;
120 void ScCaptionUtil::SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc )
122 SfxItemSet aItemSet = rCaption.GetMergedItemSet();
124 // caption tail arrow
125 ::basegfx::B2DPolygon aTriangle;
126 aTriangle.append( ::basegfx::B2DPoint( 10.0, 0.0 ) );
127 aTriangle.append( ::basegfx::B2DPoint( 0.0, 30.0 ) );
128 aTriangle.append( ::basegfx::B2DPoint( 20.0, 30.0 ) );
129 aTriangle.setClosed( true );
130 /* #99319# Line ends are now created with an empty name. The
131 checkForUniqueItem() method then finds a unique name for the item's
132 value. */
133 aItemSet.Put( XLineStartItem( String::EmptyString(), ::basegfx::B2DPolyPolygon( aTriangle ) ) );
134 aItemSet.Put( XLineStartWidthItem( 200 ) );
135 aItemSet.Put( XLineStartCenterItem( FALSE ) );
136 aItemSet.Put( XFillStyleItem( XFILL_SOLID ) );
137 aItemSet.Put( XFillColorItem( String::EmptyString(), ScDetectiveFunc::GetCommentColor() ) );
138 aItemSet.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT ) );
140 // shadow
141 /* SdrShadowItem has FALSE, instead the shadow is set for the
142 rectangle only with SetSpecialTextBoxShadow() when the object is
143 created (item must be set to adjust objects from older files). */
144 aItemSet.Put( SdrShadowItem( FALSE ) );
145 aItemSet.Put( SdrShadowXDistItem( 100 ) );
146 aItemSet.Put( SdrShadowYDistItem( 100 ) );
148 // text attributes
149 aItemSet.Put( SdrTextLeftDistItem( 100 ) );
150 aItemSet.Put( SdrTextRightDistItem( 100 ) );
151 aItemSet.Put( SdrTextUpperDistItem( 100 ) );
152 aItemSet.Put( SdrTextLowerDistItem( 100 ) );
153 aItemSet.Put( SdrTextAutoGrowWidthItem( FALSE ) );
154 aItemSet.Put( SdrTextAutoGrowHeightItem( TRUE ) );
155 // #78943# use the default cell style to be able to modify the caption font
156 const ScPatternAttr& rDefPattern = static_cast< const ScPatternAttr& >( rDoc.GetPool()->GetDefaultItem( ATTR_PATTERN ) );
157 rDefPattern.FillEditItemSet( &aItemSet );
159 rCaption.SetMergedItemSet( aItemSet );
162 void ScCaptionUtil::SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet )
164 // copy all items
165 rCaption.SetMergedItemSet( rItemSet );
166 // reset shadow items
167 rCaption.SetMergedItem( SdrShadowItem( FALSE ) );
168 rCaption.SetMergedItem( SdrShadowXDistItem( 100 ) );
169 rCaption.SetMergedItem( SdrShadowYDistItem( 100 ) );
170 rCaption.SetSpecialTextBoxShadow();
173 // ============================================================================
175 /** Helper for creation and manipulation of caption drawing objects independent
176 from cell annotations. */
177 class ScCaptionCreator
179 public:
180 /** Create a new caption. The caption will not be inserted into the document. */
181 explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bShown, bool bTailFront );
182 /** Manipulate an existing caption. */
183 explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption );
185 /** Returns the drawing layer page of the sheet contained in maPos. */
186 SdrPage* GetDrawPage();
187 /** Returns the caption drawing obejct. */
188 inline SdrCaptionObj* GetCaption() { return mpCaption; }
190 /** Moves the caption inside the passed rectangle. Uses page area if 0 is passed. */
191 void FitCaptionToRect( const Rectangle* pVisRect = 0 );
192 /** Places the caption inside the passed rectangle, tries to keep the cell rectangle uncovered. Uses page area if 0 is passed. */
193 void AutoPlaceCaption( const Rectangle* pVisRect = 0 );
194 /** Updates caption tail and textbox according to current cell position. Uses page area if 0 is passed. */
195 void UpdateCaptionPos( const Rectangle* pVisRect = 0 );
197 protected:
198 /** Helper constructor for derived classes. */
199 explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos );
201 /** Calculates the caption tail position according to current cell position. */
202 Point CalcTailPos( bool bTailFront );
203 /** Implements creation of the caption object. The caption will not be inserted into the document. */
204 void CreateCaption( bool bShown, bool bTailFront );
206 private:
207 /** Initializes all members. */
208 void Initialize();
209 /** Returns the passed rectangle if existing, page rectangle otherwise. */
210 inline const Rectangle& GetVisRect( const Rectangle* pVisRect ) const { return pVisRect ? *pVisRect : maPageRect; }
212 private:
213 ScDocument& mrDoc;
214 ScAddress maPos;
215 SdrCaptionObj* mpCaption;
216 Rectangle maPageRect;
217 Rectangle maCellRect;
218 bool mbNegPage;
221 // ----------------------------------------------------------------------------
223 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bShown, bool bTailFront ) :
224 mrDoc( rDoc ),
225 maPos( rPos ),
226 mpCaption( 0 )
228 Initialize();
229 CreateCaption( bShown, bTailFront );
232 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption ) :
233 mrDoc( rDoc ),
234 maPos( rPos ),
235 mpCaption( &rCaption )
237 Initialize();
240 ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos ) :
241 mrDoc( rDoc ),
242 maPos( rPos ),
243 mpCaption( 0 )
245 Initialize();
248 SdrPage* ScCaptionCreator::GetDrawPage()
250 ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
251 return pDrawLayer ? pDrawLayer->GetPage( static_cast< sal_uInt16 >( maPos.Tab() ) ) : 0;
254 void ScCaptionCreator::FitCaptionToRect( const Rectangle* pVisRect )
256 const Rectangle& rVisRect = GetVisRect( pVisRect );
258 // tail position
259 Point aTailPos = mpCaption->GetTailPos();
260 aTailPos.X() = ::std::max( ::std::min( aTailPos.X(), rVisRect.Right() ), rVisRect.Left() );
261 aTailPos.Y() = ::std::max( ::std::min( aTailPos.Y(), rVisRect.Bottom() ), rVisRect.Top() );
262 mpCaption->SetTailPos( aTailPos );
264 // caption rectangle
265 Rectangle aCaptRect = mpCaption->GetLogicRect();
266 Point aCaptPos = aCaptRect.TopLeft();
267 // move textbox inside right border of visible area
268 aCaptPos.X() = ::std::min< long >( aCaptPos.X(), rVisRect.Right() - aCaptRect.GetWidth() );
269 // move textbox inside left border of visible area (this may move it outside on right side again)
270 aCaptPos.X() = ::std::max< long >( aCaptPos.X(), rVisRect.Left() );
271 // move textbox inside bottom border of visible area
272 aCaptPos.Y() = ::std::min< long >( aCaptPos.Y(), rVisRect.Bottom() - aCaptRect.GetHeight() );
273 // move textbox inside top border of visible area (this may move it outside on bottom side again)
274 aCaptPos.Y() = ::std::max< long >( aCaptPos.Y(), rVisRect.Top() );
275 // update caption
276 aCaptRect.SetPos( aCaptPos );
277 mpCaption->SetLogicRect( aCaptRect );
280 void ScCaptionCreator::AutoPlaceCaption( const Rectangle* pVisRect )
282 const Rectangle& rVisRect = GetVisRect( pVisRect );
284 // caption rectangle
285 Rectangle aCaptRect = mpCaption->GetLogicRect();
286 long nWidth = aCaptRect.GetWidth();
287 long nHeight = aCaptRect.GetHeight();
289 // n***Space contains available space between border of visible area and cell
290 long nLeftSpace = maCellRect.Left() - rVisRect.Left() + 1;
291 long nRightSpace = rVisRect.Right() - maCellRect.Right() + 1;
292 long nTopSpace = maCellRect.Top() - rVisRect.Top() + 1;
293 long nBottomSpace = rVisRect.Bottom() - maCellRect.Bottom() + 1;
295 // nNeeded*** contains textbox dimensions plus needed distances to cell or border of visible area
296 long nNeededSpaceX = nWidth + SC_NOTECAPTION_CELLDIST;
297 long nNeededSpaceY = nHeight + SC_NOTECAPTION_CELLDIST;
299 // bFitsWidth*** == true means width of textbox fits into horizontal free space of visible area
300 bool bFitsWidthLeft = nNeededSpaceX <= nLeftSpace; // text box width fits into the width left of cell
301 bool bFitsWidthRight = nNeededSpaceX <= nRightSpace; // text box width fits into the width right of cell
302 bool bFitsWidth = nWidth <= rVisRect.GetWidth(); // text box width fits into width of visible area
304 // bFitsHeight*** == true means height of textbox fits into vertical free space of visible area
305 bool bFitsHeightTop = nNeededSpaceY <= nTopSpace; // text box height fits into the height above cell
306 bool bFitsHeightBottom = nNeededSpaceY <= nBottomSpace; // text box height fits into the height below cell
307 bool bFitsHeight = nHeight <= rVisRect.GetHeight(); // text box height fits into height of visible area
309 // bFits*** == true means the textbox fits completely into free space of visible area
310 bool bFitsLeft = bFitsWidthLeft && bFitsHeight;
311 bool bFitsRight = bFitsWidthRight && bFitsHeight;
312 bool bFitsTop = bFitsWidth && bFitsHeightTop;
313 bool bFitsBottom = bFitsWidth && bFitsHeightBottom;
315 Point aCaptPos;
316 // use left/right placement if possible, or if top/bottom placement not possible
317 if( bFitsLeft || bFitsRight || (!bFitsTop && !bFitsBottom) )
319 // prefer left in RTL sheet and right in LTR sheets
320 bool bPreferLeft = bFitsLeft && (mbNegPage || !bFitsRight);
321 bool bPreferRight = bFitsRight && (!mbNegPage || !bFitsLeft);
322 // move to left, if left is preferred, or if neither left nor right fit and there is more space to the left
323 if( bPreferLeft || (!bPreferRight && (nLeftSpace > nRightSpace)) )
324 aCaptPos.X() = maCellRect.Left() - SC_NOTECAPTION_CELLDIST - nWidth;
325 else // to right
326 aCaptPos.X() = maCellRect.Right() + SC_NOTECAPTION_CELLDIST;
327 // Y position according to top cell border
328 aCaptPos.Y() = maCellRect.Top() + SC_NOTECAPTION_OFFSET_Y;
330 else // top or bottom placement
332 // X position
333 aCaptPos.X() = maCellRect.Left() + SC_NOTECAPTION_OFFSET_X;
334 // top placement, if possible
335 if( bFitsTop )
336 aCaptPos.Y() = maCellRect.Top() - SC_NOTECAPTION_CELLDIST - nHeight;
337 else // bottom placement
338 aCaptPos.Y() = maCellRect.Bottom() + SC_NOTECAPTION_CELLDIST;
341 // update textbox position in note caption object
342 aCaptRect.SetPos( aCaptPos );
343 mpCaption->SetLogicRect( aCaptRect );
344 FitCaptionToRect( pVisRect );
347 void ScCaptionCreator::UpdateCaptionPos( const Rectangle* pVisRect )
349 ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
351 // update caption position
352 const Point& rOldTailPos = mpCaption->GetTailPos();
353 Point aTailPos = CalcTailPos( false );
354 if( rOldTailPos != aTailPos )
356 // create drawing undo action
357 if( pDrawLayer && pDrawLayer->IsRecording() )
358 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoGeoObject( *mpCaption ) );
359 // calculate new caption rectangle (#i98141# handle LTR<->RTL switch correctly)
360 Rectangle aCaptRect = mpCaption->GetLogicRect();
361 long nDiffX = (rOldTailPos.X() >= 0) ? (aCaptRect.Left() - rOldTailPos.X()) : (rOldTailPos.X() - aCaptRect.Right());
362 if( mbNegPage ) nDiffX = -nDiffX - aCaptRect.GetWidth();
363 long nDiffY = aCaptRect.Top() - rOldTailPos.Y();
364 aCaptRect.SetPos( aTailPos + Point( nDiffX, nDiffY ) );
365 // set new tail position and caption rectangle
366 mpCaption->SetTailPos( aTailPos );
367 mpCaption->SetLogicRect( aCaptRect );
368 // fit caption into draw page
369 FitCaptionToRect( pVisRect );
372 // update cell position in caption user data
373 ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( mpCaption, maPos.Tab() );
374 if( pCaptData && (maPos != pCaptData->maStart) )
376 // create drawing undo action
377 if( pDrawLayer && pDrawLayer->IsRecording() )
378 pDrawLayer->AddCalcUndo( new ScUndoObjData( mpCaption, pCaptData->maStart, pCaptData->maEnd, maPos, pCaptData->maEnd ) );
379 // set new position
380 pCaptData->maStart = maPos;
384 Point ScCaptionCreator::CalcTailPos( bool bTailFront )
386 // tail position
387 bool bTailLeft = bTailFront != mbNegPage;
388 Point aTailPos = bTailLeft ? maCellRect.TopLeft() : maCellRect.TopRight();
389 // move caption point 1/10 mm inside cell
390 if( bTailLeft ) aTailPos.X() += 10; else aTailPos.X() -= 10;
391 aTailPos.Y() += 10;
392 return aTailPos;
395 void ScCaptionCreator::CreateCaption( bool bShown, bool bTailFront )
397 // create the caption drawing object
398 Rectangle aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH, SC_NOTECAPTION_HEIGHT ) );
399 Point aTailPos = CalcTailPos( bTailFront );
400 mpCaption = new SdrCaptionObj( aTextRect, aTailPos );
401 // basic caption settings
402 ScCaptionUtil::SetBasicCaptionSettings( *mpCaption, bShown );
405 void ScCaptionCreator::Initialize()
407 maCellRect = ScDrawLayer::GetCellRect( mrDoc, maPos, true );
408 mbNegPage = mrDoc.IsNegativePage( maPos.Tab() );
409 if( SdrPage* pDrawPage = GetDrawPage() )
411 maPageRect = Rectangle( Point( 0, 0 ), pDrawPage->GetSize() );
412 /* #i98141# SdrPage::GetSize() returns negative width in RTL mode.
413 The call to Rectangle::Adjust() orders left/right coordinate
414 accordingly. */
415 maPageRect.Justify();
419 // ============================================================================
421 /** Helper for creation of permanent caption drawing objects for cell notes. */
422 class ScNoteCaptionCreator : public ScCaptionCreator
424 public:
425 /** Create a new caption object and inserts it into the document. */
426 explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData );
427 /** Manipulate an existing caption. */
428 explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown );
431 // ----------------------------------------------------------------------------
433 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData ) :
434 ScCaptionCreator( rDoc, rPos ) // use helper c'tor that does not create the caption yet
436 SdrPage* pDrawPage = GetDrawPage();
437 OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
438 if( pDrawPage )
440 // create the caption drawing object
441 CreateCaption( rNoteData.mbShown, false );
442 rNoteData.mpCaption = GetCaption();
443 OSL_ENSURE( rNoteData.mpCaption, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" );
444 if( rNoteData.mpCaption )
446 // store note position in user data of caption object
447 ScCaptionUtil::SetCaptionUserData( *rNoteData.mpCaption, rPos );
448 // insert object into draw page
449 pDrawPage->InsertObject( rNoteData.mpCaption );
454 ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown ) :
455 ScCaptionCreator( rDoc, rPos, rCaption )
457 SdrPage* pDrawPage = GetDrawPage();
458 OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
459 OSL_ENSURE( rCaption.GetPage() == pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" );
460 if( pDrawPage && (rCaption.GetPage() == pDrawPage) )
462 // store note position in user data of caption object
463 ScCaptionUtil::SetCaptionUserData( rCaption, rPos );
464 // basic caption settings
465 ScCaptionUtil::SetBasicCaptionSettings( rCaption, bShown );
466 // set correct tail position
467 rCaption.SetTailPos( CalcTailPos( false ) );
471 } // namespace
473 // ============================================================================
475 struct ScCaptionInitData
477 typedef ::std::auto_ptr< SfxItemSet > SfxItemSetPtr;
478 typedef ::std::auto_ptr< OutlinerParaObject > OutlinerParaObjPtr;
480 SfxItemSetPtr mxItemSet; /// Caption object formatting.
481 OutlinerParaObjPtr mxOutlinerObj; /// Text object with all text portion formatting.
482 ::rtl::OUString maSimpleText; /// Simple text without formatting.
483 Point maCaptionOffset; /// Caption position relative to cell corner.
484 Size maCaptionSize; /// Size of the caption object.
485 bool mbDefaultPosSize; /// True = use default position and size for caption.
487 explicit ScCaptionInitData();
490 // ----------------------------------------------------------------------------
492 ScCaptionInitData::ScCaptionInitData() :
493 mbDefaultPosSize( true )
497 // ============================================================================
499 ScNoteData::ScNoteData( bool bShown ) :
500 mpCaption( 0 ),
501 mbShown( bShown )
505 ScNoteData::~ScNoteData()
509 // ============================================================================
511 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, bool bShown ) :
512 mrDoc( rDoc ),
513 maNoteData( bShown )
515 AutoStamp();
516 CreateCaption( rPos );
519 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNote ) :
520 mrDoc( rDoc ),
521 maNoteData( rNote.maNoteData )
523 maNoteData.mpCaption = 0;
524 CreateCaption( rPos, rNote.maNoteData.mpCaption );
527 ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScNoteData& rNoteData, bool bAlwaysCreateCaption ) :
528 mrDoc( rDoc ),
529 maNoteData( rNoteData )
531 if( bAlwaysCreateCaption || maNoteData.mbShown )
532 CreateCaptionFromInitData( rPos );
535 ScPostIt::~ScPostIt()
537 RemoveCaption();
540 ScPostIt* ScPostIt::Clone( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, bool bCloneCaption ) const
542 CreateCaptionFromInitData( rOwnPos );
543 return bCloneCaption ? new ScPostIt( rDestDoc, rDestPos, *this ) : new ScPostIt( rDestDoc, rDestPos, maNoteData, false );
546 void ScPostIt::AutoStamp()
548 maNoteData.maDate = ScGlobal::pLocaleData->getDate( Date() );
549 maNoteData.maAuthor = SvtUserOptions().GetID();
552 const OutlinerParaObject* ScPostIt::GetOutlinerObject() const
554 if( maNoteData.mpCaption )
555 return maNoteData.mpCaption->GetOutlinerParaObject();
556 if( maNoteData.mxInitData.get() )
557 return maNoteData.mxInitData->mxOutlinerObj.get();
558 return 0;
561 const EditTextObject* ScPostIt::GetEditTextObject() const
563 const OutlinerParaObject* pOPO = GetOutlinerObject();
564 return pOPO ? &pOPO->GetTextObject() : 0;
567 OUString ScPostIt::GetText() const
569 if( const EditTextObject* pEditObj = GetEditTextObject() )
571 OUStringBuffer aBuffer;
572 for( USHORT nPara = 0, nParaCount = pEditObj->GetParagraphCount(); nPara < nParaCount; ++nPara )
574 if( nPara > 0 )
575 aBuffer.append( sal_Unicode( '\n' ) );
576 aBuffer.append( pEditObj->GetText( nPara ) );
578 return aBuffer.makeStringAndClear();
580 if( maNoteData.mxInitData.get() )
581 return maNoteData.mxInitData->maSimpleText;
582 return OUString();
585 bool ScPostIt::HasMultiLineText() const
587 if( const EditTextObject* pEditObj = GetEditTextObject() )
588 return pEditObj->GetParagraphCount() > 1;
589 if( maNoteData.mxInitData.get() )
590 return maNoteData.mxInitData->maSimpleText.indexOf( '\n' ) >= 0;
591 return false;
594 void ScPostIt::SetText( const ScAddress& rPos, const OUString& rText )
596 CreateCaptionFromInitData( rPos );
597 if( maNoteData.mpCaption )
598 maNoteData.mpCaption->SetText( rText );
601 SdrCaptionObj* ScPostIt::GetOrCreateCaption( const ScAddress& rPos ) const
603 CreateCaptionFromInitData( rPos );
604 return maNoteData.mpCaption;
607 void ScPostIt::ForgetCaption()
609 /* This function is used in undo actions to give up the responsibility for
610 the caption object which is handled by separate drawing undo actions. */
611 maNoteData.mpCaption = 0;
612 maNoteData.mxInitData.reset();
615 void ScPostIt::ShowCaption( const ScAddress& rPos, bool bShow )
617 CreateCaptionFromInitData( rPos );
618 // no separate drawing undo needed, handled completely inside ScUndoShowHideNote
619 maNoteData.mbShown = bShow;
620 if( maNoteData.mpCaption )
621 ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, bShow );
624 void ScPostIt::ShowCaptionTemp( const ScAddress& rPos, bool bShow )
626 CreateCaptionFromInitData( rPos );
627 if( maNoteData.mpCaption )
628 ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, maNoteData.mbShown || bShow );
631 void ScPostIt::UpdateCaptionPos( const ScAddress& rPos )
633 CreateCaptionFromInitData( rPos );
634 if( maNoteData.mpCaption )
636 ScCaptionCreator aCreator( mrDoc, rPos, *maNoteData.mpCaption );
637 aCreator.UpdateCaptionPos();
641 // private --------------------------------------------------------------------
643 void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const
645 OSL_ENSURE( maNoteData.mpCaption || maNoteData.mxInitData.get(), "ScPostIt::CreateCaptionFromInitData - need caption object or initial caption data" );
646 if( maNoteData.mxInitData.get() )
648 /* This function is called from ScPostIt::Clone() when copying cells
649 to the clipboard/undo document, and when copying cells from the
650 clipboard/undo document. The former should always be called first,
651 so if called in an clipboard/undo document, the caption should have
652 been created already. */
653 OSL_ENSURE( !mrDoc.IsUndo() && !mrDoc.IsClipboard(), "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" );
655 /* #i104915# Never try to create notes in Undo document, leads to
656 crash due to missing document members (e.g. row height array). */
657 if( !maNoteData.mpCaption && !mrDoc.IsUndo() )
659 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
660 ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
661 if( maNoteData.mpCaption )
663 ScCaptionInitData& rInitData = *maNoteData.mxInitData;
665 // transfer ownership of outliner object to caption, or set simple text
666 OSL_ENSURE( rInitData.mxOutlinerObj.get() || (rInitData.maSimpleText.getLength() > 0),
667 "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" );
668 if( rInitData.mxOutlinerObj.get() )
669 maNoteData.mpCaption->SetOutlinerParaObject( rInitData.mxOutlinerObj.release() );
670 else
671 maNoteData.mpCaption->SetText( rInitData.maSimpleText );
673 // copy all items or set default items; reset shadow items
674 ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
675 if( rInitData.mxItemSet.get() )
676 ScCaptionUtil::SetCaptionItems( *maNoteData.mpCaption, *rInitData.mxItemSet );
678 // set position and size of the caption object
679 if( rInitData.mbDefaultPosSize )
681 // set other items and fit caption size to text
682 maNoteData.mpCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
683 maNoteData.mpCaption->SetMergedItem( SdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) );
684 maNoteData.mpCaption->AdjustTextFrameWidthAndHeight();
685 aCreator.AutoPlaceCaption();
687 else
689 Rectangle aCellRect = ScDrawLayer::GetCellRect( mrDoc, rPos, true );
690 bool bNegPage = mrDoc.IsNegativePage( rPos.Tab() );
691 long nPosX = bNegPage ? (aCellRect.Left() - rInitData.maCaptionOffset.X()) : (aCellRect.Right() + rInitData.maCaptionOffset.X());
692 long nPosY = aCellRect.Top() + rInitData.maCaptionOffset.Y();
693 Rectangle aCaptRect( Point( nPosX, nPosY ), rInitData.maCaptionSize );
694 maNoteData.mpCaption->SetLogicRect( aCaptRect );
695 aCreator.FitCaptionToRect();
699 // forget the initial caption data struct
700 maNoteData.mxInitData.reset();
704 void ScPostIt::CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption )
706 OSL_ENSURE( !maNoteData.mpCaption, "ScPostIt::CreateCaption - unexpected caption object found" );
707 maNoteData.mpCaption = 0;
709 /* #i104915# Never try to create notes in Undo document, leads to
710 crash due to missing document members (e.g. row height array). */
711 OSL_ENSURE( !mrDoc.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" );
712 if( mrDoc.IsUndo() )
713 return;
715 // drawing layer may be missing, if a note is copied into a clipboard document
716 if( mrDoc.IsClipboard() )
717 mrDoc.InitDrawLayer();
719 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
720 ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
721 if( maNoteData.mpCaption )
723 // clone settings of passed caption
724 if( pCaption )
726 // copy edit text object (object must be inserted into page already)
727 if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
728 maNoteData.mpCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
729 // copy formatting items (after text has been copied to apply font formatting)
730 maNoteData.mpCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() );
731 // move textbox position relative to new cell, copy textbox size
732 Rectangle aCaptRect = pCaption->GetLogicRect();
733 Point aDist = maNoteData.mpCaption->GetTailPos() - pCaption->GetTailPos();
734 aCaptRect.Move( aDist.X(), aDist.Y() );
735 maNoteData.mpCaption->SetLogicRect( aCaptRect );
736 aCreator.FitCaptionToRect();
738 else
740 // set default formatting and default position
741 ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
742 aCreator.AutoPlaceCaption();
745 // create undo action
746 if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() )
747 if( pDrawLayer->IsRecording() )
748 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoNewObject( *maNoteData.mpCaption ) );
752 void ScPostIt::RemoveCaption()
755 /* Remove caption object only, if this note is its owner (e.g. notes in
756 undo documents refer to captions in original document, do not remove
757 them from drawing layer here). */
758 ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
759 if( maNoteData.mpCaption && (pDrawLayer == maNoteData.mpCaption->GetModel()) )
761 OSL_ENSURE( pDrawLayer, "ScPostIt::RemoveCaption - object without drawing layer" );
762 SdrPage* pDrawPage = maNoteData.mpCaption->GetPage();
763 OSL_ENSURE( pDrawPage, "ScPostIt::RemoveCaption - object without drawing page" );
764 if( pDrawPage )
766 pDrawPage->RecalcObjOrdNums();
767 // create drawing undo action (before removing the object to have valid draw page in undo action)
768 if( pDrawLayer && pDrawLayer->IsRecording() )
769 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoDeleteObject( *maNoteData.mpCaption ) );
770 // remove the object from the drawing page, delete if undo is disabled
771 pDrawPage->RemoveObject( maNoteData.mpCaption->GetOrdNum() );
774 maNoteData.mpCaption = 0;
777 // ============================================================================
779 void ScNoteUtil::UpdateCaptionPositions( ScDocument& rDoc, const ScRange& rRange )
781 // do not use ScCellIterator, it skips filtered and subtotal cells
782 for( ScAddress aPos( rRange.aStart ); aPos.Tab() <= rRange.aEnd.Tab(); aPos.IncTab() )
783 for( aPos.SetCol( rRange.aStart.Col() ); aPos.Col() <= rRange.aEnd.Col(); aPos.IncCol() )
784 for( aPos.SetRow( rRange.aStart.Row() ); aPos.Row() <= rRange.aEnd.Row(); aPos.IncRow() )
785 if( ScPostIt* pNote = rDoc.GetNote( aPos ) )
786 pNote->UpdateCaptionPos( aPos );
789 SdrCaptionObj* ScNoteUtil::CreateTempCaption(
790 ScDocument& rDoc, const ScAddress& rPos, SdrPage& rDrawPage,
791 const OUString& rUserText, const Rectangle& rVisRect, bool bTailFront )
793 OUStringBuffer aBuffer( rUserText );
794 // add plain text of invisible (!) cell note (no formatting etc.)
795 SdrCaptionObj* pNoteCaption = 0;
796 const ScPostIt* pNote = rDoc.GetNote( rPos );
797 if( pNote && !pNote->IsCaptionShown() )
799 if( aBuffer.getLength() > 0 )
800 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\n--------\n" ) ).append( pNote->GetText() );
801 pNoteCaption = pNote->GetOrCreateCaption( rPos );
804 // create a caption if any text exists
805 if( !pNoteCaption && (aBuffer.getLength() == 0) )
806 return 0;
808 // prepare visible rectangle (add default distance to all borders)
809 Rectangle aVisRect(
810 rVisRect.Left() + SC_NOTECAPTION_BORDERDIST_TEMP,
811 rVisRect.Top() + SC_NOTECAPTION_BORDERDIST_TEMP,
812 rVisRect.Right() - SC_NOTECAPTION_BORDERDIST_TEMP,
813 rVisRect.Bottom() - SC_NOTECAPTION_BORDERDIST_TEMP );
815 // create the caption object
816 ScCaptionCreator aCreator( rDoc, rPos, true, bTailFront );
817 SdrCaptionObj* pCaption = aCreator.GetCaption();
819 // insert caption into page (needed to set caption text)
820 rDrawPage.InsertObject( pCaption );
822 // clone the edit text object, unless user text is present, then set this text
823 if( pNoteCaption && (rUserText.getLength() == 0) )
825 if( OutlinerParaObject* pOPO = pNoteCaption->GetOutlinerParaObject() )
826 pCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
827 // set formatting (must be done after setting text) and resize the box to fit the text
828 pCaption->SetMergedItemSetAndBroadcast( pNoteCaption->GetMergedItemSet() );
829 Rectangle aCaptRect( pCaption->GetLogicRect().TopLeft(), pNoteCaption->GetLogicRect().GetSize() );
830 pCaption->SetLogicRect( aCaptRect );
832 else
834 // if pNoteCaption is null, then aBuffer contains some text
835 pCaption->SetText( aBuffer.makeStringAndClear() );
836 ScCaptionUtil::SetDefaultItems( *pCaption, rDoc );
837 // adjust caption size to text size
838 long nMaxWidth = ::std::min< long >( aVisRect.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP );
839 pCaption->SetMergedItem( SdrTextAutoGrowWidthItem( TRUE ) );
840 pCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
841 pCaption->SetMergedItem( SdrTextMaxFrameWidthItem( nMaxWidth ) );
842 pCaption->SetMergedItem( SdrTextAutoGrowHeightItem( TRUE ) );
843 pCaption->AdjustTextFrameWidthAndHeight();
846 // move caption into visible area
847 aCreator.AutoPlaceCaption( &aVisRect );
848 return pCaption;
851 ScPostIt* ScNoteUtil::CreateNoteFromCaption(
852 ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown )
854 ScNoteData aNoteData( bShown );
855 aNoteData.mpCaption = &rCaption;
856 ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, false );
857 pNote->AutoStamp();
858 rDoc.TakeNote( rPos, pNote );
859 // if pNote still points to the note after TakeNote(), insertion was successful
860 if( pNote )
862 // ScNoteCaptionCreator c'tor updates the caption object to be part of a note
863 ScNoteCaptionCreator aCreator( rDoc, rPos, rCaption, bShown );
865 return pNote;
868 ScPostIt* ScNoteUtil::CreateNoteFromObjectData(
869 ScDocument& rDoc, const ScAddress& rPos, SfxItemSet* pItemSet,
870 OutlinerParaObject* pOutlinerObj, const Rectangle& rCaptionRect,
871 bool bShown, bool bAlwaysCreateCaption )
873 OSL_ENSURE( pItemSet && pOutlinerObj, "ScNoteUtil::CreateNoteFromObjectData - item set and outliner object expected" );
874 ScNoteData aNoteData( bShown );
875 aNoteData.mxInitData.reset( new ScCaptionInitData );
876 ScCaptionInitData& rInitData = *aNoteData.mxInitData;
877 rInitData.mxItemSet.reset( pItemSet );
878 rInitData.mxOutlinerObj.reset( pOutlinerObj );
880 // convert absolute caption position to relative position
881 rInitData.mbDefaultPosSize = rCaptionRect.IsEmpty();
882 if( !rInitData.mbDefaultPosSize )
884 Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, rPos, true );
885 bool bNegPage = rDoc.IsNegativePage( rPos.Tab() );
886 rInitData.maCaptionOffset.X() = bNegPage ? (aCellRect.Left() - rCaptionRect.Right()) : (rCaptionRect.Left() - aCellRect.Right());
887 rInitData.maCaptionOffset.Y() = rCaptionRect.Top() - aCellRect.Top();
888 rInitData.maCaptionSize = rCaptionRect.GetSize();
891 /* Create the note and insert it into the document. If the note is
892 visible, the caption object will be created automatically. */
893 ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
894 pNote->AutoStamp();
895 rDoc.TakeNote( rPos, pNote );
896 // if pNote still points to the note after TakeNote(), insertion was successful
897 return pNote;
900 ScPostIt* ScNoteUtil::CreateNoteFromString(
901 ScDocument& rDoc, const ScAddress& rPos, const OUString& rNoteText,
902 bool bShown, bool bAlwaysCreateCaption )
904 ScPostIt* pNote = 0;
905 if( rNoteText.getLength() > 0 )
907 ScNoteData aNoteData( bShown );
908 aNoteData.mxInitData.reset( new ScCaptionInitData );
909 ScCaptionInitData& rInitData = *aNoteData.mxInitData;
910 rInitData.maSimpleText = rNoteText;
911 rInitData.mbDefaultPosSize = true;
913 /* Create the note and insert it into the document. If the note is
914 visible, the caption object will be created automatically. */
915 pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
916 pNote->AutoStamp();
917 rDoc.TakeNote( rPos, pNote );
918 // if pNote still points to the note after TakeNote(), insertion was successful
920 return pNote;
923 // ============================================================================