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#include <pgm_base.h>
31
32// Cursor files
33#include <cursors/cursor-add.xpm>
34#include <cursors/cursor-component.xpm>
35#include <cursors/cursor-eraser.xpm>
36#include <cursors/cursor-label-global.xpm>
37#include <cursors/cursor-label-hier.xpm>
38#include <cursors/cursor-label-net.xpm>
39#include <cursors/cursor-line-bus.xpm>
40#include <cursors/cursor-line-graphic.xpm>
41#include <cursors/cursor-line-wire.xpm>
42#include <cursors/cursor-measure.xpm>
43#include <cursors/cursor-pencil.xpm>
44#include <cursors/cursor-select-lasso.xpm>
45#include <cursors/cursor-select-window.xpm>
46#include <cursors/cursor-subtract.xpm>
47#include <cursors/cursor-text.xpm>
48#include <cursors/cursor-xor.xpm>
49#include <cursors/cursor-zoom-in.xpm>
50#include <cursors/cursor-zoom-out.xpm>
51// Under MSW, the standard cursor is white on black. Elsewhere it is black on white
52#ifdef __WINDOWS__
53#include <cursors/cursor_tune.xpm>
54#include <cursors/voltage_probe_win.xpm>
55#include <cursors/current_probe_win.xpm>
56#else
57#include <cursors/cursor_tune_black.xpm>
58#include <cursors/voltage_probe_black.xpm>
59#include <cursors/current_probe_black.xpm>
60#endif
61
62// HiDPI cursor files
63#include <cursors/cursor-add64.xpm>
64#include <cursors/cursor-component64.xpm>
65#include <cursors/cursor-eraser64.xpm>
66#include <cursors/cursor-label-global64.xpm>
67#include <cursors/cursor-label-hier64.xpm>
68#include <cursors/cursor-label-net64.xpm>
69#include <cursors/cursor-line-bus64.xpm>
70#include <cursors/cursor-line-graphic64.xpm>
71#include <cursors/cursor-line-wire64.xpm>
72#include <cursors/cursor-measure64.xpm>
73#include <cursors/cursor-pencil64.xpm>
74#include <cursors/cursor-select-lasso64.xpm>
75#include <cursors/cursor-select-window64.xpm>
76#include <cursors/cursor-subtract64.xpm>
77#include <cursors/cursor-text64.xpm>
78#include <cursors/cursor-xor64.xpm>
79#include <cursors/cursor-zoom-in64.xpm>
80#include <cursors/cursor-zoom-out64.xpm>
81#ifdef __WINDOWS__
82#include <cursors/cursor_tune64.xpm>
83#include <cursors/voltage_probe_win64.xpm>
84#include <cursors/current_probe_win64.xpm>
85#else
86#include <cursors/cursor_tune_black64.xpm>
87#include <cursors/voltage_probe_black64.xpm>
88#include <cursors/current_probe_black64.xpm>
89#endif
90
91
92// Under MSW, the standard cursor is white on black. Elsewhere it is black on white
93#ifdef __WINDOWS__
94#include <cursors/cursor-place.xpm>
95#include <cursors/cursor-place64.xpm>
96#include <cursors/cursor-select-m.xpm>
97#include <cursors/cursor-select-m64.xpm>
98#include <cursors/cursor-warning.xpm>
99#include <cursors/cursor-warning64.xpm>
100#else
101#include <cursors/cursor-place-black.xpm>
102#include <cursors/cursor-place-black64.xpm>
103#include <cursors/cursor-select-m-black.xpm>
104#include <cursors/cursor-select-m-black64.xpm>
105#include <cursors/cursor-warning-black.xpm>
106#include <cursors/cursor-warning-black64.xpm>
107#endif
108
109#include <wx/bitmap.h>
110#include <wx/debug.h>
111#include <wx/bmpbndl.h>
112
113
114static const std::map<KICURSOR, std::vector<CURSOR_STORE::CURSOR_DEF>> cursors_defs = {
115 {
117 {
118 { voltage_probe_xpm, { 1, 31 } },
119 { voltage_probe64_xpm, { 1, 62 } }
120 }
121 },
122 {
124 {
125 { current_probe_xpm, { 4, 27 } },
126 { current_probe64_xpm, { 8, 54 } }
127 }
128 },
129 {
131 {
132 { cursor_tune_xpm, { 1, 30 } },
133 { cursor_tune64_xpm, { 2, 60 } }
134 }
135 },
136 {
138 {
139 { cursor_pencil_xpm, { 4, 27 } },
140 { cursor_pencil64_xpm, { 8, 54 } }
141 }
142 },
143 {
145 {
146 {
147#ifdef __WINDOWS__
148 cursor_select_m_xpm,
149#else
150 cursor_select_m_black_xpm,
151#endif
152 { 1, 1 }
153 },
154 {
155#ifdef __WINDOWS__
156 cursor_select_m64_xpm,
157#else
158 cursor_select_m_black64_xpm,
159#endif
160 { 2, 2 }
161 }
162 }
163 },
164 {
166 {
167 {
168#ifdef __WINDOWS__
169 cursor_warning_xpm,
170#else
171 cursor_warning_black_xpm,
172#endif
173 { 1, 1 }
174 },
175 {
176#ifdef __WINDOWS__
177 cursor_warning64_xpm,
178#else
179 cursor_warning_black64_xpm,
180#endif
181 { 2, 2 }
182 }
183 }
184 },
185 {
187 {
188 { cursor_eraser_xpm, { 4, 4 } },
189 { cursor_eraser64_xpm, { 8, 8 } }
190 }
191 },
192 {
194 {
195 { cursor_text_xpm, { 7, 7 } },
196 { cursor_text64_xpm, { 14, 14 } }
197 }
198 },
199 {
201 {
202 { cursor_measure_xpm, { 4, 4 } },
203 { cursor_measure64_xpm, { 8, 8 } }
204 }
205 },
206 {
208 {
209 { cursor_add_xpm, { 7, 7 } },
210 { cursor_add64_xpm, { 14, 14 } }
211 }
212 },
213 {
215 {
216 { cursor_subtract_xpm, { 7, 7 } },
217 { cursor_subtract64_xpm, { 14, 14 } }
218 }
219 },
220 {
222 {
223 { cursor_xor_xpm, { 7, 7 } },
224 { cursor_xor64_xpm, { 14, 14 } }
225 }
226 },
227 {
229 {
230 { cursor_zoom_in_xpm, { 6, 6 } },
231 { cursor_zoom_in64_xpm, { 12, 12 } }
232 }
233 },
234 {
236 {
237 { cursor_zoom_out_xpm, { 6, 6 } },
238 { cursor_zoom_out64_xpm, { 12, 12 } }
239 }
240 },
241 {
243 {
244 { cursor_label_net_xpm, { 7, 7 } },
245 { cursor_label_net64_xpm, { 14, 14 } }
246 }
247 },
248 {
250 {
251 { cursor_label_global_xpm, { 7, 7 } },
252 { cursor_label_global64_xpm, { 14, 14 } }
253 }
254 },
255 {
257 {
258 { cursor_component_xpm, { 7, 7 } },
259 { cursor_component64_xpm, { 14, 14 } }
260 }
261 },
262 {
264 {
265 { cursor_select_lasso_xpm, { 7, 7 } },
266 { cursor_select_lasso64_xpm, { 14, 14 } }
267 }
268 },
269 {
271 {
272 { cursor_select_window_xpm, { 7, 10 } },
273 { cursor_select_window64_xpm, { 14, 20 } }
274 }
275 },
276 {
278 {
279 { cursor_line_bus_xpm, { 5, 26 } },
280 { cursor_line_bus64_xpm, { 10, 52 } }
281 }
282 },
283 {
285 {
286 { cursor_line_wire_xpm, { 5, 26 } },
287 { cursor_line_wire64_xpm, { 10, 52 } }
288 }
289 },
290 {
292 {
293 { cursor_line_graphic_xpm, { 5, 26 } },
294 { cursor_line_graphic64_xpm, { 10, 52 } }
295 }
296 },
297 {
299 {
300 { cursor_label_hier_xpm, { 7, 7 } },
301 { cursor_label_hier64_xpm, { 14, 14 } }
302 }
303 },
304 {
306 {
307 {
308#ifdef __WINDOWS__
309 cursor_place_xpm,
310#else
311 cursor_place_black_xpm,
312#endif
313 { 1, 1 }
314 },
315 {
316#ifdef __WINDOWS__
317 cursor_place64_xpm,
318#else
319 cursor_place_black64_xpm,
320#endif
321 { 2, 2 }
322 }
323 }
324 }
325};
326
327
329{
330 for( const auto& [cursorId, defs] : cursors_defs )
331 {
332 wxCHECK2( !defs.empty(), continue );
333
334#if wxCHECK_VERSION( 3, 3, 0 )
335 // For wx 3.3+, create cursor bundles from the cursor definitions
336 std::vector<wxBitmap> bitmaps;
337
338 for( const auto& [xpm, hotspot_def] : defs )
339 {
340 wxCHECK2( xpm, continue );
341 bitmaps.push_back( wxBitmap( xpm ) );
342 }
343
344 wxBitmapBundle bitmapBundle = wxBitmapBundle::FromBitmaps( bitmaps );
345
346 wxPoint hotspot = defs[0].m_hotspot; // Use hotspot from standard cursor
347 m_bundleMap[cursorId] = wxCursorBundle( bitmapBundle, hotspot );
348#else
349 auto constructCursor = []( const CURSOR_STORE::CURSOR_DEF& aDef ) -> wxCursor
350 {
351 wxCHECK( aDef.m_xpm, wxNullCursor );
352 wxImage xpmImage = wxImage( aDef.m_xpm );
353
354 xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_X, aDef.m_hotspot.x );
355 xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_Y, aDef.m_hotspot.y );
356
357 return wxCursor( xpmImage );
358 };
359
360 // Add standard cursor (first definition)
361 m_standardCursorMap[cursorId] = constructCursor( defs[0] );
362
363 // Add HiDPI cursor (second definition if available, otherwise fallback to standard)
364 if( defs.size() > 1 )
365 m_hidpiCursorMap[cursorId] = constructCursor( defs[1] );
366 else
367 m_hidpiCursorMap[cursorId] = m_standardCursorMap[cursorId];
368#endif
369 }
370}
371
372#if wxCHECK_VERSION( 3, 3, 0 )
373const wxCursorBundle& CURSOR_STORE::storeGetBundle( KICURSOR aIdKey ) const
374{
375 const auto find_iter = m_bundleMap.find( aIdKey );
376
377 if( find_iter != m_bundleMap.end() )
378 return find_iter->second;
379
380 wxASSERT_MSG( false, wxString::Format( "Could not find cursor bundle with ID %d",
381 static_cast<int>( aIdKey ) ) );
382
383 static const wxCursorBundle invalid;
384
385 return invalid;
386}
387#else
388const wxCursor& CURSOR_STORE::storeGetCursor( KICURSOR aIdKey, bool aHiDPI ) const
389{
390 const auto& store = aHiDPI ? m_hidpiCursorMap : m_standardCursorMap;
391 const auto find_iter = store.find( aIdKey );
392
393 if( find_iter != store.end() )
394 return find_iter->second;
395
396 wxASSERT_MSG( false, wxString::Format( "Could not find cursor with ID %d", static_cast<int>( aIdKey ) ) );
397
398 return wxNullCursor;
399}
400#endif
401
402/* static */
403const WX_CURSOR_TYPE CURSOR_STORE::GetCursor( KICURSOR aCursorType, bool aHiDPI )
404{
405 // Use a single cursor store instance
406 static CURSOR_STORE store;
407
408 bool useCustomCursors = true;
409
410 if( COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings() )
411 useCustomCursors = commonSettings->m_Appearance.use_custom_cursors;
412
413 if( !useCustomCursors )
414 {
415 wxStockCursor stock = GetStockCursor( aCursorType );
416
417 if( stock == wxCURSOR_MAX )
418 stock = wxCURSOR_ARROW;
419
420 return WX_CURSOR_TYPE( stock );
421 }
422
423 wxStockCursor stock = GetStockCursor( aCursorType );
424
425 if( stock != wxCURSOR_MAX )
426 return WX_CURSOR_TYPE( stock );
427
428#if wxCHECK_VERSION( 3, 3, 0 )
429 // For wx 3.3+, return the pre-built cursor bundle (aHiDPI is ignored as bundles contain both)
430 return store.storeGetBundle( aCursorType );
431#else
432 return store.storeGetCursor( aCursorType, aHiDPI );
433#endif
434}
435
436/* static */
437wxStockCursor CURSOR_STORE::GetStockCursor( KICURSOR aCursorType )
438{
439 wxStockCursor stockCursor;
440 switch( aCursorType )
441 {
442 case KICURSOR::MOVING:
443 stockCursor = wxCURSOR_SIZING;
444 break;
446 stockCursor = wxCURSOR_BULLSEYE;
447 break;
448 case KICURSOR::HAND:
449 stockCursor = wxCURSOR_HAND;
450 break;
451 case KICURSOR::ARROW:
452 stockCursor = wxCURSOR_ARROW;
453 break;
454 default:
455 stockCursor = wxCURSOR_MAX;
456 break;
457 }
458
459 if( !KIPLATFORM::UI::IsStockCursorOk( stockCursor ) )
460 stockCursor = wxCURSOR_MAX;
461
462 return stockCursor;
463}
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:403
static wxStockCursor GetStockCursor(KICURSOR aCursorType)
Get stock cursor type for the given cursor.
Definition cursors.cpp:437
CURSOR_STORE()
Construct a store with cursors for all defined types.
Definition cursors.cpp:328
const wxCursor & storeGetCursor(KICURSOR aIdKey, bool aHiDPI=false) const
Get a cursor by its ID, automatically selecting the appropriate resolution.
Definition cursors.cpp:388
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:114
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:186
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
Definition of a cursor.
Definition cursors.h:115