Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "postit.hxx"
31 : :
32 : : #include <rtl/ustrbuf.hxx>
33 : : #include <unotools/useroptions.hxx>
34 : : #include <svx/svdpage.hxx>
35 : : #include <svx/svdocapt.hxx>
36 : : #include <editeng/outlobj.hxx>
37 : : #include <editeng/editobj.hxx>
38 : : #include <basegfx/polygon/b2dpolygon.hxx>
39 : :
40 : : #include "scitems.hxx"
41 : : #include <svx/xlnstit.hxx>
42 : : #include <svx/xlnstwit.hxx>
43 : : #include <svx/xlnstcit.hxx>
44 : : #include <svx/sxcecitm.hxx>
45 : : #include <svx/xflclit.hxx>
46 : : #include <svx/sdshitm.hxx>
47 : : #include <svx/sdsxyitm.hxx>
48 : :
49 : : #include "document.hxx"
50 : : #include "docpool.hxx"
51 : : #include "patattr.hxx"
52 : : #include "cell.hxx"
53 : : #include "drwlayer.hxx"
54 : : #include "userdat.hxx"
55 : : #include "detfunc.hxx"
56 : :
57 : : #include <utility>
58 : :
59 : : using ::rtl::OUString;
60 : : using ::rtl::OUStringBuffer;
61 : :
62 : : // ============================================================================
63 : :
64 : : namespace {
65 : :
66 : : const long SC_NOTECAPTION_WIDTH = 2900; /// Default width of note caption textbox.
67 : : const long SC_NOTECAPTION_MAXWIDTH_TEMP = 12000; /// Maximum width of temporary note caption textbox.
68 : : const long SC_NOTECAPTION_HEIGHT = 1800; /// Default height of note caption textbox.
69 : : const long SC_NOTECAPTION_CELLDIST = 600; /// Default distance of note captions to border of anchor cell.
70 : : const long SC_NOTECAPTION_OFFSET_Y = -1500; /// Default Y offset of note captions to top border of anchor cell.
71 : : const long SC_NOTECAPTION_OFFSET_X = 1500; /// Default X offset of note captions to left border of anchor cell.
72 : : const long SC_NOTECAPTION_BORDERDIST_TEMP = 100; /// Distance of temporary note captions to visible sheet area.
73 : :
74 : : // ============================================================================
75 : :
76 : : /** Static helper functions for caption objects. */
77 : : class ScCaptionUtil
78 : : {
79 : : public:
80 : : /** Moves the caption object to the correct layer according to passed visibility. */
81 : : static void SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown );
82 : : /** Sets basic caption settings required for note caption objects. */
83 : : static void SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown );
84 : : /** Stores the cell position of the note in the user data area of the caption. */
85 : : static void SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos );
86 : : /** Sets all default formatting attributes to the caption object. */
87 : : static void SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc );
88 : : /** Updates caption item set according to the passed item set while removing shadow items. */
89 : : static void SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet );
90 : : };
91 : :
92 : : // ----------------------------------------------------------------------------
93 : :
94 : 12 : void ScCaptionUtil::SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown )
95 : : {
96 [ + + ]: 12 : SdrLayerID nLayer = bShown ? SC_LAYER_INTERN : SC_LAYER_HIDDEN;
97 [ + - ]: 12 : if( nLayer != rCaption.GetLayer() )
98 : 12 : rCaption.SetLayer( nLayer );
99 : 12 : }
100 : :
101 : 12 : void ScCaptionUtil::SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown )
102 : : {
103 : 12 : SetCaptionLayer( rCaption, bShown );
104 : 12 : rCaption.SetFixedTail();
105 : 12 : rCaption.SetSpecialTextBoxShadow();
106 : 12 : }
107 : :
108 : 12 : void ScCaptionUtil::SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos )
109 : : {
110 : : // pass true to ScDrawLayer::GetObjData() to create the object data entry
111 : 12 : ScDrawObjData* pObjData = ScDrawLayer::GetObjData( &rCaption, true );
112 : : OSL_ENSURE( pObjData, "ScCaptionUtil::SetCaptionUserData - missing drawing object user data" );
113 : 12 : pObjData->maStart = rPos;
114 : 12 : pObjData->meType = ScDrawObjData::CellNote;
115 : 12 : }
116 : :
117 : 10 : void ScCaptionUtil::SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc )
118 : : {
119 [ + - ][ + - ]: 10 : SfxItemSet aItemSet = rCaption.GetMergedItemSet();
120 : :
121 : : // caption tail arrow
122 [ + - ]: 10 : ::basegfx::B2DPolygon aTriangle;
123 [ + - ]: 10 : aTriangle.append( ::basegfx::B2DPoint( 10.0, 0.0 ) );
124 [ + - ]: 10 : aTriangle.append( ::basegfx::B2DPoint( 0.0, 30.0 ) );
125 [ + - ]: 10 : aTriangle.append( ::basegfx::B2DPoint( 20.0, 30.0 ) );
126 [ + - ]: 10 : aTriangle.setClosed( true );
127 : : /* Line ends are now created with an empty name. The
128 : : checkForUniqueItem() method then finds a unique name for the item's
129 : : value. */
130 [ + - ][ + - ]: 10 : aItemSet.Put( XLineStartItem( String::EmptyString(), ::basegfx::B2DPolyPolygon( aTriangle ) ) );
[ + - ][ + - ]
[ + - ][ + - ]
131 [ + - ][ + - ]: 10 : aItemSet.Put( XLineStartWidthItem( 200 ) );
[ + - ]
132 [ + - ][ + - ]: 10 : aItemSet.Put( XLineStartCenterItem( false ) );
[ + - ]
133 [ + - ][ + - ]: 10 : aItemSet.Put( XFillStyleItem( XFILL_SOLID ) );
[ + - ]
134 [ + - ][ + - ]: 10 : aItemSet.Put( XFillColorItem( String::EmptyString(), ScDetectiveFunc::GetCommentColor() ) );
[ + - ][ + - ]
[ + - ]
135 [ + - ][ + - ]: 10 : aItemSet.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT ) );
[ + - ]
136 : :
137 : : // shadow
138 : : /* SdrShadowItem has sal_False, instead the shadow is set for the
139 : : rectangle only with SetSpecialTextBoxShadow() when the object is
140 : : created (item must be set to adjust objects from older files). */
141 [ + - ][ + - ]: 10 : aItemSet.Put( SdrShadowItem( false ) );
[ + - ]
142 [ + - ][ + - ]: 10 : aItemSet.Put( SdrShadowXDistItem( 100 ) );
[ + - ]
143 [ + - ][ + - ]: 10 : aItemSet.Put( SdrShadowYDistItem( 100 ) );
[ + - ]
144 : :
145 : : // text attributes
146 [ + - ][ + - ]: 10 : aItemSet.Put( SdrTextLeftDistItem( 100 ) );
[ + - ]
147 [ + - ][ + - ]: 10 : aItemSet.Put( SdrTextRightDistItem( 100 ) );
[ + - ]
148 [ + - ][ + - ]: 10 : aItemSet.Put( SdrTextUpperDistItem( 100 ) );
[ + - ]
149 [ + - ][ + - ]: 10 : aItemSet.Put( SdrTextLowerDistItem( 100 ) );
[ + - ]
150 [ + - ][ + - ]: 10 : aItemSet.Put( SdrTextAutoGrowWidthItem( false ) );
[ + - ]
151 [ + - ][ + - ]: 10 : aItemSet.Put( SdrTextAutoGrowHeightItem( true ) );
[ + - ]
152 : : // use the default cell style to be able to modify the caption font
153 [ + - ][ + - ]: 10 : const ScPatternAttr& rDefPattern = static_cast< const ScPatternAttr& >( rDoc.GetPool()->GetDefaultItem( ATTR_PATTERN ) );
154 [ + - ]: 10 : rDefPattern.FillEditItemSet( &aItemSet );
155 : :
156 [ + - ][ + - ]: 10 : rCaption.SetMergedItemSet( aItemSet );
[ + - ]
157 : 10 : }
158 : :
159 : 5 : void ScCaptionUtil::SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet )
160 : : {
161 : : // copy all items
162 : 5 : rCaption.SetMergedItemSet( rItemSet );
163 : : // reset shadow items
164 [ + - ]: 5 : rCaption.SetMergedItem( SdrShadowItem( false ) );
165 [ + - ]: 5 : rCaption.SetMergedItem( SdrShadowXDistItem( 100 ) );
166 [ + - ]: 5 : rCaption.SetMergedItem( SdrShadowYDistItem( 100 ) );
167 : 5 : rCaption.SetSpecialTextBoxShadow();
168 : 5 : }
169 : :
170 : : // ============================================================================
171 : :
172 : : /** Helper for creation and manipulation of caption drawing objects independent
173 : : from cell annotations. */
174 : : class ScCaptionCreator
175 : : {
176 : : public:
177 : : /** Create a new caption. The caption will not be inserted into the document. */
178 : : explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bShown, bool bTailFront );
179 : : /** Manipulate an existing caption. */
180 : : explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption );
181 : :
182 : : /** Returns the drawing layer page of the sheet contained in maPos. */
183 : : SdrPage* GetDrawPage();
184 : : /** Returns the caption drawing obejct. */
185 : 12 : inline SdrCaptionObj* GetCaption() { return mpCaption; }
186 : :
187 : : /** Moves the caption inside the passed rectangle. Uses page area if 0 is passed. */
188 : : void FitCaptionToRect( const Rectangle* pVisRect = 0 );
189 : : /** Places the caption inside the passed rectangle, tries to keep the cell rectangle uncovered. Uses page area if 0 is passed. */
190 : : void AutoPlaceCaption( const Rectangle* pVisRect = 0 );
191 : : /** Updates caption tail and textbox according to current cell position. Uses page area if 0 is passed. */
192 : : void UpdateCaptionPos( const Rectangle* pVisRect = 0 );
193 : :
194 : : protected:
195 : : /** Helper constructor for derived classes. */
196 : : explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos );
197 : :
198 : : /** Calculates the caption tail position according to current cell position. */
199 : : Point CalcTailPos( bool bTailFront );
200 : : /** Implements creation of the caption object. The caption will not be inserted into the document. */
201 : : void CreateCaption( bool bShown, bool bTailFront );
202 : :
203 : : private:
204 : : /** Initializes all members. */
205 : : void Initialize();
206 : : /** Returns the passed rectangle if existing, page rectangle otherwise. */
207 [ + - ]: 24 : inline const Rectangle& GetVisRect( const Rectangle* pVisRect ) const { return pVisRect ? *pVisRect : maPageRect; }
208 : :
209 : : private:
210 : : ScDocument& mrDoc;
211 : : ScAddress maPos;
212 : : SdrCaptionObj* mpCaption;
213 : : Rectangle maPageRect;
214 : : Rectangle maCellRect;
215 : : bool mbNegPage;
216 : : };
217 : :
218 : : // ----------------------------------------------------------------------------
219 : :
220 : 0 : ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, bool bShown, bool bTailFront ) :
221 : : mrDoc( rDoc ),
222 : : maPos( rPos ),
223 : 0 : mpCaption( 0 )
224 : : {
225 : 0 : Initialize();
226 : 0 : CreateCaption( bShown, bTailFront );
227 : 0 : }
228 : :
229 : 8 : ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption ) :
230 : : mrDoc( rDoc ),
231 : : maPos( rPos ),
232 : 8 : mpCaption( &rCaption )
233 : : {
234 : 8 : Initialize();
235 : 8 : }
236 : :
237 : 15 : ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos ) :
238 : : mrDoc( rDoc ),
239 : : maPos( rPos ),
240 : 15 : mpCaption( 0 )
241 : : {
242 : 15 : Initialize();
243 : 15 : }
244 : :
245 : 38 : SdrPage* ScCaptionCreator::GetDrawPage()
246 : : {
247 : 38 : ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
248 [ + + ]: 38 : return pDrawLayer ? pDrawLayer->GetPage( static_cast< sal_uInt16 >( maPos.Tab() ) ) : 0;
249 : : }
250 : :
251 : 14 : void ScCaptionCreator::FitCaptionToRect( const Rectangle* pVisRect )
252 : : {
253 : 14 : const Rectangle& rVisRect = GetVisRect( pVisRect );
254 : :
255 : : // tail position
256 [ + - ]: 14 : Point aTailPos = mpCaption->GetTailPos();
257 [ + - ][ + - ]: 14 : aTailPos.X() = ::std::max( ::std::min( aTailPos.X(), rVisRect.Right() ), rVisRect.Left() );
258 [ + - ][ + - ]: 14 : aTailPos.Y() = ::std::max( ::std::min( aTailPos.Y(), rVisRect.Bottom() ), rVisRect.Top() );
259 [ + - ]: 14 : mpCaption->SetTailPos( aTailPos );
260 : :
261 : : // caption rectangle
262 [ + - ]: 14 : Rectangle aCaptRect = mpCaption->GetLogicRect();
263 : 14 : Point aCaptPos = aCaptRect.TopLeft();
264 : : // move textbox inside right border of visible area
265 [ + - ][ + - ]: 14 : aCaptPos.X() = ::std::min< long >( aCaptPos.X(), rVisRect.Right() - aCaptRect.GetWidth() );
266 : : // move textbox inside left border of visible area (this may move it outside on right side again)
267 [ + - ]: 14 : aCaptPos.X() = ::std::max< long >( aCaptPos.X(), rVisRect.Left() );
268 : : // move textbox inside bottom border of visible area
269 [ + - ][ + - ]: 14 : aCaptPos.Y() = ::std::min< long >( aCaptPos.Y(), rVisRect.Bottom() - aCaptRect.GetHeight() );
270 : : // move textbox inside top border of visible area (this may move it outside on bottom side again)
271 [ + - ]: 14 : aCaptPos.Y() = ::std::max< long >( aCaptPos.Y(), rVisRect.Top() );
272 : : // update caption
273 : 14 : aCaptRect.SetPos( aCaptPos );
274 [ + - ]: 14 : mpCaption->SetLogicRect( aCaptRect );
275 : 14 : }
276 : :
277 : 10 : void ScCaptionCreator::AutoPlaceCaption( const Rectangle* pVisRect )
278 : : {
279 : 10 : const Rectangle& rVisRect = GetVisRect( pVisRect );
280 : :
281 : : // caption rectangle
282 [ + - ]: 10 : Rectangle aCaptRect = mpCaption->GetLogicRect();
283 [ + - ]: 10 : long nWidth = aCaptRect.GetWidth();
284 [ + - ]: 10 : long nHeight = aCaptRect.GetHeight();
285 : :
286 : : // n***Space contains available space between border of visible area and cell
287 : 10 : long nLeftSpace = maCellRect.Left() - rVisRect.Left() + 1;
288 : 10 : long nRightSpace = rVisRect.Right() - maCellRect.Right() + 1;
289 : 10 : long nTopSpace = maCellRect.Top() - rVisRect.Top() + 1;
290 : 10 : long nBottomSpace = rVisRect.Bottom() - maCellRect.Bottom() + 1;
291 : :
292 : : // nNeeded*** contains textbox dimensions plus needed distances to cell or border of visible area
293 : 10 : long nNeededSpaceX = nWidth + SC_NOTECAPTION_CELLDIST;
294 : 10 : long nNeededSpaceY = nHeight + SC_NOTECAPTION_CELLDIST;
295 : :
296 : : // bFitsWidth*** == true means width of textbox fits into horizontal free space of visible area
297 : 10 : bool bFitsWidthLeft = nNeededSpaceX <= nLeftSpace; // text box width fits into the width left of cell
298 : 10 : bool bFitsWidthRight = nNeededSpaceX <= nRightSpace; // text box width fits into the width right of cell
299 [ + - ]: 10 : bool bFitsWidth = nWidth <= rVisRect.GetWidth(); // text box width fits into width of visible area
300 : :
301 : : // bFitsHeight*** == true means height of textbox fits into vertical free space of visible area
302 : 10 : bool bFitsHeightTop = nNeededSpaceY <= nTopSpace; // text box height fits into the height above cell
303 : 10 : bool bFitsHeightBottom = nNeededSpaceY <= nBottomSpace; // text box height fits into the height below cell
304 [ + - ]: 10 : bool bFitsHeight = nHeight <= rVisRect.GetHeight(); // text box height fits into height of visible area
305 : :
306 : : // bFits*** == true means the textbox fits completely into free space of visible area
307 [ + + ][ + - ]: 10 : bool bFitsLeft = bFitsWidthLeft && bFitsHeight;
308 [ + - ][ + - ]: 10 : bool bFitsRight = bFitsWidthRight && bFitsHeight;
309 [ + - ][ + + ]: 10 : bool bFitsTop = bFitsWidth && bFitsHeightTop;
310 [ + - ][ + - ]: 10 : bool bFitsBottom = bFitsWidth && bFitsHeightBottom;
311 : :
312 : 10 : Point aCaptPos;
313 : : // use left/right placement if possible, or if top/bottom placement not possible
314 [ - + ][ # # ]: 10 : if( bFitsLeft || bFitsRight || (!bFitsTop && !bFitsBottom) )
[ # # ][ + + ]
315 : : {
316 : : // prefer left in RTL sheet and right in LTR sheets
317 [ + + ][ + - ]: 10 : bool bPreferLeft = bFitsLeft && (mbNegPage || !bFitsRight);
[ - + ]
318 [ + - ][ - + ]: 10 : bool bPreferRight = bFitsRight && (!mbNegPage || !bFitsLeft);
[ # # ]
319 : : // move to left, if left is preferred, or if neither left nor right fit and there is more space to the left
320 [ + - ][ - + ]: 10 : if( bPreferLeft || (!bPreferRight && (nLeftSpace > nRightSpace)) )
[ # # ]
321 : 0 : aCaptPos.X() = maCellRect.Left() - SC_NOTECAPTION_CELLDIST - nWidth;
322 : : else // to right
323 : 10 : aCaptPos.X() = maCellRect.Right() + SC_NOTECAPTION_CELLDIST;
324 : : // Y position according to top cell border
325 : 10 : aCaptPos.Y() = maCellRect.Top() + SC_NOTECAPTION_OFFSET_Y;
326 : : }
327 : : else // top or bottom placement
328 : : {
329 : : // X position
330 : 0 : aCaptPos.X() = maCellRect.Left() + SC_NOTECAPTION_OFFSET_X;
331 : : // top placement, if possible
332 [ # # ]: 0 : if( bFitsTop )
333 : 0 : aCaptPos.Y() = maCellRect.Top() - SC_NOTECAPTION_CELLDIST - nHeight;
334 : : else // bottom placement
335 : 0 : aCaptPos.Y() = maCellRect.Bottom() + SC_NOTECAPTION_CELLDIST;
336 : : }
337 : :
338 : : // update textbox position in note caption object
339 : 10 : aCaptRect.SetPos( aCaptPos );
340 [ + - ]: 10 : mpCaption->SetLogicRect( aCaptRect );
341 [ + - ]: 10 : FitCaptionToRect( pVisRect );
342 : 10 : }
343 : :
344 : 8 : void ScCaptionCreator::UpdateCaptionPos( const Rectangle* pVisRect )
345 : : {
346 [ + - ]: 8 : ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
347 : :
348 : : // update caption position
349 [ + - ]: 8 : const Point& rOldTailPos = mpCaption->GetTailPos();
350 [ + - ]: 8 : Point aTailPos = CalcTailPos( false );
351 [ + + ]: 8 : if( rOldTailPos != aTailPos )
352 : : {
353 : : // create drawing undo action
354 [ + - ][ - + ]: 2 : if( pDrawLayer && pDrawLayer->IsRecording() )
[ - + ]
355 [ # # ][ # # ]: 0 : pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoGeoObject( *mpCaption ) );
[ # # ]
356 : : // calculate new caption rectangle (#i98141# handle LTR<->RTL switch correctly)
357 [ + - ]: 2 : Rectangle aCaptRect = mpCaption->GetLogicRect();
358 [ + - ]: 2 : long nDiffX = (rOldTailPos.X() >= 0) ? (aCaptRect.Left() - rOldTailPos.X()) : (rOldTailPos.X() - aCaptRect.Right());
359 [ - + ][ # # ]: 2 : if( mbNegPage ) nDiffX = -nDiffX - aCaptRect.GetWidth();
360 : 2 : long nDiffY = aCaptRect.Top() - rOldTailPos.Y();
361 : 2 : aCaptRect.SetPos( aTailPos + Point( nDiffX, nDiffY ) );
362 : : // set new tail position and caption rectangle
363 [ + - ]: 2 : mpCaption->SetTailPos( aTailPos );
364 [ + - ]: 2 : mpCaption->SetLogicRect( aCaptRect );
365 : : // fit caption into draw page
366 [ + - ]: 2 : FitCaptionToRect( pVisRect );
367 : : }
368 : :
369 : : // update cell position in caption user data
370 [ + - ]: 8 : ScDrawObjData* pCaptData = ScDrawLayer::GetNoteCaptionData( mpCaption, maPos.Tab() );
371 [ + - ][ - + ]: 8 : if( pCaptData && (maPos != pCaptData->maStart) )
[ - + ]
372 : : {
373 : : // create drawing undo action
374 [ # # ][ # # ]: 0 : if( pDrawLayer && pDrawLayer->IsRecording() )
[ # # ]
375 [ # # ][ # # ]: 0 : pDrawLayer->AddCalcUndo( new ScUndoObjData( mpCaption, pCaptData->maStart, pCaptData->maEnd, maPos, pCaptData->maEnd ) );
[ # # ]
376 : : // set new position
377 : 0 : pCaptData->maStart = maPos;
378 : : }
379 : 8 : }
380 : :
381 : 20 : Point ScCaptionCreator::CalcTailPos( bool bTailFront )
382 : : {
383 : : // tail position
384 : 20 : bool bTailLeft = bTailFront != mbNegPage;
385 [ - + ]: 20 : Point aTailPos = bTailLeft ? maCellRect.TopLeft() : maCellRect.TopRight();
386 : : // move caption point 1/10 mm inside cell
387 [ - + ]: 20 : if( bTailLeft ) aTailPos.X() += 10; else aTailPos.X() -= 10;
388 : 20 : aTailPos.Y() += 10;
389 : 20 : return aTailPos;
390 : : }
391 : :
392 : 12 : void ScCaptionCreator::CreateCaption( bool bShown, bool bTailFront )
393 : : {
394 : : // create the caption drawing object
395 [ + - ]: 12 : Rectangle aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH, SC_NOTECAPTION_HEIGHT ) );
396 [ + - ]: 12 : Point aTailPos = CalcTailPos( bTailFront );
397 [ + - ][ + - ]: 12 : mpCaption = new SdrCaptionObj( aTextRect, aTailPos );
398 : : // basic caption settings
399 [ + - ]: 12 : ScCaptionUtil::SetBasicCaptionSettings( *mpCaption, bShown );
400 : 12 : }
401 : :
402 : 23 : void ScCaptionCreator::Initialize()
403 : : {
404 : 23 : maCellRect = ScDrawLayer::GetCellRect( mrDoc, maPos, true );
405 : 23 : mbNegPage = mrDoc.IsNegativePage( maPos.Tab() );
406 [ + + ]: 23 : if( SdrPage* pDrawPage = GetDrawPage() )
407 : : {
408 [ + - ]: 20 : maPageRect = Rectangle( Point( 0, 0 ), pDrawPage->GetSize() );
409 : : /* #i98141# SdrPage::GetSize() returns negative width in RTL mode.
410 : : The call to Rectangle::Adjust() orders left/right coordinate
411 : : accordingly. */
412 : 20 : maPageRect.Justify();
413 : : }
414 : 23 : }
415 : :
416 : : // ============================================================================
417 : :
418 : : /** Helper for creation of permanent caption drawing objects for cell notes. */
419 : : class ScNoteCaptionCreator : public ScCaptionCreator
420 : : {
421 : : public:
422 : : /** Create a new caption object and inserts it into the document. */
423 : : explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData );
424 : : /** Manipulate an existing caption. */
425 : : explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown );
426 : : };
427 : :
428 : : // ----------------------------------------------------------------------------
429 : :
430 : 15 : ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData ) :
431 : 15 : ScCaptionCreator( rDoc, rPos ) // use helper c'tor that does not create the caption yet
432 : : {
433 : 15 : SdrPage* pDrawPage = GetDrawPage();
434 : : OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
435 [ + + ]: 15 : if( pDrawPage )
436 : : {
437 : : // create the caption drawing object
438 : 12 : CreateCaption( rNoteData.mbShown, false );
439 : 12 : rNoteData.mpCaption = GetCaption();
440 : : OSL_ENSURE( rNoteData.mpCaption, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" );
441 [ + - ]: 12 : if( rNoteData.mpCaption )
442 : : {
443 : : // store note position in user data of caption object
444 : 12 : ScCaptionUtil::SetCaptionUserData( *rNoteData.mpCaption, rPos );
445 : : // insert object into draw page
446 : 12 : pDrawPage->InsertObject( rNoteData.mpCaption );
447 : : }
448 : : }
449 : 15 : }
450 : :
451 : 0 : ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown ) :
452 : 0 : ScCaptionCreator( rDoc, rPos, rCaption )
453 : : {
454 : 0 : SdrPage* pDrawPage = GetDrawPage();
455 : : OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" );
456 : : OSL_ENSURE( rCaption.GetPage() == pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" );
457 [ # # ][ # # ]: 0 : if( pDrawPage && (rCaption.GetPage() == pDrawPage) )
[ # # ]
458 : : {
459 : : // store note position in user data of caption object
460 : 0 : ScCaptionUtil::SetCaptionUserData( rCaption, rPos );
461 : : // basic caption settings
462 : 0 : ScCaptionUtil::SetBasicCaptionSettings( rCaption, bShown );
463 : : // set correct tail position
464 [ # # ]: 0 : rCaption.SetTailPos( CalcTailPos( false ) );
465 : : }
466 : 0 : }
467 : :
468 : : } // namespace
469 : :
470 : : // ============================================================================
471 : :
472 [ + - ]: 16 : struct ScCaptionInitData
473 : : {
474 : : typedef ::std::auto_ptr< SfxItemSet > SfxItemSetPtr;
475 : : typedef ::std::auto_ptr< OutlinerParaObject > OutlinerParaObjPtr;
476 : :
477 : : SfxItemSetPtr mxItemSet; /// Caption object formatting.
478 : : OutlinerParaObjPtr mxOutlinerObj; /// Text object with all text portion formatting.
479 : : ::rtl::OUString maSimpleText; /// Simple text without formatting.
480 : : Point maCaptionOffset; /// Caption position relative to cell corner.
481 : : Size maCaptionSize; /// Size of the caption object.
482 : : bool mbDefaultPosSize; /// True = use default position and size for caption.
483 : :
484 : : explicit ScCaptionInitData();
485 : : };
486 : :
487 : : // ----------------------------------------------------------------------------
488 : :
489 : 16 : ScCaptionInitData::ScCaptionInitData() :
490 : 16 : mbDefaultPosSize( true )
491 : : {
492 : 16 : }
493 : :
494 : : // ============================================================================
495 : :
496 : 29 : ScNoteData::ScNoteData( bool bShown ) :
497 : : mpCaption( 0 ),
498 [ + - ]: 29 : mbShown( bShown )
499 : : {
500 : 29 : }
501 : :
502 [ + - ]: 49 : ScNoteData::~ScNoteData()
503 : : {
504 : 49 : }
505 : :
506 : : // ============================================================================
507 : :
508 : 3 : ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, bool bShown ) :
509 : : mrDoc( rDoc ),
510 : 3 : maNoteData( bShown )
511 : : {
512 [ + - ]: 3 : AutoStamp();
513 [ + - ]: 3 : CreateCaption( rPos );
514 : 3 : }
515 : :
516 : 2 : ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNote ) :
517 : : mrDoc( rDoc ),
518 : 2 : maNoteData( rNote.maNoteData )
519 : : {
520 : 2 : maNoteData.mpCaption = 0;
521 [ + - ]: 2 : CreateCaption( rPos, rNote.maNoteData.mpCaption );
522 : 2 : }
523 : :
524 : 17 : ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScNoteData& rNoteData, bool bAlwaysCreateCaption ) :
525 : : mrDoc( rDoc ),
526 : 17 : maNoteData( rNoteData )
527 : : {
528 [ + + ][ + + ]: 17 : if( bAlwaysCreateCaption || maNoteData.mbShown )
529 [ + - ]: 10 : CreateCaptionFromInitData( rPos );
530 : 17 : }
531 : :
532 : 19 : ScPostIt::~ScPostIt()
533 : : {
534 [ + - ]: 19 : RemoveCaption();
535 : 19 : }
536 : :
537 : 3 : ScPostIt* ScPostIt::Clone( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, bool bCloneCaption ) const
538 : : {
539 : 3 : CreateCaptionFromInitData( rOwnPos );
540 [ + - ][ + - ]: 3 : return bCloneCaption ? new ScPostIt( rDestDoc, rDestPos, *this ) : new ScPostIt( rDestDoc, rDestPos, maNoteData, false );
[ + + ]
541 : : }
542 : :
543 : 19 : void ScPostIt::AutoStamp()
544 : : {
545 [ + - ]: 19 : maNoteData.maDate = ScGlobal::pLocaleData->getDate( Date( Date::SYSTEM ) );
546 [ + - ]: 19 : maNoteData.maAuthor = SvtUserOptions().GetID();
547 : 19 : }
548 : :
549 : 15 : const OutlinerParaObject* ScPostIt::GetOutlinerObject() const
550 : : {
551 [ + + ]: 15 : if( maNoteData.mpCaption )
552 : 9 : return maNoteData.mpCaption->GetOutlinerParaObject();
553 [ + - ]: 6 : if( maNoteData.mxInitData.get() )
554 : 6 : return maNoteData.mxInitData->mxOutlinerObj.get();
555 : 15 : return 0;
556 : : }
557 : :
558 : 15 : const EditTextObject* ScPostIt::GetEditTextObject() const
559 : : {
560 : 15 : const OutlinerParaObject* pOPO = GetOutlinerObject();
561 [ + - ]: 15 : return pOPO ? &pOPO->GetTextObject() : 0;
562 : : }
563 : :
564 : 9 : OUString ScPostIt::GetText() const
565 : : {
566 [ + - ]: 9 : if( const EditTextObject* pEditObj = GetEditTextObject() )
567 : : {
568 : 9 : OUStringBuffer aBuffer;
569 [ + + ][ + - ]: 18 : for( sal_uInt16 nPara = 0, nParaCount = pEditObj->GetParagraphCount(); nPara < nParaCount; ++nPara )
570 : : {
571 [ - + ]: 9 : if( nPara > 0 )
572 [ # # ]: 0 : aBuffer.append( sal_Unicode( '\n' ) );
573 [ + - ][ + - ]: 9 : aBuffer.append( pEditObj->GetText( nPara ) );
[ + - ][ + - ]
574 : : }
575 [ + - ]: 9 : return aBuffer.makeStringAndClear();
576 : : }
577 [ # # ]: 0 : if( maNoteData.mxInitData.get() )
578 : 0 : return maNoteData.mxInitData->maSimpleText;
579 : 9 : return OUString();
580 : : }
581 : :
582 : 3 : void ScPostIt::SetText( const ScAddress& rPos, const OUString& rText )
583 : : {
584 : 3 : CreateCaptionFromInitData( rPos );
585 [ - + ]: 3 : if( maNoteData.mpCaption )
586 [ # # ]: 0 : maNoteData.mpCaption->SetText( rText );
587 : 3 : }
588 : :
589 : 6 : SdrCaptionObj* ScPostIt::GetOrCreateCaption( const ScAddress& rPos ) const
590 : : {
591 : 6 : CreateCaptionFromInitData( rPos );
592 : 6 : return maNoteData.mpCaption;
593 : : }
594 : :
595 : 1 : void ScPostIt::ForgetCaption()
596 : : {
597 : : /* This function is used in undo actions to give up the responsibility for
598 : : the caption object which is handled by separate drawing undo actions. */
599 : 1 : maNoteData.mpCaption = 0;
600 : 1 : maNoteData.mxInitData.reset();
601 : 1 : }
602 : :
603 : 0 : void ScPostIt::ShowCaption( const ScAddress& rPos, bool bShow )
604 : : {
605 : 0 : CreateCaptionFromInitData( rPos );
606 : : // no separate drawing undo needed, handled completely inside ScUndoShowHideNote
607 : 0 : maNoteData.mbShown = bShow;
608 [ # # ]: 0 : if( maNoteData.mpCaption )
609 : 0 : ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, bShow );
610 : 0 : }
611 : :
612 : 0 : void ScPostIt::ShowCaptionTemp( const ScAddress& rPos, bool bShow )
613 : : {
614 : 0 : CreateCaptionFromInitData( rPos );
615 [ # # ]: 0 : if( maNoteData.mpCaption )
616 [ # # ][ # # ]: 0 : ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, maNoteData.mbShown || bShow );
617 : 0 : }
618 : :
619 : 8 : void ScPostIt::UpdateCaptionPos( const ScAddress& rPos )
620 : : {
621 : 8 : CreateCaptionFromInitData( rPos );
622 [ + - ]: 8 : if( maNoteData.mpCaption )
623 : : {
624 [ + - ]: 8 : ScCaptionCreator aCreator( mrDoc, rPos, *maNoteData.mpCaption );
625 [ + - ]: 8 : aCreator.UpdateCaptionPos();
626 : : }
627 : 8 : }
628 : :
629 : : // private --------------------------------------------------------------------
630 : :
631 : 30 : void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const
632 : : {
633 : : OSL_ENSURE( maNoteData.mpCaption || maNoteData.mxInitData.get(), "ScPostIt::CreateCaptionFromInitData - need caption object or initial caption data" );
634 [ + + ]: 30 : if( maNoteData.mxInitData.get() )
635 : : {
636 : : /* This function is called from ScPostIt::Clone() when copying cells
637 : : to the clipboard/undo document, and when copying cells from the
638 : : clipboard/undo document. The former should always be called first,
639 : : so if called in an clipboard/undo document, the caption should have
640 : : been created already. */
641 : : OSL_ENSURE( !mrDoc.IsUndo() && !mrDoc.IsClipboard(), "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" );
642 : :
643 : : /* #i104915# Never try to create notes in Undo document, leads to
644 : : crash due to missing document members (e.g. row height array). */
645 [ + - ][ + - ]: 10 : if( !maNoteData.mpCaption && !mrDoc.IsUndo() )
[ + - ]
646 : : {
647 : : // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
648 [ + - ]: 10 : ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
649 [ + - ]: 10 : if( maNoteData.mpCaption )
650 : : {
651 : 10 : ScCaptionInitData& rInitData = *maNoteData.mxInitData;
652 : :
653 : : // transfer ownership of outliner object to caption, or set simple text
654 : : OSL_ENSURE( rInitData.mxOutlinerObj.get() || !rInitData.maSimpleText.isEmpty(),
655 : : "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" );
656 [ + + ]: 10 : if( rInitData.mxOutlinerObj.get() )
657 [ + - ]: 5 : maNoteData.mpCaption->SetOutlinerParaObject( rInitData.mxOutlinerObj.release() );
658 : : else
659 [ + - ][ + - ]: 5 : maNoteData.mpCaption->SetText( rInitData.maSimpleText );
[ + - ]
660 : :
661 : : // copy all items or set default items; reset shadow items
662 [ + - ]: 10 : ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
663 [ + + ]: 10 : if( rInitData.mxItemSet.get() )
664 [ + - ]: 5 : ScCaptionUtil::SetCaptionItems( *maNoteData.mpCaption, *rInitData.mxItemSet );
665 : :
666 : : // set position and size of the caption object
667 [ + - ]: 10 : if( rInitData.mbDefaultPosSize )
668 : : {
669 : : // set other items and fit caption size to text
670 [ + - ][ + - ]: 10 : maNoteData.mpCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
[ + - ]
671 [ + - ][ + - ]: 10 : maNoteData.mpCaption->SetMergedItem( SdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) );
[ + - ]
672 [ + - ]: 10 : maNoteData.mpCaption->AdjustTextFrameWidthAndHeight();
673 [ + - ]: 10 : aCreator.AutoPlaceCaption();
674 : : }
675 : : else
676 : : {
677 [ # # ]: 0 : Rectangle aCellRect = ScDrawLayer::GetCellRect( mrDoc, rPos, true );
678 [ # # ]: 0 : bool bNegPage = mrDoc.IsNegativePage( rPos.Tab() );
679 [ # # ]: 0 : long nPosX = bNegPage ? (aCellRect.Left() - rInitData.maCaptionOffset.X()) : (aCellRect.Right() + rInitData.maCaptionOffset.X());
680 : 0 : long nPosY = aCellRect.Top() + rInitData.maCaptionOffset.Y();
681 [ # # ]: 0 : Rectangle aCaptRect( Point( nPosX, nPosY ), rInitData.maCaptionSize );
682 [ # # ]: 0 : maNoteData.mpCaption->SetLogicRect( aCaptRect );
683 [ # # ]: 10 : aCreator.FitCaptionToRect();
684 : : }
685 : : }
686 : : }
687 : : // forget the initial caption data struct
688 : 10 : maNoteData.mxInitData.reset();
689 : : }
690 : 30 : }
691 : :
692 : 5 : void ScPostIt::CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption )
693 : : {
694 : : OSL_ENSURE( !maNoteData.mpCaption, "ScPostIt::CreateCaption - unexpected caption object found" );
695 : 5 : maNoteData.mpCaption = 0;
696 : :
697 : : /* #i104915# Never try to create notes in Undo document, leads to
698 : : crash due to missing document members (e.g. row height array). */
699 : : OSL_ENSURE( !mrDoc.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" );
700 [ + - ]: 5 : if( mrDoc.IsUndo() )
701 : 5 : return;
702 : :
703 : : // drawing layer may be missing, if a note is copied into a clipboard document
704 [ - + ]: 5 : if( mrDoc.IsClipboard() )
705 [ # # ]: 0 : mrDoc.InitDrawLayer();
706 : :
707 : : // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData
708 [ + - ]: 5 : ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData );
709 [ + + ]: 5 : if( maNoteData.mpCaption )
710 : : {
711 : : // clone settings of passed caption
712 [ + - ]: 2 : if( pCaption )
713 : : {
714 : : // copy edit text object (object must be inserted into page already)
715 [ + - ][ + - ]: 2 : if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
716 [ + - ][ + - ]: 2 : maNoteData.mpCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
[ + - ]
717 : : // copy formatting items (after text has been copied to apply font formatting)
718 [ + - ][ + - ]: 2 : maNoteData.mpCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() );
719 : : // move textbox position relative to new cell, copy textbox size
720 [ + - ]: 2 : Rectangle aCaptRect = pCaption->GetLogicRect();
721 [ + - ][ + - ]: 2 : Point aDist = maNoteData.mpCaption->GetTailPos() - pCaption->GetTailPos();
722 [ + - ]: 2 : aCaptRect.Move( aDist.X(), aDist.Y() );
723 [ + - ]: 2 : maNoteData.mpCaption->SetLogicRect( aCaptRect );
724 [ + - ]: 2 : aCreator.FitCaptionToRect();
725 : : }
726 : : else
727 : : {
728 : : // set default formatting and default position
729 [ # # ]: 0 : ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc );
730 [ # # ]: 0 : aCreator.AutoPlaceCaption();
731 : : }
732 : :
733 : : // create undo action
734 [ + - ][ + - ]: 2 : if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() )
735 [ - + ]: 2 : if( pDrawLayer->IsRecording() )
736 [ # # ][ # # ]: 5 : pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoNewObject( *maNoteData.mpCaption ) );
[ # # ]
737 : : }
738 : : }
739 : :
740 : 19 : void ScPostIt::RemoveCaption()
741 : : {
742 : :
743 : : /* Remove caption object only, if this note is its owner (e.g. notes in
744 : : undo documents refer to captions in original document, do not remove
745 : : them from drawing layer here). */
746 : 19 : ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer();
747 [ + + ][ + + ]: 19 : if( maNoteData.mpCaption && (pDrawLayer == maNoteData.mpCaption->GetModel()) )
[ + + ]
748 : : {
749 : : OSL_ENSURE( pDrawLayer, "ScPostIt::RemoveCaption - object without drawing layer" );
750 : 11 : SdrPage* pDrawPage = maNoteData.mpCaption->GetPage();
751 : : OSL_ENSURE( pDrawPage, "ScPostIt::RemoveCaption - object without drawing page" );
752 [ + - ]: 11 : if( pDrawPage )
753 : : {
754 [ + - ]: 11 : pDrawPage->RecalcObjOrdNums();
755 : : // create drawing undo action (before removing the object to have valid draw page in undo action)
756 [ + - ][ - + ]: 11 : bool bRecording = ( pDrawLayer && pDrawLayer->IsRecording() );
757 [ - + ]: 11 : if( bRecording )
758 [ # # ][ # # ]: 0 : pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoDeleteObject( *maNoteData.mpCaption ) );
[ # # ]
759 : : // remove the object from the drawing page, delete if undo is disabled
760 [ + - ][ + - ]: 11 : SdrObject* pObj = pDrawPage->RemoveObject( maNoteData.mpCaption->GetOrdNum() );
761 [ + - ]: 11 : if( !bRecording )
762 [ + - ]: 11 : SdrObject::Free( pObj );
763 : : }
764 : : }
765 : 19 : maNoteData.mpCaption = 0;
766 : 19 : }
767 : :
768 : : // ============================================================================
769 : :
770 : 8 : void ScNoteUtil::UpdateCaptionPositions( ScDocument& rDoc, const ScRange& rRange )
771 : : {
772 : : // do not use ScCellIterator, it skips filtered and subtotal cells
773 [ + - ][ + + ]: 16 : for( ScAddress aPos( rRange.aStart ); aPos.Tab() <= rRange.aEnd.Tab(); aPos.IncTab() )
774 [ + - ][ + + ]: 40 : for( aPos.SetCol( rRange.aStart.Col() ); aPos.Col() <= rRange.aEnd.Col(); aPos.IncCol() )
775 [ + - ][ + + ]: 160 : for( aPos.SetRow( rRange.aStart.Row() ); aPos.Row() <= rRange.aEnd.Row(); aPos.IncRow() )
776 [ + - ][ + - ]: 128 : if( ScPostIt* pNote = rDoc.GetNotes(aPos.Tab())->findByAddress( aPos ) )
[ - + ]
777 [ # # ]: 0 : pNote->UpdateCaptionPos( aPos );
778 : 8 : }
779 : :
780 : 0 : SdrCaptionObj* ScNoteUtil::CreateTempCaption(
781 : : ScDocument& rDoc, const ScAddress& rPos, SdrPage& rDrawPage,
782 : : const OUString& rUserText, const Rectangle& rVisRect, bool bTailFront )
783 : : {
784 [ # # ]: 0 : OUStringBuffer aBuffer( rUserText );
785 : : // add plain text of invisible (!) cell note (no formatting etc.)
786 : 0 : SdrCaptionObj* pNoteCaption = 0;
787 [ # # ][ # # ]: 0 : const ScPostIt* pNote = rDoc.GetNotes(rPos.Tab())->findByAddress( rPos );
788 [ # # ][ # # ]: 0 : if( pNote && !pNote->IsCaptionShown() )
[ # # ]
789 : : {
790 [ # # ]: 0 : if( aBuffer.getLength() > 0 )
791 [ # # ][ # # ]: 0 : aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\n--------\n" ) ).append( pNote->GetText() );
[ # # ]
792 [ # # ]: 0 : pNoteCaption = pNote->GetOrCreateCaption( rPos );
793 : : }
794 : :
795 : : // create a caption if any text exists
796 [ # # ][ # # ]: 0 : if( !pNoteCaption && (aBuffer.getLength() == 0) )
[ # # ]
797 : 0 : return 0;
798 : :
799 : : // prepare visible rectangle (add default distance to all borders)
800 : : Rectangle aVisRect(
801 : 0 : rVisRect.Left() + SC_NOTECAPTION_BORDERDIST_TEMP,
802 : 0 : rVisRect.Top() + SC_NOTECAPTION_BORDERDIST_TEMP,
803 : 0 : rVisRect.Right() - SC_NOTECAPTION_BORDERDIST_TEMP,
804 [ # # ]: 0 : rVisRect.Bottom() - SC_NOTECAPTION_BORDERDIST_TEMP );
805 : :
806 : : // create the caption object
807 [ # # ]: 0 : ScCaptionCreator aCreator( rDoc, rPos, true, bTailFront );
808 : 0 : SdrCaptionObj* pCaption = aCreator.GetCaption();
809 : :
810 : : // insert caption into page (needed to set caption text)
811 [ # # ]: 0 : rDrawPage.InsertObject( pCaption );
812 : :
813 : : // clone the edit text object, unless user text is present, then set this text
814 [ # # ][ # # ]: 0 : if( pNoteCaption && rUserText.isEmpty() )
[ # # ]
815 : : {
816 [ # # ][ # # ]: 0 : if( OutlinerParaObject* pOPO = pNoteCaption->GetOutlinerParaObject() )
817 [ # # ][ # # ]: 0 : pCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
[ # # ]
818 : : // set formatting (must be done after setting text) and resize the box to fit the text
819 [ # # ][ # # ]: 0 : pCaption->SetMergedItemSetAndBroadcast( pNoteCaption->GetMergedItemSet() );
820 [ # # ][ # # ]: 0 : Rectangle aCaptRect( pCaption->GetLogicRect().TopLeft(), pNoteCaption->GetLogicRect().GetSize() );
[ # # ][ # # ]
821 [ # # ]: 0 : pCaption->SetLogicRect( aCaptRect );
822 : : }
823 : : else
824 : : {
825 : : // if pNoteCaption is null, then aBuffer contains some text
826 [ # # ][ # # ]: 0 : pCaption->SetText( aBuffer.makeStringAndClear() );
[ # # ][ # # ]
827 [ # # ]: 0 : ScCaptionUtil::SetDefaultItems( *pCaption, rDoc );
828 : : // adjust caption size to text size
829 [ # # ][ # # ]: 0 : long nMaxWidth = ::std::min< long >( aVisRect.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP );
830 [ # # ][ # # ]: 0 : pCaption->SetMergedItem( SdrTextAutoGrowWidthItem( sal_True ) );
[ # # ]
831 [ # # ][ # # ]: 0 : pCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) );
[ # # ]
832 [ # # ][ # # ]: 0 : pCaption->SetMergedItem( SdrTextMaxFrameWidthItem( nMaxWidth ) );
[ # # ]
833 [ # # ][ # # ]: 0 : pCaption->SetMergedItem( SdrTextAutoGrowHeightItem( sal_True ) );
[ # # ]
834 [ # # ]: 0 : pCaption->AdjustTextFrameWidthAndHeight();
835 : : }
836 : :
837 : : // move caption into visible area
838 [ # # ]: 0 : aCreator.AutoPlaceCaption( &aVisRect );
839 : 0 : return pCaption;
840 : : }
841 : :
842 : 0 : ScPostIt* ScNoteUtil::CreateNoteFromCaption(
843 : : ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown )
844 : : {
845 [ # # ]: 0 : ScNoteData aNoteData( bShown );
846 : 0 : aNoteData.mpCaption = &rCaption;
847 [ # # ][ # # ]: 0 : ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, false );
848 [ # # ]: 0 : pNote->AutoStamp();
849 : :
850 : : // if pNote still points to the note after TakeNote(), insertion was successful
851 [ # # ][ # # ]: 0 : if( rDoc.GetNotes(rPos.Tab())->insert( rPos, pNote ) )
[ # # ]
852 : : {
853 : : // ScNoteCaptionCreator c'tor updates the caption object to be part of a note
854 [ # # ]: 0 : ScNoteCaptionCreator aCreator( rDoc, rPos, rCaption, bShown );
855 : : }
856 [ # # ]: 0 : return pNote;
857 : : }
858 : :
859 : 11 : ScPostIt* ScNoteUtil::CreateNoteFromObjectData(
860 : : ScDocument& rDoc, const ScAddress& rPos, SfxItemSet* pItemSet,
861 : : OutlinerParaObject* pOutlinerObj, const Rectangle& rCaptionRect,
862 : : bool bShown, bool bAlwaysCreateCaption )
863 : : {
864 : : OSL_ENSURE( pItemSet && pOutlinerObj, "ScNoteUtil::CreateNoteFromObjectData - item set and outliner object expected" );
865 [ + - ]: 11 : ScNoteData aNoteData( bShown );
866 [ + - ][ + - ]: 11 : aNoteData.mxInitData.reset( new ScCaptionInitData );
[ + - ]
867 : 11 : ScCaptionInitData& rInitData = *aNoteData.mxInitData;
868 : 11 : rInitData.mxItemSet.reset( pItemSet );
869 : 11 : rInitData.mxOutlinerObj.reset( pOutlinerObj );
870 : :
871 : : // convert absolute caption position to relative position
872 [ + - ]: 11 : rInitData.mbDefaultPosSize = rCaptionRect.IsEmpty();
873 [ + + ]: 11 : if( !rInitData.mbDefaultPosSize )
874 : : {
875 [ + - ]: 6 : Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, rPos, true );
876 [ + - ]: 6 : bool bNegPage = rDoc.IsNegativePage( rPos.Tab() );
877 [ - + ]: 6 : rInitData.maCaptionOffset.X() = bNegPage ? (aCellRect.Left() - rCaptionRect.Right()) : (rCaptionRect.Left() - aCellRect.Right());
878 : 6 : rInitData.maCaptionOffset.Y() = rCaptionRect.Top() - aCellRect.Top();
879 [ + - ]: 6 : rInitData.maCaptionSize = rCaptionRect.GetSize();
880 : : }
881 : :
882 : : /* Create the note and insert it into the document. If the note is
883 : : visible, the caption object will be created automatically. */
884 [ + - ][ + - ]: 11 : ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
885 [ + - ]: 11 : pNote->AutoStamp();
886 [ + - ][ + - ]: 11 : if(rDoc.GetNotes(rPos.Tab())->insert( rPos, pNote ))
[ + - ]
887 : 11 : return pNote;
888 : : else
889 [ + - ]: 11 : return NULL;
890 : : }
891 : :
892 : 5 : ScPostIt* ScNoteUtil::CreateNoteFromString(
893 : : ScDocument& rDoc, const ScAddress& rPos, const OUString& rNoteText,
894 : : bool bShown, bool bAlwaysCreateCaption )
895 : : {
896 : 5 : ScPostIt* pNote = 0;
897 [ + - ]: 5 : if( !rNoteText.isEmpty() )
898 : : {
899 [ + - ]: 5 : ScNoteData aNoteData( bShown );
900 [ + - ][ + - ]: 5 : aNoteData.mxInitData.reset( new ScCaptionInitData );
[ + - ]
901 : 5 : ScCaptionInitData& rInitData = *aNoteData.mxInitData;
902 : 5 : rInitData.maSimpleText = rNoteText;
903 : 5 : rInitData.mbDefaultPosSize = true;
904 : :
905 : : /* Create the note and insert it into the document. If the note is
906 : : visible, the caption object will be created automatically. */
907 [ + - ][ + - ]: 5 : pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption );
908 [ + - ]: 5 : pNote->AutoStamp();
909 : : //insert takes ownership
910 [ + - ][ + - ]: 5 : if(!rDoc.GetNotes(rPos.Tab())->insert( rPos, pNote ))
[ - + ]
911 [ + - ]: 5 : pNote = NULL;
912 : : }
913 : 5 : return pNote;
914 : : }
915 : :
916 : : // ============================================================================
917 : : // ScNotes
918 : : // ============================================================================
919 : :
920 : 2006 : ScNotes::ScNotes(ScDocument* pDoc):
921 : 2006 : mpDoc(pDoc)
922 : : {
923 : :
924 : 2006 : }
925 : :
926 : 1804 : ScNotes::~ScNotes()
927 : : {
928 [ + - ]: 1804 : clear();
929 : 1804 : }
930 : :
931 : 124 : ScNotes::iterator ScNotes::begin()
932 : : {
933 : 124 : return maNoteMap.begin();
934 : : }
935 : :
936 : 136 : ScNotes::iterator ScNotes::end()
937 : : {
938 : 136 : return maNoteMap.end();
939 : : }
940 : :
941 : 3895 : ScNotes::const_iterator ScNotes::begin() const
942 : : {
943 : 3895 : return maNoteMap.begin();
944 : : }
945 : :
946 : 3900 : ScNotes::const_iterator ScNotes::end() const
947 : : {
948 : 3900 : return maNoteMap.end();
949 : : }
950 : :
951 : 10 : size_t ScNotes::size() const
952 : : {
953 : 10 : return maNoteMap.size();
954 : : }
955 : :
956 : 0 : bool ScNotes::empty() const
957 : : {
958 : 0 : return maNoteMap.empty();
959 : : }
960 : :
961 : 150866 : ScPostIt* ScNotes::findByAddress(SCCOL nCol, SCROW nRow)
962 : : {
963 [ + - ][ + - ]: 150866 : ScNoteMap::iterator itr = maNoteMap.find(std::pair<SCCOL, SCROW>(nCol, nRow));
964 [ + - ][ + + ]: 150866 : if (itr != maNoteMap.end())
965 [ + - ]: 53 : return itr->second;
966 : :
967 : 150866 : return NULL;
968 : : }
969 : :
970 : 0 : const ScPostIt* ScNotes::findByAddress(SCCOL nCol, SCROW nRow) const
971 : : {
972 [ # # ][ # # ]: 0 : ScNoteMap::const_iterator itr = maNoteMap.find(std::pair<SCCOL, SCROW>(nCol, nRow));
973 [ # # ][ # # ]: 0 : if (itr != maNoteMap.end())
974 [ # # ]: 0 : return itr->second;
975 : :
976 : 0 : return NULL;
977 : : }
978 : :
979 : 280 : ScPostIt* ScNotes::findByAddress(const ScAddress& rPos)
980 : : {
981 : 280 : return findByAddress(rPos.Col(), rPos.Row());
982 : : }
983 : :
984 : 0 : const ScPostIt* ScNotes::findByAddress(const ScAddress& rPos) const
985 : : {
986 : 0 : return findByAddress(rPos.Col(), rPos.Row());
987 : : }
988 : :
989 : 34 : bool ScNotes::insert(SCCOL nCol, SCROW nRow, ScPostIt* pPostIt)
990 : : {
991 [ + - ][ + - ]: 34 : std::pair<iterator, bool> aResult = maNoteMap.insert(std::pair<ScAddress2D, ScPostIt*>(std::pair<SCCOL, SCROW>(nCol, nRow), pPostIt));
[ + - ]
992 [ - + ]: 34 : if (!aResult.second)
993 [ # # ][ # # ]: 0 : delete pPostIt;
994 : :
995 : 34 : return aResult.second;
996 : : }
997 : :
998 : 19 : bool ScNotes::insert(const ScAddress& rPos, ScPostIt* pPostIt)
999 : : {
1000 : 19 : return insert(rPos.Col(), rPos.Row(), pPostIt);
1001 : : }
1002 : :
1003 : 4 : void ScNotes::erase(SCCOL nCol, SCROW nRow, bool bForgetCaption)
1004 : : {
1005 [ + - ][ + - ]: 4 : iterator itr = maNoteMap.find(std::pair<SCCOL, SCROW>(nCol, nRow));
1006 [ + - ][ + + ]: 4 : if (itr != maNoteMap.end())
1007 : : {
1008 [ + - ]: 1 : if (bForgetCaption)
1009 [ + - ][ + - ]: 1 : itr->second->ForgetCaption();
1010 : :
1011 [ + - ][ + - ]: 1 : delete itr->second;
[ + - ]
1012 [ + - ]: 1 : maNoteMap.erase(itr);
1013 : : }
1014 : 4 : }
1015 : :
1016 : 0 : void ScNotes::erase(const ScAddress& rPos)
1017 : : {
1018 : 0 : erase(rPos.Col(), rPos.Row());
1019 : 0 : }
1020 : :
1021 : 17 : ScPostIt* ScNotes::ReleaseNote(SCCOL nCol, SCROW nRow)
1022 : : {
1023 : 17 : ScPostIt* pPostIt = NULL;
1024 [ + - ][ + - ]: 17 : iterator itr = maNoteMap.find(std::pair<SCCOL, SCROW>(nCol, nRow));
1025 [ + - ][ + + ]: 17 : if (itr!= maNoteMap.end())
1026 : : {
1027 [ + - ]: 12 : pPostIt = itr->second;
1028 [ + - ]: 12 : maNoteMap.erase(itr);
1029 : : }
1030 : 17 : return pPostIt;
1031 : : }
1032 : :
1033 : 5 : ScPostIt* ScNotes::ReleaseNote(const ScAddress& rPos)
1034 : : {
1035 : 5 : return ReleaseNote(rPos.Col(), rPos.Row());
1036 : : }
1037 : :
1038 : 3 : ScPostIt* ScNotes::GetOrCreateNote(const ScAddress& rPos)
1039 : : {
1040 [ + - ][ + - ]: 3 : iterator itr = maNoteMap.find(std::pair<SCCOL, SCROW>(rPos.Col(), rPos.Row()));
1041 [ + - ][ - + ]: 3 : if (itr != maNoteMap.end())
1042 [ # # ]: 0 : return itr->second;
1043 : : else
1044 : : {
1045 [ + - ][ + - ]: 3 : ScPostIt* pPostIt = new ScPostIt(*mpDoc, rPos, false);
1046 [ + - ]: 3 : insert(rPos, pPostIt);
1047 : 3 : return pPostIt;
1048 : : }
1049 : : }
1050 : :
1051 : 1804 : void ScNotes::clear()
1052 : : {
1053 [ + - ][ + - ]: 1822 : for (iterator itr = maNoteMap.begin(); itr != maNoteMap.end(); ++itr)
[ + + ]
1054 : : {
1055 [ + - ][ + - ]: 18 : delete itr->second;
[ + - ]
1056 : : }
1057 : 1804 : maNoteMap.clear();
1058 : 1804 : }
1059 : :
1060 : 12 : ScNotes* ScNotes::clone(ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bCloneNoteCaption, SCTAB nTab)
1061 : : {
1062 [ + - ]: 12 : ScNotes* pNotes = new ScNotes(pDoc);
1063 [ + - ][ + - ]: 15 : for (ScNotes::iterator itr = maNoteMap.begin(); itr != maNoteMap.end(); ++itr)
[ + + ]
1064 : : {
1065 [ + - ]: 3 : SCCOL nCol = itr->first.first;
1066 [ + - ]: 3 : SCROW nRow = itr->first.second;
1067 : :
1068 [ + - ][ - + ]: 3 : if (nCol >= nCol1 && nCol <= nCol2 && nRow >= nRow1 && nRow <= nRow2)
[ # # ][ # # ]
1069 : : {
1070 [ # # ][ # # ]: 0 : pNotes->insert(nCol, nRow, itr->second->Clone( ScAddress(nCol, nRow, nTab),*pDoc, ScAddress(nCol, nRow, nTab), bCloneNoteCaption));
[ # # ]
1071 : : }
1072 : : }
1073 : 12 : return pNotes;
1074 : : }
1075 : :
1076 : 305 : void ScNotes::CopyFromClip(const ScNotes& rNotes, ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCsCOL nDx, SCsROW nDy, SCTAB nTab, bool bCloneCaption)
1077 : : {
1078 [ + - ][ + - ]: 309 : for (ScNotes::const_iterator itr = rNotes.begin(); itr != rNotes.end(); ++itr)
[ + - ][ + - ]
[ + + ]
1079 : : {
1080 [ + - ]: 4 : SCCOL nCol = itr->first.first;
1081 [ + - ]: 4 : SCROW nRow = itr->first.second;
1082 [ + + ][ + - ]: 4 : if (nCol+nDx >= nCol1 && nCol+nDx <= nCol2 && nRow+nDy >= nRow1 && nRow+nDy <= nRow2)
[ + - ][ + - ]
1083 : : {
1084 [ + - ]: 3 : erase(nCol+nDx, nRow+nDy);
1085 [ + - ][ + - ]: 3 : insert(nCol+nDx, nRow+nDy, itr->second->Clone( ScAddress(nCol, nRow, nTab), *pDoc, ScAddress(nCol+nDx, nRow+nDy, nTab), bCloneCaption ));
[ + - ]
1086 : : }
1087 : : }
1088 : 305 : }
1089 : :
1090 : 897 : void ScNotes::erase(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bForgetCaption)
1091 : : {
1092 : 897 : ScNotes::iterator itr = maNoteMap.begin();
1093 [ + - ][ + + ]: 899 : while(itr != maNoteMap.end())
1094 : : {
1095 [ + - ]: 2 : SCCOL nCol = itr->first.first;
1096 [ + - ]: 2 : SCROW nRow = itr->first.second;
1097 [ + - ]: 2 : ++itr;
1098 [ + + ][ + - ]: 2 : if (nCol >= nCol1 && nCol <= nCol2 && nRow >= nRow1 && nRow <= nRow2)
[ + - ][ + - ]
1099 : : {
1100 [ + - ]: 1 : erase(nCol, nRow, bForgetCaption);
1101 : : }
1102 : : }
1103 : 897 : }
1104 : :
1105 : 4 : void ScNotes::CreateAllNoteCaptions(SCTAB nTab)
1106 : : {
1107 [ + - ][ + - ]: 4 : for(iterator itr = begin(), itrEnd = end(); itr != itrEnd; ++itr)
[ # # ][ + - ]
[ - + ]
1108 : : {
1109 [ # # ][ # # ]: 0 : itr->second->GetOrCreateCaption(ScAddress(itr->first.first, itr->first.second, nTab));
[ # # ][ # # ]
1110 : : }
1111 : 4 : }
1112 : :
1113 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|