1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/mgl/cursor.cpp
3// Purpose:
4// Author:      Vaclav Slavik
5// Id:          $Id: cursor.cpp 42752 2006-10-30 19:26:48Z VZ $
6// Copyright:   (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
7// Licence:     wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
13#ifdef __BORLANDC__
14    #pragma hdrstop
15#endif
16
17#include "wx/cursor.h"
18
19#ifndef WX_PRECOMP
20    #include "wx/intl.h"
21    #include "wx/log.h"
22    #include "wx/utils.h"
23    #include "wx/hashmap.h"
24    #include "wx/module.h"
25#endif
26
27#include "wx/mgl/private.h"
28
29
30//-----------------------------------------------------------------------------
31// wxCursor
32//-----------------------------------------------------------------------------
33
34class wxCursorRefData: public wxObjectRefData
35{
36  public:
37
38    wxCursorRefData();
39    virtual ~wxCursorRefData();
40
41    MGLCursor *m_cursor;
42};
43
44wxCursorRefData::wxCursorRefData()
45{
46    m_cursor = (MGLCursor*) NULL;
47}
48
49wxCursorRefData::~wxCursorRefData()
50{
51    delete m_cursor;
52}
53
54#define M_CURSORDATA ((wxCursorRefData *)m_refData)
55
56//-----------------------------------------------------------------------------
57
58WX_DECLARE_HASH_MAP(int, wxCursor, wxIntegerHash, wxIntegerEqual, wxCursorsHash);
59
60static wxCursorsHash *gs_cursorsHash = NULL;
61
62IMPLEMENT_DYNAMIC_CLASS(wxCursor,wxObject)
63
64wxCursor::wxCursor()
65{
66}
67
68wxCursor::wxCursor(int cursorId)
69{
70    if ( !gs_cursorsHash )
71        gs_cursorsHash = new wxCursorsHash;
72
73    if ( gs_cursorsHash->find(cursorId) != gs_cursorsHash->end() )
74    {
75        wxLogTrace(_T("mglcursor"), _T("cursor id %i fetched from cache"), cursorId);
76        *this = (*gs_cursorsHash)[cursorId];
77        return;
78    }
79
80    const char *cursorname = NULL;
81    m_refData = new wxCursorRefData();
82
83    switch (cursorId)
84    {
85        case wxCURSOR_ARROW:           cursorname = "arrow.cur"; break;
86        case wxCURSOR_RIGHT_ARROW:     cursorname = "rightarr.cur"; break;
87        case wxCURSOR_BULLSEYE:        cursorname = "bullseye.cur"; break;
88        case wxCURSOR_CHAR:            cursorname = "char.cur"; break;
89        case wxCURSOR_CROSS:           cursorname = "cross.cur"; break;
90        case wxCURSOR_HAND:            cursorname = "hand.cur"; break;
91        case wxCURSOR_IBEAM:           cursorname = "ibeam.cur"; break;
92        case wxCURSOR_LEFT_BUTTON:     cursorname = "leftbtn.cur"; break;
93        case wxCURSOR_MAGNIFIER:       cursorname = "magnif1.cur"; break;
94        case wxCURSOR_MIDDLE_BUTTON:   cursorname = "midbtn.cur"; break;
95        case wxCURSOR_NO_ENTRY:        cursorname = "noentry.cur"; break;
96        case wxCURSOR_PAINT_BRUSH:     cursorname = "pbrush.cur"; break;
97        case wxCURSOR_PENCIL:          cursorname = "pencil.cur"; break;
98        case wxCURSOR_POINT_LEFT:      cursorname = "pntleft.cur"; break;
99        case wxCURSOR_POINT_RIGHT:     cursorname = "pntright.cur"; break;
100        case wxCURSOR_QUESTION_ARROW:  cursorname = "query.cur"; break;
101        case wxCURSOR_RIGHT_BUTTON:    cursorname = "rightbtn.cur"; break;
102        case wxCURSOR_SIZENESW:        cursorname = "sizenesw.cur"; break;
103        case wxCURSOR_SIZENS:          cursorname = "sizens.cur"; break;
104        case wxCURSOR_SIZENWSE:        cursorname = "sizenwse.cur"; break;
105        case wxCURSOR_SIZEWE:          cursorname = "sizewe.cur"; break;
106        case wxCURSOR_SIZING:          cursorname = "size.cur"; break;
107        case wxCURSOR_SPRAYCAN:        cursorname = "spraycan.cur"; break;
108        case wxCURSOR_WAIT:            cursorname = "wait.cur"; break;
109        case wxCURSOR_WATCH:           cursorname = "clock.cur"; break;
110        case wxCURSOR_BLANK:           cursorname = "blank.cur"; break;
111
112        case wxCURSOR_NONE:
113            *this = wxNullCursor;
114            return;
115
116        default:
117            wxFAIL_MSG(wxT("unsupported cursor type"));
118            break;
119    }
120
121    M_CURSORDATA->m_cursor = new MGLCursor(cursorname);
122
123    // if we cannot load arrow cursor, use MGL's default arrow cursor:
124    if ( !M_CURSORDATA->m_cursor->valid() && cursorId == wxCURSOR_ARROW )
125    {
126        delete M_CURSORDATA->m_cursor;
127        M_CURSORDATA->m_cursor = new MGLCursor(MGL_DEF_CURSOR);
128    }
129
130    if ( !M_CURSORDATA->m_cursor->valid() )
131    {
132        wxLogError(_("Couldn't create cursor."));
133        UnRef();
134    }
135    else
136    {
137        (*gs_cursorsHash)[cursorId] = *this;
138        wxLogTrace(_T("mglcursor"), _T("cursor id %i added to cache (%s)"),
139                   cursorId, cursorname);
140    }
141}
142
143wxCursor::wxCursor(const char WXUNUSED(bits)[],
144                   int WXUNUSED(width),
145                   int WXUNUSED(height),
146                   int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY),
147                   const char WXUNUSED(maskBits)[],
148                   wxColour * WXUNUSED(fg), wxColour * WXUNUSED(bg) )
149{
150    //FIXME_MGL
151}
152
153wxCursor::wxCursor(const wxString& cursor_file,
154                   long flags,
155                   int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY))
156{
157    if ( flags == wxBITMAP_TYPE_CUR || flags == wxBITMAP_TYPE_CUR_RESOURCE )
158    {
159        m_refData = new wxCursorRefData();
160        M_CURSORDATA->m_cursor = new MGLCursor(cursor_file.mb_str());
161        if ( !M_CURSORDATA->m_cursor->valid() )
162        {
163            wxLogError(_("Couldn't create cursor."));
164            UnRef();
165        }
166    }
167    else
168    {
169        wxLogError(wxT("Cannot load cursor resource of this type."));
170    }
171}
172
173wxCursor::~wxCursor()
174{
175    // wxObject unrefs data
176}
177
178bool wxCursor::IsOk() const
179{
180    return (m_refData != NULL);
181}
182
183MGLCursor *wxCursor::GetMGLCursor() const
184{
185    return M_CURSORDATA->m_cursor;
186}
187
188
189
190// ----------------------------------------------------------------------------
191// Global cursor setting
192// ----------------------------------------------------------------------------
193
194static wxCursor  gs_globalCursor = wxNullCursor;
195
196void wxSetCursor(const wxCursor& cursor)
197{
198    if ( cursor.Ok() )
199    {
200        if ( g_winMng )
201            MGL_wmSetGlobalCursor(g_winMng, *cursor.GetMGLCursor());
202        gs_globalCursor = cursor;
203    }
204    else
205    {
206        if ( g_winMng )
207            MGL_wmSetGlobalCursor(g_winMng, NULL);
208        gs_globalCursor = wxNullCursor;
209    }
210}
211
212
213
214//-----------------------------------------------------------------------------
215// busy cursor routines
216//-----------------------------------------------------------------------------
217
218static wxCursor  gs_savedCursor = wxNullCursor;
219static int       gs_busyCount = 0;
220
221const wxCursor &wxBusyCursor::GetStoredCursor()
222{
223    return gs_savedCursor;
224}
225
226const wxCursor wxBusyCursor::GetBusyCursor()
227{
228    return gs_globalCursor;
229}
230
231void wxEndBusyCursor()
232{
233    if ( --gs_busyCount > 0 ) return;
234
235    wxSetCursor(gs_savedCursor);
236    gs_savedCursor = wxNullCursor;
237}
238
239void wxBeginBusyCursor(const wxCursor *cursor)
240{
241    if ( gs_busyCount++ > 0 ) return;
242
243    wxASSERT_MSG( !gs_savedCursor.Ok(),
244                  wxT("forgot to call wxEndBusyCursor, will leak memory") );
245
246    gs_savedCursor = gs_globalCursor;
247    if ( cursor->Ok() )
248        wxSetCursor(*cursor);
249    else
250        wxSetCursor(wxCursor(wxCURSOR_WAIT));
251}
252
253bool wxIsBusy()
254{
255    return (gs_busyCount > 0);
256}
257
258
259
260//-----------------------------------------------------------------------------
261// module - clean up code
262//-----------------------------------------------------------------------------
263
264class wxCursorModule : public wxModule
265{
266public:
267    virtual bool OnInit() { return true; }
268
269    virtual void OnExit()
270    {
271        wxDELETE(gs_cursorsHash);
272    }
273
274private:
275    DECLARE_DYNAMIC_CLASS(wxCursorModule)
276};
277
278IMPLEMENT_DYNAMIC_CLASS(wxCursorModule, wxModule)
279