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