Add a comment to clarify what kind of inputs the class handles
[LibreOffice.git] / toolkit / source / hatchwindow / ipwin.cxx
blob3315cd910089e322d563b33c53d015b06a977c65
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 <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>
27 #include "ipwin.hxx"
28 #include "hatchwindow.hxx"
30 /************************************************************************/
31 /*************************************************************************
32 |* SvResizeHelper::SvResizeHelper()
34 |* Description
35 *************************************************************************/
36 SvResizeHelper::SvResizeHelper()
37 : aBorder( 5, 5 )
38 , nGrab( -1 )
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();
54 // upper left
55 aRects[ 0 ] = tools::Rectangle( aOuter.TopLeft(), aBorder );
56 // upper middle
57 aRects[ 1 ] = tools::Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
58 aOuter.Top() ),
59 aBorder );
60 // upper right
61 aRects[ 2 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
62 aOuter.Top() ),
63 aBorder );
64 // middle right
65 aRects[ 3 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
66 aOuter.Center().Y() - aBorder.Height() / 2 ),
67 aBorder );
68 // lower right
69 aRects[ 4 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
70 aBottomRight.Y() - aBorder.Height() +1 ),
71 aBorder );
72 // lower middle
73 aRects[ 5 ] = tools::Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
74 aBottomRight.Y() - aBorder.Height() +1),
75 aBorder );
76 // lower left
77 aRects[ 6 ] = tools::Rectangle( Point( aOuter.Left(),
78 aBottomRight.Y() - aBorder.Height() +1),
79 aBorder );
80 // middle left
81 aRects[ 7 ] = tools::Rectangle( Point( aOuter.Left(),
82 aOuter.Center().Y() - aBorder.Height() / 2 ),
83 aBorder );
84 return aRects;
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;
96 // upper
97 aRects[ 0 ] = aOuter;
98 aRects[ 0 ].SetBottom( aRects[ 0 ].Top() + aBorder.Height() -1 );
99 // right
100 aRects[ 1 ] = aOuter;
101 if (!aOuter.IsWidthEmpty())
102 aRects[ 1 ].SetLeft( aRects[ 1 ].Right() - aBorder.Width() -1 );
103 // lower
104 aRects[ 2 ] = aOuter;
105 if (!aOuter.IsHeightEmpty())
106 aRects[ 2 ].SetTop( aRects[ 2 ].Bottom() - aBorder.Height() -1 );
107 // left
108 aRects[ 3 ] = aOuter;
109 aRects[ 3 ].SetRight( aRects[ 3 ].Left() + aBorder.Width() -1 );
111 return aRects;
114 /*************************************************************************
115 |* SvResizeHelper::Draw()
117 |* Description
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();
128 sal_uInt16 i;
129 for (i = 0; i < 4; i++)
130 rRenderContext.DrawRect(aMoveRects[i]);
131 // draw handles
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()
142 |* Description
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()
154 |* Description
155 *************************************************************************/
156 bool SvResizeHelper::SelectBegin( vcl::Window * pWin, const Point & rPos )
158 if( -1 == nGrab )
160 nGrab = SelectMove( pWin, rPos );
161 if( -1 != nGrab )
163 aSelPos = rPos; // store start position
164 pWin->CaptureMouse();
165 return true;
168 return false;
171 /*************************************************************************
172 |* SvResizeHelper::SelectMove()
174 |* Description
175 *************************************************************************/
176 short SvResizeHelper::SelectMove( vcl::Window * pWin, const Point & rPos )
178 if( -1 == nGrab )
180 std::array<tools::Rectangle,8> aRects = FillHandleRectsPixel();
181 for( sal_uInt16 i = 0; i < 8; i++ )
182 if( aRects[ i ].Contains( rPos ) )
183 return i;
184 // Move-Rect overlaps Handles
185 std::array<tools::Rectangle,4> aMoveRects = FillMoveRectsPixel();
186 for(const auto & rMoveRect : aMoveRects)
187 if( rMoveRect.Contains( rPos ) )
188 return 8;
190 else
192 tools::Rectangle aRect = pWin->PixelToLogic(GetTrackRectPixel( rPos ));
193 pWin->ShowTracking( aRect );
195 return nGrab;
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
202 Point aPos;
203 tools::Rectangle aRect( rRect );
204 aRect.Normalize();
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();
210 switch( nGrab )
212 case 0:
213 // FIXME: disable it for RTL because it's wrong calculations
214 if( bRTL )
215 break;
216 aPos = aRect.TopLeft() - aOuter.TopLeft();
217 break;
218 case 1:
219 aPos.setY( aRect.Top() - aOuter.Top() );
220 break;
221 case 2:
222 // FIXME: disable it for RTL because it's wrong calculations
223 if( bRTL )
224 break;
225 aPos = aRect.TopRight() - aTR;
226 break;
227 case 3:
228 if( bRTL )
229 aPos.setX( aRect.Left() - aTR.X() );
230 else
231 aPos.setX( aRect.Right() - aTR.X() );
232 break;
233 case 4:
234 // FIXME: disable it for RTL because it's wrong calculations
235 if( bRTL )
236 break;
237 aPos = aRect.BottomRight() - aBR;
238 break;
239 case 5:
240 aPos.setY( aRect.Bottom() - aBR.Y() );
241 break;
242 case 6:
243 // FIXME: disable it for RTL because it's wrong calculations
244 if( bRTL )
245 break;
246 aPos = aRect.BottomLeft() - aBL;
247 break;
248 case 7:
249 if( bRTL )
250 aPos.setX( aRect.Right() + aOuter.Right() - aOuter.Right() );
251 else
252 aPos.setX( aRect.Left() - aOuter.Left() );
253 break;
254 case 8:
255 aPos = aRect.TopLeft() - aOuter.TopLeft();
256 break;
258 return aPos + aSelPos;
261 /*************************************************************************
262 |* SvResizeHelper::GetTrackRectPixel()
264 |* Description
265 *************************************************************************/
266 tools::Rectangle SvResizeHelper::GetTrackRectPixel( const Point & rTrackPos ) const
268 tools::Rectangle aTrackRect;
269 if( -1 != nGrab )
271 Point aDiff = rTrackPos - aSelPos;
272 aTrackRect = aOuter;
273 Point aBR = aOuter.BottomRight();
274 bool bRTL = AllSettings::GetLayoutRTL();
275 switch( nGrab )
277 case 0:
278 aTrackRect.AdjustTop(aDiff.Y() );
279 // ugly solution for resizing OLE objects in RTL
280 if( bRTL )
281 aTrackRect.SetRight( aBR.X() - aDiff.X() );
282 else
283 aTrackRect.AdjustLeft(aDiff.X() );
284 break;
285 case 1:
286 aTrackRect.AdjustTop(aDiff.Y() );
287 break;
288 case 2:
289 aTrackRect.AdjustTop(aDiff.Y() );
290 // ugly solution for resizing OLE objects in RTL
291 if( bRTL )
292 aTrackRect.AdjustLeft( -(aDiff.X()) );
293 else
294 aTrackRect.SetRight( aBR.X() + aDiff.X() );
295 break;
296 case 3:
297 // ugly solution for resizing OLE objects in RTL
298 if( bRTL )
299 aTrackRect.AdjustLeft( -(aDiff.X()) );
300 else
301 aTrackRect.SetRight( aBR.X() + aDiff.X() );
302 break;
303 case 4:
304 aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
305 // ugly solution for resizing OLE objects in RTL
306 if( bRTL )
307 aTrackRect.AdjustLeft( -(aDiff.X()) );
308 else
309 aTrackRect.SetRight( aBR.X() + aDiff.X() );
310 break;
311 case 5:
312 aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
313 break;
314 case 6:
315 aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
316 // ugly solution for resizing OLE objects in RTL
317 if( bRTL )
318 aTrackRect.SetRight( aBR.X() - aDiff.X() );
319 else
320 aTrackRect.AdjustLeft(aDiff.X() );
321 break;
322 case 7:
323 // ugly solution for resizing OLE objects in RTL
324 if( bRTL )
325 aTrackRect.SetRight( aBR.X() - aDiff.X() );
326 else
327 aTrackRect.AdjustLeft(aDiff.X() );
328 break;
329 case 8:
330 if( bRTL )
331 aDiff.setX( -aDiff.X() ); // workaround for move in RTL mode
332 aTrackRect.SetPos( aTrackRect.TopLeft() + aDiff );
333 break;
336 return aTrackRect;
339 void SvResizeHelper::ValidateRect( tools::Rectangle & rValidate ) const
341 switch( nGrab )
343 case 0:
344 if( rValidate.Top() > rValidate.Bottom() )
345 rValidate.SetTop( rValidate.Bottom() );
346 if( rValidate.Left() > rValidate.Right() )
347 rValidate.SetLeft( rValidate.Right() );
348 break;
349 case 1:
350 if( rValidate.Top() > rValidate.Bottom() )
351 rValidate.SetTop( rValidate.Bottom() );
352 break;
353 case 2:
354 if( rValidate.Top() > rValidate.Bottom() )
355 rValidate.SetTop( rValidate.Bottom() );
356 if( rValidate.Left() > rValidate.Right() )
357 rValidate.SetRight( rValidate.Left() );
358 break;
359 case 3:
360 if( rValidate.Left() > rValidate.Right() )
361 rValidate.SetRight( rValidate.Left() );
362 break;
363 case 4:
364 if( rValidate.Top() > rValidate.Bottom() )
365 rValidate.SetBottom( rValidate.Top() );
366 if( rValidate.Left() > rValidate.Right() )
367 rValidate.SetRight( rValidate.Left() );
368 break;
369 case 5:
370 if( rValidate.Top() > rValidate.Bottom() )
371 rValidate.SetBottom( rValidate.Top() );
372 break;
373 case 6:
374 if( rValidate.Top() > rValidate.Bottom() )
375 rValidate.SetBottom( rValidate.Top() );
376 if( rValidate.Left() > rValidate.Right() )
377 rValidate.SetLeft( rValidate.Right() );
378 break;
379 case 7:
380 if( rValidate.Left() > rValidate.Right() )
381 rValidate.SetLeft( rValidate.Right() );
382 break;
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()
395 |* Description
396 *************************************************************************/
397 bool SvResizeHelper::SelectRelease( vcl::Window * pWin, const Point & rPos,
398 tools::Rectangle & rOutPosSize )
400 if( -1 != nGrab )
402 rOutPosSize = GetTrackRectPixel( rPos );
403 rOutPosSize.Normalize();
404 nGrab = -1;
405 pWin->ReleaseMouse();
406 pWin->HideTracking();
407 return true;
409 return false;
412 /*************************************************************************
413 |* SvResizeHelper::Release()
415 |* Description
416 *************************************************************************/
417 void SvResizeHelper::Release( vcl::Window * pWin )
419 if( nGrab != -1 )
421 pWin->ReleaseMouse();
422 pWin->HideTracking();
423 nGrab = -1;
427 /*************************************************************************
428 |* SvResizeWindow::SvResizeWindow()
430 |* Description
431 *************************************************************************/
432 SvResizeWindow::SvResizeWindow
434 vcl::Window * pParent,
435 VCLXHatchWindow* pWrapper
437 : Window( pParent, WB_CLIPCHILDREN )
438 , m_aOldPointer(PointerStyle::Arrow)
439 , m_nMoveGrab( -1 )
440 , m_bActive( false )
441 , m_pWrapper( pWrapper )
443 OSL_ENSURE( pParent != nullptr && pWrapper != nullptr, "Wrong initialization of hatch window!" );
444 SetBackground();
445 SetAccessibleRole( css::accessibility::AccessibleRole::EMBEDDED_OBJECT );
446 m_aResizer.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
449 /*************************************************************************
450 |* SvResizeWindow::SetHatchBorderPixel()
452 |* Description
453 *************************************************************************/
454 void SvResizeWindow::SetHatchBorderPixel( const Size & rSize )
456 m_aResizer.SetBorderPixel( rSize );
459 /*************************************************************************
460 |* SvResizeWindow::SelectMouse()
462 |* Description
463 *************************************************************************/
464 void SvResizeWindow::SelectMouse( const Point & rPos )
466 short nGrab = m_aResizer.SelectMove( this, rPos );
467 if( nGrab >= 4 )
468 nGrab -= 4;
469 if( m_nMoveGrab == nGrab )
470 return;
472 // Pointer did change
473 if( -1 == nGrab )
474 SetPointer( m_aOldPointer );
475 else
477 PointerStyle aStyle = PointerStyle::Move;
478 if( nGrab == 3 )
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 );
491 else
492 SetPointer( aStyle );
494 m_nMoveGrab = nGrab;
497 /*************************************************************************
498 |* SvResizeWindow::MouseButtonDown()
500 |* Description
501 *************************************************************************/
502 void SvResizeWindow::MouseButtonDown( const MouseEvent & rEvt )
504 if( m_aResizer.SelectBegin( this, rEvt.GetPosPixel() ) )
505 SelectMouse( rEvt.GetPosPixel() );
508 /*************************************************************************
509 |* SvResizeWindow::MouseMove()
511 |* Description
512 *************************************************************************/
513 void SvResizeWindow::MouseMove( const MouseEvent & rEvt )
515 if( m_aResizer.GetGrab() == -1 )
516 SelectMouse( rEvt.GetPosPixel() );
517 else
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 );
528 SelectMouse( aPos );
532 /*************************************************************************
533 |* SvResizeWindow::MouseButtonUp()
535 |* Description
536 *************************************************************************/
537 void SvResizeWindow::MouseButtonUp( const MouseEvent & rEvt )
539 if( m_aResizer.GetGrab() == -1 )
540 return;
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 ) )
553 m_nMoveGrab = -1;
554 SetPointer( m_aOldPointer );
555 m_pWrapper->RequestObjAreaPixel( aRect );
559 /*************************************************************************
560 |* SvResizeWindow::KeyEvent()
562 |* Description
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()
576 |* Description
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()
588 |* Description
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 )
599 m_bActive = true;
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);
611 if ( !bHasFocus )
613 m_bActive = false;
614 m_pWrapper->Deactivated();
618 return Window::EventNotify(rEvt);
621 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */