1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/editeng.hxx> // EditEngine::IsSimpleCharInput
21 #include <editeng/outlobj.hxx>
22 #include <svx/svdobj.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <svx/svdouno.hxx>
25 #include <svx/svdocapt.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svditer.hxx>
28 #include <svx/svdundo.hxx>
29 #include <sfx2/dispatch.hxx>
30 #include <sfx2/viewfrm.hxx>
35 #include "tabvwsh.hxx"
36 #include "drwlayer.hxx"
37 #include "scresid.hxx"
38 #include "userdat.hxx"
41 #include "globstr.hrc"
42 #include "drawview.hxx"
44 /*************************************************************************
46 |* Basisklasse fuer alle Drawmodul-spezifischen Funktionen
48 \************************************************************************/
50 FuDraw::FuDraw(ScTabViewShell
* pViewSh
, Window
* pWin
, ScDrawView
* pViewP
,
51 SdrModel
* pDoc
, SfxRequest
& rReq
) :
52 FuPoor (pViewSh
, pWin
, pViewP
, pDoc
, rReq
),
53 aNewPointer ( POINTER_ARROW
),
54 aOldPointer ( POINTER_ARROW
)
58 /*************************************************************************
62 \************************************************************************/
68 /*************************************************************************
70 |* Modifier-Tasten auswerten
72 \************************************************************************/
74 void FuDraw::DoModifiers(const MouseEvent
& rMEvt
)
76 // Shift = Ortho und AngleSnap
77 // Control = Snap (Toggle)
80 sal_Bool bShift
= rMEvt
.IsShift();
81 sal_Bool bAlt
= rMEvt
.IsMod2();
84 sal_Bool bAngleSnap
= bShift
;
85 sal_Bool bCenter
= bAlt
;
88 if(doConstructOrthogonal())
93 if (pView
->IsOrtho() != bOrtho
)
94 pView
->SetOrtho(bOrtho
);
95 if (pView
->IsAngleSnapEnabled() != bAngleSnap
)
96 pView
->SetAngleSnapEnabled(bAngleSnap
);
98 if (pView
->IsCreate1stPointAsCenter() != bCenter
)
99 pView
->SetCreate1stPointAsCenter(bCenter
);
100 if (pView
->IsResizeAtCenter() != bCenter
)
101 pView
->SetResizeAtCenter(bCenter
);
105 void FuDraw::ResetModifiers()
107 ScViewData
* pViewData
= pViewShell
->GetViewData();
108 const ScViewOptions
& rOpt
= pViewData
->GetOptions();
109 const ScGridOptions
& rGrid
= rOpt
.GetGridOptions();
110 sal_Bool bGridOpt
= rGrid
.GetUseGridSnap();
112 if (pView
->IsOrtho())
113 pView
->SetOrtho(false);
114 if (pView
->IsAngleSnapEnabled())
115 pView
->SetAngleSnapEnabled(false);
117 if (pView
->IsGridSnap() != bGridOpt
)
118 pView
->SetGridSnap(bGridOpt
);
119 if (pView
->IsSnapEnabled() != bGridOpt
)
120 pView
->SetSnapEnabled(bGridOpt
);
122 if (pView
->IsCreate1stPointAsCenter())
123 pView
->SetCreate1stPointAsCenter(false);
124 if (pView
->IsResizeAtCenter())
125 pView
->SetResizeAtCenter(false);
128 /*************************************************************************
130 |* MouseButtonDown-event
132 \************************************************************************/
134 sal_Bool
FuDraw::MouseButtonDown(const MouseEvent
& rMEvt
)
136 // remember button state for creation of own MouseEvents
137 SetMouseButtonCode(rMEvt
.GetButtons());
139 DoModifiers( rMEvt
);
143 /*************************************************************************
147 \************************************************************************/
149 sal_Bool
FuDraw::MouseMove(const MouseEvent
& rMEvt
)
151 // evaluate modifiers only if in a drawing layer action
152 // (don't interfere with keyboard shortcut handling)
153 if (pView
->IsAction())
154 DoModifiers( rMEvt
);
159 /*************************************************************************
161 |* MouseButtonUp-event
163 \************************************************************************/
165 sal_Bool
FuDraw::MouseButtonUp(const MouseEvent
& rMEvt
)
167 // remember button state for creation of own MouseEvents
168 SetMouseButtonCode(rMEvt
.GetButtons());
174 /*************************************************************************
176 |* Tastaturereignisse bearbeiten
178 |* Wird ein KeyEvent bearbeitet, so ist der Return-Wert sal_True, andernfalls
181 \************************************************************************/
183 static sal_Bool
lcl_KeyEditMode( SdrObject
* pObj
, ScTabViewShell
* pViewShell
, const KeyEvent
* pInitialKey
)
185 sal_Bool bReturn
= false;
186 if ( pObj
&& pObj
->ISA(SdrTextObj
) && !pObj
->ISA(SdrUnoObj
) )
188 // start text edit - like FuSelection::MouseButtonUp,
189 // but with bCursorToEnd instead of mouse position
191 OutlinerParaObject
* pOPO
= pObj
->GetOutlinerParaObject();
192 sal_Bool bVertical
= ( pOPO
&& pOPO
->IsVertical() );
193 sal_uInt16 nTextSlotId
= bVertical
? SID_DRAW_TEXT_VERTICAL
: SID_DRAW_TEXT
;
195 // don't switch shells if text shell is already active
196 FuPoor
* pPoor
= pViewShell
->GetViewData()->GetView()->GetDrawFuncPtr();
197 if ( !pPoor
|| pPoor
->GetSlotID() != nTextSlotId
)
199 pViewShell
->GetViewData()->GetDispatcher().
200 Execute(nTextSlotId
, SFX_CALLMODE_SYNCHRON
| SFX_CALLMODE_RECORD
);
203 // get the resulting FuText and set in edit mode
204 pPoor
= pViewShell
->GetViewData()->GetView()->GetDrawFuncPtr();
205 if ( pPoor
&& pPoor
->GetSlotID() == nTextSlotId
) // no RTTI
207 FuText
* pText
= (FuText
*)pPoor
;
208 pText
->SetInEditMode( pObj
, NULL
, sal_True
, pInitialKey
);
209 //! set cursor to end of text
216 sal_Bool
FuDraw::KeyInput(const KeyEvent
& rKEvt
)
218 sal_Bool bReturn
= false;
219 ScViewData
& rViewData
= *pViewShell
->GetViewData();
221 switch ( rKEvt
.GetKeyCode().GetCode() )
224 if ( pViewShell
->IsDrawTextShell() || aSfxRequest
.GetSlot() == SID_DRAW_NOTEEDIT
)
226 // in normale Draw-Shell, wenn Objekt selektiert, sonst Zeichnen aus
227 rViewData
.GetDispatcher().Execute(aSfxRequest
.GetSlot(), SFX_CALLMODE_SLOT
| SFX_CALLMODE_RECORD
);
230 else if ( pViewShell
->IsDrawSelMode() )
233 rViewData
.GetDispatcher().Execute(SID_OBJECT_SELECT
, SFX_CALLMODE_SLOT
| SFX_CALLMODE_RECORD
);
236 else if ( pView
->AreObjectsMarked() )
239 SdrHdlList
& rHdlList
= const_cast< SdrHdlList
& >( pView
->GetHdlList() );
240 if( rHdlList
.GetFocusHdl() )
241 rHdlList
.ResetFocusHdl();
245 // Beim Bezier-Editieren ist jetzt wieder das Objekt selektiert
246 if (!pView
->AreObjectsMarked())
247 pViewShell
->SetDrawShell( false );
253 case KEY_DELETE
: //! ueber Accelerator
254 pView
->DeleteMarked();
260 if( rKEvt
.GetKeyCode().GetModifier() == 0 )
262 // activate OLE object on RETURN for selected object
263 // put selected text object in edit mode
264 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
265 if( !pView
->IsTextEdit() && 1 == rMarkList
.GetMarkCount() )
267 sal_Bool bOle
= pViewShell
->GetViewFrame()->GetFrame().IsInPlace();
268 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
269 if( pObj
&& pObj
->ISA( SdrOle2Obj
) && !bOle
)
271 pViewShell
->ActivateObject( static_cast< SdrOle2Obj
* >( pObj
), 0 );
276 else if ( lcl_KeyEditMode( pObj
, pViewShell
, NULL
) ) // start text edit for suitable object
285 if( rKEvt
.GetKeyCode().GetModifier() == 0 )
287 // put selected text object in edit mode
288 // (this is not SID_SETINPUTMODE, but F2 hardcoded, like in Writer)
289 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
290 if( !pView
->IsTextEdit() && 1 == rMarkList
.GetMarkCount() )
292 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
293 if ( lcl_KeyEditMode( pObj
, pViewShell
, NULL
) ) // start text edit for suitable object
303 // in calc do NOT start draw object selection using TAB/SHIFT-TAB when
304 // there is not yet a object selected
305 if(pView
->AreObjectsMarked())
307 KeyCode aCode
= rKEvt
.GetKeyCode();
309 if ( !aCode
.IsMod1() && !aCode
.IsMod2() )
311 // changeover to the next object
312 if(!pView
->MarkNextObj( !aCode
.IsShift() ))
314 // No next object: go over open end and
315 // get first from the other side
316 pView
->UnmarkAllObj();
317 pView
->MarkNextObj(!aCode
.IsShift());
321 if(pView
->AreObjectsMarked())
322 pView
->MakeVisible(pView
->GetAllMarkedRect(), *pWindow
);
327 // handle Mod1 and Mod2 to get travelling running on different systems
328 if(rKEvt
.GetKeyCode().IsMod1() || rKEvt
.GetKeyCode().IsMod2())
330 // II do something with a selected handle?
331 const SdrHdlList
& rHdlList
= pView
->GetHdlList();
332 sal_Bool
bForward(!rKEvt
.GetKeyCode().IsShift());
334 ((SdrHdlList
&)rHdlList
).TravelFocusHdl(bForward
);
336 // guarantee visibility of focused handle
337 SdrHdl
* pHdl
= rHdlList
.GetFocusHdl();
341 Point
aHdlPosition(pHdl
->GetPos());
342 Rectangle
aVisRect(aHdlPosition
- Point(100, 100), Size(200, 200));
343 pView
->MakeVisible(aVisRect
, *pWindow
);
356 // in calc do NOT select the last draw object when
357 // there is not yet a object selected
358 if(pView
->AreObjectsMarked())
360 KeyCode aCode
= rKEvt
.GetKeyCode();
362 if ( aCode
.IsMod1() )
365 pView
->UnmarkAllObj();
366 pView
->MarkNextObj(false);
369 if(pView
->AreObjectsMarked())
370 pView
->MakeVisible(pView
->GetAllMarkedRect(), *pWindow
);
381 // in calc do NOT select the first draw object when
382 // there is not yet a object selected
383 if(pView
->AreObjectsMarked())
385 KeyCode aCode
= rKEvt
.GetKeyCode();
387 if ( aCode
.IsMod1() )
390 pView
->UnmarkAllObj();
391 pView
->MarkNextObj(sal_True
);
394 if(pView
->AreObjectsMarked())
395 pView
->MakeVisible(pView
->GetAllMarkedRect(), *pWindow
);
409 // in calc do cursor travelling of draw objects only when
410 // there is a object selected yet
411 if(pView
->AreObjectsMarked())
414 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
415 if(rMarkList
.GetMarkCount() == 1)
417 // disable cursor travelling on note objects as the tail connector position
419 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
420 if( ScDrawLayer::IsNoteCaption( pObj
) )
426 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
434 else if (nCode
== KEY_DOWN
)
440 else if (nCode
== KEY_LEFT
)
446 else if (nCode
== KEY_RIGHT
)
448 // Scroll nach rechts
453 sal_Bool bReadOnly
= rViewData
.GetDocShell()->IsReadOnly();
455 if(!rKEvt
.GetKeyCode().IsMod1() && !bReadOnly
)
457 if(rKEvt
.GetKeyCode().IsMod2())
459 // move in 1 pixel distance
460 Size aLogicSizeOnePixel
= (pWindow
) ? pWindow
->PixelToLogic(Size(1,1)) : Size(100, 100);
461 nX
*= aLogicSizeOnePixel
.Width();
462 nY
*= aLogicSizeOnePixel
.Height();
466 // old, fixed move distance
471 // is there a movement to do?
472 if(0 != nX
|| 0 != nY
)
475 const SdrHdlList
& rHdlList
= pView
->GetHdlList();
476 SdrHdl
* pHdl
= rHdlList
.GetFocusHdl();
480 // only take action when move is allowed
481 if(pView
->IsMoveAllowed())
483 // restrict movement to WorkArea
484 const Rectangle
& rWorkArea
= pView
->GetWorkArea();
486 if(!rWorkArea
.IsEmpty())
488 Rectangle
aMarkRect(pView
->GetMarkedObjRect());
489 aMarkRect
.Move(nX
, nY
);
491 if(!aMarkRect
.IsInside(rWorkArea
))
493 if(aMarkRect
.Left() < rWorkArea
.Left())
495 nX
+= rWorkArea
.Left() - aMarkRect
.Left();
498 if(aMarkRect
.Right() > rWorkArea
.Right())
500 nX
-= aMarkRect
.Right() - rWorkArea
.Right();
503 if(aMarkRect
.Top() < rWorkArea
.Top())
505 nY
+= rWorkArea
.Top() - aMarkRect
.Top();
508 if(aMarkRect
.Bottom() > rWorkArea
.Bottom())
510 nY
-= aMarkRect
.Bottom() - rWorkArea
.Bottom();
515 // now move the selected draw objects
516 pView
->MoveAllMarked(Size(nX
, nY
));
519 pView
->MakeVisible(pView
->GetAllMarkedRect(), *pWindow
);
526 // move handle with index nHandleIndex
527 if(pHdl
&& (nX
|| nY
))
529 // now move the Handle (nX, nY)
530 Point
aStartPoint(pHdl
->GetPos());
531 Point
aEndPoint(pHdl
->GetPos() + Point(nX
, nY
));
532 const SdrDragStat
& rDragStat
= pView
->GetDragStat();
535 pView
->BegDragObj(aStartPoint
, 0, pHdl
, 0);
537 if(pView
->IsDragObj())
539 bool bWasNoSnap
= rDragStat
.IsNoSnap();
540 sal_Bool bWasSnapEnabled
= pView
->IsSnapEnabled();
542 // switch snapping off
544 ((SdrDragStat
&)rDragStat
).SetNoSnap(sal_True
);
546 pView
->SetSnapEnabled(false);
548 pView
->MovAction(aEndPoint
);
553 ((SdrDragStat
&)rDragStat
).SetNoSnap(bWasNoSnap
);
555 pView
->SetSnapEnabled(bWasSnapEnabled
);
558 // make moved handle visible
559 Rectangle
aVisRect(aEndPoint
- Point(100, 100), Size(200, 200));
560 pView
->MakeVisible(aVisRect
, *pWindow
);
574 // in calc do only something when draw objects are selected
575 if(pView
->AreObjectsMarked())
577 const SdrHdlList
& rHdlList
= pView
->GetHdlList();
578 SdrHdl
* pHdl
= rHdlList
.GetFocusHdl();
582 if(pHdl
->GetKind() == HDL_POLY
)
584 // rescue ID of point with focus
585 sal_uInt32
nPol(pHdl
->GetPolyNum());
586 sal_uInt32
nPnt(pHdl
->GetPointNum());
588 if(pView
->IsPointMarked(*pHdl
))
590 if(rKEvt
.GetKeyCode().IsShift())
592 pView
->UnmarkPoint(*pHdl
);
597 if(!rKEvt
.GetKeyCode().IsShift())
599 pView
->UnmarkAllPoints();
602 pView
->MarkPoint(*pHdl
);
605 if(0L == rHdlList
.GetFocusHdl())
607 // restore point with focus
608 SdrHdl
* pNewOne
= 0L;
610 for(sal_uInt32
a(0); !pNewOne
&& a
< rHdlList
.GetHdlCount(); a
++)
612 SdrHdl
* pAct
= rHdlList
.GetHdl(a
);
615 && pAct
->GetKind() == HDL_POLY
616 && pAct
->GetPolyNum() == nPol
617 && pAct
->GetPointNum() == nPnt
)
625 ((SdrHdlList
&)rHdlList
).SetFocusHdl(pNewOne
);
639 bReturn
= FuPoor::KeyInput(rKEvt
);
644 // allow direct typing into a selected text object
646 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
647 if( !pView
->IsTextEdit() && 1 == rMarkList
.GetMarkCount() && EditEngine::IsSimpleCharInput(rKEvt
) )
649 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
651 // start text edit for suitable object, pass key event to OutlinerView
652 if ( lcl_KeyEditMode( pObj
, pViewShell
, &rKEvt
) )
661 void FuDraw::SelectionHasChanged()
663 const SdrHdlList
& rHdlList
= pView
->GetHdlList();
664 ((SdrHdlList
&)rHdlList
).ResetFocusHdl();
667 /*************************************************************************
669 |* Function aktivieren
671 \************************************************************************/
673 void FuDraw::Activate()
678 /*************************************************************************
680 |* Function deaktivieren
682 \************************************************************************/
684 void FuDraw::Deactivate()
686 FuPoor::Deactivate();
689 /*************************************************************************
691 |* Maus-Pointer umschalten
693 \************************************************************************/
695 static sal_Bool
lcl_UrlHit( SdrView
* pView
, const Point
& rPosPixel
, Window
* pWindow
)
698 MouseEvent
aMEvt( rPosPixel
, 1, 0, MOUSE_LEFT
);
699 SdrHitKind eHit
= pView
->PickAnything( aMEvt
, SDRMOUSEBUTTONDOWN
, aVEvt
);
701 if ( eHit
!= SDRHIT_NONE
&& aVEvt
.pObj
!= NULL
)
703 if ( ScDrawLayer::GetIMapInfo( aVEvt
.pObj
) && ScDrawLayer::GetHitIMapObject(
704 aVEvt
.pObj
, pWindow
->PixelToLogic(rPosPixel
), *pWindow
) )
707 if ( aVEvt
.eEvent
== SDREVENT_EXECUTEURL
)
714 void FuDraw::ForcePointer(const MouseEvent
* pMEvt
)
716 if ( !pView
->IsAction() )
718 Point aPosPixel
= pWindow
->GetPointerPosPixel();
719 sal_Bool bAlt
= pMEvt
&& pMEvt
->IsMod2();
720 Point aPnt
= pWindow
->PixelToLogic( aPosPixel
);
721 SdrHdl
* pHdl
= pView
->PickHandle(aPnt
);
725 ScMacroInfo
* pInfo
= 0;
726 if ( pView
->PickObj(aPnt
, pView
->getHitTolLog(), pObj
, pPV
, SDRSEARCH_ALSOONMASTER
) )
728 if ( pObj
->IsGroupObject() )
731 if ( pView
->PickObj(aMDPos
, pView
->getHitTolLog(), pHit
, pPV
, SDRSEARCH_DEEP
) )
734 pInfo
= ScDrawLayer::GetMacroInfo( pObj
);
737 if ( pView
->IsTextEdit() )
739 pViewShell
->SetActivePointer(Pointer(POINTER_TEXT
)); // kann nicht sein ?
743 pViewShell
->SetActivePointer(
744 pView
->GetPreferedPointer( aPnt
, pWindow
) );
746 else if ( pView
->IsMarkedHit(aPnt
) )
748 pViewShell
->SetActivePointer( Pointer(POINTER_MOVE
) );
750 else if ( !bAlt
&& ( !pMEvt
|| !pMEvt
->GetButtons() )
751 && lcl_UrlHit( pView
, aPosPixel
, pWindow
) )
753 // kann mit ALT unterdrueckt werden
754 pWindow
->SetPointer( Pointer( POINTER_REFHAND
) ); // Text-URL / ImageMap
756 else if ( !bAlt
&& pView
->PickObj(aPnt
, pView
->getHitTolLog(), pObj
, pPV
, SDRSEARCH_PICKMACRO
) )
758 // kann mit ALT unterdrueckt werden
759 SdrObjMacroHitRec aHitRec
; //! muss da noch irgendwas gesetzt werden ????
760 pViewShell
->SetActivePointer( pObj
->GetMacroPointer(aHitRec
) );
762 else if ( !bAlt
&& pInfo
&& (!pInfo
->GetMacro().isEmpty() || !pInfo
->GetHlink().isEmpty()) )
763 pWindow
->SetPointer( Pointer( POINTER_REFHAND
) );
764 else if ( IsDetectiveHit( aPnt
) )
765 pViewShell
->SetActivePointer( Pointer( POINTER_DETECTIVE
) );
767 pViewShell
->SetActivePointer( aNewPointer
); //! in Gridwin?
771 sal_Bool
FuDraw::IsEditingANote() const
773 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
774 sal_Int32 backval
=rMarkList
.GetMarkCount();
775 for (sal_Int32 nlv1
=0;nlv1
<backval
;nlv1
++)
777 SdrObject
* pObj
= rMarkList
.GetMark( nlv1
)->GetMarkedSdrObj();
778 if ( ScDrawLayer::IsNoteCaption( pObj
) )
786 sal_Bool
FuDraw::IsSizingOrMovingNote( const MouseEvent
& rMEvt
) const
788 sal_Bool bIsSizingOrMoving
= false;
789 if ( rMEvt
.IsLeft() )
791 const SdrMarkList
& rNoteMarkList
= pView
->GetMarkedObjectList();
792 if(rNoteMarkList
.GetMarkCount() == 1)
794 SdrObject
* pObj
= rNoteMarkList
.GetMark( 0 )->GetMarkedSdrObj();
795 if ( ScDrawLayer::IsNoteCaption( pObj
) )
797 Point aMPos
= pWindow
->PixelToLogic( rMEvt
.GetPosPixel() );
799 pView
->PickHandle( aMPos
) || // handles to resize the note
800 pView
->IsTextEditFrameHit( aMPos
); // frame for moving the note
804 return bIsSizingOrMoving
;
807 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */