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#else
84#include <cursors/cursor-place-black.xpm>
85#include <cursors/cursor-place-black64.xpm>
86#include <cursors/cursor-select-m-black.xpm>
87#include <cursors/cursor-select-m-black64.xpm>
88#endif
89
90#include <wx/bitmap.h>
91#include <wx/debug.h>
92#include <wx/bmpbndl.h>
93
94
95static const std::map<KICURSOR, std::vector<CURSOR_STORE::CURSOR_DEF>> cursors_defs = {
96 {
98 {
99 { voltage_probe_xpm, { 1, 31 } },
100 { voltage_probe64_xpm, { 1, 62 } }
101 }
102 },
103 {
105 {
106 { current_probe_xpm, { 4, 27 } },
107 { current_probe64_xpm, { 8, 54 } }
108 }
109 },
110 {
112 {
113 { cursor_tune_xpm, { 1, 30 } },
114 { cursor_tune64_xpm, { 2, 60 } }
115 }
116 },
117 {
119 {
120 { cursor_pencil_xpm, { 4, 27 } },
121 { cursor_pencil64_xpm, { 8, 54 } }
122 }
123 },
124 {
126 {
127 {
128#ifdef __WINDOWS__
129 cursor_select_m_xpm,
130#else
131 cursor_select_m_black_xpm,
132#endif
133 { 1, 1 }
134 },
135 {
136#ifdef __WINDOWS__
137 cursor_select_m64_xpm,
138#else
139 cursor_select_m_black64_xpm,
140#endif
141 { 2, 2 }
142 }
143 }
144 },
145 {
147 {
148 { cursor_eraser_xpm, { 4, 4 } },
149 { cursor_eraser64_xpm, { 8, 8 } }
150 }
151 },
152 {
154 {
155 { cursor_text_xpm, { 7, 7 } },
156 { cursor_text64_xpm, { 14, 14 } }
157 }
158 },
159 {
161 {
162 { cursor_measure_xpm, { 4, 4 } },
163 { cursor_measure64_xpm, { 8, 8 } }
164 }
165 },
166 {
168 {
169 { cursor_add_xpm, { 7, 7 } },
170 { cursor_add64_xpm, { 14, 14 } }
171 }
172 },
173 {
175 {
176 { cursor_subtract_xpm, { 7, 7 } },
177 { cursor_subtract64_xpm, { 14, 14 } }
178 }
179 },
180 {
182 {
183 { cursor_xor_xpm, { 7, 7 } },
184 { cursor_xor64_xpm, { 14, 14 } }
185 }
186 },
187 {
189 {
190 { cursor_zoom_in_xpm, { 6, 6 } },
191 { cursor_zoom_in64_xpm, { 12, 12 } }
192 }
193 },
194 {
196 {
197 { cursor_zoom_out_xpm, { 6, 6 } },
198 { cursor_zoom_out64_xpm, { 12, 12 } }
199 }
200 },
201 {
203 {
204 { cursor_label_net_xpm, { 7, 7 } },
205 { cursor_label_net64_xpm, { 14, 14 } }
206 }
207 },
208 {
210 {
211 { cursor_label_global_xpm, { 7, 7 } },
212 { cursor_label_global64_xpm, { 14, 14 } }
213 }
214 },
215 {
217 {
218 { cursor_component_xpm, { 7, 7 } },
219 { cursor_component64_xpm, { 14, 14 } }
220 }
221 },
222 {
224 {
225 { cursor_select_lasso_xpm, { 7, 7 } },
226 { cursor_select_lasso64_xpm, { 14, 14 } }
227 }
228 },
229 {
231 {
232 { cursor_select_window_xpm, { 7, 10 } },
233 { cursor_select_window64_xpm, { 14, 20 } }
234 }
235 },
236 {
238 {
239 { cursor_line_bus_xpm, { 5, 26 } },
240 { cursor_line_bus64_xpm, { 10, 52 } }
241 }
242 },
243 {
245 {
246 { cursor_line_wire_xpm, { 5, 26 } },
247 { cursor_line_wire64_xpm, { 10, 52 } }
248 }
249 },
250 {
252 {
253 { cursor_line_graphic_xpm, { 5, 26 } },
254 { cursor_line_graphic64_xpm, { 10, 52 } }
255 }
256 },
257 {
259 {
260 { cursor_label_hier_xpm, { 7, 7 } },
261 { cursor_label_hier64_xpm, { 14, 14 } }
262 }
263 },
264 {
266 {
267 {
268#ifdef __WINDOWS__
269 cursor_place_xpm,
270#else
271 cursor_place_black_xpm,
272#endif
273 { 1, 1 }
274 },
275 {
276#ifdef __WINDOWS__
277 cursor_place64_xpm,
278#else
279 cursor_place_black64_xpm,
280#endif
281 { 2, 2 }
282 }
283 }
284 }
285};
286
287
289{
290 for( const auto& [cursorId, defs] : cursors_defs )
291 {
292 wxCHECK2( !defs.empty(), continue );
293
294#if wxCHECK_VERSION( 3, 3, 0 )
295 // For wx 3.3+, create cursor bundles from the cursor definitions
296 std::vector<wxBitmap> bitmaps;
297
298 for( const auto& [xpm, hotspot_def] : defs )
299 {
300 wxCHECK2( xpm, continue );
301 bitmaps.push_back( wxBitmap( xpm ) );
302 }
303
304 wxBitmapBundle bitmapBundle = wxBitmapBundle::FromBitmaps( bitmaps );
305
306 wxPoint hotspot = defs[0].m_hotspot; // Use hotspot from standard cursor
307 m_bundleMap[cursorId] = wxCursorBundle( bitmapBundle, hotspot );
308#else
309 auto constructCursor = []( const CURSOR_STORE::CURSOR_DEF& aDef ) -> wxCursor
310 {
311 wxCHECK( aDef.m_xpm, wxNullCursor );
312 wxImage xpmImage = wxImage( aDef.m_xpm );
313
314 xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_X, aDef.m_hotspot.x );
315 xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_Y, aDef.m_hotspot.y );
316
317 return wxCursor( xpmImage );
318 };
319
320 // Add standard cursor (first definition)
321 m_standardCursorMap[cursorId] = constructCursor( defs[0] );
322
323 // Add HiDPI cursor (second definition if available, otherwise fallback to standard)
324 if( defs.size() > 1 )
325 m_hidpiCursorMap[cursorId] = constructCursor( defs[1] );
326 else
327 m_hidpiCursorMap[cursorId] = m_standardCursorMap[cursorId];
328#endif
329 }
330}
331
332#if wxCHECK_VERSION( 3, 3, 0 )
333const wxCursorBundle& CURSOR_STORE::storeGetBundle( KICURSOR aIdKey ) const
334{
335 const auto find_iter = m_bundleMap.find( aIdKey );
336
337 if( find_iter != m_bundleMap.end() )
338 return find_iter->second;
339
340 wxASSERT_MSG( false, wxString::Format( "Could not find cursor bundle with ID %d",
341 static_cast<int>( aIdKey ) ) );
342
343 static const wxCursorBundle invalid;
344
345 return invalid;
346}
347#else
348const wxCursor& CURSOR_STORE::storeGetCursor( KICURSOR aIdKey, bool aHiDPI ) const
349{
350 const auto& store = aHiDPI ? m_hidpiCursorMap : m_standardCursorMap;
351 const auto find_iter = store.find( aIdKey );
352
353 if( find_iter != store.end() )
354 return find_iter->second;
355
356 wxASSERT_MSG( false, wxString::Format( "Could not find cursor with ID %d", static_cast<int>( aIdKey ) ) );
357
358 return wxNullCursor;
359}
360#endif
361
362/* static */
363const WX_CURSOR_TYPE CURSOR_STORE::GetCursor( KICURSOR aCursorType, bool aHiDPI )
364{
365 // Use a single cursor store instance
366 static CURSOR_STORE store;
367
368 wxStockCursor stock = GetStockCursor( aCursorType );
369
370 if( stock != wxCURSOR_MAX )
371 return WX_CURSOR_TYPE( stock );
372
373#if wxCHECK_VERSION( 3, 3, 0 )
374 // For wx 3.3+, return the pre-built cursor bundle (aHiDPI is ignored as bundles contain both)
375 return store.storeGetBundle( aCursorType );
376#else
377 return store.storeGetCursor( aCursorType, aHiDPI );
378#endif
379}
380
381/* static */
382wxStockCursor CURSOR_STORE::GetStockCursor( KICURSOR aCursorType )
383{
384 wxStockCursor stockCursor;
385 switch( aCursorType )
386 {
387 case KICURSOR::MOVING:
388 stockCursor = wxCURSOR_SIZING;
389 break;
390 case KICURSOR::BULLSEYE:
391 stockCursor = wxCURSOR_BULLSEYE;
392 break;
393 case KICURSOR::HAND:
394 stockCursor = wxCURSOR_HAND;
395 break;
396 case KICURSOR::ARROW:
397 stockCursor = wxCURSOR_ARROW;
398 break;
399 default:
400 stockCursor = wxCURSOR_MAX;
401 break;
402 }
403
404 if( !KIPLATFORM::UI::IsStockCursorOk( stockCursor ) )
405 stockCursor = wxCURSOR_MAX;
406
407 return stockCursor;
408}
Simple class to construct and store cursors against unique ID keys.
Definition: cursors.h:107
std::map< KICURSOR, wxCursor > m_hidpiCursorMap
Definition: cursors.h:164
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:363
static wxStockCursor GetStockCursor(KICURSOR aCursorType)
Get stock cursor type for the given cursor.
Definition: cursors.cpp:382
CURSOR_STORE()
Construct a store with cursors for all defined types.
Definition: cursors.cpp:288
const wxCursor & storeGetCursor(KICURSOR aIdKey, bool aHiDPI=false) const
Get a cursor by its ID, automatically selecting the appropriate resolution.
Definition: cursors.cpp:348
std::map< KICURSOR, wxCursor > m_standardCursorMap
Definition: cursors.h:163
static const std::map< KICURSOR, std::vector< CURSOR_STORE::CURSOR_DEF > > cursors_defs
Definition: cursors.cpp:95
KICURSOR
Definition: cursors.h:44
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:163
Definition of a cursor.
Definition: cursors.h:113