wxdragon-sys 0.9.16

Raw FFI bindings to libwxdragon (which statically links wxWidgets).
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
#include <wx/wxprec.h>
#include <wx/wx.h>
#include "../include/wxdragon.h"
#include <wx/cursor.h>
#include <wx/bitmap.h>
#include <wx/utils.h>
#include <cstring>

extern "C" {

// Mapping function to convert our enum to wxWidgets stock cursor IDs
static wxStockCursor
map_stock_cursor(wxd_StockCursor cursor_id)
{
    switch (cursor_id) {
    case WXD_CURSOR_ARROW:
        return wxCURSOR_ARROW;
    case WXD_CURSOR_RIGHT_ARROW:
        return wxCURSOR_RIGHT_ARROW;
    case WXD_CURSOR_BULLSEYE:
        return wxCURSOR_BULLSEYE;
    case WXD_CURSOR_CHAR:
        return wxCURSOR_CHAR;
    case WXD_CURSOR_CROSS:
        return wxCURSOR_CROSS;
    case WXD_CURSOR_HAND:
        return wxCURSOR_HAND;
    case WXD_CURSOR_IBEAM:
        return wxCURSOR_IBEAM;
    case WXD_CURSOR_LEFT_BUTTON:
        return wxCURSOR_LEFT_BUTTON;
    case WXD_CURSOR_MAGNIFIER:
        return wxCURSOR_MAGNIFIER;
    case WXD_CURSOR_MIDDLE_BUTTON:
        return wxCURSOR_MIDDLE_BUTTON;
    case WXD_CURSOR_NO_ENTRY:
        return wxCURSOR_NO_ENTRY;
    case WXD_CURSOR_PAINT_BRUSH:
        return wxCURSOR_PAINT_BRUSH;
    case WXD_CURSOR_PENCIL:
        return wxCURSOR_PENCIL;
    case WXD_CURSOR_POINT_LEFT:
        return wxCURSOR_POINT_LEFT;
    case WXD_CURSOR_POINT_RIGHT:
        return wxCURSOR_POINT_RIGHT;
    case WXD_CURSOR_QUESTION_ARROW:
        return wxCURSOR_QUESTION_ARROW;
    case WXD_CURSOR_RIGHT_BUTTON:
        return wxCURSOR_RIGHT_BUTTON;
    case WXD_CURSOR_SIZENESW:
        return wxCURSOR_SIZENESW;
    case WXD_CURSOR_SIZENS:
        return wxCURSOR_SIZENS;
    case WXD_CURSOR_SIZENWSE:
        return wxCURSOR_SIZENWSE;
    case WXD_CURSOR_SIZEWE:
        return wxCURSOR_SIZEWE;
    case WXD_CURSOR_SIZING:
        return wxCURSOR_SIZING;
    case WXD_CURSOR_SPRAYCAN:
        return wxCURSOR_SPRAYCAN;
    case WXD_CURSOR_WAIT:
        return wxCURSOR_WAIT;
    case WXD_CURSOR_WATCH:
        return wxCURSOR_WATCH;
    case WXD_CURSOR_BLANK:
        return wxCURSOR_BLANK;
    case WXD_CURSOR_DEFAULT:
        return wxCURSOR_DEFAULT;
    case WXD_CURSOR_ARROWWAIT:
        return wxCURSOR_ARROWWAIT;
    default:
        return wxCURSOR_ARROW;
    }
}

static wxBitmapType
map_bitmap_type(wxd_BitmapType type)
{
    switch (type) {
    case WXD_BITMAP_TYPE_BMP:
        return wxBITMAP_TYPE_BMP;
    case WXD_BITMAP_TYPE_ICO:
        return wxBITMAP_TYPE_ICO;
    case WXD_BITMAP_TYPE_CUR:
        return wxBITMAP_TYPE_CUR;
    case WXD_BITMAP_TYPE_XBM:
        return wxBITMAP_TYPE_XBM;
    case WXD_BITMAP_TYPE_XPM:
        return wxBITMAP_TYPE_XPM;
    case WXD_BITMAP_TYPE_PNG:
        return wxBITMAP_TYPE_PNG;
    case WXD_BITMAP_TYPE_JPEG:
        return wxBITMAP_TYPE_JPEG;
    case WXD_BITMAP_TYPE_GIF:
        return wxBITMAP_TYPE_GIF;
    case WXD_BITMAP_TYPE_ANI:
        return wxBITMAP_TYPE_ANI;
    case WXD_BITMAP_TYPE_ANY:
        return wxBITMAP_TYPE_ANY;
    default:
        return wxBITMAP_TYPE_ANY;
    }
}

// --- Cursor Creation Functions ---

WXD_EXPORTED wxd_Cursor_t*
wxd_Cursor_CreateStock(wxd_StockCursor cursor_id)
{
    if (cursor_id == WXD_CURSOR_NONE) {
        return nullptr;
    }

    try {
        wxStockCursor stock_id = map_stock_cursor(cursor_id);
        wxCursor* cursor = new wxCursor(stock_id);
        return reinterpret_cast<wxd_Cursor_t*>(cursor);
    }
    catch (...) {
        return nullptr;
    }
}

WXD_EXPORTED wxd_Cursor_t*
wxd_Cursor_CreateFromFile(const char* filename, wxd_BitmapType type, int hotspot_x, int hotspot_y)
{
    if (!filename) {
        return nullptr;
    }

    try {
        wxString wx_filename = wxString::FromUTF8(filename);
        wxBitmapType wx_type = map_bitmap_type(type);
        wxCursor* cursor = new wxCursor(wx_filename, wx_type, hotspot_x, hotspot_y);

        if (cursor && cursor->IsOk()) {
            return reinterpret_cast<wxd_Cursor_t*>(cursor);
        }
        else {
            delete cursor;
            return nullptr;
        }
    }
    catch (...) {
        return nullptr;
    }
}

WXD_EXPORTED wxd_Cursor_t*
wxd_Cursor_CreateFromData(const unsigned char* bits, int width, int height, int hotspot_x,
                          int hotspot_y, const unsigned char* mask_bits)
{
    if (!bits || width <= 0 || height <= 0) {
        return nullptr;
    }

    try {
#ifdef __WXMSW__
        // On Windows, we need to create a cursor from a wxImage
        // The raw bits constructor takes different parameters

        // Create bitmap from bits
        wxBitmap bitmap = wxBitmap(reinterpret_cast<const char*>(bits), width, height);

        if (mask_bits) {
            wxBitmap mask_bitmap =
                wxBitmap(reinterpret_cast<const char*>(mask_bits), width, height);
            bitmap.SetMask(new wxMask(mask_bitmap));
        }

        // Convert to image and set hotspot
        wxImage image = bitmap.ConvertToImage();
        image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, hotspot_x);
        image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, hotspot_y);

        wxCursor* cursor = new wxCursor(image);

        if (cursor && cursor->IsOk()) {
            return reinterpret_cast<wxd_Cursor_t*>(cursor);
        }
        else {
            delete cursor;
            return nullptr;
        }
#elif defined(__WXGTK__)
        // On GTK, we can use the raw bits constructor with foreground/background colors
        wxCursor* cursor;
        if (mask_bits) {
            cursor = new wxCursor(reinterpret_cast<const char*>(bits), width, height, hotspot_x,
                                  hotspot_y, reinterpret_cast<const char*>(mask_bits), wxWHITE,
                                  wxBLACK);
        }
        else {
            // For GTK without mask, we need to create a simple bitmap
            wxBitmap bitmap = wxBitmap(reinterpret_cast<const char*>(bits), width, height);
            wxImage image = bitmap.ConvertToImage();
            image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, hotspot_x);
            image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, hotspot_y);
            cursor = new wxCursor(image);
        }

        if (cursor && cursor->IsOk()) {
            return reinterpret_cast<wxd_Cursor_t*>(cursor);
        }
        else {
            delete cursor;
            return nullptr;
        }
