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