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/svdmrkv.hxx> 28 #include <svx/svdetc.hxx> 29 #include <svx/svdoedge.hxx> 30 #include "svx/svdglob.hxx" 31 #include "svx/svditext.hxx" 32 #include <svx/svdview.hxx> 33 #include <svx/svdpagv.hxx> 34 #include <svx/svdpage.hxx> 35 #include "svddrgm1.hxx" 36 37 #ifdef DBG_UTIL 38 #include <svdibrow.hxx> 39 #endif 40 41 #include <svx/svdoole2.hxx> 42 #include <svx/xgrad.hxx> 43 #include <svx/xflgrit.hxx> 44 #include "gradtrns.hxx" 45 #include <svx/xflftrit.hxx> 46 #include <svx/dialmgr.hxx> 47 #include "svx/svdstr.hrc" 48 #include <svx/svdundo.hxx> 49 #include <svx/svdopath.hxx> 50 #include <svx/scene3d.hxx> 51 #include <svx/svdovirt.hxx> 52 #include <svx/sdr/overlay/overlayrollingrectangle.hxx> 53 #include <svx/sdr/overlay/overlaymanager.hxx> 54 #include <svx/sdrpaintwindow.hxx> 55 #include <svx/sdrpagewindow.hxx> 56 #include <svx/sdrhittesthelper.hxx> 57 58 //////////////////////////////////////////////////////////////////////////////////////////////////// 59 // predefines 60 61 class SdrUnoControlList; 62 63 //////////////////////////////////////////////////////////////////////////////////////////////////// 64 // #114409#-3 Migrate Marking of Objects, Points and GluePoints 65 66 class ImplMarkingOverlay 67 { 68 // The OverlayObjects 69 ::sdr::overlay::OverlayObjectList maObjects; 70 71 // The remembered second position in logical coodinates 72 basegfx::B2DPoint maSecondPosition; 73 74 // bitfield 75 // A flag to remember if the action is for unmarking. 76 unsigned mbUnmarking : 1; 77 78 public: 79 ImplMarkingOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos, sal_Bool bUnmarking = sal_False); 80 ~ImplMarkingOverlay(); 81 82 void SetSecondPosition(const basegfx::B2DPoint& rNewPosition); 83 sal_Bool IsUnmarking() const { return mbUnmarking; } 84 }; 85 86 ImplMarkingOverlay::ImplMarkingOverlay(const SdrPaintView& rView, const basegfx::B2DPoint& rStartPos, sal_Bool bUnmarking) 87 : maSecondPosition(rStartPos), 88 mbUnmarking(bUnmarking) 89 { 90 for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++) 91 { 92 SdrPaintWindow* pCandidate = rView.GetPaintWindow(a); 93 ::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager(); 94 95 if(pTargetOverlay) 96 { 97 ::sdr::overlay::OverlayRollingRectangleStriped* pNew = new ::sdr::overlay::OverlayRollingRectangleStriped( 98 rStartPos, rStartPos, false); 99 pTargetOverlay->add(*pNew); 100 maObjects.append(*pNew); 101 } 102 } 103 } 104 105 ImplMarkingOverlay::~ImplMarkingOverlay() 106 { 107 // The OverlayObjects are cleared using the destructor of OverlayObjectList. 108 // That destructor calls clear() at the list which removes all objects from the 109 // OverlayManager and deletes them. 110 } 111 112 void ImplMarkingOverlay::SetSecondPosition(const basegfx::B2DPoint& rNewPosition) 113 { 114 if(rNewPosition != maSecondPosition) 115 { 116 // apply to OverlayObjects 117 for(sal_uInt32 a(0L); a < maObjects.count(); a++) 118 { 119 ::sdr::overlay::OverlayRollingRectangleStriped& rCandidate = (::sdr::overlay::OverlayRollingRectangleStriped&)maObjects.getOverlayObject(a); 120 rCandidate.setSecondPosition(rNewPosition); 121 } 122 123 // remember new position 124 maSecondPosition = rNewPosition; 125 } 126 } 127 128 //////////////////////////////////////////////////////////////////////////////////////////////////// 129 //////////////////////////////////////////////////////////////////////////////////////////////////// 130 // 131 // @@ @@ @@@@ @@@@@ @@ @@ @@ @@ @@ @@@@@ @@ @@ 132 // @@@ @@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ 133 // @@@@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ @@ 134 // @@@@@@@ @@@@@@ @@@@@ @@@@ @@@@@ @@ @@@@ @@@@@@@ 135 // @@ @ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@@@@@ 136 // @@ @@ @@ @@ @@ @@ @@ @@ @@@ @@ @@ @@@ @@@ 137 // @@ @@ @@ @@ @@ @@ @@ @@ @ @@ @@@@@ @@ @@ 138 // 139 //////////////////////////////////////////////////////////////////////////////////////////////////// 140 //////////////////////////////////////////////////////////////////////////////////////////////////// 141 142 void SdrMarkView::ImpClearVars() 143 { 144 eDragMode=SDRDRAG_MOVE; 145 //HMHbHdlShown=sal_False; 146 bRefHdlShownOnly=sal_False; 147 eEditMode=SDREDITMODE_EDIT; 148 eEditMode0=SDREDITMODE_EDIT; 149 bDesignMode=sal_False; 150 pMarkedObj=NULL; 151 pMarkedPV=NULL; 152 bForceFrameHandles=sal_False; 153 bPlusHdlAlways=sal_False; 154 nFrameHandlesLimit=50; 155 bInsPolyPoint=sal_False; 156 mnInsPointNum = 0L; 157 bMarkedObjRectDirty=sal_False; 158 bMarkedPointsRectsDirty=sal_False; 159 mbMarkHandlesHidden = false; 160 bMrkPntDirty=sal_False; 161 bMarkHdlWhenTextEdit=sal_False; 162 bMarkableObjCountDirty=sal_False; // noch nicht implementiert 163 nMarkableObjCount=0; // noch nicht implementiert 164 165 // #114409#-3 Migrate selections 166 BrkMarkObj(); 167 BrkMarkPoints(); 168 BrkMarkGluePoints(); 169 } 170 171 SdrMarkView::SdrMarkView(SdrModel* pModel1, OutputDevice* pOut) 172 : SdrSnapView(pModel1,pOut), 173 mpMarkObjOverlay(0L), 174 mpMarkPointsOverlay(0L), 175 mpMarkGluePointsOverlay(0L), 176 aHdl(this), 177 mpSdrViewSelection(new sdr::ViewSelection()) 178 { 179 ImpClearVars(); 180 StartListening(*pModel1); 181 } 182 183 SdrMarkView::~SdrMarkView() 184 { 185 // #114409#-3 Migrate selections 186 BrkMarkObj(); 187 BrkMarkPoints(); 188 BrkMarkGluePoints(); 189 delete mpSdrViewSelection; 190 } 191 192 void __EXPORT SdrMarkView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) 193 { 194 SdrHint* pSdrHint=PTR_CAST(SdrHint,&rHint); 195 if (pSdrHint!=NULL) 196 { 197 SdrHintKind eKind=pSdrHint->GetKind(); 198 199 if (eKind==HINT_OBJCHG || eKind==HINT_OBJINSERTED || eKind==HINT_OBJREMOVED) 200 { 201 bMarkedObjRectDirty=sal_True; 202 bMarkedPointsRectsDirty=sal_True; 203 } 204 /* removed for now since this breaks existing code who iterates over the mark list and sequentially replaces objects 205 if( eKind==HINT_OBJREMOVED && IsObjMarked( const_cast<SdrObject*>(pSdrHint->GetObject()) ) ) 206 { 207 MarkObj( const_cast<SdrObject*>(pSdrHint->GetObject()), GetSdrPageView(), sal_True ); 208 } 209 */ 210 } 211 SdrSnapView::Notify(rBC,rHint); 212 } 213 214 void SdrMarkView::ModelHasChanged() 215 { 216 SdrPaintView::ModelHasChanged(); 217 GetMarkedObjectListWriteAccess().SetNameDirty(); 218 bMarkedObjRectDirty=sal_True; 219 bMarkedPointsRectsDirty=sal_True; 220 // Es sind beispielsweise Obj markiert und maMarkedObjectListist Sorted. 221 // In einer anderen View 2 wird die ObjOrder veraendert 222 // (z.B. MovToTop()). Dann ist Neusortieren der MarkList erforderlich. 223 GetMarkedObjectListWriteAccess().SetUnsorted(); 224 SortMarkedObjects(); 225 bMrkPntDirty=sal_True; 226 UndirtyMrkPnt(); 227 SdrView* pV=(SdrView*)this; 228 if (pV!=NULL && !pV->IsDragObj() && !pV->IsInsObjPoint()) { // an dieser Stelle habe ich ein ziemliches Problem !!! 229 AdjustMarkHdl(); 230 } 231 } 232 233 //////////////////////////////////////////////////////////////////////////////////////////////////// 234 235 sal_Bool SdrMarkView::IsAction() const 236 { 237 return SdrSnapView::IsAction() || IsMarkObj() || IsMarkPoints() || IsMarkGluePoints(); 238 } 239 240 void SdrMarkView::MovAction(const Point& rPnt) 241 { 242 SdrSnapView::MovAction(rPnt); 243 244 if(IsMarkObj()) 245 { 246 MovMarkObj(rPnt); 247 } 248 else if(IsMarkPoints()) 249 { 250 MovMarkPoints(rPnt); 251 } 252 else if(IsMarkGluePoints()) 253 { 254 MovMarkGluePoints(rPnt); 255 } 256 } 257 258 void SdrMarkView::EndAction() 259 { 260 if(IsMarkObj()) 261 { 262 EndMarkObj(); 263 } 264 else if(IsMarkPoints()) 265 { 266 EndMarkPoints(); 267 } 268 else if(IsMarkGluePoints()) 269 { 270 EndMarkGluePoints(); 271 } 272 273 SdrSnapView::EndAction(); 274 } 275 276 void SdrMarkView::BckAction() 277 { 278 SdrSnapView::BckAction(); 279 BrkMarkObj(); 280 BrkMarkPoints(); 281 BrkMarkGluePoints(); 282 } 283 284 void SdrMarkView::BrkAction() 285 { 286 SdrSnapView::BrkAction(); 287 BrkMarkObj(); 288 BrkMarkPoints(); 289 BrkMarkGluePoints(); 290 } 291 292 void SdrMarkView::TakeActionRect(Rectangle& rRect) const 293 { 294 if(IsMarkObj() || IsMarkPoints() || IsMarkGluePoints()) 295 { 296 rRect = Rectangle(aDragStat.GetStart(), aDragStat.GetNow()); 297 } 298 else 299 { 300 SdrSnapView::TakeActionRect(rRect); 301 } 302 } 303 304 //////////////////////////////////////////////////////////////////////////////////////////////////// 305 306 void SdrMarkView::ClearPageView() 307 { 308 UnmarkAllObj(); 309 SdrSnapView::ClearPageView(); 310 } 311 312 void SdrMarkView::HideSdrPage() 313 { 314 bool bMrkChg(false); 315 //HMHbool bVis(false); 316 317 if(mpPageView) 318 { 319 // break all creation actions when hiding page (#75081#) 320 BrkAction(); 321 //HMHbVis = IsMarkHdlShown(); 322 323 //HMHif(bVis) 324 //HMH{ 325 //HMH HideMarkHdl(); 326 //HMH} 327 328 // Alle Markierungen dieser Seite verwerfen 329 bMrkChg = GetMarkedObjectListWriteAccess().DeletePageView(*mpPageView); 330 } 331 332 SdrSnapView::HideSdrPage(); 333 334 if(bMrkChg) 335 { 336 MarkListHasChanged(); 337 AdjustMarkHdl(); 338 } 339 340 //HMHif(bVis) 341 //HMH{ 342 //HMH ShowMarkHdl(); 343 //HMH} 344 } 345 346 //////////////////////////////////////////////////////////////////////////////////////////////////// 347 348 sal_Bool SdrMarkView::BegMarkObj(const Point& rPnt, sal_Bool bUnmark) 349 { 350 BrkAction(); 351 352 DBG_ASSERT(0L == mpMarkObjOverlay, "SdrMarkView::BegMarkObj: There exists a mpMarkObjOverlay (!)"); 353 basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); 354 mpMarkObjOverlay = new ImplMarkingOverlay(*this, aStartPos, bUnmark); 355 356 aDragStat.Reset(rPnt); 357 aDragStat.NextPoint(); 358 aDragStat.SetMinMove(nMinMovLog); 359 360 return sal_True; 361 } 362 363 void SdrMarkView::MovMarkObj(const Point& rPnt) 364 { 365 if(IsMarkObj() && aDragStat.CheckMinMoved(rPnt)) 366 { 367 aDragStat.NextMove(rPnt); 368 DBG_ASSERT(mpMarkObjOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); 369 basegfx::B2DPoint aNewPos(rPnt.X(), rPnt.Y()); 370 mpMarkObjOverlay->SetSecondPosition(aNewPos); 371 } 372 } 373 374 sal_Bool SdrMarkView::EndMarkObj() 375 { 376 sal_Bool bRetval(sal_False); 377 378 if(IsMarkObj()) 379 { 380 if(aDragStat.IsMinMoved()) 381 { 382 Rectangle aRect(aDragStat.GetStart(), aDragStat.GetNow()); 383 aRect.Justify(); 384 MarkObj(aRect, mpMarkObjOverlay->IsUnmarking()); 385 bRetval = sal_True; 386 } 387 388 // cleanup 389 BrkMarkObj(); 390 } 391 392 return bRetval; 393 } 394 395 void SdrMarkView::BrkMarkObj() 396 { 397 if(IsMarkObj()) 398 { 399 DBG_ASSERT(mpMarkObjOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); 400 delete mpMarkObjOverlay; 401 mpMarkObjOverlay = 0L; 402 } 403 } 404 405 //////////////////////////////////////////////////////////////////////////////////////////////////// 406 407 sal_Bool SdrMarkView::BegMarkPoints(const Point& rPnt, sal_Bool bUnmark) 408 { 409 if(HasMarkablePoints()) 410 { 411 BrkAction(); 412 413 DBG_ASSERT(0L == mpMarkPointsOverlay, "SdrMarkView::BegMarkObj: There exists a mpMarkPointsOverlay (!)"); 414 basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); 415 mpMarkPointsOverlay = new ImplMarkingOverlay(*this, aStartPos, bUnmark); 416 417 aDragStat.Reset(rPnt); 418 aDragStat.NextPoint(); 419 aDragStat.SetMinMove(nMinMovLog); 420 421 return sal_True; 422 } 423 424 return sal_False; 425 } 426 427 void SdrMarkView::MovMarkPoints(const Point& rPnt) 428 { 429 if(IsMarkPoints() && aDragStat.CheckMinMoved(rPnt)) 430 { 431 aDragStat.NextMove(rPnt); 432 433 DBG_ASSERT(mpMarkPointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); 434 basegfx::B2DPoint aNewPos(rPnt.X(), rPnt.Y()); 435 mpMarkPointsOverlay->SetSecondPosition(aNewPos); 436 } 437 } 438 439 sal_Bool SdrMarkView::EndMarkPoints() 440 { 441 sal_Bool bRetval(sal_False); 442 443 if(IsMarkPoints()) 444 { 445 if(aDragStat.IsMinMoved()) 446 { 447 Rectangle aRect(aDragStat.GetStart(), aDragStat.GetNow()); 448 aRect.Justify(); 449 MarkPoints(aRect, mpMarkPointsOverlay->IsUnmarking()); 450 451 bRetval = sal_True; 452 } 453 454 // cleanup 455 BrkMarkPoints(); 456 } 457 458 return bRetval; 459 } 460 461 void SdrMarkView::BrkMarkPoints() 462 { 463 if(IsMarkPoints()) 464 { 465 DBG_ASSERT(mpMarkPointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); 466 delete mpMarkPointsOverlay; 467 mpMarkPointsOverlay = 0L; 468 } 469 } 470 471 //////////////////////////////////////////////////////////////////////////////////////////////////// 472 473 sal_Bool SdrMarkView::BegMarkGluePoints(const Point& rPnt, sal_Bool bUnmark) 474 { 475 if(HasMarkableGluePoints()) 476 { 477 BrkAction(); 478 479 DBG_ASSERT(0L == mpMarkGluePointsOverlay, "SdrMarkView::BegMarkObj: There exists a mpMarkGluePointsOverlay (!)"); 480 basegfx::B2DPoint aStartPos(rPnt.X(), rPnt.Y()); 481 mpMarkGluePointsOverlay = new ImplMarkingOverlay(*this, aStartPos, bUnmark); 482 483 aDragStat.Reset(rPnt); 484 aDragStat.NextPoint(); 485 aDragStat.SetMinMove(nMinMovLog); 486 487 return sal_True; 488 } 489 490 return sal_False; 491 } 492 493 void SdrMarkView::MovMarkGluePoints(const Point& rPnt) 494 { 495 if(IsMarkGluePoints() && aDragStat.CheckMinMoved(rPnt)) 496 { 497 aDragStat.NextMove(rPnt); 498 499 DBG_ASSERT(mpMarkGluePointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); 500 basegfx::B2DPoint aNewPos(rPnt.X(), rPnt.Y()); 501 mpMarkGluePointsOverlay->SetSecondPosition(aNewPos); 502 } 503 } 504 505 sal_Bool SdrMarkView::EndMarkGluePoints() 506 { 507 sal_Bool bRetval(sal_False); 508 509 if(IsMarkGluePoints()) 510 { 511 if(aDragStat.IsMinMoved()) 512 { 513 Rectangle aRect(aDragStat.GetStart(),aDragStat.GetNow()); 514 aRect.Justify(); 515 MarkGluePoints(&aRect, mpMarkGluePointsOverlay->IsUnmarking()); 516 517 bRetval = sal_True; 518 } 519 520 // cleanup 521 BrkMarkGluePoints(); 522 } 523 524 return bRetval; 525 } 526 527 void SdrMarkView::BrkMarkGluePoints() 528 { 529 if(IsMarkGluePoints()) 530 { 531 DBG_ASSERT(mpMarkGluePointsOverlay, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)"); 532 delete mpMarkGluePointsOverlay; 533 mpMarkGluePointsOverlay = 0L; 534 } 535 } 536 537 sal_Bool SdrMarkView::HasMarkableObj() const 538 { 539 sal_uIntPtr nCount=0; 540 541 SdrPageView* pPV = GetSdrPageView(); 542 if(pPV) 543 { 544 SdrObjList* pOL=pPV->GetObjList(); 545 sal_uIntPtr nObjAnz=pOL->GetObjCount(); 546 for (sal_uIntPtr nObjNum=0; nObjNum<nObjAnz && nCount==0; nObjNum++) { 547 SdrObject* pObj=pOL->GetObj(nObjNum); 548 if (IsObjMarkable(pObj,pPV)) { 549 nCount++; 550 } 551 } 552 } 553 return nCount!=0; 554 } 555 556 sal_uIntPtr SdrMarkView::GetMarkableObjCount() const 557 { 558 sal_uIntPtr nCount=0; 559 SdrPageView* pPV = GetSdrPageView(); 560 561 if(pPV) 562 { 563 SdrObjList* pOL=pPV->GetObjList(); 564 sal_uIntPtr nObjAnz=pOL->GetObjCount(); 565 for (sal_uIntPtr nObjNum=0; nObjNum<nObjAnz; nObjNum++) { 566 SdrObject* pObj=pOL->GetObj(nObjNum); 567 if (IsObjMarkable(pObj,pPV)) { 568 nCount++; 569 } 570 } 571 } 572 return nCount; 573 } 574 575 //HMHvoid SdrMarkView::ImpShowMarkHdl(bool /*bNoRefHdl*/) 576 //HMH{ 577 //HMH bNoRefHdl=sal_False; // geht leider erstmal nicht anders 578 //HMH if (!bHdlShown) { 579 //HMH bRefHdlShownOnly=sal_False; 580 //HMH bHdlShown=sal_True; 581 //HMH } 582 //HMH} 583 584 //HMHvoid SdrMarkView::ShowMarkHdl(bool /*bNoRefHdl*/) 585 //HMH{ 586 //HMH bNoRefHdl=sal_False; // geht leider erstmal nicht anders 587 //HMH ImpShowMarkHdl(bNoRefHdl); 588 //HMH} 589 590 591 //HMHvoid SdrMarkView::HideMarkHdl(bool /*bNoRefHdl*/) 592 //HMH{ 593 //HMH bNoRefHdl=sal_False; // geht leider erstmal nicht anders 594 //HMH if (bHdlShown) { 595 //HMH bRefHdlShownOnly=bNoRefHdl; 596 //HMH bHdlShown=sal_False; 597 //HMH } 598 //HMH} 599 600 void SdrMarkView::hideMarkHandles() 601 { 602 if(!mbMarkHandlesHidden) 603 { 604 mbMarkHandlesHidden = true; 605 AdjustMarkHdl(); 606 } 607 } 608 609 void SdrMarkView::showMarkHandles() 610 { 611 if(mbMarkHandlesHidden) 612 { 613 mbMarkHandlesHidden = false; 614 AdjustMarkHdl(); 615 } 616 } 617 618 sal_Bool SdrMarkView::ImpIsFrameHandles() const 619 { 620 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 621 sal_Bool bFrmHdl=nMarkAnz>nFrameHandlesLimit || bForceFrameHandles; 622 sal_Bool bStdDrag=eDragMode==SDRDRAG_MOVE; 623 if (nMarkAnz==1 && bStdDrag && bFrmHdl) 624 { 625 const SdrObject* pObj=GetMarkedObjectByIndex(0); 626 if (pObj->GetObjInventor()==SdrInventor) 627 { 628 sal_uInt16 nIdent=pObj->GetObjIdentifier(); 629 if (nIdent==OBJ_LINE || nIdent==OBJ_EDGE || nIdent==OBJ_CAPTION || nIdent==OBJ_MEASURE || nIdent==OBJ_CUSTOMSHAPE || nIdent==OBJ_TABLE ) 630 { 631 bFrmHdl=sal_False; 632 } 633 } 634 } 635 if (!bStdDrag && !bFrmHdl) { 636 // Grundsaetzlich erstmal alle anderen Dragmodi nur mit FrameHandles 637 bFrmHdl=sal_True; 638 if (eDragMode==SDRDRAG_ROTATE) { 639 // bei Rotate ObjOwn-Drag, wenn mind. 1 PolyObj 640 for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz && bFrmHdl; nMarkNum++) { 641 const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); 642 const SdrObject* pObj=pM->GetMarkedSdrObj(); 643 bFrmHdl=!pObj->IsPolyObj(); 644 } 645 } 646 } 647 if (!bFrmHdl) { 648 // FrameHandles, wenn wenigstens 1 Obj kein SpecialDrag kann 649 for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz && !bFrmHdl; nMarkNum++) { 650 const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); 651 const SdrObject* pObj=pM->GetMarkedSdrObj(); 652 bFrmHdl=!pObj->hasSpecialDrag(); 653 } 654 } 655 return bFrmHdl; 656 } 657 658 void SdrMarkView::SetMarkHandles() 659 { 660 // #105722# remember old focus handle values to search for it again 661 const SdrHdl* pSaveOldFocusHdl = aHdl.GetFocusHdl(); 662 sal_Bool bSaveOldFocus(sal_False); 663 sal_uInt32 nSavePolyNum(0L), nSavePointNum(0L); 664 SdrHdlKind eSaveKind(HDL_MOVE); 665 SdrObject* pSaveObj = NULL; 666 667 if(pSaveOldFocusHdl 668 && pSaveOldFocusHdl->GetObj() 669 && pSaveOldFocusHdl->GetObj()->ISA(SdrPathObj) 670 && (pSaveOldFocusHdl->GetKind() == HDL_POLY || pSaveOldFocusHdl->GetKind() == HDL_BWGT)) 671 { 672 bSaveOldFocus = sal_True; 673 nSavePolyNum = pSaveOldFocusHdl->GetPolyNum(); 674 nSavePointNum = pSaveOldFocusHdl->GetPointNum(); 675 pSaveObj = pSaveOldFocusHdl->GetObj(); 676 eSaveKind = pSaveOldFocusHdl->GetKind(); 677 } 678 679 // delete/clear all handles. This will always be done, even with areMarkHandlesHidden() 680 aHdl.Clear(); 681 aHdl.SetRotateShear(eDragMode==SDRDRAG_ROTATE); 682 aHdl.SetDistortShear(eDragMode==SDRDRAG_SHEAR); 683 pMarkedObj=NULL; 684 pMarkedPV=NULL; 685 686 // are handles enabled at all? Create only then 687 if(!areMarkHandlesHidden()) 688 { 689 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 690 sal_Bool bStdDrag=eDragMode==SDRDRAG_MOVE; 691 sal_Bool bSingleTextObjMark=sal_False; 692 693 if (nMarkAnz==1) 694 { 695 pMarkedObj=GetMarkedObjectByIndex(0); 696 bSingleTextObjMark = 697 pMarkedObj && 698 pMarkedObj->ISA(SdrTextObj) && 699 static_cast<SdrTextObj*>(pMarkedObj)->IsTextFrame(); 700 } 701 702 sal_Bool bFrmHdl=ImpIsFrameHandles(); 703 704 if (nMarkAnz>0) 705 { 706 pMarkedPV=GetSdrPageViewOfMarkedByIndex(0); 707 708 for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz && (pMarkedPV!=NULL || !bFrmHdl); nMarkNum++) 709 { 710 const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); 711 712 if (pMarkedPV!=pM->GetPageView()) 713 { 714 pMarkedPV=NULL; 715 } 716 } 717 } 718 719 if (bFrmHdl) 720 { 721 Rectangle aRect(GetMarkedObjRect()); 722 723 // #i33755# 724 const sal_Bool bHideHandlesWhenInTextEdit( 725 ((SdrView*)this)->IsTextEdit() 726 && pMarkedObj 727 && pMarkedObj->ISA(SdrTextObj) 728 && ((SdrTextObj*)pMarkedObj)->IsInEditMode()); 729 730 // #i118524# if inplace activated OLE is selected, 731 // suppress handles 732 bool bHideHandlesWhenOleActive(false); 733 const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pMarkedObj); 734 735 if(pSdrOle2Obj && (pSdrOle2Obj->isInplaceActive() || pSdrOle2Obj->isUiActive())) 736 { 737 bHideHandlesWhenOleActive = true; 738 } 739 740 if(!aRect.IsEmpty() && !bHideHandlesWhenInTextEdit && !bHideHandlesWhenOleActive) 741 { // sonst nix gefunden 742 if( bSingleTextObjMark ) 743 { 744 const sal_uIntPtr nSiz0=aHdl.GetHdlCount(); 745 pMarkedObj->AddToHdlList(aHdl); 746 const sal_uIntPtr nSiz1=aHdl.GetHdlCount(); 747 for (sal_uIntPtr i=nSiz0; i<nSiz1; i++) 748 { 749 SdrHdl* pHdl=aHdl.GetHdl(i); 750 pHdl->SetObj(pMarkedObj); 751 pHdl->SetPageView(pMarkedPV); 752 pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); 753 } 754 } 755 else if( eDragMode==SDRDRAG_CROP ) 756 { 757 aHdl.AddHdl(new SdrCropHdl(aRect.TopLeft() ,HDL_UPLFT)); 758 aHdl.AddHdl(new SdrCropHdl(aRect.TopCenter() ,HDL_UPPER)); 759 aHdl.AddHdl(new SdrCropHdl(aRect.TopRight() ,HDL_UPRGT)); 760 aHdl.AddHdl(new SdrCropHdl(aRect.LeftCenter() ,HDL_LEFT )); 761 aHdl.AddHdl(new SdrCropHdl(aRect.RightCenter() ,HDL_RIGHT)); 762 aHdl.AddHdl(new SdrCropHdl(aRect.BottomLeft() ,HDL_LWLFT)); 763 aHdl.AddHdl(new SdrCropHdl(aRect.BottomCenter(),HDL_LOWER)); 764 aHdl.AddHdl(new SdrCropHdl(aRect.BottomRight() ,HDL_LWRGT)); 765 } 766 else 767 { 768 sal_Bool bWdt0=aRect.Left()==aRect.Right(); 769 sal_Bool bHgt0=aRect.Top()==aRect.Bottom(); 770 if (bWdt0 && bHgt0) 771 { 772 aHdl.AddHdl(new SdrHdl(aRect.TopLeft(),HDL_UPLFT)); 773 } 774 else if (!bStdDrag && (bWdt0 || bHgt0)) 775 { 776 aHdl.AddHdl(new SdrHdl(aRect.TopLeft() ,HDL_UPLFT)); 777 aHdl.AddHdl(new SdrHdl(aRect.BottomRight(),HDL_LWRGT)); 778 } 779 else 780 { 781 if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.TopLeft() ,HDL_UPLFT)); 782 if ( !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.TopCenter() ,HDL_UPPER)); 783 if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.TopRight() ,HDL_UPRGT)); 784 if (!bWdt0 ) aHdl.AddHdl(new SdrHdl(aRect.LeftCenter() ,HDL_LEFT )); 785 if (!bWdt0 ) aHdl.AddHdl(new SdrHdl(aRect.RightCenter() ,HDL_RIGHT)); 786 if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.BottomLeft() ,HDL_LWLFT)); 787 if ( !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.BottomCenter(),HDL_LOWER)); 788 if (!bWdt0 && !bHgt0) aHdl.AddHdl(new SdrHdl(aRect.BottomRight() ,HDL_LWRGT)); 789 } 790 } 791 } 792 } 793 else 794 { 795 for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) 796 { 797 const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); 798 SdrObject* pObj=pM->GetMarkedSdrObj(); 799 SdrPageView* pPV=pM->GetPageView(); 800 const sal_uIntPtr nSiz0=aHdl.GetHdlCount(); 801 pObj->AddToHdlList(aHdl); 802 const sal_uIntPtr nSiz1=aHdl.GetHdlCount(); 803 bool bPoly=pObj->IsPolyObj(); 804 const SdrUShortCont* pMrkPnts=pM->GetMarkedPoints(); 805 for (sal_uIntPtr i=nSiz0; i<nSiz1; i++) 806 { 807 SdrHdl* pHdl=aHdl.GetHdl(i); 808 pHdl->SetObj(pObj); 809 pHdl->SetPageView(pPV); 810 pHdl->SetObjHdlNum(sal_uInt16(i-nSiz0)); 811 if (bPoly) 812 { 813 sal_Bool bSelected=pMrkPnts!=NULL && pMrkPnts->Exist(sal_uInt16(i-nSiz0)); 814 pHdl->SetSelected(bSelected); 815 //sal_Bool bPlus=bPlusHdlAlways; 816 if (bPlusHdlAlways || bSelected) 817 { 818 sal_uInt32 nPlusAnz=pObj->GetPlusHdlCount(*pHdl); 819 for (sal_uInt32 nPlusNum=0; nPlusNum<nPlusAnz; nPlusNum++) 820 { 821 SdrHdl* pPlusHdl=pObj->GetPlusHdl(*pHdl,nPlusNum); 822 if (pPlusHdl!=NULL) 823 { 824 pPlusHdl->SetObj(pObj); 825 pPlusHdl->SetPageView(pPV); 826 pPlusHdl->SetPlusHdl(sal_True); 827 aHdl.AddHdl(pPlusHdl); 828 } 829 } 830 } 831 } 832 } 833 } // for nMarkNum 834 } // if bFrmHdl else 835 836 // GluePoint-Handles 837 for (sal_uIntPtr nMarkNum=0; nMarkNum<nMarkAnz; nMarkNum++) 838 { 839 const SdrMark* pM=GetSdrMarkByIndex(nMarkNum); 840 SdrObject* pObj=pM->GetMarkedSdrObj(); 841 SdrPageView* pPV=pM->GetPageView(); 842 const SdrUShortCont* pMrkGlue=pM->GetMarkedGluePoints(); 843 if (pMrkGlue!=NULL) 844 { 845 const SdrGluePointList* pGPL=pObj->GetGluePointList(); 846 if (pGPL!=NULL) 847 { 848 //sal_uInt16 nGlueAnz=pGPL->GetCount(); 849 sal_uInt16 nAnz=(sal_uInt16)pMrkGlue->GetCount(); 850 for (sal_uInt16 nNum=0; nNum<nAnz; nNum++) 851 { 852 sal_uInt16 nId=pMrkGlue->GetObject(nNum); 853 //nNum changed to nNumGP because already used in for loop 854 sal_uInt16 nNumGP=pGPL->FindGluePoint(nId); 855 if (nNumGP!=SDRGLUEPOINT_NOTFOUND) 856 { 857 const SdrGluePoint& rGP=(*pGPL)[nNumGP]; 858 Point aPos(rGP.GetAbsolutePos(*pObj)); 859 SdrHdl* pGlueHdl=new SdrHdl(aPos,HDL_GLUE); 860 pGlueHdl->SetObj(pObj); 861 pGlueHdl->SetPageView(pPV); 862 pGlueHdl->SetObjHdlNum(nId); 863 aHdl.AddHdl(pGlueHdl); 864 } 865 } 866 } 867 } 868 } 869 870 // Drehpunkt/Spiegelachse 871 AddDragModeHdl(eDragMode); 872 873 // sort handles 874 aHdl.Sort(); 875 876 // add custom handles (used by other apps, e.g. AnchorPos) 877 AddCustomHdl(); 878 879 // #105722# try to restore focus handle index from remembered values 880 if(bSaveOldFocus) 881 { 882 for(sal_uInt32 a(0); a < aHdl.GetHdlCount(); a++) 883 { 884 SdrHdl* pCandidate = aHdl.GetHdl(a); 885 886 if(pCandidate->GetObj() 887 && pCandidate->GetObj() == pSaveObj 888 && pCandidate->GetKind() == eSaveKind 889 && pCandidate->GetPolyNum() == nSavePolyNum 890 && pCandidate->GetPointNum() == nSavePointNum) 891 { 892 aHdl.SetFocusHdl(pCandidate); 893 break; 894 } 895 } 896 } 897 } 898 } 899 900 void SdrMarkView::AddCustomHdl() 901 { 902 // add custom handles (used by other apps, e.g. AnchorPos) 903 } 904 905 void SdrMarkView::SetDragMode(SdrDragMode eMode) 906 { 907 SdrDragMode eMode0=eDragMode; 908 eDragMode=eMode; 909 if (eDragMode==SDRDRAG_RESIZE) eDragMode=SDRDRAG_MOVE; 910 if (eDragMode!=eMode0) { 911 //HMHBOOL bVis=IsMarkHdlShown(); 912 //HMHif (bVis) HideMarkHdl(); 913 ForceRefToMarked(); 914 SetMarkHandles(); 915 //HMHif (bVis) ShowMarkHdl(); 916 { 917 if (AreObjectsMarked()) MarkListHasChanged(); 918 } 919 } 920 } 921 922 void SdrMarkView::AddDragModeHdl(SdrDragMode eMode) 923 { 924 switch(eMode) 925 { 926 case SDRDRAG_ROTATE: 927 { 928 // add rotation center 929 SdrHdl* pHdl = new SdrHdl(aRef1, HDL_REF1); 930 931 aHdl.AddHdl(pHdl); 932 933 break; 934 } 935 case SDRDRAG_MIRROR: 936 { 937 // add mirror axis 938 SdrHdl* pHdl3 = new SdrHdl(aRef2, HDL_REF2); 939 SdrHdl* pHdl2 = new SdrHdl(aRef1, HDL_REF1); 940 SdrHdl* pHdl1 = new SdrHdlLine(*pHdl2, *pHdl3, HDL_MIRX); 941 942 pHdl1->SetObjHdlNum(1); // fuer Sortierung 943 pHdl2->SetObjHdlNum(2); // fuer Sortierung 944 pHdl3->SetObjHdlNum(3); // fuer Sortierung 945 946 aHdl.AddHdl(pHdl1); // Linie als erstes, damit als letztes im HitTest 947 aHdl.AddHdl(pHdl2); 948 aHdl.AddHdl(pHdl3); 949 950 break; 951 } 952 case SDRDRAG_TRANSPARENCE: 953 { 954 // add interactive transparence handle 955 sal_uIntPtr nMarkAnz = GetMarkedObjectCount(); 956 if(nMarkAnz == 1) 957 { 958 SdrObject* pObj = GetMarkedObjectByIndex(0); 959 SdrModel* pModel = GetModel(); 960 const SfxItemSet& rSet = pObj->GetMergedItemSet(); 961 962 if(SFX_ITEM_SET != rSet.GetItemState(XATTR_FILLFLOATTRANSPARENCE, sal_False)) 963 { 964 // add this item, it's not yet there 965 XFillFloatTransparenceItem aNewItem( 966 (const XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE)); 967 XGradient aGrad = aNewItem.GetGradientValue(); 968 969 aNewItem.SetEnabled(sal_True); 970 aGrad.SetStartIntens(100); 971 aGrad.SetEndIntens(100); 972 aNewItem.SetGradientValue(aGrad); 973 974 // add undo to allow user to take back this step 975 if( pModel->IsUndoEnabled() ) 976 { 977 pModel->BegUndo(SVX_RESSTR(SIP_XA_FILLTRANSPARENCE)); 978 pModel->AddUndo(pModel->GetSdrUndoFactory().CreateUndoAttrObject(*pObj)); 979 pModel->EndUndo(); 980 } 981 982 //pObj->SetItemAndBroadcast(aNewItem); 983 SfxItemSet aNewSet(pModel->GetItemPool()); 984 aNewSet.Put(aNewItem); 985 pObj->SetMergedItemSetAndBroadcast(aNewSet); 986 } 987 988 // set values and transform to vector set 989 GradTransformer aGradTransformer; 990 GradTransVector aGradTransVector; 991 GradTransGradient aGradTransGradient; 992 993 aGradTransGradient.aGradient = ((XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE)).GetGradientValue(); 994 aGradTransformer.GradToVec(aGradTransGradient, aGradTransVector, pObj); 995 996 // build handles 997 const Point aTmpPos1(basegfx::fround(aGradTransVector.maPositionA.getX()), basegfx::fround(aGradTransVector.maPositionA.getY())); 998 const Point aTmpPos2(basegfx::fround(aGradTransVector.maPositionB.getX()), basegfx::fround(aGradTransVector.maPositionB.getY())); 999 SdrHdlColor* pColHdl1 = new SdrHdlColor(aTmpPos1, aGradTransVector.aCol1, SDR_HANDLE_COLOR_SIZE_NORMAL, sal_True); 1000 SdrHdlColor* pColHdl2 = new SdrHdlColor(aTmpPos2, aGradTransVector.aCol2, SDR_HANDLE_COLOR_SIZE_NORMAL, sal_True); 1001 SdrHdlGradient* pGradHdl = new SdrHdlGradient(aTmpPos1, aTmpPos2, sal_False); 1002 DBG_ASSERT(pColHdl1 && pColHdl2 && pGradHdl, "Got not all necessary handles!!"); 1003 1004 // link them 1005 pGradHdl->SetColorHandles(pColHdl1, pColHdl2); 1006 pGradHdl->SetObj(pObj); 1007 pColHdl1->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); 1008 pColHdl2->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); 1009 1010 // insert them 1011 aHdl.AddHdl(pColHdl1); 1012 aHdl.AddHdl(pColHdl2); 1013 aHdl.AddHdl(pGradHdl); 1014 } 1015 break; 1016 } 1017 case SDRDRAG_GRADIENT: 1018 { 1019 // add interactive gradient handle 1020 sal_uIntPtr nMarkAnz = GetMarkedObjectCount(); 1021 if(nMarkAnz == 1) 1022 { 1023 SdrObject* pObj = GetMarkedObjectByIndex(0); 1024 const SfxItemSet& rSet = pObj->GetMergedItemSet(); 1025 XFillStyle eFillStyle = ((XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue(); 1026 1027 if(eFillStyle == XFILL_GRADIENT) 1028 { 1029 // set values and transform to vector set 1030 GradTransformer aGradTransformer; 1031 GradTransVector aGradTransVector; 1032 GradTransGradient aGradTransGradient; 1033 Size aHdlSize(15, 15); 1034 1035 aGradTransGradient.aGradient = ((XFillGradientItem&)rSet.Get(XATTR_FILLGRADIENT)).GetGradientValue(); 1036 aGradTransformer.GradToVec(aGradTransGradient, aGradTransVector, pObj); 1037 1038 // build handles 1039 const Point aTmpPos1(basegfx::fround(aGradTransVector.maPositionA.getX()), basegfx::fround(aGradTransVector.maPositionA.getY())); 1040 const Point aTmpPos2(basegfx::fround(aGradTransVector.maPositionB.getX()), basegfx::fround(aGradTransVector.maPositionB.getY())); 1041 SdrHdlColor* pColHdl1 = new SdrHdlColor(aTmpPos1, aGradTransVector.aCol1, aHdlSize, sal_False); 1042 SdrHdlColor* pColHdl2 = new SdrHdlColor(aTmpPos2, aGradTransVector.aCol2, aHdlSize, sal_False); 1043 SdrHdlGradient* pGradHdl = new SdrHdlGradient(aTmpPos1, aTmpPos2, sal_True); 1044 DBG_ASSERT(pColHdl1 && pColHdl2 && pGradHdl, "Got not all necessary handles!!"); 1045 1046 // link them 1047 pGradHdl->SetColorHandles(pColHdl1, pColHdl2); 1048 pGradHdl->SetObj(pObj); 1049 pColHdl1->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); 1050 pColHdl2->SetColorChangeHdl(LINK(pGradHdl, SdrHdlGradient, ColorChangeHdl)); 1051 1052 // insert them 1053 aHdl.AddHdl(pColHdl1); 1054 aHdl.AddHdl(pColHdl2); 1055 aHdl.AddHdl(pGradHdl); 1056 } 1057 } 1058 break; 1059 } 1060 case SDRDRAG_CROP: 1061 { 1062 // todo 1063 break; 1064 } 1065 default: break; 1066 } 1067 } 1068 1069 /** handle mouse over effects for handles */ 1070 sal_Bool SdrMarkView::MouseMove(const MouseEvent& rMEvt, Window* pWin) 1071 { 1072 if(aHdl.GetHdlCount()) 1073 { 1074 SdrHdl* pMouseOverHdl = 0; 1075 if( !rMEvt.IsLeaveWindow() && pWin ) 1076 { 1077 Point aMDPos( pWin->PixelToLogic( rMEvt.GetPosPixel() ) ); 1078 pMouseOverHdl = PickHandle(aMDPos); 1079 } 1080 1081 // notify last mouse over handle that he lost the mouse 1082 const sal_uIntPtr nHdlCount = aHdl.GetHdlCount(); 1083 1084 for(sal_uIntPtr nHdl = 0; nHdl < nHdlCount; nHdl++ ) 1085 { 1086 SdrHdl* pCurrentHdl = GetHdl(nHdl); 1087 if( pCurrentHdl->mbMouseOver ) 1088 { 1089 if( pCurrentHdl != pMouseOverHdl ) 1090 { 1091 pCurrentHdl->mbMouseOver = false; 1092 pCurrentHdl->onMouseLeave(); 1093 } 1094 break; 1095 } 1096 } 1097 1098 // notify current mouse over handle 1099 if( pMouseOverHdl /* && !pMouseOverHdl->mbMouseOver */ ) 1100 { 1101 pMouseOverHdl->mbMouseOver = true; 1102 pMouseOverHdl->onMouseEnter(rMEvt); 1103 } 1104 } 1105 return SdrSnapView::MouseMove(rMEvt, pWin); 1106 } 1107 1108 void SdrMarkView::ForceRefToMarked() 1109 { 1110 switch(eDragMode) 1111 { 1112 case SDRDRAG_ROTATE: 1113 { 1114 Rectangle aR(GetMarkedObjRect()); 1115 aRef1 = aR.Center(); 1116 1117 break; 1118 } 1119 1120 case SDRDRAG_MIRROR: 1121 { 1122 // Erstmal die laenge der Spiegelachsenlinie berechnen 1123 long nOutMin=0; 1124 long nOutMax=0; 1125 long nMinLen=0; 1126 long nObjDst=0; 1127 long nOutHgt=0; 1128 OutputDevice* pOut=GetFirstOutputDevice(); 1129 //OutputDevice* pOut=GetWin(0); 1130 if (pOut!=NULL) { 1131 // Mindestlaenge 50 Pixel 1132 nMinLen=pOut->PixelToLogic(Size(0,50)).Height(); 1133 // 20 Pixel fuer RefPt-Abstand vom Obj 1134 nObjDst=pOut->PixelToLogic(Size(0,20)).Height(); 1135 // MinY/MaxY 1136 // Abstand zum Rand = Mindestlaenge = 10 Pixel 1137 long nDst=pOut->PixelToLogic(Size(0,10)).Height(); 1138 nOutMin=-pOut->GetMapMode().GetOrigin().Y(); 1139 nOutMax=pOut->GetOutputSize().Height()-1+nOutMin; 1140 nOutMin+=nDst; 1141 nOutMax-=nDst; 1142 // Absolute Mindestlaenge jedoch 10 Pixel 1143 if (nOutMax-nOutMin<nDst) { 1144 nOutMin+=nOutMax+1; 1145 nOutMin/=2; 1146 nOutMin-=(nDst+1)/2; 1147 nOutMax=nOutMin+nDst; 1148 } 1149 nOutHgt=nOutMax-nOutMin; 1150 // Sonst Mindestlaenge = 1/4 OutHgt 1151 long nTemp=nOutHgt/4; 1152 if (nTemp>nMinLen) nMinLen=nTemp; 1153 } 1154 1155 Rectangle aR(GetMarkedObjBoundRect()); 1156 Point aCenter(aR.Center()); 1157 long nMarkHgt=aR.GetHeight()-1; 1158 long nHgt=nMarkHgt+nObjDst*2; // 20 Pixel obej und unten ueberstehend 1159 if (nHgt<nMinLen) nHgt=nMinLen; // Mindestlaenge 50 Pixel bzw. 1/4 OutHgt 1160 1161 long nY1=aCenter.Y()-(nHgt+1)/2; 1162 long nY2=nY1+nHgt; 1163 1164 if (pOut!=NULL && nMinLen>nOutHgt) nMinLen=nOutHgt; // evtl. noch etwas verkuerzen 1165 1166 if (pOut!=NULL) { // nun vollstaendig in den sichtbaren Bereich schieben 1167 if (nY1<nOutMin) { 1168 nY1=nOutMin; 1169 if (nY2<nY1+nMinLen) nY2=nY1+nMinLen; 1170 } 1171 if (nY2>nOutMax) { 1172 nY2=nOutMax; 1173 if (nY1>nY2-nMinLen) nY1=nY2-nMinLen; 1174 } 1175 } 1176 1177 aRef1.X()=aCenter.X(); 1178 aRef1.Y()=nY1; 1179 aRef2.X()=aCenter.X(); 1180 aRef2.Y()=nY2; 1181 1182 break; 1183 } 1184 1185 case SDRDRAG_TRANSPARENCE: 1186 case SDRDRAG_GRADIENT: 1187 case SDRDRAG_CROP: 1188 { 1189 Rectangle aRect(GetMarkedObjBoundRect()); 1190 aRef1 = aRect.TopLeft(); 1191 aRef2 = aRect.BottomRight(); 1192 break; 1193 } 1194 default: break; 1195 } 1196 } 1197 1198 void SdrMarkView::SetRef1(const Point& rPt) 1199 { 1200 if(eDragMode == SDRDRAG_ROTATE || eDragMode == SDRDRAG_MIRROR) 1201 { 1202 aRef1 = rPt; 1203 SdrHdl* pH = aHdl.GetHdl(HDL_REF1); 1204 if(pH) 1205 pH->SetPos(rPt); 1206 //HMHShowMarkHdl(); 1207 } 1208 } 1209 1210 void SdrMarkView::SetRef2(const Point& rPt) 1211 { 1212 if(eDragMode == SDRDRAG_MIRROR) 1213 { 1214 aRef2 = rPt; 1215 SdrHdl* pH = aHdl.GetHdl(HDL_REF2); 1216 if(pH) 1217 pH->SetPos(rPt); 1218 //HMHShowMarkHdl(); 1219 } 1220 } 1221 1222 void SdrMarkView::CheckMarked() 1223 { 1224 for (sal_uIntPtr nm=GetMarkedObjectCount(); nm>0;) { 1225 nm--; 1226 SdrMark* pM=GetSdrMarkByIndex(nm); 1227 SdrObject* pObj=pM->GetMarkedSdrObj(); 1228 SdrPageView* pPV=pM->GetPageView(); 1229 SdrLayerID nLay=pObj->GetLayer(); 1230 sal_Bool bRaus=!pObj->IsInserted(); // Obj geloescht? 1231 if (!pObj->Is3DObj()) { 1232 bRaus=bRaus || pObj->GetPage()!=pPV->GetPage(); // Obj ploetzlich in anderer Page oder Group 1233 } 1234 bRaus=bRaus || pPV->GetLockedLayers().IsSet(nLay) || // Layer gesperrt? 1235 !pPV->GetVisibleLayers().IsSet(nLay); // Layer nicht sichtbar? 1236 1237 if( !bRaus ) 1238 bRaus = !pObj->IsVisible(); // not visible objects can not be marked 1239 1240 if (!bRaus) { 1241 // Joe am 9.3.1997: Gruppierte Objekten koennen nun auch 1242 // markiert werden. Nach EnterGroup muessen aber die Objekte 1243 // der hoeheren Ebene deselektiert werden. 1244 const SdrObjList* pOOL=pObj->GetObjList(); 1245 const SdrObjList* pVOL=pPV->GetObjList(); 1246 while (pOOL!=NULL && pOOL!=pVOL) { 1247 pOOL=pOOL->GetUpList(); 1248 } 1249 bRaus=pOOL!=pVOL; 1250 } 1251 1252 if (bRaus) 1253 { 1254 GetMarkedObjectListWriteAccess().DeleteMark(nm); 1255 } 1256 else 1257 { 1258 if (!IsGluePointEditMode()) { // Markierte GluePoints nur im GlueEditMode 1259 SdrUShortCont* pPts=pM->GetMarkedGluePoints(); 1260 if (pPts!=NULL && pPts->GetCount()!=0) { 1261 pPts->Clear(); 1262 } 1263 } 1264 } 1265 } 1266 1267 // #97995# at least reset the remembered BoundRect to prevent handle 1268 // generation if bForceFrameHandles is TRUE. 1269 bMarkedObjRectDirty = sal_True; 1270 } 1271 1272 void SdrMarkView::SetMarkRects() 1273 { 1274 SdrPageView* pPV = GetSdrPageView(); 1275 1276 if(pPV) 1277 { 1278 pPV->SetHasMarkedObj(GetSnapRectFromMarkedObjects(pPV, pPV->MarkSnap())); 1279 GetBoundRectFromMarkedObjects(pPV, pPV->MarkBound()); 1280 } 1281 } 1282 1283 void SdrMarkView::SetFrameHandles(sal_Bool bOn) 1284 { 1285 if (bOn!=bForceFrameHandles) { 1286 sal_Bool bOld=ImpIsFrameHandles(); 1287 bForceFrameHandles=bOn; 1288 sal_Bool bNew=ImpIsFrameHandles(); 1289 if (bNew!=bOld) { 1290 AdjustMarkHdl(); //HMHTRUE); 1291 MarkListHasChanged(); 1292 } 1293 } 1294 } 1295 1296 void SdrMarkView::SetEditMode(SdrViewEditMode eMode) 1297 { 1298 if (eMode!=eEditMode) { 1299 sal_Bool bGlue0=eEditMode==SDREDITMODE_GLUEPOINTEDIT; 1300 sal_Bool bEdge0=((SdrCreateView*)this)->IsEdgeTool(); 1301 eEditMode0=eEditMode; 1302 eEditMode=eMode; 1303 sal_Bool bGlue1=eEditMode==SDREDITMODE_GLUEPOINTEDIT; 1304 sal_Bool bEdge1=((SdrCreateView*)this)->IsEdgeTool(); 1305 // etwas Aufwand um Flackern zu verhindern beim Umschalten 1306 // zwischen GlueEdit und EdgeTool 1307 if (bGlue1 && !bGlue0) ImpSetGlueVisible2(bGlue1); 1308 if (bEdge1!=bEdge0) ImpSetGlueVisible3(bEdge1); 1309 if (!bGlue1 && bGlue0) ImpSetGlueVisible2(bGlue1); 1310 if (bGlue0 && !bGlue1) UnmarkAllGluePoints(); 1311 } 1312 } 1313 1314 //////////////////////////////////////////////////////////////////////////////////////////////////// 1315 1316 sal_Bool SdrMarkView::IsObjMarkable(SdrObject* pObj, SdrPageView* pPV) const 1317 { 1318 if (pObj) 1319 { 1320 if (pObj->IsMarkProtect() || 1321 (!bDesignMode && pObj->IsUnoObj())) 1322 { 1323 // Objekt nicht selektierbar oder 1324 // SdrUnoObj nicht im DesignMode 1325 return sal_False; 1326 } 1327 } 1328 return pPV!=NULL ? pPV->IsObjMarkable(pObj) : sal_True; 1329 } 1330 1331 sal_Bool SdrMarkView::IsMarkedObjHit(const Point& rPnt, short nTol) const 1332 { 1333 sal_Bool bRet=sal_False; 1334 nTol=ImpGetHitTolLogic(nTol,NULL); 1335 Point aPt(rPnt); 1336 for (sal_uIntPtr nm=0; nm<GetMarkedObjectCount() && !bRet; nm++) { 1337 SdrMark* pM=GetSdrMarkByIndex(nm); 1338 bRet = 0 != CheckSingleSdrObjectHit(aPt,sal_uInt16(nTol),pM->GetMarkedSdrObj(),pM->GetPageView(),0,0); 1339 } 1340 return bRet; 1341 } 1342 1343 SdrHdl* SdrMarkView::PickHandle(const Point& rPnt, sal_uIntPtr nOptions, SdrHdl* pHdl0) const 1344 { 1345 if (bSomeObjChgdFlag) { // ggf. Handles neu berechnen lassen! 1346 FlushComeBackTimer(); 1347 } 1348 sal_Bool bBack=(nOptions & SDRSEARCH_BACKWARD) !=0; 1349 sal_Bool bNext=(nOptions & SDRSEARCH_NEXT) !=0; 1350 Point aPt(rPnt); 1351 return aHdl.IsHdlListHit(aPt,bBack,bNext,pHdl0); 1352 } 1353 1354 sal_Bool SdrMarkView::MarkObj(const Point& rPnt, short nTol, sal_Bool bToggle, sal_Bool bDeep) 1355 { 1356 SdrObject* pObj; 1357 SdrPageView* pPV; 1358 nTol=ImpGetHitTolLogic(nTol,NULL); 1359 sal_uIntPtr nOptions=SDRSEARCH_PICKMARKABLE; 1360 if (bDeep) nOptions=nOptions|SDRSEARCH_DEEP; 1361 sal_Bool bRet=PickObj(rPnt,(sal_uInt16)nTol,pObj,pPV,nOptions); 1362 if (bRet) { 1363 sal_Bool bUnmark=bToggle && IsObjMarked(pObj); 1364 MarkObj(pObj,pPV,bUnmark); 1365 } 1366 return bRet; 1367 } 1368 1369 sal_Bool SdrMarkView::MarkNextObj(sal_Bool bPrev) 1370 { 1371 SdrPageView* pPageView = GetSdrPageView(); 1372 1373 if(!pPageView) 1374 { 1375 return sal_False; 1376 } 1377 1378 SortMarkedObjects(); 1379 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 1380 sal_uIntPtr nChgMarkNum = ULONG_MAX; // Nummer des zu ersetzenden MarkEntries 1381 sal_uIntPtr nSearchObjNum = bPrev ? 0 : ULONG_MAX; 1382 if (nMarkAnz!=0) { 1383 nChgMarkNum=bPrev ? 0 : sal_uIntPtr(nMarkAnz-1); 1384 SdrMark* pM=GetSdrMarkByIndex(nChgMarkNum); 1385 OSL_ASSERT(pM!=NULL); 1386 if (pM->GetMarkedSdrObj() != NULL) 1387 nSearchObjNum = pM->GetMarkedSdrObj()->GetNavigationPosition(); 1388 } 1389 1390 SdrObject* pMarkObj=NULL; 1391 SdrObjList* pSearchObjList=pPageView->GetObjList(); 1392 sal_uIntPtr nObjAnz=pSearchObjList->GetObjCount(); 1393 if (nObjAnz!=0) { 1394 if (nSearchObjNum>nObjAnz) nSearchObjNum=nObjAnz; 1395 while (pMarkObj==NULL && ((!bPrev && nSearchObjNum>0) || (bPrev && nSearchObjNum<nObjAnz))) 1396 { 1397 if (!bPrev) 1398 nSearchObjNum--; 1399 SdrObject* pSearchObj = pSearchObjList->GetObjectForNavigationPosition(nSearchObjNum); 1400 if (IsObjMarkable(pSearchObj,pPageView)) 1401 { 1402 if (TryToFindMarkedObject(pSearchObj)==CONTAINER_ENTRY_NOTFOUND) 1403 { 1404 pMarkObj=pSearchObj; 1405 } 1406 } 1407 if (bPrev) nSearchObjNum++; 1408 } 1409 } 1410 1411 if(!pMarkObj) 1412 { 1413 return sal_False; 1414 } 1415 1416 if (nChgMarkNum!=ULONG_MAX) 1417 { 1418 GetMarkedObjectListWriteAccess().DeleteMark(nChgMarkNum); 1419 } 1420 MarkObj(pMarkObj,pPageView); // ruft auch MarkListHasChanged(), AdjustMarkHdl() 1421 return sal_True; 1422 } 1423 1424 sal_Bool SdrMarkView::MarkNextObj(const Point& rPnt, short nTol, sal_Bool bPrev) 1425 { 1426 SortMarkedObjects(); 1427 nTol=ImpGetHitTolLogic(nTol,NULL); 1428 Point aPt(rPnt); 1429 SdrMark* pTopMarkHit=NULL; 1430 SdrMark* pBtmMarkHit=NULL; 1431 sal_uIntPtr nTopMarkHit=0; 1432 sal_uIntPtr nBtmMarkHit=0; 1433 // oberstes der markierten Objekte suchen, das von rPnt getroffen wird 1434 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 1435 sal_uIntPtr nm=0; 1436 for (nm=nMarkAnz; nm>0 && pTopMarkHit==NULL;) { 1437 nm--; 1438 SdrMark* pM=GetSdrMarkByIndex(nm); 1439 if(CheckSingleSdrObjectHit(aPt,sal_uInt16(nTol),pM->GetMarkedSdrObj(),pM->GetPageView(),0,0)) 1440 { 1441 pTopMarkHit=pM; 1442 nTopMarkHit=nm; 1443 } 1444 } 1445 // Nichts gefunden, dann ganz normal ein Obj markieren. 1446 if (pTopMarkHit==NULL) return MarkObj(rPnt,sal_uInt16(nTol),sal_False); 1447 1448 SdrObject* pTopObjHit=pTopMarkHit->GetMarkedSdrObj(); 1449 SdrObjList* pObjList=pTopObjHit->GetObjList(); 1450 SdrPageView* pPV=pTopMarkHit->GetPageView(); 1451 // unterstes der markierten Objekte suchen, das von rPnt getroffen wird 1452 // und auf der gleichen PageView liegt wie pTopMarkHit 1453 for (nm=0; nm<nMarkAnz && pBtmMarkHit==NULL; nm++) { 1454 SdrMark* pM=GetSdrMarkByIndex(nm); 1455 SdrPageView* pPV2=pM->GetPageView(); 1456 if (pPV2==pPV && CheckSingleSdrObjectHit(aPt,sal_uInt16(nTol),pM->GetMarkedSdrObj(),pPV2,0,0)) 1457 { 1458 pBtmMarkHit=pM; 1459 nBtmMarkHit=nm; 1460 } 1461 } 1462 if (pBtmMarkHit==NULL) { pBtmMarkHit=pTopMarkHit; nBtmMarkHit=nTopMarkHit; } 1463 SdrObject* pBtmObjHit=pBtmMarkHit->GetMarkedSdrObj(); 1464 sal_uIntPtr nObjAnz=pObjList->GetObjCount(); 1465 1466 // #110988# 1467 //sal_uIntPtr nSearchBeg=bPrev ? pBtmObjHit->GetOrdNum()+1 : pTopObjHit->GetOrdNum(); 1468 sal_uInt32 nSearchBeg; 1469 E3dScene* pScene = NULL; 1470 SdrObject* pObjHit = (bPrev) ? pBtmObjHit : pTopObjHit; 1471 sal_Bool bRemap = pObjHit->ISA(E3dCompoundObject) 1472 ? ((E3dCompoundObject*)pObjHit)->IsAOrdNumRemapCandidate(pScene) 1473 : sal_False; 1474 1475 if(bPrev) 1476 { 1477 sal_uInt32 nOrdNumBtm(pBtmObjHit->GetOrdNum()); 1478 1479 if(bRemap) 1480 { 1481 nOrdNumBtm = pScene->RemapOrdNum(nOrdNumBtm); 1482 } 1483 1484 nSearchBeg = nOrdNumBtm + 1; 1485 } 1486 else 1487 { 1488 sal_uInt32 nOrdNumTop(pTopObjHit->GetOrdNum()); 1489 1490 if(bRemap) 1491 { 1492 nOrdNumTop = pScene->RemapOrdNum(nOrdNumTop); 1493 } 1494 1495 nSearchBeg = nOrdNumTop; 1496 } 1497 1498 sal_uIntPtr no=nSearchBeg; 1499 SdrObject* pFndObj=NULL; 1500 //SdrObject* pAktObj=NULL; 1501 while (pFndObj==NULL && ((!bPrev && no>0) || (bPrev && no<nObjAnz))) { 1502 if (!bPrev) no--; 1503 SdrObject* pObj; 1504 1505 if(bRemap) 1506 { 1507 pObj = pObjList->GetObj(pScene->RemapOrdNum(no)); 1508 } 1509 else 1510 { 1511 pObj = pObjList->GetObj(no); 1512 } 1513 1514 if (CheckSingleSdrObjectHit(aPt,sal_uInt16(nTol),pObj,pPV,SDRSEARCH_TESTMARKABLE,0)) 1515 { 1516 if (TryToFindMarkedObject(pObj)==CONTAINER_ENTRY_NOTFOUND) { 1517 pFndObj=pObj; 1518 } else { 1519 // hier wg. Performance ggf. noch no auf Top bzw. auf Btm stellen 1520 } 1521 } 1522 if (bPrev) no++; 1523 } 1524 if (pFndObj!=NULL) 1525 { 1526 GetMarkedObjectListWriteAccess().DeleteMark(bPrev?nBtmMarkHit:nTopMarkHit); 1527 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pFndObj,pPV)); 1528 MarkListHasChanged(); 1529 AdjustMarkHdl(); //HMHTRUE); 1530 } 1531 return pFndObj!=NULL; 1532 } 1533 1534 sal_Bool SdrMarkView::MarkObj(const Rectangle& rRect, sal_Bool bUnmark) 1535 { 1536 sal_Bool bFnd=sal_False; 1537 Rectangle aR(rRect); 1538 SdrObject* pObj; 1539 SdrObjList* pObjList; 1540 BrkAction(); 1541 SdrPageView* pPV = GetSdrPageView(); 1542 1543 if(pPV) 1544 { 1545 pObjList=pPV->GetObjList(); 1546 Rectangle aFrm1(aR); 1547 sal_uIntPtr nObjAnz=pObjList->GetObjCount(); 1548 for (sal_uIntPtr nO=0; nO<nObjAnz; nO++) { 1549 pObj=pObjList->GetObj(nO); 1550 Rectangle aRect(pObj->GetCurrentBoundRect()); 1551 if (aFrm1.IsInside(aRect)) { 1552 if (!bUnmark) { 1553 if (IsObjMarkable(pObj,pPV)) 1554 { 1555 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj,pPV)); 1556 bFnd=sal_True; 1557 } 1558 } else { 1559 sal_uIntPtr nPos=TryToFindMarkedObject(pObj); 1560 if (nPos!=CONTAINER_ENTRY_NOTFOUND) 1561 { 1562 GetMarkedObjectListWriteAccess().DeleteMark(nPos); 1563 bFnd=sal_True; 1564 } 1565 } 1566 } 1567 } 1568 } 1569 if (bFnd) { 1570 SortMarkedObjects(); 1571 MarkListHasChanged(); 1572 AdjustMarkHdl(); //HMHTRUE); 1573 //HMHShowMarkHdl(); 1574 } 1575 return bFnd; 1576 } 1577 1578 void SdrMarkView::MarkObj(SdrObject* pObj, SdrPageView* pPV, sal_Bool bUnmark, sal_Bool bImpNoSetMarkHdl) 1579 { 1580 if (pObj!=NULL && pPV!=NULL && IsObjMarkable(pObj, pPV)) { 1581 BrkAction(); 1582 if (!bUnmark) 1583 { 1584 GetMarkedObjectListWriteAccess().InsertEntry(SdrMark(pObj,pPV)); 1585 } 1586 else 1587 { 1588 sal_uIntPtr nPos=TryToFindMarkedObject(pObj); 1589 if (nPos!=CONTAINER_ENTRY_NOTFOUND) 1590 { 1591 GetMarkedObjectListWriteAccess().DeleteMark(nPos); 1592 } 1593 } 1594 if (!bImpNoSetMarkHdl) { 1595 MarkListHasChanged(); 1596 AdjustMarkHdl(); //HMHTRUE); 1597 //HMHif (!bSomeObjChgdFlag) { 1598 // ShowMarkHdl kommt sonst mit dem AfterPaintTimer 1599 //HMHShowMarkHdl(); 1600 //HMH} 1601 } 1602 } 1603 } 1604 1605 sal_Bool SdrMarkView::IsObjMarked(SdrObject* pObj) const 1606 { 1607 // nicht so ganz die feine Art: Da FindObject() nicht const ist 1608 // muss ich mich hier auf non-const casten. 1609 sal_uIntPtr nPos=((SdrMarkView*)this)->TryToFindMarkedObject(pObj); 1610 return nPos!=CONTAINER_ENTRY_NOTFOUND; 1611 } 1612 1613 sal_uInt16 SdrMarkView::GetMarkHdlSizePixel() const 1614 { 1615 return aHdl.GetHdlSize()*2+1; 1616 } 1617 1618 void SdrMarkView::SetSolidMarkHdl(sal_Bool bOn) 1619 { 1620 if (bOn!=aHdl.IsFineHdl()) { 1621 //HMHBOOL bMerk=IsMarkHdlShown(); 1622 //HMHif (bMerk) HideMarkHdl(); 1623 aHdl.SetFineHdl(bOn); 1624 //HMHif (bMerk) ShowMarkHdl(); 1625 } 1626 } 1627 1628 void SdrMarkView::SetMarkHdlSizePixel(sal_uInt16 nSiz) 1629 { 1630 if (nSiz<3) nSiz=3; 1631 nSiz/=2; 1632 if (nSiz!=aHdl.GetHdlSize()) { 1633 //HMHBOOL bMerk=IsMarkHdlShown(); 1634 //HMHif (bMerk) HideMarkHdl(); 1635 aHdl.SetHdlSize(nSiz); 1636 //HMHif (bMerk) ShowMarkHdl(); 1637 } 1638 } 1639 1640 #define SDRSEARCH_IMPISMASTER 0x80000000 /* MasterPage wird gerade durchsucht */ 1641 SdrObject* SdrMarkView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, sal_uIntPtr nOptions, const SetOfByte* pMVisLay) const 1642 { 1643 if(((nOptions & SDRSEARCH_IMPISMASTER) && pObj->IsNotVisibleAsMaster()) || (!pObj->IsVisible())) 1644 { 1645 return NULL; 1646 } 1647 1648 const bool bCheckIfMarkable(nOptions & SDRSEARCH_TESTMARKABLE); 1649 const bool bDeep(nOptions & SDRSEARCH_DEEP); 1650 const bool bOLE(pObj->ISA(SdrOle2Obj)); 1651 const bool bTXT(pObj->ISA(SdrTextObj) && ((SdrTextObj*)pObj)->IsTextFrame()); 1652 SdrObject* pRet=NULL; 1653 Rectangle aRect(pObj->GetCurrentBoundRect()); 1654 sal_uInt16 nTol2(nTol); 1655 1656 // double tolerance for OLE, text frames and objects in 1657 // active text edit 1658 if(bOLE || bTXT || pObj==((SdrObjEditView*)this)->GetTextEditObject()) 1659 { 1660 nTol2*=2; 1661 } 1662 1663 aRect.Left ()-=nTol2; // Einmal Toleranz drauf fuer alle Objekte 1664 aRect.Top ()-=nTol2; 1665 aRect.Right ()+=nTol2; 1666 aRect.Bottom()+=nTol2; 1667 1668 if (aRect.IsInside(rPnt)) 1669 { 1670 if ((!bCheckIfMarkable || IsObjMarkable(pObj,pPV))) 1671 { 1672 SdrObjList* pOL=pObj->GetSubList(); 1673 1674 if (pOL!=NULL && pOL->GetObjCount()!=0) 1675 { 1676 SdrObject* pTmpObj; 1677 // OD 30.06.2003 #108784# - adjustment hit point for virtual 1678 // objects. 1679 Point aPnt( rPnt ); 1680 1681 if ( pObj->ISA(SdrVirtObj) ) 1682 { 1683 Point aOffset = static_cast<SdrVirtObj*>(pObj)->GetOffset(); 1684 aPnt.Move( -aOffset.X(), -aOffset.Y() ); 1685 } 1686 1687 pRet=CheckSingleSdrObjectHit(aPnt,nTol,pOL,pPV,nOptions,pMVisLay,pTmpObj); 1688 } 1689 else 1690 { 1691 if(!pMVisLay || pMVisLay->IsSet(pObj->GetLayer())) 1692 { 1693 pRet = SdrObjectPrimitiveHit(*pObj, rPnt, nTol2, *pPV, &pPV->GetVisibleLayers(), false); 1694 } 1695 } 1696 } 1697 } 1698 1699 if (!bDeep && pRet!=NULL) 1700 { 1701 pRet=pObj; 1702 } 1703 1704 return pRet; 1705 } 1706 1707 SdrObject* SdrMarkView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObjList* pOL, SdrPageView* pPV, sal_uIntPtr nOptions, const SetOfByte* pMVisLay, SdrObject*& rpRootObj) const 1708 { 1709 sal_Bool bBack=(nOptions & SDRSEARCH_BACKWARD)!=0; 1710 SdrObject* pRet=NULL; 1711 rpRootObj=NULL; 1712 if (pOL!=NULL) 1713 { 1714 // #110988# 1715 sal_Bool bRemap(pOL->GetOwnerObj() && pOL->GetOwnerObj()->ISA(E3dScene)); 1716 E3dScene* pRemapScene = (bRemap ? (E3dScene*)pOL->GetOwnerObj() : 0L); 1717 1718 sal_uIntPtr nObjAnz=pOL->GetObjCount(); 1719 sal_uIntPtr nObjNum=bBack ? 0 : nObjAnz; 1720 while (pRet==NULL && (bBack ? nObjNum<nObjAnz : nObjNum>0)) { 1721 if (!bBack) nObjNum--; 1722 SdrObject* pObj; 1723 1724 // #110988# 1725 if(bRemap) 1726 { 1727 pObj = pOL->GetObj(pRemapScene->RemapOrdNum(nObjNum)); 1728 } 1729 else 1730 { 1731 pObj = pOL->GetObj(nObjNum); 1732 } 1733 1734 pRet=CheckSingleSdrObjectHit(rPnt,nTol,pObj,pPV,nOptions,pMVisLay); 1735 if (pRet!=NULL) rpRootObj=pObj; 1736 if (bBack) nObjNum++; 1737 } 1738 } 1739 return pRet; 1740 } 1741 1742 sal_Bool SdrMarkView::PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, sal_uIntPtr nOptions) const 1743 { 1744 return PickObj(rPnt,nTol,rpObj,rpPV,nOptions,NULL,NULL,NULL); 1745 } 1746 1747 sal_Bool SdrMarkView::PickObj(const Point& rPnt, short nTol, SdrObject*& rpObj, SdrPageView*& rpPV, sal_uIntPtr nOptions, SdrObject** ppRootObj, sal_uIntPtr* pnMarkNum, sal_uInt16* pnPassNum) const 1748 { // Fehlt noch Pass2,Pass3 1749 SortMarkedObjects(); 1750 if (ppRootObj!=NULL) *ppRootObj=NULL; 1751 if (pnMarkNum!=NULL) *pnMarkNum=CONTAINER_ENTRY_NOTFOUND; 1752 if (pnPassNum!=NULL) *pnPassNum=0; 1753 rpObj=NULL; 1754 rpPV=NULL; 1755 sal_Bool bWholePage=(nOptions & SDRSEARCH_WHOLEPAGE) !=0; 1756 sal_Bool bMarked=(nOptions & SDRSEARCH_MARKED) !=0; 1757 sal_Bool bMasters=!bMarked && (nOptions & SDRSEARCH_ALSOONMASTER) !=0; 1758 sal_Bool bBack=(nOptions & SDRSEARCH_BACKWARD) !=0; 1759 #if OSL_DEBUG_LEVEL > 0 1760 sal_Bool bNext=(nOptions & SDRSEARCH_NEXT) !=0; (void)bNext; // n.i. 1761 sal_Bool bBoundCheckOn2ndPass=(nOptions & SDRSEARCH_PASS2BOUND) !=0; (void)bBoundCheckOn2ndPass;// n.i. 1762 sal_Bool bCheckNearestOn3rdPass=(nOptions & SDRSEARCH_PASS3NEAREST) !=0; (void)bCheckNearestOn3rdPass;// n.i. 1763 #endif 1764 if (nTol<0) nTol=ImpGetHitTolLogic(nTol,NULL); 1765 Point aPt(rPnt); 1766 SdrObject* pObj=NULL; 1767 SdrObject* pHitObj=NULL; 1768 SdrPageView* pPV=NULL; 1769 if (!bBack && ((SdrObjEditView*)this)->IsTextEditFrameHit(rPnt)) { 1770 pObj=((SdrObjEditView*)this)->GetTextEditObject(); 1771 pHitObj=pObj; 1772 pPV=((SdrObjEditView*)this)->GetTextEditPageView(); 1773 } 1774 if (bMarked) { 1775 sal_uIntPtr nMrkAnz=GetMarkedObjectCount(); 1776 sal_uIntPtr nMrkNum=bBack ? 0 : nMrkAnz; 1777 while (pHitObj==NULL && (bBack ? nMrkNum<nMrkAnz : nMrkNum>0)) { 1778 if (!bBack) nMrkNum--; 1779 SdrMark* pM=GetSdrMarkByIndex(nMrkNum); 1780 pObj=pM->GetMarkedSdrObj(); 1781 pPV=pM->GetPageView(); 1782 pHitObj=CheckSingleSdrObjectHit(aPt,nTol,pObj,pPV,nOptions,NULL); 1783 if (bBack) nMrkNum++; 1784 } 1785 } 1786 else 1787 { 1788 pPV = GetSdrPageView(); 1789 1790 if(pPV) 1791 { 1792 SdrPage* pPage=pPV->GetPage(); 1793 sal_uInt16 nPgAnz=1; 1794 1795 if(bMasters && pPage->TRG_HasMasterPage()) 1796 { 1797 nPgAnz++; 1798 } 1799 1800 sal_Bool bExtraPassForWholePage=bWholePage && pPage!=pPV->GetObjList(); 1801 if (bExtraPassForWholePage) nPgAnz++; // Suche erst in AktObjList, dann auf der gesamten Page 1802 sal_uInt16 nPgNum=bBack ? 0 : nPgAnz; 1803 while (pHitObj==NULL && (bBack ? nPgNum<nPgAnz : nPgNum>0)) { 1804 sal_uIntPtr nTmpOptions=nOptions; 1805 if (!bBack) nPgNum--; 1806 const SetOfByte* pMVisLay=NULL; 1807 SdrObjList* pObjList=NULL; 1808 if (pnPassNum!=NULL) *pnPassNum&=~(SDRSEARCHPASS_MASTERPAGE|SDRSEARCHPASS_INACTIVELIST); 1809 if (nPgNum>=nPgAnz-1 || (bExtraPassForWholePage && nPgNum>=nPgAnz-2)) 1810 { 1811 pObjList=pPV->GetObjList(); 1812 if (bExtraPassForWholePage && nPgNum==nPgAnz-2) { 1813 pObjList=pPage; 1814 if (pnPassNum!=NULL) *pnPassNum|=SDRSEARCHPASS_INACTIVELIST; 1815 } 1816 } 1817 else 1818 { 1819 // sonst MasterPage 1820 SdrPage& rMasterPage = pPage->TRG_GetMasterPage(); 1821 pMVisLay = &pPage->TRG_GetMasterPageVisibleLayers(); 1822 pObjList = &rMasterPage; 1823 1824 if (pnPassNum!=NULL) *pnPassNum|=SDRSEARCHPASS_MASTERPAGE; 1825 nTmpOptions=nTmpOptions | SDRSEARCH_IMPISMASTER; 1826 } 1827 pHitObj=CheckSingleSdrObjectHit(aPt,nTol,pObjList,pPV,nTmpOptions,pMVisLay,pObj); 1828 if (bBack) nPgNum++; 1829 } 1830 } 1831 } 1832 if (pHitObj!=NULL) { 1833 if (ppRootObj!=NULL) *ppRootObj=pObj; 1834 if ((nOptions & SDRSEARCH_DEEP) !=0) pObj=pHitObj; 1835 if ((nOptions & SDRSEARCH_TESTTEXTEDIT) !=0) { 1836 if (!pObj->HasTextEdit() || pPV->GetLockedLayers().IsSet(pObj->GetLayer())) { 1837 pObj=NULL; 1838 } 1839 } 1840 if (pObj!=NULL && (nOptions & SDRSEARCH_TESTMACRO) !=0) { 1841 SdrObjMacroHitRec aHitRec; 1842 aHitRec.aPos=aPt; 1843 aHitRec.aDownPos=aPt; 1844 aHitRec.nTol=nTol; 1845 aHitRec.pVisiLayer=&pPV->GetVisibleLayers(); 1846 aHitRec.pPageView=pPV; 1847 if (!pObj->HasMacro() || !pObj->IsMacroHit(aHitRec)) pObj=NULL; 1848 } 1849 if (pObj!=NULL && (nOptions & SDRSEARCH_WITHTEXT) !=0 && pObj->GetOutlinerParaObject()==NULL) pObj=NULL; 1850 if (pObj!=NULL && (nOptions & SDRSEARCH_TESTTEXTAREA) !=0) 1851 { 1852 if(!SdrObjectPrimitiveHit(*pObj, aPt, 0, *pPV, 0, true)) 1853 { 1854 pObj = 0; 1855 } 1856 } 1857 if (pObj!=NULL) { 1858 rpObj=pObj; 1859 rpPV=pPV; 1860 if (pnPassNum!=NULL) *pnPassNum|=SDRSEARCHPASS_DIRECT; 1861 } 1862 } 1863 return rpObj!=NULL; 1864 } 1865 1866 sal_Bool SdrMarkView::PickMarkedObj(const Point& rPnt, SdrObject*& rpObj, SdrPageView*& rpPV, sal_uIntPtr* pnMarkNum, sal_uIntPtr nOptions) const 1867 { 1868 SortMarkedObjects(); 1869 sal_Bool bBoundCheckOn2ndPass=(nOptions & SDRSEARCH_PASS2BOUND) !=0; 1870 sal_Bool bCheckNearestOn3rdPass=(nOptions & SDRSEARCH_PASS3NEAREST) !=0; 1871 rpObj=NULL; 1872 rpPV=NULL; 1873 if (pnMarkNum!=NULL) *pnMarkNum=CONTAINER_ENTRY_NOTFOUND; 1874 Point aPt(rPnt); 1875 sal_uInt16 nTol=(sal_uInt16)nHitTolLog; 1876 sal_Bool bFnd=sal_False; 1877 sal_uIntPtr nMarkAnz=GetMarkedObjectCount(); 1878 sal_uIntPtr nMarkNum; 1879 for (nMarkNum=nMarkAnz; nMarkNum>0 && !bFnd;) { 1880 nMarkNum--; 1881 SdrMark* pM=GetSdrMarkByIndex(nMarkNum); 1882 SdrPageView* pPV=pM->GetPageView(); 1883 SdrObject* pObj=pM->GetMarkedSdrObj(); 1884 bFnd = 0 != CheckSingleSdrObjectHit(aPt,nTol,pObj,pPV,SDRSEARCH_TESTMARKABLE,0); 1885 if (bFnd) { 1886 rpObj=pObj; 1887 rpPV=pPV; 1888 if (pnMarkNum!=NULL) *pnMarkNum=nMarkNum; 1889 } 1890 } 1891 if ((bBoundCheckOn2ndPass || bCheckNearestOn3rdPass) && !bFnd) { 1892 SdrObject* pBestObj=NULL; 1893 SdrPageView* pBestPV=NULL; 1894 sal_uIntPtr nBestMarkNum=0; 1895 sal_uIntPtr nBestDist=ULONG_MAX; 1896 for (nMarkNum=nMarkAnz; nMarkNum>0 && !bFnd;) { 1897 nMarkNum--; 1898 SdrMark* pM=GetSdrMarkByIndex(nMarkNum); 1899 SdrPageView* pPV=pM->GetPageView(); 1900 SdrObject* pObj=pM->GetMarkedSdrObj(); 1901 Rectangle aRect(pObj->GetCurrentBoundRect()); 1902 aRect.Left ()-=nTol; 1903 aRect.Top ()-=nTol; 1904 aRect.Right ()+=nTol; 1905 aRect.Bottom()+=nTol; 1906 if (aRect.IsInside(aPt)) { 1907 bFnd=sal_True; 1908 rpObj=pObj; 1909 rpPV=pPV; 1910 if (pnMarkNum!=NULL) *pnMarkNum=nMarkNum; 1911 } else if (bCheckNearestOn3rdPass) { 1912 sal_uIntPtr nDist=0; 1913 if (aPt.X()<aRect.Left()) nDist+=aRect.Left()-aPt.X(); 1914 if (aPt.X()>aRect.Right()) nDist+=aPt.X()-aRect.Right(); 1915 if (aPt.Y()<aRect.Top()) nDist+=aRect.Top()-aPt.Y(); 1916 if (aPt.Y()>aRect.Bottom()) nDist+=aPt.Y()-aRect.Bottom(); 1917 if (nDist<nBestDist) { 1918 pBestObj=pObj; 1919 pBestPV=pPV; 1920 nBestMarkNum=nMarkNum; 1921 } 1922 } 1923 } 1924 if (bCheckNearestOn3rdPass && !bFnd) { 1925 rpObj=pBestObj; 1926 rpPV=pBestPV; 1927 if (pnMarkNum!=NULL) *pnMarkNum=nBestMarkNum; 1928 bFnd=pBestObj!=NULL; 1929 } 1930 } 1931 return bFnd; 1932 } 1933 1934 SdrHitKind SdrMarkView::PickSomething(const Point& rPnt, short nTol) const 1935 { 1936 nTol=ImpGetHitTolLogic(nTol,NULL); 1937 SdrHitKind eRet=SDRHIT_NONE; 1938 Point aPt(rPnt); 1939 SdrObject* pObj=NULL; 1940 SdrPageView* pPV=NULL; 1941 if (eRet==SDRHIT_NONE && PickObj(rPnt,sal_uInt16(nTol),pObj,pPV,SDRSEARCH_PICKMARKABLE)) { 1942 Rectangle aRct1(aPt-Point(nTol,nTol),aPt+Point(nTol,nTol)); // HitRect fuer Toleranz 1943 Rectangle aBR(pObj->GetCurrentBoundRect()); 1944 if (aRct1.IsInside(aBR.TopLeft())) eRet=SDRHIT_BOUNDTL; 1945 else if (aRct1.IsInside(aBR.TopCenter())) eRet=SDRHIT_BOUNDTC; 1946 else if (aRct1.IsInside(aBR.TopRight())) eRet=SDRHIT_BOUNDTR; 1947 else if (aRct1.IsInside(aBR.LeftCenter())) eRet=SDRHIT_BOUNDCL; 1948 else if (aRct1.IsInside(aBR.RightCenter())) eRet=SDRHIT_BOUNDCR; 1949 else if (aRct1.IsInside(aBR.BottomLeft())) eRet=SDRHIT_BOUNDBL; 1950 else if (aRct1.IsInside(aBR.BottomCenter())) eRet=SDRHIT_BOUNDBC; 1951 else if (aRct1.IsInside(aBR.BottomRight())) eRet=SDRHIT_BOUNDBR; 1952 else eRet=SDRHIT_OBJECT; 1953 } 1954 return eRet; 1955 } 1956 1957 void SdrMarkView::UnmarkAllObj(SdrPageView* pPV) 1958 { 1959 if (GetMarkedObjectCount()!=0) { 1960 BrkAction(); 1961 //HMHBOOL bVis=bHdlShown; 1962 //HMHif (bVis) HideMarkHdl(); 1963 if (pPV!=NULL) 1964 { 1965 GetMarkedObjectListWriteAccess().DeletePageView(*pPV); 1966 } 1967 else 1968 { 1969 GetMarkedObjectListWriteAccess().Clear(); 1970 } 1971 pMarkedObj=NULL; 1972 pMarkedPV=NULL; 1973 MarkListHasChanged(); 1974 AdjustMarkHdl(); //HMHTRUE); 1975 //HMHif (bVis) ShowMarkHdl(); // ggf. fuer die RefPoints 1976 } 1977 } 1978 1979 void SdrMarkView::MarkAllObj(SdrPageView* _pPV) 1980 { 1981 BrkAction(); 1982 //HMHHideMarkHdl(); 1983 1984 if(!_pPV) 1985 { 1986 _pPV = GetSdrPageView(); 1987 } 1988 1989 // #i69171# _pPV may still be NULL if there is no SDrPageView (!), e.g. when inserting 1990 // other files 1991 if(_pPV) 1992 { 1993 const bool bMarkChg(GetMarkedObjectListWriteAccess().InsertPageView(*_pPV)); 1994 1995 if(bMarkChg) 1996 { 1997 MarkListHasChanged(); 1998 } 1999 } 2000 2001 if(GetMarkedObjectCount()) 2002 { 2003 AdjustMarkHdl(); //HMHTRUE); 2004 //HMHShowMarkHdl(); 2005 } 2006 } 2007 2008 void SdrMarkView::AdjustMarkHdl() //HMHBOOL bRestraintPaint) 2009 { 2010 //HMHBOOL bVis=bHdlShown; 2011 //HMHif (bVis) HideMarkHdl(); 2012 CheckMarked(); 2013 SetMarkRects(); 2014 SetMarkHandles(); 2015 //HMHif(bRestraintPaint && bVis) 2016 //HMH{ 2017 //HMH ShowMarkHdl(); 2018 //HMH} 2019 } 2020 2021 Rectangle SdrMarkView::GetMarkedObjBoundRect() const 2022 { 2023 Rectangle aRect; 2024 for (sal_uIntPtr nm=0; nm<GetMarkedObjectCount(); nm++) { 2025 SdrMark* pM=GetSdrMarkByIndex(nm); 2026 SdrObject* pO=pM->GetMarkedSdrObj(); 2027 Rectangle aR1(pO->GetCurrentBoundRect()); 2028 if (aRect.IsEmpty()) aRect=aR1; 2029 else aRect.Union(aR1); 2030 } 2031 return aRect; 2032 } 2033 2034 const Rectangle& SdrMarkView::GetMarkedObjRect() const 2035 { 2036 if (bMarkedObjRectDirty) { 2037 ((SdrMarkView*)this)->bMarkedObjRectDirty=sal_False; 2038 Rectangle aRect; 2039 for (sal_uIntPtr nm=0; nm<GetMarkedObjectCount(); nm++) { 2040 SdrMark* pM=GetSdrMarkByIndex(nm); 2041 SdrObject* pO=pM->GetMarkedSdrObj(); 2042 Rectangle aR1(pO->GetSnapRect()); 2043 if (aRect.IsEmpty()) aRect=aR1; 2044 else aRect.Union(aR1); 2045 } 2046 ((SdrMarkView*)this)->aMarkedObjRect=aRect; 2047 } 2048 return aMarkedObjRect; 2049 } 2050 2051 //////////////////////////////////////////////////////////////////////////////////////////////////// 2052 2053 void SdrMarkView::ImpTakeDescriptionStr(sal_uInt16 nStrCacheID, XubString& rStr, sal_uInt16 nVal, sal_uInt16 nOpt) const 2054 { 2055 rStr = ImpGetResStr(nStrCacheID); 2056 xub_StrLen nPos = rStr.SearchAscii("%1"); 2057 2058 if(nPos != STRING_NOTFOUND) 2059 { 2060 rStr.Erase(nPos, 2); 2061 2062 if(nOpt == IMPSDR_POINTSDESCRIPTION) 2063 { 2064 rStr.Insert(GetDescriptionOfMarkedPoints(), nPos); 2065 } 2066 else if(nOpt == IMPSDR_GLUEPOINTSDESCRIPTION) 2067 { 2068 rStr.Insert(GetDescriptionOfMarkedGluePoints(), nPos); 2069 } 2070 else 2071 { 2072 rStr.Insert(GetDescriptionOfMarkedObjects(), nPos); 2073 } 2074 } 2075 2076 nPos = rStr.SearchAscii("%2"); 2077 2078 if(nPos != STRING_NOTFOUND) 2079 { 2080 rStr.Erase(nPos, 2); 2081 rStr.Insert(UniString::CreateFromInt32(nVal), nPos); 2082 } 2083 } 2084 2085 //////////////////////////////////////////////////////////////////////////////////////////////////// 2086 2087 sal_Bool SdrMarkView::EnterMarkedGroup() 2088 { 2089 sal_Bool bRet=sal_False; 2090 // Es wird nur die erste gefundene Gruppe (also nur in einer PageView) geentert 2091 // Weil PageView::EnterGroup ein AdjustMarkHdl ruft. 2092 // Das muss ich per Flag mal unterbinden vvvvvvvv 2093 SdrPageView* pPV = GetSdrPageView(); 2094 2095 if(pPV) 2096 { 2097 sal_Bool bEnter=sal_False; 2098 for (sal_uInt32 nm(GetMarkedObjectCount()); nm > 0 && !bEnter;) 2099 { 2100 nm--; 2101 SdrMark* pM=GetSdrMarkByIndex(nm); 2102 if (pM->GetPageView()==pPV) { 2103 SdrObject* pObj=pM->GetMarkedSdrObj(); 2104 if (pObj->IsGroupObject()) { 2105 if (pPV->EnterGroup(pObj)) { 2106 bRet=sal_True; 2107 bEnter=sal_True; 2108 } 2109 } 2110 } 2111 } 2112 } 2113 return bRet; 2114 } 2115 2116 //////////////////////////////////////////////////////////////////////////////////////////////////// 2117 2118 void SdrMarkView::MarkListHasChanged() 2119 { 2120 GetMarkedObjectListWriteAccess().SetNameDirty(); 2121 SetEdgesOfMarkedNodesDirty(); // bEdgesOfMarkedNodesDirty=sal_True; 2122 2123 bMarkedObjRectDirty=sal_True; 2124 bMarkedPointsRectsDirty=sal_True; 2125 #ifdef DBG_UTIL 2126 if (pItemBrowser!=NULL) pItemBrowser->SetDirty(); 2127 #endif 2128 sal_Bool bOneEdgeMarked=sal_False; 2129 if (GetMarkedObjectCount()==1) { 2130 const SdrObject* pObj=GetMarkedObjectByIndex(0); 2131 if (pObj->GetObjInventor()==SdrInventor) { 2132 sal_uInt16 nIdent=pObj->GetObjIdentifier(); 2133 bOneEdgeMarked=nIdent==OBJ_EDGE; 2134 } 2135 } 2136 ImpSetGlueVisible4(bOneEdgeMarked); 2137 } 2138 2139 //////////////////////////////////////////////////////////////////////////////////////////////////// 2140 2141 void SdrMarkView::SetMoveOutside(sal_Bool bOn) 2142 { 2143 aHdl.SetMoveOutside(bOn); 2144 } 2145 2146 sal_Bool SdrMarkView::IsMoveOutside() const 2147 { 2148 return aHdl.IsMoveOutside(); 2149 } 2150 2151 void SdrMarkView::SetDesignMode( sal_Bool _bOn ) 2152 { 2153 if ( bDesignMode != _bOn ) 2154 { 2155 bDesignMode = _bOn; 2156 SdrPageView* pPageView = GetSdrPageView(); 2157 if ( pPageView ) 2158 pPageView->SetDesignMode( _bOn ); 2159 } 2160 } 2161 2162 // MarkHandles Objektaenderung: 2163 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2164 // - Bei Notify mit HINT_OBJCHG (oder so) werden die Handles erstmal versteckt 2165 // (wenn nicht schon wegen Dragging versteckt). 2166 // - XorHdl: Bei ModelHasChanged() werden sie dann wieder angezeigt. 2167 // - PaintEvents kommen nun durch. 2168 // - Die XorHandles werden z.T. wieder uebermalt. 2169 // - Xor: Nach dem Painten werden die Handles im (vom PaintHandler gerufenen) 2170 // CompleteRedraw per ToggleShownXor bei gesetzter ClipRegion nochmal gemalt 2171 // und damit ist alles in Butter. 2172 // - ToggleShownXor macht bei SolidHdl nix weil bHdlShown=FALSE 2173 // - Der AfterPaintTimer wird gestartet. 2174 // - SolidHdl: Im AfterPaintHandler wird ShowMarkHdl gerufen. 2175 // Da die Handles zu diesem Zeitpunkt nicht angezeigt sind wird: 2176 // - SaveBackground durchgefuehrt. 2177 // - DrawMarkHdl gerufen und bHdlShown gesetzt. 2178 // 2179 // MarkHandles bei sonstigem Invalidate: 2180 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2181 // In diesem Fall bekomme ich kein Notify und beim Aufruf des 2182 // PaintHandlers->CompleteRedraw() sind auch die SolidHandles sichtbar. 2183 2184