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