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
= pWin
->PixelToLogic(GetTrackRectPixel( rPos
));
193 pWin
->ShowTracking( aRect
);
198 Point
SvResizeHelper::GetTrackPosPixel( const tools::Rectangle
& rRect
) const
200 // not important how the rectangle is returned, it is important
201 // which handle has been touched
203 tools::Rectangle
aRect( rRect
);
205 // only because of EMPTY_RECT
206 Point aBR
= aOuter
.BottomRight();
207 Point aTR
= aOuter
.TopRight();
208 Point aBL
= aOuter
.BottomLeft();
209 bool bRTL
= AllSettings::GetLayoutRTL();
213 // FIXME: disable it for RTL because it's wrong calculations
216 aPos
= aRect
.TopLeft() - aOuter
.TopLeft();
219 aPos
.setY( aRect
.Top() - aOuter
.Top() );
222 // FIXME: disable it for RTL because it's wrong calculations
225 aPos
= aRect
.TopRight() - aTR
;
229 aPos
.setX( aRect
.Left() - aTR
.X() );
231 aPos
.setX( aRect
.Right() - aTR
.X() );
234 // FIXME: disable it for RTL because it's wrong calculations
237 aPos
= aRect
.BottomRight() - aBR
;
240 aPos
.setY( aRect
.Bottom() - aBR
.Y() );
243 // FIXME: disable it for RTL because it's wrong calculations
246 aPos
= aRect
.BottomLeft() - aBL
;
250 aPos
.setX( aRect
.Right() + aOuter
.Right() - aOuter
.Right() );
252 aPos
.setX( aRect
.Left() - aOuter
.Left() );
255 aPos
= aRect
.TopLeft() - aOuter
.TopLeft();
258 return aPos
+ aSelPos
;
261 /*************************************************************************
262 |* SvResizeHelper::GetTrackRectPixel()
265 *************************************************************************/
266 tools::Rectangle
SvResizeHelper::GetTrackRectPixel( const Point
& rTrackPos
) const
268 tools::Rectangle aTrackRect
;
271 Point aDiff
= rTrackPos
- aSelPos
;
273 Point aBR
= aOuter
.BottomRight();
274 bool bRTL
= AllSettings::GetLayoutRTL();
278 aTrackRect
.AdjustTop(aDiff
.Y() );
279 // ugly solution for resizing OLE objects in RTL
281 aTrackRect
.SetRight( aBR
.X() - aDiff
.X() );
283 aTrackRect
.AdjustLeft(aDiff
.X() );
286 aTrackRect
.AdjustTop(aDiff
.Y() );
289 aTrackRect
.AdjustTop(aDiff
.Y() );
290 // ugly solution for resizing OLE objects in RTL
292 aTrackRect
.AdjustLeft( -(aDiff
.X()) );
294 aTrackRect
.SetRight( aBR
.X() + aDiff
.X() );
297 // ugly solution for resizing OLE objects in RTL
299 aTrackRect
.AdjustLeft( -(aDiff
.X()) );
301 aTrackRect
.SetRight( aBR
.X() + aDiff
.X() );
304 aTrackRect
.SetBottom( aBR
.Y() + aDiff
.Y() );
305 // ugly solution for resizing OLE objects in RTL
307 aTrackRect
.AdjustLeft( -(aDiff
.X()) );
309 aTrackRect
.SetRight( aBR
.X() + aDiff
.X() );
312 aTrackRect
.SetBottom( aBR
.Y() + aDiff
.Y() );
315 aTrackRect
.SetBottom( aBR
.Y() + aDiff
.Y() );
316 // ugly solution for resizing OLE objects in RTL
318 aTrackRect
.SetRight( aBR
.X() - aDiff
.X() );
320 aTrackRect
.AdjustLeft(aDiff
.X() );
323 // ugly solution for resizing OLE objects in RTL
325 aTrackRect
.SetRight( aBR
.X() - aDiff
.X() );
327 aTrackRect
.AdjustLeft(aDiff
.X() );
331 aDiff
.setX( -aDiff
.X() ); // workaround for move in RTL mode
332 aTrackRect
.SetPos( aTrackRect
.TopLeft() + aDiff
);
339 void SvResizeHelper::ValidateRect( tools::Rectangle
& rValidate
) const
344 if( rValidate
.Top() > rValidate
.Bottom() )
345 rValidate
.SetTop( rValidate
.Bottom() );
346 if( rValidate
.Left() > rValidate
.Right() )
347 rValidate
.SetLeft( rValidate
.Right() );
350 if( rValidate
.Top() > rValidate
.Bottom() )
351 rValidate
.SetTop( rValidate
.Bottom() );
354 if( rValidate
.Top() > rValidate
.Bottom() )
355 rValidate
.SetTop( rValidate
.Bottom() );
356 if( rValidate
.Left() > rValidate
.Right() )
357 rValidate
.SetRight( rValidate
.Left() );
360 if( rValidate
.Left() > rValidate
.Right() )
361 rValidate
.SetRight( rValidate
.Left() );
364 if( rValidate
.Top() > rValidate
.Bottom() )
365 rValidate
.SetBottom( rValidate
.Top() );
366 if( rValidate
.Left() > rValidate
.Right() )
367 rValidate
.SetRight( rValidate
.Left() );
370 if( rValidate
.Top() > rValidate
.Bottom() )
371 rValidate
.SetBottom( rValidate
.Top() );
374 if( rValidate
.Top() > rValidate
.Bottom() )
375 rValidate
.SetBottom( rValidate
.Top() );
376 if( rValidate
.Left() > rValidate
.Right() )
377 rValidate
.SetLeft( rValidate
.Right() );
380 if( rValidate
.Left() > rValidate
.Right() )
381 rValidate
.SetLeft( rValidate
.Right() );
385 // Minimum size 5 x 5
386 if( rValidate
.Left() + 5 > rValidate
.Right() )
387 rValidate
.SetRight( rValidate
.Left() + 5 );
388 if( rValidate
.Top() + 5 > rValidate
.Bottom() )
389 rValidate
.SetBottom( rValidate
.Top() + 5 );
392 /*************************************************************************
393 |* SvResizeHelper::SelectRelease()
396 *************************************************************************/
397 bool SvResizeHelper::SelectRelease( vcl::Window
* pWin
, const Point
& rPos
,
398 tools::Rectangle
& rOutPosSize
)
402 rOutPosSize
= GetTrackRectPixel( rPos
);
403 rOutPosSize
.Normalize();
405 pWin
->ReleaseMouse();
406 pWin
->HideTracking();
412 /*************************************************************************
413 |* SvResizeHelper::Release()
416 *************************************************************************/
417 void SvResizeHelper::Release( vcl::Window
* pWin
)
421 pWin
->ReleaseMouse();
422 pWin
->HideTracking();
427 /*************************************************************************
428 |* SvResizeWindow::SvResizeWindow()
431 *************************************************************************/
432 SvResizeWindow::SvResizeWindow
434 vcl::Window
* pParent
,
435 VCLXHatchWindow
* pWrapper
437 : Window( pParent
, WB_CLIPCHILDREN
)
438 , m_aOldPointer(PointerStyle::Arrow
)
441 , m_pWrapper( pWrapper
)
443 OSL_ENSURE( pParent
!= nullptr && pWrapper
!= nullptr, "Wrong initialization of hatch window!" );
445 SetAccessibleRole( css::accessibility::AccessibleRole::EMBEDDED_OBJECT
);
446 m_aResizer
.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
449 /*************************************************************************
450 |* SvResizeWindow::SetHatchBorderPixel()
453 *************************************************************************/
454 void SvResizeWindow::SetHatchBorderPixel( const Size
& rSize
)
456 m_aResizer
.SetBorderPixel( rSize
);
459 /*************************************************************************
460 |* SvResizeWindow::SelectMouse()
463 *************************************************************************/
464 void SvResizeWindow::SelectMouse( const Point
& rPos
)
466 short nGrab
= m_aResizer
.SelectMove( this, rPos
);
469 if( m_nMoveGrab
== nGrab
)
472 // Pointer did change
474 SetPointer( m_aOldPointer
);
477 PointerStyle aStyle
= PointerStyle::Move
;
479 aStyle
= PointerStyle::ESize
;
480 else if( nGrab
== 2 )
481 aStyle
= PointerStyle::NESize
;
482 else if( nGrab
== 1 )
483 aStyle
= PointerStyle::SSize
;
484 else if( nGrab
== 0 )
485 aStyle
= PointerStyle::SESize
;
486 if( m_nMoveGrab
== -1 ) // the first time
488 m_aOldPointer
= GetPointer();
489 SetPointer( aStyle
);
492 SetPointer( aStyle
);
497 /*************************************************************************
498 |* SvResizeWindow::MouseButtonDown()
501 *************************************************************************/
502 void SvResizeWindow::MouseButtonDown( const MouseEvent
& rEvt
)
504 if( m_aResizer
.SelectBegin( this, rEvt
.GetPosPixel() ) )
505 SelectMouse( rEvt
.GetPosPixel() );
508 /*************************************************************************
509 |* SvResizeWindow::MouseMove()
512 *************************************************************************/
513 void SvResizeWindow::MouseMove( const MouseEvent
& rEvt
)
515 if( m_aResizer
.GetGrab() == -1 )
516 SelectMouse( rEvt
.GetPosPixel() );
519 tools::Rectangle
aRect( m_aResizer
.GetTrackRectPixel( rEvt
.GetPosPixel() ) );
520 Point aDiff
= GetPosPixel();
521 aRect
.SetPos( aRect
.TopLeft() + aDiff
);
522 m_aResizer
.ValidateRect( aRect
);
524 m_pWrapper
->QueryObjAreaPixel( aRect
);
525 aRect
.SetPos( aRect
.TopLeft() - aDiff
);
526 Point aPos
= m_aResizer
.GetTrackPosPixel( aRect
);
532 /*************************************************************************
533 |* SvResizeWindow::MouseButtonUp()
536 *************************************************************************/
537 void SvResizeWindow::MouseButtonUp( const MouseEvent
& rEvt
)
539 if( m_aResizer
.GetGrab() == -1 )
542 tools::Rectangle
aRect( m_aResizer
.GetTrackRectPixel( rEvt
.GetPosPixel() ) );
543 Point aDiff
= GetPosPixel();
544 aRect
.SetPos( aRect
.TopLeft() + aDiff
);
545 // aRect -= GetAllBorderPixel();
546 m_aResizer
.ValidateRect( aRect
);
548 m_pWrapper
->QueryObjAreaPixel( aRect
);
550 tools::Rectangle aOutRect
;
551 if( m_aResizer
.SelectRelease( this, rEvt
.GetPosPixel(), aOutRect
) )
554 SetPointer( m_aOldPointer
);
555 m_pWrapper
->RequestObjAreaPixel( aRect
);
559 /*************************************************************************
560 |* SvResizeWindow::KeyEvent()
563 *************************************************************************/
564 void SvResizeWindow::KeyInput( const KeyEvent
& rEvt
)
566 if( rEvt
.GetKeyCode().GetCode() == KEY_ESCAPE
)
568 m_aResizer
.Release( this );
569 m_pWrapper
->InplaceDeactivate();
573 /*************************************************************************
574 |* SvResizeWindow::Resize()
577 *************************************************************************/
578 void SvResizeWindow::Resize()
580 m_aResizer
.InvalidateBorder( this ); // old area
581 m_aResizer
.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
582 m_aResizer
.InvalidateBorder( this ); // new area
585 /*************************************************************************
586 |* SvResizeWindow::Paint()
589 *************************************************************************/
590 void SvResizeWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/ )
592 m_aResizer
.Draw(rRenderContext
);
595 bool SvResizeWindow::PreNotify( NotifyEvent
& rEvt
)
597 if ( rEvt
.GetType() == NotifyEventType::GETFOCUS
&& !m_bActive
)
600 m_pWrapper
->Activated();
603 return Window::PreNotify(rEvt
);
606 bool SvResizeWindow::EventNotify( NotifyEvent
& rEvt
)
608 if ( rEvt
.GetType() == NotifyEventType::LOSEFOCUS
&& m_bActive
)
610 bool bHasFocus
= HasChildPathFocus(true);
614 m_pWrapper
->Deactivated();
618 return Window::EventNotify(rEvt
);
621 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */