xref: /AOO41X/main/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 #include <tolayoutanchoredobjectposition.hxx>
31 #include <anchoredobject.hxx>
32 #include <frame.hxx>
33 #include <pagefrm.hxx>
34 #include <svx/svdobj.hxx>
35 #include <frmfmt.hxx>
36 #include <fmtanchr.hxx>
37 #include <fmtornt.hxx>
38 #include <fmtsrnd.hxx>
39 #include <IDocumentSettingAccess.hxx>
40 #include <frmatr.hxx>
41 #include "viewsh.hxx"
42 #include "viewopt.hxx"
43 #include "rootfrm.hxx"
44 #include <editeng/lrspitem.hxx>
45 #include <editeng/ulspitem.hxx>
46 
47 using namespace objectpositioning;
48 using namespace ::com::sun::star;
49 
50 
51 SwToLayoutAnchoredObjectPosition::SwToLayoutAnchoredObjectPosition( SdrObject& _rDrawObj )
52     : SwAnchoredObjectPosition( _rDrawObj ),
53       maRelPos( Point() ),
54       // --> OD 2004-06-17 #i26791#
55       maOffsetToFrmAnchorPos( Point() )
56 {}
57 
58 SwToLayoutAnchoredObjectPosition::~SwToLayoutAnchoredObjectPosition()
59 {}
60 
61 /** calculate position for object position type TO_LAYOUT
62 
63     @author OD
64 */
65 void SwToLayoutAnchoredObjectPosition::CalcPosition()
66 {
67     const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
68 
69     SWRECTFN( (&GetAnchorFrm()) );
70 
71     const SwFrmFmt& rFrmFmt = GetFrmFmt();
72     const SvxLRSpaceItem &rLR = rFrmFmt.GetLRSpace();
73     const SvxULSpaceItem &rUL = rFrmFmt.GetULSpace();
74 
75     const bool bFlyAtFly = FLY_AT_FLY == rFrmFmt.GetAnchor().GetAnchorId();
76 
77     // determine position.
78     // 'vertical' and 'horizontal' position are calculated separately
79     Point aRelPos;
80 
81     // calculate 'vertical' position
82     SwFmtVertOrient aVert( rFrmFmt.GetVertOrient() );
83     {
84         // to-frame anchored objects are *only* vertical positioned centered or
85         // bottom, if its wrap mode is 'throught' and its anchor frame has fixed
86         // size. Otherwise, it's positioned top.
87         sal_Int16 eVertOrient = aVert.GetVertOrient();
88         if ( ( bFlyAtFly &&
89                ( eVertOrient == text::VertOrientation::CENTER ||
90                  eVertOrient == text::VertOrientation::BOTTOM ) &&
91              SURROUND_THROUGHT != rFrmFmt.GetSurround().GetSurround() &&
92              !GetAnchorFrm().HasFixSize() ) )
93         {
94             eVertOrient = text::VertOrientation::TOP;
95         }
96         // --> OD 2004-06-17 #i26791# - get vertical offset to frame anchor position.
97         SwTwips nVertOffsetToFrmAnchorPos( 0L );
98         SwTwips nRelPosY =
99                 _GetVertRelPos( GetAnchorFrm(), GetAnchorFrm(), eVertOrient,
100                                 aVert.GetRelationOrient(), aVert.GetPos(),
101                                 rLR, rUL, nVertOffsetToFrmAnchorPos );
102 
103 
104         // keep the calculated relative vertical position - needed for filters
105         // (including the xml-filter)
106         {
107             SwTwips nAttrRelPosY = nRelPosY - nVertOffsetToFrmAnchorPos;
108             if ( aVert.GetVertOrient() != text::VertOrientation::NONE &&
109                  aVert.GetPos() != nAttrRelPosY )
110             {
111                 aVert.SetPos( nAttrRelPosY );
112                 const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
113                 const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
114                 const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
115             }
116         }
117 
118         // determine absolute 'vertical' position, depending on layout-direction
119         // --> OD 2004-06-17 #i26791# - determine offset to 'vertical' frame
120         // anchor position, depending on layout-direction
121         if( bVert )
122         {
123             ASSERT( !bRev, "<SwToLayoutAnchoredObjectPosition::CalcPosition()> - reverse layout set." );
124             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
125             if ( bVertL2R )
126                	aRelPos.X() = nRelPosY;
127             else
128                	aRelPos.X() = -nRelPosY - aObjBoundRect.Width();
129             maOffsetToFrmAnchorPos.X() = nVertOffsetToFrmAnchorPos;
130         }
131         else
132         {
133             aRelPos.Y() = nRelPosY;
134             maOffsetToFrmAnchorPos.Y() = nVertOffsetToFrmAnchorPos;
135         }
136 
137         // if in online-layout the bottom of to-page anchored object is beyond
138         // the page bottom, the page frame has to grow by growing its body frame.
139         const ViewShell *pSh = GetAnchorFrm().getRootFrm()->GetCurrShell();
140         if ( !bFlyAtFly && GetAnchorFrm().IsPageFrm() &&
141              pSh && pSh->GetViewOptions()->getBrowseMode() )
142         {
143             const long nAnchorBottom = GetAnchorFrm().Frm().Bottom();
144             const long nBottom = GetAnchorFrm().Frm().Top() +
145                                  aRelPos.Y() + aObjBoundRect.Height();
146             if ( nAnchorBottom < nBottom )
147             {
148                 static_cast<SwPageFrm&>(GetAnchorFrm()).
149                         FindBodyCont()->Grow( nBottom - nAnchorBottom );
150             }
151         }
152     } // end of determination of vertical position
153 
154     // calculate 'horizontal' position
155     SwFmtHoriOrient aHori( rFrmFmt.GetHoriOrient() );
156     {
157         // consider toggle of horizontal position for even pages.
158         const bool bToggle = aHori.IsPosToggle() &&
159                              !GetAnchorFrm().FindPageFrm()->OnRightPage();
160         sal_Int16 eHoriOrient = aHori.GetHoriOrient();
161         sal_Int16 eRelOrient = aHori.GetRelationOrient();
162         // toggle orientation
163         _ToggleHoriOrientAndAlign( bToggle, eHoriOrient, eRelOrient );
164 
165         // determine alignment values:
166         // <nWidth>: 'width' of the alignment area
167         // <nOffset>: offset of alignment area, relative to 'left' of
168         //            frame anchor position
169         SwTwips nWidth, nOffset;
170         {
171             bool bDummy; // in this context irrelevant output parameter
172             _GetHoriAlignmentValues( GetAnchorFrm(), GetAnchorFrm(),
173                                      eRelOrient, false,
174                                      nWidth, nOffset, bDummy );
175         }
176 
177         SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
178 
179         // determine relative horizontal position
180         SwTwips nRelPosX;
181         if ( text::HoriOrientation::NONE == eHoriOrient )
182         {
183             if( bToggle ||
184                 ( !aHori.IsPosToggle() && GetAnchorFrm().IsRightToLeft() ) )
185             {
186                 nRelPosX = nWidth - nObjWidth - aHori.GetPos();
187             }
188             else
189             {
190                 nRelPosX = aHori.GetPos();
191             }
192         }
193         else if ( text::HoriOrientation::CENTER == eHoriOrient )
194             nRelPosX = (nWidth / 2) - (nObjWidth / 2);
195         else if ( text::HoriOrientation::RIGHT == eHoriOrient )
196             nRelPosX = nWidth - ( nObjWidth +
197                              ( bVert ? rUL.GetLower() : rLR.GetRight() ) );
198         else
199             nRelPosX = bVert ? rUL.GetUpper() : rLR.GetLeft();
200         nRelPosX += nOffset;
201 
202         // no 'negative' relative horizontal position
203         // OD 06.11.2003 #FollowTextFlowAtFrame# - negative positions allow for
204         // to frame anchored objects.
205         if ( !bFlyAtFly && nRelPosX < 0 )
206         {
207             nRelPosX = 0;
208         }
209 
210         // determine absolute 'horizontal' position, depending on layout-direction
211         // --> OD 2004-06-17 #i26791# - determine offset to 'horizontal' frame
212         // anchor position, depending on layout-direction
213         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
214         // --> OD 2009-09-04 #mongolianlayout#
215         if( bVert || bVertL2R )
216         // <--
217         {
218 
219             aRelPos.Y() = nRelPosX;
220             maOffsetToFrmAnchorPos.Y() = nOffset;
221         }
222         else
223         {
224             aRelPos.X() = nRelPosX;
225             maOffsetToFrmAnchorPos.X() = nOffset;
226         }
227 
228         // keep the calculated relative horizontal position - needed for filters
229         // (including the xml-filter)
230         {
231             SwTwips nAttrRelPosX = nRelPosX - nOffset;
232             if ( text::HoriOrientation::NONE != aHori.GetHoriOrient() &&
233                  aHori.GetPos() != nAttrRelPosX )
234             {
235                 aHori.SetPos( nAttrRelPosX );
236                 const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
237                 const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aHori );
238                 const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
239             }
240         }
241     } // end of determination of horizontal position
242 
243     // keep calculate relative position
244     maRelPos = aRelPos;
245 }
246 
247 /** calculated relative position for object position
248 
249     @author OD
250 */
251 Point SwToLayoutAnchoredObjectPosition::GetRelPos() const
252 {
253     return maRelPos;
254 }
255 
256