/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright The KiCad Developers, see AUTHORS.TXT for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include // Cursor files #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // HiDPI cursor files #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Under MSW, the standard cursor is white on black. Elsewhere it is black on white #ifdef __WINDOWS__ #include #include #include #include #else #include #include #include #include #endif #include #include #include static const std::map> cursors_defs = { { KICURSOR::VOLTAGE_PROBE, { { voltage_probe_xpm, { 1, 31 } }, { voltage_probe64_xpm, { 1, 62 } } } }, { KICURSOR::CURRENT_PROBE, { { current_probe_xpm, { 4, 27 } }, { current_probe64_xpm, { 8, 54 } } } }, { KICURSOR::TUNE, { { cursor_tune_xpm, { 1, 30 } }, { cursor_tune64_xpm, { 2, 60 } } } }, { KICURSOR::PENCIL, { { cursor_pencil_xpm, { 4, 27 } }, { cursor_pencil64_xpm, { 8, 54 } } } }, { KICURSOR::MOVING, { { #ifdef __WINDOWS__ cursor_select_m_xpm, #else cursor_select_m_black_xpm, #endif { 1, 1 } }, { #ifdef __WINDOWS__ cursor_select_m64_xpm, #else cursor_select_m_black64_xpm, #endif { 2, 2 } } } }, { KICURSOR::REMOVE, { { cursor_eraser_xpm, { 4, 4 } }, { cursor_eraser64_xpm, { 8, 8 } } } }, { KICURSOR::TEXT, { { cursor_text_xpm, { 7, 7 } }, { cursor_text64_xpm, { 14, 14 } } } }, { KICURSOR::MEASURE, { { cursor_measure_xpm, { 4, 4 } }, { cursor_measure64_xpm, { 8, 8 } } } }, { KICURSOR::ADD, { { cursor_add_xpm, { 7, 7 } }, { cursor_add64_xpm, { 14, 14 } } } }, { KICURSOR::SUBTRACT, { { cursor_subtract_xpm, { 7, 7 } }, { cursor_subtract64_xpm, { 14, 14 } } } }, { KICURSOR::XOR, { { cursor_xor_xpm, { 7, 7 } }, { cursor_xor64_xpm, { 14, 14 } } } }, { KICURSOR::ZOOM_IN, { { cursor_zoom_in_xpm, { 6, 6 } }, { cursor_zoom_in64_xpm, { 12, 12 } } } }, { KICURSOR::ZOOM_OUT, { { cursor_zoom_out_xpm, { 6, 6 } }, { cursor_zoom_out64_xpm, { 12, 12 } } } }, { KICURSOR::LABEL_NET, { { cursor_label_net_xpm, { 7, 7 } }, { cursor_label_net64_xpm, { 14, 14 } } } }, { KICURSOR::LABEL_GLOBAL, { { cursor_label_global_xpm, { 7, 7 } }, { cursor_label_global64_xpm, { 14, 14 } } } }, { KICURSOR::COMPONENT, { { cursor_component_xpm, { 7, 7 } }, { cursor_component64_xpm, { 14, 14 } } } }, { KICURSOR::SELECT_LASSO, { { cursor_select_lasso_xpm, { 7, 7 } }, { cursor_select_lasso64_xpm, { 14, 14 } } } }, { KICURSOR::SELECT_WINDOW, { { cursor_select_window_xpm, { 7, 10 } }, { cursor_select_window64_xpm, { 14, 20 } } } }, { KICURSOR::LINE_BUS, { { cursor_line_bus_xpm, { 5, 26 } }, { cursor_line_bus64_xpm, { 10, 52 } } } }, { KICURSOR::LINE_WIRE, { { cursor_line_wire_xpm, { 5, 26 } }, { cursor_line_wire64_xpm, { 10, 52 } } } }, { KICURSOR::LINE_GRAPHIC, { { cursor_line_graphic_xpm, { 5, 26 } }, { cursor_line_graphic64_xpm, { 10, 52 } } } }, { KICURSOR::LABEL_HIER, { { cursor_label_hier_xpm, { 7, 7 } }, { cursor_label_hier64_xpm, { 14, 14 } } } }, { KICURSOR::PLACE, { { #ifdef __WINDOWS__ cursor_place_xpm, #else cursor_place_black_xpm, #endif { 1, 1 } }, { #ifdef __WINDOWS__ cursor_place64_xpm, #else cursor_place_black64_xpm, #endif { 2, 2 } } } } }; CURSOR_STORE::CURSOR_STORE() { for( const auto& [cursorId, defs] : cursors_defs ) { wxCHECK2( !defs.empty(), continue ); #if wxCHECK_VERSION( 3, 3, 0 ) // For wx 3.3+, create cursor bundles from the cursor definitions std::vector bitmaps; for( const auto& [xpm, hotspot_def] : defs ) { wxCHECK2( xpm, continue ); bitmaps.push_back( wxBitmap( xpm ) ); } wxBitmapBundle bitmapBundle = wxBitmapBundle::FromBitmaps( bitmaps ); wxPoint hotspot = defs[0].m_hotspot; // Use hotspot from standard cursor m_bundleMap[cursorId] = wxCursorBundle( bitmapBundle, hotspot ); #else auto constructCursor = []( const CURSOR_STORE::CURSOR_DEF& aDef ) -> wxCursor { wxCHECK( aDef.m_xpm, wxNullCursor ); wxImage xpmImage = wxImage( aDef.m_xpm ); xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_X, aDef.m_hotspot.x ); xpmImage.SetOption( wxIMAGE_OPTION_CUR_HOTSPOT_Y, aDef.m_hotspot.y ); return wxCursor( xpmImage ); }; // Add standard cursor (first definition) m_standardCursorMap[cursorId] = constructCursor( defs[0] ); // Add HiDPI cursor (second definition if available, otherwise fallback to standard) if( defs.size() > 1 ) m_hidpiCursorMap[cursorId] = constructCursor( defs[1] ); else m_hidpiCursorMap[cursorId] = m_standardCursorMap[cursorId]; #endif } } #if wxCHECK_VERSION( 3, 3, 0 ) const wxCursorBundle& CURSOR_STORE::storeGetBundle( KICURSOR aIdKey ) const { const auto find_iter = m_bundleMap.find( aIdKey ); if( find_iter != m_bundleMap.end() ) return find_iter->second; wxASSERT_MSG( false, wxString::Format( "Could not find cursor bundle with ID %d", static_cast( aIdKey ) ) ); static const wxCursorBundle invalid; return invalid; } #else const wxCursor& CURSOR_STORE::storeGetCursor( KICURSOR aIdKey, bool aHiDPI ) const { const auto& store = aHiDPI ? m_hidpiCursorMap : m_standardCursorMap; const auto find_iter = store.find( aIdKey ); if( find_iter != store.end() ) return find_iter->second; wxASSERT_MSG( false, wxString::Format( "Could not find cursor with ID %d", static_cast( aIdKey ) ) ); return wxNullCursor; } #endif /* static */ const WX_CURSOR_TYPE CURSOR_STORE::GetCursor( KICURSOR aCursorType, bool aHiDPI ) { // Use a single cursor store instance static CURSOR_STORE store; wxStockCursor stock = GetStockCursor( aCursorType ); if( stock != wxCURSOR_MAX ) return WX_CURSOR_TYPE( stock ); #if wxCHECK_VERSION( 3, 3, 0 ) // For wx 3.3+, return the pre-built cursor bundle (aHiDPI is ignored as bundles contain both) return store.storeGetBundle( aCursorType ); #else return store.storeGetCursor( aCursorType, aHiDPI ); #endif } /* static */ wxStockCursor CURSOR_STORE::GetStockCursor( KICURSOR aCursorType ) { wxStockCursor stockCursor; switch( aCursorType ) { case KICURSOR::MOVING: stockCursor = wxCURSOR_SIZING; break; case KICURSOR::BULLSEYE: stockCursor = wxCURSOR_BULLSEYE; break; case KICURSOR::HAND: stockCursor = wxCURSOR_HAND; break; case KICURSOR::ARROW: stockCursor = wxCURSOR_ARROW; break; default: stockCursor = wxCURSOR_MAX; break; } if( !KIPLATFORM::UI::IsStockCursorOk( stockCursor ) ) stockCursor = wxCURSOR_MAX; return stockCursor; }