bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdview.cxx
blob9b8952c59711bd58fbea32576ee408d49d73bebd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <editeng/eeitem.hxx>
22 #include "svx/svdstr.hrc"
23 #include "svdglob.hxx"
24 #include <svx/svdpagv.hxx>
25 #include <svx/svdmrkv.hxx>
26 #include <svx/svdedxv.hxx>
27 #include <svx/svdobj.hxx>
28 #include <svx/svdopath.hxx>
29 #include <svx/svdograf.hxx>
30 #include <svx/svdomedia.hxx>
31 #include <svx/svdetc.hxx>
33 #ifdef DBG_UTIL
34 #include <svdibrow.hxx>
35 #endif
37 #include "svx/svdoutl.hxx"
38 #include "svx/svdview.hxx"
39 #include "editeng/editview.hxx"
40 #include "editeng/flditem.hxx"
41 #include "svx/obj3d.hxx"
42 #include "svx/svddrgmt.hxx"
43 #include "svx/svdotable.hxx"
44 #include <tools/tenccvt.hxx>
45 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
46 #include <svx/sdr/overlay/overlaymanager.hxx>
47 #include <svx/sdrpaintwindow.hxx>
48 #include <svx/sdrpagewindow.hxx>
49 #include <svx/sdrhittesthelper.hxx>
50 #include <svx/sdr/contact/viewcontact.hxx>
51 #include <drawinglayer/processor2d/contourextractor2d.hxx>
55 SdrViewEvent::SdrViewEvent()
56 : pHdl(NULL),
57 pObj(NULL),
58 pRootObj(NULL),
59 pPV(NULL),
60 pURLField(NULL),
61 eHit(SDRHIT_NONE),
62 eEvent(SDREVENT_NONE),
63 eHdlKind(HDL_MOVE),
64 eEndCreateCmd(SDRCREATE_NEXTPOINT),
65 nMouseClicks(0),
66 nMouseMode(MouseEventModifiers::NONE),
67 nMouseCode(0),
68 nHlplIdx(0),
69 nGlueId(0),
70 bMouseDown(false),
71 bMouseUp(false),
72 bDoubleHdlSize(false),
73 bIsAction(false),
74 bIsTextEdit(false),
75 bTextEditHit(false),
76 bAddMark(false),
77 bUnmark(false),
78 bPrevNextMark(false),
79 bMarkPrev(false),
80 bInsPointNewObj(false),
81 bDragWithCopy(false),
82 bCaptureMouse(false),
83 bReleaseMouse(false)
87 SdrViewEvent::~SdrViewEvent()
92 // helper class for all D&D overlays
94 void SdrDropMarkerOverlay::ImplCreateOverlays(
95 const SdrView& rView,
96 const basegfx::B2DPolyPolygon& rLinePolyPolygon)
98 for(sal_uInt32 a(0L); a < rView.PaintWindowCount(); a++)
100 SdrPaintWindow* pCandidate = rView.GetPaintWindow(a);
101 rtl::Reference< sdr::overlay::OverlayManager > xTargetOverlay = pCandidate->GetOverlayManager();
103 if (xTargetOverlay.is())
105 sdr::overlay::OverlayPolyPolygonStripedAndFilled* pNew = new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
106 rLinePolyPolygon);
108 xTargetOverlay->add(*pNew);
109 maObjects.append(*pNew);
114 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const SdrObject& rObject)
116 ImplCreateOverlays(
117 rView,
118 rObject.TakeXorPoly());
121 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const Rectangle& rRectangle)
123 basegfx::B2DPolygon aB2DPolygon;
125 aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Top()));
126 aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Top()));
127 aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Right(), rRectangle.Bottom()));
128 aB2DPolygon.append(basegfx::B2DPoint(rRectangle.Left(), rRectangle.Bottom()));
129 aB2DPolygon.setClosed(true);
131 ImplCreateOverlays(
132 rView,
133 basegfx::B2DPolyPolygon(aB2DPolygon));
136 SdrDropMarkerOverlay::SdrDropMarkerOverlay(const SdrView& rView, const Point& rStart, const Point& rEnd)
138 basegfx::B2DPolygon aB2DPolygon;
140 aB2DPolygon.append(basegfx::B2DPoint(rStart.X(), rStart.Y()));
141 aB2DPolygon.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y()));
142 aB2DPolygon.setClosed(true);
144 ImplCreateOverlays(
145 rView,
146 basegfx::B2DPolyPolygon(aB2DPolygon));
149 SdrDropMarkerOverlay::~SdrDropMarkerOverlay()
151 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
152 // That destructor calls clear() at the list which removes all objects from the
153 // OverlayManager and deletes them.
157 TYPEINIT1(SdrView,SdrCreateView);
159 SdrView::SdrView(SdrModel* pModel1, OutputDevice* pOut)
160 : SdrCreateView(pModel1,pOut),
161 bNoExtendedMouseDispatcher(false),
162 bNoExtendedKeyDispatcher(false),
163 bNoExtendedCommandDispatcher(false),
164 mbMasterPagePaintCaching(false)
166 bTextEditOnObjectsWithoutTextIfTextTool=false;
168 maAccessibilityOptions.AddListener(this);
170 onAccessibilityOptionsChanged();
173 SdrView::~SdrView()
175 maAccessibilityOptions.RemoveListener(this);
178 bool SdrView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin)
180 SetActualWin(pWin);
181 bool bRet = SdrCreateView::KeyInput(rKEvt,pWin);
182 if (!bRet && !IsExtendedKeyInputDispatcherEnabled()) {
183 bRet = true;
184 switch (rKEvt.GetKeyCode().GetFullFunction()) {
185 case KeyFuncType::CUT : Cut(); break;
186 case KeyFuncType::COPY : Yank(); break;
187 case KeyFuncType::PASTE : Paste(pWin); break;
188 case KeyFuncType::DELETE: DeleteMarked(); break;
189 case KeyFuncType::UNDO: pMod->Undo(); break;
190 case KeyFuncType::REDO: pMod->Redo(); break;
191 case KeyFuncType::REPEAT: pMod->Repeat(*this); break;
192 default: {
193 switch (rKEvt.GetKeyCode().GetFullCode()) {
194 case KEY_ESCAPE: {
195 if (IsTextEdit()) SdrEndTextEdit();
196 if (IsAction()) BrkAction();
197 if (pWin!=NULL) pWin->ReleaseMouse();
198 } break;
199 case KEY_DELETE: DeleteMarked(); break;
200 case KEY_CUT: case KEY_DELETE+KEY_SHIFT: Cut(); break;
201 case KEY_COPY: case KEY_INSERT+KEY_MOD1: Yank(); break;
202 case KEY_PASTE: case KEY_INSERT+KEY_SHIFT: Paste(pWin); break;
203 case KEY_UNDO: case KEY_BACKSPACE+KEY_MOD2: pMod->Undo(); break;
204 case KEY_BACKSPACE+KEY_MOD2+KEY_SHIFT: pMod->Redo(); break;
205 case KEY_REPEAT: case KEY_BACKSPACE+KEY_MOD2+KEY_MOD1: pMod->Repeat(*this); break;
206 case KEY_MOD1+KEY_A: MarkAll(); break;
207 default: bRet=false;
208 } // switch
210 } // switch
211 if (bRet && pWin!=NULL) {
212 pWin->SetPointer(GetPreferredPointer(
213 pWin->PixelToLogic(pWin->ScreenToOutputPixel( pWin->GetPointerPosPixel() ) ),
214 pWin,
215 rKEvt.GetKeyCode().GetModifier()));
218 return bRet;
221 bool SdrView::MouseButtonDown(const MouseEvent& rMEvt, vcl::Window* pWin)
223 SetActualWin(pWin);
224 if (rMEvt.IsLeft()) aDragStat.SetMouseDown(true);
225 bool bRet = SdrCreateView::MouseButtonDown(rMEvt,pWin);
226 if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) {
227 SdrViewEvent aVEvt;
228 PickAnything(rMEvt,SdrMouseEventKind::BUTTONDOWN,aVEvt);
229 bRet = DoMouseEvent(aVEvt);
231 return bRet;
234 bool SdrView::MouseButtonUp(const MouseEvent& rMEvt, vcl::Window* pWin)
236 SetActualWin(pWin);
237 if (rMEvt.IsLeft()) aDragStat.SetMouseDown(false);
238 bool bAction = IsAction();
239 bool bRet = !bAction && SdrCreateView::MouseButtonUp(rMEvt,pWin);
240 if (!bRet && !IsExtendedMouseEventDispatcherEnabled()) {
241 SdrViewEvent aVEvt;
242 PickAnything(rMEvt,SdrMouseEventKind::BUTTONUP,aVEvt);
243 bRet = DoMouseEvent(aVEvt);
245 return bRet;
248 bool SdrView::MouseMove(const MouseEvent& rMEvt, vcl::Window* pWin)
250 SetActualWin(pWin);
251 aDragStat.SetMouseDown(rMEvt.IsLeft());
252 bool bRet = SdrCreateView::MouseMove(rMEvt,pWin);
253 if (!IsExtendedMouseEventDispatcherEnabled() && !IsTextEditInSelectionMode()) {
254 SdrViewEvent aVEvt;
255 PickAnything(rMEvt,SdrMouseEventKind::MOVE,aVEvt);
256 if (DoMouseEvent(aVEvt)) bRet=true;
259 return bRet;
262 bool SdrView::Command(const CommandEvent& rCEvt, vcl::Window* pWin)
264 SetActualWin(pWin);
265 bool bRet = SdrCreateView::Command(rCEvt,pWin);
266 return bRet;
269 bool SdrView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
271 return SdrCreateView::GetAttributes(rTargetSet, bOnlyHardAttr);
274 SfxStyleSheet* SdrView::GetStyleSheet() const
276 return SdrCreateView::GetStyleSheet();
279 SdrHitKind SdrView::PickAnything(const MouseEvent& rMEvt, SdrMouseEventKind nEventKind, SdrViewEvent& rVEvt) const
281 rVEvt.bMouseDown=nEventKind==SdrMouseEventKind::BUTTONDOWN;
282 rVEvt.bMouseUp=nEventKind==SdrMouseEventKind::BUTTONUP;
283 rVEvt.nMouseClicks=rMEvt.GetClicks();
284 rVEvt.nMouseMode=rMEvt.GetMode();
285 rVEvt.nMouseCode=rMEvt.GetButtons() | rMEvt.GetModifier();
286 const OutputDevice* pOut=pActualOutDev;
287 if (pOut==NULL)
289 pOut = GetFirstOutputDevice();
291 Point aPnt(rMEvt.GetPosPixel());
292 if (pOut!=NULL) aPnt=pOut->PixelToLogic(aPnt);
293 rVEvt.aLogicPos=aPnt;
294 return PickAnything(aPnt,rVEvt);
297 // Dragging with the Mouse (Move)
298 // Example when creating a rectangle: MouseDown has to happen without a ModKey,
299 // else we usually force a selection (see below).
300 // When pressing Shift, Ctrl and Alt at the same time while doing a MouseMove,
301 // a centered, not snapped square is created.
302 // The dual allocation of Ortho and Shift won't usually create a problem, as the
303 // two functions are in most cases mutually exclusive. Only shearing (the kind
304 // that happens when contorting, not when rotating) can use both functions at
305 // the same time. To get around this, the user can use e. g. help lines.
306 #define MODKEY_NoSnap bCtrl /* temporarily disable snapping */
307 #define MODKEY_Ortho bShift /* ortho */
308 #define MODKEY_Center bAlt /* create/resize centeredly */
309 #define MODKEY_AngleSnap bShift
310 #define MODKEY_CopyDrag bCtrl /* drag and copy */
312 // click somewhere (MouseDown)
313 #define MODKEY_PolyPoly bAlt /* new Poly at InsPt and at Create */
314 #define MODKEY_MultiMark bShift /* MarkObj without doing UnmarkAll first */
315 #define MODKEY_Unmark bAlt /* deselect with a dragged frame */
316 #define MODKEY_ForceMark bCtrl /* force dragging a frame, even if there's an object at cursor position */
317 #define MODKEY_DeepMark bAlt /* MarkNextObj */
318 #define MODKEY_DeepBackw bShift /* MarkNextObj but backwards */
320 SdrHitKind SdrView::PickAnything(const Point& rLogicPos, SdrViewEvent& rVEvt) const
322 const OutputDevice* pOut=pActualOutDev;
323 if (pOut==NULL)
325 pOut = GetFirstOutputDevice();
328 // #i73628# Use a non-changeable copy of he logic position
329 const Point aLocalLogicPosition(rLogicPos);
331 bool bEditMode=IsEditMode();
332 bool bPointMode=bEditMode && HasMarkablePoints();
333 bool bGluePointMode=IsGluePointEditMode();
334 bool bInsPolyPt=bPointMode && IsInsObjPointMode() && IsInsObjPointPossible();
335 bool bInsGluePt=bGluePointMode && IsInsGluePointMode() && IsInsGluePointPossible();
336 bool bIsTextEdit=IsTextEdit();
337 bool bTextEditHit=IsTextEditHit(aLocalLogicPosition,0/*nHitTolLog*/);
338 bool bTextEditSel=IsTextEditInSelectionMode();
339 bool bShift=(rVEvt.nMouseCode & KEY_SHIFT) !=0;
340 bool bCtrl=(rVEvt.nMouseCode & KEY_MOD1) !=0;
341 bool bAlt=(rVEvt.nMouseCode & KEY_MOD2) !=0;
342 SdrHitKind eHit=SDRHIT_NONE;
343 SdrHdl* pHdl=pOut!=NULL && !bTextEditSel ? PickHandle(aLocalLogicPosition) : NULL;
344 SdrPageView* pPV=NULL;
345 SdrObject* pObj=NULL;
346 SdrObject* pHitObj=NULL;
347 bool bHitPassDirect=true;
348 sal_uInt16 nHlplIdx=0;
349 sal_uInt16 nGlueId=0;
350 if (bTextEditHit || bTextEditSel)
352 eHit=SDRHIT_TEXTEDIT;
353 bTextEditHit=true;
355 else if (pHdl!=NULL)
357 eHit=SDRHIT_HANDLE; // handle is hit: highest priority
359 else if (bEditMode && IsHlplVisible() && IsHlplFront() && pOut!=NULL && PickHelpLine(aLocalLogicPosition,nHitTolLog,*pOut,nHlplIdx,pPV))
361 eHit=SDRHIT_HELPLINE; // help line in the foreground hit: can be moved now
363 else if (bGluePointMode && PickGluePoint(aLocalLogicPosition,pObj,nGlueId,pPV))
365 eHit=SDRHIT_GLUEPOINT; // deselected glue point hit
367 else if (PickObj(aLocalLogicPosition,nHitTolLog,pHitObj,pPV,SdrSearchOptions::DEEP|SdrSearchOptions::MARKED,&pObj,&bHitPassDirect))
369 eHit=SDRHIT_MARKEDOBJECT;
370 sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( pObj );
371 if( pTableObj )
373 sal_Int32 nX = 0, nY = 0;
374 switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY, 0 ) )
376 case sdr::table::SDRTABLEHIT_CELL:
377 eHit = SDRHIT_CELL;
378 break;
379 case sdr::table::SDRTABLEHIT_CELLTEXTAREA:
380 eHit = SDRHIT_TEXTEDITOBJ;
381 break;
382 default:
383 break;
387 else if (PickObj(aLocalLogicPosition,nHitTolLog,pHitObj,pPV,SdrSearchOptions::DEEP|SdrSearchOptions::ALSOONMASTER|SdrSearchOptions::WHOLEPAGE,&pObj,&bHitPassDirect))
389 // MasterPages and WholePage for Macro and URL
390 eHit=SDRHIT_UNMARKEDOBJECT;
391 sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( pObj );
392 if( pTableObj )
394 sal_Int32 nX = 0, nY = 0;
395 switch( pTableObj->CheckTableHit( aLocalLogicPosition, nX, nY, 0 ) )
397 case sdr::table::SDRTABLEHIT_CELL:
398 eHit = SDRHIT_CELL;
399 break;
400 case sdr::table::SDRTABLEHIT_CELLTEXTAREA:
401 eHit = SDRHIT_TEXTEDITOBJ;
402 break;
403 default:
404 break;
408 else if (bEditMode && IsHlplVisible() && !IsHlplFront() && pOut!=NULL && PickHelpLine(aLocalLogicPosition,nHitTolLog,*pOut,nHlplIdx,pPV))
410 eHit=SDRHIT_HELPLINE; // help line in foreground hit: can be moved now
412 if (IsMacroMode() && eHit==SDRHIT_UNMARKEDOBJECT)
414 bool bRoot=pObj->HasMacro();
415 bool bDeep=pObj!=pHitObj && pHitObj->HasMacro();
416 bool bMid=false; // Have we hit upon a grouped group with a macro?
417 SdrObject* pMidObj=NULL;
418 if (pObj!=pHitObj)
420 SdrObject* pObjTmp=NULL;
421 pObjTmp=pHitObj->GetUpGroup();
422 if (pObjTmp==pObj) pObjTmp=NULL;
423 while (pObjTmp!=NULL)
425 if (pObjTmp->HasMacro())
427 bMid=true;
428 pMidObj=pObjTmp;
430 pObjTmp=pObjTmp->GetUpGroup();
431 if (pObjTmp==pObj) pObjTmp=NULL;
435 if (bDeep || bMid || bRoot)
437 SdrObjMacroHitRec aHitRec;
438 aHitRec.aPos=aLocalLogicPosition;
439 aHitRec.aDownPos=aLocalLogicPosition;
440 aHitRec.nTol=nHitTolLog;
441 aHitRec.pVisiLayer=&pPV->GetVisibleLayers();
442 aHitRec.pPageView=pPV;
443 if (bDeep) bDeep=pHitObj->IsMacroHit(aHitRec);
444 if (bMid ) bMid =pMidObj->IsMacroHit(aHitRec);
445 if (bRoot) bRoot=pObj->IsMacroHit(aHitRec);
446 if (bRoot || bMid || bDeep)
448 // Priorities: 1. Root, 2. Mid, 3. Deep
449 rVEvt.pRootObj=pObj;
450 if (!bRoot) pObj=pMidObj;
451 if (!bRoot && !bMid) pObj=pHitObj;
452 eHit=SDRHIT_MACRO;
456 // check for URL field
457 if (IsMacroMode() && eHit==SDRHIT_UNMARKEDOBJECT)
459 SdrTextObj* pTextObj=PTR_CAST(SdrTextObj,pHitObj);
460 if (pTextObj!=NULL && pTextObj->HasText())
462 bool bTEHit(pPV &&
463 SdrObjectPrimitiveHit(*pTextObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true));
465 if (bTEHit)
467 Rectangle aTextRect;
468 Rectangle aAnchor;
469 SdrOutliner* pOutliner = &pTextObj->ImpGetDrawOutliner();
470 if( pTextObj->GetModel() )
471 pOutliner = &pTextObj->GetModel()->GetHitTestOutliner();
473 pTextObj->TakeTextRect( *pOutliner, aTextRect, false, &aAnchor, false );
475 // #i73628# Use a text-relative position for hit test in hit test outliner
476 Point aTemporaryTextRelativePosition(aLocalLogicPosition - aTextRect.TopLeft());
478 // account for FitToSize
479 bool bFitToSize(pTextObj->IsFitToSize());
480 if (bFitToSize) {
481 Fraction aX(aTextRect.GetWidth()-1,aAnchor.GetWidth()-1);
482 Fraction aY(aTextRect.GetHeight()-1,aAnchor.GetHeight()-1);
483 ResizePoint(aTemporaryTextRelativePosition,Point(),aX,aY);
485 // account for rotation
486 const GeoStat& rGeo=pTextObj->GetGeoStat();
487 if (rGeo.nRotationAngle!=0) RotatePoint(aTemporaryTextRelativePosition,Point(),-rGeo.nSin,rGeo.nCos); // -sin for Unrotate
488 // we currently don't account for ticker text
489 if(pActualOutDev && pActualOutDev->GetOutDevType() == OUTDEV_WINDOW)
491 OutlinerView aOLV(pOutliner, const_cast<vcl::Window*>(static_cast<const vcl::Window*>(pActualOutDev.get())));
492 const EditView& aEV=aOLV.GetEditView();
493 const SvxFieldItem* pItem=aEV.GetField(aTemporaryTextRelativePosition);
494 if (pItem!=NULL) {
495 const SvxFieldData* pFld=pItem->GetField();
496 const SvxURLField* pURL=PTR_CAST(SvxURLField,pFld);
497 if (pURL!=NULL) {
498 eHit=SDRHIT_URLFIELD;
499 rVEvt.pURLField=pURL;
507 if (bHitPassDirect &&
508 (eHit==SDRHIT_MARKEDOBJECT || eHit==SDRHIT_UNMARKEDOBJECT) &&
509 (IsTextTool() || (IsEditMode() && IsQuickTextEditMode())) && pHitObj->HasTextEdit())
511 // Around the TextEditArea there's a border to select without going into text edit mode.
512 Rectangle aBoundRect(pHitObj->GetCurrentBoundRect());
514 // Force to SnapRect when Fontwork
515 if(pHitObj->ISA(SdrTextObj) && static_cast<SdrTextObj*>(pHitObj)->IsFontwork())
517 aBoundRect = pHitObj->GetSnapRect();
520 sal_Int32 nTolerance(nHitTolLog);
521 bool bBoundRectHit(false);
523 if(pOut)
525 nTolerance = pOut->PixelToLogic(Size(2, 0)).Width();
528 if( (aLocalLogicPosition.X() >= aBoundRect.Left() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Left() + nTolerance)
529 || (aLocalLogicPosition.X() >= aBoundRect.Right() - nTolerance && aLocalLogicPosition.X() <= aBoundRect.Right() + nTolerance)
530 || (aLocalLogicPosition.Y() >= aBoundRect.Top() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Top() + nTolerance)
531 || (aLocalLogicPosition.Y() >= aBoundRect.Bottom() - nTolerance && aLocalLogicPosition.Y() <= aBoundRect.Bottom() + nTolerance))
533 bBoundRectHit = true;
536 if(!bBoundRectHit)
538 bool bTEHit(pPV &&
539 SdrObjectPrimitiveHit(*pHitObj, aLocalLogicPosition, 0, *pPV, &pPV->GetVisibleLayers(), true));
541 // TextEdit attached to an object in a locked layer
542 if (pPV->GetLockedLayers().IsSet(pHitObj->GetLayer()))
544 bTEHit=false;
547 if (bTEHit)
549 rVEvt.pRootObj=pObj;
550 pObj=pHitObj;
551 eHit=SDRHIT_TEXTEDITOBJ;
555 if (!bHitPassDirect && eHit==SDRHIT_UNMARKEDOBJECT) {
556 eHit=SDRHIT_NONE;
557 pObj=NULL;
558 pPV=NULL;
560 bool bMouseLeft=(rVEvt.nMouseCode&MOUSE_LEFT)!=0;
561 bool bMouseRight=(rVEvt.nMouseCode&MOUSE_RIGHT)!=0;
562 bool bMouseDown=rVEvt.bMouseDown;
563 bool bMouseUp=rVEvt.bMouseUp;
564 SdrEventKind eEvent=SDREVENT_NONE;
565 bool bIsAction=IsAction();
567 if (bIsAction)
569 if (bMouseDown)
571 if (bMouseRight) eEvent=SDREVENT_BCKACTION;
573 else if (bMouseUp)
575 if (bMouseLeft)
577 eEvent=SDREVENT_ENDACTION;
578 if (IsDragObj())
580 eEvent=SDREVENT_ENDDRAG;
581 rVEvt.bDragWithCopy=MODKEY_CopyDrag;
583 else if (IsCreateObj() || IsInsObjPoint())
585 eEvent=IsCreateObj() ? SDREVENT_ENDCREATE : SDREVENT_ENDINSOBJPOINT;
586 rVEvt.eEndCreateCmd=SDRCREATE_NEXTPOINT;
587 if (MODKEY_PolyPoly) rVEvt.eEndCreateCmd=SDRCREATE_NEXTOBJECT;
588 if (rVEvt.nMouseClicks>1) rVEvt.eEndCreateCmd=SDRCREATE_FORCEEND;
590 else if (IsMarking())
592 eEvent=SDREVENT_ENDMARK;
593 if (!aDragStat.IsMinMoved())
595 eEvent=SDREVENT_BRKMARK;
596 rVEvt.bAddMark=MODKEY_MultiMark;
601 else
603 eEvent=SDREVENT_MOVACTION;
606 else if (eHit==SDRHIT_TEXTEDIT)
608 eEvent=SDREVENT_TEXTEDIT;
610 else if (bMouseDown && bMouseLeft)
612 if (rVEvt.nMouseClicks==2 && rVEvt.nMouseCode==MOUSE_LEFT && pObj!=NULL && pHitObj!=NULL && pHitObj->HasTextEdit() && eHit==SDRHIT_MARKEDOBJECT)
614 rVEvt.pRootObj=pObj;
615 pObj=pHitObj;
616 eEvent=SDREVENT_BEGTEXTEDIT;
618 else if (MODKEY_ForceMark && eHit!=SDRHIT_URLFIELD)
620 eEvent=SDREVENT_BEGMARK; // AddMark,Unmark */
622 else if (eHit==SDRHIT_HELPLINE)
624 eEvent=SDREVENT_BEGDRAGHELPLINE; // nothing, actually
626 else if (eHit==SDRHIT_GLUEPOINT)
628 eEvent=SDREVENT_MARKGLUEPOINT; // AddMark+Drag
629 rVEvt.bAddMark=MODKEY_MultiMark || MODKEY_DeepMark; // if not hit with Deep
631 else if (eHit==SDRHIT_HANDLE)
633 eEvent=SDREVENT_BEGDRAGOBJ; // Mark+Drag,AddMark+Drag,DeepMark+Drag,Unmark
634 bool bGlue=pHdl->GetKind()==HDL_GLUE;
635 bool bPoly=!bGlue && IsPointMarkable(*pHdl);
636 bool bMarked=bGlue || (bPoly && pHdl->IsSelected());
637 if (bGlue || bPoly)
639 eEvent=bGlue ? SDREVENT_MARKGLUEPOINT : SDREVENT_MARKPOINT;
640 if (MODKEY_DeepMark)
642 rVEvt.bAddMark=true;
643 rVEvt.bPrevNextMark=true;
644 rVEvt.bMarkPrev=MODKEY_DeepBackw;
646 else if (MODKEY_MultiMark)
648 rVEvt.bAddMark=true;
649 rVEvt.bUnmark=bMarked; // Toggle
650 if (bGlue)
652 pObj=pHdl->GetObj();
653 nGlueId=(sal_uInt16)pHdl->GetObjHdlNum();
656 else if (bMarked)
658 eEvent=SDREVENT_BEGDRAGOBJ; // don't change MarkState, only change Drag
662 else if (bInsPolyPt && (MODKEY_PolyPoly || (!MODKEY_MultiMark && !MODKEY_DeepMark)))
664 eEvent=SDREVENT_BEGINSOBJPOINT;
665 rVEvt.bInsPointNewObj=MODKEY_PolyPoly;
667 else if (bInsGluePt && !MODKEY_MultiMark && !MODKEY_DeepMark)
669 eEvent=SDREVENT_BEGINSGLUEPOINT;
671 else if (eHit==SDRHIT_TEXTEDITOBJ)
673 eEvent=SDREVENT_BEGTEXTEDIT; // AddMark+Drag,DeepMark+Drag,Unmark
674 if (MODKEY_MultiMark || MODKEY_DeepMark)
675 { // if not hit with Deep
676 eEvent=SDREVENT_MARKOBJ;
679 else if (eHit==SDRHIT_MACRO)
681 eEvent=SDREVENT_BEGMACROOBJ; // AddMark+Drag
682 if (MODKEY_MultiMark || MODKEY_DeepMark)
683 { // if not hit with Deep
684 eEvent=SDREVENT_MARKOBJ;
687 else if (eHit==SDRHIT_URLFIELD)
689 eEvent=SDREVENT_EXECUTEURL; // AddMark+Drag
690 if (MODKEY_MultiMark || MODKEY_DeepMark)
691 { // if not hit with Deep
692 eEvent=SDREVENT_MARKOBJ;
695 else if (eHit==SDRHIT_MARKEDOBJECT)
697 eEvent=SDREVENT_BEGDRAGOBJ; // DeepMark+Drag,Unmark
699 if (MODKEY_MultiMark || MODKEY_DeepMark)
700 { // if not hit with Deep
701 eEvent=SDREVENT_MARKOBJ;
704 else if (IsCreateMode())
706 eEvent=SDREVENT_BEGCREATEOBJ; // nothing, actually
708 else if (eHit==SDRHIT_UNMARKEDOBJECT)
710 eEvent=SDREVENT_MARKOBJ; // AddMark+Drag
712 else
714 eEvent=SDREVENT_BEGMARK;
717 if (eEvent==SDREVENT_MARKOBJ)
719 rVEvt.bAddMark=MODKEY_MultiMark || MODKEY_DeepMark; // if not hit with Deep
720 rVEvt.bPrevNextMark=MODKEY_DeepMark;
721 rVEvt.bMarkPrev=MODKEY_DeepMark && MODKEY_DeepBackw;
723 if (eEvent==SDREVENT_BEGMARK)
725 rVEvt.bAddMark=MODKEY_MultiMark;
726 rVEvt.bUnmark=MODKEY_Unmark;
729 rVEvt.bIsAction=bIsAction;
730 rVEvt.bIsTextEdit=bIsTextEdit;
731 rVEvt.bTextEditHit=bTextEditHit;
732 rVEvt.aLogicPos=aLocalLogicPosition;
733 rVEvt.pHdl=pHdl;
734 rVEvt.pObj=pObj;
735 if(rVEvt.pRootObj==NULL)
736 rVEvt.pRootObj=pObj;
737 rVEvt.pPV=pPV;
738 rVEvt.nHlplIdx=nHlplIdx;
739 rVEvt.nGlueId=nGlueId;
740 rVEvt.eHit=eHit;
741 rVEvt.eEvent=eEvent;
742 rVEvt.bCaptureMouse=bMouseLeft && bMouseDown && eEvent!=SDREVENT_NONE;
743 rVEvt.bReleaseMouse=bMouseLeft && bMouseUp;
744 #ifdef DGB_UTIL
745 if (rVEvt.pRootObj!=NULL) {
746 if (rVEvt.pRootObj->GetObjList()!=rVEvt.pPV->GetObjList()) {
747 OSL_FAIL("SdrView::PickAnything(): pRootObj->GetObjList()!=pPV->GetObjList() !");
750 #endif
751 return eHit;
754 bool SdrView::DoMouseEvent(const SdrViewEvent& rVEvt)
756 bool bRet=false;
757 SdrHitKind eHit=rVEvt.eHit;
758 Point aLogicPos(rVEvt.aLogicPos);
760 bool bShift=(rVEvt.nMouseCode & KEY_SHIFT) !=0;
761 bool bCtrl=(rVEvt.nMouseCode & KEY_MOD1) !=0;
762 bool bAlt=(rVEvt.nMouseCode & KEY_MOD2) !=0;
763 bool bMouseLeft=(rVEvt.nMouseCode&MOUSE_LEFT)!=0;
764 bool bMouseDown=rVEvt.bMouseDown;
765 bool bMouseUp=rVEvt.bMouseUp;
766 if (bMouseDown) {
767 if (bMouseLeft) aDragStat.SetMouseDown(true);
768 } else if (bMouseUp) {
769 if (bMouseLeft) aDragStat.SetMouseDown(false);
770 } else { // else, MouseMove
771 aDragStat.SetMouseDown(bMouseLeft);
774 #ifdef MODKEY_NoSnap
775 SetSnapEnabled(!MODKEY_NoSnap);
776 #endif
777 #ifdef MODKEY_Ortho
778 SetOrtho(MODKEY_Ortho!=IsOrthoDesired());
779 #endif
780 #ifdef MODKEY_AngleSnap
781 SetAngleSnapEnabled(MODKEY_AngleSnap);
782 #endif
783 #ifdef MODKEY_CopyDrag
784 SetDragWithCopy(MODKEY_CopyDrag);
785 #endif
786 #ifdef MODKEY_Center
787 SetCreate1stPointAsCenter(MODKEY_Center);
788 SetResizeAtCenter(MODKEY_Center);
789 SetCrookAtCenter(MODKEY_Center);
790 #endif
791 if (bMouseLeft && bMouseDown && rVEvt.bIsTextEdit && (eHit==SDRHIT_UNMARKEDOBJECT || eHit==SDRHIT_NONE)) {
792 SdrEndTextEdit(); // User has clicked beneath object, exit edit mode.
793 // pHdl is invalid, then, that shouldn't matter, though, as we expect
794 // pHdl==NULL (because of eHit).
796 switch (rVEvt.eEvent) {
797 case SDREVENT_NONE: bRet=false; break;
798 case SDREVENT_TEXTEDIT: bRet=false; break; // Events handled by the OutlinerView are not taken into account here.
799 case SDREVENT_MOVACTION: MovAction(aLogicPos); bRet=true; break;
800 case SDREVENT_ENDACTION: EndAction(); bRet=true; break;
801 case SDREVENT_BCKACTION: BckAction(); bRet=true; break;
802 case SDREVENT_BRKACTION: BrkAction(); bRet=true; break;
803 case SDREVENT_ENDMARK : EndAction(); bRet=true; break;
804 case SDREVENT_BRKMARK : {
805 BrkAction();
806 if (!MarkObj(aLogicPos,nHitTolLog,rVEvt.bAddMark)) {
807 // No object hit. Do the following:
808 // 1. deselect any selected glue points
809 // 2. deselect any selected polygon points
810 // 3. deselect any selected objects
811 if (!rVEvt.bAddMark) UnmarkAll();
813 bRet=true;
814 } break;
815 case SDREVENT_ENDCREATE: { // if necessary, MarkObj
816 SdrCreateCmd eCmd=SDRCREATE_NEXTPOINT;
817 if (MODKEY_PolyPoly) eCmd=SDRCREATE_NEXTOBJECT;
818 if (rVEvt.nMouseClicks>1) eCmd=SDRCREATE_FORCEEND;
819 if (!EndCreateObj(eCmd)) { // Don't evaluate event for Create? -> Select
820 if (eHit==SDRHIT_UNMARKEDOBJECT || eHit==SDRHIT_TEXTEDIT) {
821 MarkObj(rVEvt.pRootObj,rVEvt.pPV);
822 if (eHit==SDRHIT_TEXTEDIT)
824 bool bRet2(pActualOutDev && OUTDEV_WINDOW == pActualOutDev->GetOutDevType() &&
825 SdrBeginTextEdit(rVEvt.pObj, rVEvt.pPV, const_cast<vcl::Window*>(static_cast<const vcl::Window*>(pActualOutDev.get())), false, (SdrOutliner*)0L));
827 if(bRet2)
829 MouseEvent aMEvt(pActualOutDev->LogicToPixel(aLogicPos),
830 1,rVEvt.nMouseMode,rVEvt.nMouseCode,rVEvt.nMouseCode);
832 OutlinerView* pOLV=GetTextEditOutlinerView();
833 if (pOLV!=NULL) {
834 pOLV->MouseButtonDown(aMEvt); // event for the Outliner, but without double-click
835 pOLV->MouseButtonUp(aMEvt); // event for the Outliner, but without double-click
839 bRet=true; // object is selected and (if necessary) TextEdit is started
840 } else bRet=false; // canceled Create, nothing else
841 } else bRet=true; // return true for EndCreate
842 } break;
843 case SDREVENT_ENDDRAG: {
844 bRet=EndDragObj(IsDragWithCopy());
845 ForceMarkedObjToAnotherPage(); // TODO: Undo+bracing missing!
846 } break;
847 case SDREVENT_MARKOBJ: { // + (if applicable) BegDrag
848 if (!rVEvt.bAddMark) UnmarkAllObj();
849 bool bUnmark=rVEvt.bUnmark;
850 if (rVEvt.bPrevNextMark) {
851 bRet=MarkNextObj(aLogicPos,nHitTolLog,rVEvt.bMarkPrev);
852 } else {
853 SortMarkedObjects();
854 const size_t nCount0=GetMarkedObjectCount();
855 bRet=MarkObj(aLogicPos,nHitTolLog,rVEvt.bAddMark);
856 SortMarkedObjects();
857 const size_t nCount1=GetMarkedObjectCount();
858 bUnmark=nCount1<nCount0;
860 if (!bUnmark) {
861 BegDragObj(aLogicPos,NULL,(SdrHdl*)NULL,nMinMovLog);
862 bRet=true;
864 } break;
865 case SDREVENT_MARKPOINT: { // + (if applicable) BegDrag
866 if (!rVEvt.bAddMark) UnmarkAllPoints();
867 if (rVEvt.bPrevNextMark) {
868 bRet=MarkNextPoint(aLogicPos,rVEvt.bMarkPrev);
869 } else {
870 bRet=MarkPoint(*rVEvt.pHdl,rVEvt.bUnmark);
872 if (!rVEvt.bUnmark && !rVEvt.bPrevNextMark) {
873 BegDragObj(aLogicPos,NULL,rVEvt.pHdl,nMinMovLog);
874 bRet=true;
876 } break;
877 case SDREVENT_MARKGLUEPOINT: { // + (if applicable) BegDrag
878 if (!rVEvt.bAddMark) UnmarkAllGluePoints();
879 if (rVEvt.bPrevNextMark) {
880 bRet=MarkNextGluePoint(aLogicPos,rVEvt.bMarkPrev);
881 } else {
882 bRet=MarkGluePoint(rVEvt.pObj,rVEvt.nGlueId,rVEvt.pPV,rVEvt.bUnmark);
884 if (!rVEvt.bUnmark && !rVEvt.bPrevNextMark) {
885 SdrHdl* pHdl=GetGluePointHdl(rVEvt.pObj,rVEvt.nGlueId);
886 BegDragObj(aLogicPos,NULL,pHdl,nMinMovLog);
887 bRet=true;
889 } break;
890 case SDREVENT_BEGMARK: bRet=BegMark(aLogicPos,rVEvt.bAddMark,rVEvt.bUnmark); break;
891 case SDREVENT_BEGINSOBJPOINT: bRet = BegInsObjPoint(aLogicPos, MODKEY_PolyPoly); break;
892 case SDREVENT_ENDINSOBJPOINT: {
893 SdrCreateCmd eCmd=SDRCREATE_NEXTPOINT;
894 if (MODKEY_PolyPoly) eCmd=SDRCREATE_NEXTOBJECT;
895 if (rVEvt.nMouseClicks>1) eCmd=SDRCREATE_FORCEEND;
896 EndInsObjPoint(eCmd);
897 bRet=true;
898 } break;
899 case SDREVENT_BEGINSGLUEPOINT: bRet=BegInsGluePoint(aLogicPos); break;
900 case SDREVENT_BEGDRAGHELPLINE: bRet=BegDragHelpLine(rVEvt.nHlplIdx,rVEvt.pPV); break;
901 case SDREVENT_BEGDRAGOBJ: bRet=BegDragObj(aLogicPos,NULL,rVEvt.pHdl,nMinMovLog); break;
902 case SDREVENT_BEGCREATEOBJ: {
903 if (nAktInvent==SdrInventor && nAktIdent==OBJ_CAPTION) {
904 long nHgt=SdrEngineDefaults::GetFontHeight();
905 bRet=BegCreateCaptionObj(aLogicPos,Size(5*nHgt,2*nHgt));
906 } else bRet=BegCreateObj(aLogicPos);
907 } break;
908 case SDREVENT_BEGMACROOBJ: {
909 bRet=BegMacroObj(aLogicPos,nHitTolLog,rVEvt.pObj,rVEvt.pPV,const_cast<vcl::Window*>(static_cast<const vcl::Window*>(pActualOutDev.get())));
910 } break;
911 case SDREVENT_BEGTEXTEDIT: {
912 if (!IsObjMarked(rVEvt.pObj)) {
913 UnmarkAllObj();
914 MarkObj(rVEvt.pRootObj,rVEvt.pPV);
917 bRet = pActualOutDev && OUTDEV_WINDOW == pActualOutDev->GetOutDevType()&&
918 SdrBeginTextEdit(rVEvt.pObj, rVEvt.pPV, const_cast<vcl::Window*>(static_cast<const vcl::Window*>(pActualOutDev.get())), false, (SdrOutliner*)0L);
920 if(bRet)
922 MouseEvent aMEvt(pActualOutDev->LogicToPixel(aLogicPos),
923 1,rVEvt.nMouseMode,rVEvt.nMouseCode,rVEvt.nMouseCode);
924 OutlinerView* pOLV=GetTextEditOutlinerView();
925 if (pOLV!=NULL) pOLV->MouseButtonDown(aMEvt); // event for the Outliner, but without double-click
927 } break;
928 default: break;
929 } // switch
930 if (bRet && pActualOutDev && pActualOutDev->GetOutDevType()==OUTDEV_WINDOW) {
931 vcl::Window* pWin=const_cast<vcl::Window*>(static_cast<const vcl::Window*>(pActualOutDev.get()));
932 // left mouse button pressed?
933 bool bLeftDown=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && rVEvt.bMouseDown;
934 // left mouse button released?
935 bool bLeftUp=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && rVEvt.bMouseUp;
936 // left mouse button pressed or held?
937 bool bLeftDown1=(rVEvt.nMouseCode&MOUSE_LEFT)!=0 && !rVEvt.bMouseUp;
938 pWin->SetPointer(GetPreferredPointer(rVEvt.aLogicPos,pWin,
939 rVEvt.nMouseCode & (KEY_SHIFT|KEY_MOD1|KEY_MOD2),bLeftDown1));
940 bool bAction=IsAction();
941 if (bLeftDown && bAction)
942 pWin->CaptureMouse();
943 else if (bLeftUp || (rVEvt.bIsAction && !bAction))
944 pWin->ReleaseMouse();
946 return bRet;
948 #include <editeng/outlobj.hxx>
950 Pointer SdrView::GetPreferredPointer(const Point& rMousePos, const OutputDevice* pOut, sal_uInt16 nModifier, bool bLeftDown) const
952 // Actions
953 if (IsCreateObj())
955 return pAktCreate->GetCreatePointer();
957 if (mpCurrentSdrDragMethod)
959 if ((IsDraggingPoints() || IsDraggingGluePoints()) && IsMouseHideWhileDraggingPoints())
960 return Pointer(PointerStyle::Null);
962 return mpCurrentSdrDragMethod->GetSdrDragPointer();
964 if (IsMarkObj() || IsMarkPoints() || IsMarkGluePoints() || IsSetPageOrg()) return Pointer(PointerStyle::Arrow);
965 if (IsDragHelpLine()) return GetDraggedHelpLinePointer();
966 if (IsMacroObj()) {
967 SdrObjMacroHitRec aHitRec;
968 aHitRec.aPos=pOut->LogicToPixel(rMousePos);
969 aHitRec.aDownPos=aMacroDownPos;
970 aHitRec.nTol=nMacroTol;
971 aHitRec.pVisiLayer=&pMacroPV->GetVisibleLayers();
972 aHitRec.pPageView=pMacroPV;
973 aHitRec.pOut=pMacroWin.get();
974 aHitRec.bDown=bMacroDown;
975 return pMacroObj->GetMacroPointer(aHitRec);
978 // TextEdit, ObjEdit, Macro
979 if (IsTextEdit() && (IsTextEditInSelectionMode() || IsTextEditHit(rMousePos,0/*nTol*/)))
981 if(!pOut || IsTextEditInSelectionMode())
983 if(pTextEditOutliner->IsVertical())
984 return Pointer(PointerStyle::TextVertical);
985 else
986 return Pointer(PointerStyle::Text);
988 // Outliner should return something here...
989 Point aPos(pOut->LogicToPixel(rMousePos));
990 Pointer aPointer(pTextEditOutlinerView->GetPointer(aPos));
991 if (aPointer==PointerStyle::Arrow)
993 if(pTextEditOutliner->IsVertical())
994 aPointer = PointerStyle::TextVertical;
995 else
996 aPointer = PointerStyle::Text;
998 return aPointer;
1001 SdrViewEvent aVEvt;
1002 aVEvt.nMouseCode=(nModifier&(KEY_SHIFT|KEY_MOD1|KEY_MOD2))|MOUSE_LEFT; // to see what would happen on MouseLeftDown
1003 aVEvt.bMouseDown=!bLeftDown; // What if ..?
1004 aVEvt.bMouseUp=bLeftDown; // What if ..?
1005 if (pOut!=NULL)
1006 const_cast<SdrView*>(this)->SetActualWin(pOut);
1007 SdrHitKind eHit=PickAnything(rMousePos,aVEvt);
1008 SdrEventKind eEvent=aVEvt.eEvent;
1009 switch (eEvent)
1011 case SDREVENT_BEGCREATEOBJ:
1012 return aAktCreatePointer;
1013 case SDREVENT_MARKOBJ:
1014 return Pointer(PointerStyle::Move);
1015 case SDREVENT_BEGMARK:
1016 return Pointer(PointerStyle::Arrow);
1017 case SDREVENT_MARKPOINT:
1018 case SDREVENT_MARKGLUEPOINT:
1019 return Pointer(PointerStyle::MovePoint);
1020 case SDREVENT_BEGINSOBJPOINT:
1021 case SDREVENT_BEGINSGLUEPOINT:
1022 return Pointer(PointerStyle::Cross);
1023 case SDREVENT_EXECUTEURL:
1024 return Pointer(PointerStyle::RefHand);
1025 case SDREVENT_BEGMACROOBJ:
1027 SdrObjMacroHitRec aHitRec;
1028 aHitRec.aPos=aVEvt.aLogicPos;
1029 aHitRec.aDownPos=aHitRec.aPos;
1030 aHitRec.nTol=nHitTolLog;
1031 aHitRec.pVisiLayer=&aVEvt.pPV->GetVisibleLayers();
1032 aHitRec.pPageView=aVEvt.pPV;
1033 aHitRec.pOut=const_cast<OutputDevice*>(pOut);
1034 return aVEvt.pObj->GetMacroPointer(aHitRec);
1036 default: break;
1037 } // switch
1039 switch(eHit)
1041 case SDRHIT_CELL:
1042 return Pointer(PointerStyle::Arrow);
1043 case SDRHIT_HELPLINE :
1044 return aVEvt.pPV->GetHelpLines()[aVEvt.nHlplIdx].GetPointer();
1045 case SDRHIT_GLUEPOINT:
1046 return Pointer(PointerStyle::MovePoint);
1047 case SDRHIT_TEXTEDIT :
1048 case SDRHIT_TEXTEDITOBJ:
1050 SdrTextObj* pText = dynamic_cast< SdrTextObj* >( aVEvt.pObj );
1051 if(pText && pText->HasText())
1053 OutlinerParaObject* pParaObj = pText->GetOutlinerParaObject();
1054 if(pParaObj && pParaObj->IsVertical())
1055 return Pointer(PointerStyle::TextVertical);
1057 return Pointer(PointerStyle::Text);
1059 default: break;
1062 bool bMarkHit=eHit==SDRHIT_MARKEDOBJECT;
1063 SdrHdl* pHdl=aVEvt.pHdl;
1064 // now check the pointers for dragging
1065 if (pHdl!=NULL || bMarkHit) {
1066 SdrHdlKind eHdl= pHdl!=NULL ? pHdl->GetKind() : HDL_MOVE;
1067 bool bCorner=pHdl!=NULL && pHdl->IsCornerHdl();
1068 bool bVertex=pHdl!=NULL && pHdl->IsVertexHdl();
1069 bool bMov=eHdl==HDL_MOVE;
1070 if (bMov && (eDragMode==SDRDRAG_MOVE || eDragMode==SDRDRAG_RESIZE || bMarkedHitMovesAlways)) {
1071 if (!IsMoveAllowed()) return Pointer(PointerStyle::Arrow); // because double click or drag & drop is possible
1072 return Pointer(PointerStyle::Move);
1074 switch (eDragMode) {
1075 case SDRDRAG_ROTATE: {
1076 if ((bCorner || bMov) && !IsRotateAllowed(true))
1077 return Pointer(PointerStyle::NotAllowed);
1079 // are 3D objects selected?
1080 bool b3DObjSelected = false;
1081 for (size_t a=0; !b3DObjSelected && a<GetMarkedObjectCount(); ++a) {
1082 SdrObject* pObj = GetMarkedObjectByIndex(a);
1083 if(pObj && pObj->ISA(E3dObject))
1084 b3DObjSelected = true;
1086 // If we have a 3D object, go on despite !IsShearAllowed,
1087 // because then we have a rotation instead of a shear.
1088 if (bVertex && !IsShearAllowed() && !b3DObjSelected)
1089 return Pointer(PointerStyle::NotAllowed);
1090 if (bMov)
1091 return Pointer(PointerStyle::Rotate);
1092 } break;
1093 case SDRDRAG_SHEAR: case SDRDRAG_DISTORT: {
1094 if (bCorner) {
1095 if (!IsDistortAllowed(true) && !IsDistortAllowed(false)) return Pointer(PointerStyle::NotAllowed);
1096 else return Pointer(PointerStyle::RefHand);
1098 if (bVertex && !IsShearAllowed()) return Pointer(PointerStyle::NotAllowed);
1099 if (bMov) {
1100 if (!IsMoveAllowed()) return Pointer(PointerStyle::Arrow); // because double click or drag & drop is possible
1101 return Pointer(PointerStyle::Move);
1103 } break;
1104 case SDRDRAG_MIRROR: {
1105 if (bCorner || bVertex || bMov) {
1106 SdrHdl* pH1=maHdlList.GetHdl(HDL_REF1);
1107 SdrHdl* pH2=maHdlList.GetHdl(HDL_REF2);
1108 bool b90=false;
1109 bool b45=false;
1110 Point aDif;
1111 if (pH1!=NULL && pH2!=NULL) {
1112 aDif=pH2->GetPos()-pH1->GetPos();
1113 b90=(aDif.X()==0) || aDif.Y()==0;
1114 b45=b90 || (std::abs(aDif.X())==std::abs(aDif.Y()));
1116 bool bNo=false;
1117 if (!IsMirrorAllowed(true,true)) bNo=true; // any mirroring is forbidden
1118 if (!IsMirrorAllowed(false,false) && !b45) bNo=true; // mirroring freely is forbidden
1119 if (!IsMirrorAllowed(true,false) && !b90) bNo=true; // mirroring horizontally/vertically is allowed
1120 if (bNo) return Pointer(PointerStyle::NotAllowed);
1121 if (b90) {
1122 return Pointer(PointerStyle::Mirror);
1124 return Pointer(PointerStyle::Mirror);
1126 } break;
1128 case SDRDRAG_TRANSPARENCE:
1130 if(!IsTransparenceAllowed())
1131 return Pointer(PointerStyle::NotAllowed);
1133 return Pointer(PointerStyle::RefHand);
1136 case SDRDRAG_GRADIENT:
1138 if(!IsGradientAllowed())
1139 return Pointer(PointerStyle::NotAllowed);
1141 return Pointer(PointerStyle::RefHand);
1144 case SDRDRAG_CROOK: {
1145 if (bCorner || bVertex || bMov) {
1146 if (!IsCrookAllowed(true) && !IsCrookAllowed(false)) return Pointer(PointerStyle::NotAllowed);
1147 return Pointer(PointerStyle::Crook);
1151 case SDRDRAG_CROP:
1153 return Pointer(PointerStyle::Crop);
1156 default: {
1157 if ((bCorner || bVertex) && !IsResizeAllowed(true)) return Pointer(PointerStyle::NotAllowed);
1160 if (pHdl!=NULL) return pHdl->GetPointer();
1161 if (bMov) {
1162 if (!IsMoveAllowed()) return Pointer(PointerStyle::Arrow); // because double click or drag & drop is possible
1163 return Pointer(PointerStyle::Move);
1166 if (eEditMode==SDREDITMODE_CREATE) return aAktCreatePointer;
1167 return Pointer(PointerStyle::Arrow);
1170 #define STR_NOTHING "nothing"
1171 OUString SdrView::GetStatusText()
1173 OUString aStr;
1174 OUString aName;
1176 aStr += STR_NOTHING;
1178 if (pAktCreate!=NULL)
1180 aStr=pAktCreate->getSpecialDragComment(aDragStat);
1182 if(aStr.isEmpty())
1184 aName = pAktCreate->TakeObjNameSingul();
1185 aStr = ImpGetResStr(STR_ViewCreateObj);
1188 else if (mpCurrentSdrDragMethod)
1190 if (bInsPolyPoint || IsInsertGluePoint())
1192 aStr=aInsPointUndoStr;
1194 else
1196 if (aDragStat.IsMinMoved())
1198 SAL_INFO(
1199 "svx.svdraw",
1200 "(" << this << ") " << mpCurrentSdrDragMethod);
1201 mpCurrentSdrDragMethod->TakeSdrDragComment(aStr);
1205 else if(IsMarkObj())
1207 if(AreObjectsMarked())
1209 aStr = ImpGetResStr(STR_ViewMarkMoreObjs);
1211 else
1213 aStr = ImpGetResStr(STR_ViewMarkObjs);
1216 else if(IsMarkPoints())
1218 if(HasMarkedPoints())
1220 aStr = ImpGetResStr(STR_ViewMarkMorePoints);
1222 else
1224 aStr = ImpGetResStr(STR_ViewMarkPoints);
1226 } else if (IsMarkGluePoints())
1228 if(HasMarkedGluePoints())
1230 aStr = ImpGetResStr(STR_ViewMarkMoreGluePoints);
1232 else
1234 aStr = ImpGetResStr(STR_ViewMarkGluePoints);
1237 else if (IsTextEdit() && pTextEditOutlinerView!=NULL) {
1238 aStr=ImpGetResStr(STR_ViewTextEdit); // "TextEdit - Row y, Column x";
1239 ESelection aSel(pTextEditOutlinerView->GetSelection());
1240 long nPar=aSel.nEndPara,nLin=0,nCol=aSel.nEndPos;
1241 if (aSel.nEndPara>0) {
1242 for (sal_Int32 nParaNum=0; nParaNum<aSel.nEndPara; nParaNum++) {
1243 nLin+=pTextEditOutliner->GetLineCount(nParaNum);
1246 // A little imperfection:
1247 // At the end of a line of any multi-line paragraph, we display the
1248 // position of the next line of the same paragraph, if there is one.
1249 sal_uInt16 nParaLine = 0;
1250 sal_uIntPtr nParaLineCount = pTextEditOutliner->GetLineCount(aSel.nEndPara);
1251 bool bBrk = false;
1252 while (!bBrk)
1254 sal_uInt16 nLen = pTextEditOutliner->GetLineLen(aSel.nEndPara, nParaLine);
1255 bool bLastLine = (nParaLine == nParaLineCount - 1);
1256 if (nCol>nLen || (!bLastLine && nCol == nLen))
1258 nCol -= nLen;
1259 nLin++;
1260 nParaLine++;
1262 else
1263 bBrk = true;
1265 if (nLen == 0)
1266 bBrk = true; // to be sure
1269 aStr = aStr.replaceFirst("%1", OUString::number(nPar + 1));
1270 aStr = aStr.replaceFirst("%2", OUString::number(nLin + 1));
1271 aStr = aStr.replaceFirst("%3", OUString::number(nCol + 1));
1273 #ifdef DBG_UTIL
1274 aStr += ", Level " ;
1275 aStr += OUString::number( pTextEditOutliner->GetDepth( aSel.nEndPara ) );
1276 #endif
1279 if(aStr == STR_NOTHING)
1281 if (AreObjectsMarked()) {
1282 ImpTakeDescriptionStr(STR_ViewMarked,aStr);
1283 if (IsGluePointEditMode()) {
1284 if (HasMarkedGluePoints()) {
1285 ImpTakeDescriptionStr(STR_ViewMarked,aStr,0,ImpTakeDescriptionOptions::GLUEPOINTS);
1287 } else {
1288 if (HasMarkedPoints()) {
1289 ImpTakeDescriptionStr(STR_ViewMarked,aStr,0,ImpTakeDescriptionOptions::POINTS);
1292 } else {
1293 aStr.clear();
1296 else if(!aName.isEmpty())
1298 aStr = aStr.replaceFirst("%1", aName);
1301 if(!aStr.isEmpty())
1303 // capitalize first letter
1304 aStr = aStr.replaceAt(0, 1, OUString(aStr[0]).toAsciiUpperCase());
1306 return aStr;
1309 SdrViewContext SdrView::GetContext() const
1311 if( IsGluePointEditMode() )
1312 return SDRCONTEXT_GLUEPOINTEDIT;
1314 const size_t nMarkCount = GetMarkedObjectCount();
1316 if( HasMarkablePoints() && !IsFrameHandles() )
1318 bool bPath=true;
1319 for( size_t nMarkNum = 0; nMarkNum < nMarkCount && bPath; ++nMarkNum )
1320 if (!GetMarkedObjectByIndex(nMarkNum)->ISA(SdrPathObj))
1321 bPath=false;
1323 if( bPath )
1324 return SDRCONTEXT_POINTEDIT;
1327 if( GetMarkedObjectCount() )
1329 bool bGraf = true, bMedia = true, bTable = true;
1331 for( size_t nMarkNum = 0; nMarkNum < nMarkCount && ( bGraf || bMedia ); ++nMarkNum )
1333 const SdrObject* pMarkObj = GetMarkedObjectByIndex( nMarkNum );
1334 DBG_ASSERT( pMarkObj, "SdrView::GetContext(), null pointer in mark list!" );
1336 if( !pMarkObj )
1337 continue;
1339 if( !pMarkObj->ISA( SdrGrafObj ) )
1340 bGraf = false;
1342 if( !pMarkObj->ISA( SdrMediaObj ) )
1343 bMedia = false;
1345 if( !pMarkObj->ISA( sdr::table::SdrTableObj ) )
1346 bTable = false;
1349 if( bGraf )
1350 return SDRCONTEXT_GRAPHIC;
1351 else if( bMedia )
1352 return SDRCONTEXT_MEDIA;
1353 else if( bTable )
1354 return SDRCONTEXT_TABLE;
1357 return SDRCONTEXT_STANDARD;
1360 void SdrView::MarkAll()
1362 if (IsTextEdit()) {
1363 GetTextEditOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL,EE_TEXTPOS_ALL));
1364 #ifdef DBG_UTIL
1365 if (pItemBrowser!=nullptr) pItemBrowser->SetDirty();
1366 #endif
1367 } else if (IsGluePointEditMode()) MarkAllGluePoints();
1368 else if (HasMarkablePoints()) MarkAllPoints();
1369 else MarkAllObj();
1372 void SdrView::UnmarkAll()
1374 if (IsTextEdit()) {
1375 ESelection eSel=GetTextEditOutlinerView()->GetSelection();
1376 eSel.nStartPara=eSel.nEndPara;
1377 eSel.nStartPos=eSel.nEndPos;
1378 GetTextEditOutlinerView()->SetSelection(eSel);
1379 #ifdef DBG_UTIL
1380 if (pItemBrowser!=nullptr) pItemBrowser->SetDirty();
1381 #endif
1382 } else if (HasMarkedGluePoints()) UnmarkAllGluePoints();
1383 else if (HasMarkedPoints()) UnmarkAllPoints(); // Marked, not Markable!
1384 else UnmarkAllObj();
1387 const Rectangle& SdrView::GetMarkedRect() const
1389 if (IsGluePointEditMode() && HasMarkedGluePoints()) {
1390 return GetMarkedGluePointsRect();
1392 if (HasMarkedPoints()) {
1393 return GetMarkedPointsRect();
1395 return GetMarkedObjRect();
1398 void SdrView::DeleteMarked()
1400 if (IsTextEdit())
1402 SdrObjEditView::KeyInput(KeyEvent(0,vcl::KeyCode(KeyFuncType::DELETE)),pTextEditWin);
1404 else
1406 if( mxSelectionController.is() && mxSelectionController->DeleteMarked() )
1408 // action already performed by current selection controller, do nothing
1410 else if (IsGluePointEditMode() && HasMarkedGluePoints())
1412 DeleteMarkedGluePoints();
1414 else if (GetContext()==SDRCONTEXT_POINTEDIT && HasMarkedPoints())
1416 DeleteMarkedPoints();
1418 else
1420 DeleteMarkedObj();
1425 bool SdrView::BegMark(const Point& rPnt, bool bAddMark, bool bUnmark)
1427 if (bUnmark) bAddMark=true;
1428 if (IsGluePointEditMode()) {
1429 if (!bAddMark) UnmarkAllGluePoints();
1430 return BegMarkGluePoints(rPnt,bUnmark);
1431 } else if (HasMarkablePoints()) {
1432 if (!bAddMark) UnmarkAllPoints();
1433 return BegMarkPoints(rPnt,bUnmark);
1434 } else {
1435 if (!bAddMark) UnmarkAllObj();
1436 return BegMarkObj(rPnt,bUnmark);
1440 void SdrView::ConfigurationChanged( ::utl::ConfigurationBroadcaster*p, sal_uInt32 nHint)
1442 onAccessibilityOptionsChanged();
1443 SdrCreateView::ConfigurationChanged(p, nHint);
1447 /** method is called whenever the global SvtAccessibilityOptions is changed */
1448 void SdrView::onAccessibilityOptionsChanged()
1452 void SdrView::SetMasterPagePaintCaching(bool bOn)
1454 if(mbMasterPagePaintCaching != bOn)
1456 mbMasterPagePaintCaching = bOn;
1458 // reset at all SdrPageWindows
1459 SdrPageView* pPageView = GetSdrPageView();
1461 if(pPageView)
1463 for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1465 SdrPageWindow* pPageWindow = pPageView->GetPageWindow(b);
1466 assert(pPageWindow && "SdrView::SetMasterPagePaintCaching: Corrupt SdrPageWindow list (!)");
1468 // force deletion of ObjectContact, so at re-display all VOCs
1469 // will be re-created with updated flag setting
1470 pPageWindow->ResetObjectContact();
1473 // force redraw of this view
1474 pPageView->InvalidateAllWin();
1480 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */