xref: /aoo41x/main/vcl/source/window/cursor.cxx (revision cdf0e10c)
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_vcl.hxx"
30 
31 #include <vcl/svapp.hxx>
32 #include <vcl/timer.hxx>
33 #include <vcl/settings.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/cursor.hxx>
36 
37 #include <window.h>
38 
39 #include <tools/poly.hxx>
40 
41 
42 // =======================================================================
43 
44 struct ImplCursorData
45 {
46 	AutoTimer		maTimer;			// Timer
47 	Point			maPixPos;			// Pixel-Position
48 	Point			maPixRotOff;		// Pixel-Offset-Position
49 	Size			maPixSize;			// Pixel-Size
50 	long			mnPixSlant; 		// Pixel-Slant
51 	short			mnOrientation;		// Pixel-Orientation
52 	unsigned char	mnDirection;		// indicates writing direction
53 	sal_uInt16			mnStyle;			// Cursor-Style
54 	sal_Bool			mbCurVisible;		// Ist Cursor aktuell sichtbar
55 	Window* 		mpWindow;			// Zugeordnetes Windows
56 };
57 
58 // =======================================================================
59 
60 static void ImplCursorInvert( ImplCursorData* pData )
61 {
62 	Window* pWindow  = pData->mpWindow;
63 	sal_Bool	bMapMode = pWindow->IsMapModeEnabled();
64 	pWindow->EnableMapMode( sal_False );
65 	sal_uInt16 nInvertStyle;
66 	if ( pData->mnStyle & CURSOR_SHADOW )
67 		nInvertStyle = INVERT_50;
68 	else
69 		nInvertStyle = 0;
70 
71 	Rectangle aRect( pData->maPixPos, pData->maPixSize );
72 	if ( pData->mnDirection || pData->mnOrientation || pData->mnPixSlant )
73 	{
74 		Polygon aPoly( aRect );
75         if( aPoly.GetSize() == 5 )
76         {
77             aPoly[1].X() += 1;  // include the right border
78             aPoly[2].X() += 1;
79 		    if ( pData->mnPixSlant )
80 		    {
81 			    Point aPoint = aPoly.GetPoint( 0 );
82 			    aPoint.X() += pData->mnPixSlant;
83 			    aPoly.SetPoint( aPoint, 0 );
84 			    aPoly.SetPoint( aPoint, 4 );
85 			    aPoint = aPoly.GetPoint( 1 );
86 			    aPoint.X() += pData->mnPixSlant;
87 			    aPoly.SetPoint( aPoint, 1 );
88 		    }
89 
90             // apply direction flag after slant to use the correct shape
91 		    if ( pData->mnDirection )
92             {
93                 Point pAry[7];
94                 int delta = 3*aRect.getWidth()+1;
95                 if( pData->mnDirection == CURSOR_DIRECTION_LTR )
96                 {
97                     // left-to-right
98                     pAry[0] = aPoly.GetPoint( 0 );
99                     pAry[1] = aPoly.GetPoint( 1 );
100                     pAry[2] = pAry[1];
101                     pAry[2].X() += delta;
102                     pAry[3] =  pAry[1];
103                     pAry[3].Y() += delta;
104                     pAry[4] = aPoly.GetPoint( 2 );
105                     pAry[5] = aPoly.GetPoint( 3 );
106                     pAry[6] = aPoly.GetPoint( 4 );
107                 }
108                 else if( pData->mnDirection == CURSOR_DIRECTION_RTL )
109                 {
110                     // right-to-left
111                     pAry[0] = aPoly.GetPoint( 0 );
112                     pAry[1] = aPoly.GetPoint( 1 );
113                     pAry[2] = aPoly.GetPoint( 2 );
114                     pAry[3] = aPoly.GetPoint( 3 );
115                     pAry[4] = pAry[0];
116                     pAry[4].Y() += delta;
117                     pAry[5] =  pAry[0];
118                     pAry[5].X() -= delta;
119                     pAry[6] = aPoly.GetPoint( 4 );
120                 }
121                 aPoly = Polygon( 7, pAry);
122             }
123 
124 		    if ( pData->mnOrientation )
125 			    aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
126 		    pWindow->Invert( aPoly, nInvertStyle );
127         }
128 	}
129 	else
130 		pWindow->Invert( aRect, nInvertStyle );
131 	pWindow->EnableMapMode( bMapMode );
132 }
133 
134 // -----------------------------------------------------------------------
135 
136 void Cursor::ImplDraw()
137 {
138 	if ( mpData && mpData->mpWindow && !mpData->mbCurVisible )
139 	{
140 		Window* pWindow 		= mpData->mpWindow;
141 		mpData->maPixPos		= pWindow->LogicToPixel( maPos );
142 		mpData->maPixSize		= pWindow->LogicToPixel( maSize );
143 		mpData->mnPixSlant		= pWindow->LogicToPixel( Size( mnSlant, 0 ) ).Width();
144 		mpData->mnOrientation	= mnOrientation;
145 		mpData->mnDirection	    = mnDirection;
146 		long nOffsetY			= pWindow->LogicToPixel( Size( 0, mnOffsetY ) ).Height();
147 
148 		// Position um den Offset korrigieren
149 		mpData->maPixPos.Y() -= nOffsetY;
150 		mpData->maPixRotOff = mpData->maPixPos;
151 		mpData->maPixRotOff.Y() += nOffsetY;
152 
153 		// Wenn groesse 0 ist, nehmen wir die breite, die in den
154 		// Settings eingestellt ist
155 		if ( !mpData->maPixSize.Width() )
156 			mpData->maPixSize.Width() = pWindow->GetSettings().GetStyleSettings().GetCursorSize();
157 
158 		// Ausgabeflaeche berechnen und ausgeben
159 		ImplCursorInvert( mpData );
160 		mpData->mbCurVisible = sal_True;
161 	}
162 }
163 
164 // -----------------------------------------------------------------------
165 
166 void Cursor::ImplRestore()
167 {
168 	if ( mpData && mpData->mbCurVisible )
169 	{
170 		ImplCursorInvert( mpData );
171 		mpData->mbCurVisible = sal_False;
172 	}
173 }
174 
175 // -----------------------------------------------------------------------
176 
177 void Cursor::ImplShow( bool bDrawDirect, bool bRestore )
178 {
179 	if ( mbVisible )
180 	{
181 		Window* pWindow;
182 		if ( mpWindow )
183 			pWindow = mpWindow;
184 		else
185 		{
186 			// Gibt es ein aktives Fenster und ist der Cursor in dieses Fenster
187 			// selektiert, dann zeige den Cursor an
188 			pWindow = Application::GetFocusWindow();
189 			if ( !pWindow || (pWindow->mpWindowImpl->mpCursor != this) || pWindow->mpWindowImpl->mbInPaint
190 				|| !pWindow->mpWindowImpl->mpFrameData->mbHasFocus )
191 				pWindow = NULL;
192 		}
193 
194 		if ( pWindow )
195 		{
196 			if ( !mpData )
197 			{
198 				mpData = new ImplCursorData;
199 				mpData->mbCurVisible = sal_False;
200 				mpData->maTimer.SetTimeoutHdl( LINK( this, Cursor, ImplTimerHdl ) );
201 			}
202 
203 			mpData->mpWindow	= pWindow;
204 			mpData->mnStyle 	= mnStyle;
205 			if ( bDrawDirect || bRestore )
206 				ImplDraw();
207 
208 			if ( !mpWindow && ! ( ! bDrawDirect && mpData->maTimer.IsActive()) )
209 			{
210 				mpData->maTimer.SetTimeout( pWindow->GetSettings().GetStyleSettings().GetCursorBlinkTime() );
211 				if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
212 					mpData->maTimer.Start();
213 				else if ( !mpData->mbCurVisible )
214 					ImplDraw();
215 			}
216 		}
217 	}
218 }
219 
220 // -----------------------------------------------------------------------
221 
222 bool Cursor::ImplHide( bool i_bStopTimer )
223 {
224     bool bWasCurVisible = false;
225 	if ( mpData && mpData->mpWindow )
226 	{
227 	    bWasCurVisible = mpData->mbCurVisible;
228 		if ( mpData->mbCurVisible )
229 			ImplRestore();
230 	}
231 
232     if( mpData && i_bStopTimer )
233     {
234         mpData->maTimer.Stop();
235         mpData->mpWindow = NULL;
236     }
237 
238 	return bWasCurVisible;
239 }
240 
241 // -----------------------------------------------------------------------
242 
243 void Cursor::ImplNew()
244 {
245 	if ( mbVisible && mpData && mpData->mpWindow )
246 	{
247 		if ( mpData->mbCurVisible )
248 			ImplRestore();
249 
250 		ImplDraw();
251 		if ( !mpWindow )
252 		{
253 			if ( mpData->maTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME )
254 				mpData->maTimer.Start();
255 		}
256 	}
257 }
258 
259 // -----------------------------------------------------------------------
260 
261 IMPL_LINK( Cursor, ImplTimerHdl, AutoTimer*, EMPTYARG )
262 {
263 	if ( mpData->mbCurVisible )
264 		ImplRestore();
265 	else
266 		ImplDraw();
267 	return 0;
268 }
269 
270 // =======================================================================
271 
272 Cursor::Cursor()
273 {
274 	mpData			= NULL;
275 	mpWindow		= NULL;
276 	mnSlant 		= 0;
277 	mnOffsetY		= 0;
278 	mnOrientation	= 0;
279 	mnDirection 	= 0;
280 	mnStyle 		= 0;
281 	mbVisible		= sal_False;
282 }
283 
284 // -----------------------------------------------------------------------
285 
286 Cursor::Cursor( const Cursor& rCursor ) :
287 	maSize( rCursor.maSize ),
288 	maPos( rCursor.maPos )
289 {
290 	mpData			= NULL;
291 	mpWindow		= NULL;
292 	mnSlant 		= rCursor.mnSlant;
293 	mnOrientation	= rCursor.mnOrientation;
294 	mnDirection 	= rCursor.mnDirection;
295 	mnStyle 		= 0;
296 	mbVisible		= rCursor.mbVisible;
297 }
298 
299 // -----------------------------------------------------------------------
300 
301 Cursor::~Cursor()
302 {
303 	if ( mpData )
304 	{
305 		if ( mpData->mbCurVisible )
306 			ImplRestore();
307 
308 		delete mpData;
309 	}
310 }
311 
312 // -----------------------------------------------------------------------
313 
314 void Cursor::SetStyle( sal_uInt16 nStyle )
315 {
316 	if ( mnStyle != nStyle )
317 	{
318 		mnStyle = nStyle;
319 		ImplNew();
320 	}
321 }
322 
323 // -----------------------------------------------------------------------
324 
325 void Cursor::Show()
326 {
327 	if ( !mbVisible )
328 	{
329 		mbVisible = sal_True;
330 		ImplShow();
331 	}
332 }
333 
334 // -----------------------------------------------------------------------
335 
336 void Cursor::Hide()
337 {
338 	if ( mbVisible )
339 	{
340 		mbVisible = sal_False;
341 		ImplHide( true );
342 	}
343 }
344 
345 // -----------------------------------------------------------------------
346 
347 void Cursor::SetWindow( Window* pWindow )
348 {
349 	if ( mpWindow != pWindow )
350 	{
351 		mpWindow = pWindow;
352 		ImplNew();
353 	}
354 }
355 
356 // -----------------------------------------------------------------------
357 
358 void Cursor::SetPos( const Point& rPoint )
359 {
360 	if ( maPos != rPoint )
361 	{
362 		maPos = rPoint;
363 		ImplNew();
364 	}
365 }
366 
367 // -----------------------------------------------------------------------
368 
369 void Cursor::SetOffsetY( long nNewOffsetY )
370 {
371 	if ( mnOffsetY != nNewOffsetY )
372 	{
373 		mnOffsetY = nNewOffsetY;
374 		ImplNew();
375 	}
376 }
377 
378 // -----------------------------------------------------------------------
379 
380 void Cursor::SetSize( const Size& rSize )
381 {
382 	if ( maSize != rSize )
383 	{
384 		maSize = rSize;
385 		ImplNew();
386 	}
387 }
388 
389 // -----------------------------------------------------------------------
390 
391 void Cursor::SetWidth( long nNewWidth )
392 {
393 	if ( maSize.Width() != nNewWidth )
394 	{
395 		maSize.Width() = nNewWidth;
396 		ImplNew();
397 	}
398 }
399 
400 // -----------------------------------------------------------------------
401 
402 void Cursor::SetHeight( long nNewHeight )
403 {
404 	if ( maSize.Height() != nNewHeight )
405 	{
406 		maSize.Height() = nNewHeight;
407 		ImplNew();
408 	}
409 }
410 
411 // -----------------------------------------------------------------------
412 
413 void Cursor::SetSlant( long nNewSlant )
414 {
415 	if ( mnSlant != nNewSlant )
416 	{
417 		mnSlant = nNewSlant;
418 		ImplNew();
419 	}
420 }
421 
422 // -----------------------------------------------------------------------
423 
424 void Cursor::SetOrientation( short nNewOrientation )
425 {
426 	if ( mnOrientation != nNewOrientation )
427 	{
428 		mnOrientation = nNewOrientation;
429 		ImplNew();
430 	}
431 }
432 
433 // -----------------------------------------------------------------------
434 
435 void Cursor::SetDirection( unsigned char nNewDirection )
436 {
437 	if ( mnDirection != nNewDirection )
438 	{
439 		mnDirection = nNewDirection;
440 		ImplNew();
441 	}
442 }
443 
444 // -----------------------------------------------------------------------
445 
446 Cursor& Cursor::operator=( const Cursor& rCursor )
447 {
448 	maPos			= rCursor.maPos;
449 	maSize			= rCursor.maSize;
450 	mnSlant 		= rCursor.mnSlant;
451 	mnOrientation	= rCursor.mnOrientation;
452 	mnDirection 	= rCursor.mnDirection;
453 	mbVisible		= rCursor.mbVisible;
454 	ImplNew();
455 
456 	return *this;
457 }
458 
459 // -----------------------------------------------------------------------
460 
461 sal_Bool Cursor::operator==( const Cursor& rCursor ) const
462 {
463 	if ( (maPos 		== rCursor.maPos)			&&
464 		 (maSize		== rCursor.maSize)			&&
465 		 (mnSlant		== rCursor.mnSlant) 		&&
466 		 (mnOrientation == rCursor.mnOrientation)	&&
467 		 (mnDirection   == rCursor.mnDirection)	    &&
468 		 (mbVisible 	== rCursor.mbVisible) )
469 		return sal_True;
470 	else
471 		return sal_False;
472 }
473