1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
31 
32 #include <vcl/svapp.hxx>
33 
34 #include <ipwin.hxx>
35 #include <hatchwindow.hxx>
36 
37 /************************************************************************/
38 /*************************************************************************
39 |*    SvResizeHelper::SvResizeHelper()
40 |*
41 |*    Beschreibung
42 *************************************************************************/
43 SvResizeHelper::SvResizeHelper()
44 	: aBorder( 5, 5 )
45 	, nGrab( -1 )
46 	, bResizeable( sal_True )
47 {
48 }
49 
50 /*************************************************************************
51 |*    SvResizeHelper::FillHandleRects()
52 |*
53 |*    Beschreibung: Die acht Handles zum vergroessern
54 *************************************************************************/
55 void SvResizeHelper::FillHandleRectsPixel( Rectangle aRects[ 8 ] ) const
56 {
57 	// nur wegen EMPTY_RECT
58 	Point aBottomRight = aOuter.BottomRight();
59 
60 	// Links Oben
61 	aRects[ 0 ] = Rectangle( aOuter.TopLeft(), aBorder );
62 	// Oben Mitte
63 	aRects[ 1 ] = Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
64 									aOuter.Top() ),
65 							aBorder );
66 	// Oben Rechts
67 	aRects[ 2 ] = Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
68 									aOuter.Top() ),
69 							aBorder );
70 	// Mitte Rechts
71 	aRects[ 3 ] = Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
72 									aOuter.Center().Y() - aBorder.Height() / 2 ),
73 							aBorder );
74 	// Unten Rechts
75 	aRects[ 4 ] = Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
76 									aBottomRight.Y() - aBorder.Height() +1 ),
77 							aBorder );
78 	// Mitte Unten
79 	aRects[ 5 ] = Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
80 									aBottomRight.Y() - aBorder.Height() +1),
81 							aBorder );
82 	// Links Unten
83 	aRects[ 6 ] = Rectangle( Point( aOuter.Left(),
84 									aBottomRight.Y() - aBorder.Height() +1),
85 							aBorder );
86 	// Mitte Links
87 	aRects[ 7 ] = Rectangle( Point( aOuter.Left(),
88 									aOuter.Center().Y() - aBorder.Height() / 2 ),
89 							aBorder );
90 }
91 
92 /*************************************************************************
93 |*    SvResizeHelper::FillMoveRectsPixel()
94 |*
95 |*    Beschreibung: Die vier Kanten werden berechnet
96 *************************************************************************/
97 void SvResizeHelper::FillMoveRectsPixel( Rectangle aRects[ 4 ] ) const
98 {
99 	// Oben
100 	aRects[ 0 ] = aOuter;
101 	aRects[ 0 ].Bottom() = aRects[ 0 ].Top() + aBorder.Height() -1;
102 	// Rechts
103 	aRects[ 1 ] = aOuter;
104 	aRects[ 1 ].Left() = aRects[ 1 ].Right() - aBorder.Width() -1;
105 	//Unten
106 	aRects[ 2 ] = aOuter;
107 	aRects[ 2 ].Top() = aRects[ 2 ].Bottom() - aBorder.Height() -1;
108 	//Links
109 	aRects[ 3 ] = aOuter;
110 	aRects[ 3 ].Right() = aRects[ 3 ].Left() + aBorder.Width() -1;
111 }
112 
113 /*************************************************************************
114 |*    SvResizeHelper::Draw()
115 |*
116 |*    Beschreibung
117 *************************************************************************/
118 void SvResizeHelper::Draw( OutputDevice * pDev )
119 {
120 	pDev->Push();
121 	pDev->SetMapMode( MapMode() );
122 	Color aColBlack;
123 	Color aFillColor( COL_LIGHTGRAY );
124 
125 	pDev->SetFillColor( aFillColor );
126 	pDev->SetLineColor();
127 
128 	Rectangle   aMoveRects[ 4 ];
129 	FillMoveRectsPixel( aMoveRects );
130 	sal_uInt16 i;
131 	for( i = 0; i < 4; i++ )
132 		pDev->DrawRect( aMoveRects[ i ] );
133 	if( bResizeable )
134 	{
135 		// Handles malen
136 		pDev->SetFillColor( aColBlack );
137 		Rectangle   aRects[ 8 ];
138 		FillHandleRectsPixel( aRects );
139 		for( i = 0; i < 8; i++ )
140 			pDev->DrawRect( aRects[ i ] );
141 	}
142 	pDev->Pop();
143 }
144 
145 /*************************************************************************
146 |*    SvResizeHelper::InvalidateBorder()
147 |*
148 |*    Beschreibung
149 *************************************************************************/
150 void SvResizeHelper::InvalidateBorder( Window * pWin )
151 {
152 	Rectangle   aMoveRects[ 4 ];
153 	FillMoveRectsPixel( aMoveRects );
154 	for( sal_uInt16 i = 0; i < 4; i++ )
155 		pWin->Invalidate( aMoveRects[ i ] );
156 }
157 
158 /*************************************************************************
159 |*    SvResizeHelper::SelectBegin()
160 |*
161 |*    Beschreibung
162 *************************************************************************/
163 sal_Bool SvResizeHelper::SelectBegin( Window * pWin, const Point & rPos )
164 {
165 	if( -1 == nGrab )
166 	{
167 		nGrab = SelectMove( pWin, rPos );
168 		if( -1 != nGrab )
169 		{
170 			aSelPos = rPos; // Start-Position merken
171 			pWin->CaptureMouse();
172 			return sal_True;
173 		}
174 	}
175 	return sal_False;
176 }
177 
178 /*************************************************************************
179 |*    SvResizeHelper::SelectMove()
180 |*
181 |*    Beschreibung
182 *************************************************************************/
183 short SvResizeHelper::SelectMove( Window * pWin, const Point & rPos )
184 {
185 	if( -1 == nGrab )
186 	{
187 		if( bResizeable )
188 		{
189 			Rectangle aRects[ 8 ];
190 			FillHandleRectsPixel( aRects );
191 			for( sal_uInt16 i = 0; i < 8; i++ )
192 				if( aRects[ i ].IsInside( rPos ) )
193 					return i;
194 		}
195 		// Move-Rect ueberlappen Handles
196 		Rectangle aMoveRects[ 4 ];
197 		FillMoveRectsPixel( aMoveRects );
198 		for( sal_uInt16 i = 0; i < 4; i++ )
199 			if( aMoveRects[ i ].IsInside( rPos ) )
200 				return 8;
201 	}
202 	else
203 	{
204 		Rectangle aRect( GetTrackRectPixel( rPos ) );
205 		aRect.SetSize( pWin->PixelToLogic( aRect.GetSize() ) );
206 		aRect.SetPos( pWin->PixelToLogic( aRect.TopLeft() ) );
207 		pWin->ShowTracking( aRect );
208 	}
209 	return nGrab;
210 }
211 
212 Point SvResizeHelper::GetTrackPosPixel( const Rectangle & rRect ) const
213 {
214 	// wie das Rechteck zurueckkommt ist egal, es zaehlt welches Handle
215 	// initial angefasst wurde
216 	Point aPos;
217 	Rectangle aRect( rRect );
218 	aRect.Justify();
219 	// nur wegen EMPTY_RECT
220 	Point aBR = aOuter.BottomRight();
221 	Point aTR = aOuter.TopRight();
222 	Point aBL = aOuter.BottomLeft();
223 	switch( nGrab )
224 	{
225 		case 0:
226 			aPos = aRect.TopLeft() - aOuter.TopLeft();
227 			break;
228 		case 1:
229 			aPos.Y() =  aRect.Top() - aOuter.Top();
230 			break;
231 		case 2:
232 			aPos =  aRect.TopRight() - aTR;
233 			break;
234 		case 3:
235 			aPos.X() = aRect.Right() - aTR.X();
236 			break;
237 		case 4:
238 			aPos =  aRect.BottomRight() - aBR;
239 			break;
240 		case 5:
241 			aPos.Y() = aRect.Bottom() - aBR.Y();
242 			break;
243 		case 6:
244 			aPos =  aRect.BottomLeft() - aBL;
245 			break;
246 		case 7:
247 			aPos.X() = aRect.Left() - aOuter.Left();
248 			break;
249 		case 8:
250 			aPos = aRect.TopLeft() - aOuter.TopLeft();
251 			break;
252 	}
253 	return aPos += aSelPos;
254 }
255 
256 /*************************************************************************
257 |*    SvResizeHelper::GetTrackRectPixel()
258 |*
259 |*    Beschreibung
260 *************************************************************************/
261 Rectangle SvResizeHelper::GetTrackRectPixel( const Point & rTrackPos ) const
262 {
263 	Rectangle aTrackRect;
264 	if( -1 != nGrab )
265 	{
266 		Point aDiff = rTrackPos - aSelPos;
267 		aTrackRect = aOuter;
268 		Point aBR = aOuter.BottomRight();
269 		switch( nGrab )
270 		{
271 			case 0:
272 				aTrackRect.Top() += aDiff.Y();
273 				aTrackRect.Left() += aDiff.X();
274 				break;
275 			case 1:
276 				aTrackRect.Top() += aDiff.Y();
277 				break;
278 			case 2:
279 				aTrackRect.Top() += aDiff.Y();
280 				aTrackRect.Right() = aBR.X() + aDiff.X();
281 				break;
282 			case 3:
283 				aTrackRect.Right() = aBR.X() + aDiff.X();
284 				break;
285 			case 4:
286 				aTrackRect.Bottom() = aBR.Y() + aDiff.Y();
287 				aTrackRect.Right() = aBR.X() + aDiff.X();
288 				break;
289 			case 5:
290 				aTrackRect.Bottom() = aBR.Y() + aDiff.Y();
291 				break;
292 			case 6:
293 				aTrackRect.Bottom() = aBR.Y() + aDiff.Y();
294 				aTrackRect.Left() += aDiff.X();
295 				break;
296 			case 7:
297 				aTrackRect.Left() += aDiff.X();
298 				break;
299 			case 8:
300                 if( Application::GetSettings().GetLayoutRTL() )
301                     aDiff.X() = -aDiff.X(); // workaround for move in RTL mode
302 				aTrackRect.SetPos( aTrackRect.TopLeft() + aDiff );
303 				break;
304 /*
305 			case 0:
306 				aTrackRect = Rectangle( rTrackPos, aOuter.BottomRight() );
307 				break;
308 			case 1:
309 				aTrackRect = Rectangle( Point( aOuter.Left(), rTrackPos.Y() ),
310 										 aOuter.BottomRight() );
311 				break;
312 			case 2:
313 				aTrackRect = Rectangle( rTrackPos, aOuter.BottomLeft() );
314 				break;
315 			case 3:
316 				aTrackRect = Rectangle( Point( rTrackPos.X(), aOuter.Top() ),
317 										 aOuter.BottomLeft() );
318 				break;
319 			case 4:
320 				aTrackRect = Rectangle( rTrackPos, aOuter.TopLeft() );
321 				break;
322 			case 5:
323 				aTrackRect = Rectangle( aOuter.TopLeft(),
324 									 Point( aOuter.Right(), rTrackPos.Y() ) );
325 				break;
326 			case 6:
327 				aTrackRect = Rectangle( aOuter.TopRight(), rTrackPos );
328 				break;
329 			case 7:
330 				aTrackRect = Rectangle( Point( rTrackPos.X(), aOuter.Top() ),
331 										 aOuter.BottomRight() );
332 				break;
333 			case 8:
334 				aTrackRect = Rectangle( aOuter.TopLeft() + rTrackPos - aSelPos,
335 										aOuter.GetSize() );
336 				break;
337 */
338 		}
339 	}
340 	return aTrackRect;
341 }
342 
343 void SvResizeHelper::ValidateRect( Rectangle & rValidate ) const
344 {
345 	switch( nGrab )
346 	{
347 		case 0:
348 			if( rValidate.Top() > rValidate.Bottom() )
349 			{
350 				rValidate.Top() = rValidate.Bottom();
351 				rValidate.Bottom() = RECT_EMPTY;
352 			}
353 			if( rValidate.Left() > rValidate.Right() )
354 			{
355 				rValidate.Left() = rValidate.Right();
356 				rValidate.Right() = RECT_EMPTY;
357 			}
358 			break;
359 		case 1:
360 			if( rValidate.Top() > rValidate.Bottom() )
361 			{
362 				rValidate.Top() = rValidate.Bottom();
363 				rValidate.Bottom() = RECT_EMPTY;
364 			}
365 			break;
366 		case 2:
367 			if( rValidate.Top() > rValidate.Bottom() )
368 			{
369 				rValidate.Top() = rValidate.Bottom();
370 				rValidate.Bottom() = RECT_EMPTY;
371 			}
372 			if( rValidate.Left() > rValidate.Right() )
373 				rValidate.Right() = RECT_EMPTY;
374 			break;
375 		case 3:
376 			if( rValidate.Left() > rValidate.Right() )
377 				rValidate.Right() = RECT_EMPTY;
378 			break;
379 		case 4:
380 			if( rValidate.Top() > rValidate.Bottom() )
381 				rValidate.Bottom() = RECT_EMPTY;
382 			if( rValidate.Left() > rValidate.Right() )
383 				rValidate.Right() = RECT_EMPTY;
384 			break;
385 		case 5:
386 			if( rValidate.Top() > rValidate.Bottom() )
387 				rValidate.Bottom() = RECT_EMPTY;
388 			break;
389 		case 6:
390 			if( rValidate.Top() > rValidate.Bottom() )
391 				rValidate.Bottom() = RECT_EMPTY;
392 			if( rValidate.Left() > rValidate.Right() )
393 			{
394 				rValidate.Left() = rValidate.Right();
395 				rValidate.Right() = RECT_EMPTY;
396 			}
397 			break;
398 		case 7:
399 			if( rValidate.Left() > rValidate.Right() )
400 			{
401 				rValidate.Left() = rValidate.Right();
402 				rValidate.Right() = RECT_EMPTY;
403 			}
404 			break;
405 	}
406 	if( rValidate.Right() == RECT_EMPTY )
407 		rValidate.Right() = rValidate.Left();
408 	if( rValidate.Bottom() == RECT_EMPTY )
409 		rValidate.Bottom() = rValidate.Top();
410 
411 	// Mindestgr"osse 5 x 5
412 	if( rValidate.Left() + 5 > rValidate.Right() )
413 		rValidate.Right() = rValidate.Left() +5;
414 	if( rValidate.Top() + 5 > rValidate.Bottom() )
415 		rValidate.Bottom() = rValidate.Top() +5;
416 }
417 
418 /*************************************************************************
419 |*    SvResizeHelper::SelectRelease()
420 |*
421 |*    Beschreibung
422 *************************************************************************/
423 sal_Bool SvResizeHelper::SelectRelease( Window * pWin, const Point & rPos,
424 									Rectangle & rOutPosSize )
425 {
426 	if( -1 != nGrab )
427 	{
428 		rOutPosSize = GetTrackRectPixel( rPos );
429 		rOutPosSize.Justify();
430 		nGrab = -1;
431 		pWin->ReleaseMouse();
432 		pWin->HideTracking();
433 		return sal_True;
434 	}
435 	return sal_False;
436 }
437 
438 /*************************************************************************
439 |*    SvResizeHelper::Release()
440 |*
441 |*    Beschreibung
442 *************************************************************************/
443 void SvResizeHelper::Release( Window * pWin )
444 {
445 	if( nGrab != -1 )
446 	{
447 		pWin->ReleaseMouse();
448 		pWin->HideTracking();
449 		nGrab = -1;
450 	}
451 }
452 
453 /*************************************************************************
454 |*    SvResizeWindow::SvResizeWindow()
455 |*
456 |*    Beschreibung
457 *************************************************************************/
458 SvResizeWindow::SvResizeWindow
459 (
460 	Window * pParent,
461 	VCLXHatchWindow* pWrapper
462 )
463 	: Window( pParent, WB_CLIPCHILDREN )
464 	, m_nMoveGrab( -1 )
465     , m_bActive( sal_False )
466 	, m_pWrapper( pWrapper )
467 {
468 	OSL_ENSURE( pParent != NULL && pWrapper != NULL, "Wrong initialization of hatch window!\n" );
469 	SetBackground();
470 	SetAccessibleRole( ::com::sun::star::accessibility::AccessibleRole::EMBEDDED_OBJECT );
471 	m_aResizer.SetOuterRectPixel( Rectangle( Point(), GetOutputSizePixel() ) );
472 }
473 
474 /*************************************************************************
475 |*    SvResizeWindow::SetHatchBorderPixel()
476 |*
477 |*    Beschreibung
478 *************************************************************************/
479 void SvResizeWindow::SetHatchBorderPixel( const Size & rSize )
480 {
481 	 m_aResizer.SetBorderPixel( rSize );
482 }
483 
484 /*************************************************************************
485 |*    SvResizeWindow::SelectMouse()
486 |*
487 |*    Beschreibung
488 *************************************************************************/
489 void SvResizeWindow::SelectMouse( const Point & rPos )
490 {
491 	short nGrab = m_aResizer.SelectMove( this, rPos );
492 	if( nGrab >= 4 )
493 		nGrab -= 4;
494 	if( m_nMoveGrab != nGrab )
495 	{ // Pointer hat sich geaendert
496 		if( -1 == nGrab )
497 			SetPointer( m_aOldPointer );
498 		else
499 		{
500 			PointerStyle aStyle = POINTER_MOVE;
501 			if( nGrab == 3 )
502 				aStyle = POINTER_ESIZE;
503 			else if( nGrab == 2 )
504 				aStyle = POINTER_NESIZE;
505 			else if( nGrab == 1 )
506 				aStyle = POINTER_SSIZE;
507 			else if( nGrab == 0 )
508 				aStyle = POINTER_SESIZE;
509 			if( m_nMoveGrab == -1 ) // das erste mal
510 			{
511 				m_aOldPointer = GetPointer();
512 				SetPointer( Pointer( aStyle ) );
513 			}
514 			else
515 				SetPointer( Pointer( aStyle ) );
516 		}
517 		m_nMoveGrab = nGrab;
518 	}
519 }
520 
521 /*************************************************************************
522 |*    SvResizeWindow::MouseButtonDown()
523 |*
524 |*    Beschreibung
525 *************************************************************************/
526 void SvResizeWindow::MouseButtonDown( const MouseEvent & rEvt )
527 {
528 	if( m_aResizer.SelectBegin( this, rEvt.GetPosPixel() ) )
529 		SelectMouse( rEvt.GetPosPixel() );
530 }
531 
532 /*************************************************************************
533 |*    SvResizeWindow::MouseMove()
534 |*
535 |*    Beschreibung
536 *************************************************************************/
537 void SvResizeWindow::MouseMove( const MouseEvent & rEvt )
538 {
539 	if( m_aResizer.GetGrab() == -1 )
540 		SelectMouse( rEvt.GetPosPixel() );
541 	else
542 	{
543 		Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) );
544 		Point aDiff = GetPosPixel();
545 		aRect.SetPos( aRect.TopLeft() + aDiff );
546 		m_aResizer.ValidateRect( aRect );
547 
548 		m_pWrapper->QueryObjAreaPixel( aRect );
549 		aRect.SetPos( aRect.TopLeft() - aDiff );
550 		Point aPos = m_aResizer.GetTrackPosPixel( aRect );
551 
552 		SelectMouse( aPos );
553 	}
554 }
555 
556 /*************************************************************************
557 |*    SvResizeWindow::MouseButtonUp()
558 |*
559 |*    Beschreibung
560 *************************************************************************/
561 void SvResizeWindow::MouseButtonUp( const MouseEvent & rEvt )
562 {
563 	if( m_aResizer.GetGrab() != -1 )
564 	{
565 		Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) );
566 		Point aDiff = GetPosPixel();
567 		aRect.SetPos( aRect.TopLeft() + aDiff );
568 		// aRect -= GetAllBorderPixel();
569 		m_aResizer.ValidateRect( aRect );
570 
571 		m_pWrapper->QueryObjAreaPixel( aRect );
572 
573 		Rectangle aOutRect;
574 		if( m_aResizer.SelectRelease( this, rEvt.GetPosPixel(), aOutRect ) )
575 		{
576 			m_nMoveGrab = -1;
577 			SetPointer( m_aOldPointer );
578 			m_pWrapper->RequestObjAreaPixel( aRect );
579 		}
580 	}
581 }
582 
583 /*************************************************************************
584 |*    SvResizeWindow::KeyEvent()
585 |*
586 |*    Beschreibung
587 *************************************************************************/
588 void SvResizeWindow::KeyInput( const KeyEvent & rEvt )
589 {
590 	if( rEvt.GetKeyCode().GetCode() == KEY_ESCAPE )
591 	{
592 		m_aResizer.Release( this );
593 		m_pWrapper->InplaceDeactivate();
594 	}
595 }
596 
597 /*************************************************************************
598 |*    SvResizeWindow::Resize()
599 |*
600 |*    Beschreibung
601 *************************************************************************/
602 void SvResizeWindow::Resize()
603 {
604 	m_aResizer.InvalidateBorder( this ); // alten Bereich
605 	m_aResizer.SetOuterRectPixel( Rectangle( Point(), GetOutputSizePixel() ) );
606 	m_aResizer.InvalidateBorder( this ); // neuen Bereich
607 }
608 
609 /*************************************************************************
610 |*    SvResizeWindow::Paint()
611 |*
612 |*    Beschreibung
613 *************************************************************************/
614 void SvResizeWindow::Paint( const Rectangle & /*rRect*/ )
615 {
616 	m_aResizer.Draw( this );
617 }
618 
619 long SvResizeWindow::PreNotify( NotifyEvent& rEvt )
620 {
621     if ( rEvt.GetType() == EVENT_GETFOCUS && !m_bActive )
622     {
623         m_bActive = sal_True;
624         m_pWrapper->Activated();
625     }
626 
627     return Window::PreNotify(rEvt);
628 }
629 
630 long SvResizeWindow::Notify( NotifyEvent& rEvt )
631 {
632     if ( rEvt.GetType() == EVENT_LOSEFOCUS && m_bActive )
633     {
634         sal_Bool bHasFocus = HasChildPathFocus(sal_True);
635         if ( !bHasFocus )
636         {
637             m_bActive = sal_False;
638             m_pWrapper->Deactivated();
639         }
640     }
641 
642     return Window::Notify(rEvt);
643 }
644 
645