update dev300-m58
[ooovba.git] / sc / source / core / data / postit.cxx
blobc53694b7674c8ab13e17160976b6166c61606786
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 if( !maNoteData.mpCaption )
657 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
658 ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
659 if( maNoteData.mpCaption )
661 ScCaptionInitData& rInitData = *maNoteData.mxInitData;
663 // transfer ownership of outliner object to caption, or set simple text
664 OSL_ENSURE( rInitData.mxOutlinerObj.get() || (rInitData.maSimpleText.getLength() > 0),
665 "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" );
666 if( rInitData.mxOutlinerObj.get() )
667 maNoteData.mpCaption->SetOutlinerParaObject( rInitData.mxOutlinerObj.release() );
668 else
669 maNoteData.mpCaption->SetText( rInitData.maSimpleText );
671 // copy all items or set default items; reset shadow items
672 ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
673 if( rInitData.mxItemSet.get() )
674 ScCaptionUtil::SetCaptionItems( *maNoteData.mpCaption, *rInitData.mxItemSet );
676 // set position and size of the caption object
677 if( rInitData.mbDefaultPosSize )
679 // set other items and fit caption size to text
680 maNoteData.mpCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
681 maNoteData.mpCaption->SetMergedItem( SdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) );
682 maNoteData.mpCaption->AdjustTextFrameWidthAndHeight();
683 aCreator.AutoPlaceCaption();
685 else
687 Rectangle aCellRect = ScDrawLayer::GetCellRect( mrDoc, rPos, true );
688 bool bNegPage = mrDoc.IsNegativePage( rPos.Tab() );
689 long nPosX = bNegPage ? (aCellRect.Left() - rInitData.maCaptionOffset.X()) : (aCellRect.Right() + rInitData.maCaptionOffset.X());
690 long nPosY = aCellRect.Top() + rInitData.maCaptionOffset.Y();
691 Rectangle aCaptRect( Point( nPosX, nPosY ), rInitData.maCaptionSize );
692 maNoteData.mpCaption->SetLogicRect( aCaptRect );
693 aCreator.FitCaptionToRect();
697 // forget the initial caption data struct
698 maNoteData.mxInitData.reset();
702 void ScPostIt::CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption )
704 OSL_ENSURE( !maNoteData.mpCaption, "ScPostIt::CreateCaption - unexpected caption object found" );
705 maNoteData.mpCaption = 0;
707 // drawing layer may be missing, if a note is copied into a clipboard document
708 OSL_ENSURE( !mrDoc.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" );
709 if( mrDoc.IsClipboard() )
710 mrDoc.InitDrawLayer();
712 // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
713 ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
714 if( maNoteData.mpCaption )
716 // clone settings of passed caption
717 if( pCaption )
719 // copy edit text object (object must be inserted into page already)
720 if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
721 maNoteData.mpCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
722 // copy formatting items (after text has been copied to apply font formatting)
723 maNoteData.mpCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() );
724 // move textbox position relative to new cell, copy textbox size
725 Rectangle aCaptRect = pCaption->GetLogicRect();
726 Point aDist = maNoteData.mpCaption->GetTailPos() - pCaption->GetTailPos();
727 aCaptRect.Move( aDist.X(), aDist.Y() );
728 maNoteData.mpCaption->SetLogicRect( aCaptRect );
729 aCreator.FitCaptionToRect();
731 else
733 // set default formatting and default position
734 ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
735 aCreator.AutoPlaceCaption();
738 // create undo action
739 if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() )
740 if( pDrawLayer->IsRecording() )
741 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoNewObject( *maNoteData.mpCaption ) );
745 void ScPostIt::RemoveCaption()
748 /* Remove caption object only, if this note is its owner (e.g. notes in
749 undo documents refer to captions in original document, do not remove
750 them from drawing layer here). */
751 ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
752 if( maNoteData.mpCaption && (pDrawLayer == maNoteData.mpCaption->GetModel()) )
754 OSL_ENSURE( pDrawLayer, "ScPostIt::RemoveCaption - object without drawing layer" );
755 SdrPage* pDrawPage = maNoteData.mpCaption->GetPage();
756 OSL_ENSURE( pDrawPage, "ScPostIt::RemoveCaption - object without drawing page" );
757 if( pDrawPage )
759 pDrawPage->RecalcObjOrdNums();
760 // create drawing undo action (before removing the object to have valid draw page in undo action)
761 if( pDrawLayer && pDrawLayer->IsRecording() )
762 pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoDeleteObject( *maNoteData.mpCaption ) );
763 // remove the object from the drawing page, delete if undo is disabled
764 pDrawPage->RemoveObject( maNoteData.mpCaption->GetOrdNum() );
767 maNoteData.mpCaption = 0;
770 // ============================================================================
772 void ScNoteUtil::UpdateCaptionPositions( ScDocument& rDoc, const ScRange& rRange )
774 // do not use ScCellIterator, it skips filtered and subtotal cells
775 for( ScAddress aPos( rRange.aStart ); aPos.Tab() <= rRange.aEnd.Tab(); aPos.IncTab() )
776 for( aPos.SetCol( rRange.aStart.Col() ); aPos.Col() <= rRange.aEnd.Col(); aPos.IncCol() )
777 for( aPos.SetRow( rRange.aStart.Row() ); aPos.Row() <= rRange.aEnd.Row(); aPos.IncRow() )
778 if( ScPostIt* pNote = rDoc.GetNote( aPos ) )
779 pNote->UpdateCaptionPos( aPos );
782 SdrCaptionObj* ScNoteUtil::CreateTempCaption(
783 ScDocument& rDoc, const ScAddress& rPos, SdrPage& rDrawPage,
784 const OUString& rUserText, const Rectangle& rVisRect, bool bTailFront )
786 OUStringBuffer aBuffer( rUserText );
787 // add plain text of invisible (!) cell note (no formatting etc.)
788 SdrCaptionObj* pNoteCaption = 0;
789 if( const ScPostIt* pNote = rDoc.GetNote( rPos ) )
791 if( !pNote->IsCaptionShown() )
793 if( aBuffer.getLength() > 0 )
794 aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\n--------\n" ) );
795 aBuffer.append( pNote->GetText() );
796 pNoteCaption = pNote->GetOrCreateCaption( rPos );
800 // create a caption if any text exists
801 if( aBuffer.getLength() == 0 )
802 return 0;
804 // prepare visible rectangle (add default distance to all borders)
805 Rectangle aVisRect(
806 rVisRect.Left() + SC_NOTECAPTION_BORDERDIST_TEMP,
807 rVisRect.Top() + SC_NOTECAPTION_BORDERDIST_TEMP,
808 rVisRect.Right() - SC_NOTECAPTION_BORDERDIST_TEMP,
809 rVisRect.Bottom() - SC_NOTECAPTION_BORDERDIST_TEMP );
811 // create the caption object
812 ScCaptionCreator aCreator( rDoc, rPos, true, bTailFront );
813 SdrCaptionObj* pCaption = aCreator.GetCaption();
814 // insert caption into page (needed to set caption text)
815 rDrawPage.InsertObject( pCaption );
816 // set the text to the object
817 pCaption->SetText( aBuffer.makeStringAndClear() );
819 // set formatting (must be done after setting text) and resize the box to fit the text
820 if( pNoteCaption && (rUserText.getLength() == 0) )
822 pCaption->SetMergedItemSetAndBroadcast( pNoteCaption->GetMergedItemSet() );
823 Rectangle aCaptRect( pCaption->GetLogicRect().TopLeft(), pNoteCaption->GetLogicRect().GetSize() );
824 pCaption->SetLogicRect( aCaptRect );
826 else
828 ScCaptionUtil::SetDefaultItems( *pCaption, rDoc );
829 // adjust caption size to text size
830 long nMaxWidth = ::std::min< long >( aVisRect.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP );
831 pCaption->SetMergedItem( SdrTextAutoGrowWidthItem( TRUE ) );
832 pCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
833 pCaption->SetMergedItem( SdrTextMaxFrameWidthItem( nMaxWidth ) );
834 pCaption->SetMergedItem( SdrTextAutoGrowHeightItem( TRUE ) );
835 pCaption->AdjustTextFrameWidthAndHeight();
838 // move caption into visible area
839 aCreator.AutoPlaceCaption( &aVisRect );
840 return pCaption;
843 ScPostIt* ScNoteUtil::CreateNoteFromCaption(
844 ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown )
846 ScNoteData aNoteData( bShown );
847 aNoteData.mpCaption = &rCaption;
848 ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, false );
849 pNote->AutoStamp();
850 rDoc.TakeNote( rPos, pNote );
851 // if pNote still points to the note after TakeNote(), insertion was successful
852 if( pNote )
854 // ScNoteCaptionCreator c'tor updates the caption object to be part of a note
855 ScNoteCaptionCreator aCreator( rDoc, rPos, rCaption, bShown );
857 return pNote;
860 ScPostIt* ScNoteUtil::CreateNoteFromObjectData(
861 ScDocument& rDoc, const ScAddress& rPos, SfxItemSet* pItemSet,
862 OutlinerParaObject* pOutlinerObj, const Rectangle& rCaptionRect,
863 bool bShown, bool bAlwaysCreateCaption )
865 OSL_ENSURE( pItemSet && pOutlinerObj, "ScNoteUtil::CreateNoteFromObjectData - item set and outliner object expected" );
866 ScNoteData aNoteData( bShown );
867 aNoteData.mxInitData.reset( new ScCaptionInitData );
868 ScCaptionInitData& rInitData = *aNoteData.mxInitData;
869 rInitData.mxItemSet.reset( pItemSet );
870 rInitData.mxOutlinerObj.reset( pOutlinerObj );
872 // convert absolute caption position to relative position
873 rInitData.mbDefaultPosSize = rCaptionRect.IsEmpty();
874 if( !rInitData.mbDefaultPosSize )
876 Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, rPos, true );
877 bool bNegPage = rDoc.IsNegativePage( rPos.Tab() );
878 rInitData.maCaptionOffset.X() = bNegPage ? (aCellRect.Left() - rCaptionRect.Right()) : (rCaptionRect.Left() - aCellRect.Right());
879 rInitData.maCaptionOffset.Y() = rCaptionRect.Top() - aCellRect.Top();
880 rInitData.maCaptionSize = rCaptionRect.GetSize();
883 /* Create the note and insert it into the document. If the note is
884 visible, the caption object will be created automatically. */
885 ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
886 pNote->AutoStamp();
887 rDoc.TakeNote( rPos, pNote );
888 // if pNote still points to the note after TakeNote(), insertion was successful
889 return pNote;
892 ScPostIt* ScNoteUtil::CreateNoteFromString(
893 ScDocument& rDoc, const ScAddress& rPos, const OUString& rNoteText,
894 bool bShown, bool bAlwaysCreateCaption )
896 ScPostIt* pNote = 0;
897 if( rNoteText.getLength() > 0 )
899 ScNoteData aNoteData( bShown );
900 aNoteData.mxInitData.reset( new ScCaptionInitData );
901 ScCaptionInitData& rInitData = *aNoteData.mxInitData;
902 rInitData.maSimpleText = rNoteText;
903 rInitData.mbDefaultPosSize = true;
905 /* Create the note and insert it into the document. If the note is
906 visible, the caption object will be created automatically. */
907 pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
908 pNote->AutoStamp();
909 rDoc.TakeNote( rPos, pNote );
910 // if pNote still points to the note after TakeNote(), insertion was successful
912 return pNote;
915 // ============================================================================