#else
        // On other platforms (macOS, etc.), try to use the image-based approach
        wxBitmap bitmap = wxBitmap(reinterpret_cast<const char*>(bits), width, height);

        if (mask_bits) {
            wxBitmap mask_bitmap =
                wxBitmap(reinterpret_cast<const char*>(mask_bits), width, height);
            bitmap.SetMask(new wxMask(mask_bitmap));
        }

        wxImage image = bitmap.ConvertToImage();
        image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_X, hotspot_x);
        image.SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, hotspot_y);

        wxCursor* cursor = new wxCursor(image);

        if (cursor && cursor->IsOk()) {
            return reinterpret_cast<wxd_Cursor_t*>(cursor);
        }
        else {
            delete cursor;
            return nullptr;
        }
#endif
    }
    catch (...) {
        return nullptr;
    }
}

WXD_EXPORTED wxd_Cursor_t*
wxd_Cursor_CreateFromImage(const wxd_Bitmap_t* image)
{
    if (!image) {
        return nullptr;
    }

    try {
        const wxBitmap* wx_bitmap = reinterpret_cast<const wxBitmap*>(image);
        wxImage wx_image = wx_bitmap->ConvertToImage();
        wxCursor* cursor = new wxCursor(wx_image);

        if (cursor && cursor->IsOk()) {
            return reinterpret_cast<wxd_Cursor_t*>(cursor);
        }
        else {
            delete cursor;
            return nullptr;
        }
    }
    catch (...) {
        return nullptr;
    }
}

