fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / svx / source / dialog / graphctl.cxx
blob17dcc15269cf7ba9c65e30e999af98cbf5e8ff6c
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 <svl/itempool.hxx>
21 #include <vcl/dialog.hxx>
22 #include <vcl/wrkwin.hxx>
23 #include <vcl/settings.hxx>
24 #include <vcl/builderfactory.hxx>
25 #include <unotools/syslocale.hxx>
26 #include <rtl/math.hxx>
27 #include <unotools/localedatawrapper.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <vcl/svapp.hxx>
30 #include <osl/mutex.hxx>
32 #include <svx/graphctl.hxx>
33 #include "GraphCtlAccessibleContext.hxx"
34 #include "svx/xoutbmp.hxx"
35 #include <svx/svxids.hrc>
36 #include <svx/svdpage.hxx>
37 #include "svx/sdrpaintwindow.hxx"
39 void GraphCtrlUserCall::Changed( const SdrObject& rObj, SdrUserCallType eType, const Rectangle& /*rOldBoundRect*/ )
41 switch( eType )
43 case( SDRUSERCALL_MOVEONLY ):
44 case( SDRUSERCALL_RESIZE ):
45 rWin.SdrObjChanged( rObj );
46 break;
48 case( SDRUSERCALL_INSERTED ):
49 rWin.SdrObjCreated( rObj );
50 break;
52 default:
53 break;
57 GraphCtrl::GraphCtrl( vcl::Window* pParent, WinBits nStyle ) :
58 Control ( pParent, nStyle ),
59 aMap100 ( MAP_100TH_MM ),
60 nWinStyle ( 0 ),
61 eObjKind ( OBJ_NONE ),
62 nPolyEdit ( 0 ),
63 bEditMode ( false ),
64 bSdrMode ( false ),
65 bAnim ( false ),
66 mpAccContext ( NULL ),
67 pModel ( NULL ),
68 pView ( NULL )
70 pUserCall = new GraphCtrlUserCall( *this );
71 aUpdateIdle.SetPriority( SchedulerPriority::LOWEST );
72 aUpdateIdle.SetIdleHdl( LINK( this, GraphCtrl, UpdateHdl ) );
73 aUpdateIdle.Start();
74 EnableRTL( false );
77 VCL_BUILDER_DECL_FACTORY(GraphCtrl)
79 WinBits nWinStyle = 0;
80 OString sBorder = VclBuilder::extractCustomProperty(rMap);
81 if (!sBorder.isEmpty())
82 nWinStyle |= WB_BORDER;
83 rRet = VclPtr<GraphCtrl>::Create(pParent, nWinStyle);
86 GraphCtrl::~GraphCtrl()
88 disposeOnce();
91 void GraphCtrl::dispose()
93 if( mpAccContext )
95 mpAccContext->disposing();
96 mpAccContext->release();
98 delete pView;
99 delete pModel;
100 delete pUserCall;
101 Control::dispose();
104 void GraphCtrl::SetWinStyle( WinBits nWinBits )
106 nWinStyle = nWinBits;
107 bAnim = ( nWinStyle & WB_ANIMATION ) == WB_ANIMATION;
108 bSdrMode = ( nWinStyle & WB_SDRMODE ) == WB_SDRMODE;
110 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
111 SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
112 SetMapMode( aMap100 );
114 delete pView;
115 pView = NULL;
117 delete pModel;
118 pModel = NULL;
120 if ( bSdrMode )
121 InitSdrModel();
124 void GraphCtrl::InitSdrModel()
126 SolarMutexGuard aGuard;
128 SdrPage* pPage;
130 // destroy old junk
131 delete pView;
132 delete pModel;
134 // Creating a Model
135 pModel = new SdrModel;
136 pModel->GetItemPool().FreezeIdRanges();
137 pModel->SetScaleUnit( aMap100.GetMapUnit() );
138 pModel->SetScaleFraction( Fraction( 1, 1 ) );
139 pModel->SetDefaultFontHeight( 500 );
141 pPage = new SdrPage( *pModel );
143 pPage->SetSize( aGraphSize );
144 pPage->SetBorder( 0, 0, 0, 0 );
145 pModel->InsertPage( pPage );
146 pModel->SetChanged( false );
148 // Creating a View
149 pView = new GraphCtrlView( pModel, this );
150 pView->SetWorkArea( Rectangle( Point(), aGraphSize ) );
151 pView->EnableExtendedMouseEventDispatcher( true );
152 pView->ShowSdrPage(pView->GetModel()->GetPage(0));
153 pView->SetFrameDragSingles( true );
154 pView->SetMarkedPointsSmooth( SDRPATHSMOOTH_SYMMETRIC );
155 pView->SetEditMode( true );
157 // #i72889# set neeeded flags
158 pView->SetPagePaintingAllowed(false);
159 pView->SetBufferedOutputAllowed(true);
160 pView->SetBufferedOverlayAllowed(true);
162 // Tell the accessibility object about the changes.
163 if (mpAccContext != NULL)
164 mpAccContext->setModelAndView (pModel, pView);
167 void GraphCtrl::SetGraphic( const Graphic& rGraphic, bool bNewModel )
169 // If possible we dither bitmaps for the display
170 if ( !bAnim && ( rGraphic.GetType() == GRAPHIC_BITMAP ) )
172 if ( rGraphic.IsTransparent() )
174 Bitmap aBmp( rGraphic.GetBitmap() );
176 DitherBitmap( aBmp );
177 aGraphic = Graphic( BitmapEx( aBmp, rGraphic.GetBitmapEx().GetMask() ) );
179 else
181 Bitmap aBmp( rGraphic.GetBitmap() );
182 DitherBitmap( aBmp );
183 aGraphic = aBmp;
186 else
187 aGraphic = rGraphic;
189 if ( aGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
190 aGraphSize = Application::GetDefaultDevice()->PixelToLogic( aGraphic.GetPrefSize(), aMap100 );
191 else
192 aGraphSize = OutputDevice::LogicToLogic( aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(), aMap100 );
194 if ( bSdrMode && bNewModel )
195 InitSdrModel();
197 if ( aGraphSizeLink.IsSet() )
198 aGraphSizeLink.Call( this );
200 Resize();
201 Invalidate();
204 void GraphCtrl::Resize()
206 Control::Resize();
208 if ( aGraphSize.Width() && aGraphSize.Height() )
210 MapMode aDisplayMap( aMap100 );
211 Point aNewPos;
212 Size aNewSize;
213 const Size aWinSize = PixelToLogic( GetOutputSizePixel(), aDisplayMap );
214 const long nWidth = aWinSize.Width();
215 const long nHeight = aWinSize.Height();
216 double fGrfWH = (double) aGraphSize.Width() / aGraphSize.Height();
217 double fWinWH = (double) nWidth / nHeight;
219 // Adapt Bitmap to Thumb size
220 if ( fGrfWH < fWinWH)
222 aNewSize.Width() = (long) ( (double) nHeight * fGrfWH );
223 aNewSize.Height()= nHeight;
225 else
227 aNewSize.Width() = nWidth;
228 aNewSize.Height()= (long) ( (double) nWidth / fGrfWH );
231 aNewPos.X() = ( nWidth - aNewSize.Width() ) >> 1;
232 aNewPos.Y() = ( nHeight - aNewSize.Height() ) >> 1;
234 // Implementing MapMode for Engine
235 aDisplayMap.SetScaleX( Fraction( aNewSize.Width(), aGraphSize.Width() ) );
236 aDisplayMap.SetScaleY( Fraction( aNewSize.Height(), aGraphSize.Height() ) );
238 aDisplayMap.SetOrigin( LogicToLogic( aNewPos, aMap100, aDisplayMap ) );
239 SetMapMode( aDisplayMap );
242 Invalidate();
245 void GraphCtrl::Paint( vcl::RenderContext& rRenderContext, const Rectangle& rRect)
247 // #i72889# used splitted repaint to be able to paint an own background
248 // even to the buffered view
249 const bool bGraphicValid(GRAPHIC_NONE != aGraphic.GetType());
251 if (bSdrMode)
253 SdrPaintWindow* pPaintWindow = pView->BeginCompleteRedraw(&rRenderContext);
255 if (bGraphicValid)
257 vcl::RenderContext& rTarget = pPaintWindow->GetTargetOutputDevice();
259 rTarget.SetBackground(GetBackground());
260 rTarget.Erase();
262 aGraphic.Draw(&rTarget, Point(), aGraphSize);
265 const vcl::Region aRepaintRegion(rRect);
266 pView->DoCompleteRedraw(*pPaintWindow, aRepaintRegion);
267 pView->EndCompleteRedraw(*pPaintWindow, true);
269 else
271 // #i73381# in non-SdrMode, paint to local directly
272 if(bGraphicValid)
274 aGraphic.Draw(&rRenderContext, Point(), aGraphSize);
279 void GraphCtrl::SdrObjChanged( const SdrObject& )
283 void GraphCtrl::SdrObjCreated( const SdrObject& )
287 void GraphCtrl::MarkListHasChanged()
289 if ( aMarkObjLink.IsSet() )
290 aMarkObjLink.Call( this );
293 void GraphCtrl::KeyInput( const KeyEvent& rKEvt )
295 vcl::KeyCode aCode( rKEvt.GetKeyCode() );
296 bool bProc = false;
298 Dialog* pDialog = GetParentDialog();
300 switch ( aCode.GetCode() )
302 case KEY_DELETE:
303 case KEY_BACKSPACE:
305 if ( bSdrMode )
307 pView->DeleteMarked();
308 bProc = true;
309 if (!pView->AreObjectsMarked() && pDialog)
310 pDialog->GrabFocusToFirstControl();
313 break;
315 case KEY_ESCAPE:
317 if ( bSdrMode )
319 bool bGrabFocusToFirstControl = true;
320 if ( pView->IsAction() )
322 pView->BrkAction();
323 bGrabFocusToFirstControl = false;
325 else if ( pView->AreObjectsMarked() )
327 const SdrHdlList& rHdlList = pView->GetHdlList();
328 SdrHdl* pHdl = rHdlList.GetFocusHdl();
330 if(pHdl)
332 ((SdrHdlList&)rHdlList).ResetFocusHdl();
333 bGrabFocusToFirstControl = false;
336 if (bGrabFocusToFirstControl && pDialog)
337 pDialog->GrabFocusToFirstControl();
338 bProc = true;
341 break;
343 case KEY_F11:
344 case KEY_TAB:
346 if( bSdrMode )
348 if( !aCode.IsMod1() && !aCode.IsMod2() )
350 bool bForward = !aCode.IsShift();
351 // select next object
352 if ( ! pView->MarkNextObj( bForward ))
354 // At first or last object. Cycle to the other end
355 // of the list.
356 pView->UnmarkAllObj();
357 pView->MarkNextObj (bForward);
359 bProc = true;
361 else if(aCode.IsMod1())
363 // select next handle
364 const SdrHdlList& rHdlList = pView->GetHdlList();
365 bool bForward(!aCode.IsShift());
367 ((SdrHdlList&)rHdlList).TravelFocusHdl(bForward);
369 bProc = true;
373 break;
375 case KEY_END:
378 if ( aCode.IsMod1() )
380 // mark last object
381 pView->UnmarkAllObj();
382 pView->MarkNextObj(false);
384 bProc = true;
387 break;
389 case KEY_HOME:
391 if ( aCode.IsMod1() )
393 pView->UnmarkAllObj();
394 pView->MarkNextObj(true);
396 bProc = true;
399 break;
401 case KEY_UP:
402 case KEY_DOWN:
403 case KEY_LEFT:
404 case KEY_RIGHT:
406 long nX = 0;
407 long nY = 0;
409 if (aCode.GetCode() == KEY_UP)
411 // Scroll up
412 nX = 0;
413 nY =-1;
415 else if (aCode.GetCode() == KEY_DOWN)
417 // Scroll down
418 nX = 0;
419 nY = 1;
421 else if (aCode.GetCode() == KEY_LEFT)
423 // Scroll left
424 nX =-1;
425 nY = 0;
427 else if (aCode.GetCode() == KEY_RIGHT)
429 // Scroll right
430 nX = 1;
431 nY = 0;
434 if (pView->AreObjectsMarked() && !aCode.IsMod1() )
436 if(aCode.IsMod2())
438 // move in 1 pixel distance
439 Size aLogicSizeOnePixel = PixelToLogic(Size(1,1));
440 nX *= aLogicSizeOnePixel.Width();
441 nY *= aLogicSizeOnePixel.Height();
443 else
445 // old, fixed move distance
446 nX *= 100;
447 nY *= 100;
450 // II
451 const SdrHdlList& rHdlList = pView->GetHdlList();
452 SdrHdl* pHdl = rHdlList.GetFocusHdl();
454 if(0L == pHdl)
456 // restrict movement to WorkArea
457 const Rectangle& rWorkArea = pView->GetWorkArea();
459 if(!rWorkArea.IsEmpty())
461 Rectangle aMarkRect(pView->GetMarkedObjRect());
462 aMarkRect.Move(nX, nY);
464 if(!aMarkRect.IsInside(rWorkArea))
466 if(aMarkRect.Left() < rWorkArea.Left())
468 nX += rWorkArea.Left() - aMarkRect.Left();
471 if(aMarkRect.Right() > rWorkArea.Right())
473 nX -= aMarkRect.Right() - rWorkArea.Right();
476 if(aMarkRect.Top() < rWorkArea.Top())
478 nY += rWorkArea.Top() - aMarkRect.Top();
481 if(aMarkRect.Bottom() > rWorkArea.Bottom())
483 nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
488 // no handle selected
489 if(0 != nX || 0 != nY)
491 pView->MoveAllMarked(Size(nX, nY));
494 else
496 // move handle with index nHandleIndex
497 if(pHdl && (nX || nY))
499 // now move the Handle (nX, nY)
500 Point aStartPoint(pHdl->GetPos());
501 Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
502 const SdrDragStat& rDragStat = pView->GetDragStat();
504 // start dragging
505 pView->BegDragObj(aStartPoint, 0, pHdl, 0);
507 if(pView->IsDragObj())
509 bool bWasNoSnap = rDragStat.IsNoSnap();
510 bool bWasSnapEnabled = pView->IsSnapEnabled();
512 // switch snapping off
513 if(!bWasNoSnap)
514 ((SdrDragStat&)rDragStat).SetNoSnap(true);
515 if(bWasSnapEnabled)
516 pView->SetSnapEnabled(false);
518 pView->MovAction(aEndPoint);
519 pView->EndDragObj();
521 // restore snap
522 if(!bWasNoSnap)
523 ((SdrDragStat&)rDragStat).SetNoSnap(bWasNoSnap);
524 if(bWasSnapEnabled)
525 pView->SetSnapEnabled(bWasSnapEnabled);
530 bProc = true;
533 break;
535 case KEY_SPACE:
537 const SdrHdlList& rHdlList = pView->GetHdlList();
538 SdrHdl* pHdl = rHdlList.GetFocusHdl();
540 if(pHdl)
542 if(pHdl->GetKind() == HDL_POLY)
544 // rescue ID of point with focus
545 sal_uInt32 nPol(pHdl->GetPolyNum());
546 sal_uInt32 nPnt(pHdl->GetPointNum());
548 if(pView->IsPointMarked(*pHdl))
550 if(rKEvt.GetKeyCode().IsShift())
552 pView->UnmarkPoint(*pHdl);
555 else
557 if(!rKEvt.GetKeyCode().IsShift())
559 pView->UnmarkAllPoints();
562 pView->MarkPoint(*pHdl);
565 if(0L == rHdlList.GetFocusHdl())
567 // restore point with focus
568 SdrHdl* pNewOne = 0L;
570 for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
572 SdrHdl* pAct = rHdlList.GetHdl(a);
574 if(pAct
575 && pAct->GetKind() == HDL_POLY
576 && pAct->GetPolyNum() == nPol
577 && pAct->GetPointNum() == nPnt)
579 pNewOne = pAct;
583 if(pNewOne)
585 ((SdrHdlList&)rHdlList).SetFocusHdl(pNewOne);
589 bProc = true;
593 break;
595 default:
596 break;
599 if ( !bProc )
600 Control::KeyInput( rKEvt );
601 else
602 ReleaseMouse();
605 void GraphCtrl::MouseButtonDown( const MouseEvent& rMEvt )
607 if ( bSdrMode && ( rMEvt.GetClicks() < 2 ) )
609 const Point aLogPt( PixelToLogic( rMEvt.GetPosPixel() ) );
611 if ( !Rectangle( Point(), aGraphSize ).IsInside( aLogPt ) && !pView->IsEditMode() )
612 Control::MouseButtonDown( rMEvt );
613 else
615 // Get Focus for key inputs
616 GrabFocus();
618 if ( nPolyEdit )
620 SdrViewEvent aVEvt;
621 SdrHitKind eHit = pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
623 if ( nPolyEdit == SID_BEZIER_INSERT && eHit == SDRHIT_MARKEDOBJECT )
624 pView->BegInsObjPoint( aLogPt, rMEvt.IsMod1());
625 else
626 pView->MouseButtonDown( rMEvt, this );
628 else
629 pView->MouseButtonDown( rMEvt, this );
632 SdrObject* pCreateObj = pView->GetCreateObj();
634 // We want to realize the insert
635 if ( pCreateObj && !pCreateObj->GetUserCall() )
636 pCreateObj->SetUserCall( pUserCall );
638 SetPointer( pView->GetPreferredPointer( aLogPt, this ) );
640 else
641 Control::MouseButtonDown( rMEvt );
644 void GraphCtrl::MouseMove(const MouseEvent& rMEvt)
646 const Point aLogPos( PixelToLogic( rMEvt.GetPosPixel() ) );
648 if ( bSdrMode )
650 pView->MouseMove( rMEvt, this );
652 if( ( SID_BEZIER_INSERT == nPolyEdit ) &&
653 !pView->PickHandle( aLogPos ) &&
654 !pView->IsInsObjPoint() )
656 SetPointer( PointerStyle::Cross );
658 else
659 SetPointer( pView->GetPreferredPointer( aLogPos, this ) );
661 else
662 Control::MouseButtonUp( rMEvt );
664 if ( aMousePosLink.IsSet() )
666 if ( Rectangle( Point(), aGraphSize ).IsInside( aLogPos ) )
667 aMousePos = aLogPos;
668 else
669 aMousePos = Point();
671 aMousePosLink.Call( this );
675 void GraphCtrl::MouseButtonUp(const MouseEvent& rMEvt)
677 if ( bSdrMode )
679 if ( pView->IsInsObjPoint() )
680 pView->EndInsObjPoint( SDRCREATE_FORCEEND );
681 else
682 pView->MouseButtonUp( rMEvt, this );
684 ReleaseMouse();
685 SetPointer( pView->GetPreferredPointer( PixelToLogic( rMEvt.GetPosPixel() ), this ) );
687 else
688 Control::MouseButtonUp( rMEvt );
691 SdrObject* GraphCtrl::GetSelectedSdrObject() const
693 SdrObject* pSdrObj = NULL;
695 if ( bSdrMode )
697 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
699 if ( rMarkList.GetMarkCount() == 1 )
700 pSdrObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
703 return pSdrObj;
706 void GraphCtrl::SetEditMode( const bool _bEditMode )
708 if ( bSdrMode )
710 bEditMode = _bEditMode;
711 pView->SetEditMode( bEditMode );
712 eObjKind = OBJ_NONE;
713 pView->SetCurrentObj( sal::static_int_cast< sal_uInt16 >( eObjKind ) );
715 else
716 bEditMode = false;
719 void GraphCtrl::SetPolyEditMode( const sal_uInt16 _nPolyEdit )
721 if ( bSdrMode && ( _nPolyEdit != nPolyEdit ) )
723 nPolyEdit = _nPolyEdit;
724 pView->SetFrameDragSingles( nPolyEdit == 0 );
726 else
727 nPolyEdit = 0;
730 void GraphCtrl::SetObjKind( const SdrObjKind _eObjKind )
732 if ( bSdrMode )
734 bEditMode = false;
735 pView->SetEditMode( bEditMode );
736 eObjKind = _eObjKind;
737 pView->SetCurrentObj( sal::static_int_cast< sal_uInt16 >( eObjKind ) );
739 else
740 eObjKind = OBJ_NONE;
743 IMPL_LINK_TYPED( GraphCtrl, UpdateHdl, Idle*, pTimer, void )
745 if ( aUpdateLink.IsSet() )
746 aUpdateLink.Call( this );
748 pTimer->Start();
752 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > GraphCtrl::CreateAccessible()
754 if( mpAccContext == NULL )
756 vcl::Window* pParent = GetParent();
758 DBG_ASSERT( pParent, "-GraphCtrl::CreateAccessible(): No Parent!" );
760 if( pParent )
762 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAccParent( pParent->GetAccessible() );
764 // Disable accessibility if no model/view data available
765 if( pView &&
766 pModel &&
767 xAccParent.is() )
769 mpAccContext = new SvxGraphCtrlAccessibleContext( xAccParent, *this );
770 mpAccContext->acquire();
775 return mpAccContext;
778 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */