Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / toolkit / source / hatchwindow / ipwin.cxx
blobd21e94166c7c1cead50bab33845c08af5cf91b6a
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( GetTrackRectPixel( rPos ) );
193 aRect.SetSize( pWin->PixelToLogic( aRect.GetSize() ) );
194 aRect.SetPos( pWin->PixelToLogic( aRect.TopLeft() ) );
195 pWin->ShowTracking( aRect );
197 return nGrab;
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
204 Point aPos;
205 tools::Rectangle aRect( rRect );
206 aRect.Normalize();
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();
212 switch( nGrab )
214 case 0:
215 // FIXME: disable it for RTL because it's wrong calculations
216 if( bRTL )
217 break;
218 aPos = aRect.TopLeft() - aOuter.TopLeft();
219 break;
220 case 1:
221 aPos.setY( aRect.Top() - aOuter.Top() );
222 break;
223 case 2:
224 // FIXME: disable it for RTL because it's wrong calculations
225 if( bRTL )
226 break;
227 aPos = aRect.TopRight() - aTR;
228 break;
229 case 3:
230 if( bRTL )
231 aPos.setX( aRect.Left() - aTR.X() );
232 else
233 aPos.setX( aRect.Right() - aTR.X() );
234 break;
235 case 4:
236 // FIXME: disable it for RTL because it's wrong calculations
237 if( bRTL )
238 break;
239 aPos = aRect.BottomRight() - aBR;
240 break;
241 case 5:
242 aPos.setY( aRect.Bottom() - aBR.Y() );
243 break;
244 case 6:
245 // FIXME: disable it for RTL because it's wrong calculations
246 if( bRTL )
247 break;
248 aPos = aRect.BottomLeft() - aBL;
249 break;
250 case 7:
251 if( bRTL )
252 aPos.setX( aRect.Right() + aOuter.Right() - aOuter.Right() );
253 else
254 aPos.setX( aRect.Left() - aOuter.Left() );
255 break;
256 case 8:
257 aPos = aRect.TopLeft() - aOuter.TopLeft();
258 break;
260 return aPos + aSelPos;
263 /*************************************************************************
264 |* SvResizeHelper::GetTrackRectPixel()
266 |* Description
267 *************************************************************************/
268 tools::Rectangle SvResizeHelper::GetTrackRectPixel( const Point & rTrackPos ) const
270 tools::Rectangle aTrackRect;
271 if( -1 != nGrab )
273 Point aDiff = rTrackPos - aSelPos;
274 aTrackRect = aOuter;
275 Point aBR = aOuter.BottomRight();
276 bool bRTL = AllSettings::GetLayoutRTL();
277 switch( nGrab )
279 case 0:
280 aTrackRect.AdjustTop(aDiff.Y() );
281 // ugly solution for resizing OLE objects in RTL
282 if( bRTL )
283 aTrackRect.SetRight( aBR.X() - aDiff.X() );
284 else
285 aTrackRect.AdjustLeft(aDiff.X() );
286 break;
287 case 1:
288 aTrackRect.AdjustTop(aDiff.Y() );
289 break;
290 case 2:
291 aTrackRect.AdjustTop(aDiff.Y() );
292 // ugly solution for resizing OLE objects in RTL
293 if( bRTL )
294 aTrackRect.AdjustLeft( -(aDiff.X()) );
295 else
296 aTrackRect.SetRight( aBR.X() + aDiff.X() );
297 break;
298 case 3:
299 // ugly solution for resizing OLE objects in RTL
300 if( bRTL )
301 aTrackRect.AdjustLeft( -(aDiff.X()) );
302 else
303 aTrackRect.SetRight( aBR.X() + aDiff.X() );
304 break;
305 case 4:
306 aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
307 // ugly solution for resizing OLE objects in RTL
308 if( bRTL )
309 aTrackRect.AdjustLeft( -(aDiff.X()) );
310 else
311 aTrackRect.SetRight( aBR.X() + aDiff.X() );
312 break;
313 case 5:
314 aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
315 break;
316 case 6:
317 aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
318 // ugly solution for resizing OLE objects in RTL
319 if( bRTL )
320 aTrackRect.SetRight( aBR.X() - aDiff.X() );
321 else
322 aTrackRect.AdjustLeft(aDiff.X() );
323 break;
324 case 7:
325 // ugly solution for resizing OLE objects in RTL
326 if( bRTL )
327 aTrackRect.SetRight( aBR.X() - aDiff.X() );
328 else
329 aTrackRect.AdjustLeft(aDiff.X() );
330 break;
331 case 8:
332 if( bRTL )
333 aDiff.setX( -aDiff.X() ); // workaround for move in RTL mode
334 aTrackRect.SetPos( aTrackRect.TopLeft() + aDiff );
335 break;
338 return aTrackRect;
341 void SvResizeHelper::ValidateRect( tools::Rectangle & rValidate ) const
343 switch( nGrab )
345 case 0:
346 if( rValidate.Top() > rValidate.Bottom() )
347 rValidate.SetTop( rValidate.Bottom() );
348 if( rValidate.Left() > rValidate.Right() )
349 rValidate.SetLeft( rValidate.Right() );
350 break;
351 case 1:
352 if( rValidate.Top() > rValidate.Bottom() )
353 rValidate.SetTop( rValidate.Bottom() );
354 break;
355 case 2:
356 if( rValidate.Top() > rValidate.Bottom() )
357 rValidate.SetTop( rValidate.Bottom() );
358 if( rValidate.Left() > rValidate.Right() )
359 rValidate.SetRight( rValidate.Left() );
360 break;
361 case 3:
362 if( rValidate.Left() > rValidate.Right() )
363 rValidate.SetRight( rValidate.Left() );
364 break;
365 case 4:
366 if( rValidate.Top() > rValidate.Bottom() )
367 rValidate.SetBottom( rValidate.Top() );
368 if( rValidate.Left() > rValidate.Right() )
369 rValidate.SetRight( rValidate.Left() );
370 break;
371 case 5:
372 if( rValidate.Top() > rValidate.Bottom() )
373 rValidate.SetBottom( rValidate.Top() );
374 break;
375 case 6:
376 if( rValidate.Top() > rValidate.Bottom() )
377 rValidate.SetBottom( rValidate.Top() );
378 if( rValidate.Left() > rValidate.Right() )
379 rValidate.SetLeft( rValidate.Right() );
380 break;
381 case 7:
382 if( rValidate.Left() > rValidate.Right() )
383 rValidate.SetLeft( rValidate.Right() );
384 break;
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()
397 |* Description
398 *************************************************************************/
399 bool SvResizeHelper::SelectRelease( vcl::Window * pWin, const Point & rPos,
400 tools::Rectangle & rOutPosSize )
402 if( -1 != nGrab )
404 rOutPosSize = GetTrackRectPixel( rPos );
405 rOutPosSize.Normalize();
406 nGrab = -1;
407 pWin->ReleaseMouse();
408 pWin->HideTracking();
409 return true;
411 return false;
414 /*************************************************************************
415 |* SvResizeHelper::Release()
417 |* Description
418 *************************************************************************/
419 void SvResizeHelper::Release( vcl::Window * pWin )
421 if( nGrab != -1 )
423 pWin->ReleaseMouse();
424 pWin->HideTracking();
425 nGrab = -1;
429 /*************************************************************************
430 |* SvResizeWindow::SvResizeWindow()
432 |* Description
433 *************************************************************************/
434 SvResizeWindow::SvResizeWindow
436 vcl::Window * pParent,
437 VCLXHatchWindow* pWrapper
439 : Window( pParent, WB_CLIPCHILDREN )
440 , m_aOldPointer(PointerStyle::Arrow)
441 , m_nMoveGrab( -1 )
442 , m_bActive( false )
443 , m_pWrapper( pWrapper )
445 OSL_ENSURE( pParent != nullptr && pWrapper != nullptr, "Wrong initialization of hatch window!" );
446 SetBackground();
447 SetAccessibleRole( css::accessibility::AccessibleRole::EMBEDDED_OBJECT );
448 m_aResizer.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
451 /*************************************************************************
452 |* SvResizeWindow::SetHatchBorderPixel()
454 |* Description
455 *************************************************************************/
456 void SvResizeWindow::SetHatchBorderPixel( const Size & rSize )
458 m_aResizer.SetBorderPixel( rSize );
461 /*************************************************************************
462 |* SvResizeWindow::SelectMouse()
464 |* Description
465 *************************************************************************/
466 void SvResizeWindow::SelectMouse( const Point & rPos )
468 short nGrab = m_aResizer.SelectMove( this, rPos );
469 if( nGrab >= 4 )
470 nGrab -= 4;
471 if( m_nMoveGrab == nGrab )
472 return;
474 // Pointer did change
475 if( -1 == nGrab )
476 SetPointer( m_aOldPointer );
477 else
479 PointerStyle aStyle = PointerStyle::Move;
480 if( nGrab == 3 )
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 );
493 else
494 SetPointer( aStyle );
496 m_nMoveGrab = nGrab;
499 /*************************************************************************
500 |* SvResizeWindow::MouseButtonDown()
502 |* Description
503 *************************************************************************/
504 void SvResizeWindow::MouseButtonDown( const MouseEvent & rEvt )
506 if( m_aResizer.SelectBegin( this, rEvt.GetPosPixel() ) )
507 SelectMouse( rEvt.GetPosPixel() );
510 /*************************************************************************
511 |* SvResizeWindow::MouseMove()
513 |* Description
514 *************************************************************************/
515 void SvResizeWindow::MouseMove( const MouseEvent & rEvt )
517 if( m_aResizer.GetGrab() == -1 )
518 SelectMouse( rEvt.GetPosPixel() );
519 else
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 );
530 SelectMouse( aPos );
534 /*************************************************************************
535 |* SvResizeWindow::MouseButtonUp()
537 |* Description
538 *************************************************************************/
539 void SvResizeWindow::MouseButtonUp( const MouseEvent & rEvt )
541 if( m_aResizer.GetGrab() == -1 )
542 return;
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 ) )
555 m_nMoveGrab = -1;
556 SetPointer( m_aOldPointer );
557 m_pWrapper->RequestObjAreaPixel( aRect );
561 /*************************************************************************
562 |* SvResizeWindow::KeyEvent()
564 |* Description
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()
578 |* Description
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()
590 |* Description
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 )
601 m_bActive = true;
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);
613 if ( !bHasFocus )
615 m_bActive = false;
616 m_pWrapper->Deactivated();
620 return Window::EventNotify(rEvt);
623 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */