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_svx.hxx" 30 31 #include <svx/svdotext.hxx> 32 #include <svx/svdhdl.hxx> 33 #include <svx/svddrag.hxx> 34 #include <svx/svdview.hxx> 35 #include <svx/svdorect.hxx> // fuer SetXPolyDirty in MovCreate bei SolidDragging 36 #include "svx/svdglob.hxx" // Stringcache 37 #include "svx/svdstr.hrc" // Objektname 38 #include <svx/svdoashp.hxx> 39 #include <tools/bigint.hxx> 40 #include <basegfx/polygon/b2dpolygon.hxx> 41 #include <basegfx/range/b2drange.hxx> 42 #include <basegfx/polygon/b2dpolygontools.hxx> 43 44 //////////////////////////////////////////////////////////////////////////////////////////////////// 45 // 46 // @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ 47 // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ 48 // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ 49 // @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ 50 // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ 51 // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ 52 // @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ 53 // 54 // Dragging, Handles, Create 55 // 56 //////////////////////////////////////////////////////////////////////////////////////////////////// 57 58 sal_uInt32 SdrTextObj::GetHdlCount() const 59 { 60 return 8L; 61 } 62 63 SdrHdl* SdrTextObj::GetHdl(sal_uInt32 nHdlNum) const 64 { 65 SdrHdl* pH=NULL; 66 Point aPnt; 67 SdrHdlKind eKind=HDL_MOVE; 68 switch (nHdlNum) { 69 case 0: aPnt=aRect.TopLeft(); eKind=HDL_UPLFT; break; // Oben links 70 case 1: aPnt=aRect.TopCenter(); eKind=HDL_UPPER; break; // Oben 71 case 2: aPnt=aRect.TopRight(); eKind=HDL_UPRGT; break; // Oben rechts 72 case 3: aPnt=aRect.LeftCenter(); eKind=HDL_LEFT ; break; // Links 73 case 4: aPnt=aRect.RightCenter(); eKind=HDL_RIGHT; break; // Rechts 74 case 5: aPnt=aRect.BottomLeft(); eKind=HDL_LWLFT; break; // Unten links 75 case 6: aPnt=aRect.BottomCenter(); eKind=HDL_LOWER; break; // Unten 76 case 7: aPnt=aRect.BottomRight(); eKind=HDL_LWRGT; break; // Unten rechts 77 } 78 if (aGeo.nShearWink!=0) ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan); 79 if (aGeo.nDrehWink!=0) RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); 80 if (eKind!=HDL_MOVE) { 81 pH=new SdrHdl(aPnt,eKind); 82 pH->SetObj((SdrObject*)this); 83 pH->SetDrehWink(aGeo.nDrehWink); 84 } 85 return pH; 86 } 87 88 //////////////////////////////////////////////////////////////////////////////////////////////////// 89 90 bool SdrTextObj::hasSpecialDrag() const 91 { 92 return true; 93 } 94 95 Rectangle SdrTextObj::ImpDragCalcRect(const SdrDragStat& rDrag) const 96 { 97 Rectangle aTmpRect(aRect); 98 const SdrHdl* pHdl=rDrag.GetHdl(); 99 SdrHdlKind eHdl=pHdl==NULL ? HDL_MOVE : pHdl->GetKind(); 100 FASTBOOL bEcke=(eHdl==HDL_UPLFT || eHdl==HDL_UPRGT || eHdl==HDL_LWLFT || eHdl==HDL_LWRGT); 101 FASTBOOL bOrtho=rDrag.GetView()!=NULL && rDrag.GetView()->IsOrtho(); 102 FASTBOOL bBigOrtho=bEcke && bOrtho && rDrag.GetView()->IsBigOrtho(); 103 Point aPos(rDrag.GetNow()); 104 // Unrotate: 105 if (aGeo.nDrehWink!=0) RotatePoint(aPos,aTmpRect.TopLeft(),-aGeo.nSin,aGeo.nCos); 106 // Unshear: 107 if (aGeo.nShearWink!=0) ShearPoint(aPos,aTmpRect.TopLeft(),-aGeo.nTan); 108 // 109 FASTBOOL bLft=(eHdl==HDL_UPLFT || eHdl==HDL_LEFT || eHdl==HDL_LWLFT); 110 FASTBOOL bRgt=(eHdl==HDL_UPRGT || eHdl==HDL_RIGHT || eHdl==HDL_LWRGT); 111 FASTBOOL bTop=(eHdl==HDL_UPRGT || eHdl==HDL_UPPER || eHdl==HDL_UPLFT); 112 FASTBOOL bBtm=(eHdl==HDL_LWRGT || eHdl==HDL_LOWER || eHdl==HDL_LWLFT); 113 if (bLft) aTmpRect.Left() =aPos.X(); 114 if (bRgt) aTmpRect.Right() =aPos.X(); 115 if (bTop) aTmpRect.Top() =aPos.Y(); 116 if (bBtm) aTmpRect.Bottom()=aPos.Y(); 117 if (bOrtho) { // Ortho 118 long nWdt0=aRect.Right() -aRect.Left(); 119 long nHgt0=aRect.Bottom()-aRect.Top(); 120 long nXMul=aTmpRect.Right() -aTmpRect.Left(); 121 long nYMul=aTmpRect.Bottom()-aTmpRect.Top(); 122 long nXDiv=nWdt0; 123 long nYDiv=nHgt0; 124 FASTBOOL bXNeg=(nXMul<0)!=(nXDiv<0); 125 FASTBOOL bYNeg=(nYMul<0)!=(nYDiv<0); 126 nXMul=Abs(nXMul); 127 nYMul=Abs(nYMul); 128 nXDiv=Abs(nXDiv); 129 nYDiv=Abs(nYDiv); 130 Fraction aXFact(nXMul,nXDiv); // Fractions zum kuerzen 131 Fraction aYFact(nYMul,nYDiv); // und zum vergleichen 132 nXMul=aXFact.GetNumerator(); 133 nYMul=aYFact.GetNumerator(); 134 nXDiv=aXFact.GetDenominator(); 135 nYDiv=aYFact.GetDenominator(); 136 if (bEcke) { // Eckpunkthandles 137 FASTBOOL bUseX=(aXFact<aYFact) != bBigOrtho; 138 if (bUseX) { 139 long nNeed=long(BigInt(nHgt0)*BigInt(nXMul)/BigInt(nXDiv)); 140 if (bYNeg) nNeed=-nNeed; 141 if (bTop) aTmpRect.Top()=aTmpRect.Bottom()-nNeed; 142 if (bBtm) aTmpRect.Bottom()=aTmpRect.Top()+nNeed; 143 } else { 144 long nNeed=long(BigInt(nWdt0)*BigInt(nYMul)/BigInt(nYDiv)); 145 if (bXNeg) nNeed=-nNeed; 146 if (bLft) aTmpRect.Left()=aTmpRect.Right()-nNeed; 147 if (bRgt) aTmpRect.Right()=aTmpRect.Left()+nNeed; 148 } 149 } else { // Scheitelpunkthandles 150 if ((bLft || bRgt) && nXDiv!=0) { 151 long nHgt0b=aRect.Bottom()-aRect.Top(); 152 long nNeed=long(BigInt(nHgt0b)*BigInt(nXMul)/BigInt(nXDiv)); 153 aTmpRect.Top()-=(nNeed-nHgt0b)/2; 154 aTmpRect.Bottom()=aTmpRect.Top()+nNeed; 155 } 156 if ((bTop || bBtm) && nYDiv!=0) { 157 long nWdt0b=aRect.Right()-aRect.Left(); 158 long nNeed=long(BigInt(nWdt0b)*BigInt(nYMul)/BigInt(nYDiv)); 159 aTmpRect.Left()-=(nNeed-nWdt0b)/2; 160 aTmpRect.Right()=aTmpRect.Left()+nNeed; 161 } 162 } 163 } 164 if (!ISA(SdrObjCustomShape)) // not justifying for CustomShapes to be able to detect if a shape has to be mirrored 165 ImpJustifyRect(aTmpRect); 166 return aTmpRect; 167 } 168 169 //////////////////////////////////////////////////////////////////////////////////////////////////// 170 // drag 171 172 bool SdrTextObj::applySpecialDrag(SdrDragStat& rDrag) 173 { 174 Rectangle aNewRect(ImpDragCalcRect(rDrag)); 175 176 if(aNewRect.TopLeft() != aRect.TopLeft() && (aGeo.nDrehWink || aGeo.nShearWink)) 177 { 178 Point aNewPos(aNewRect.TopLeft()); 179 180 if(aGeo.nShearWink) 181 ShearPoint(aNewPos,aRect.TopLeft(),aGeo.nTan); 182 183 if(aGeo.nDrehWink) 184 RotatePoint(aNewPos,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); 185 186 aNewRect.SetPos(aNewPos); 187 } 188 189 if(aNewRect != aRect) 190 { 191 NbcSetLogicRect(aNewRect); 192 } 193 194 return true; 195 } 196 197 String SdrTextObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const 198 { 199 XubString aStr; 200 ImpTakeDescriptionStr(STR_DragRectResize,aStr); 201 return aStr; 202 } 203 204 //////////////////////////////////////////////////////////////////////////////////////////////////// 205 // Create 206 207 FASTBOOL SdrTextObj::BegCreate(SdrDragStat& rStat) 208 { 209 rStat.SetOrtho4Possible(); 210 Rectangle aRect1(rStat.GetStart(), rStat.GetNow()); 211 aRect1.Justify(); 212 rStat.SetActionRect(aRect1); 213 aRect = aRect1; 214 return sal_True; 215 } 216 217 FASTBOOL SdrTextObj::MovCreate(SdrDragStat& rStat) 218 { 219 Rectangle aRect1; 220 rStat.TakeCreateRect(aRect1); 221 ImpJustifyRect(aRect1); 222 rStat.SetActionRect(aRect1); 223 aRect=aRect1; // fuer ObjName 224 SetBoundRectDirty(); 225 bSnapRectDirty=sal_True; 226 if (HAS_BASE(SdrRectObj,this)) { 227 ((SdrRectObj*)this)->SetXPolyDirty(); 228 } 229 return sal_True; 230 } 231 232 FASTBOOL SdrTextObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) 233 { 234 rStat.TakeCreateRect(aRect); 235 ImpJustifyRect(aRect); 236 if (bTextFrame) { 237 if (IsAutoGrowHeight()) { 238 // MinTextHeight 239 long nHgt=aRect.GetHeight()-1; 240 if (nHgt==1) nHgt=0; 241 NbcSetMinTextFrameHeight(nHgt); 242 } 243 if (IsAutoGrowWidth()) { 244 // MinTextWidth 245 long nWdt=aRect.GetWidth()-1; 246 if (nWdt==1) nWdt=0; 247 NbcSetMinTextFrameWidth(nWdt); 248 } 249 // Textrahmen neu berechnen 250 NbcAdjustTextFrameWidthAndHeight(); 251 } 252 SetRectsDirty(); 253 if (HAS_BASE(SdrRectObj,this)) { 254 ((SdrRectObj*)this)->SetXPolyDirty(); 255 } 256 return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); 257 } 258 259 void SdrTextObj::BrkCreate(SdrDragStat& /*rStat*/) 260 { 261 } 262 263 FASTBOOL SdrTextObj::BckCreate(SdrDragStat& /*rStat*/) 264 { 265 return sal_True; 266 } 267 268 basegfx::B2DPolyPolygon SdrTextObj::TakeCreatePoly(const SdrDragStat& rDrag) const 269 { 270 Rectangle aRect1; 271 rDrag.TakeCreateRect(aRect1); 272 aRect1.Justify(); 273 274 basegfx::B2DPolyPolygon aRetval; 275 const basegfx::B2DRange aRange(aRect1.Left(), aRect1.Top(), aRect1.Right(), aRect1.Bottom()); 276 aRetval.append(basegfx::tools::createPolygonFromRect(aRange)); 277 return aRetval; 278 } 279 280 Pointer SdrTextObj::GetCreatePointer() const 281 { 282 if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT); 283 return Pointer(POINTER_CROSS); 284 } 285 286