KiCad PCB EDA Suite
Loading...
Searching...
No Matches
cursors.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <vector>
25#include <map>
26
27#include <gal/cursors.h>
28#include <kiplatform/ui.h>
29
30// Cursor files
31#include <cursors/cursor-add.xpm>
32#include <cursors/cursor-component.xpm>
33#include <cursors/cursor-eraser.xpm>
34#include <cursors/cursor-label-global.xpm>
35#include <cursors/cursor-label-hier.xpm>
36#include <cursors/cursor-label-net.xpm>
37#include <cursors/cursor-line-bus.xpm>
38#include <cursors/cursor-line-graphic.xpm>
39#include <cursors/cursor-line-wire.xpm>
40#include <cursors/cursor-measure.xpm>
41#include <cursors/cursor-pencil.xpm>
42#include <cursors/cursor-select-lasso.xpm>
43#include <cursors/cursor-select-window.xpm>
44#include <cursors/cursor-subtract.xpm>
45#include <cursors/cursor-text.xpm>
46#include <cursors/cursor-xor.xpm>
47#include <cursors/cursor-zoom-in.xpm>
48#include <cursors/cursor-zoom-out.xpm>
49#include <cursors/cursor_tune.xpm>
50#include <cursors/voltage_probe.xpm>
51#include <cursors/current_probe.xpm>
52
53// HiDPI cursor files
54#include <cursors/cursor-add64.xpm>
55#include <cursors/cursor-component64.xpm>
56#include <cursors/cursor-eraser64.xpm>
57#include <cursors/cursor-label-global64.xpm>
58#include <cursors/cursor-label-hier64.xpm>
59#include <cursors/cursor-label-net64.xpm>
60#include <cursors/cursor-line-bus64.xpm>
61#include <cursors/cursor-line-graphic64.xpm>
62#include <cursors/cursor-line-wire64.xpm>
63#include <cursors/cursor-measure64.xpm>
64#include <cursors/cursor-pencil64.xpm>
65#include <cursors/cursor-select-lasso64.xpm>
66#include <cursors/cursor-select-window64.xpm>
67#include <cursors/cursor-subtract64.xpm>
68#include <cursors/cursor-text64.xpm>
69#include <cursors/cursor-xor64.xpm>
70#include <cursors/cursor-zoom-in64.xpm>
71#include <cursors/cursor-zoom-out64.xpm>
72#include <cursors/cursor_tune64.xpm>
73#include <cursors/voltage_probe64.xpm>
74#include <cursors/current_probe64.xpm>
75
76
77// Under MSW, the standard cursor is white on black. Elsewhere it is black on white
78#ifdef __WINDOWS__
79#include <cursors/cursor-place.xpm>
80#include <cursors/cursor-place64.xpm>
81#include <cursors/cursor-select-m.xpm>
82#include <cursors/cursor-select-m64.xpm>
83#include <cursors/cursor-warning.xpm>
84#include <cursors/cursor-warning64.xpm>
85#else
86#include <cursors/cursor-place-black.xpm>
87#include <cursors/cursor-place-black64.xpm>
88#include <cursors/cursor-select-m-black.xpm>
89#include <cursors/cursor-select-m-black64.xpm>
90#include <cursors/cursor-warning-black.xpm>
91#include <cursors/cursor-warning-black64.xpm>
92#endif
93
94#include <wx/bitmap.h>
95#include <wx/debug.h>
96#include <wx/bmpbndl.h>
97
98
99static const std::map<KICURSOR, std::vector<CURSOR_STORE::CURSOR_DEF>> cursors_defs = {
100 {
102 {
103 { voltage_probe_xpm, { 1, 31 } },
104 { voltage_probe64_xpm, { 1, 62 } }
105 }
106 },
107 {
109 {
110 { current_probe_xpm, { 4, 27 } },
111 { current_probe64_xpm, { 8, 54 } }
112 }
113 },
114 {
116 {
117 { cursor_tune_xpm, { 1, 30 } },
118 { cursor_tune64_xpm, { 2, 60 } }
119 }
120 },
121 {
123 {
124 { cursor_pencil_xpm, { 4, 27 } },
125 { cursor_pencil64_xpm, { 8, 54 } }
126 }
127 },
128 {
130 {
131 {
132#ifdef __WINDOWS__
133 cursor_select_m_xpm,
134#else
135 cursor_select_m_black_xpm,
136#endif
137 { 1, 1 }
138 },
139 {
140#ifdef __WINDOWS__
141 cursor_select_m64_xpm,
142#else
143 cursor_select_m_black64_xpm,
144#endif
145 { 2, 2 }
146 }
147 }
148 },
149 {
151 {
152 {
153#ifdef __WINDOWS__
154 cursor_warning_xpm,
155#else
156 cursor_warning_black_xpm,
157#endif
158 { 1, 1 }
159 },
160 {
161#ifdef __WINDOWS__
162 cursor_warning64_xpm,
163#else
164 cursor_warning_black64_xpm,
165#endif
166 { 2, 2 }
167 }
168 }
169 },
170 {
172 {
173 { cursor_eraser_xpm, { 4, 4 } },
174 { cursor_eraser64_xpm, { 8, 8 } }
175 }
176 },
177 {
179 {
180 { cursor_text_xpm, { 7, 7 } },
181 { cursor_text64_xpm, { 14, 14 } }
182 }
183 },
184 {
186 {
187 { cursor_measure_xpm, { 4, 4 } },
188 { cursor_measure64_xpm, { 8, 8 } }
189 }
190 },
191 {
193 {
194 { cursor_add_xpm, { 7, 7 } },
195 { cursor_add64_xpm, { 14, 14 } }
196 }
197 },
198 {
200 {
201 { cursor_subtract_xpm, { 7, 7 } },
202 { cursor_subtract64_xpm, { 14, 14 } }
203 }
204 },
205 {
207 {
208 { cursor_xor_xpm, { 7, 7 } },
209 { cursor_xor64_xpm, { 14, 14 } }
210 }
211 },
212 {
214 {
215 { cursor_zoom_in_xpm, { 6, 6 } },
216 { cursor_zoom_in64_xpm, { 12, 12 } }
217 }
218 },
219 {
221 {
222 { cursor_zoom_out_xpm, { 6, 6 } },
223 { cursor_zoom_out64_xpm, { 12, 12 } }
224 }
225 },
226 {
228 {
229 { cursor_label_net_xpm, { 7, 7 } },
230 { cursor_label_net64_xpm, { 14, 14 } }
231 }
232 },
233 {
235 {
236 { cursor_label_global_xpm, { 7, 7 } },
237 { cursor_label_global64_xpm, { 14, 14 } }
238 }
239 },
240 {
242 {
243 { cursor_component_xpm, { 7, 7 } },
244 { cursor_component64_xpm, { 14, 14 } }
245 }
246 },
247 {
249 {
250 { cursor_select_lasso_xpm, { 7, 7 } },
251 { cursor_select_lasso64_xpm, { 14, 14 } }
252 }
253 },
254 {
256 {
257 { cursor_select_window_xpm, { 7, 10 } },
258 { cursor_select_window64_xpm, { 14, 20 } }
259 }
260 },
261 {
263 {
264 { cursor_line_bus_xpm, { 5, 26 } },
265 { cursor_line_bus64_xpm, { 10, 52 } }
266 }
267 },
268 {
270 {
271 { cursor_line_wire_xpm, { 5, 26 } },
272 { cursor_line_wire64_xpm, { 10, 52 } }
273 }
274 },
275 {
277 {
278 { cursor_line_graphic_xpm, { 5, 26 } },
279 { cursor_line_graphic64_xpm, { 10, 52 } }
280 }
281 },
282 {
284 {
285 { cursor_label_hier_xpm, { 7, 7 } },
286 { cursor_label_hier64_xpm, { 14, 14 } }
287 }
288 },
289 {
291 {
292 {
293#ifdef __WINDOWS__
294 cursor_place_xpm,
295#else
296 cursor_place_black_xpm,
297#endif
298 { 1, 1 }
299 },
300 {
301#ifdef __WINDOWS__
302 cursor_place64_xpm,
303#else
304 cursor_place_black64_xpm,
305#endif
306 { 2, 2 }
307 }
308 }
309 }
310};
311
312
314{
315 for( const auto& [cursorId, defs] : cursors_defs )
316 {
317 wxCHECK2( !defs.empty(), continue );
318
319#if wxCHECK_VERSION( 3, 3, 0 )
320 // For wx 3.3+, create cursor bundles from the cursor definitions
321 std::vector<wxBitmap> bitmaps;
322
323 for( const auto& [xpm, hotspot_def] : defs )
324 {
325 wxCHECK2( xpm, continue );
326 bitmaps.push_back( wxBitmap( xpm ) );
327 }
328
329 wxBitmapBundle bitmapBundle = wxBitmapBundle::FromBitmaps( bitmaps );
330
331 wxPoint hotspot = defs[0].m_hotspot; // Use hotspot from standard cursor
332 m_bundleMap[cursorId] = wxCursorBundle( bitmapBundle, hotspot );
333#else
334 auto constructCursor = []( const CURSOR_STORE::CURSOR_DEF& aDef ) -> wxCursor
335 {
336 wxCHECK( aDef.m_xpm, wxNullCursor );
337 wxImage xpmImage = wxImage( aDef.m_xpm );
338
339 xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_X, aDef.m_hotspot.x );
340 xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_Y, aDef.m_hotspot.y );
341
342 return wxCursor( xpmImage );
343 };
344
345 // Add standard cursor (first definition)
346 m_standardCursorMap[cursorId] = constructCursor( defs[0] );
347
348 // Add HiDPI cursor (second definition if available, otherwise fallback to standard)
349 if( defs.size() > 1 )
350 m_hidpiCursorMap[cursorId] = constructCursor( defs[1] );
351 else
352 m_hidpiCursorMap[cursorId] = m_standardCursorMap[cursorId];
353#endif
354 }
355}
356
357#if wxCHECK_VERSION( 3, 3, 0 )
358const wxCursorBundle& CURSOR_STORE::storeGetBundle( KICURSOR aIdKey ) const
359{
360 const auto find_iter = m_bundleMap.find( aIdKey );
361
362 if( find_iter != m_bundleMap.end() )
363 return find_iter->second;
364
365 wxASSERT_MSG( false, wxString::Format( "Could not find cursor bundle with ID %d",
366 static_cast<int>( aIdKey ) ) );
367
368 static const wxCursorBundle invalid;
369
370 return invalid;
371}
372#else
373const wxCursor& CURSOR_STORE::storeGetCursor( KICURSOR aIdKey, bool aHiDPI ) const
374{
375 const auto& store = aHiDPI ? m_hidpiCursorMap : m_standardCursorMap;
376 const auto find_iter = store.find( aIdKey );
377
378 if( find_iter != store.end() )
379 return find_iter->second;
380
381 wxASSERT_MSG( false, wxString::Format( "Could not find cursor with ID %d", static_cast<int>( aIdKey ) ) );
382
383 return wxNullCursor;
384}
385#endif
386
387/* static */
388const WX_CURSOR_TYPE CURSOR_STORE::GetCursor( KICURSOR aCursorType, bool aHiDPI )
389{
390 // Use a single cursor store instance
391 static CURSOR_STORE store;
392
393 wxStockCursor stock = GetStockCursor( aCursorType );
394
395 if( stock != wxCURSOR_MAX )
396 return WX_CURSOR_TYPE( stock );
397
398#if wxCHECK_VERSION( 3, 3, 0 )
399 // For wx 3.3+, return the pre-built cursor bundle (aHiDPI is ignored as bundles contain both)
400 return store.storeGetBundle( aCursorType );
401#else
402 return store.storeGetCursor( aCursorType, aHiDPI );
403#endif
404}
405
406/* static */
407wxStockCursor CURSOR_STORE::GetStockCursor( KICURSOR aCursorType )
408{
409 wxStockCursor stockCursor;
410 switch( aCursorType )
411 {
412 case KICURSOR::MOVING:
413 stockCursor = wxCURSOR_SIZING;
414 break;
416 stockCursor = wxCURSOR_BULLSEYE;
417 break;
418 case KICURSOR::HAND:
419 stockCursor = wxCURSOR_HAND;
420 break;
421 case KICURSOR::ARROW:
422 stockCursor = wxCURSOR_ARROW;
423 break;
424 default:
425 stockCursor = wxCURSOR_MAX;
426 break;
427 }
428
429 if( !KIPLATFORM::UI::IsStockCursorOk( stockCursor ) )
430 stockCursor = wxCURSOR_MAX;
431
432 return stockCursor;
433}
std::map< KICURSOR, wxCursor > m_hidpiCursorMap
Definition cursors.h:166
static const WX_CURSOR_TYPE GetCursor(KICURSOR aCursorType, bool aHiDPI=false)
Get a cursor bundle (wx 3.3+) or appropriate cursor (older versions)
Definition cursors.cpp:388
static wxStockCursor GetStockCursor(KICURSOR aCursorType)
Get stock cursor type for the given cursor.
Definition cursors.cpp:407
CURSOR_STORE()
Construct a store with cursors for all defined types.
Definition cursors.cpp:313
const wxCursor & storeGetCursor(KICURSOR aIdKey, bool aHiDPI=false) const
Get a cursor by its ID, automatically selecting the appropriate resolution.
Definition cursors.cpp:373
std::map< KICURSOR, wxCursor > m_standardCursorMap
Definition cursors.h:165
static const std::map< KICURSOR, std::vector< CURSOR_STORE::CURSOR_DEF > > cursors_defs
Definition cursors.cpp:99
KICURSOR
Definition cursors.h:44
@ LINE_BUS
Definition cursors.h:90
@ WARNING
Definition cursors.h:50
@ LINE_WIRE
Definition cursors.h:94
@ SUBTRACT
Definition cursors.h:72
@ VOLTAGE_PROBE
Definition cursors.h:60
@ SELECT_WINDOW
Definition cursors.h:86
@ REMOVE
Definition cursors.h:54
@ COMPONENT
Definition cursors.h:84
@ MEASURE
Definition cursors.h:68
@ PLACE
Definition cursors.h:98
@ SELECT_LASSO
Definition cursors.h:88
@ ZOOM_IN
Definition cursors.h:76
@ ZOOM_OUT
Definition cursors.h:78
@ LABEL_GLOBAL
Definition cursors.h:82
@ MOVING
Definition cursors.h:48
@ CURRENT_PROBE
Definition cursors.h:62
@ LABEL_NET
Definition cursors.h:80
@ ARROW
Definition cursors.h:46
@ LINE_GRAPHIC
Definition cursors.h:92
@ LABEL_HIER
Definition cursors.h:96
@ BULLSEYE
Definition cursors.h:58
@ PENCIL
Definition cursors.h:52
wxCursor WX_CURSOR_TYPE
Represents either a wxCursorBundle for wx 3.3+ or a wxCursor for older versions.
Definition cursors.h:39
bool IsStockCursorOk(wxStockCursor aCursor)
Checks if we designated a stock cursor for this OS as "OK" or else we may need to load a custom one.
Definition wxgtk/ui.cpp:169
Definition of a cursor.
Definition cursors.h:115