WXD_EXPORTED wxd_Cursor_t*
wxd_Cursor_Copy(wxd_Cursor_t* cursor)
{
    if (!cursor) {
        return nullptr;
    }

    try {
        wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
        wxCursor* new_cursor = new wxCursor(*wx_cursor);
        return reinterpret_cast<wxd_Cursor_t*>(new_cursor);
    }
    catch (...) {
        return nullptr;
    }
}

// --- Cursor Destruction ---

WXD_EXPORTED void
wxd_Cursor_Destroy(wxd_Cursor_t* cursor)
{
    if (cursor) {
        wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
        delete wx_cursor;
    }
}

// --- Cursor Properties ---

WXD_EXPORTED bool
wxd_Cursor_IsOk(wxd_Cursor_t* cursor)
{
    if (!cursor) {
        return false;
    }

    wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
    return wx_cursor->IsOk();
}

WXD_EXPORTED wxd_Point
wxd_Cursor_GetHotSpot(wxd_Cursor_t* cursor)
{
    wxd_Point result = { -1, -1 };

    if (!cursor) {
        return result;
    }

    wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
    wxPoint hotspot = wx_cursor->GetHotSpot();

    result.x = hotspot.x;
    result.y = hotspot.y;
    return result;
}

WXD_EXPORTED void
wxd_Cursor_SetHotSpot(wxd_Cursor_t* cursor, int x, int y)
{
    // Note: wxWidgets doesn't provide a SetHotSpot method for cursors
    // This is included for completeness but may not be implemented
    // on all platforms
    (void)cursor;
    (void)x;
    (void)y;
}

// --- Platform-specific Functions ---

WXD_EXPORTED void*
wxd_Cursor_GetHandle(wxd_Cursor_t* cursor)
{
    if (!cursor) {
        return nullptr;
    }

    wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
#ifdef __WXMSW__
    return reinterpret_cast<void*>(wx_cursor->GetHandle());
#else
    // On non-Windows platforms, handle may not be available
    return nullptr;
#endif
}

WXD_EXPORTED void
wxd_Cursor_SetHandle(wxd_Cursor_t* cursor, void* handle)
{
    if (!cursor || !handle) {
        return;
    }

#ifdef __WXMSW__
    wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
    wx_cursor->SetHandle(reinterpret_cast<WXHANDLE>(handle));
#else
    // On non-Windows platforms, this may not be supported
    (void)cursor;
    (void)handle;
#endif
}

// --- Global Cursor Functions ---

WXD_EXPORTED void
wxd_SetCursor(wxd_Cursor_t* cursor)
{
    if (cursor) {
        wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
        wxSetCursor(*wx_cursor);
    }
    else {
        wxSetCursor(wxNullCursor);
    }
}

WXD_EXPORTED wxd_Cursor_t*
wxd_GetCursor()
{
    // Note: wxWidgets doesn't have a global wxGetCursor function
    // This would need to be implemented by tracking the current cursor
    return nullptr;
}

WXD_EXPORTED void
wxd_BeginBusyCursor(wxd_Cursor_t* cursor)
{
    if (cursor) {
        wxCursor* wx_cursor = reinterpret_cast<wxCursor*>(cursor);
        wxBeginBusyCursor(wx_cursor);
    }
    else {
        wxBeginBusyCursor();
    }
}

WXD_EXPORTED void
wxd_EndBusyCursor()
{
    wxEndBusyCursor();
}

WXD_EXPORTED bool
wxd_IsBusy()
{
    return wxIsBusy();
}

} // extern "C"