xref: /trunk/main/vcl/source/window/cursor.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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