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 <com/sun/star/accessibility/AccessibleRole.hpp>
22 #include <osl/diagnose.h>
23 #include <vcl/event.hxx>
24 #include <vcl/settings.hxx>
25 #include <vcl/ptrstyle.hxx>
28 #include "hatchwindow.hxx"
30 /************************************************************************/
31 /*************************************************************************
32 |* SvResizeHelper::SvResizeHelper()
35 *************************************************************************/
36 SvResizeHelper::SvResizeHelper()
42 /*************************************************************************
43 |* SvResizeHelper::FillHandleRects()
45 |* Description: the eight handles to magnify
46 *************************************************************************/
47 std::array
<tools::Rectangle
,8> SvResizeHelper::FillHandleRectsPixel() const
49 std::array
<tools::Rectangle
,8> aRects
;
51 // only because of EMPTY_RECT
52 Point aBottomRight
= aOuter
.BottomRight();
55 aRects
[ 0 ] = tools::Rectangle( aOuter
.TopLeft(), aBorder
);
57 aRects
[ 1 ] = tools::Rectangle( Point( aOuter
.Center().X() - aBorder
.Width() / 2,
61 aRects
[ 2 ] = tools::Rectangle( Point( aBottomRight
.X() - aBorder
.Width() +1,
65 aRects
[ 3 ] = tools::Rectangle( Point( aBottomRight
.X() - aBorder
.Width() +1,
66 aOuter
.Center().Y() - aBorder
.Height() / 2 ),
69 aRects
[ 4 ] = tools::Rectangle( Point( aBottomRight
.X() - aBorder
.Width() +1,
70 aBottomRight
.Y() - aBorder
.Height() +1 ),
73 aRects
[ 5 ] = tools::Rectangle( Point( aOuter
.Center().X() - aBorder
.Width() / 2,
74 aBottomRight
.Y() - aBorder
.Height() +1),
77 aRects
[ 6 ] = tools::Rectangle( Point( aOuter
.Left(),
78 aBottomRight
.Y() - aBorder
.Height() +1),
81 aRects
[ 7 ] = tools::Rectangle( Point( aOuter
.Left(),
82 aOuter
.Center().Y() - aBorder
.Height() / 2 ),
87 /*************************************************************************
88 |* SvResizeHelper::FillMoveRectsPixel()
90 |* Description: the four edges are calculated
91 *************************************************************************/
92 std::array
<tools::Rectangle
,4> SvResizeHelper::FillMoveRectsPixel() const
94 std::array
<tools::Rectangle
,4> aRects
;
98 aRects
[ 0 ].SetBottom( aRects
[ 0 ].Top() + aBorder
.Height() -1 );
100 aRects
[ 1 ] = aOuter
;
101 if (!aOuter
.IsWidthEmpty())
102 aRects
[ 1 ].SetLeft( aRects
[ 1 ].Right() - aBorder
.Width() -1 );
104 aRects
[ 2 ] = aOuter
;
105 if (!aOuter
.IsHeightEmpty())
106 aRects
[ 2 ].SetTop( aRects
[ 2 ].Bottom() - aBorder
.Height() -1 );
108 aRects
[ 3 ] = aOuter
;
109 aRects
[ 3 ].SetRight( aRects
[ 3 ].Left() + aBorder
.Width() -1 );
114 /*************************************************************************
115 |* SvResizeHelper::Draw()
118 *************************************************************************/
119 void SvResizeHelper::Draw(vcl::RenderContext
& rRenderContext
)
121 rRenderContext
.Push();
122 rRenderContext
.SetMapMode( MapMode() );
124 rRenderContext
.SetFillColor( COL_LIGHTGRAY
);
125 rRenderContext
.SetLineColor();
127 std::array
<tools::Rectangle
,4> aMoveRects
= FillMoveRectsPixel();
129 for (i
= 0; i
< 4; i
++)
130 rRenderContext
.DrawRect(aMoveRects
[i
]);
132 rRenderContext
.SetFillColor(Color()); // black
133 std::array
<tools::Rectangle
,8> aRects
= FillHandleRectsPixel();
134 for (i
= 0; i
< 8; i
++)
135 rRenderContext
.DrawRect( aRects
[ i
] );
136 rRenderContext
.Pop();
139 /*************************************************************************
140 |* SvResizeHelper::InvalidateBorder()
143 *************************************************************************/
144 void SvResizeHelper::InvalidateBorder( vcl::Window
* pWin
)
146 std::array
<tools::Rectangle
,4> aMoveRects
= FillMoveRectsPixel();
147 for(const auto & rMoveRect
: aMoveRects
)
148 pWin
->Invalidate( rMoveRect
);
151 /*************************************************************************
152 |* SvResizeHelper::SelectBegin()
155 *************************************************************************/
156 bool SvResizeHelper::SelectBegin( vcl::Window
* pWin
, const Point
& rPos
)
160 nGrab
= SelectMove( pWin
, rPos
);
163 aSelPos
= rPos
; // store start position
164 pWin
->CaptureMouse();
171 /*************************************************************************
172 |* SvResizeHelper::SelectMove()
175 *************************************************************************/
176 short SvResizeHelper::SelectMove( vcl::Window
* pWin
, const Point
& rPos
)
180 std::array
<tools::Rectangle
,8> aRects
= FillHandleRectsPixel();
181 for( sal_uInt16 i
= 0; i
< 8; i
++ )
182 if( aRects
[ i
].Contains( rPos
) )
184 // Move-Rect overlaps Handles
185 std::array
<tools::Rectangle
,4> aMoveRects
= FillMoveRectsPixel();
186 for(const auto & rMoveRect
: aMoveRects
)
187 if( rMoveRect
.Contains( rPos
) )
192 tools::Rectangle
aRect( GetTrackRectPixel( rPos
) );
193 aRect
.SetSize( pWin
->PixelToLogic( aRect
.GetSize() ) );
194 aRect
.SetPos( pWin
->PixelToLogic( aRect
.TopLeft() ) );
195 pWin
->ShowTracking( aRect
);
200 Point
SvResizeHelper::GetTrackPosPixel( const tools::Rectangle
& rRect
) const
202 // not important how the rectangle is returned, it is important
203 // which handle has been touched
205 tools::Rectangle
aRect( rRect
);
207 // only because of EMPTY_RECT
208 Point aBR
= aOuter
.BottomRight();
209 Point aTR
= aOuter
.TopRight();
210 Point aBL
= aOuter
.BottomLeft();
211 bool bRTL
= AllSettings::GetLayoutRTL();
215 // FIXME: disable it for RTL because it's wrong calculations
218 aPos
= aRect
.TopLeft() - aOuter
.TopLeft();
221 aPos
.setY( aRect
.Top() - aOuter
.Top() );
224 // FIXME: disable it for RTL because it's wrong calculations
227 aPos
= aRect
.TopRight() - aTR
;
231 aPos
.setX( aRect
.Left() - aTR
.X() );
233 aPos
.setX( aRect
.Right() - aTR
.X() );
236 // FIXME: disable it for RTL because it's wrong calculations
239 aPos
= aRect
.BottomRight() - aBR
;
242 aPos
.setY( aRect
.Bottom() - aBR
.Y() );
245 // FIXME: disable it for RTL because it's wrong calculations
248 aPos
= aRect
.BottomLeft() - aBL
;
252 aPos
.setX( aRect
.Right() + aOuter
.Right() - aOuter
.Right() );
254 aPos
.setX( aRect
.Left() - aOuter
.Left() );
257 aPos
= aRect
.TopLeft() - aOuter
.TopLeft();
260 return aPos
+ aSelPos
;
263 /*************************************************************************
264 |* SvResizeHelper::GetTrackRectPixel()
267 *************************************************************************/
268 tools::Rectangle
SvResizeHelper::GetTrackRectPixel( const Point
& rTrackPos
) const
270 tools::Rectangle aTrackRect
;
273 Point aDiff
= rTrackPos
- aSelPos
;
275 Point aBR
= aOuter
.BottomRight();
276 bool bRTL
= AllSettings::GetLayoutRTL();
280 aTrackRect
.AdjustTop(aDiff
.Y() );
281 // ugly solution for resizing OLE objects in RTL
283 aTrackRect
.SetRight( aBR
.X() - aDiff
.X() );
285 aTrackRect
.AdjustLeft(aDiff
.X() );
288 aTrackRect
.AdjustTop(aDiff
.Y() );
291 aTrackRect
.AdjustTop(aDiff
.Y() );
292 // ugly solution for resizing OLE objects in RTL
294 aTrackRect
.AdjustLeft( -(aDiff
.X()) );
296 aTrackRect
.SetRight( aBR
.X() + aDiff
.X() );
299 // ugly solution for resizing OLE objects in RTL
301 aTrackRect
.AdjustLeft( -(aDiff
.X()) );
303 aTrackRect
.SetRight( aBR
.X() + aDiff
.X() );
306 aTrackRect
.SetBottom( aBR
.Y() + aDiff
.Y() );
307 // ugly solution for resizing OLE objects in RTL
309 aTrackRect
.AdjustLeft( -(aDiff
.X()) );
311 aTrackRect
.SetRight( aBR
.X() + aDiff
.X() );
314 aTrackRect
.SetBottom( aBR
.Y() + aDiff
.Y() );
317 aTrackRect
.SetBottom( aBR
.Y() + aDiff
.Y() );
318 // ugly solution for resizing OLE objects in RTL
320 aTrackRect
.SetRight( aBR
.X() - aDiff
.X() );
322 aTrackRect
.AdjustLeft(aDiff
.X() );
325 // ugly solution for resizing OLE objects in RTL
327 aTrackRect
.SetRight( aBR
.X() - aDiff
.X() );
329 aTrackRect
.AdjustLeft(aDiff
.X() );
333 aDiff
.setX( -aDiff
.X() ); // workaround for move in RTL mode
334 aTrackRect
.SetPos( aTrackRect
.TopLeft() + aDiff
);
341 void SvResizeHelper::ValidateRect( tools::Rectangle
& rValidate
) const
346 if( rValidate
.Top() > rValidate
.Bottom() )
347 rValidate
.SetTop( rValidate
.Bottom() );
348 if( rValidate
.Left() > rValidate
.Right() )
349 rValidate
.SetLeft( rValidate
.Right() );
352 if( rValidate
.Top() > rValidate
.Bottom() )
353 rValidate
.SetTop( rValidate
.Bottom() );
356 if( rValidate
.Top() > rValidate
.Bottom() )
357 rValidate
.SetTop( rValidate
.Bottom() );
358 if( rValidate
.Left() > rValidate
.Right() )
359 rValidate
.SetRight( rValidate
.Left() );
362 if( rValidate
.Left() > rValidate
.Right() )
363 rValidate
.SetRight( rValidate
.Left() );
366 if( rValidate
.Top() > rValidate
.Bottom() )
367 rValidate
.SetBottom( rValidate
.Top() );
368 if( rValidate
.Left() > rValidate
.Right() )
369 rValidate
.SetRight( rValidate
.Left() );
372 if( rValidate
.Top() > rValidate
.Bottom() )
373 rValidate
.SetBottom( rValidate
.Top() );
376 if( rValidate
.Top() > rValidate
.Bottom() )
377 rValidate
.SetBottom( rValidate
.Top() );
378 if( rValidate
.Left() > rValidate
.Right() )
379 rValidate
.SetLeft( rValidate
.Right() );
382 if( rValidate
.Left() > rValidate
.Right() )
383 rValidate
.SetLeft( rValidate
.Right() );
387 // Mindestgr"osse 5 x 5
388 if( rValidate
.Left() + 5 > rValidate
.Right() )
389 rValidate
.SetRight( rValidate
.Left() + 5 );
390 if( rValidate
.Top() + 5 > rValidate
.Bottom() )
391 rValidate
.SetBottom( rValidate
.Top() + 5 );
394 /*************************************************************************
395 |* SvResizeHelper::SelectRelease()
398 *************************************************************************/
399 bool SvResizeHelper::SelectRelease( vcl::Window
* pWin
, const Point
& rPos
,
400 tools::Rectangle
& rOutPosSize
)
404 rOutPosSize
= GetTrackRectPixel( rPos
);
405 rOutPosSize
.Normalize();
407 pWin
->ReleaseMouse();
408 pWin
->HideTracking();
414 /*************************************************************************
415 |* SvResizeHelper::Release()
418 *************************************************************************/
419 void SvResizeHelper::Release( vcl::Window
* pWin
)
423 pWin
->ReleaseMouse();
424 pWin
->HideTracking();
429 /*************************************************************************
430 |* SvResizeWindow::SvResizeWindow()
433 *************************************************************************/
434 SvResizeWindow::SvResizeWindow
436 vcl::Window
* pParent
,
437 VCLXHatchWindow
* pWrapper
439 : Window( pParent
, WB_CLIPCHILDREN
)
440 , m_aOldPointer(PointerStyle::Arrow
)
443 , m_pWrapper( pWrapper
)
445 OSL_ENSURE( pParent
!= nullptr && pWrapper
!= nullptr, "Wrong initialization of hatch window!" );
447 SetAccessibleRole( css::accessibility::AccessibleRole::EMBEDDED_OBJECT
);
448 m_aResizer
.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
451 /*************************************************************************
452 |* SvResizeWindow::SetHatchBorderPixel()
455 *************************************************************************/
456 void SvResizeWindow::SetHatchBorderPixel( const Size
& rSize
)
458 m_aResizer
.SetBorderPixel( rSize
);
461 /*************************************************************************
462 |* SvResizeWindow::SelectMouse()
465 *************************************************************************/
466 void SvResizeWindow::SelectMouse( const Point
& rPos
)
468 short nGrab
= m_aResizer
.SelectMove( this, rPos
);
471 if( m_nMoveGrab
== nGrab
)
474 // Pointer did change
476 SetPointer( m_aOldPointer
);
479 PointerStyle aStyle
= PointerStyle::Move
;
481 aStyle
= PointerStyle::ESize
;
482 else if( nGrab
== 2 )
483 aStyle
= PointerStyle::NESize
;
484 else if( nGrab
== 1 )
485 aStyle
= PointerStyle::SSize
;
486 else if( nGrab
== 0 )
487 aStyle
= PointerStyle::SESize
;
488 if( m_nMoveGrab
== -1 ) // the first time
490 m_aOldPointer
= GetPointer();
491 SetPointer( aStyle
);
494 SetPointer( aStyle
);
499 /*************************************************************************
500 |* SvResizeWindow::MouseButtonDown()
503 *************************************************************************/
504 void SvResizeWindow::MouseButtonDown( const MouseEvent
& rEvt
)
506 if( m_aResizer
.SelectBegin( this, rEvt
.GetPosPixel() ) )
507 SelectMouse( rEvt
.GetPosPixel() );
510 /*************************************************************************
511 |* SvResizeWindow::MouseMove()
514 *************************************************************************/
515 void SvResizeWindow::MouseMove( const MouseEvent
& rEvt
)
517 if( m_aResizer
.GetGrab() == -1 )
518 SelectMouse( rEvt
.GetPosPixel() );
521 tools::Rectangle
aRect( m_aResizer
.GetTrackRectPixel( rEvt
.GetPosPixel() ) );
522 Point aDiff
= GetPosPixel();
523 aRect
.SetPos( aRect
.TopLeft() + aDiff
);
524 m_aResizer
.ValidateRect( aRect
);
526 m_pWrapper
->QueryObjAreaPixel( aRect
);
527 aRect
.SetPos( aRect
.TopLeft() - aDiff
);
528 Point aPos
= m_aResizer
.GetTrackPosPixel( aRect
);
534 /*************************************************************************
535 |* SvResizeWindow::MouseButtonUp()
538 *************************************************************************/
539 void SvResizeWindow::MouseButtonUp( const MouseEvent
& rEvt
)
541 if( m_aResizer
.GetGrab() == -1 )
544 tools::Rectangle
aRect( m_aResizer
.GetTrackRectPixel( rEvt
.GetPosPixel() ) );
545 Point aDiff
= GetPosPixel();
546 aRect
.SetPos( aRect
.TopLeft() + aDiff
);
547 // aRect -= GetAllBorderPixel();
548 m_aResizer
.ValidateRect( aRect
);
550 m_pWrapper
->QueryObjAreaPixel( aRect
);
552 tools::Rectangle aOutRect
;
553 if( m_aResizer
.SelectRelease( this, rEvt
.GetPosPixel(), aOutRect
) )
556 SetPointer( m_aOldPointer
);
557 m_pWrapper
->RequestObjAreaPixel( aRect
);
561 /*************************************************************************
562 |* SvResizeWindow::KeyEvent()
565 *************************************************************************/
566 void SvResizeWindow::KeyInput( const KeyEvent
& rEvt
)
568 if( rEvt
.GetKeyCode().GetCode() == KEY_ESCAPE
)
570 m_aResizer
.Release( this );
571 m_pWrapper
->InplaceDeactivate();
575 /*************************************************************************
576 |* SvResizeWindow::Resize()
579 *************************************************************************/
580 void SvResizeWindow::Resize()
582 m_aResizer
.InvalidateBorder( this ); // old area
583 m_aResizer
.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
584 m_aResizer
.InvalidateBorder( this ); // new area
587 /*************************************************************************
588 |* SvResizeWindow::Paint()
591 *************************************************************************/
592 void SvResizeWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/ )
594 m_aResizer
.Draw(rRenderContext
);
597 bool SvResizeWindow::PreNotify( NotifyEvent
& rEvt
)
599 if ( rEvt
.GetType() == NotifyEventType::GETFOCUS
&& !m_bActive
)
602 m_pWrapper
->Activated();
605 return Window::PreNotify(rEvt
);
608 bool SvResizeWindow::EventNotify( NotifyEvent
& rEvt
)
610 if ( rEvt
.GetType() == NotifyEventType::LOSEFOCUS
&& m_bActive
)
612 bool bHasFocus
= HasChildPathFocus(true);
616 m_pWrapper
->Deactivated();
620 return Window::EventNotify(rEvt
);
623 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */