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